fix further problems uncovered by test; allow for anonymous cloning
This commit is contained in:
parent
17c7160f02
commit
0bcbf7fee0
5 changed files with 48 additions and 20 deletions
|
|
@ -32,8 +32,7 @@
|
|||
namespace control {
|
||||
|
||||
|
||||
|
||||
|
||||
LUMIERA_ERROR_DECLARE (INVALID_ARGUMENTS); ///< Arguments provided for binding doesn't match stored command function parameters
|
||||
|
||||
|
||||
|
||||
|
|
@ -63,7 +62,8 @@ namespace control {
|
|||
{
|
||||
TypedArguments<TUP>* dest = dynamic_cast<TypedArguments<TUP>*> (this);
|
||||
if (!dest)
|
||||
throw lumiera::error::Invalid("Wrong type or number of arguments");
|
||||
throw lumiera::error::Invalid("Wrong type or number of arguments"
|
||||
, LUMIERA_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
return dest->args_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,13 +92,13 @@ namespace control {
|
|||
using lumiera::typelist::NullType;
|
||||
using lumiera::typelist::Tuple;
|
||||
|
||||
typedef shared_ptr<CommandImpl> ImplInstance;
|
||||
typedef function<Command&(ImplInstance const&)> Activation;
|
||||
|
||||
|
||||
|
||||
namespace stage { ///< helpers for building up a command definition
|
||||
|
||||
typedef shared_ptr<CommandImpl> ImplInstance;
|
||||
typedef function<Command&(ImplInstance const&)> Activation;
|
||||
|
||||
|
||||
template<typename SIG>
|
||||
|
|
@ -245,6 +245,9 @@ namespace control {
|
|||
Symbol id_;
|
||||
Command prototype_;
|
||||
|
||||
typedef stage::ImplInstance PImpl;
|
||||
typedef stage::Activation Activation;
|
||||
|
||||
public:
|
||||
CommandDef (Symbol cmdID)
|
||||
: id_(cmdID)
|
||||
|
|
@ -275,9 +278,9 @@ namespace control {
|
|||
/** callback from completed command definition stage:
|
||||
* "arm up" the command handle object and register it
|
||||
* with the CommandRegistry. */
|
||||
Command& activate (ImplInstance const& completedDef)
|
||||
Command& activate (PImpl const& completedDef)
|
||||
{
|
||||
prototype_.activate (id_,completedDef);
|
||||
prototype_.activate (completedDef, id_);
|
||||
ENSURE (prototype_);
|
||||
return prototype_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,10 +117,13 @@ namespace control {
|
|||
}
|
||||
|
||||
|
||||
/** @internal to be invoked through CommandDef to make a command ready for use
|
||||
* @throw error::Logic when this is already activated. */
|
||||
/** @internal make a command ready for use. Typically to be invoked
|
||||
* through CommandDef during the definition stage, but also used
|
||||
* for activating clone instances.
|
||||
* @param cmdID new ID for creating a separate command registration when provided
|
||||
* @throw error::Logic when \c this is already activated. */
|
||||
void
|
||||
Command::activate (Symbol cmdID, shared_ptr<CommandImpl> const& implFrame)
|
||||
Command::activate (shared_ptr<CommandImpl> const& implFrame, Symbol cmdID)
|
||||
{
|
||||
REQUIRE (implFrame);
|
||||
static format fmt("Command \"%s\" already defined");
|
||||
|
|
@ -129,12 +132,15 @@ namespace control {
|
|||
duplicate_detected (cmdID);
|
||||
|
||||
_Handle::activate (implFrame);
|
||||
CommandRegistry::instance().track (cmdID, *this);
|
||||
if (cmdID)
|
||||
CommandRegistry::instance().track (cmdID, *this);
|
||||
|
||||
INFO (command, "Command \"%s\" defined OK", cStr(*this));
|
||||
}
|
||||
|
||||
|
||||
/** create an independent clone copy of this command
|
||||
* and register it as new command definition under a different ID */
|
||||
Command
|
||||
Command::storeDef (Symbol newCmdID) const
|
||||
{
|
||||
|
|
@ -144,12 +150,26 @@ namespace control {
|
|||
duplicate_detected (newCmdID);
|
||||
|
||||
Command cloneDefinition;
|
||||
cloneDefinition.activate (newCmdID, registry.createCloneImpl(impl()));
|
||||
cloneDefinition.activate (registry.createCloneImpl(this->impl()), newCmdID);
|
||||
ENSURE (cloneDefinition);
|
||||
return cloneDefinition;
|
||||
}
|
||||
|
||||
|
||||
/** create independent clone copy of this command */
|
||||
Command
|
||||
Command::newInstance () const
|
||||
{
|
||||
CommandRegistry& registry = CommandRegistry::instance();
|
||||
shared_ptr<CommandImpl> cloneImpl = registry.createCloneImpl(this->impl());
|
||||
|
||||
Command clone;
|
||||
clone.activate (cloneImpl);
|
||||
ENSURE (clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Command::duplicate_detected (Symbol newCmdID) const
|
||||
{
|
||||
|
|
@ -305,6 +325,10 @@ namespace control {
|
|||
ExecResult
|
||||
Command::exec (HandlingPattern const& execPattern)
|
||||
{
|
||||
if (!canExec())
|
||||
throw error::State ("Lifecycle error: command arguments not bound",
|
||||
LUMIERA_ERROR_UNBOUND_ARGUMENTS);
|
||||
|
||||
CommandImpl& thisCommand (_Handle::impl());
|
||||
return execPattern.invoke (thisCommand, cStr(*this));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ namespace control {
|
|||
|
||||
/** create a clone definition */
|
||||
Command storeDef (Symbol newCmdID) const;
|
||||
Command newInstance () const;
|
||||
|
||||
Command() { } ///< undefined command
|
||||
~Command();
|
||||
|
|
@ -175,7 +176,7 @@ namespace control {
|
|||
|
||||
protected:
|
||||
static Command fetchDef (Symbol cmdID);
|
||||
void activate (Symbol cmdID, shared_ptr<CommandImpl> const&);
|
||||
void activate (shared_ptr<CommandImpl> const&, Symbol cmdID =0);
|
||||
|
||||
friend class CommandDef; //...invoking those two functions during definition stage
|
||||
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ namespace test {
|
|||
def.operation (command1::operate)
|
||||
.captureUndo (command1::capture);
|
||||
ASSERT (!def); // undo functor still missing
|
||||
ASSERT (!Command::get("test.command1.2"));
|
||||
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.2") );
|
||||
|
||||
def.operation (command1::operate)
|
||||
.captureUndo (command1::capture)
|
||||
|
|
@ -213,10 +213,10 @@ namespace test {
|
|||
ASSERT (c1.canExec());
|
||||
ASSERT (!c1.canUndo());
|
||||
|
||||
Command c2 = Command::get("test.command1.3");
|
||||
ASSERT (c1);
|
||||
ASSERT (c1.canExec());
|
||||
ASSERT (!c1.canUndo());
|
||||
Command c2 = c1.newInstance();
|
||||
ASSERT (c2);
|
||||
ASSERT (c2.canExec());
|
||||
ASSERT (!c2.canUndo());
|
||||
|
||||
ASSERT (c1 == c2);
|
||||
ASSERT (!isSameObject(c1, c2));
|
||||
|
|
@ -226,9 +226,9 @@ namespace test {
|
|||
c1();
|
||||
|
||||
ASSERT (randVal == command1::check_);
|
||||
ASSERT (c1.canUndo());
|
||||
ASSERT (c1 != c2);
|
||||
ASSERT ( c1.canUndo());
|
||||
ASSERT (!c2.canUndo());
|
||||
ASSERT (c1 != c2);
|
||||
|
||||
c2();
|
||||
ASSERT (randVal + randVal == command1::check_);
|
||||
|
|
|
|||
Loading…
Reference in a new issue