From 09359cf92aaf543592133901c8255fc9ac4c3568 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 7 Apr 2018 02:28:29 +0200 Subject: [PATCH] ElementAccess: initial brainstorming about the interface mechanics --- src/gui/ctrl/elem-access-dir.hpp | 67 ++++------- src/gui/model/element-access.hpp | 113 ++++++++++-------- src/lib/result.hpp | 28 ++--- tests/gui/ctrl/element-access-test.cpp | 33 ++--- .../gui}/gen-node-location-query.hpp | 0 tests/gui/interact/ui-coord-resolver-test.cpp | 2 +- .../gui/interact/ui-location-solver-test.cpp | 2 +- tests/gui/interact/view-spec-dsl-test.cpp | 2 +- tests/gui/test/test-element-access.hpp | 39 ++---- wiki/renderengine.html | 6 +- wiki/thinkPad.ichthyo.mm | 37 ++++++ 11 files changed, 168 insertions(+), 161 deletions(-) rename {src/gui/interact => tests/gui}/gen-node-location-query.hpp (100%) diff --git a/src/gui/ctrl/elem-access-dir.hpp b/src/gui/ctrl/elem-access-dir.hpp index a249a252b..6fb9c92aa 100644 --- a/src/gui/ctrl/elem-access-dir.hpp +++ b/src/gui/ctrl/elem-access-dir.hpp @@ -22,18 +22,18 @@ /** @file elem-access-directory.hpp - ** Generic building block in the Lumiera GUI model. - ** A model::Element has a unique identifier, which is tied to the - ** identification scheme used in the "real" model in Proc-Layer. - ** Model elements can be addressed receive mutations caused by changes - ** and rebuilding of elements within the Session; moreover, a generic - ** representation of attributes is provided. + ** A service to discover and access raw UI elements in a cross cutting way. + ** This is the actual low-level implementation of the model::ElementAccess interface + ** Tightly coupled to the internals of Lumiera's GTK UI, this implementation embodies + ** all the inside knowledge necessary to navigate over the various levels (Windows, + ** panels, views, specific components) to get at those elements abstracted as + ** UI-Coordinates. ** - ** @note as of 1/2015 this is a first draft and WIP-WIP-WIP - ** @todo WIP ///////////////////////TICKET #1134 + ** @note as of 4/2018 this is a first draft and will remain unimplemented for the time being + ** @todo WIP-WIP-WIP need to learn more about the concrete UI implementation ///////////////////////TICKET #1134 ** - ** @see ////TODO_test usage example - ** @see element.cpp implementation + ** @see view-locator.hpp + ** @see navigator.hpp ** */ @@ -43,67 +43,46 @@ #include "lib/error.hpp" -#include "lib/nocopy.hpp" -#include "lib/hash-value.h" #include "gui/model/element-access.hpp" //#include "lib/symbol.hpp" -#include "lib/util.hpp" +//#include "lib/util.hpp" -#include +//#include namespace gui { -namespace model { +namespace ctrl{ - using lib::HashVal; - using util::isnil; - using std::string; +// using util::isnil; +// using std::string; /** - * Basic (abstracted) view of... - * - * @see SomeSystem - * @see NA_test + * Low-level service to navigate the internals of the Lumiera GTK UI. + * @todo mostly not yet implemented as of 4/2018 -- need to learn more about aforementioned internals. */ - template class ElemAccessDir + : public model::ElementAccess { - string nothing_; public: explicit - ElemAccessDir (string const& b) - : nothing_(b) + ElemAccessDir () { } - // using default copy/assignment /* == Adapter interface for == */ - void - setSolution (string const& solution ="") - { - UNIMPLEMENTED ("tbw"); #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1134 if (isDeaf()) this->transmogrify (solution); #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1134 - } protected: - void maybe () const; - - - friend HashVal - hash_value (Element const& entry) - { - return hash_value (entry.nothing_); - } }; @@ -113,16 +92,10 @@ namespace model { /** @internal in case */ - template - inline void - ElementAccess::maybe () const - { - UNIMPLEMENTED ("tbw"); - } -}} // namespace gui::model +}} // namespace gui::ctrl #endif /*GUI_CTRL_ELEM_ACCESS_DIR_H*/ diff --git a/src/gui/model/element-access.hpp b/src/gui/model/element-access.hpp index 0955760d6..42479a5c0 100644 --- a/src/gui/model/element-access.hpp +++ b/src/gui/model/element-access.hpp @@ -22,18 +22,28 @@ /** @file element-access.hpp - ** Generic building block in the Lumiera GUI model. - ** A model::Element has a unique identifier, which is tied to the - ** identification scheme used in the "real" model in Proc-Layer. - ** Model elements can be addressed receive mutations caused by changes - ** and rebuilding of elements within the Session; moreover, a generic - ** representation of attributes is provided. + ** Interface to discover and access raw UI elements in a cross cutting way. + ** We have several orthogonal identification and access schemes within the UI. + ** A naively written UI application just attaches the core logic below some widgets and + ** controllers -- not only does this lead to a hard to maintain codebase, this approach + ** is even outright impossible for Lumiera, since the core is able to run standalone and + ** the UI is loaded as plug-in, which places us into the situation to connect a self + ** contained core with a self contained UI. This is a binding, which, as a sideline, also + ** generates a control structure of its own. An another kind of generic access happens + ** when we _navigate_ the topological UI structure for focus management. ** - ** @note as of 1/2015 this is a first draft and WIP-WIP-WIP + ** This interface defines an abstract service to translate a generic element designation + ** into a (language level) access to internal structures of the UI toolkit (GTK in our case). + ** This access to low-level structure proceeds in two stages: + ** - navigate down the UI topology. Optionally, this may involve a mutation (create element) + ** - evaluate the result (found, not found, element created) and access the target, + ** possibly with conversion (which might fail) + ** + ** @note as of 4/2018 this is a first draft and WIP-WIP-WIP ** @todo WIP ///////////////////////TICKET #1134 ** - ** @see ////TODO_test usage example - ** @see element.cpp implementation + ** @see ElementAccess_test + ** @see elem-access-dir.hpp implementation ** */ @@ -44,65 +54,54 @@ #include "lib/error.hpp" #include "lib/nocopy.hpp" -#include "lib/hash-value.h" +#include "lib/result.hpp" +#include "gui/interact/ui-coord.hpp" //#include "lib/symbol.hpp" -#include "lib/util.hpp" +//#include "lib/util.hpp" -#include +//#include namespace gui { namespace model { - using lib::HashVal; - using util::isnil; - using std::string; + using interact::UICoord; +// using util::isnil; +// using std::string; /** - * Basic (abstracted) view of... + * Interface: access UI elements by navigating the UI topology. * - * @see SomeSystem - * @see NA_test + * @see gui::interact::Navigator + * @see ElementAccess_test */ - template class ElementAccess + : util::NonCopyable { - string nothing_; public: - explicit - ElementAccess (string const& b) - : nothing_(b) - { } - - // using default copy/assignment + virtual ~ElementAccess () { } ///< this is an interface + template + using Result = lib::Result; - /* == Adapter interface for == */ + /* == Access by Location == */ - void - setSolution (string const& solution ="") - { - UNIMPLEMENTED ("tbw"); + template + Result access (UICoord destination); + + template + Result access_or_create (UICoord destination); + + + protected: #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1134 if (isDeaf()) this->transmogrify (solution); #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1134 - } - - - protected: - void maybe () const; - - - friend HashVal - hash_value (Element const& entry) - { - return hash_value (entry.nothing_); - } }; @@ -110,13 +109,31 @@ namespace model { - /** @internal in case + /** Navigate the UI topology to access the designated component + * @return suitably converted direct (language) reference to the desired element + * wrapped as _result proxy_ + * @note when access was not possible because the element does not exist, + * the result proxy is empty and convertible to `bool(false)` */ - template - inline void - ElementAccess::maybe () const + template + inline ElementAccess::Result + ElementAccess::access (UICoord destination) { - UNIMPLEMENTED ("tbw"); + UNIMPLEMENTED ("delegate to a suitable polymorphic navigation function"); + } + + + /** Navigate to the designated component, possibly create the element and parents + * @return suitably converted direct (language) reference to the desired element + * wrapped as _result proxy_ + * @note when access was not possible because the element could not been created, + * the result proxy is empty and convertible to `bool(false)` + */ + template + inline ElementAccess::Result + ElementAccess::access_or_create (UICoord destination) + { + UNIMPLEMENTED ("delegate to a suitable polymorphic navigation/creation function"); } diff --git a/src/lib/result.hpp b/src/lib/result.hpp index 38b3ba123..5757e1d0c 100644 --- a/src/lib/result.hpp +++ b/src/lib/result.hpp @@ -24,15 +24,13 @@ /** @file result.hpp ** Intermediary value object to represent the result of an operation. ** This operation might have produced a value result or failed with an exception. - ** Typically, the Result token is used \em inline -- immediately either invoking + ** Typically, the Result token is used _inline_ -- immediately either invoking ** one of the member function or employing the built-in result type conversion. ** It will be copyable iff the result value is copyable. There is an implicit ** valid or failure state, which can be tested. Any attempt to get the value - ** of an invalid result token will cause in an exception to be thrown. + ** of an invalid result token will cause an exception to be thrown. ** - ** @todo WIP and rather brainstorming as of 2/10 - ** - ** @see backend::ThreadJob usage example + ** @see backend::ThreadJoinable usage example */ @@ -58,7 +56,7 @@ namespace lib { /** * Optional Result value or status of some operation. - * It can be created for passing a result produced by the operation, or the + * It can be created for passing a result produced by the operation, or the * failure to do so. The value can be retrieved by implicit or explicit conversion. * @throw error::State on any attempt to access the value in case of failure * @warning this class has a lot of implicit conversions; @@ -74,18 +72,18 @@ namespace lib { public: /** mark an invalid/failed result */ Result () - : failureLog_("no result") + : failureLog_{"no result"} { } /** failed result, with reason given.*/ Result (lumiera::Error const& reason) - : failureLog_(reason.what()) - { } + : failureLog_{reason.what()} + { } /** standard case: valid result */ Result (RES const& value) - : failureLog_("") - , value_(value) + : failureLog_{} + , value_{value} { } @@ -99,7 +97,7 @@ namespace lib { void maybeThrow() const { - if (!isValid()) + if (not isValid()) throw error::State (failureLog_, lumiera_error_peek()); } @@ -131,12 +129,12 @@ namespace lib { public: /** mark either failure (default) or success */ Result (bool success =false) - : failureLog_(success? "": "operation failed") + : failureLog_{success? "": "operation failed"} { } /** failed result, with reason given.*/ Result (lumiera::Error const& reason) - : failureLog_(reason.what()) + : failureLog_{reason.what()} { } @@ -150,7 +148,7 @@ namespace lib { void maybeThrow() const { - if (!isValid()) + if (not isValid()) throw error::State (failureLog_, lumiera_error_peek()); } }; diff --git a/tests/gui/ctrl/element-access-test.cpp b/tests/gui/ctrl/element-access-test.cpp index 15e33e4ad..c30b6ec47 100644 --- a/tests/gui/ctrl/element-access-test.cpp +++ b/tests/gui/ctrl/element-access-test.cpp @@ -20,16 +20,17 @@ * *****************************************************/ -/** @file view-spec-dsl-test.cpp - ** unit test \ref ViewSpecDSL_test +/** @file element-access-test.cpp + ** unit test \ref ElementAccess_test */ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" -#include "gui/interact/view-spec-dsl.hpp" +//#include "gui/interact/view-spec-dsl.hpp" +#include "test/test-element-access.hpp" #include "gui/interact/ui-coord.hpp" -#include "gui/interact/gen-node-location-query.hpp" +//#include "gen-node-location-query.hpp" #include "lib/depend-inject.hpp" #include "lib/format-cout.hpp" //#include "lib/idi/entry-id.hpp" @@ -40,9 +41,9 @@ //#include -using std::string; -using lib::diff::MakeRec; -using lib::diff::Rec; +//using std::string; +//using lib::diff::MakeRec; +//using lib::diff::Rec; //using lib::idi::EntryID; //using lib::diff::GenNode; //using util::isSameObject; @@ -50,13 +51,13 @@ using lib::diff::Rec; namespace gui { -namespace interact { +namespace model { namespace test { // using lumiera::error::LUMIERA_ERROR_WRONG_TYPE; - using lib::test::showSizeof; +// using lib::test::showSizeof; - using MockLoationSolver = lib::DependInject::Local<>; + using MockAccess = lib::DependInject::Local; namespace { //Test fixture... @@ -64,12 +65,12 @@ namespace test { /******************************************************************************//** - * @test verify the mechanics of a functor based internal DSL - * to configure access and allocation patters for component views. + * @test verify the usage pattern of low-level UI element access, based on a + * mock implementation of the accessor directory. * * @see id-scheme.hpp * @see ViewLocator - * @see UICoord_test + * @see ViewSpecDSL_test */ class ElementAccess_test : public Test { @@ -77,6 +78,8 @@ namespace test { virtual void run (Arg) { + MockAccess fakeDirectory; + // verify_basicProperties(); verify_standardUsage(); verify_alternatives(); @@ -121,7 +124,7 @@ namespace test { /** Register this test class... */ - LAUNCHER (ElementAccess, "unit gui"); + LAUNCHER (ElementAccess_test, "unit gui"); -}}} // namespace gui::interact::test +}}} // namespace gui::model::test diff --git a/src/gui/interact/gen-node-location-query.hpp b/tests/gui/gen-node-location-query.hpp similarity index 100% rename from src/gui/interact/gen-node-location-query.hpp rename to tests/gui/gen-node-location-query.hpp diff --git a/tests/gui/interact/ui-coord-resolver-test.cpp b/tests/gui/interact/ui-coord-resolver-test.cpp index 67b937b0e..3f3bc6d66 100644 --- a/tests/gui/interact/ui-coord-resolver-test.cpp +++ b/tests/gui/interact/ui-coord-resolver-test.cpp @@ -29,7 +29,7 @@ #include "lib/test/test-helper.hpp" #include "gui/interact/ui-coord.hpp" #include "gui/interact/ui-coord-resolver.hpp" -#include "gui/interact/gen-node-location-query.hpp" +#include "gen-node-location-query.hpp" #include "lib/diff/gen-node.hpp" #include "lib/format-util.hpp" #include "lib/util.hpp" diff --git a/tests/gui/interact/ui-location-solver-test.cpp b/tests/gui/interact/ui-location-solver-test.cpp index 105b45bdb..6faaaf6e4 100644 --- a/tests/gui/interact/ui-location-solver-test.cpp +++ b/tests/gui/interact/ui-location-solver-test.cpp @@ -29,7 +29,7 @@ #include "lib/test/test-helper.hpp" #include "gui/interact/ui-coord.hpp" #include "gui/interact/ui-location-solver.hpp" -#include "gui/interact/gen-node-location-query.hpp" +#include "gen-node-location-query.hpp" #include "lib/format-cout.hpp" #include diff --git a/tests/gui/interact/view-spec-dsl-test.cpp b/tests/gui/interact/view-spec-dsl-test.cpp index 5c12d52b9..976f11d51 100644 --- a/tests/gui/interact/view-spec-dsl-test.cpp +++ b/tests/gui/interact/view-spec-dsl-test.cpp @@ -29,7 +29,7 @@ #include "lib/test/test-helper.hpp" #include "gui/interact/view-spec-dsl.hpp" #include "gui/interact/ui-coord.hpp" -#include "gui/interact/gen-node-location-query.hpp" +#include "gen-node-location-query.hpp" #include "lib/depend-inject.hpp" #include "lib/format-cout.hpp" //#include "lib/idi/entry-id.hpp" diff --git a/tests/gui/test/test-element-access.hpp b/tests/gui/test/test-element-access.hpp index fb3edfaf6..8e21915ae 100644 --- a/tests/gui/test/test-element-access.hpp +++ b/tests/gui/test/test-element-access.hpp @@ -43,22 +43,19 @@ #include "lib/error.hpp" -#include "lib/nocopy.hpp" -#include "lib/hash-value.h" #include "gui/model/element-access.hpp" //#include "lib/symbol.hpp" -#include "lib/util.hpp" +//#include "lib/util.hpp" -#include +//#include namespace gui { namespace model { - using lib::HashVal; - using util::isnil; - using std::string; +// using util::isnil; +// using std::string; /** @@ -67,43 +64,23 @@ namespace model { * @see SomeSystem * @see NA_test */ - template - class ElementAccess + class TestElementAccess + : public ElementAccess { - string nothing_; public: explicit - ElementAccess (string const& b) - : nothing_(b) + TestElementAccess () { } - // using default copy/assignment /* == Adapter interface for == */ - void - setSolution (string const& solution ="") - { - UNIMPLEMENTED ("tbw"); -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1134 - if (isDeaf()) - this->transmogrify (solution); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1134 - } protected: - void maybe () const; - - - friend HashVal - hash_value (Element const& entry) - { - return hash_value (entry.nothing_); - } }; @@ -113,12 +90,14 @@ namespace model { /** @internal in case */ +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1134 template inline void ElementAccess::maybe () const { UNIMPLEMENTED ("tbw"); } +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1134 diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 9e6767098..ff91175b1 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -9912,11 +9912,11 @@ In addition to querying the interpretation of a given coordinate spec with respe __Navigation mutations:__ //In theory,// it would even be possible to extend the path by creating suitable child components; but actually this would require all "elements" to implement a suitable mutation interface -- which in the case of //generic elements// might be far beyond the common ground. For this reason, we keep mutation of the backing environment outside of a path mutator's scope and rather keep mutation limited to the path itself. -
+
//Cross cutting access to elementary UI structures.//
-We have several orthogonal identification and access schemes within the UI. A naively written UI application just attaches the core logic below some widgets and controllers -- not only does this lead to a hard to maintain codebase, this approch is even outright impossible in our case, due to the strict decoupling between core and GUI, which places us into the situation to connect a self contained core with a self contained UI. This is a binding, which, as a sideline, also generates a control structure of its own. We can indeed write code dealing with a generic UI element -- but there needs to be some place where this kind of generic designation is translated into internal structures of the UI toolkit (GTK in our case), to obtain a direct (language) reference to some implementation widget finally.
+We have several orthogonal identification and access schemes within the UI. A naively written UI application just attaches the core logic below some widgets and controllers -- not only does this lead to a hard to maintain code base, this approach is even outright impossible in our case, due to the strict decoupling between core and GUI, which places us into the situation to connect a self contained core with a self contained UI. This is a binding, which, as a sideline, also generates a control structure of its own. We can indeed write code dealing with a generic UI element -- but there needs to be some place where this kind of generic designation is translated into internal structures of the UI toolkit (GTK in our case), to obtain a direct (language) reference to some implementation widget finally.
 
-A service to translate some generic address scheme into actual entities builds the foundation of designating a "place withih the UI" by abstracted topological [[UI coordinates|UICoord]]. It allows to define //rules// how some generic [[kind of view|GuiComponentView]] shall be //placed and allocated// into the existing UI structure.
+A service to translate some generic address scheme into actual entities builds the foundation of designating a "place within the UI" by abstracted topological [[UI coordinates|UICoord]]. It allows to define //rules// how some generic [[kind of view|GuiComponentView]] shall be //placed and allocated// into the existing UI structure.
 
 !Notes about design and implementation {{red{WIP 4/2018}}}
 At the time of this writing, it is not really clear if we need such a facility and what form its implementation will take -- which in turn places several further planning steps and design consideration into dangling state. The programmer's usual remedy in such a situation is to create yet another abstraction as a tie break. We do not know what it is, but at least we can write unit tests against it to find out what it could be.
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index f7cc821a4..35ee4230b 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -12622,6 +12622,43 @@
 
 
 
+
+
+
+
+
+  
+    
+  
+  
+    

+ model::Tangible ist schön, +

+

+ aber ich weiß nicht, ob das nicht zu eingeschränkt ist. +

+

+ Beispielsweise werden Panel oder WorkspaceWindow ganz sicher keine Tangibles sein, +

+

+ aber es könnte durchaus sein, daß man auf sie generisch zugreifen möchte +

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