/* VIEW-SPEC-DSL.hpp - configuration of view allocation patterns Copyright (C) Lumiera.org 2017, 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 view-spec-dsl.hpp ** A framework for configuration of view access and allocation patterns. ** Component views are building blocks of the Lumiera UI, and may, depending on their, ** be instantiated or allocated according to specific rules and patterns. And these might ** vary in accordance to the desired working style. To give a typical example, at times it ** might be mandatory to use a single, external output for all kind of media playback, while ** other users prefer the classical editing application layout with two media viewers side by ** side. And yet another working style would be to use a stack of media viewers allocated on ** demand in MRU-fashion. ** ** To specify those standard behaviour patterns, we provide a small internal DSL to spell out ** the default configuration in a (hopefully) self explanatory way. ** @todo as of 9/2017, the intention to open this configuration DSL for some kind of ** user provided flexible configuration of screen layouts eventually; right now ** only the foundation for this flexible configuration is provided while the defaults ** are compiled in hard wired. ** ** # Allocation of UI component views ** ** Here, Allocation means ** - to constitute the desired element's identity ** - to consider multiplicity and possibly retrieve an existing instance ** - to determine the hosting location ** - possibly to instantiate and register a new instance ** - and finally to configure that instance for the desired role ** ** ## View access ** ** The global access point to component views is the ViewLocator within InteractionDirector, ** which exposes a generic access- and management API to ** - get (possibly create) some view of given type ** - get (possibly create) a view with specific identity ** - destroy a specific view ** Together these operations expose a strictly typed direct reference to the respective view component ** and thus allow to manage them like child objects. Operating on top of these primitive operations, ** the _configuration of view access patterns_ creates a flexible binding layer, which isolates the ** users of component views (typically other parts of the UI) from the actual mechanics of locating. ** While the client just retrieves a view instance, a dedicate _allocation logic_ ensures this view ** instance is placed at the desired place within the UI and manages the active view instances. ** ** ## Configuration DSL ** ** Access to component views typically happens through the ViewLocator provided by the InteractionDirector. ** The implementation of view access in turn redirects access through the configured patterns. ** - at [definition site](\ref id-scheme.hpp), explicit specialisations are given for the relevant types ** of component view ** - each of those general view configurations ** * defines the multiplicity allowed for this kind of view ** * defines how to locate this view ** ... and that location definition is given as a list of alternatives in order of precedence. ** That is, the system tries each pattern of location and uses the first one applicable. ** ** Actually, the definitions and tokens used within the configuration DSL are implemented as _functors._ ** At implementation level, the basic specification tokens are bound to the corresponding operations ** within ViewLocator and PanelLocator. Thus, the "value" retrieved from the configuration is actually ** a functor, which provides the desired behaviour pattern ** - the *locate* spec is evaluated to yield [user interface coordinates](\ref UICoord) representing the ** desired location of the view ** - the *allocate* spec is then evaluated as a second step, while providing the coordinates from first step. ** This results in calling a dedicated _view allocator_ to create a new view or re-use an existing one ** as appropriate. ** ** @note the actual binding for the DSL tokens can be found in the [ViewLocator implementation](view-locator.cpp) ** ** @see ViewSpecDSL_test ** @see id-scheme.hpp ** @see view-locator.hpp ** @see view-locator.cpp ** @see interaction-director.hpp */ #ifndef GUI_INTERACT_VIEW_SPEC_DSL_H #define GUI_INTERACT_VIEW_SPEC_DSL_H #include "lib/error.hpp" #include "lib/symbol.hpp" #include "gui/interact/ui-coord.hpp" //#include #include //#include //#include #include namespace gui { namespace interact { // using std::unique_ptr; // using std::string; // class GlobalCtx; /** * A specification to describe the desired location of a component view within the Lumiera UI. * ViewSpec is basically a set of [UI coordinates](\ref UICoord), with the additional possibility * of specifying several alternatives, with the intention to pick the first applicable one. * * @todo initial draft as of 9/2017 */ class ViewSpec { public: ViewSpec(UICoord coordinates) { UNIMPLEMENTED ("build a view spec from explicitly given UI coordinates"); } /** shortcut to allow initialisation from UI-Coordintate builder expressiong */ ViewSpec(UICoord::Builder&& coordinates) : ViewSpec{UICoord(std::move (coordinates))} { } operator UICoord() { UNIMPLEMENTED ("resolve a view spec to yield explicit UI coordinates"); } private: }; /** * Allocator is a functor to resolve a given, desired location of a view within the UI, resulting * in creation or allocation of the view. The result of this invocation are the UI coordinates * of an existing or newly created view. */ class Allocator : public std::function { }; template class AllocSpec : public std::function { public: template AllocSpec(FUN fun) { UNIMPLEMENTED ("generate an allocator builder functor by partial function application"); } }; }}// namespace gui::interact #endif /*GUI_INTERACT_VIEW_SPEC_DSL_H*/