From 449fa16444d9c6979611370d29e4acfeee75a15a Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 19 Dec 2015 03:40:19 +0100 Subject: [PATCH] WIP: draft of the UI backbone setup - front-end handle - Nexus == routing hub - CoreService == service access point for command invocation --- src/gui/ctrl/bus-controller.cpp | 25 ++++--- src/gui/ctrl/bus-term.hpp | 15 ++++- src/gui/ctrl/core-service.hpp | 115 ++++++++++++++++++++++++++++++++ src/gui/ctrl/nexus.hpp | 4 +- src/gui/gtk-lumiera.cpp | 3 + src/gui/ui-bus.cpp | 19 +++++- src/gui/ui-bus.hpp | 43 +++++++++++- wiki/renderengine.html | 17 +++-- wiki/thinkPad.ichthyo.mm | 37 +++++++++- 9 files changed, 255 insertions(+), 23 deletions(-) create mode 100644 src/gui/ctrl/core-service.hpp diff --git a/src/gui/ctrl/bus-controller.cpp b/src/gui/ctrl/bus-controller.cpp index 9edb4bdaa..fc76fb258 100644 --- a/src/gui/ctrl/bus-controller.cpp +++ b/src/gui/ctrl/bus-controller.cpp @@ -89,6 +89,23 @@ namespace ctrl { /* ==== standard implementation of the BusTerm interface ==== */ + /** prepare or trigger invocation of a command. + * @param command a GenNode holding parameters invocation trigger + * @remarks some commands can simply be invoked right away, but + * in the general case, command preparation and invocation + * is a multi-step process. The gui::interact::InvocationTrail + * is used to conduct this argument binding process from within + * the UI. Here, at the UI-Bus interface, we're just interested + * in the fact _that_ some command is to be bound or invoked. + * This information is forwarded to the command receiver service, + * which in turn talks to the proc dispatcher. + * @note no information regarding the _origin_ of this command invocation + * is captured. If a command needs a _subject_, this has to be + * bound as an command argument beforehand. + * @see gui::interact::InvocationTrail + * @see gui::model::Tangible::prepareCommand() + * @see gui::model::Tangible::issueCommand() + */ void BusTerm::act (GenNode const& command) { @@ -96,14 +113,6 @@ namespace ctrl { } - /** record state mark from this subject */ - void - BusTerm::note (GenNode const& mark) - { - theBus_.note(this->endpointID_, mark); - } - - /** */ void BusTerm::note (ID subject, GenNode const& mark) diff --git a/src/gui/ctrl/bus-term.hpp b/src/gui/ctrl/bus-term.hpp index f9f9c4032..1c4268996 100644 --- a/src/gui/ctrl/bus-term.hpp +++ b/src/gui/ctrl/bus-term.hpp @@ -106,12 +106,12 @@ namespace ctrl{ public: virtual ~BusTerm(); ///< this is an interface - virtual void act (GenNode const& command); - virtual void note (GenNode const& mark); - + virtual void act (GenNode const& command); virtual void note (ID subject, GenNode const& mark); virtual void mark (ID subject, GenNode const& mark); + void note (GenNode const& mark); + ID getID() const { return endpointID_; } @@ -132,6 +132,15 @@ namespace ctrl{ }; + + + /** record state mark from this subject */ + void + BusTerm::note (GenNode const& mark) + { + theBus_.note (this->endpointID_, mark); + } + }} // namespace gui::ctrl #endif /*GUI_CTRL_BUS_TERM_H*/ diff --git a/src/gui/ctrl/core-service.hpp b/src/gui/ctrl/core-service.hpp new file mode 100644 index 000000000..bd3dac340 --- /dev/null +++ b/src/gui/ctrl/core-service.hpp @@ -0,0 +1,115 @@ +/* + CORE-SERVICE.hpp - fake user interface backbone for test support + + Copyright (C) Lumiera.org + 2015, 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 test/nexus.hpp + ** Core hub and routing table of the UI-Bus. + ** Any relevant element within the Lumiera GTK UI is connected to the [UI-Bus][ui-bus.hpp] + ** through some [bus terminal][bus-term.hpp]. Actually, there is one special BustTerm + ** implementation, which acts as router and messaging hub. + ** + ** @todo initial draft and WIP-WIP-WIP as of 11/2015 + ** + ** @see abstract-tangible-test.cpp + ** + */ + + +#ifndef GUI_CTRL_CORE_SERVICE_H +#define GUI_CTRL_CORE_SERVICE_H + + +#include "lib/error.hpp" +//#include "lib/idi/entry-id.hpp" +#include "gui/ctrl/bus-term.hpp" +//#include "lib/util.hpp" +//#include "gui/model/tangible.hpp" +//#include "lib/diff/record.hpp" +#include "lib/idi/entry-id.hpp" + +#include +//#include + + +namespace gui { +namespace ctrl{ + +// using lib::HashVal; +// using util::isnil; +// using lib::idi::EntryID; +// using lib::diff::Record; +// using std::string; + + + /** + * Central hub of the UI-Bus. + * This special implementation of the [BusTerm] interface maintains + * a routing table and manages the connections to individual UI-Elements. + * The nexus relies on a dedicated (up)link to the [CoreService] to handle + * command invocation and presentation state. + * + * @todo write type comment + */ + class CoreService + : public BusTerm + , boost::noncopyable + { + + + virtual void + note (ID subject, GenNode const& mark) override + { + UNIMPLEMENTED ("forward note messages to the presentation state manager"); + } + + + virtual void + mark (ID subject, GenNode const& mark) override + { + UNIMPLEMENTED ("route mark messages down to the individual Tangible"); + } + + + virtual BusTerm& + routeAdd(Tangible newNode) override + { + UNIMPLEMENTED ("add a new down-link connection to the routing table"); + } + + + virtual void + routeDetach(ID node) noexcept override + { + UNIMPLEMENTED ("deactivate and remove a down-link route"); + } + + public: + explicit + CoreService (BusTerm& uplink_to_CoreService, ID identity =lib::idi::EntryID()) + : BusTerm(identity, uplink_to_CoreService) + { } + }; + + + +}} // namespace gui::ctrl +#endif /*GUI_CTRL_CORE_SERVICE_H*/ diff --git a/src/gui/ctrl/nexus.hpp b/src/gui/ctrl/nexus.hpp index cefd673d4..044523915 100644 --- a/src/gui/ctrl/nexus.hpp +++ b/src/gui/ctrl/nexus.hpp @@ -1,5 +1,5 @@ /* - test/NEXUS.hpp - fake user interface backbone for test support + NEXUS.hpp - UI-Bus central hub and routing table Copyright (C) Lumiera.org 2015, Hermann Vosseler @@ -64,6 +64,8 @@ namespace ctrl{ * Central hub of the UI-Bus. * This special implementation of the [BusTerm] interface maintains * a routing table and manages the connections to individual UI-Elements. + * The nexus relies on a dedicated (up)link to the [CoreService] to handle + * command invocation and presentation state. * * @todo write type comment */ diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index da6fb7957..3f3719d69 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -97,6 +97,9 @@ namespace gui { Project project; Controller controller(project); + //////////////////////TICKET #959 : establish the new backbone here / replaces Project and Controller + // UiBus uiBus; + windowManagerInstance_.init (Config::get (KEY_ICON_PATH), Config::get (KEY_UIRES_PATH)); windowManagerInstance_.setTheme (Config::get (KEY_STYLESHEET)); diff --git a/src/gui/ui-bus.cpp b/src/gui/ui-bus.cpp index 1a398fcc1..6b8062a80 100644 --- a/src/gui/ui-bus.cpp +++ b/src/gui/ui-bus.cpp @@ -25,6 +25,7 @@ #include "gui/ui-bus.hpp" namespace gui { + ///////////////////////////////////////////////////////////////////////////////////TICKET #959 : scheduled for termination.... namespace controller { Controller::Controller (model::Project& modelProject) @@ -39,5 +40,19 @@ namespace controller { return playback_; } -}}// namespace gui::controller - +}// namespace gui::controller + ///////////////////////////////////////////////////////////////////////////////////TICKET #959 : scheduled for termination.... + + + UiBus::UiBus() + { } + + + UiBus::~UiBus() + { + TODO ("UI-Bus Lifecycle"); + } + + + +}// namespace gui diff --git a/src/gui/ui-bus.hpp b/src/gui/ui-bus.hpp index a242f7536..6fbf32e75 100644 --- a/src/gui/ui-bus.hpp +++ b/src/gui/ui-bus.hpp @@ -22,7 +22,20 @@ */ /** @file ui-bus.hpp - ** The top level UI controller. + ** Under construction: the top level UI controller. + ** The Lumiera GTK GUI is built around a generic backbone structure known as **UI-Bus**. + ** This is a messaging system and taps into any widget of more than local relevance. + ** To that end, any globally relevant (custom) widget, and all secondary controllers + ** inherit from the gui::model::Tangible base. The top-level gui::UiBus element is + ** a front-end and framework component managed by the [GTK-main][GtkLumiera::main]. + ** + ** @warning as of 12/2015, this is still totally a mess. This \em will remain + ** the one-and-only master controller of the UI, but I am determined + ** to change the architecture and implementation technique altogether. + ** For the time being, we keep the controller::Controller in place, as + ** written by Joel Holdsworth, while building the new UI-Bus frontend + ** to take on this central role eventually. + ** ** ** @todo as of 1/2015, this needs to be reshaped ////////////////////TICKET #959 */ @@ -35,8 +48,11 @@ #include "gui/gtk-lumiera.hpp" //////////////////////////////////////////////////////TODO remove any GTK dependency if possible #include "gui/ctrl/playback-controller.hpp" +#include + namespace gui { + ///////////////////////////////////////////////////////////////////////////////////TICKET #959 : scheduled for termination.... namespace model { class Project; } // namespace model @@ -57,6 +73,29 @@ namespace gui { PlaybackController& get_playback_controller(); }; -}}// namespace gui::controller +}// namespace gui::controller + ///////////////////////////////////////////////////////////////////////////////////TICKET #959 : scheduled for termination.... + + + /** + * Backbone of the Lumiera GTK GUI. + * This is the Interface and Lifecycle front-end. + * When an instance of this class is created, the backbone becomes operative + * and is linked to the active gui::WindowManager. When it goes away, the + * backbone service switches into disabled mode, awaiting disconnection + * of all remaining clients. After that, it dissolves into nothingness. + */ + class UiBus + : boost::noncopyable + { + public: + UiBus(); + ~UiBus(); + + }; + + + +}// namespace gui #endif /*GUI_UI_BUS_H*/ diff --git a/wiki/renderengine.html b/wiki/renderengine.html index cd2b8c270..364c716e0 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2383,12 +2383,12 @@ On a second thought, the fact that the [[Bus-MObject|BusMO]] is rather void of a :sound mixing desks use list style arrangement, and this has proven to be quite viable, when combined with the ability to //send over// output from one mixer stripe to the input of another, allowing to build arbitrary complex filter matrices. On the other hand, organising a mix in //subgroups// can be considered best practice. This leads to arranging the pipes //as wood:// by default and on top level as list, optionally expanding into a subtree with automatic rooting, augmented by the ability to route any output to any input (cycles being detected and flagged as error). -
+
The question //how to connect the notion of an ''interface action'' to the notion of a ''command'' issued towards the [[session model|HighLevelModel]].//
 
 !prerequisites for issuing a command
 Within the Lumiera architecture, with the very distinct separation between [[Session]] and interface view, several steps have to be met before we're able to operate on the model.
-* we need a pre-written script, which directly works on the entities reachable through the session interface
+* we need a pre-written script, which directly works on the entities reachable through the session interface &rarr; [[Command handling in Proc-Layer|CommandHandling]]
 * we need to complement this script with a state capturing script and a script to undo the given action
 * we need to combine these fixed snippets into a //command prototype.//
 * we need to care for the supply of parameters
@@ -2414,7 +2414,7 @@ This contrastive approach attempts to keep knowledge and definition clustered in
 * we need to introduce a new abstraction, termed InteractionStateManager. This is deliberately not a single entity, rather some distinct facility in charge for one specific kind of interaction, like gestures being formed by mouse, touch or pen input.
 * from the command definition site, we need to send a combination of //rules// and parameter accessors, which together define an invocation path for one specific flavour of a command
 * the InteractionStateManager, driven by the state changes he observes, will evaluate those rules and determine the feasibility of specific command invocation paths
-* he sends the //enablement of a command invocation trail// as a preconfigured binding to the actual //trigger sites,// which in turn allows them to install actual reaction patterns
+* he sends the //enablement of a command invocation trail// as a preconfigured binding to the actual //trigger sites,// which in turn allows them to install actual reaction patterns &rarr; InvocationTrail
 * if finally some button is hit, the local event binding can issue the command right away, as preconfigured in this //enablement binding,// by accessing just any UI-Bus terminal at reach within that context
 
 ''Lumera decides to take the latter apptoch'' -- resulting in a separation between immediate low-level UI element reactions, and anything of relevance for the behaviour of the UI. The widget code embodies the low-level UI element reactions and as such becomes more or less meaningless beyond local concerns of layout and presentation. If you want to find out about the behaviour of the UI, you need to know where to look, and you need to know how to read and understand those enablement rules. Another consequence is the build-up of dedicated yet rather abstract state tracking facilities, hooking like an octopus into various widgets and controllers, which might work counter to the intentions behind the design of common UI toolkit sets.
@@ -2954,6 +2954,10 @@ From experiences with other middle scale projects, I prefer having the test code
 [img[Example: Interfaces/Namespaces of the ~Session-Subsystems|uml/fig130053.png]]
 
+
+
//A command in preparation of being issued from the UI.//
+The actual persistent operations on the session model are defined as DSL scripts acting on the session interface, and configured as a //command prototype.// Typically these need to be enriched with at least the actual subject to invoke this command on; many commands require additional parameters, e.g. some time or colour value. These actual invocation parameters need to be picked up from UI elements, and the process of preparing and outfitting a generic command with these actual values is tracked by an ''InvocationTrail handle''. When ready, finally this handle can be issued on any bus terminal, i.e. on any [[tangible interface element|UI-Element]].
+
The actual media data is rendered by [[individually scheduled render jobs|RenderJob]]. All these calculations together implement a [[stream of calculations|CalcStream]], as demanded and directed by the PlayProcess. During the preparation of playback, a ''node planning phase'' is performed, to arrange for [[dispatching|FrameDispatcher]] the individual calculations per frame.  The goal of these //preparations//&nbsp; is to find out
 * what channel(s) to pull
@@ -8366,7 +8370,7 @@ For now, as of 6/10, we use specialised QueryResolver instances explicitly and d
 &rarr; QueryRegistration
 
-
+
Abstraction used in the Backbone of Lumiera's GTK User Interface
 The UI-Bus is a ''Mediator'' -- impersonating the role of the //Model// and the //Controler// in the [[MVC-Pattern|http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller]] in common UI architecture.
 
@@ -8380,7 +8384,7 @@ And we arrive at a backbone like structure, which can be wired, programmed and r
 The UI-Bus has a star shaped topology, with a central "bus master" hub, which maintains a routing table. Attachment and detachment of elements can be managed automatically, since all of the UI-Bus operations perform within the GUI event thread. We distinguish between up-link messages, directed towards some central service (presentation state management or command invocation) and down-link messages, directed towards individual elements. The interactions at the bus are closely interrelated with the elementary UI-Element operations.
 ;act
 :send a GenNode representing the action
-:* in a first step, a command prototype is outfitted with actual parameter values
+:* in a first step, a command prototype is outfitted with actual parameter values &rarr; InvocationTrail
 :* the actual command invocation is triggered by a "bang" message
 ;note
 :send a GenNode representing the //state mark//
@@ -8389,7 +8393,7 @@ The UI-Bus has a star shaped topology, with a central "bus master" hub
 :down-link communication to //feed back// state updates or to replay previously recorded  //state marks//
 
-
+
While our UI widgets are implemented the standard way as proposed by GTKmm, some key elements -- which are especially relevant for the anatomy and mechanics of the interface -- are made to conform to a common interface and behaviour protocol. {{red{WIP 11/15 work out what this protocol is all about}}}. #975
 As a starting point, we know
 * there is a backbone structure known as the UI-Bus
@@ -8441,6 +8445,7 @@ We should note that these conventions of interchange lead to a recursive or ''se
 While the above definitions might seem more or less obvious and reasonable, there is one tiny detail, which -- on second thought -- unfolds into a fundamental decision to be taken. The point in question is //how we refer to a command.// More specifically: is referring to a command something generic, or is it rather something left to the actual implementing widget? In the first case, a generic foundation element has to provide some framework to deal with command definitions, whereas in the second case just a protected slot to pass on invocations from derived classes would be sufficient. This is a question of fundamental importance; subsidiarity has its merits, so once we forgo the opportunity to build from a generic pattern, local patterns will take over, while similarities and symmetries have to grow and wait to be discovered sometimes, if at all. This might actually not be a problem -- yet if you know Lumiera, you know that we tend to look at existing practice and draw fundamental conclusions, prior to acting.
 &rarr; InteractionControl
 &rarr; GuiCommandBinding
+&rarr; [[Command handling (Proc-Layer)|CommandHandling]]
 
 !!!actual implementation of command invocation
 The {{{InvocationTrail}}} of an command is actually just a tag object, wrapping the command definition ID. In a first step, when the arguments can be closed, a {{{Record}}} with suitable bindings is created and wrapped into a {{{GenNode}}} corresponding to the command. This compound is sent over the UI-Bus, marking the command ready for execution. From this point on, just the {{{InvocationTrail}}} is passed to enable the trigger sites. When it is triggered, just a "bang!" message with the command ID is sent over the bus. An command instance can be re-used, as long as it is structurally the same as before, and as log as there is no possible collision with a similar, but differently parametrised instantiation process.
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 02dfe96a2..9df85fc81 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -306,8 +306,24 @@
 
 
 
-
+
 
+
+
+
+
+  
+    
+  
+  
+    

+ ...was ich einen Monat später schon wieder vergessen hatte... +

+ + +
+ +
@@ -345,6 +361,12 @@ + + + + + + @@ -2691,6 +2713,19 @@ + + + + + + + + + + + + +