/* * Action.hpp * * Created on: Dec 8, 2009 * Author: crueger */ #ifndef ACTION_HPP_ #define ACTION_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include /** Used in .def files in paramdefaults define to set that no default value exists. * We define NODEFAULT here, as it is used in .def files and needs to be present * before these are included. */ #define NODEFAULT "" // forward declaration namespace MoleCuilder { class ActionState; class ActionSequence; } class Dialog; #include "Actions/ActionTrait.hpp" namespace MoleCuilder { /** * Base class for all actions. * * Actions describe something that has to be done. * Actions can be passed around, stored, performed and undone (Command-Pattern). */ class Action { friend class ActionSequence; friend class ActionHistory; public: enum QueryOptions {Interactive, NonInteractive}; /** * This type is used to store pointers to ActionStates while allowing multiple ownership */ typedef boost::shared_ptr state_ptr; /** * Standard constructor of Action Base class * * All Actions need to have a name. The second flag indicates, whether the action should * be registered with the ActionRegistry. If the Action is registered the name of the * Action needs to be unique for all Actions that are registered. * * \note NO reference for \a _Traits as we do have to copy it, otherwise _Traits would have * to be present throughout the program's run. * * \param Traits information class to this action * \param _doRegister whether to register with ActionRegistry */ Action(const ActionTrait &_Traits, bool _doRegister=true); virtual ~Action(); /** * This method is used to call an action. The basic operations for the Action * are carried out and if necessary/possible the Action is added to the History * to allow for undo of this action. * * If the call needs to undone you have to use the History, to avoid destroying * invariants used by the History. * * Note that this call can be Interactive (i.e. a dialog will ask the user for * necessary information) and NonInteractive (i.e. the information will have to * be present already within the ValueStorage class or else a MissingArgumentException * is thrown) */ void call(enum QueryOptions state = Interactive); /** * This method provides a flag that indicates if an undo mechanism is implemented * for this Action. If this is true, and this action was called last, you can * use the History to undo this action. */ virtual bool canUndo()=0; /** * This method provides a flag, that indicates if the Action changes the state of * the application in a way that needs to be undone for the History to work. * * If this is false the Action will not be added to the History upon calling. However * Actions called before this one will still be available for undo. */ virtual bool shouldUndo()=0; /** * Indicates whether the Action can do it's work at the moment. If this * is false calling the action will result in a no-op. */ virtual bool isActive(); /** * Returns the name of the Action. */ const std::string getName() const; /** * returns a detailed help message. */ const std::string help() const; /** * Traits resemble all necessary information that "surrounds" an action, such as * its name (for ActionRegistry and as ref from string to instance and vice versa), * which menu, which position, what parameters, their types, if it is itself a * parameter and so on ... * * Note that is important that we do not use a reference here. We want to copy the * information in the Action's constructor and have it contained herein. Hence, we * also have our own copy constructor for ActionTrait. Information should be * encapsulated in the Action, no more references to the outside than absolutely * necessary. */ const ActionTrait Traits; protected: /** Removes the static entities Action::success and Action::failure. * This is only to be called on the program's exit, i.e. in cleanUp(), * as these static entities are used throughout all Actions. */ static void removeStaticStateEntities(); /** Creates the static entities Action::success and Action::failure. * This is only to be called by ActionHistory. */ static void createStaticStateEntities(); /** * This method is called by the History, when an undo is performed. It is * provided with the corresponding state produced by the performCall or * performRedo method and needs to provide a state that can be used for redo. */ state_ptr undo(state_ptr); /** * This method is called by the Histor, when a redo is performed. It is * provided with the corresponding state produced by the undo method and * needs to produce a State that can then be used for another undo. */ state_ptr redo(state_ptr); /** * This special state can be used to indicate that the Action was successfull * without providing a special state. Use this if your Action does not need * a speciallized state. */ static state_ptr success; /** * This special state can be returned, to indicate that the action could not do it's * work, was abborted by the user etc. If you return this state make sure to transactionize * your Actions and unroll the complete transaction before this is returned. */ static state_ptr failure; /** * This creates the dialog requesting the information needed for this action from the user * via means of the user interface. */ Dialog * createDialog(); /** Virtual function that starts the timer. * */ virtual void startTimer() const {}; /** Virtual function that ends the timer. * */ virtual void endTimer() const {}; private: /** * This is called internally before the Action::performCall(). It initializes the * necessary ActionParameters by retrieving the values from ValueStorage. */ virtual void getParametersfromValueStorage()=0; /** * This is called internally before the action is processed. This adds necessary queries * to a given dialog to obtain parameters for the user for processing the action accordingly. * The dialog will be given to the user before Action::performCall() is initiated, values * are transfered via ValueStorage. */ virtual Dialog * fillDialog(Dialog*)=0; /** * This is called internally when the call is being done. Implement this method to do the actual * work of the Action. Implement this in your Derived classes. Needs to return a state that can be * used to undo the action. */ virtual state_ptr performCall()=0; /** * This is called internally when the undo process is chosen. This Method should use the state * produced by the performCall method to return the state of the application to the state * it had before the Action. */ virtual state_ptr performUndo(state_ptr)=0; /** * This is called internally when the redo process is chosen. This method shoudl use the state * produced by the performUndo method to return the application to the state it should have after * the action. * * Often this method can be implement to re-use the performCall method. However if user interaction * or further parameters are needed, those should be taken from the state and not query the user * again. */ virtual state_ptr performRedo(state_ptr)=0; }; /** * This class can be used by actions to save the state. * * It is implementing a memento pattern. The base class is completely empty, * since no general state internals can be given. The Action performing * the Undo should downcast to the apropriate type. */ class ActionState{ public: ActionState(){} virtual ~ActionState(){} }; /** * This class can be used by actions to contain parameters. * * The base class is completely empty, since no general parameters can be given. The * Action performing the function should construct its own parameter class derived * from it. */ class ActionParameters{ public: ActionParameters(){} virtual ~ActionParameters(){} }; } #endif /* ACTION_HPP_ */