/* * Action_impl.hpp * * Created on: Aug 25, 2010 * Author: heber */ /** These macros define the following functions, necessary but repetitive for * every Action: * -# Dialog* fillDialog() * -# action command (e.g. AnalysisMolecularVolume() ) * -# void getParametersfromValuStorage() * -# struct Action...Parameters * * For this, the user has the define the following values, each with * parenthesis, for the values/parameters the action needs * -# paramtypes, e.g. (int)(double) * -# paramtokens, e.g. ("Z")("length") * -# paramreferences, e.g. (Z)(length) * and for additional values/parameters to save in the state * -# statetypes, e.g. (int)(double) * -# statereferences, e.g. (Z)(length) * and the name and category of the action * -# CATEGORY, e.g. Analysis * -# ACTIONNAME, e.g. MolecularVolume */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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 STATE BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, State)) #define PARAMS BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, Parameters)) #else #define ACTION BOOST_PP_CAT(ACTIONNAME, Action) #define COMMAND ACTIONNAME #define STATE BOOST_PP_CAT(ACTIONNAME, State) #define PARAMS BOOST_PP_CAT(ACTIONNAME, Parameters) #endif #define INSTANCE BOOST_PP_CAT(this_, BOOST_PP_CAT(ACTIONNAME, _instance)) // check if no lists given #ifndef paramtypes #define MAXPARAMTYPES 0 #else #define MAXPARAMTYPES BOOST_PP_SEQ_SIZE(paramtypes) #endif #ifndef statetypes #define MAXSTATETYPES 0 #else #define MAXSTATETYPES BOOST_PP_SEQ_SIZE(statetypes) #endif // 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 statetypes BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXSTATETYPES, BOOST_PP_SEQ_SIZE(statereferences)),\ ERROR: There are not the same number of "statetypes" and "statereferences" in: __FILE__ \ ) #endif // print a list of type ref followed by a separator, i.e. "int i;" #define initialiser_print(z,n,initialiserlist) \ BOOST_PP_SEQ_ELEM(n, initialiserlist) \ (BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(n, initialiserlist))), // print a list of ref(_ref) followed by a separator, i.e. "id(_id)," #define type_print(z,n,TYPELIST, VARLIST, separator) \ 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 dialog->query calls for paramtypes with tokens #define dialog_print(z,n,unused) \ dialog->query<\ BOOST_PP_SEQ_ELEM(n, paramtypes)\ >(\ BOOST_PP_SEQ_ELEM(n, paramtokens)\ , Traits.getDescription()\ ); // prints set/queryCurrentValue (command) for paramreferences and paramtokens #define value_print(z,n,command, prefix) \ ValueStorage::getInstance(). command (\ BOOST_PP_SEQ_ELEM(n, paramtokens)\ , \ prefix\ BOOST_PP_SEQ_ELEM(n, paramreferences)\ ); #include "Actions/ActionRegistry.hpp" #include "UIElements/Dialog.hpp" #ifdef paramtokens #define statenecessary 1 #endif #ifndef statetokens #define statenecessary 1 #endif // =========== memento to remember the state when undoing =========== #ifdef statenecessary class STATE : public ActionState { public: STATE( #if defined statetypes && defined statereferences // if we have parameters, we have to add "_" before each reference and add the params as the last one #define OP(s,data,elem) BOOST_PP_CAT(data, elem) // OP to add "_" #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, BOOST_PP_SEQ_PUSH_BACK(statetypes, const ACTION::PARAMS &), BOOST_PP_SEQ_TRANSFORM(OP, _, BOOST_PP_SEQ_PUSH_BACK(statereferences, params))) #else /// if not, params is only list #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, (const ACTION::PARAMS &), (_params)) #endif #define BOOST_PP_LOCAL_LIMITS (0, MAXSTATETYPES) #include BOOST_PP_LOCAL_ITERATE() ) : #if defined statetypes && defined statereferences // do we have parameters at all? BOOST_PP_REPEAT(MAXSTATETYPES, initialiser_print, statereferences) #endif params(_params) {} #if defined statetypes && defined statereferences // do we have parameters at all? #define BOOST_PP_LOCAL_MACRO(n) type_print(~, n, statetypes, statereferences, ;) #define BOOST_PP_LOCAL_LIMITS (0, MAXSTATETYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ACTION::PARAMS params; }; #endif /* statenecessary */ // (const) prototype to be placed into the ActionRegistry (must be deleted by registry itself) const ACTION *INSTANCE = new ACTION(); // =========== constructor =========== ACTION::ACTION () : Action(ActionTrait()) {} // =========== destructor =========== ACTION::~ACTION () { //std::cout << "Action ACTION is being destroyed." << std::endl; } // =========== fill a dialog =========== Dialog* ACTION::fillDialog(Dialog *dialog) { ASSERT(dialog,"No Dialog given when filling actionname's dialog"); #if BOOST_PP_EQUAL(MAXPARAMTYPES,0) dialog->queryEmpty(TOKEN, Traits.getDescription()); #else #define BOOST_PP_LOCAL_MACRO(n) dialog_print(~, n, ~) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif return dialog; }; // =========== command for calling action directly =========== #if defined paramtypes && defined paramreferences void COMMAND( #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, paramtypes, paramreferences) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() ) #else void COMMAND() #endif { ACTION::PARAMS params; Action *ToCall = ActionRegistry::getInstance().getActionByName( TOKEN ); //->clone(params); #if BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) value_print(~, n, setCurrentValue, ) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ToCall->call(Action::NonInteractive); }; // =========== obtain parameters from Storage, used by performCall() =========== void ACTION::getParametersfromValueStorage() { #if BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) value_print(~, n, queryCurrentValue, params.) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif }; // free up defines #undef paramtypes #undef paramtokens #undef paramreferences #undef MAXPARAMTYPES #undef statetypes #undef statereferences #undef MAXSTATETYPES #undef ACTION #undef COMMAND #undef PARAMS #undef STATE #undef INSTANCE #undef ACTIONNAME #undef CATEGORY #undef TOKEN