![]() |
Main Page Class Hierarchy Alphabetical List Compound List File List Compound Members
|
00001 /******************************************************************************** 00002 * * 00003 * U n d o / R e d o - a b l e C o m m a n d * 00004 * * 00005 ********************************************************************************* 00006 * Copyright (C) 2000,2010 by Jeroen van der Zijp. All Rights Reserved. * 00007 ********************************************************************************* 00008 * This library is free software; you can redistribute it and/or modify * 00009 * it under the terms of the GNU Lesser General Public License as published by * 00010 * the Free Software Foundation; either version 3 of the License, or * 00011 * (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00016 * GNU Lesser General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU Lesser General Public License * 00019 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00020 ********************************************************************************/ 00021 #ifndef FXUNDOLIST_H 00022 #define FXUNDOLIST_H 00023 00024 #ifndef FXOBJECT_H 00025 #include "FXObject.h" 00026 #endif 00027 00028 namespace FX { 00029 00030 00031 class FXUndoList; 00032 class FXCommandGroup; 00033 00034 00035 /** 00036 * Base class for undoable commands. Each undo records all the 00037 * information necessary to undo as well as redo a given operation. 00038 * Since commands are derived from FXObject, subclassed commands can 00039 * both send and receive messages (like ID_GETINTVALUE, for example). 00040 */ 00041 class FXAPI FXCommand : public FXObject { 00042 FXDECLARE_ABSTRACT(FXCommand) 00043 friend class FXUndoList; 00044 friend class FXCommandGroup; 00045 private: 00046 FXCommand *next; 00047 private: 00048 FXCommand(const FXCommand&); 00049 FXCommand &operator=(const FXCommand&); 00050 protected: 00051 FXCommand():next(NULL){} 00052 public: 00053 00054 /** 00055 * Undo this command; this should save the 00056 * information for a subsequent redo. 00057 */ 00058 virtual void undo() = 0; 00059 00060 /** 00061 * Redo this command; this should save the 00062 * information for a subsequent undo. 00063 */ 00064 virtual void redo() = 0; 00065 00066 /** 00067 * Return the size of the information in the undo record. 00068 * The undo list may be trimmed to limit memory usage to 00069 * a certain limit. The value returned should include 00070 * the size of the command record itself as well as any 00071 * data linked from it. 00072 */ 00073 virtual FXuint size() const; 00074 00075 /** 00076 * Name of the undo command to be shown on a button; 00077 * for example, "Undo Delete". 00078 */ 00079 virtual FXString undoName() const; 00080 00081 /** 00082 * Name of the redo command to be shown on a button; 00083 * for example, "Redo Delete". 00084 */ 00085 virtual FXString redoName() const; 00086 00087 /** 00088 * Return true if this command can be merged with previous undo 00089 * commands. This is useful to combine e.g. multiple consecutive 00090 * single-character text changes into a single block change. 00091 * The default implementation returns false. 00092 */ 00093 virtual FXbool canMerge() const; 00094 00095 /** 00096 * Called by the undo system to try and merge the new incoming command 00097 * with this command; should return true if merging was possible. 00098 * The default implementation returns false. 00099 */ 00100 virtual FXbool mergeWith(FXCommand* command); 00101 00102 /// Delete undo command 00103 virtual ~FXCommand(){} 00104 }; 00105 00106 00107 00108 /** 00109 * Group of undoable commands. A group may comprise multiple 00110 * individual actions which together undo (or redo) a larger 00111 * operation. Even larger operations may be built by nesting 00112 * multiple undo groups. 00113 */ 00114 class FXAPI FXCommandGroup : public FXCommand { 00115 FXDECLARE(FXCommandGroup) 00116 friend class FXUndoList; 00117 private: 00118 FXCommand *undolist; 00119 FXCommand *redolist; 00120 FXCommandGroup *group; 00121 private: 00122 FXCommandGroup(const FXCommandGroup&); 00123 FXCommandGroup &operator=(const FXCommandGroup&); 00124 public: 00125 00126 /// Construct initially empty undo command group 00127 FXCommandGroup():undolist(NULL),redolist(NULL),group(NULL){} 00128 00129 /// Return true if empty 00130 FXbool empty(){ return !undolist; } 00131 00132 /// Undo whole command group 00133 virtual void undo(); 00134 00135 /// Redo whole command group 00136 virtual void redo(); 00137 00138 /// Return the size of the command group 00139 virtual FXuint size() const; 00140 00141 /// Delete undo command and sub-commands 00142 virtual ~FXCommandGroup(); 00143 }; 00144 00145 00146 00147 /** 00148 * The Undo List class manages a list of undoable commands. 00149 */ 00150 class FXAPI FXUndoList : public FXCommandGroup { 00151 FXDECLARE(FXUndoList) 00152 private: 00153 FXint undocount; // Number of undo records 00154 FXint redocount; // Number of redo records 00155 FXint marker; // Marker value 00156 FXuint space; // Space taken up by all the undo records 00157 FXbool working; // Currently busy with undo or redo 00158 private: 00159 FXUndoList(const FXUndoList&); 00160 FXUndoList &operator=(const FXUndoList&); 00161 public: 00162 long onCmdUndo(FXObject*,FXSelector,void*); 00163 long onUpdUndo(FXObject*,FXSelector,void*); 00164 long onCmdRedo(FXObject*,FXSelector,void*); 00165 long onUpdRedo(FXObject*,FXSelector,void*); 00166 long onCmdClear(FXObject*,FXSelector,void*); 00167 long onUpdClear(FXObject*,FXSelector,void*); 00168 long onCmdRevert(FXObject*,FXSelector,void*); 00169 long onUpdRevert(FXObject*,FXSelector,void*); 00170 long onCmdUndoAll(FXObject*,FXSelector,void*); 00171 long onCmdRedoAll(FXObject*,FXSelector,void*); 00172 long onUpdUndoCount(FXObject*,FXSelector,void*); 00173 long onUpdRedoCount(FXObject*,FXSelector,void*); 00174 public: 00175 enum{ 00176 ID_CLEAR=FXWindow::ID_LAST, 00177 ID_REVERT, 00178 ID_UNDO, 00179 ID_REDO, 00180 ID_UNDO_ALL, 00181 ID_REDO_ALL, 00182 ID_UNDO_COUNT, 00183 ID_REDO_COUNT, 00184 ID_LAST 00185 }; 00186 public: 00187 00188 /** 00189 * Make new empty undo list, initially unmarked. 00190 */ 00191 FXUndoList(); 00192 00193 /** 00194 * Cut the redo list. 00195 * This is automatically invoked when a new undo command is added. 00196 */ 00197 void cut(); 00198 00199 /** 00200 * Add new command, executing it if desired. The new command will be merged 00201 * with the previous command if merge is true and we're not at a marked position 00202 * and the commands are mergeable. Otherwise the new command will be appended 00203 * after the last undo command in the currently active undo group. 00204 * If the new command is successfully merged, it will be deleted. Furthermore, 00205 * all redo commands will be deleted since it is no longer possible to redo 00206 * from this point. 00207 */ 00208 void add(FXCommand* command,FXbool doit=false,FXbool merge=true); 00209 00210 /** 00211 * Begin undo command sub-group. This begins a new group of commands that 00212 * are treated as a single command. Must eventually be followed by a 00213 * matching end() after recording the sub-commands. The new sub-group 00214 * will be appended to its parent group's undo list when end() is called. 00215 */ 00216 void begin(FXCommandGroup *command); 00217 00218 /** 00219 * End undo command sub-group. If the sub-group is still empty, it will 00220 * be deleted; otherwise, the sub-group will be added as a new command 00221 * into parent group. 00222 * A matching begin() must have been called previously. 00223 */ 00224 void end(); 00225 00226 /** 00227 * Abort the current command sub-group being compiled. All commands 00228 * already added to the sub-groups undo list will be discarded. 00229 * Intermediate command groups will be left intact. 00230 */ 00231 void abort(); 00232 00233 /** 00234 * Undo last command. This will move the command to the redo list. 00235 */ 00236 virtual void undo(); 00237 00238 /** 00239 * Redo next command. This will move the command back to the undo list. 00240 */ 00241 virtual void redo(); 00242 00243 /// Undo all commands 00244 void undoAll(); 00245 00246 /// Redo all commands 00247 void redoAll(); 00248 00249 /// Revert to marked 00250 void revert(); 00251 00252 /// Can we undo more commands 00253 FXbool canUndo() const; 00254 00255 /// Can we redo more commands 00256 FXbool canRedo() const; 00257 00258 /// Can revert to marked 00259 FXbool canRevert() const; 00260 00261 /** 00262 * Return true if currently inside undo or redo operation; this 00263 * is useful to avoid generating another undo command while inside 00264 * an undo operation. 00265 */ 00266 FXbool busy() const { return working; } 00267 00268 /// Current top level undo command 00269 FXCommand* current() const { return undolist; } 00270 00271 /** 00272 * Return name of the first undo command available; if no 00273 * undo command available this will return the empty string. 00274 */ 00275 virtual FXString undoName() const; 00276 00277 /** 00278 * Return name of the first redo command available; if no 00279 * Redo command available this will return the empty string. 00280 */ 00281 virtual FXString redoName() const; 00282 00283 /// Number of undo records 00284 FXint undoCount() const { return undocount; } 00285 00286 /// Number of redo records 00287 FXint redoCount() const { return redocount; } 00288 00289 /// Size of undo information 00290 virtual FXuint size() const; 00291 00292 /** 00293 * Clear list, and unmark all states. 00294 * All undo and redo information will be destroyed. 00295 */ 00296 void clear(); 00297 00298 /** 00299 * Trim undo list down to at most nc commands. 00300 * Call this periodically to prevent the undo-list from growing 00301 * beyond a certain number of records. 00302 */ 00303 void trimCount(FXint nc); 00304 00305 /** 00306 * Trim undo list down to at most size sz. 00307 * Call this periodically to prevent the undo-list from growing 00308 * beyond a certain amount of memory. 00309 */ 00310 void trimSize(FXuint sz); 00311 00312 /** 00313 * Mark the current state of the undo list, which is initially unmarked. 00314 * There can be only one active mark at any time. Call mark() at any 00315 * time when you know the document to be "clean"; for example when you 00316 * save the document to disk. 00317 */ 00318 void mark(); 00319 00320 /** 00321 * Unmark all states in the undo list. 00322 */ 00323 void unmark(); 00324 00325 /** 00326 * Check if the current state was marked, if the application has returned 00327 * to the previously marked state. 00328 */ 00329 FXbool marked() const; 00330 }; 00331 00332 00333 } 00334 00335 #endif
|
|