WIP draft capturing mechanism implementation, using the new tools and helpers...
This commit is contained in:
parent
c8c577c4cc
commit
2348a5af2b
2 changed files with 74 additions and 76 deletions
|
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
//#include "pre.hpp"
|
//#include "pre.hpp"
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
|
#include "lib/bool-checkable.hpp"
|
||||||
#include "proc/control/command-closure.hpp"
|
#include "proc/control/command-closure.hpp"
|
||||||
#include "proc/control/memento-tie.hpp"
|
#include "proc/control/memento-tie.hpp"
|
||||||
|
|
||||||
|
|
@ -66,6 +67,7 @@ namespace control {
|
||||||
* @todo Type-comment
|
* @todo Type-comment
|
||||||
*/
|
*/
|
||||||
class Mutation
|
class Mutation
|
||||||
|
: public lib::BoolCheckable<Mutation>
|
||||||
{
|
{
|
||||||
CmdFunctor func_;
|
CmdFunctor func_;
|
||||||
CmdClosure* clo_;
|
CmdClosure* clo_;
|
||||||
|
|
@ -101,37 +103,24 @@ namespace control {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* == diagnostics == */
|
/** diagnostics */
|
||||||
typedef CmdClosure* Mutation::*_unspecified_bool_type;
|
|
||||||
|
|
||||||
/** implicit conversion to "bool" */
|
|
||||||
operator _unspecified_bool_type() const { return isValid()? &Mutation::clo_ : 0; } // never throws
|
|
||||||
bool operator! () const { return !isValid(); } // ditto
|
|
||||||
|
|
||||||
operator string() const
|
operator string() const
|
||||||
{
|
{
|
||||||
return isValid()? string (*clo_) : "Mutation(state missing)";
|
return isValid()? string (*clo_) : "Mutation(state missing)";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool
|
virtual bool
|
||||||
isValid () const
|
isValid () const
|
||||||
{
|
{
|
||||||
return func_ && clo_;
|
return func_ && clo_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
void
|
void
|
||||||
invoke (CmdFunctor & closedFunction)
|
invoke (CmdFunctor & closedFunction)
|
||||||
{
|
{
|
||||||
closedFunction.getFun<void()>() ();
|
closedFunction.getFun<void()>() ();
|
||||||
}
|
}
|
||||||
|
|
||||||
CmdClosure&
|
|
||||||
getClosure() ///< Interface for subclasses to access the bound parameters
|
|
||||||
{
|
|
||||||
REQUIRE (clo_, "Lifecycle error: function arguments not yet bound");
|
|
||||||
return *clo_;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -146,51 +135,24 @@ namespace control {
|
||||||
class UndoMutation
|
class UndoMutation
|
||||||
: public Mutation
|
: public Mutation
|
||||||
{
|
{
|
||||||
Mutation memento_;
|
Mutation captureMemento_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename SIG_undo, typename SIG_cap>
|
template<typename TIE>
|
||||||
UndoMutation (function<SIG_undo> const& undoFunc,
|
UndoMutation (TIE & mementoHolder)
|
||||||
function<SIG_cap> const& captureFunc)
|
: Mutation (mementoHolder.tieUndoFunc())
|
||||||
: Mutation (undoFunc)
|
, captureMemento_(mementoHolder.tieCaptureFunc())
|
||||||
, memento_(captureFunc)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
#if false /////////////////////////////////////////////////TODO: remove after refactoring
|
|
||||||
UndoMutation (UndoMutation const& o)
|
|
||||||
: Mutation (*this)
|
|
||||||
, captureFunc_(o.captureFunc_)
|
|
||||||
, memento_(o.memento_->clone().get())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
UndoMutation&
|
|
||||||
operator= (UndoMutation const& o)
|
|
||||||
{
|
|
||||||
Mutation::operator= (o);
|
|
||||||
captureFunc_ = o.captureFunc_;
|
|
||||||
memento_.reset(o.memento_->clone().get());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual Mutation&
|
virtual Mutation&
|
||||||
close (CmdClosure& cmdClosure)
|
close (CmdClosure& cmdClosure)
|
||||||
{
|
{
|
||||||
REQUIRE (!memento_, "Lifecycle error: already closed over the arguments");
|
Mutation::close(cmdClosure);
|
||||||
REQUIRE (captureFunc_, "Param error: not bound to a valid function");
|
captureMemento_.close(cmdClosure);
|
||||||
|
|
||||||
// create a special state closure, which can later on store the captured undo state (memento)
|
|
||||||
scoped_ptr<MementoClosure> stateClosure (new MementoClosure (captureFunc_));
|
|
||||||
CmdFunctor closedCaptureFunc = cmdClosure.bindArguments(captureFunc_);
|
|
||||||
|
|
||||||
// the undoFunc (within parent class) will retrieve an argument tuple extended by the memento
|
|
||||||
Mutation::close (stateClosure->decorate (cmdClosure));
|
|
||||||
|
|
||||||
captureFunc_ = closedCaptureFunc;
|
|
||||||
// memento_.swap(stateClosure);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Mutation&
|
Mutation&
|
||||||
captureState ()
|
captureState ()
|
||||||
|
|
@ -199,22 +161,16 @@ namespace control {
|
||||||
throw lumiera::error::State ("need to bind function arguments prior to capturing undo state",
|
throw lumiera::error::State ("need to bind function arguments prior to capturing undo state",
|
||||||
LUMIERA_ERROR_UNBOUND_ARGUMENTS);
|
LUMIERA_ERROR_UNBOUND_ARGUMENTS);
|
||||||
|
|
||||||
memento_();
|
captureMemento_();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CmdClosure&
|
|
||||||
getMemento()
|
|
||||||
{
|
|
||||||
ASSERT (memento_, "Lifecycle error: need to close first");
|
|
||||||
// return *memento_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool
|
virtual bool
|
||||||
isValid () const
|
isValid () const
|
||||||
{
|
{
|
||||||
// return Mutation::isValid() && captureFunc_ && memento_;
|
return Mutation::isValid() && memento_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
** the "undo capture function" and the actual "undo function", by retrieving the
|
** the "undo capture function" and the actual "undo function", by retrieving the
|
||||||
** memento data or memento object from the former and feeding it to the latter
|
** memento data or memento object from the former and feeding it to the latter
|
||||||
** as an additional parameter, when the undo operation is invoked.
|
** as an additional parameter, when the undo operation is invoked.
|
||||||
** //TODO
|
|
||||||
**
|
**
|
||||||
** @see CmdClosure
|
** @see CmdClosure
|
||||||
** @see UndoMutation
|
** @see UndoMutation
|
||||||
|
|
@ -44,7 +43,7 @@
|
||||||
//#include "pre.hpp"
|
//#include "pre.hpp"
|
||||||
//#include "lib/meta/typelist.hpp" ////////////////TODO include these??
|
//#include "lib/meta/typelist.hpp" ////////////////TODO include these??
|
||||||
//#include "lib/meta/function.hpp"
|
//#include "lib/meta/function.hpp"
|
||||||
//#include "lib/meta/function-closure.hpp"
|
#include "lib/meta/function-closure.hpp"
|
||||||
//#include "lib/meta/function-erasure.hpp"
|
//#include "lib/meta/function-erasure.hpp"
|
||||||
//#include "lib/meta/tuple.hpp"
|
//#include "lib/meta/tuple.hpp"
|
||||||
#include "proc/control/command-signature.hpp"
|
#include "proc/control/command-signature.hpp"
|
||||||
|
|
@ -52,7 +51,7 @@
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
//#include <tr1/memory>
|
//#include <tr1/memory>
|
||||||
//#include <tr1/functional>
|
#include <tr1/functional>
|
||||||
//#include <iostream>
|
//#include <iostream>
|
||||||
//#include <string>
|
//#include <string>
|
||||||
|
|
||||||
|
|
@ -70,6 +69,7 @@ namespace control {
|
||||||
// using std::tr1::shared_ptr;
|
// using std::tr1::shared_ptr;
|
||||||
// using util::unConst;
|
// using util::unConst;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
using lumiera::typelist::func::bindLast;
|
||||||
// using std::ostream;
|
// using std::ostream;
|
||||||
// using std::tr1::function;
|
// using std::tr1::function;
|
||||||
// using lumiera::typelist::FunctionSignature;
|
// using lumiera::typelist::FunctionSignature;
|
||||||
|
|
@ -85,10 +85,10 @@ namespace control {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binding together state capturing and execution of the undo operation.
|
* Binding together state capturing and execution of the undo operation.
|
||||||
* MementoTie itself is passive container object with a very specific type,
|
* MementoTie itself is a passive container object with a very specific type,
|
||||||
* depending on the type of the operation arguments and the type of the memento.
|
* depending on the type of the operation arguments and the type of the memento.
|
||||||
* It is to be allocated within the ArgumentHolder of the command, thereby wrapping
|
* It is to be allocated within the ArgumentHolder of the command, thereby wrapping
|
||||||
* or decorating the undo and capture function, setting up the necessary bindings and
|
* or decorating the undo and capture function, setting up the necessary bindings and
|
||||||
* closures, allowing them to cooperate behind the scenes to carry out the UNDO functionality.
|
* closures, allowing them to cooperate behind the scenes to carry out the UNDO functionality.
|
||||||
* Through a reference to the MementoTie, the UndoMutation functor gets access to the prepared
|
* Through a reference to the MementoTie, the UndoMutation functor gets access to the prepared
|
||||||
* functions, storing them into generic containers (type erasure) for later invocation.
|
* functions, storing them into generic containers (type erasure) for later invocation.
|
||||||
|
|
@ -109,20 +109,15 @@ namespace control {
|
||||||
/** storage holding the captured state for undo */
|
/** storage holding the captured state for undo */
|
||||||
MEM memento_;
|
MEM memento_;
|
||||||
|
|
||||||
function<SIG> undo_;
|
bool isCaptured_;
|
||||||
function<SIG> capture_;
|
|
||||||
|
|
||||||
|
function<SIG_undo> undo_;
|
||||||
|
function<SIG_cap> capture_;
|
||||||
|
|
||||||
function<SIG>
|
void capture (MEM const& mementoVal)
|
||||||
buildFun()
|
|
||||||
{
|
{
|
||||||
// PlaceholderTuple<SIG> tup;
|
memento_ = mementoVal;
|
||||||
// return tupleApplicator(tup).bind(origFun);
|
isCaptured_ = true;
|
||||||
}
|
|
||||||
|
|
||||||
void capture ()
|
|
||||||
{
|
|
||||||
memento_ = capture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -133,11 +128,58 @@ namespace control {
|
||||||
*/
|
*/
|
||||||
MementoTie (function<SIG_undo> const& undoFunc,
|
MementoTie (function<SIG_undo> const& undoFunc,
|
||||||
function<SIG_cap> const& captureFunc)
|
function<SIG_cap> const& captureFunc)
|
||||||
|
: memento_()
|
||||||
|
, isCaptured_(false)
|
||||||
|
, undo_(undoFunc)
|
||||||
|
, capture_(captureFunc)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////TODO currently just fleshing out the API....
|
/** bind the undo function to the internal memento store within this object.
|
||||||
|
* @return a functor, which, when invoked with the remaining arguments, will
|
||||||
|
* automatically call #getState() to retrieve the current memento value.
|
||||||
|
* @note similar to #getState(), the returned functor will throw
|
||||||
|
* when the state capturing wasn't yet invoked
|
||||||
|
*/
|
||||||
|
function<SIG>
|
||||||
|
tieUndoFunc()
|
||||||
|
{
|
||||||
|
using std::tr1::bind;
|
||||||
|
|
||||||
|
return bindLast( undo_
|
||||||
|
, bind (&MementoTie::getState, this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** bind the capturing function to the internal memento store within this object.
|
||||||
|
* @return a functor, which on invocation will automatically store the return value
|
||||||
|
* of the capturing function (= the current memento value) into the field
|
||||||
|
* #memento_ within this object
|
||||||
|
*/
|
||||||
|
function<SIG>
|
||||||
|
tieCaptureFunc()
|
||||||
|
{
|
||||||
|
using std::tr1::placeholders::_1;
|
||||||
|
|
||||||
|
function<void(MEM)> doCaptureMemento = bind (&MementoTie::capture, this, _1);
|
||||||
|
|
||||||
|
return chained(capture_, doCaptureMemento);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** get the currently captured memento state value
|
||||||
|
* @throw when the capturing function wasn't yet invoked
|
||||||
|
*/
|
||||||
|
MEM&
|
||||||
|
getState ()
|
||||||
|
{
|
||||||
|
if (!isCaptured_)
|
||||||
|
throw lumiera::error::State ("need to invoke memento state capturing beforehand",
|
||||||
|
LUMIERA_ERROR_MISSING_MEMENTO);
|
||||||
|
return memento_;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue