Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members

FXUndoList.h

Go to the documentation of this file.
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

Copyright © 1997-2010 Jeroen van der Zijp