From b865acf7587ed20399eb63d01f94f0f2e85e5b94 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 18 Mar 2017 01:55:45 +0100 Subject: [PATCH] Commands: decide about the basic concept how commands are to be defined (#215) The point in question is how to manage these definitions in practice, since we're about to create a huge lot of them eventually. The solution attempted here is heavily inspired by the boost-test framework --- src/proc/cmd.hpp | 3 +- src/proc/control/command-instance-manager.hpp | 6 +- ...instance-manager.cpp => command-setup.cpp} | 9 +- src/proc/control/command-setup.hpp | 100 +++++++++++++++ .../control/session-command-function-test.cpp | 2 +- wiki/renderengine.html | 18 ++- wiki/thinkPad.ichthyo.mm | 118 +++++++++++++++++- 7 files changed, 242 insertions(+), 14 deletions(-) rename src/proc/control/{command-instance-manager.cpp => command-setup.cpp} (88%) create mode 100644 src/proc/control/command-setup.hpp diff --git a/src/proc/cmd.hpp b/src/proc/cmd.hpp index 08ab2c31f..c6cab24f7 100644 --- a/src/proc/cmd.hpp +++ b/src/proc/cmd.hpp @@ -39,8 +39,7 @@ #ifndef PROC_CMD_H #define PROC_CMD_H -#include "lib/error.hpp" -#include "proc/control/command.hpp" +#include "proc/control/command-setup.hpp" //#include "lib/symbol.hpp" //#include "proc/common.hpp" diff --git a/src/proc/control/command-instance-manager.hpp b/src/proc/control/command-instance-manager.hpp index 06179bbee..0075a2cd8 100644 --- a/src/proc/control/command-instance-manager.hpp +++ b/src/proc/control/command-instance-manager.hpp @@ -1,5 +1,5 @@ /* - COMMAND-INSTANCE-MANAGER.hpp - Key abstraction for proc/edit operations and UNDO management + COMMAND-INSTANCE-MANAGER.hpp - Service to manage command instances for actual invocation Copyright (C) Lumiera.org 2017, Hermann Vosseler @@ -38,8 +38,10 @@ ** about to happen, a corresponding registration handle is transfered to the ProcDispatcher, where ** it is enqueued for execution. ** - ** @see command-def.hpp + ** @see command-setup.cpp service implementation ** @see command.hpp + ** @see command-def.hpp + ** @see command-setup.hpp ** @see command-accessor.hpp ** @see TODO_CommandInstanceManager_test ** diff --git a/src/proc/control/command-instance-manager.cpp b/src/proc/control/command-setup.cpp similarity index 88% rename from src/proc/control/command-instance-manager.cpp rename to src/proc/control/command-setup.cpp index 08ef7da33..ab3828224 100644 --- a/src/proc/control/command-instance-manager.cpp +++ b/src/proc/control/command-setup.cpp @@ -1,5 +1,5 @@ /* - CommandInstanceManager - Key abstraction for proc/edit operations and UNDO management + CommandSetup - Implementation of command registration and instance management Copyright (C) Lumiera.org 2017, Hermann Vosseler @@ -21,12 +21,14 @@ * *****************************************************/ -/** @file command-instance-manager.cpp +/** @file command-setup.cpp ** Implementation details of instance management for command invocation by the GUI. ** + ** @see command-setup.hpp + ** @see command-instance-manager.hpp + ** @see TODO_CommandInstanceManager_test ** @see command.hpp ** @see command-registry.hpp - ** @see TODO_CommandInstanceManager_test ** */ @@ -60,6 +62,7 @@ namespace control { // emit dtors of embedded objects here.... CommandInstanceManager::~CommandInstanceManager() { } + CommandSetup::~CommandSetup() { } CommandInstanceManager::CommandInstanceManager() { } diff --git a/src/proc/control/command-setup.hpp b/src/proc/control/command-setup.hpp new file mode 100644 index 000000000..19fc759d0 --- /dev/null +++ b/src/proc/control/command-setup.hpp @@ -0,0 +1,100 @@ +/* + COMMAND-INSTANCE-SETUP.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-setup.hpp + ** Provision for setup of concrete commands for use by the UI. + ** A *Proc-Layer command* is a functor, which can be parametrised with actual arguments. + ** It needs to be [defined](command-def.hpp) beforehand, which means to establish an unique + ** name and to supply three functions, one for the actual command operation, one to capture + ** state and one to _undo_ the effect of the command invocation. CommandSetup allows to create + ** series of such definitions with minimal effort. Since any access and mutation from the UI into + ** the Session data must be performed by invoking such commands, a huge amount of individual command + ** definitions need to be written eventually. + ** + ** The macro COMMAND_DEFINITION(name) allows to introduce a new definition with a single line, + ** followed by a code block, which actually ends up as the body of a lambda function, and receives + ** the bare CommandDef as single argument with name `cmd`. The `name` argument of the macro ends up + ** both stringified as the value of the command-ID, and as an identifier holding a new CommandSetup + ** instance. It is assumed that a header with corresponding _declarations_ (the header \ref cmd.hpp) + ** is included by all UI elements actually to use, handle and invoke commands towards the + ** session-command-facade.h + ** + ** @todo WIP-WIP 3/2017 initial draft + ** + ** @see command-def.hpp + ** @see command.hpp + ** @see command-accessor.hpp + ** @see TODO_CommandSetup_test + ** + */ + + + +#ifndef CONTROL_COMMAND_SETUP_H +#define CONTROL_COMMAND_SETUP_H + +#include "lib/error.hpp" +#include "proc/control/command.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 CommandSetup + : boost::noncopyable + { + + public: + + ~CommandSetup(); + + + private: + }; + + + + + /** */ + + + + +}} // namespace proc::control +#endif /*CONTROL_COMMAND_SETUP_H*/ diff --git a/tests/core/proc/control/session-command-function-test.cpp b/tests/core/proc/control/session-command-function-test.cpp index 195c66b6a..13cec905e 100644 --- a/tests/core/proc/control/session-command-function-test.cpp +++ b/tests/core/proc/control/session-command-function-test.cpp @@ -68,7 +68,7 @@ ** while some producer threads are still alive -- because in this case the main thread might ** verify the checksum before all command instances have been triggered. To avoid this ** situation, make sure the delay between actions in the threads is not too long and - ** start a sufficiently high nubmer of producer threads. + ** start a sufficiently high number of producer threads. ** */ diff --git a/wiki/renderengine.html b/wiki/renderengine.html index d07d980d6..a12fb3a25 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -1472,7 +1472,7 @@ Commands are //defined// using a [[fluent API|http://en.wikipedia.org/wiki/Fluen → see CommandUsage -
+
Commands can be identified and accessed //by name// — consequently there needs to be an internal command registry, including a link to the actual implementing function, thus allowing to re-establish the connection between command and implementing functions when de-serialising a persisted command. To create a command, we need to provide the following information
 * operation function actually implementing the command
 * function to [[undo|UndoManager]] the effect of the command
@@ -1502,6 +1502,7 @@ Usually, parameters should be passed //by value// — with the exception
 !Actual command definition scripts
 The actual scripts bound as functors into the aforementioned command definitions are located in translation units in {{{proc/cmd}}}
 These definitions must be written in a way to ensure that just compiling those translation units causes registration of the corresponding command-~IDs
+This is achieved by placing a series of CommandSetup helper instances into those command defining translation units.
 
@@ -1604,6 +1605,15 @@ When a command has been executed (and maybe undone), it's best to leave it alone State predicates are accessible through the Command (frontend); additionally there are static query functions in class {{{Command}}}
+
+
//Helper facility to ease the creation of actual command definitions.//
+A [[Proc-Layer command|CommandHandling]] is a functor, which can be parametrised with actual arguments. It needs to be [defined](command-def.hpp) beforehand, which means to establish an unique name and to supply three functions, one for the actual command operation, one to capture state and one to [[UNDO]] the effect of the command invocation. 
+
+The helper class {{{CommandSetup}}} allows to create series of such definitions with minimal effort. Since any access and mutation from the UI into the Session data must be performed by invoking such commands, a huge amount of individual command definitions need to be written eventually. These are organised into a series of implementation translation units with location {{{poc/cmd/*-cmd.cpp}}}.
+
+Each of these files is specialised to defining a set of thematically related command, supplying the code for the actual command scripts. Each definition is introduced by a single line with the macro {{{COMMAND_DEFINITION(name)}}}, followed by a code block, which actually ends up as the body of a lambda function, and receives the bare [[CommandDef|CommandDefinition]] as single argument with name {{{cmd}}}. The {{{name}}} argument of the macro ends up both stringified as the value of the command-~ID, and as an identifier holding a new {{{CommandSetup}}} instance. It is assumed that a header with //corresponding declarations// (the header {{{cmd.hpp}}}) is included by all UI elements actually to use, handle and invoke commands towards the SessionSubsystem
+
+
//for now (7/09) I'll use this page to collect ideas how commands might be used...//
 
@@ -2553,7 +2563,7 @@ In a typical editing application, the user can expect to get some visual clue re
 To start with, mostly this means to avoid a naive approach, like having code in the UI to pull in some graphics from media files. We certainly won't just render every media channel blindly. Rather, we acknowledge that we'll have a //strategy,// depending on the media content and some further parameters of the clip. This might well just be a single ''pivot image'' chosen explicitly by the editor to represent a given take. And the actual implementation of content preview rendering will largely be postponed until we get our rendering engine into a roughly working state.
 
-
+
The question //how to connect the notion of an ''interface action'' to the notion of a ''command'' issued towards the [[session model|HighLevelModel]].//
 * actual design of command invocation in the UI → GuiCommandCycle
 * study of pivotal action invocation situations → CommandInvocationAnalysis
@@ -2591,9 +2601,10 @@ This contrastive approach attempts to keep knowledge and definition clustered in
 
 ''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.
 → GuiCommandCycle
+→ CommandSetup
 
-
+
//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.
@@ -2641,6 +2652,7 @@ Command instances are like prototypes -- thus each additional level of different
 → Command scripts are defined in translation units in {{{proc/cmd}}}
 → They reside in the corresponding namespace, which is typically aliased as {{{cmd}}}
 → definitions and usage include the common header {{{proc/cmd.hpp}}}
+see the description in → CommandSetup
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index a51b3b0ff..7f4b04338 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -11823,11 +11823,11 @@ - + - + @@ -11876,7 +11876,7 @@ - + @@ -11894,6 +11894,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ vermutlich läuft es immer darauf hinaus +

+
    +
  • + daß cmd.hpp die Implementierungs-Einheiten includiert +
  • +
  • + oder daß in einer ausgezeichneten Impl-Einheit das marker-Makro gesetzt wird und dann cmd.hpp includiert wird +
  • +
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +