Index: awt/src/org/openide/awt/UndoRedo.java =================================================================== RCS file: /cvs/openide/awt/src/org/openide/awt/UndoRedo.java,v retrieving revision 1.5 diff -u -r1.5 UndoRedo.java --- awt/src/org/openide/awt/UndoRedo.java 27 Mar 2007 01:26:06 -0000 1.5 +++ awt/src/org/openide/awt/UndoRedo.java 8 May 2007 07:31:59 -0000 @@ -93,7 +93,7 @@ /** An undo manager which fires a change event each time it consumes a new undoable edit. */ - public static class Manager extends UndoManager implements UndoRedo { + public static class Manager extends UndoGroupManager implements UndoRedo { static final long serialVersionUID = 6721367974521509720L; private final ChangeSupport cs = new ChangeSupport(this); @@ -251,5 +251,184 @@ public String getRedoPresentationName() { return ""; // NOI18N } + } + + /** UndoGroupManager is an UndoManager + * that allows explicit control of how + * UndoableEdits are coalesced into compound edits, + * rather than using the rules defined by the edits themselves. + * Other than the default usage, special handling is initiated by doing + * beginUndoGroup(). + *

+ * Three use cases are supported. + *

+ *
    + *
  1. Default behavior is defined by {@link javax.swing.undo.UndoManager}.
  2. + *
  3. UnddoableEdits issued between beginUndoGroup() + * and endUndoGroup() are placed into a single CompoundEdit. + * Thus undo() and redo() treat them atomically.
  4. + *
  5. Use commitUndoGroup() to place any accumulated + * UndoableEdits into a CompoundEdit; + * the application does this at strategic points, such as EndOfLine + * entry or cursor movement.
  6. + *
+ * Note that certain methods, such as undo(), automatically issue + * commitUndoGroup(). + */ + public static class UndoGroupManager extends UndoManager { + /** signals that edits should be accumulated */ + boolean buildUndoGroup; + /** accumulate edits here in undoGroup */ + CompoundEdit undoGroup; + + public synchronized void beginUndoGroup() { + commitUndoGroup(); + buildUndoGroup = true; + } + + public synchronized void endUndoGroup() { + buildUndoGroup = false; + commitUndoGroup(); + } + + public synchronized void commitUndoGroup() { + if(undoGroup == null) { + return; + } + // super.addEdit may end up in this.addEdit, + // so buildUndoGroup must be false + boolean saveInUndoGroup = buildUndoGroup; + buildUndoGroup = false; + + undoGroup.end(); + super.addEdit(undoGroup); + + undoGroup = null; + buildUndoGroup = saveInUndoGroup; + } + + + public synchronized boolean addEdit(UndoableEdit anEdit) { + if(!isInProgress()) + return false; + if(buildUndoGroup) { + if(undoGroup == null) + undoGroup = new CompoundEdit(); + return undoGroup.addEdit(anEdit); + } else { + return super.addEdit(anEdit); + } + } + + public synchronized void discardAllEdits() { + commitUndoGroup(); + super.discardAllEdits(); + } + + // + // TODO: limits + // + + public synchronized void undoOrRedo() { + commitUndoGroup(); + super.undoOrRedo(); + } + + public synchronized boolean canUndoOrRedo() { + if(undoGroup != null) + return true; + return super.canUndoOrRedo(); + } + + public synchronized void undo() { + commitUndoGroup(); + super.undo(); + } + + public synchronized boolean canUndo() { + if(undoGroup != null) + return true; + return super.canUndo(); + } + + public synchronized void redo() { + if(undoGroup != null) + throw new CannotRedoException(); + super.redo(); + } + + public synchronized boolean canRedo() { + if(undoGroup != null) + return false; + return super.canRedo(); + } + + public synchronized void end() { + commitUndoGroup(); + super.end(); + } + + public synchronized String getUndoOrRedoPresentationName() { + if(undoGroup != null) + return undoGroup.getUndoPresentationName(); + return super.getUndoOrRedoPresentationName(); + } + + public synchronized String getUndoPresentationName() { + if(undoGroup != null) + return undoGroup.getUndoPresentationName(); + return super.getUndoPresentationName(); + } + + public synchronized String getRedoPresentationName() { + if(undoGroup != null) + return undoGroup.getRedoPresentationName(); + return super.getRedoPresentationName(); + } + + public boolean isSignificant() { + if(undoGroup != null && undoGroup.isSignificant()) { + return true; + } + return super.isSignificant(); + } + + public synchronized void die() { + commitUndoGroup(); + super.die(); + } + + public String getPresentationName() { + if(undoGroup != null) + return undoGroup.getPresentationName(); + return super.getPresentationName(); + } + + /* since these protected methods are only accessed from + * synchronized methods that commitUndoGroup, + * they do not need to be in this class + protected UndoableEdit editToBeUndone() { + if(undoGroup != null) + return null; + return super.editToBeUndone(); + } + + protected UndoableEdit editToBeRedone() { + if(undoGroup != null) + return null; + return super.editToBeRedone(); + } + + protected void undoTo(UndoableEdit edit) { + if(undoGroup != null) + throw new CannotUndoException(); + super.undoTo(edit); + } + + protected void redoTo(UndoableEdit edit) { + if(undoGroup != null) + throw new CannotRedoException(); + super.redoTo(edit); + }*/ } }