undo.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _UNDO_H_
  23. #define _UNDO_H_
  24. #ifndef _SIMOBJECT_H_
  25. #include "console/simObject.h"
  26. #endif
  27. #ifndef _TVECTOR_H_
  28. #include "core/util/tVector.h"
  29. #endif
  30. #ifndef _SIMBASE_H_
  31. #include "console/simBase.h"
  32. #endif
  33. #ifndef _ENGINEAPI_H_
  34. #include "console/engineAPI.h"
  35. #endif
  36. class UndoManager;
  37. ///
  38. class UndoAction : public SimObject
  39. {
  40. friend class UndoManager;
  41. protected:
  42. // The manager this was added to.
  43. UndoManager* mUndoManager;
  44. public:
  45. /// A brief description of the action, for display in menus and the like.
  46. // not private because we're exposing it to the console.
  47. String mActionName;
  48. // Required in all ConsoleObject subclasses.
  49. typedef SimObject Parent;
  50. DECLARE_CONOBJECT(UndoAction);
  51. static void initPersistFields();
  52. /// Create a new action, assigning it a name for display in menus et cetera.
  53. UndoAction(const UTF8 *actionName = " ");
  54. virtual ~UndoAction();
  55. /// Implement these methods to perform your specific undo & redo tasks.
  56. virtual void undo() { };
  57. virtual void redo() { };
  58. /// Adds the action to the undo stack of the default UndoManager, or the provided manager.
  59. void addToManager(UndoManager* theMan = NULL);
  60. };
  61. /// An undo action that is comprised of other undo actions.
  62. class CompoundUndoAction : public UndoAction
  63. {
  64. friend class UndoManager;
  65. protected:
  66. Vector< UndoAction* > mChildren;
  67. public:
  68. typedef UndoAction Parent;
  69. CompoundUndoAction( const UTF8 *actionName = " " );
  70. virtual ~CompoundUndoAction();
  71. DECLARE_CONOBJECT(CompoundUndoAction);
  72. virtual void addAction( UndoAction *action );
  73. virtual void undo();
  74. virtual void redo();
  75. virtual void onDeleteNotify( SimObject* object );
  76. U32 getNumChildren() const { return mChildren.size(); }
  77. };
  78. ///
  79. class UndoManager : public SimObject
  80. {
  81. private:
  82. /// Default number of undo & redo levels.
  83. const static U32 kDefaultNumLevels = 100;
  84. /// The stacks of undo & redo actions. They will be capped at size mNumLevels.
  85. Vector<UndoAction*> mUndoStack;
  86. Vector<UndoAction*> mRedoStack;
  87. /// Stack for assembling compound actions.
  88. Vector< CompoundUndoAction* > mCompoundStack;
  89. /// Deletes all the UndoActions in a stack, then clears it.
  90. void clearStack(Vector<UndoAction*> &stack);
  91. /// Clamps a Vector to mNumLevels entries.
  92. void clampStack(Vector<UndoAction*> &stack);
  93. /// Run the removal logic on the action.
  94. void doRemove( UndoAction* action, bool noDelete );
  95. public:
  96. /// Number of undo & redo levels.
  97. // not private because we're exposing it to the console.
  98. U32 mNumLevels;
  99. // Required in all ConsoleObject subclasses.
  100. typedef SimObject Parent;
  101. DECLARE_CONOBJECT(UndoManager);
  102. static void initPersistFields();
  103. /// Constructor. If levels = 0, we use the default number of undo levels.
  104. UndoManager(U32 levels = kDefaultNumLevels);
  105. /// Destructor. deletes and clears the undo & redo stacks.
  106. ~UndoManager();
  107. /// Accessor to the default undo manager singleton. Creates one if needed.
  108. static UndoManager& getDefaultManager();
  109. /// Undo last action, and put it on the redo stack.
  110. void undo();
  111. /// Redo the last action, and put it on the undo stack.
  112. void redo();
  113. /// Clears the undo and redo stacks.
  114. void clearAll();
  115. /// Returns the printable name of the top actions on the undo & redo stacks.
  116. const char* getNextUndoName();
  117. const char* getNextRedoName();
  118. S32 getUndoCount();
  119. S32 getRedoCount();
  120. const char* getUndoName(S32 index);
  121. const char* getRedoName(S32 index);
  122. UndoAction* getUndoAction(S32 index);
  123. UndoAction* getRedoAction(S32 index);
  124. /// Add an action to the top of the undo stack, and clear the redo stack.
  125. void addAction(UndoAction* action);
  126. void removeAction(UndoAction* action, bool noDelete = false);
  127. /// @name Compound Actions
  128. ///
  129. /// The compound action stack allows to redirect undos to a CompoundUndoAction
  130. /// and thus assemble multi-operation undos directly through the UndoManager.
  131. /// When the bottom-most CompoundUndoAction is popped off the stack, the compound
  132. /// will be moved onto the undo stack.
  133. ///
  134. /// @{
  135. /// Push a compound action called "name" onto the compound stack. While the
  136. /// compound stack is not empty, all undos that are queued on the undo manager will
  137. /// go to the topmost compound instead of the undo stack.
  138. CompoundUndoAction* pushCompound( const String& name );
  139. /// Pop the topmost compound off the compound stack and add it to the undo manager.
  140. /// If the compound stack is still not empty, the compound will be added to the next
  141. /// lower compound on the stack. Otherwise it will be recorded as a regular undo.
  142. void popCompound( bool discard = false );
  143. /// Return the current nesting depth of the compound stack.
  144. U32 getCompoundStackDepth() const { return mCompoundStack.size(); }
  145. /// @}
  146. };
  147. /// Script Undo Action Creation
  148. ///
  149. /// Undo actions can be created in script like this:
  150. ///
  151. /// ...
  152. /// %undo = new UndoScriptAction() { class = SampleUndo; actionName = "Sample Undo"; };
  153. /// %undo.addToManager(UndoManager);
  154. /// ...
  155. ///
  156. /// function SampleUndo::undo()
  157. /// {
  158. /// ...
  159. /// }
  160. ///
  161. /// function SampleUndo::redo()
  162. /// {
  163. /// ...
  164. /// }
  165. ///
  166. class UndoScriptAction : public UndoAction
  167. {
  168. public:
  169. typedef UndoAction Parent;
  170. UndoScriptAction() : UndoAction()
  171. {
  172. }
  173. virtual void undo() { Con::executef(this, "undo"); };
  174. virtual void redo() { Con::executef(this, "redo"); }
  175. virtual bool onAdd()
  176. {
  177. // Let Parent Do Work.
  178. if(!Parent::onAdd())
  179. return false;
  180. // Notify Script.
  181. if(isMethod("onAdd"))
  182. Con::executef(this, "onAdd");
  183. // Return Success.
  184. return true;
  185. };
  186. virtual void onRemove()
  187. {
  188. if (mUndoManager)
  189. mUndoManager->removeAction((UndoAction*)this, true);
  190. // notify script
  191. if(isMethod("onRemove"))
  192. Con::executef(this, "onRemove");
  193. Parent::onRemove();
  194. }
  195. DECLARE_CONOBJECT(UndoScriptAction);
  196. };
  197. #endif // _UNDO_H_