/* * Action_impl_header.hpp * * Created on: Aug 25, 2010 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Actions/ActionSequence.hpp" #include "Actions/ActionTraits.hpp" #include "Parameters/Parameter.hpp" // some derived names: if CATEGORY is not given, we don't prefix with it #ifdef CATEGORY #define ACTION BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, Action)) #define COMMAND BOOST_PP_CAT(CATEGORY, ACTIONNAME) #define PARAMS BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, Parameters)) #else #define ACTION BOOST_PP_CAT(ACTIONNAME, Action) #define COMMAND ACTIONNAME #define PARAMS BOOST_PP_CAT(ACTIONNAME, Parameters) #endif // check if no lists given #ifndef paramtypes #define MAXPARAMTYPES 0 #else #define MAXPARAMTYPES BOOST_PP_SEQ_SIZE(paramtypes) #endif #ifndef paramdefaults #define MAXPARAMDEFAULTS 0 // this is required for valid_print "else part" #define sequencer(z,n,data) \ BOOST_PP_SEQ_PUSH_BACK( data, NOPARAM_DEFAULT) #define paramdefaults BOOST_PP_REPEAT( MAXPARAMTYPES, sequencer, BOOST_PP_SEQ_NIL ) #else #define MAXPARAMDEFAULTS BOOST_PP_SEQ_SIZE(paramdefaults) #endif #define PARAM_DEFAULT(x) \ (x, BOOST_PP_NIL) // check user has given name and category #ifndef ACTIONNAME ERROR: No "ACTIONNAME" defined in: __FILE__ #endif // calculate numbers and check whether all have same size #ifdef paramtokens BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramtokens)),\ ERROR: There are not the same number of "paramtokens" and "paramtypes" in: __FILE__ \ ) #endif #ifdef paramreferences BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramreferences)),\ ERROR: There are not the same number of "paramtokens" and "paramreferences" in: __FILE__ \ ) #endif #ifdef paramdescriptions BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramdescriptions)),\ ERROR: There are not the same number of "paramtokens" and "paramdescriptions" in: __FILE__ \ ) #endif // check for mandatory defines #ifndef DESCRIPTION BOOST_PP_ASSERT_MSG(0, \ "ERROR: Description is mandatory for Actions, here for ACTION " \ ) #endif // check if paramdefaults is given, otherwise fill list with NOPARAM_DEFAULT // this does not work: paramdefaults has to be completely defined before // being used within option_print (used as an array there and not as // some function call still to be expanded) //#define paramdefaults (NOPARAM_DEFAULT) //#define tempvalue(z,n,value) // BOOST_PP_CAT(value,(NOPARAM_DEFAULT)) //BOOST_PP_REPEAT(tempvalue, MAXPARAMTYPES, paramdefaults) //#undef tempvalue //#else // if present, check if correct number of arguments #ifdef paramdefaults BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramdefaults)),\ ERROR: There are not the same number of "paramtokens" and "paramdefaults" in: __FILE__ \ ) #endif // print a list of type ref followed by a separator, i.e. "Parameter i;" #define type_print(z,n,TYPELIST, VARLIST, separator) \ Parameter < \ BOOST_PP_SEQ_ELEM(n, TYPELIST) \ > \ BOOST_PP_SEQ_ELEM(n, VARLIST) \ separator // print a list of type ref followed, i.e. "int i, double position" #define type_list(z,n,TYPELIST, VARLIST) \ BOOST_PP_COMMA_IF(n)\ BOOST_PP_SEQ_ELEM(n, TYPELIST) \ BOOST_PP_SEQ_ELEM(n, VARLIST) // prints Options.insert #define option_print(z,n,unused, unused2) \ tester = Options. insert (\ std::pair< std::string, OptionTrait *> ( \ BOOST_PP_SEQ_ELEM(n, paramtokens), \ new OptionTrait(\ BOOST_PP_SEQ_ELEM(n, paramtokens), \ &typeid( BOOST_PP_SEQ_ELEM(n, paramtypes) ), \ BOOST_PP_SEQ_ELEM(n, paramdescriptions) \ BOOST_PP_COMMA_IF( BOOST_PP_NOT( BOOST_PP_LIST_IS_NIL( BOOST_PP_SEQ_ELEM(n, paramdefaults) ) ) ) \ BOOST_PP_EXPR_IF( \ BOOST_PP_NOT( BOOST_PP_LIST_IS_NIL( BOOST_PP_SEQ_ELEM(n, paramdefaults) ) ), \ toString BOOST_PP_LPAREN() \ BOOST_PP_LIST_FIRST( BOOST_PP_SEQ_ELEM(n, paramdefaults) )) \ BOOST_PP_RPAREN() \ )\ )\ ); \ ASSERT(tester.second, "ActionTrait::ActionTrait() option token present twice!"); #define stringtype std::string #define type2string(s, data, elem) \ stringtype namespace MoleCuilder { void COMMAND( #if defined paramtypes && defined paramreferences #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, paramtypes, paramreferences) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ); void BOOST_PP_CAT( COMMAND, _stringargs)( #if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, BOOST_PP_SEQ_TRANSFORM( type2string, , paramtypes), paramreferences) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ); class ACTION; template <> class ActionTraits : public ActionTrait { public: ActionTraits() : #ifndef SHORTFORM ActionTrait(OptionTrait(TOKEN, &typeid(void), DESCRIPTION, std::string())) #else ActionTrait(OptionTrait(TOKEN, &typeid(void), DESCRIPTION, std::string(), SHORTFORM)) #endif /* SHORTFORM */ { // initialize remainder of action info #ifdef MENUNAME MenuTitle = MENUNAME; #endif #ifdef MENUPOSITION MenuPosition = MENUPOSITION; #endif // initialize action's options std::pair< ActionTrait::options_iterator, bool > tester; #ifdef paramtokens #define BOOST_PP_LOCAL_MACRO(n) option_print(~, n, ~, ) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif // associate action's short form also with option #ifdef SHORTFORM if (Options.find(TOKEN) != Options.end()) Options[TOKEN]->setShortForm(std::string(SHORTFORM)); #endif /* SHORTFORM */ //std::cout << "ActionTraits<" << BOOST_PP_STRINGIZE(ACTION) << ">::ActionTraits() on instance " << this << " with " << getName() << ", type " << getTypeName() << " and description " << getDescription() << std::endl; } virtual ~ActionTraits() { //std::cout << "ActionTraits<" << BOOST_PP_STRINGIZE(ACTION) << ">::~ActionTraits() on instance " << this << " with name " << getName() << " called." << std::endl; } }; class ACTION : public MakroAction { friend void COMMAND( #if defined paramtypes && defined paramreferences #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, paramtypes, paramreferences) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ); friend void BOOST_PP_CAT( COMMAND, _stringargs)( #if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, BOOST_PP_SEQ_TRANSFORM( type2string, , paramtypes), paramreferences) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ); public: ACTION(); virtual ~ACTION(); // must be called after all primitive actions are present void prepare(ActionRegistry &AR); // must be called before alle primitive actions are removed void unprepare(ActionRegistry &AR); bool canUndo(); bool shouldUndo(); virtual Action* clone(enum QueryOptions flag = Interactive) const; void outputAsCLI(std::ostream &ost) const; void outputAsPython(std::ostream &ost, const std::string &prefix) const; struct PARAMS : ActionParameters { //!> constructor for class PARAMS, setting valid ranges PARAMS(); //!> copy constructor for class PARAMS, setting valid ranges PARAMS(const PARAMS &p); #if defined paramtypes && defined paramreferences #define BOOST_PP_LOCAL_MACRO(n) type_print(~, n, paramtypes, paramreferences, ;) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif } params; protected: virtual Dialog * fillOwnDialog(Dialog*); void startTimer() const; void endTimer() const; private: //!> flag to check whether actions have been prepared static bool isPrepared; //!> sequence of prototype actions for this macro action static ActionSequence prototype_actions; //!> sequence of actions for this specific instance ActionSequence actions; private: virtual ActionState::ptr performCall(); virtual ActionState::ptr performUndo(ActionState::ptr); virtual ActionState::ptr performRedo(ActionState::ptr); }; } #undef paramvalids #undef paramtypes #undef paramtokens #undef paramreferences #undef paramdescriptions #undef paramdefaults #undef MAXPARAMTYPES #undef MAXPARAMDEFAULTS #undef statetypes #undef statereferences #undef MAXSTATETYPES #undef PARAM_DEFAULT #undef option_print #undef sequencer #undef type_print #undef type_list #undef ACTION #undef COMMAND #undef COMMANDFULL #undef PARAMS #undef ACTIONNAME #undef CATEGORY #undef MENUNAME #undef MENUPOSITION #undef TOKEN #undef DESCRIPTION #undef SHORTFORM