From f4648c393fbc48467e61c043fd8af616cbbb271d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 4 Jan 2018 04:52:09 +0100 Subject: [PATCH] Navigator: unit test simple cases of coverage --- src/gui/interact/ui-coord-resolver.hpp | 6 ++ tests/gui/interact/ui-coord-resolver-test.cpp | 96 +++++++++++++++---- wiki/renderengine.html | 4 +- wiki/thinkPad.ichthyo.mm | 57 +++++------ 4 files changed, 115 insertions(+), 48 deletions(-) diff --git a/src/gui/interact/ui-coord-resolver.hpp b/src/gui/interact/ui-coord-resolver.hpp index 5cafe4ce2..a199d8ac5 100644 --- a/src/gui/interact/ui-coord-resolver.hpp +++ b/src/gui/interact/ui-coord-resolver.hpp @@ -330,6 +330,12 @@ namespace interact { } + /** diagnostics */ + operator string() const { return string(this->uic_); } + size_t coverDepth() const { return res_.depth; } + + + private: /** establish a trivial anchorage and coverage, if possible. * @note when the UICoord contains wildcards or is incomplete, diff --git a/tests/gui/interact/ui-coord-resolver-test.cpp b/tests/gui/interact/ui-coord-resolver-test.cpp index a8db4c4f9..6c2251ecc 100644 --- a/tests/gui/interact/ui-coord-resolver-test.cpp +++ b/tests/gui/interact/ui-coord-resolver-test.cpp @@ -82,9 +82,8 @@ namespace test { verify_simpleUsage(); verify_backingQuery(); verify_queryAnchor(); - verify_queryCoverage(); + verify_mutateCoverage(); verify_mutateAnchor(); - verify_mutateCovered(); verify_mutateExtend(); } @@ -243,11 +242,14 @@ namespace test { /** @test query anchorage of given UI coordinates. * - an anchored UI coordinate spec explicitly rooted within a top level window. + * - an explicit UI coordinate spec impossible to anchor within current UI tree + * - a UI coordinate spec with dynamic reference to first/current window + * - an incomplete spec, which needs to be solved (pattern matched) to determine anchor. */ void verify_queryAnchor() { - GenNodeLocationQuery loQu{MakeRec() + GenNodeLocationQuery tree{MakeRec() .set("window-1" , MakeRec() .type("perspective-A") @@ -268,12 +270,12 @@ namespace test { UICoord uic5 = UICoord::currentWindow().panel("panelY"); UICoord uic6 = UICoord().view("someView").path("α/β/γ"); - UICoordResolver r1{uic1, loQu}; - UICoordResolver r2{uic2, loQu}; - UICoordResolver r3{uic3, loQu}; - UICoordResolver r4{uic4, loQu}; - UICoordResolver r5{uic5, loQu}; - UICoordResolver r6{uic6, loQu}; + UICoordResolver r1{uic1, tree}; + UICoordResolver r2{uic2, tree}; + UICoordResolver r3{uic3, tree}; + UICoordResolver r4{uic4, tree}; + UICoordResolver r5{uic5, tree}; + UICoordResolver r6{uic6, tree}; CHECK ( r1.isAnchored()); CHECK (not r2.isAnchored()); @@ -291,10 +293,75 @@ namespace test { } + + /** @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. + * Whenever a coordinate spec is _not explicit,_ has wildcards or a leading gap, we need to perform the full + * matching algorithm, even to just answer the question if coverage _is possible_. The result, i.e. the computed + * coverage, is cached internally, and can be used to _mutate_ the UI coordinate spec to match that coverage. + * + * This test verifies various corner cases; especially there is a rule to prevent a partial match based + * on wildcards solely, rather we require at least one explicit match to qualify as partial solution. + * - (r1) trivial cases not requiring a tree search + * ** total coverage + * ** partial coverage, leaving an uncovered suffix + */ void - verify_queryCoverage() + verify_mutateCoverage() { - UNIMPLEMENTED ("query coverage of given UI coordinates with respect to actual UI"); + GenNodeLocationQuery tree{MakeRec() + .set("window-1" + , MakeRec() + .type("perspective-A") + .set("panelX" + , MakeRec() + .set("firstView", MakeRec()) + .set("secondView", MakeRec()) + ) + ) + .set("window-2" + , MakeRec() + .type("perspective-B") + .set("panelY", MakeRec()) + ) + .set("window-3" + , MakeRec() + .type("perspective-C") + .set("panelZ" + , MakeRec() + .set("thirdView", MakeRec()) + ) + .set("panelZZ", MakeRec()) + ) + }; + + /* === trivial cases === */ + UICoordResolver r11 {UICoord::window("window-1") + .persp("perspective-A") + .panel("panelX"), tree}; + CHECK (r11.isCovered()); + CHECK (3 == r11.coverDepth()); + + + UICoordResolver r12 {UICoord::window("window-1") + .persp("perspective-A") + .panel("panelX") + .view("thirdView"), tree}; + CHECK (not r12.isCovered()); + CHECK ( r12.isCoveredPartially()); + CHECK (3 ==r12.coverDepth()); + CHECK ("UI:window-1[perspective-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[perspective-A]-panelX" == string(r12_covered)); + + + UNIMPLEMENTED ("TODO: further cases of coverage query...."); } @@ -305,13 +372,6 @@ namespace test { } - void - verify_mutateCovered() - { - UNIMPLEMENTED ("mutate given UI coordinates by reducing to covered part"); - } - - void verify_mutateExtend() { diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 194359f74..e5653437f 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -9744,7 +9744,7 @@ The dispatch of //diff messages// is directly integrated into the UI-Bus -- whic The Graphical User interface, the upper layer in this hierarchy, embodies everything of tangible relevance to the user working with the application. The interplay with Proc-Layer, the middle layer below the UI, is organised along the distinction between two realms of equal importance: on one side, there is the immediate //mechanics of the interface,// which is implemented directly within the ~UI-Layer, based on the Graphical User Interface Toolkit. And, on the other side, there are those //core concerns of working with media,// which are cast into the HighLevelModel at the heart of the middle layer. -
+
//A topological addressing scheme to designate structural locations within the UI.//
 Contrary to conventional screen pixel coordinates, here we aim at a topological description of the UI structure. Such a framework of structural reference allows us                                                                     
 * to refer to some "place" or "space" within the interface                                    
@@ -9792,7 +9792,7 @@ In addition to the //locally decidable properties// of a coordinate spec, which
 :* it is //partially covered// with an remaining, uncovered extension part
 :* it is //possible to cover completely//
 :* it is //impossible to cover//
-__Some fine points to note__: Anchorage and coverage are not the same thing, but coverage implies anchorage. Only when a path is complete (starts with the window spec) and explicit (has no wildcards), then anchorage implies also partial coverage (namely at least to depth 1). To determine the possible coverage means to perform a resolution with backtracking to pick the maximal solution. Moreover, since "covered" means that the path specification //is at least partially supported by the real UI,// we establish an additional constraint to ensure this resolution did not just match some arbitrary wildcards. Rather we demand that behind rsp. below the last wildcard there is at least one further explicit component in the path spec, which is supported by the real UI. As a consequence, the coverage resolution may fail altogether, while still providing at least a possible anchor point.
+__Some fine points to note__: Anchorage and coverage are not the same thing, but coverage implies anchorage. Only when a path is complete (starts with the window spec) and explicit (has no wildcards), then anchorage implies also partial coverage (namely at least to depth 1). To determine the possibility of coverage means to perform a resolution with backtracking to pick the maximal solution. Moreover, since "covered" means that the path specification //is at least partially supported by the real UI,// we establish an additional constraint to ensure this resolution did not just match some arbitrary wildcards. Rather we demand that behind rsp. below the last wildcard there is at least one further explicit component in the path spec, which is supported by the real UI. As a consequence, the coverage resolution may fail altogether, while still providing at least a possible anchor point.
 !!!Mutations
 In addition to querying the interpretation of a given coordinate spec with respect to the current UI environment, it is also possible to rewrite or extend the spec based on this environment
 ;anchoring
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 447892482..b1cd22c90 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -4463,8 +4463,8 @@
 
 
 
-
-
+
+
 
 
 
@@ -4533,21 +4533,21 @@
 
 
 
-
-
+
+
 
 
 
-
-
+
+
 
-
-
+
+
 
 
-
+
 
-
+
 
 
 
@@ -4559,8 +4559,8 @@
 
 
 
-
-
+
+
 
 
 
@@ -4625,7 +4625,8 @@
 
 
 
-
+
+
 
 
 
@@ -8356,7 +8357,7 @@
 
 
 
-
+
 
 
 
@@ -8368,7 +8369,7 @@
 
 
 
-
+
 
 
 
@@ -8415,7 +8416,7 @@
 
 
 
-
+
 
 
 
@@ -8505,7 +8506,7 @@
 
 
 
-
+
 
 
 
@@ -8582,7 +8583,7 @@
 
 
 
-
+
 
 
 
@@ -8690,8 +8691,8 @@
 
 
 
-
-
+
+
 
 
 
@@ -8717,8 +8718,8 @@
 
 
 
-
-
+
+
 
 
 
@@ -8758,13 +8759,13 @@
 
 
 
-
-
-
-
+
+
+
+
 
-
-
+
+