WIP: create a "scrapbook" test for trying out some ideas

This commit is contained in:
Fischlurch 2009-06-08 21:29:09 +02:00
parent ba37045b48
commit 3a7de1654a
5 changed files with 185 additions and 6 deletions

View file

@ -0,0 +1,81 @@
/*
COMMAND-DEF.hpp - defining and binding a Proc-Layer command
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
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-def.hpp
** Actually defining a command and binding it to execution parameters.
** While the header command.hpp contains everything needed for executing and
** commands and referring to them, this more heavy-weight header is needed when
** \em defining the concrete operations to be encapsulated into a command. To
** create a command, you need to provide three functors (for the actual operation,
** the undo operation and for capturing undo state prior to invoking the operation).
** Besides, you provide a \em binding, thus creating a closue out of these three
** function objects and a set of actual parameters. This closure effectively is
** the command, which in a last step can be either dispatched, stored or
** invoked immediately.
** //TODO
**
** @see Command
** @see Mutation
** @see CommandClosure
** @see ProcDispatcher
** @see CommandBasic_test simple usage example
**
*/
#ifndef CONTROL_COMMAND_H
#define CONTROL_COMMAND_H
//#include "pre.hpp"
#include "proc/control/command.hpp"
#include "proc/control/mutation.hpp"
#include "proc/control/command-closure.hpp"
//#include <tr1/memory>
namespace control {
// using lumiera::Symbol;
// using std::tr1::shared_ptr;
/**
* @todo Type-comment
*/
class CommandDef
{
public:
};
////////////////TODO currently just fleshing out the API....
} // namespace control
#endif

View file

@ -3,4 +3,8 @@ TESTING "Component Test Suite: Proc-Layer controller" ./test-components --group=
PLANNED "CommandBasic_test" CommandBasic_test <<END
END
#

View file

@ -47,6 +47,7 @@ test_components_SOURCES = \
$(testcomponents_srcdir)/proc/asset/makecliptest.cpp \
$(testcomponents_srcdir)/proc/asset/orderingofassetstest.cpp \
$(testcomponents_srcdir)/proc/asset/testasset.cpp \
$(testcomponents_srcdir)/proc/control/command-basic-test.cpp \
$(testcomponents_srcdir)/proc/engine/bufftabletest.cpp \
$(testcomponents_srcdir)/proc/engine/sourcenodetest.cpp \
$(testcomponents_srcdir)/proc/mobject/builder/buildertooltest.cpp \

View file

@ -0,0 +1,94 @@
/*
CommandBasic(Test) - checking simple ProcDispatcher command definition and execution
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
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.
* *****************************************************/
#include "lib/test/run.hpp"
//#include "proc/asset/media.hpp"
//#include "proc/mobject/session.hpp"
//#include "proc/mobject/session/edl.hpp"
//#include "proc/mobject/session/testclip.hpp"
//#include "proc/mobject/placement.hpp"
//#include "proc/mobject/placement-index.hpp"
//#include "proc/mobject/explicitplacement.hpp"
#include "proc/control/command-def.hpp"
//#include "lib/util.hpp"
//#include <boost/format.hpp>
//#include <iostream>
#include <string>
//using boost::format;
//using lumiera::Time;
//using util::contains;
using std::string;
//using std::cout;
namespace control {
namespace test {
// using session::test::TestClip;
namespace command1 {
////////////////////////////////////////////TODO braindump
////////////////////////////////////////////TODO braindump
}
/***************************************************************************
* @test basic usage of the Proc-Layer command dispatch system.
* Shows how to define a simple command inline and another
* simple command as dedicated class. Finally triggers
* execution of both commands and verifies the command
* action has been invoked.
*
* @todo currently rather a scrapbook for trying out first ideas on the command system !!!!!!!!!!!!!!!
*
* @see control::Command
* @see control::CommandDef
* @see mobject::ProcDispatcher
*/
class CommandBasic_test : public Test
{
typedef shared_ptr<PlacementIndex> PIdx;
virtual void
run (Arg)
{
/////////////////////////////////TODO
}
void
checkExecution ()
{
}
};
/** Register this test class... */
LAUNCHER (CommandBasic_test, "unit controller");
}} // namespace control::test

View file

@ -957,7 +957,7 @@ Thus, each command is a ''Functor'' and a ''Closure'' ([[command pattern|http://
&amp;rarr; see CommandHandling</pre>
</div>
<div title="CommandHandling" modifier="Ichthyostega" modified="200906080146" created="200906072048" tags="SessionLogic spec draft decision design img" changecount="17">
<div title="CommandHandling" modifier="Ichthyostega" modified="200906080316" created="200906072048" tags="SessionLogic spec draft decision design img" changecount="21">
<pre>Organising any ''mutating'' operations executable by the user (via GUI) by means of the [[command pattern|http://en.wikipedia.org/wiki/Command_pattern]] can be considered //state of the art//&amp;nbsp; today. First of all, it allows to discern the specific implementation operations to be called on one or several objects within the HighLevelModel from the operation requested by the user, the latter being rather a concept. A command can be labeled clearly, executed under controlled circumstances, allowing transactional behaviour.
@ -965,13 +965,12 @@ Thus, each command is a ''Functor'' and a ''Closure'' ([[command pattern|http://
[&gt;img[Structure of Commands|uml/fig134021.png]] Basically, a command could contain arbitrary operations, but we'll assume that it causes a well defined mutation within the HighLevelModel, which can be ''undone''. Thus, when defining a command, we need to specify not only a function doing the mutation, but also another function which might be called later to reverse the effect of the action. Besides, the action operates on a number of ''target'' objects and additionally may require a set of ''parameter'' values. These are to be stored explicitly within the command object, thus creating a ''closure'' &amp;mdash; the operation //must not//&amp;nbsp; rely on other hidden parameters (maybe with the exception of very generic singleton system services?).
Theoretically, defining the &quot;undo&quot; operation might utilise two different approaches:
* specifying an //inverse operation,// known to cancel out the effect of the command operation
* capturing a //state memento,// which can be played back to restore the state found prior to executing the command.
while obviously the first solution is much simpler to implement on behalf of the command framework, the second solution has distinct advantages, especially in the context of an editing application: there might be rounding or calculation errors, the inverse might be difficult to define correctly, the effect of the operation might depend on circumstances, be random, or might even trigger a resolution operation to yield the final result. Thus the decision is within Lumiera to //favour state capturing// &amp;mdash; but in a modified, semi-manual and not completely exclusive way.
* specifying an //inverse operation,// known to cancel out the effect of the command
* capturing a //state memento,// which can later be played back to restore the state found prior to executing the command.
While obviously the first solution is much simpler to implement on behalf of the command framework, the second solution has distinct advantages, especially in the context of an editing application: there might be rounding or calculation errors, the inverse might be difficult to define correctly, the effect of the operation might depend on circumstances, be random, or might even trigger a resolution operation to yield the final result. Thus the decision is within Lumiera Proc-Layer to //favour state capturing// &amp;mdash; but in a modified, semi-manual and not completely exclusive way.
!Undo state
While the usual implementation might automatically capture the whole model (resulting in a lot of data to be stored and some uncertainty about the scope of the model to be captured), in Lumiera we rely instead on the client code to provide a ''capture function'' and a ''playback function'' alongside with the actual operation. To help with this task, we provide a set of standard handlers for common situations. This way, operations might capture very specific information, might provide an &quot;intelligent undo&quot; to restore a given semantic instead of just a fixed value &amp;mdash; and moreover the client code is free actually to employ the &quot;inverse operation&quot; model in special cases where it just makes more sense.
While the usual implementation might automatically capture the whole model (resulting in a lot of data to be stored and some uncertainty about the scope of the model to be captured), in Lumiera we rely instead on the client code to provide a ''capture function'' and a ''playback function'' alongside with the actual operation. To help with this task, we provide a set of standard handlers for common situations. This way, operations might capture very specific information, might provide an &quot;intelligent undo&quot; to restore a given semantic instead of just a fixed value &amp;mdash; and moreover the client code is free actually to employ the &quot;inverse operation&quot; model in special cases where it just makes more sense than capturing state.
!Handling of commands
A command may be defined completely from scratch, or it might just instantiate a CommandPrototype with specific targets and parameters. The command could then be serialised and later be recovered and re-bound with the parameters, but usually it will be handed over to the ProcDispatcher, pending execution. When ''invoking'', the handling sequence is to [[log the command|SessionStorage]], then call the ''undo capture function'', followed from calling the actual ''operation function''. After success, the logging and [[undo registration|UndoManager]] is completed. In any case, finally the ''result signal'' (a functor previously stored within the command) is emitted.