diff --git a/src/proc/control/command-def.hpp b/src/proc/control/command-def.hpp index 5f4eb19af..058f06ce9 100644 --- a/src/proc/control/command-def.hpp +++ b/src/proc/control/command-def.hpp @@ -91,6 +91,7 @@ namespace control { using lumiera::typelist::Types; using lumiera::typelist::NullType; using lumiera::typelist::Tuple; + using lumiera::typelist::tuple::makeNullTuple; @@ -101,6 +102,8 @@ namespace control { typedef function Activation; + + template struct CompletedDefinition : AcceptArgumentBindingRet< Command&, SIG // Return type and Argument Signature of the \c bind(..) function @@ -115,19 +118,52 @@ namespace control { : prototype_(definedCommand) { REQUIRE (prototype_); + maybeArm_if_zero_parameters(); TRACE (command_dbg, "Completed definition of %s.", cStr(prototype_)); } + typedef HandlingPattern::ID PattID; - PattID getDefaultHandlingPattern() const { return prototype_.getDefaultHandlingPattern();} - PattID setHandlingPattern (PattID newID) { return prototype_.setHandlingPattern(newID); } + /** allow for defining the default execution pattern, + * which is used by Command::operator() */ + CompletedDefinition + setHandlingPattern (PattID newID) + { + prototype_.setHandlingPattern(newID); + return *this; + } + + /** allow to bind immediately to a set of arguments. + * @return standard Command handle, usable for invocation + */ Command& bindArg (Tuple const& params) { return prototype_.bindArg(params); } + + + /** a completed definition can be retrieved and + * manipulated further through a standard Command handle + */ + operator Command () + { + return prototype_; + } + + private: + /** Helper: automatically "bind" and make executable a command, + * for the case when the command operation takes zero arguments. + * Because even in that case we need to build a CmdClosure internally. + */ + void + maybeArm_if_zero_parameters() + { + if (0 == Tuple::SIZE ) + prototype_.bindArg (makeNullTuple()); + } }; diff --git a/src/proc/control/command-invocation.hpp b/src/proc/control/command-invocation.hpp index 6f87f598f..64cbbe44f 100644 --- a/src/proc/control/command-invocation.hpp +++ b/src/proc/control/command-invocation.hpp @@ -124,6 +124,17 @@ namespace control { } + template< typename T1 + , typename T2 + > + ExecResult //_________________________________ + operator() (T1 a1, T2 a2) ///< Invoke command with 2 Arguments + { + com_.bind(a1,a2); + return com_(); + } + + template< typename T1 , typename T2 , typename T3 @@ -134,6 +145,48 @@ namespace control { com_.bind(a1,a2,a3); return com_(); } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + > + ExecResult //_________________________________ + operator() (T1 a1, T2 a2, T3 a3, T4 a4) ///< Invoke command with 4 Arguments + { + com_.bind(a1,a2,a3,a4); + return com_(); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + > + ExecResult //_________________________________ + operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) ///< Invoke command with 5 Arguments + { + com_.bind(a1,a2,a3,a4,a5); + return com_(); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + > + ExecResult //_________________________________ + operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) ///< Invoke command with 6 Arguments + { + com_.bind(a1,a2,a3,a4,a5,a6); + return com_(); + } }; } diff --git a/tests/45controller.tests b/tests/45controller.tests index e65406102..a5f0f530f 100644 --- a/tests/45controller.tests +++ b/tests/45controller.tests @@ -70,12 +70,18 @@ return: 0 END -TEST "handling pattern basics" HandlingPatternBasics_test < + + 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/control/command-def.hpp" + +#include "proc/control/test-dummy-commands.hpp" + +#include + + +namespace control { +namespace test { + + using std::cout; + using std::endl; + + + + + + + + /***************************************************************************** + * @test coverage for some specific situations when binding command arguments. + * + * @todo add more test cases... + * + * @see Command + * @see command-basic-test.cpp (simple usage example) + * @see command-use1-test.cpp (various aspects of command use) + */ + class CommandBinding_test : public Test + { + + + virtual void + run (Arg) + { + uint cnt_defs = Command::definition_count(); + uint cnt_inst = Command::instance_count(); + + zeroArgumentCommand(); + + Command::remove("test.command3.1"); + Command::remove("test.command3.2"); + + ASSERT (cnt_defs == Command::definition_count()); + ASSERT (cnt_inst == Command::instance_count()); + } + + + void + zeroArgumentCommand() + { + command3::check_ = 0; + + CommandDef ("test.command3.1") + .operation (command3::operate) + .captureUndo (command3::capture) + .undoOperation (command3::undoIt) + .bind() // spurious bind doesn't hurt + .execSync() + ; + + ASSERT ( 1 == command3::check_); + + CommandDef ("test.command3.2") + .operation (command3::operate) + .captureUndo (command3::capture) + .undoOperation (command3::undoIt) + ; + Command com ("test.command3.2"); + ASSERT (com.canExec()); + cout << string(com) << endl; + + com(); + ASSERT ( 2 == command3::check_); + com.undo(); + ASSERT ( 1 == command3::check_); + + Command commi = com.newInstance(); + com(); + com(); + com(); + ASSERT ( 4 == command3::check_); + + commi.undo(); // it uses the inherited UNDO state + ASSERT ( 1 == command3::check_); + + com.undo(); + ASSERT ( 3 == command3::check_); + + Command::get("test.command3.1").undo(); + ASSERT ( 0 == command3::check_); + } + }; + + + + /** Register this test class... */ + LAUNCHER (CommandBinding_test, "function controller"); + + +}} // namespace control::test diff --git a/tests/components/proc/control/command-use1-test.cpp b/tests/components/proc/control/command-use1-test.cpp index b20fdbace..8e2452551 100644 --- a/tests/components/proc/control/command-use1-test.cpp +++ b/tests/components/proc/control/command-use1-test.cpp @@ -312,12 +312,12 @@ namespace test { cout << string (Command::get("test.command1.4")) << endl; cout << string (Command() ) << endl; - CommandDef ("test.command1.5") - .operation (command1::operate) - .captureUndo (command1::capture) - .undoOperation (command1::undoIt); + Command com + = CommandDef ("test.command1.5") + .operation (command1::operate) + .captureUndo (command1::capture) + .undoOperation (command1::undoIt); - Command com("test.command1.5"); cout << string (com) << endl; com.bind(123); cout << string (com) << endl; diff --git a/tests/components/proc/control/test-dummy-commands.cpp b/tests/components/proc/control/test-dummy-commands.cpp index 8ec030c72..520ad90fb 100644 --- a/tests/components/proc/control/test-dummy-commands.cpp +++ b/tests/components/proc/control/test-dummy-commands.cpp @@ -41,4 +41,10 @@ namespace test { } + + namespace command3 { + ulong check_; + } + + }} // namespace control::test diff --git a/tests/components/proc/control/test-dummy-commands.hpp b/tests/components/proc/control/test-dummy-commands.hpp index 230984498..142ac8cd8 100644 --- a/tests/components/proc/control/test-dummy-commands.hpp +++ b/tests/components/proc/control/test-dummy-commands.hpp @@ -24,10 +24,10 @@ /** @file test-dummy-commands.hpp ** Some dummy command functions used for building unit test cases. ** Any of these functions comes in triples of operation function, undo state - ** capturing function and und function. They are placed into a nested test + ** capturing function and UNDO function. They are placed into a nested test ** namespace, together with some global variables used as a backdoor to ** verify the effect of calling these functions. - ** + ** ** @see command-use1-test.cpp ** @see CommandBasic_test simple complete command definition example ** @@ -39,36 +39,9 @@ #define COMMAND_TEST_DUMMY_COMMANDS_H //#include "pre.hpp" -//#include "lib/test/run.hpp" #include "lib/error.hpp" #include "lib/test/test-helper.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/test-dummy-mobject.hpp" -//#include "lib/p.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/lumitime.hpp" -//#include "lib/util.hpp" - -//#include -//#include -//#include -//#include - -//using boost::format; - -//using lumiera::Time; -//using util::contains; -//using std::string; -//using std::rand; -//using std::cout; -//using std::endl; #include #include #include @@ -76,19 +49,19 @@ namespace control { namespace test { - -// using lib::test::showSizeof; + using std::ostringstream; using std::tr1::function; using std::string; - + namespace command1 { ///< test command just adding a given value extern long check_; - + + inline void operate (int someVal) { @@ -148,6 +121,35 @@ namespace test { } - + + + + + namespace command3 { ///< test command taking zero arguments + + extern ulong check_; + + + inline void + operate () + { + ++check_; + } + + inline ulong + capture () + { + return check_; + } + + inline void + undoIt (ulong oldVal) + { + check_ = oldVal; + } + + } + + }} // namespace control::test #endif