From 789246fc3a73f5ae3e1117f4286f4c91f3659d4b Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 8 Mar 2017 04:25:33 +0100 Subject: [PATCH] draft a concept for command instantiation (#1070) --- src/gui/interact/cmd-accessor.cpp | 63 ++++ src/gui/interact/cmd-accessor.hpp | 86 +++++ src/proc/control/command-instance-manager.cpp | 73 +++++ src/proc/control/command-instance-manager.hpp | 97 ++++++ wiki/renderengine.html | 16 +- wiki/thinkPad.ichthyo.mm | 295 +++++++++++++++++- 6 files changed, 613 insertions(+), 17 deletions(-) create mode 100644 src/gui/interact/cmd-accessor.cpp create mode 100644 src/gui/interact/cmd-accessor.hpp create mode 100644 src/proc/control/command-instance-manager.cpp create mode 100644 src/proc/control/command-instance-manager.hpp diff --git a/src/gui/interact/cmd-accessor.cpp b/src/gui/interact/cmd-accessor.cpp new file mode 100644 index 000000000..4f095315d --- /dev/null +++ b/src/gui/interact/cmd-accessor.cpp @@ -0,0 +1,63 @@ +/* + CmdAccessor - interface to access command invocation services within the UI + + 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 cmd-accessor.cpp + ** Implementation details of command invocation services for the UI. + ** + ** @see TODO___cmd-accessor-test.cpp + ** + */ + + +//#include "lib/util.hpp" +//#include "lib/symbol.hpp" +//#include "include/logging.h" +#include "gui/interact/cmd-accessor.hpp" + +//#include +//#include +//#include + +//using std::map; +//using std::string; + +//using util::contains; +//using util::isnil; + +namespace gui { +namespace interact { + + namespace { // internal details + + } // internal details + + + + CmdAccessor::~CmdAccessor() { } // Emit dtors of embedded objects here... + + + + + /** nonsense */ + +}} // namespace gui::interact diff --git a/src/gui/interact/cmd-accessor.hpp b/src/gui/interact/cmd-accessor.hpp new file mode 100644 index 000000000..e37edb4d8 --- /dev/null +++ b/src/gui/interact/cmd-accessor.hpp @@ -0,0 +1,86 @@ +/* + CMD-ACCESSOR.hpp - interface to access command invocation services within the UI + + 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 cmd-accessor.hpp + ** Abstraction: access to command invocation for UI-Elements. + ** The interact::CmdAccessor front-end is used by any UI element about to invoke and dispatch + ** commands into the session via ProcDispatcher. To invoke a command, typically it is necessary + ** to prepare a _command instance_ and to pick up and bind _command arguments._ This can be achieved + ** with the help of an intermediary, known as InteractionStateManager. Thus, CmdAccessor allows to + ** discover a specific InteractionStateManager instance, which + ** - is responsible for the specific command to be invoked + ** - can handle context information related to a specific _control system_ (e.g mouse, keyboard, + ** hardware controller, pen) + ** - might handle changing contextual state and thus decide if a command can be invoked + ** From the InteractionStateManager, it is possible to retrieve a concrete InvocationTrail for + ** this specific command instance about to be invoked. This InvocationTrail is an embedded command ID + ** and can be used, to bind arguments and finally trigger the command invocation. + ** + ** @todo as of 3/2017 this is a early design draft and WIP-WIP-WIP + ** + ** @see TODO___cmd-accessor-test.cpp + ** @see ////TODO_test usage example + ** + */ + + +#ifndef GUI_INTERACT_CMD_ACCESSOR_H +#define GUI_INTERACT_CMD_ACCESSOR_H + + +#include "lib/error.hpp" +//#include "gui/ctrl/bus-term.hpp" +//#include "lib/idi/entry-id.hpp" +//#include "lib/symbol.hpp" +//#include "lib/util.hpp" + +#include +#include + + +namespace gui { +namespace interact { + +// using lib::HashVal; +// using util::isnil; + using std::string; + + + /** + * Abstract foundation of UI state tracking components. + * @todo write type comment... + */ + class CmdAccessor + : boost::noncopyable + { + + public: + ~CmdAccessor(); ///< @todo do we need a VTable / virtual dtor? + + private: + }; + + + +}} // namespace gui::interact +#endif /*GUI_INTERACT_CMD_ACCESSOR_H*/ diff --git a/src/proc/control/command-instance-manager.cpp b/src/proc/control/command-instance-manager.cpp new file mode 100644 index 000000000..08ef7da33 --- /dev/null +++ b/src/proc/control/command-instance-manager.cpp @@ -0,0 +1,73 @@ +/* + CommandInstanceManager - Key abstraction for proc/edit operations and UNDO management + + 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 command-instance-manager.cpp + ** Implementation details of instance management for command invocation by the GUI. + ** + ** @see command.hpp + ** @see command-registry.hpp + ** @see TODO_CommandInstanceManager_test + ** + */ + + +#include "lib/error.hpp" +//#include "lib/symbol.hpp" +//#include "lib/format-string.hpp" +#include "proc/control/command-instance-manager.hpp" + +//#include + +//using std::string; +//using util::cStr; +//using util::_Fmt; + + +namespace proc { +namespace control { + namespace error = lumiera::error; + + + + namespace { // implementation helper... + }//(End) implementation helper + + + + + /** storage for.... */ + + + // emit dtors of embedded objects here.... + CommandInstanceManager::~CommandInstanceManager() { } + + CommandInstanceManager::CommandInstanceManager() { } + + + + + /** more to come here...*/ + + + +}} // namespace proc::control diff --git a/src/proc/control/command-instance-manager.hpp b/src/proc/control/command-instance-manager.hpp new file mode 100644 index 000000000..06179bbee --- /dev/null +++ b/src/proc/control/command-instance-manager.hpp @@ -0,0 +1,97 @@ +/* + COMMAND-INSTANCE-MANAGER.hpp - Key abstraction for proc/edit operations and UNDO management + + 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 command-instance-manager.hpp + ** Service to support forming and invocation of command instances for use by the UI. + ** A *Proc-Layer command* is a functor, which can be parametrised with concrete arguments. + ** Typically, these arguments are to be picked up from the actual usage context in the GUI. + ** This creates the specific twist that possible command instances for invocation can and will + ** be formed during an extended time period, non-deterministically -- since the actual context + ** depends on the user interactions. Within the UI, there is a dedicated mechanism to form such + ** command invocation similar to forming sentences of a language (with subject, predication and + ** possibly some further objects). The UI manages several InteractionStateManager instances to + ** observe and pick up contextual state, finally leading to a complete parametrisation of a command. + ** The CommandInstanceManager is a service to support this process; it prepares command instances + ** and provides dedicated instance IDs, which can be stored in the UI and later used to retrieve + ** those instances for invocation. These IDs are created by decorating a base command ID, allowing + ** for several competing invocations to exist at the same time. When finally a given invocation is + ** about to happen, a corresponding registration handle is transfered to the ProcDispatcher, where + ** it is enqueued for execution. + ** + ** @see command-def.hpp + ** @see command.hpp + ** @see command-accessor.hpp + ** @see TODO_CommandInstanceManager_test + ** + */ + + + +#ifndef CONTROL_COMMAND_INSTANCE_MANAGER_H +#define CONTROL_COMMAND_INSTANCE_MANAGER_H + +#include "lib/error.hpp" +//#include "lib/symbol.hpp" +//#include "proc/common.hpp" + +#include +//#include + + + + +namespace proc { +namespace control { + +// using std::string; +// using lib::Symbol; + //using std::shared_ptr; + + + + /** + * @todo write type comment + */ + class CommandInstanceManager + : boost::noncopyable + { + + public: + + CommandInstanceManager(); + ~CommandInstanceManager(); + + + private: + }; + + + + + /** */ + + + + +}} // namespace proc::control +#endif /*CONTROL_COMMAND_INSTANCE_MANAGER_H*/ diff --git a/wiki/renderengine.html b/wiki/renderengine.html index ed329bd5d..9431c1546 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2582,7 +2582,7 @@ This contrastive approach attempts to keep knowledge and definition clustered in &rarr; GuiCommandCycle -
+
//the process of issuing a session command from the UI//
 Within the Lumiera UI, we distinguish between core concerns and the //local mechanics of the UI.// The latter is addressed in the usual way, based on a variation of the [[MVC-Pattern|http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller]]. The UI toolkit set, here the GTK, affords ample ways to express actions and reactions within this framework, where widgets in the presentation view are wired with the corresponding controllers vice versa (GTK terms these connections as //"signals"//, we rely on {{{libSigC++}}} for implementation).
 A naive approach would extend these mature mechanisms to also cover the actual functionality of the application. This compelling solution allows quickly to get "something tangible" up and running, yet -- on the long run -- inevitably leads to core concerns being tangled into the presentation layer, which in turn becomes hard to maintain and loaded with "code behind". Since we are here "for the long run", we immediately draw the distinction between UI mechanics and core concerns. The latter are, by decree and axiom, required to perform without even an UI layer running. This decision gives rise to the challenge how to form and integrate the invocation of ''core commands'' into the presentation layer.
@@ -2609,7 +2609,19 @@ from these use cases, we can derive the //crucial activities for command handlin
 :a widget just wants to invoke a command, yet it needs the help of "some" InteractionStateManager for
 :* creating the command instance, so arguments can be bound
 :* fill in missing values for the arguments, depending on context
-
+ +!command invocation protocol +* at start-up, command definitions are created in Proc, hard wired +* ~UI-Elements know the basic ~Command-IDs relevant to their functionality. These are defined in some central header +* when command usage is indicated, some part in the UI queries the {{{CmdAccessor}}} for an InteractionStateManager +* the latter in turn retrieves a new command instance ID from the {{{CmdInstanceManager}}} in Proc +* and the latter keeps a smart-ptr corresponding to this instance in its internal registration table +* within the UI, a command instance corresponds to a specific invocation trail, and is thus stored within the managing {{{InteractionStateManager}}} +* ~UI-Elements use the services of the InteractionStateManager, either to get arguments directly, or to act as observer of state changes +* when a command is completely parametrised, it can be invoked. The managing {{{InteractionStateManager}}} knows about this +* on invocation, the ID of the instance is sent via UI-Bus to the {{{CmdInstanceManager}}} +* which in turn removes the instance handle from its registration table and hands it over into the ProcDispatcher +Consequently this means that command instances will be formed //per {{{InteractionStateManager}}} instance.// Thus, each distinct kind of control system has its own instances, which are kept around, until they are ready for invocation. Each invocation "burns" an instance -- on next access, a new instance ID will be allocated, and the next command invocation cycle starts...
All communication between Proc-Layer and GUI has to be routed through the respective LayerSeparationInterfaces. Following a fundamental design decision within Lumiera, these interface are //intended to be language agnostic// &mdash; forcing them to stick to the least common denominator. Which creates the additional problem of how to create a smooth integration without forcing the architecture into functional decomposition style. To solve this problem, we rely on ''messaging'' rather than on a //business facade// -- our facade interfaces are rather narrow and limited to lifecycle management. In addition, the UI exposes a [[notification facade|GuiNotificationFacade]] for pushing back status information created as result of the edit operations, the build process and the render tasks.
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 1d93028e6..42c98d877 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -2486,9 +2486,9 @@
 
 
 
-
+
 
-
+
 
 
 
@@ -11124,20 +11124,37 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
 
-
-
-
-
+
+
+
+
 
-
-
+
+
+
+
 
 
-
+
 
 
 
@@ -11149,8 +11166,8 @@
 
 
 
-
-
+
+
 
 
   
@@ -11189,7 +11206,8 @@
 
 
 
-
+
+
 
 
 
@@ -11220,8 +11238,81 @@
 
 
 
+
+
+
+
+
 
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  
+    
+  
+  
+    

+ GUI: CmdAccessor +

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

+ Proc: CmdInstanceManager +

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + @@ -11239,12 +11330,186 @@ - + + + + + + + + +

+ hat überhaupt nichts mit dem Zugang zu Commands zu tun, +

+

+ und auch nichts mit der Trennung zwischen Layern und Subsystemen +

+ + +
+
+ + + + + + +

+ es geht um Service-Dependencies +

+

+ aka DependencyInjection + Lifecycle Management +

+ + +
+ + + + + + + + + +
    +
  • + man hat ein statisches Front-End, d.h. by-name access +
  • +
  • + hinter dem liegt eine Factory +
  • +
  • + die Instanz kann von innen her wieder geschlossen werden +
  • +
  • + wenn geschlossen, dann Fehler werfen +
  • +
+ + +
+
+
+
+
+
+ + + + + + + + + +

+ ...nicht klar, ob das notwendig (und gut) ist +

+

+ es könnte auch ausreichen, einfach die passende InteractionStateManager-Impl zu verwenden +

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

+ denn InteractionStateManager ist ein Interface! +

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

+ ...das UI weiß, +

+

+ wer das konkret immer sein wird. +

+

+ D.h. beim Start des UI wird eine Verbindung irgendwo hinterlegt +

+

+ Das könnte ein Advice sein +

+ + +
+
+ + + + + + +

+ vom Command her ist der Typ festgelegt +

+

+ auf das "aktuelle Element" wir eine Art Typ-Match gemacht. +

+

+ Wenn der paßt, kann das aktuelle Element verwendet werden. +

+

+ In diesem Fall wird das Command enabled +

+ + +
+
+ + + + + + +

+ eine Argumentliste mit mehreren Parametern wir Schritt für Schritt geschlossen +

+ + +
+
+ + + + + + +

+ wenn mehrere Objekte als Argumente in Frage kommen, +

+

+ wird das gemäß Scope "nächstgelegne" genommen +

+ + +
+
+
+ + +
-