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

Copyright © 1997-2005 Jeroen van der Zijp