diff --git a/src/gui/id-scheme.hpp b/src/gui/id-scheme.hpp index 8e39c7275..629c8828d 100644 --- a/src/gui/id-scheme.hpp +++ b/src/gui/id-scheme.hpp @@ -56,6 +56,7 @@ #include "lib/symbol.hpp" #include "lib/idi/entry-id.hpp" +#include "gui/interact/view-spec-dsl.hpp" /* === forward declarations === */ @@ -122,7 +123,8 @@ namespace gui { // add to group of timelines within the timelinePanel alloc = unlimited -locate = panel(timeline) +locate = perspective(edit).panel(timeline) + or panel(timeline) // Viewer // here multiple alternatives are conceivable @@ -130,32 +132,32 @@ locate = panel(timeline) alloc = onlyOne locate = external(beamer) - or perspective(mediaView), panel(viewer) - or existingPanel(viewer) - or firstWindow, panel(viewer) + or perspective(mediaView).panel(viewer) + or panel(viewer).existing() + or firstWindow().panel(viewer) // - allow two viewer panels (the standard layout of editing applications) alloc = limitPerWindow(2) -locate = perspective(edit), existingPanel(viewer) - or currentWindow, existingPanel(viewer) - or existingPanel(viewer) - or panel(viewer) +locate = perspective(edit).panel(viewer).existing() + or currentWindow().panel(viewer).existing() + or panel(viewer).existing() + or panel(viewer) // (Asset)Bin // within the dedicated asset panel, add to the appropriate group for the kind of asset alloc = unlimited -locate = currentWindow, perspective(edit), existingPanel(asset), existingGroup - or perspective(asset), panel(asset) - or firstWindow, panel(asset) +locate = currentWindow().perspective(edit).panel(asset).assetTypeGroup().existing() + or perspective(asset).panel(asset) + or firstWindow().panel(asset) // Error-Log // use the current {{{InfoBoxPanel}}} if such exists, fall back to using a single view on the primary window alloc = limitPerWindow(1) -locate = currentWindow, existingPanel(infobox) - or firstWindow, panel(infobox) +locate = currentWindow().panel(infobox).existing() + or firstWindow().panel(infobox) */ diff --git a/src/gui/interact/view-locator.cpp b/src/gui/interact/view-locator.cpp index 92c6b7b01..dff7128ab 100644 --- a/src/gui/interact/view-locator.cpp +++ b/src/gui/interact/view-locator.cpp @@ -46,6 +46,9 @@ using gui::ctrl::WindowLocator; namespace gui { namespace interact { + namespace error = lumiera::error; + + /* ==== definitions and concrete bindings for the View-Spec-DSL ==== */ Symbol UIC_CURRENT_WINDOW{"currentWindow"}; @@ -53,14 +56,39 @@ namespace interact { Symbol UIC_ELIDED {"."}; - // dtors via smart-ptr invoked from here... - ViewLocator::~ViewLocator() { } + + namespace { + const LocationQueryAccess LOCATION_QUERY_SERIVCE_NOT_AVAILABLE + = []() -> LocationQuery& + { + throw error::State (error::LUMIERA_ERROR_LIFECYCLE + ,"No LocationQuery service available. Is the GUI running?"); + }; + } + + /** @internal global access point to some implementation of the LocationQuery API. + * Typically, this is provided by the Navigator service in conjunction with the ViewLocator; + * both are components managed by the InteractionDirector. Thus, when the UI starts, a suitable + * access functor will be installed here, and likewise removed/disabled on shutdown. + */ + LocationQueryAccess locationQuery = LOCATION_QUERY_SERIVCE_NOT_AVAILABLE; - ViewLocator::ViewLocator (ctrl::GlobalCtx& uiTopLevel, std::function getLocQuery) + + + + ViewLocator::ViewLocator (ctrl::GlobalCtx& uiTopLevel, LocationQueryAccess getLocQuery) : globals_{uiTopLevel} - , locationQuery{getLocQuery} - { } + { + locationQuery = getLocQuery; + } + + // dtors via smart-ptr invoked from here... + ViewLocator::~ViewLocator() + { + locationQuery = LOCATION_QUERY_SERIVCE_NOT_AVAILABLE; + } + /* === Service accessors within global context === */ diff --git a/src/gui/interact/view-locator.hpp b/src/gui/interact/view-locator.hpp index e23d3cff2..cabe3d17c 100644 --- a/src/gui/interact/view-locator.hpp +++ b/src/gui/interact/view-locator.hpp @@ -33,6 +33,21 @@ ** - multiplicity (one, one per window, many) depends on the type of view and needs to be managed. ** - such a view is not just _created_ -- rather it needs to be _allocated_ ** + ** ## LocationQuery and the View-Spec DSL + ** + ** Implementation wise, there is a tight connection between the ViewLocator service, the Navigator service + ** and the configuration how and where to create standard view elements (the "View-Spec DSL"). Several interactions + ** require the UI to access or create some specific view widget by side-effect. And the logic how and where to create + ** views can be quite intricate and is closely related to global, overarching topics of interaction design. Lumiera + ** thus relies on a framework for default configuration, and a matching mechanism to determine the location and + ** creation modes of such views. This matching mechanism in turn requires an abstracted view on the UI seen as + ** a topological tree structure of relevant entities (windows, panels, views,...) -- which is basically the + ** service provided by the Navigator; yet this Navigator service can be abstracted into the gui::interact::LocationQuery + ** API, and this abstraction allows to keep all the intricacies of navigating concrete UI widgets confined within the + ** implementation of the Navigator service. To enable this usage pattern, there is an access functor, to be found at + ** gui::interact::locationQuery, which will be installed when the UI starts and disabled on shutdown. This functor + ** can be exchanged for the purpose of unit testing. + ** ** @todo WIP 9/2017 early draft ////////////////////////////////////////////////////////////TICKET #1104 ** ** @see interaction-director.hpp @@ -44,6 +59,7 @@ #define GUI_INTERACT_VIEW_LOCATOR_H #include "gui/gtk-base.hpp" +#include "gui/interact/view-spec-dsl.hpp" #include "gui/id-scheme.hpp" #include @@ -62,9 +78,9 @@ namespace interact { // using std::unique_ptr; // using std::string; - using std::function; - class LocationQuery; + using LocationQueryAccess = std::function; + // class GlobalCtx; @@ -80,7 +96,7 @@ namespace interact { ctrl::GlobalCtx& globals_; public: - ViewLocator (ctrl::GlobalCtx&, function); + ViewLocator (ctrl::GlobalCtx&, LocationQueryAccess); ~ViewLocator(); @@ -92,7 +108,6 @@ namespace interact { private: /* === accessors to sibling global services === */ - function locationQuery; ctrl::PanelLocator& panelLocator(); ctrl::WindowLocator& windowLocator(); diff --git a/src/gui/interact/view-spec-dsl.hpp b/src/gui/interact/view-spec-dsl.hpp index 10a76d308..66ed1e62d 100644 --- a/src/gui/interact/view-spec-dsl.hpp +++ b/src/gui/interact/view-spec-dsl.hpp @@ -103,6 +103,7 @@ #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 @@ -113,6 +114,12 @@ namespace interact { using std::forward; + class LocationQuery; + + using LocationQueryAccess = std::function; + + /** @internal access UI service to query and discover locations within UI topology */ + extern LocationQueryAccess loactionQuery; /** diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 67e4008a8..e6a75ef4f 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
@@ -2877,7 +2877,8 @@ Since view allocation offers a choice amongst several complex patterns of behavi
 :add to group of timelines within the timelinePanel
 {{{
 alloc = unlimited
-locate = panel(timeline)
+locate = perspective(edit).panel(timeline)
+          or panel(timeline)
 }}}
 ;Viewer
 :here multiple alternatives are conceivable
@@ -2886,22 +2887,22 @@ locate = panel(timeline)
 alloc = onlyOne
 locate = external(beamer)
           or perspective(mediaView).panel(viewer)
-          or existingPanel(viewer)
+          or panel(viewer).existing()
           or firstWindow().panel(viewer)
 }}}
 :* allow two viewer panels (the standard layout of editing applications)
 {{{
 alloc = limitPerWindow(2)
-locate = perspective(edit).existingPanel(viewer)
-          or currentWindow().existingPanel(viewer)
-          or existingPanel(viewer)
+locate = perspective(edit).panel(viewer).existing()
+          or currentWindow().panel(viewer).existing()
+          or panel(viewer).existing()
           or panel(viewer)
 }}}
 ;(Asset)Bin
 :within the dedicated asset panel, add to the appropriate group for the kind of asset
 {{{
 alloc = unlimited
-locate = currentWindow().perspective(edit).existingPanel(asset).existingGroup()
+locate = currentWindow().perspective(edit).panel(asset).assetTypeGroup().existing()
           or perspective(asset).panel(asset)
           or firstWindow().panel(asset)
 }}}
@@ -2909,7 +2910,7 @@ locate = currentWindow().perspective(edit).existingPanel(asset).existingGroup()
 :use the current {{{InfoBoxPanel}}} if such exists, fall back to using a single view on the primary window
 {{{
 alloc = limitPerWindow(1)
-locate = currentWindow().existingPanel(infobox)
+locate = currentWindow().panel(infobox).existing()
           or firstWindow().panel(infobox)
 }}}
 ;Playcontrol
@@ -2938,12 +2939,15 @@ locate = currentWindow().existingPanel(infobox)
 : currentWindow
 : perspective(id)
 : panel(id)
-: existingPanel(id)
-: existingGroup {{red{WIP 9/17 not clear if possible}}}
+: assetTypeGroup {{red{WIP 9/17 not clear if possible}}}
+: existing()
 ;alloc
 : unlimited
 : onlyOne
 : limitPerWindow(cnt)
+
+!!!Semantics of location
+The given UICoord specs are matched one by one, using the first one applicable. The location indicated by this process describes the parent or scope where the desired view can be found or shall be created. The matching itself is based on the matching of UI coordinates against the existing UI topology, but enriched with some contextual information. When the predicate {{{existing()}}} is used, the constructed UI coordinate path is required to exist already, i.e. we demand //complete coverage.// In all other cases, only partial coverage is required, and the remaining, extraneous suffix of the coordinate path is what will be created by the instantiation process.
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 3a1c66372..51ecf6e00 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -762,8 +762,8 @@ - - + + @@ -1989,7 +1989,7 @@ - + @@ -9031,8 +9031,7 @@ Resolver / Navigator

- -
+ @@ -9054,8 +9053,7 @@ aber auch: Resolver

- - + @@ -9090,8 +9088,7 @@ an einer Stelle über eine allgemeine Abstraktion

- - +
@@ -9111,8 +9108,7 @@ implementiert LocationQuery

- - +
@@ -9146,8 +9142,7 @@ ...als Namespace-globale Variable mit externer Linkage

- - +
@@ -9167,6 +9162,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -9197,8 +9214,7 @@ nur "hinten herum" über die verwendete LocationQuery

- - +
@@ -10606,11 +10622,11 @@
+ - @@ -13055,7 +13071,7 @@ - + @@ -13081,7 +13097,7 @@ - + @@ -13149,7 +13165,7 @@ - + @@ -13194,7 +13210,7 @@ - + @@ -13205,7 +13221,7 @@ - + @@ -13283,7 +13299,7 @@ - + @@ -13309,7 +13325,7 @@ - + @@ -13380,7 +13396,7 @@ - + @@ -13468,7 +13484,7 @@ - + @@ -13477,7 +13493,7 @@ - + @@ -13550,7 +13566,7 @@ - + @@ -13919,7 +13935,7 @@ - + @@ -14010,7 +14026,7 @@ - + @@ -14123,7 +14139,7 @@ - + @@ -14427,7 +14443,7 @@ - + @@ -14464,9 +14480,9 @@ - + - + @@ -14652,7 +14668,7 @@ - + @@ -14693,10 +14709,11 @@ - - + + + - + @@ -14746,7 +14763,7 @@ - + @@ -14866,7 +14883,7 @@ - + @@ -14924,7 +14941,7 @@ - + @@ -14938,6 +14955,7 @@

+ @@ -15021,14 +15039,15 @@
- + - + + @@ -15196,7 +15215,7 @@ - + @@ -15473,7 +15492,7 @@ - + @@ -15632,7 +15651,7 @@ - + @@ -15800,10 +15819,10 @@ - + - + @@ -16109,10 +16128,10 @@ - + - + @@ -16164,7 +16183,7 @@ - + @@ -16179,7 +16198,7 @@ - + @@ -16263,7 +16282,7 @@ - + @@ -16305,7 +16324,7 @@ - + @@ -16598,7 +16617,7 @@ - + @@ -16865,7 +16884,7 @@ - + @@ -16923,7 +16942,7 @@ - + @@ -17259,7 +17278,7 @@ - + @@ -17360,7 +17379,7 @@ - + @@ -17383,7 +17402,7 @@ - + @@ -17501,7 +17520,7 @@ - + @@ -17594,7 +17613,7 @@ - + @@ -17653,7 +17672,7 @@ - + @@ -17698,7 +17717,7 @@ - + @@ -18153,7 +18172,7 @@ - + @@ -18300,7 +18319,7 @@ - + @@ -18620,7 +18639,7 @@ - + @@ -19332,7 +19351,7 @@ - + @@ -19473,9 +19492,12 @@ + + - - + + + @@ -19745,7 +19767,7 @@ - + @@ -19848,7 +19870,7 @@ - + @@ -19959,7 +19981,7 @@ - + @@ -19973,6 +19995,7 @@

+ @@ -20136,7 +20159,8 @@ - + + @@ -20153,9 +20177,9 @@ - + - + @@ -20329,7 +20353,7 @@ - + @@ -20497,7 +20521,7 @@ - + @@ -20666,10 +20690,6 @@ - - - - @@ -20689,18 +20709,18 @@ - - + + - + - + @@ -20911,7 +20931,7 @@ - + @@ -21049,7 +21069,7 @@ - + @@ -21063,7 +21083,7 @@ - + @@ -21080,7 +21100,7 @@ - + @@ -21102,8 +21122,8 @@ - - + + @@ -21180,7 +21200,7 @@ - + @@ -21378,7 +21398,7 @@ - + @@ -21487,7 +21507,7 @@ - + @@ -21537,7 +21557,7 @@ - + @@ -21587,7 +21607,8 @@ - + + @@ -21615,7 +21636,7 @@ - + @@ -21672,7 +21693,7 @@ - + @@ -21724,7 +21745,7 @@ - + @@ -21891,11 +21912,11 @@ - - + + - + @@ -21916,7 +21937,7 @@ - + @@ -21971,7 +21992,7 @@ - + @@ -22401,7 +22422,7 @@ - + @@ -22533,7 +22554,7 @@ - + @@ -22733,12 +22754,12 @@ - - + + - + @@ -22933,7 +22954,7 @@ - + @@ -23101,7 +23122,8 @@ - + + @@ -23119,7 +23141,7 @@ - + @@ -23148,14 +23170,14 @@ - + - + @@ -23163,7 +23185,7 @@ - + @@ -23519,7 +23541,7 @@ - + @@ -23623,7 +23645,7 @@ - + @@ -23772,7 +23794,7 @@ - + @@ -23806,7 +23828,7 @@ - + @@ -24060,7 +24082,7 @@ - + @@ -24096,7 +24118,7 @@ - + @@ -24405,7 +24427,58 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +