diff --git a/src/gui/interact/ui-coord-resolver.cpp b/src/gui/interact/ui-coord-resolver.cpp index ae7981575..ab9dcc50a 100644 --- a/src/gui/interact/ui-coord-resolver.cpp +++ b/src/gui/interact/ui-coord-resolver.cpp @@ -143,7 +143,7 @@ namespace interact { .filter ([&](auto& iter) { size_t depth = iter.depth(); // we are at that depth in target tree - if (depth >= coordDepth) // search pattern exhausted + if (depth >= coordDepth) // search pattern exhausted without match... return false; Literal patt = uic_[depth]; // pick search pattern component at that depth Literal curr = *iter; // iterator points at current tree position (ID) diff --git a/src/gui/interact/ui-coord-resolver.hpp b/src/gui/interact/ui-coord-resolver.hpp index 5d0444223..ff457948a 100644 --- a/src/gui/interact/ui-coord-resolver.hpp +++ b/src/gui/interact/ui-coord-resolver.hpp @@ -517,7 +517,7 @@ namespace interact { } /** @internal algorithm to resolve this UICoord path against the actual UI topology. - * @return true if total coverage is possibly (by interpolating wildcards) + * @return true if total coverage is possible (by interpolating wildcards) * @remark after invoking this function, res_.isResolved and possible coverage are set. */ bool pathResolution(); diff --git a/src/gui/interact/ui-location-solver.hpp b/src/gui/interact/ui-location-solver.hpp new file mode 100644 index 000000000..5be3a1016 --- /dev/null +++ b/src/gui/interact/ui-location-solver.hpp @@ -0,0 +1,92 @@ +/* + UI-LOCATION-SOLVER.hpp - decide upon a possible location for some UI component + + Copyright (C) Lumiera.org + 2018, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file ui-location-resolver.hpp + ** A solver to match incomplete coordinate specifications against the actual UI topology. + ** Within the Lumiera UI, a _component view_ is typically _created or retrieved_ to live at some position + ** within the tree-like topology of the interface. Such happens as a consequence of interaction or other + ** events, and the logic as to where and how to place a new UI element shall not be intermingled with the + ** actual event handling code. Rather, the ViewLocator, as a service related to the InteractionDirector, + ** can be invoked to draw on some default configuration plus the actual UI topology present at this time. + ** + ** @todo WIP 2/2018 early draft ////////////////////////////////////////////////////////////TICKET #1127 + ** + ** @see UILocationResolver_test + ** @see ViewSpecDSL_test + ** @see UICoordResolver + ** @see view-locator.hpp + */ + + +#ifndef GUI_INTERACT_UI_LOCATION_SOLVER_H +#define GUI_INTERACT_UI_LOCATION_SOLVER_H + +#include "lib/error.hpp" +//#include "lib/symbol.hpp" +//#include "lib/meta/function.hpp" +//#include "lib/meta/tuple-helper.hpp" +//#include "lib/meta/function-closure.hpp" +#include "gui/interact/ui-coord.hpp" +//#include "gui/interact/ui-coord-resolver.hpp" + +//#include +#include + + +namespace gui { +namespace interact { + +// using std::forward; + + class LocationQuery; + + + /** + * Access or allocate a UI component view + * + * @todo initial draft as of 9/2017 -- actual implementation need to be filled in + */ + class UILocationSolver + : boost::noncopyable + { +// ctrl::GlobalCtx& globals_; + + public: + UILocationSolver() + { } + + + /** + * Access and possibly create _just some_ component view of the desired type + */ + UICoord solve(); + + private: + + }; + + + + +}}// namespace gui::interact +#endif /*GUI_INTERACT_UI_LOCATION_SOLVER_H*/ diff --git a/src/gui/interact/view-locator.cpp b/src/gui/interact/view-locator.cpp index dff7128ab..b783cabd3 100644 --- a/src/gui/interact/view-locator.cpp +++ b/src/gui/interact/view-locator.cpp @@ -23,12 +23,24 @@ /** @file view-locator.cpp ** Implementation details of a machinery to allocate UI global component views. + ** Essentially this compilation unit hosts the implementation backing the [ViewSpec-DSL](view-spec-dsl.hpp) + ** and the [Location Solver](ui-location-solver.hpp) to drive evaluation of the standard location defaults, + ** which are [hard-wired into the UI](\ref id-scheme.hpp). For this integration of various facilities and + ** frameworks we rely on actual definitions for the DSL-tokens, which themselves are functors and tied by + ** lambda-binding into the implementation side of ViewLocator; which both acts as a front-end to access + ** the service to "get or create" a component and also holds the UILocationSolver component to perform + ** the actual location solving mechanism. The DSL thus sits between both poles, since _resolving a view_ + ** draws upon the default locating configuration encoded as DSL tokens, which in turn call back into + ** the implementation services within ViewLocator to resolve those partial location specifications + ** against the currently existing UI topology and then to access or create new UI components as + ** laid out through those definitions. ** ** @todo WIP 9/2017 early draft ////////////////////////////////////////////////////////////TICKET #1104 */ #include "gui/interact/view-locator.hpp" +#include "gui/interact/ui-location-solver.hpp" #include "gui/ctrl/panel-locator.hpp" #include "gui/ctrl/window-locator.hpp" #include "gui/interact/ui-coord-resolver.hpp" @@ -79,6 +91,7 @@ namespace interact { ViewLocator::ViewLocator (ctrl::GlobalCtx& uiTopLevel, LocationQueryAccess getLocQuery) : globals_{uiTopLevel} + , locResolver_{new UILocationSolver} { locationQuery = getLocQuery; } diff --git a/src/gui/interact/view-locator.hpp b/src/gui/interact/view-locator.hpp index cabe3d17c..6cd12ef49 100644 --- a/src/gui/interact/view-locator.hpp +++ b/src/gui/interact/view-locator.hpp @@ -65,7 +65,7 @@ #include #include //#include -//#include +#include namespace gui { @@ -76,12 +76,12 @@ namespace ctrl{ } namespace interact { -// using std::unique_ptr; + using std::unique_ptr; // using std::string; class LocationQuery; using LocationQueryAccess = std::function; -// class GlobalCtx; + class UILocationSolver; @@ -94,6 +94,7 @@ namespace interact { : boost::noncopyable { ctrl::GlobalCtx& globals_; + unique_ptr locResolver_; public: ViewLocator (ctrl::GlobalCtx&, LocationQueryAccess); diff --git a/src/lib/format-obj.cpp b/src/lib/format-obj.cpp index e3cd29fcb..2e6a57848 100644 --- a/src/lib/format-obj.cpp +++ b/src/lib/format-obj.cpp @@ -95,7 +95,8 @@ namespace meta { #ifdef __GNUG__ /** - * \par Implementation notes + * # Implementation notes + * * GCC / G++ subscribes to a cross-vendor ABI for C++, sometimes called the IA64 ABI * because it happens to be the native ABI for that platform. It is summarised at * \link http://www.codesourcery.com/cxx-abi/ mentor-embedded \endlink diff --git a/tests/gui/interact/ui-location-solver-test.cpp b/tests/gui/interact/ui-location-solver-test.cpp new file mode 100644 index 000000000..157f32330 --- /dev/null +++ b/tests/gui/interact/ui-location-solver-test.cpp @@ -0,0 +1,112 @@ +/* + UILocationSolver(Test) - verify mechanics of a DSL to configure view allocation + + Copyright (C) Lumiera.org + 2018, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + +/** @file ui-location-resolver-test.cpp + ** unit test \ref UILocationSolver_test + */ + + +#include "lib/test/run.hpp" +#include "lib/test/test-helper.hpp" +#include "gui/interact/view-spec-dsl.hpp" +#include "gui/interact/ui-coord.hpp" +#include "lib/format-cout.hpp" +//#include "lib/idi/entry-id.hpp" +//#include "lib/diff/gen-node.hpp" +//#include "lib/util.hpp" + +//#include + + +//using std::string; +//using lib::idi::EntryID; +//using lib::diff::GenNode; +//using util::isSameObject; +//using util::isnil; + + +namespace gui { +namespace interact { +namespace test { + +// using lumiera::error::LUMIERA_ERROR_WRONG_TYPE; + using lib::test::showSizeof; + + namespace { //Test fixture... + + }//(End)Test fixture + + + /******************************************************************************//** + * @test cover a mechanism to resolve the desired location of an ui element. + * The UILocationSolver is operated by the ViewLocator service, which itself + * is part of the InteractionDirector. In typical usage, the location rules + * are drawn from the [ViewSpec-DSL](\ref view-spec-dsl.hpp), evaluated + * with the help of a [Coordinate Resolver](\ref UICoordResolver), based on + * the real UI topology existing at that moment, accessible in abstracted + * form through the LocationQuery interface. This test setup mimics this + * invocation scheme, but replaces the real UI by an abstract tree notation + * embedded directly into the individual test cases. + * + * @see ui-location-solver.hpp + * @see view-spec-dsl.hpp + * @see UICoordResolver_test + */ + class UILocationSolver_test : public Test + { + + virtual void + run (Arg) + { + simple_usage_example(); + verify_cornerCases(); + verify_standardSituations(); + } + + + void + simple_usage_example() + { + UNIMPLEMENTED ("demonstrate the typical invocation and usage"); + } + + + void + verify_cornerCases() + { + UNIMPLEMENTED ("cover some corner cases"); + } + + + void + verify_standardSituations() + { + UNIMPLEMENTED ("emulate the relevant standard situations of view location resolution"); + } + }; + + + /** Register this test class... */ + LAUNCHER (UILocationSolver_test, "unit gui"); + + +}}} // namespace gui::interact::test diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 01de462ad..c17d0d803 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2838,7 +2838,7 @@ Command instances are like prototypes -- thus each additional level of different see the description in → CommandSetup -
+
//A view within the UI, featuring some component of relevance to »the model«.//
 While any UI is comprised of numerous widgets acting as //view of something,// only some of those views play the prominent role to act as //building block component// of the user interface.
 Such UI component views exhibit some substantial traits
@@ -2911,7 +2911,7 @@ locate = currentWindow().perspective(edit).tab(assetType())
           or firstWindow().panel(asset).view(asset).create()
 }}}
 ;~Error-Log
-:use the current {{{InfoBoxPanel}}} if such exists, fall back to using a single view on the primary window
+:use the current {{{InfoBoxPanel}}} if such exists, else fall back to using a single view on the primary window
 {{{
 alloc = limitPerWindow(1)
 locate = currentWindow().panel(infobox)
@@ -2957,7 +2957,7 @@ The given UICoord specs are matched one by one, using the first one applicable.
 
 The coordinate specs as written within the DSL are slightly abridged, as the final element, the actual component to be created, can be omitted and will be supplied automatically. This is possible insofar the ID of the queried element is actually more like a type specifier, and thus drawn from a finite and well known collection of possible elements (Timeline, Asset Bin, Error Log, Media Viewer, etc.). The elements to be created must invoke existing code and must be able to interface with their actual environment after all.
 
-However, the semantics of UI coordinate resolution and matching are applied against the coordinate specs //as given in the DSL.// Since, by default, what is given is required to exist, it makes quite a difference as to what kind of element is used as terminal element of a given spec. Since our UI coordinate system establishes a distinct depth for each kind of element, we can and even must reject any spec which does yield a definite location for at least the parent element; we do not interpolate or even invent arbitrary elements, we only ever match against existing ones. Thus any DSL definition must encompass a sane default, and is considered broken if it doesn't.
+However, the semantics of UI coordinate resolution and matching are applied against the coordinate specs //as given in the DSL.// Since, by default, what is given is required to exist, it makes quite a difference as to what kind of element is used as terminal element of a given spec. Since our UI coordinate system establishes a distinct depth for each kind of element, we can and even must reject any spec which does not yield a definite location for at least the parent element; we do not interpolate or even invent arbitrary elements, we only ever match against existing ones. Thus any DSL definition must encompass a sane default, a final alternative clause which always succeeds -- and the DSL considered broken if it doesn't.
 
 !!!Semantics of allocation
 While the process of probing and matching the location specification finally yields an explicit UICoord path to the desired element, it is up to the allocation step actually to decide on the action to be taken. Some allocation operations impose some kind of limit, and are thus free to ignore the given spec and rather return an existing element in place. In the end, the purpose of this whole matching and allocation process is to get hold of a suitable UI component without knowing its precise coordinates in the UI topology. And this is the very property to enable flexible mapping of the strictly hierarchical session structures onto the UI in a fluid way.
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 6951edd8d..caef09635 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -1351,7 +1351,7 @@
 
 
 
-
+
 
 
 
@@ -2224,7 +2224,7 @@
 
 
 
-
+
 
   
     
@@ -2253,7 +2253,7 @@
     

- +
@@ -3390,7 +3390,7 @@
- + @@ -4210,6 +4210,9 @@ + + + @@ -4493,7 +4496,7 @@ - + @@ -4599,7 +4602,7 @@ - + @@ -8399,7 +8402,7 @@ - + @@ -8535,6 +8538,21 @@ + + + + + + +

+ Support für elided element +

+ + +
+ + +
@@ -8774,7 +8792,7 @@
- + @@ -8835,8 +8853,7 @@ - - + @@ -8853,6 +8870,13 @@ + + + + + + + @@ -8869,6 +8893,20 @@ + + + + + + +

+ realer Pfad endet mit elided nach Wildcard +

+ + +
+ +
@@ -9156,13 +9194,13 @@
- - + + - + @@ -9312,22 +9350,605 @@ - - + + + + - - + + + + + + + + + + + + +

+ zwar könnte es (später mal) sein, +

+

+ daß wir mehrere Perspektiven gleichzeitig in die UI-Topologie abbilden... +

+ + +
+
+ + + + + + +

+ ...weil die Perspektive eigentlich als etwas Orthogonales empfunden wird, +

+

+ das nicht dirket zur "harten" Topologie gehört, sondern vielmehr bestehende Elemente umgruppiert. +

+

+ Andererseits möchte man eben doch manchmal eine View-Spec eigens auf eine bestimmte Perspektive beschränken, +

+

+ und deshalb habe ich die Perspektive zu den UI-Koordinaten hinzugenommen +

+ + +
+
+ + + + + + +

+ ...und zwar genau dann, wenn bereits die nächste Komponente unterhalb der Perspektive, +

+

+ also das Pannel, nicht oder nicht in dieser Form existiert, also erzeugt werden müßte. +

+

+ Unser Kriterium für Lösungen jedoch verlangt mindestens einen Match jenseits der Wildcards, +

+

+ um den Match eindeutig zu machen. +

+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + +

+ ...sofern es stets eine Perspektive geben muß +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + +

+ ...und zwar zwingend notwendig, weil es (viele) Views geben wird, +

+

+ welche keine mehrfachen TABs unterstützen. In solchen Fällen brauchen wir +

+

+ ein Konstrukt, mit dem sich eine Ebene im Baum überspringen läßt +

+ + +
+
+ + + + + + +

+ "muß" ist relativ, denn mit den bisherigen Anforderungen +

+

+ hätte es genügt, den "elided"-Platzhalter nur in den konkreten UI-Koordinaten +

+

+ zu verwenden, und ihn dann jeweils per Wildcard zu matchen (was automatisch passiert, +

+

+ einfach wenn die betreffende Komponente in der Angabe fehlt) +

+ + +
+
+ + + + + + +

+ Die korrekte Semantik fällt uns hier wirklich in den Schoß, +

+

+ es ist nur eine weitere Zeile in dem Test, ob ein Match vorliegt +

+ + +
+
+
+ + + + + + + + +

+ wobei einer, nämlich '*' sehr offensichtlich und bekannt ist, +

+

+ während der andere (eben dieses '.' == elided) eigens erklärt werden muß +

+ + +
+
+ + + + + + +

+ ...weil es eigentlich ein Wildcard ist, +

+

+ aber vom gesamten sonstigen Algorithmus nicht als Wildcard behandelt wird. +

+

+ Damit kann man alle Einschränkungen unterlaufen +

+ + +
+
+ + + + + + +

+ Korrekter Gebrauch setzt eigentlich voraus, +

+

+ daß es an dieser Stelle auch tatsächlich "gar nichts" oder nur "ein stets festes Element" gibt. +

+

+ Für die Perspektive ist das (nach jetztiger Planung) stets gegeben. +

+

+ +

+

+ Wenn man allerdings diese Bedingung verletzt, dann matcht der "elided"-Platzhalter +

+

+ in mehreren alternativen Zweigen wie ein Wildcard, und es hängt dann von +

+

+ zufälligen Umständen ab, ob man die erwartete Lösung bekommt +

+ + +
+
+
+
+
+ + + + +
+ + + + + + + + + + + + + + +

+ bloß würde sich die Signatur der DSL-Bausteine ändern: +

+

+ Allocator = std::function<UICoord(UICoordResolver)>; +

+ + +
+
+ + + + + + +

+ ...denn Reolver ist ein UICoord::Builder und als Solcher non-copyable. +

+

+ Also würde das ganze Gefrickel mit Referenzen losgehen, +

+

+ in einem Stück Metaprogramming-Code, das ohnenhin schon ziemlich "dicht" ist.... +

+ + +
+
+ + + + + + +

+ Der Punkt ist: das ist eine reine Lauzeit/Effzienz-Überlegung. +

+

+ +

+

+ Nachdem das Pfad-Matching in der DSL für die Location die passende Lösung gewählt hat, +

+

+ wäre -- im UICoordResolver eben -- auch schon die effektive Coverage bekannt. +

+

+ Da aber unser API nach (reinen) UI-Coord verlangt, werden diese aus der berechneten Lösung +

+

+ herausbewegt. Und der Allokator muß sich dann erneut einen UICoordResolver bauen, +

+

+ oder zumindest das LocationQuery-Interface bemühen, welches dann nochmal den Baum +

+

+ traversiert um die Coverage festzustellen. +

+
    +
  • + Ja, das kostet und ist verschwenderisch... +
  • +
  • + und Ja, vermutlich sind die paar CPU-Zyklen komplett egal +
  • +
+ + +
+
+ + + + + + +

+ das ist der klassische Fall, wo man wegen einer solchen Optimierung +

+

+ sich ein Interface versaut und ziemliche zusätzliche Komplexitäten an Bord zieht. +

+ + +
+ +
+
+ + - - + + + + + + + + + + + + + + + + + + + + +

+ das ist eine typische, rein lokale Optimierung (Speicher vs CPU) +

+

+ Ein solcher View-Index sollte dann ebenfalls via LocationQuery exponiert werden +

+ +
+ +
+
+ + + + + + + + +
+ + + + + + + + + + + + + +

+ es gibt nur einen "Locator" +

+ + +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...die es hinten herum bekommt +

+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + @@ -9338,7 +9959,8 @@ - + + @@ -9843,9 +10465,8 @@ - + - @@ -9886,6 +10507,28 @@
+ + + + + + + + + + + + + + + + + + + + + + @@ -12697,7 +13340,7 @@ - + @@ -20310,7 +20953,7 @@ - + @@ -24648,8 +25291,8 @@ - - + +