Book Home Java Enterprise in a Nutshell Search this book

Chapter 35. The javax.swing.undo Package

The classes and interfaces in this package form the undo framework for Swing applications. The UndoManager manages a list of UndoableEdit objects, each of which can be individually undone or redone. Any Swing application that wants to provide an undo capability will find this package useful. Figure 35-1 shows the class hierarchy of this package.

figure

Figure 35-1. The javax.swing.undo package

AbstractUndoableEditJava 1.2
javax.swing.undoserializable

This class is a simple implementation of UndoableEdit. It enforces the restriction that an edit cannot be undone twice or redone without first being undone. Although the undo() and redo() methods do not actually undo or redo anything, subclasses should still call super.undo() and super.redo() in order to retain these restrictions. addEdit() and replaceEdit() return false; this implementation makes no attempt to merge events. getUndoPresentationName() and getRedoPresentationName() return the strings "Undo" and "Redo", followed by the string returned from getPresentationName(). Therefore, typical subclasses only need to override getPresentationName().

public class AbstractUndoableEdit implements Serializable, UndoableEdit {
// Public Constructors
public AbstractUndoableEdit ();
// Protected Constants
protected static final String RedoName ; ="Redo"
protected static final String UndoName ; ="Undo"
// Methods Implementing UndoableEdit
public boolean addEdit (UndoableEdit anEdit); constant
public boolean canRedo ();
public boolean canUndo ();
public void die ();
public String getPresentationName (); default:""
public String getRedoPresentationName (); default:"Redo"
public String getUndoPresentationName (); default:"Undo"
public boolean isSignificant (); constant default:true
public void redo () throws CannotRedoException;
public boolean replaceEdit (UndoableEdit anEdit); constant
public void undo () throws CannotUndoException;
// Public Methods Overriding Object
public String toString ();
}

Hierarchy: Object-->AbstractUndoableEdit(Serializable,UndoableEdit)

Subclasses: javax.swing.text.AbstractDocument.ElementEdit, javax.swing.text.DefaultStyledDocument.AttributeUndoableEdit, CompoundEdit, StateEdit

CannotRedoExceptionJava 1.2
javax.swing.undoserializable unchecked

Signals that an UndoableEdit cannot be redone, perhaps because it has not been undone yet or because it has already been redone.

public class CannotRedoException extends RuntimeException {
// Public Constructors
public CannotRedoException ();
}

Hierarchy: Object-->Throwable(Serializable)-->Exception-->RuntimeException-->CannotRedoException

Thrown By: javax.swing.text.AbstractDocument.DefaultDocumentEvent.redo(), javax.swing.text.AbstractDocument.ElementEdit.redo(), javax.swing.text.DefaultStyledDocument.AttributeUndoableEdit.redo(), AbstractUndoableEdit.redo(), CompoundEdit.redo(), UndoableEdit.redo(), UndoManager.{redo(), redoTo(), undoOrRedo()}

CannotUndoExceptionJava 1.2
javax.swing.undoserializable unchecked

Signals that an UndoableEdit cannot be undone, perhaps because it has already been undone.

public class CannotUndoException extends RuntimeException {
// Public Constructors
public CannotUndoException ();
}

Hierarchy: Object-->Throwable(Serializable)-->Exception-->RuntimeException-->CannotUndoException

Thrown By: javax.swing.text.AbstractDocument.DefaultDocumentEvent.undo(), javax.swing.text.AbstractDocument.ElementEdit.undo(), javax.swing.text.DefaultStyledDocument.AttributeUndoableEdit.undo(), AbstractUndoableEdit.undo(), CompoundEdit.undo(), UndoableEdit.undo(), UndoManager.{undo(), undoOrRedo(), undoTo()}

CompoundEditJava 1.2
javax.swing.undoserializable

This class is a compound UndoableEdit that collects a group of UndoableEdit objects into a single object and allows them to be undone and redone as a group. After creating a CompoundEdit object, you use addEdit() to add UndoableEdit objects to it. When you are done adding edits, call end(). Once end() has been called, you can freely use the undo() and redo() methods. The isInProgress() method returns true if end() has not been called yet and edits are still being added. While CompoundEdit maintains a list of UndoableEdit objects to undo and redo, the addEdit() method does not simply add edits to this list. When a new edit is added, CompoundEdit first attempts to merge it with the previously added edit by calling the addEdit() and replaceEdit() methods of the individual UndoableEdit objects. If these methods fail to merge the two edits into one, the new edit is added to the list of edits. The isSignificant() method returns true if any of the edits on the list of edits is significant and returns false otherwise. getPresentationName() returns the name of the last edit on the list, if it has one.

public class CompoundEdit extends AbstractUndoableEdit {
// Public Constructors
public CompoundEdit ();
// Public Instance Methods
public void end ();
public boolean isInProgress (); default:true
// Public Methods Overriding AbstractUndoableEdit
public boolean addEdit (UndoableEdit anEdit);
public boolean canRedo ();
public boolean canUndo ();
public void die ();
public String getPresentationName (); default:""
public String getRedoPresentationName (); default:"Redo"
public String getUndoPresentationName (); default:"Undo"
public boolean isSignificant (); default:false
public void redo () throws CannotRedoException;
public String toString ();
public void undo () throws CannotUndoException;
// Protected Instance Methods
protected UndoableEdit lastEdit ();
// Protected Instance Fields
protected java.util.Vector edits ;
}

Hierarchy: Object-->AbstractUndoableEdit(Serializable,UndoableEdit)-->CompoundEdit

Subclasses: javax.swing.text.AbstractDocument.DefaultDocumentEvent, UndoManager

Returned By: UndoableEditSupport.createCompoundEdit()

Type Of: UndoableEditSupport.compoundEdit

StateEditJava 1.2
javax.swing.undoserializable

This class is an UndoableEdit implementation that works with StateEditable objects. First, create a StateEdit object, passing the StateEditable object to be edited to the constructor (and optionally specifying a presentation name for the StateEdit). The constructor queries the initial state of the StateEditable object and saves it. Next, make your edits to the StateEditable object and then call the end() method on your StateEdit object. This method queries the edited state of the object and saves that state. StateEdit implements the undo() method by restoring the saved preedit state and implements the redo() method by restoring the saved postedit state. For efficiency, StateEdit removes duplicate state entries from the preedit and postedit hashtables, so only the state that changes is saved.

public class StateEdit extends AbstractUndoableEdit {
// Public Constructors
public StateEdit (StateEditable anObject);
public StateEdit (StateEditable anObject, String name);
// Protected Constants
protected static final String RCSID ;
// Public Instance Methods
public void end ();
// Public Methods Overriding AbstractUndoableEdit
public String getPresentationName ();
public void redo ();
public void undo ();
// Protected Instance Methods
protected void init (StateEditable anObject, String name);
protected void removeRedundantState ();
// Protected Instance Fields
protected StateEditable object ;
protected java.util.Hashtable postState ;
protected java.util.Hashtable preState ;
protected String undoRedoName ;
}

Hierarchy: Object-->AbstractUndoableEdit(Serializable,UndoableEdit)-->StateEdit

StateEditableJava 1.2
javax.swing.undo

This interface defines methods that allow an object to save and restore its state to and from a java.util.Hashtable. Objects that are able to implement this interface can easily support undo management with the StateEdit class.

public abstract interface StateEditable {
// Public Constants
public static final String RCSID ;
// Public Instance Methods
public abstract void restoreState (java.util.Hashtable state);
public abstract void storeState (java.util.Hashtable state);
}

Passed To: StateEdit.{init(), StateEdit()}

Type Of: StateEdit.object

UndoableEditJava 1.2
javax.swing.undo

This interface defines methods that encapsulate an undoable and redoable change to the state of an application or component. The undo() and redo() methods are the most important: they must actually undo and redo the edit. They throw exceptions if an edit is undone twice or redone twice or if for some other reason an edit cannot be undone or redone. canUndo() and canRedo() specify whether an UndoableEdit can currently be undone or redone. die() tells an edit that it is no longer needed, so it can release any resources it is holding. Neither undo() nor redo() should be called once die() has been called.

getPresentationName() returns a human-readable description of the edit. getUndoPresentationName() and getRedoPresentationName() return human-readable descriptions of undoing and redoing the edit. These two methods are usually implemented in terms of getPresentationName() and might return strings like "Undo typing" or "Redo deletion". isSignificant() specifies whether the edit is a significant one. Typically, significant edits are presented to the user in a user interface, while insignificant edits are simply undone and redone in conjunction with adjacent significant edits. The UndoManager class treats insignificant edits in this way, for example.

addEdit() and replaceEdit() are used for merging two UndoableEdit objects into one. addEdit() is called to see if an existing UndoableEdit is willing to merge or absorb another edit into itself. For example, if the user strikes the Backspace key twice in a row, the UndoableEdit object generated by the first keystroke might absorb the UndoableEdit object generated by the second keystroke, changing itself from a "backspace 1" edit to a "backspace 2" edit. addEdit() should return true if it adds the edit and false otherwise. replaceEdit() has a similar purpose but operates in the other direction. It gives a new UndoableEdit object the opportunity to absorb and replace an existing UndoableEdit. For example, if the user of a text editor selects a paragraph of text and then deletes that paragraph, the "delete-paragraph" edit might simply subsume and replace the "select-paragraph" edit. replaceEdit() should return true if it replaces the specified UndoableEdit object.

public abstract interface UndoableEdit {
// Property Accessor Methods (by property name)
public abstract String getPresentationName ();
public abstract String getRedoPresentationName ();
public abstract boolean isSignificant ();
public abstract String getUndoPresentationName ();
// Public Instance Methods
public abstract boolean addEdit (UndoableEdit anEdit);
public abstract boolean canRedo ();
public abstract boolean canUndo ();
public abstract void die ();
public abstract void redo () throws CannotRedoException;
public abstract boolean replaceEdit (UndoableEdit anEdit);
public abstract void undo () throws CannotUndoException;
}

Implementations: AbstractUndoableEdit

Passed To: javax.swing.event.UndoableEditEvent.UndoableEditEvent(), javax.swing.text.AbstractDocument.DefaultDocumentEvent.addEdit(), AbstractUndoableEdit.{addEdit(), replaceEdit()}, CompoundEdit.addEdit(), UndoableEdit.{addEdit(), replaceEdit()}, UndoableEditSupport.{_postEdit(), postEdit()}, UndoManager.{addEdit(), redoTo(), undoTo()}

Returned By: javax.swing.event.UndoableEditEvent.getEdit(), javax.swing.text.AbstractDocument.Content.{insertString(), remove()}, javax.swing.text.GapContent.{insertString(), remove()}, javax.swing.text.StringContent.{insertString(), remove()}, CompoundEdit.lastEdit(), UndoManager.{editToBeRedone(), editToBeUndone()}

UndoableEditSupportJava 1.2
javax.swing.undo

This utility class is useful for classes that support undoable edits and send javax.swing.event.UndoableEditEvent events to javax.swing.event.UndoableEditListener objects. An object that generates undoable events must allow the registration and deregistration of event listeners for those events. Such an object can simply create an UndoableEditSupport object and delegate to its addUndoableEditListener() and removeUndoableEditListener() methods.

UndoableEditSupport normally sends an UndoableEditEvent to all registered listeners when the postEdit() method is invoked. It also allows batching of edits into a CompoundEdit, however. If beginUpdate() is called, all UndoableEdit objects passed to postEdit() are batched into a CompoundEdit until endUpdate() is called. In this case, the UndoableEditEvent that contains the CompoundEdit is not sent to the registered UndoableEditListener objects until endUpdate() is invoked. If beginUpdate() is called more than once, endUpdate() must be called a matching number of times.

public class UndoableEditSupport {
// Public Constructors
public UndoableEditSupport ();
public UndoableEditSupport (Object r);
// Event Registration Methods (by event name)
public void addUndoableEditListener (javax.swing.event.UndoableEditListener l); synchronized
public void removeUndoableEditListener (javax.swing.event.UndoableEditListener l); synchronized
// Public Instance Methods
public void beginUpdate (); synchronized
public void endUpdate (); synchronized
public int getUpdateLevel (); default:0
public void postEdit (UndoableEdit e); synchronized
// Public Methods Overriding Object
public String toString ();
// Protected Instance Methods
protected void _postEdit (UndoableEdit e);
protected CompoundEdit createCompoundEdit ();
// Protected Instance Fields
protected CompoundEdit compoundEdit ;
protected java.util.Vector listeners ;
protected Object realSource ;
protected int updateLevel ;
}
UndoManagerJava 1.2
javax.swing.undoserializable

This class maintains a list of UndoableEdit objects and allows them to be undone and redone one significant edit at a time. Edits can be added explicitly by calling addEdit(). UndoManager implements the javax.swing.event.UndoableEditListener interface and automatically calls addEdit() to add an edit to its list when it receives a javax.swing.event.UndoableEditEvent. The addEdit() method works like the addEdit() method of CompoundEdit: it first attempts to merge the new edit with the last edit on the list by calling the addEdit() and replaceEdit() methods of those edits. The edit is added as a separate edit only if it could not be merged.

After an edit is made and added to the UndoManager, the undo() method undoes it. After it is undone, the redo() method redoes it. However, if a new edit is made after the first is undone, that first undone edit is removed from the list and is no longer redoable. This is the normal and expected behavior for an undo system. UndoManager distinguishes between significant and insignificant edits. When you call undo(), it undoes all edits up to the last significant edit that occurred. When you call redo(), it redoes the next significant edit and all insignificant edits that follow it. A significant UndoableEdit is one whose isSignificant() method returns true. getUndoPresentationName() returns the undo presentation name of the significant UndoableEdit that is undone by undo(). getRedoPresentationName() returns the redo presentation name of the significant UndoableEdit that is performed by the redo() action. setLimit() and getLimit() set and query the maximum number of UndoableEdit objects that the UndoManager tracks. The default is 100.

UndoManager is a subclass of CompoundEdit. If you call the end() method on an UndoManager, its behavior becomes that of a CompoundEdit and the list of edits is undone and redone all at once. This can occasionally be useful when doing nested edits.

public class UndoManager extends CompoundEdit implements javax.swing.event.UndoableEditListener {
// Public Constructors
public UndoManager ();
// Property Accessor Methods (by property name)
public int getLimit (); synchronized default:100
public void setLimit (int l); synchronized
public String getRedoPresentationName (); Overrides:CompoundEdit synchronized default:"Redo"
public String getUndoOrRedoPresentationName (); synchronized default:"Undo"
public String getUndoPresentationName (); Overrides:CompoundEdit synchronized default:"Undo"
// Public Instance Methods
public boolean canUndoOrRedo (); synchronized
public void discardAllEdits (); synchronized
public void undoOrRedo () throws CannotRedoException, CannotUndoException; synchronized
// Methods Implementing UndoableEditListener
public void undoableEditHappened (javax.swing.event.UndoableEditEvent e);
// Public Methods Overriding CompoundEdit
public boolean addEdit (UndoableEdit anEdit); synchronized
public boolean canRedo (); synchronized
public boolean canUndo (); synchronized
public void end (); synchronized
public void redo () throws CannotRedoException; synchronized
public String toString ();
public void undo () throws CannotUndoException; synchronized
// Protected Instance Methods
protected UndoableEdit editToBeRedone ();
protected UndoableEdit editToBeUndone ();
protected void redoTo (UndoableEdit edit) throws CannotRedoException;
protected void trimEdits (int from, int to);
protected void trimForLimit ();
protected void undoTo (UndoableEdit edit) throws CannotUndoException;
}

Hierarchy: Object-->AbstractUndoableEdit(Serializable,UndoableEdit)-->CompoundEdit-->UndoManager(javax.swing.event.UndoableEditListener(java.util.EventListener))



Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.