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