lumiera_/src/proc/control/command-invocation.hpp

156 lines
4.6 KiB
C++

/*
COMMAND-INVOCATION.hpp - shortcuts and helpers for calling Steam-Layer commands
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-invocation.hpp
** Some additional helpers and convenience shortcuts to ease command invocation.
** Especially, this header defines a set of free \c invoke(...) functions,
** allowing to bind to specific arguments and then invoke through the default
** HandlingPatern in a single call.
**
** While in some cases, a command will be set up completely finished and closed
** over all it's arguments, usually the CommandDef will just specify the command operation
** and undo function, thus leaving the task of binding concrete arguments to the client code.
** Thus, depending on the circumstances, there might be usage situations where the exact number
** and type of arguments can be detected and checked at compile time, while otherwise this check
** needs to be deferred to happen at runtime, when the binding is actually invoked.
**
** @see Command
** @see CommandDef
** @see command-binding.hpp
** @see command-use1-test.cpp
**
*/
#ifndef CONTROL_COMMAND_INVOCACTION_H
#define CONTROL_COMMAND_INVOCACTION_H
#include "proc/control/command.hpp"
#include "proc/control/handling-pattern.hpp"
#include "proc/control/argument-tuple-accept.hpp"
#include <utility>
namespace proc {
namespace control {
using namespace lib::meta;
namespace com { ///< Proc-Layer command implementation details
// define transient invoker objects, to allow for arbitrary bindings
template<typename SIG>
struct _DefineBindFunc
{
typedef ExecResult SIG_Bind(int);
};
/** @internal transient invoker object for invoking the command based
* on a function provided at compile time. Because of the
* known signature, we're able to expose a precisely typed
* function invocation operator.
*/
template<typename SIG>
struct CommandInvoker
: AcceptArgumentTuple< typename _DefineBindFunc<SIG>::SIG_Bind
, CommandInvoker<SIG>
>
{
Command com_;
CommandInvoker (Command c)
: com_(c)
{ }
template<typename TYPES>
ExecResult
bindArg (Tuple<TYPES> const& args)
{
com_.bindArg(args);
ASSERT (com_.canExec());
return com_();
}
};
/** @internal transient invoker object, usable when the exact signature
* of the command's operation isn't known at compile time.
* In this case, we allow any invocation call to compile,
* but the command will reject unsuitable signatures
* at runtime, when fetching the operation functor.
* @remarks actually this kind of invocation is the default case,
* since commands are defined statically at application start-up
* and invoked via the UI-Bus by command-ID
*/
struct RuntimeCheckedCommandInvoker
{
Command com_;
RuntimeCheckedCommandInvoker (Command c)
: com_(c)
{ }
/** invoke command with arbitrary arguments
* @warning argument types will be checked at runtime only
*/
template<typename...ARGS>
ExecResult
operator() (ARGS&& ...args)
{
com_.bind (std::forward<ARGS> (args)...);
return com_();
}
};
}
inline
com::RuntimeCheckedCommandInvoker
invoke (Symbol cmdID)
{
Command command = Command::get (cmdID);
ASSERT (command);
return com::RuntimeCheckedCommandInvoker (command);
}
inline
com::RuntimeCheckedCommandInvoker
invoke (const char* cmdID)
{
return invoke(Symbol(cmdID));
}
}} // namespace proc::control
#endif