Navigator: fix covering of an explicit UI-Coordinate

...especially to make the anchorage explicit
This commit is contained in:
Fischlurch 2018-01-06 02:54:24 +01:00
parent 0ea5583b62
commit e7ce82d17e
4 changed files with 60 additions and 37 deletions

View file

@ -31,8 +31,6 @@
#include "gui/interact/ui-coord-resolver.hpp"
#include "lib/util.hpp"
#include <boost/noncopyable.hpp>
using util::isnil;
using lib::Symbol;
using lib::treeExplore;

View file

@ -159,6 +159,7 @@ namespace interact {
* @return the depth to which the given spec is _"covered"_ by the actual UI.
* Can be zero, in which case the given coordinates can not be resolved
* and addressed within the currently existing windows, panes and views.
* @remark a depth > 0 also implies that the path can be _anchored._
* @note this operation does not perform any _resolution_ or interpolation of wildcards,
* it just matches explicit UI component names.
* @see UICoordResolver for a facility to perform such a resolution and to navigate paths.
@ -289,12 +290,22 @@ namespace interact {
/* === mutation functions === */
/** mutate the path to get it totally covered
* - make the anchorage explicit
* - possibly match and expand any wildcards
* - then truncate the UI-Coordinate spec to that part
* actually covered by the UI
* @note if the coordinate spec can not be covered at all,
* it will be truncated to zero size
*/
UICoordResolver
cover()
{
if (isCoveredPartially() and not res_.covfefe)
truncateTo (res_.depth);
{
ASSERT (res_.anchor); // depth > 0 implies anchorage
window (res_.anchor); // thus make this anchor explicit
truncateTo (res_.depth);
}
else if (canCover())
{
ASSERT (res_.isResolved);

View file

@ -67,6 +67,12 @@ namespace test {
/******************************************************************************//**
* @test verify query and mutation of UICoord in relation to actual UI topology.
* A UI-Coordinate resolver is a special builder, which is initialised by
* the given coordinate spec, and also attached to a "location query API",
* which allows to investigate the current actual UI structure. The builder
* then exposes query and mutation operations, to determine to what extent
* the coordinate spec is "covered" by the real UI, and to match and expand
* any wildcards in the coordinate spec (pattern).
*
* @see UICoordResolver
* @see navigator.hpp
@ -294,7 +300,7 @@ namespace test {
/** @test patch matching algorithm to resolve UI coordinates with wildcards against the current UI structure tree.
/** @test patch matching algorithm to resolve UI coordinates with wildcards against the current UI structure tree.
* Since an UI coordinate path with gaps and wildcards could match anywhere, even several times, we need to perform
* an exhaustive search with backtracking over the whole tree. By convention, we use the first maximal solution,
* which can be just a partial solution, leaving an additional uncovered trailing part of the UI coordinate spec.
@ -385,47 +391,57 @@ namespace test {
CHECK (3 ==r12.coverDepth());
CHECK ("UI:window-1[persp-A]-panelX.thirdView" == string(r12));
auto r12_covered = r12.cover();
CHECK (r12_covered.isCovered());
CHECK (r12_covered.isCoveredPartially());
CHECK (3 ==r12_covered.coverDepth());
CHECK ("UI:window-1[persp-A]-panelX" == string(r12_covered));
r12.cover();
CHECK (r12.isCovered());
CHECK (r12.isCoveredPartially());
CHECK (3 ==r12.coverDepth());
CHECK ("UI:window-1[persp-A]-panelX" == string(r12));
/* === expand anchor === */
UICoordResolver r21 {UICoord::firstWindow().persp("persp-A"), tree};
cout << r21.cover()<<endl; ///////////////////////////////////////////TODO doesn't work, yields UI:firstWindow[persp-A]
CHECK ("UI:firstWindow[persp-A]" == string(r21));
r21.cover();
CHECK ("UI:window-1[persp-A]" == string(r21));
/* === expand anchor alone === */
UICoordResolver r22 {UICoord::currentWindow(), tree};
cout << r22.cover()<<endl; ///////////////////////////////////////////TODO doesn't work, yields UI:currentWindow
CHECK ("UI:window-3" == string(r22.cover()));
/* === interpolate a single gap === */
UICoordResolver r31 {UICoord::window("window-1").view("secondView"), tree};
CHECK("UI:window-1[persp-A]-panelX.secondView" == string(r31.cover()));
CHECK ("UI:window-1[*]-*.secondView" == string(r31));
CHECK (0 ==r31.coverDepth());
CHECK (not r31.isCovered());
CHECK (r31.canCover());
r31.cover();
CHECK (r31.isCovered());
CHECK (4 == r31.coverDepth());
CHECK ("UI:window-1[persp-A]-panelX.secondView" == string(r31));
/* === interpolate several gaps === */
UICoordResolver r32 {UICoord().view("thirdView").path("sub"), tree};
CHECK("UI:window-3[persp-C]-panelZ.thirdView.tab/sub" == string(r32.cover()));
CHECK ("UI:window-3[persp-C]-panelZ.thirdView.tab/sub" == string(r32.cover()));
/* === interpolate anchor and consecutive wildcards === */
UICoordResolver r33 {UICoord::firstWindow().tab(2), tree};
CHECK("UI:window-1[persp-A]-panelZ.thirdView.#2" == string(r33.cover()));
CHECK ("UI:window-1[persp-A]-panelZ.thirdView.#2" == string(r33.cover()));
/* === discriminate by anchor and fill second gap === */
UICoordResolver r34 {UICoord::currentWindow().panel("panelZ").tab("tab"), tree};
CHECK("UI:window-3[persp-C]-panelZ.thirdView.tab" == string(r34.cover())); // Note: rest of the path would also match on window-1, but currentWindow == window-3
CHECK ("UI:currentWindow[*]-panelZ.*.tab" == string(r34));
CHECK ("UI:window-3[persp-C]-panelZ.thirdView.tab" == string(r34.cover())); // Note: rest of the path would also match on window-1, but currentWindow == window-3
/* === trailing wildcards stripped automatically === */
UICoordResolver r41 {UICoord::window("window-2").append("*/*"), tree};
CHECK("UI:window-2" == string(r41)); // Note: trailing wildcards are already discarded by PathArray / UICoord
CHECK ("UI:window-2" == string(r41)); // Note: trailing wildcards are already discarded by PathArray / UICoord
auto r41_extended = r41.extend("*/*"); // if we now attempt to "sneak in" trailing wildcards...
CHECK("UI:window-2[*]-*" == string(r41_extended));
CHECK(not r41_extended.canCover()); // ...then the algorithm rejects any solution
CHECK("UI:window-2" == string(r41_extended.cover())); // Note: but cover() will act on the previous coverage and just strip the extraneous suffix
r41.extend("*/*"); // if we now attempt to "sneak in" trailing wildcards...
CHECK ("UI:window-2[*]-*" == string(r41));
CHECK (not r41.canCover()); // ...then the algorithm rejects any solution
CHECK ("UI:window-2" == string(r41.cover())); // Note: but cover() will act on the previous coverage and just strip the extraneous suffix
/* === reject gap beyond existing real UI tree === */
UICoordResolver r42 {UICoord::window("window-2").append("*/*/*/some/path"), tree};

View file

@ -8766,15 +8766,13 @@
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1515114713029" ID="ID_424458820" MODIFIED="1515114729586" TEXT="Ankern">
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1514745345018" ID="ID_1229106293" MODIFIED="1515114727644" TEXT="fehlender Anker allein">
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="flag-pink"/>
<node COLOR="#338800" CREATED="1515114713029" ID="ID_424458820" MODIFIED="1515204865644" TEXT="Ankern">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1514745345018" ID="ID_1229106293" MODIFIED="1515204862321" TEXT="fehlender Anker allein">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1515114721228" ID="ID_1329702278" MODIFIED="1515114726603" TEXT="fehlender Anker">
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="flag-pink"/>
<node COLOR="#338800" CREATED="1515114721228" ID="ID_1329702278" MODIFIED="1515204863932" TEXT="fehlender Anker">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1515114740273" ID="ID_224432926" MODIFIED="1515120853113" TEXT="interpolieren">
@ -8855,16 +8853,16 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1508540835505" ID="ID_191493714" MODIFIED="1514748460975" TEXT="Zustand">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1508540835505" ID="ID_191493714" MODIFIED="1515204888544" TEXT="Zustand">
<icon BUILTIN="button_ok"/>
<node CREATED="1514748438984" ID="ID_84241950" MODIFIED="1514748444387" TEXT="reflektiert letzte L&#xf6;sung"/>
<node CREATED="1514748445520" ID="ID_728061293" MODIFIED="1514748446779" TEXT="swap(*this, Coverage)"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1514748450687" ID="ID_919694647" MODIFIED="1514748457327" TEXT="default: total">
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1514748463645" ID="ID_2814761" MODIFIED="1514748469603" TEXT="TODO: &#xe4;ndern">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1514748445520" ID="ID_728061293" MODIFIED="1515204926369" TEXT="*this = move (Coverage)"/>
<node COLOR="#338800" CREATED="1514748450687" ID="ID_919694647" MODIFIED="1515204876780" TEXT="default: total">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1514748463645" ID="ID_2814761" MODIFIED="1515204880477" TEXT="TODO: &#xe4;ndern">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1514748505488" ID="ID_947047856" MODIFIED="1514748548523" TEXT="TODO: API umstellen">
<node COLOR="#338800" CREATED="1514748505488" ID="ID_947047856" MODIFIED="1515204882332" TEXT="TODO: API umstellen">
<richcontent TYPE="NOTE"><html>
<head>
@ -8882,7 +8880,7 @@
</body>
</html>
</richcontent>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>