Java by API/javax.swing.undo/UndoManager

Материал из Java эксперт
Перейти к: навигация, поиск

new UndoManager()

 
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
public class MainClass {
  public static void main(final String args[]) {
    JFrame frame = new JFrame("Undo Sample");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextArea textArea = new JTextArea();
    JScrollPane scrollPane = new JScrollPane(textArea);
    UndoManager manager = new UndoManager();
    textArea.getDocument().addUndoableEditListener(manager);
    JToolBar toolbar = new JToolBar();
    JButton undoButton = new JButton(new UndoAction(manager, (String) UIManager
        .get("AbstractUndoableEdit.undoText")));
    toolbar.add(undoButton);
    Container content = frame.getContentPane();
    content.add(toolbar, BorderLayout.NORTH);
    content.add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}
abstract class UndoRedoAction extends AbstractAction {
  UndoManager undoManager = new UndoManager();
  String errorMessage = "Cannot undo";
  String errorTitle = "Undo Problem";
  protected UndoRedoAction(UndoManager manager, String name) {
    super(name);
    undoManager = manager;
  }
  public void setErrorMessage(String newValue) {
    errorMessage = newValue;
  }
  public void setErrorTitle(String newValue) {
    errorTitle = newValue;
  }
  protected void showMessage(Object source) {
    if (source instanceof Component) {
      JOptionPane.showMessageDialog((Component) source, errorMessage, errorTitle,
          JOptionPane.WARNING_MESSAGE);
    } else {
      System.err.println(errorMessage);
    }
  }
}
class UndoAction extends UndoRedoAction {
  public UndoAction(UndoManager manager, String name) {
    super(manager, name);
    setErrorMessage("Cannot undo");
    setErrorTitle("Undo Problem");
  }
  public void actionPerformed(ActionEvent actionEvent) {
    try {
      undoManager.undo();
    } catch (CannotUndoException cannotUndoException) {
      showMessage(actionEvent.getSource());
    }
  }
}





UndoManager: addEdit(UndoableEdit anEdit)

 
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
  public static void main(String[] args) {
    UndoManager mgr = new UndoManager();
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
    System.out.println("Insignificant edit example");
    mgr.undo();
    mgr.redo();
    System.out.println(mgr.canRedo()); // No more sig. edits
    // Show how edits that call add/replace are used.
    //
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Absorbed (by addEdit) edit example");
    mgr.undo();
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
    System.out.println("Absorbed (by replaceEdit) edit example");
    mgr.undo();
    System.out.println(mgr.canUndo());
    // Show how changing limit works.
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Changing limit example");
    mgr.undo();
    mgr.undo();
    mgr.undo(); // Now 3 undoable, 3 redoable
    mgr.setLimit(4); // Now 2 undoable, 2 redoable!
    while (mgr.canUndo())
      mgr.undo();
    while (mgr.canRedo())
      mgr.redo();
    // undoOrRedo example
    mgr.discardAllEdits();
    mgr.setLimit(1);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    System.out.println("undoOrRedo example");
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    // Show how UndoManager becomes a CompositeEdit.
    mgr.discardAllEdits();
    mgr.setLimit(100);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    System.out.println("Transform to composite example");
    mgr.end();
    mgr.undo();
    mgr.redo();
    // Show that adds are no longer allowed. Note that addEdit() returns true in
    // pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
    System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
    mgr.undo(); // note that edit 4 is not there
  }
}
class SampleUndoableEdit extends AbstractUndoableEdit {
  private boolean isSignificant;
  private boolean isReplacer;
  private int number;
  private boolean allowAdds;
  private Vector addedEdits;
  private UndoableEdit replaced;
  // Create a new edit with an identifying number. The boolean arguments define
  // the edit"s behavior.
  public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
    this.number = number;
    this.allowAdds = allowAdds;
    if (allowAdds)
      addedEdits = new Vector();
    this.isSignificant = isSignificant;
    this.isReplacer = isReplacer;
  }
  // "Undo" the edit by printing a message to the screen.
  public void undo() throws CannotUndoException {
    super.undo();
    System.out.print("Undo " + number);
    dumpState();
  }
  // "Redo" the edit by printing a message to the screen.
  public void redo() throws CannotRedoException {
    super.redo();
    System.out.print("Redo " + number);
    dumpState();
  }
  // If allowAdds is true, we store the input edit. If not, just return false.
  public boolean addEdit(UndoableEdit anEdit) {
    if (allowAdds) {
      addedEdits.addElement(anEdit);
      return true;
    } else
      return false;
  }
  // If isReplacer is true, we store the edit we are replacing.
  public boolean replaceEdit(UndoableEdit anEdit) {
    if (isReplacer) {
      replaced = anEdit;
      return true;
    } else
      return false;
  }
  // Significance is based on constructor parameter.
  public boolean isSignificant() {
    return isSignificant;
  }
  // Just return our identifier.
  public String toString() {
    return "<" + number + ">";
  }
  // Debug output.
  public void dumpState() {
    if (allowAdds && addedEdits.size() > 0) {
      Enumeration e = addedEdits.elements();
      System.out.print(" (absorbed: ");
      while (e.hasMoreElements()) {
        System.out.print(e.nextElement());
      }
      System.out.print(")");
    }
    if (isReplacer && replaced != null) {
      System.out.print(" (replaced: " + replaced + ")");
    }
    System.out.println();
  }
}





UndoManager: canRedo()

 
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
  public static void main(String[] args) {
    UndoManager mgr = new UndoManager();
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
    System.out.println("Insignificant edit example");
    mgr.undo();
    mgr.redo();
    System.out.println(mgr.canRedo()); // No more sig. edits
    // Show how edits that call add/replace are used.
    //
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Absorbed (by addEdit) edit example");
    mgr.undo();
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
    System.out.println("Absorbed (by replaceEdit) edit example");
    mgr.undo();
    System.out.println(mgr.canUndo());
    // Show how changing limit works.
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Changing limit example");
    mgr.undo();
    mgr.undo();
    mgr.undo(); // Now 3 undoable, 3 redoable
    mgr.setLimit(4); // Now 2 undoable, 2 redoable!
    while (mgr.canUndo())
      mgr.undo();
    while (mgr.canRedo())
      mgr.redo();
    // undoOrRedo example
    mgr.discardAllEdits();
    mgr.setLimit(1);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    System.out.println("undoOrRedo example");
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    // Show how UndoManager becomes a CompositeEdit.
    mgr.discardAllEdits();
    mgr.setLimit(100);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    System.out.println("Transform to composite example");
    mgr.end();
    mgr.undo();
    mgr.redo();
    // Show that adds are no longer allowed. Note that addEdit() returns true in
    // pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
    System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
    mgr.undo(); // note that edit 4 is not there
  }
}
class SampleUndoableEdit extends AbstractUndoableEdit {
  private boolean isSignificant;
  private boolean isReplacer;
  private int number;
  private boolean allowAdds;
  private Vector addedEdits;
  private UndoableEdit replaced;
  // Create a new edit with an identifying number. The boolean arguments define
  // the edit"s behavior.
  public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
    this.number = number;
    this.allowAdds = allowAdds;
    if (allowAdds)
      addedEdits = new Vector();
    this.isSignificant = isSignificant;
    this.isReplacer = isReplacer;
  }
  // "Undo" the edit by printing a message to the screen.
  public void undo() throws CannotUndoException {
    super.undo();
    System.out.print("Undo " + number);
    dumpState();
  }
  // "Redo" the edit by printing a message to the screen.
  public void redo() throws CannotRedoException {
    super.redo();
    System.out.print("Redo " + number);
    dumpState();
  }
  // If allowAdds is true, we store the input edit. If not, just return false.
  public boolean addEdit(UndoableEdit anEdit) {
    if (allowAdds) {
      addedEdits.addElement(anEdit);
      return true;
    } else
      return false;
  }
  // If isReplacer is true, we store the edit we are replacing.
  public boolean replaceEdit(UndoableEdit anEdit) {
    if (isReplacer) {
      replaced = anEdit;
      return true;
    } else
      return false;
  }
  // Significance is based on constructor parameter.
  public boolean isSignificant() {
    return isSignificant;
  }
  // Just return our identifier.
  public String toString() {
    return "<" + number + ">";
  }
  // Debug output.
  public void dumpState() {
    if (allowAdds && addedEdits.size() > 0) {
      Enumeration e = addedEdits.elements();
      System.out.print(" (absorbed: ");
      while (e.hasMoreElements()) {
        System.out.print(e.nextElement());
      }
      System.out.print(")");
    }
    if (isReplacer && replaced != null) {
      System.out.print(" (replaced: " + replaced + ")");
    }
    System.out.println();
  }
}





UndoManager: canUndo()

 
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
  public static void main(String[] args) {
    UndoManager mgr = new UndoManager();
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
    System.out.println("Insignificant edit example");
    mgr.undo();
    mgr.redo();
    System.out.println(mgr.canRedo()); // No more sig. edits
    // Show how edits that call add/replace are used.
    //
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Absorbed (by addEdit) edit example");
    mgr.undo();
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
    System.out.println("Absorbed (by replaceEdit) edit example");
    mgr.undo();
    System.out.println(mgr.canUndo());
    // Show how changing limit works.
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Changing limit example");
    mgr.undo();
    mgr.undo();
    mgr.undo(); // Now 3 undoable, 3 redoable
    mgr.setLimit(4); // Now 2 undoable, 2 redoable!
    while (mgr.canUndo())
      mgr.undo();
    while (mgr.canRedo())
      mgr.redo();
    // undoOrRedo example
    mgr.discardAllEdits();
    mgr.setLimit(1);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    System.out.println("undoOrRedo example");
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    // Show how UndoManager becomes a CompositeEdit.
    mgr.discardAllEdits();
    mgr.setLimit(100);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    System.out.println("Transform to composite example");
    mgr.end();
    mgr.undo();
    mgr.redo();
    // Show that adds are no longer allowed. Note that addEdit() returns true in
    // pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
    System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
    mgr.undo(); // note that edit 4 is not there
  }
}
class SampleUndoableEdit extends AbstractUndoableEdit {
  private boolean isSignificant;
  private boolean isReplacer;
  private int number;
  private boolean allowAdds;
  private Vector addedEdits;
  private UndoableEdit replaced;
  // Create a new edit with an identifying number. The boolean arguments define
  // the edit"s behavior.
  public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
    this.number = number;
    this.allowAdds = allowAdds;
    if (allowAdds)
      addedEdits = new Vector();
    this.isSignificant = isSignificant;
    this.isReplacer = isReplacer;
  }
  // "Undo" the edit by printing a message to the screen.
  public void undo() throws CannotUndoException {
    super.undo();
    System.out.print("Undo " + number);
    dumpState();
  }
  // "Redo" the edit by printing a message to the screen.
  public void redo() throws CannotRedoException {
    super.redo();
    System.out.print("Redo " + number);
    dumpState();
  }
  // If allowAdds is true, we store the input edit. If not, just return false.
  public boolean addEdit(UndoableEdit anEdit) {
    if (allowAdds) {
      addedEdits.addElement(anEdit);
      return true;
    } else
      return false;
  }
  // If isReplacer is true, we store the edit we are replacing.
  public boolean replaceEdit(UndoableEdit anEdit) {
    if (isReplacer) {
      replaced = anEdit;
      return true;
    } else
      return false;
  }
  // Significance is based on constructor parameter.
  public boolean isSignificant() {
    return isSignificant;
  }
  // Just return our identifier.
  public String toString() {
    return "<" + number + ">";
  }
  // Debug output.
  public void dumpState() {
    if (allowAdds && addedEdits.size() > 0) {
      Enumeration e = addedEdits.elements();
      System.out.print(" (absorbed: ");
      while (e.hasMoreElements()) {
        System.out.print(e.nextElement());
      }
      System.out.print(")");
    }
    if (isReplacer && replaced != null) {
      System.out.print(" (replaced: " + replaced + ")");
    }
    System.out.println();
  }
}





UndoManager: discardAllEdits()

 
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
  public static void main(String[] args) {
    UndoManager mgr = new UndoManager();
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
    System.out.println("Insignificant edit example");
    mgr.undo();
    mgr.redo();
    System.out.println(mgr.canRedo()); // No more sig. edits
    // Show how edits that call add/replace are used.
    //
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Absorbed (by addEdit) edit example");
    mgr.undo();
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
    System.out.println("Absorbed (by replaceEdit) edit example");
    mgr.undo();
    System.out.println(mgr.canUndo());
    // Show how changing limit works.
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Changing limit example");
    mgr.undo();
    mgr.undo();
    mgr.undo(); // Now 3 undoable, 3 redoable
    mgr.setLimit(4); // Now 2 undoable, 2 redoable!
    while (mgr.canUndo())
      mgr.undo();
    while (mgr.canRedo())
      mgr.redo();
    // undoOrRedo example
    mgr.discardAllEdits();
    mgr.setLimit(1);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    System.out.println("undoOrRedo example");
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    // Show how UndoManager becomes a CompositeEdit.
    mgr.discardAllEdits();
    mgr.setLimit(100);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    System.out.println("Transform to composite example");
    mgr.end();
    mgr.undo();
    mgr.redo();
    // Show that adds are no longer allowed. Note that addEdit() returns true in
    // pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
    System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
    mgr.undo(); // note that edit 4 is not there
  }
}
class SampleUndoableEdit extends AbstractUndoableEdit {
  private boolean isSignificant;
  private boolean isReplacer;
  private int number;
  private boolean allowAdds;
  private Vector addedEdits;
  private UndoableEdit replaced;
  // Create a new edit with an identifying number. The boolean arguments define
  // the edit"s behavior.
  public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
    this.number = number;
    this.allowAdds = allowAdds;
    if (allowAdds)
      addedEdits = new Vector();
    this.isSignificant = isSignificant;
    this.isReplacer = isReplacer;
  }
  // "Undo" the edit by printing a message to the screen.
  public void undo() throws CannotUndoException {
    super.undo();
    System.out.print("Undo " + number);
    dumpState();
  }
  // "Redo" the edit by printing a message to the screen.
  public void redo() throws CannotRedoException {
    super.redo();
    System.out.print("Redo " + number);
    dumpState();
  }
  // If allowAdds is true, we store the input edit. If not, just return false.
  public boolean addEdit(UndoableEdit anEdit) {
    if (allowAdds) {
      addedEdits.addElement(anEdit);
      return true;
    } else
      return false;
  }
  // If isReplacer is true, we store the edit we are replacing.
  public boolean replaceEdit(UndoableEdit anEdit) {
    if (isReplacer) {
      replaced = anEdit;
      return true;
    } else
      return false;
  }
  // Significance is based on constructor parameter.
  public boolean isSignificant() {
    return isSignificant;
  }
  // Just return our identifier.
  public String toString() {
    return "<" + number + ">";
  }
  // Debug output.
  public void dumpState() {
    if (allowAdds && addedEdits.size() > 0) {
      Enumeration e = addedEdits.elements();
      System.out.print(" (absorbed: ");
      while (e.hasMoreElements()) {
        System.out.print(e.nextElement());
      }
      System.out.print(")");
    }
    if (isReplacer && replaced != null) {
      System.out.print(" (replaced: " + replaced + ")");
    }
    System.out.println();
  }
}





UndoManager: end()

 
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
  public static void main(String[] args) {
    UndoManager mgr = new UndoManager();
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
    System.out.println("Insignificant edit example");
    mgr.undo();
    mgr.redo();
    System.out.println(mgr.canRedo()); // No more sig. edits
    // Show how edits that call add/replace are used.
    //
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Absorbed (by addEdit) edit example");
    mgr.undo();
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
    System.out.println("Absorbed (by replaceEdit) edit example");
    mgr.undo();
    System.out.println(mgr.canUndo());
    // Show how changing limit works.
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Changing limit example");
    mgr.undo();
    mgr.undo();
    mgr.undo(); // Now 3 undoable, 3 redoable
    mgr.setLimit(4); // Now 2 undoable, 2 redoable!
    while (mgr.canUndo())
      mgr.undo();
    while (mgr.canRedo())
      mgr.redo();
    // undoOrRedo example
    mgr.discardAllEdits();
    mgr.setLimit(1);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    System.out.println("undoOrRedo example");
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    // Show how UndoManager becomes a CompositeEdit.
    mgr.discardAllEdits();
    mgr.setLimit(100);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    System.out.println("Transform to composite example");
    mgr.end();
    mgr.undo();
    mgr.redo();
    // Show that adds are no longer allowed. Note that addEdit() returns true in
    // pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
    System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
    mgr.undo(); // note that edit 4 is not there
  }
}
class SampleUndoableEdit extends AbstractUndoableEdit {
  private boolean isSignificant;
  private boolean isReplacer;
  private int number;
  private boolean allowAdds;
  private Vector addedEdits;
  private UndoableEdit replaced;
  // Create a new edit with an identifying number. The boolean arguments define
  // the edit"s behavior.
  public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
    this.number = number;
    this.allowAdds = allowAdds;
    if (allowAdds)
      addedEdits = new Vector();
    this.isSignificant = isSignificant;
    this.isReplacer = isReplacer;
  }
  // "Undo" the edit by printing a message to the screen.
  public void undo() throws CannotUndoException {
    super.undo();
    System.out.print("Undo " + number);
    dumpState();
  }
  // "Redo" the edit by printing a message to the screen.
  public void redo() throws CannotRedoException {
    super.redo();
    System.out.print("Redo " + number);
    dumpState();
  }
  // If allowAdds is true, we store the input edit. If not, just return false.
  public boolean addEdit(UndoableEdit anEdit) {
    if (allowAdds) {
      addedEdits.addElement(anEdit);
      return true;
    } else
      return false;
  }
  // If isReplacer is true, we store the edit we are replacing.
  public boolean replaceEdit(UndoableEdit anEdit) {
    if (isReplacer) {
      replaced = anEdit;
      return true;
    } else
      return false;
  }
  // Significance is based on constructor parameter.
  public boolean isSignificant() {
    return isSignificant;
  }
  // Just return our identifier.
  public String toString() {
    return "<" + number + ">";
  }
  // Debug output.
  public void dumpState() {
    if (allowAdds && addedEdits.size() > 0) {
      Enumeration e = addedEdits.elements();
      System.out.print(" (absorbed: ");
      while (e.hasMoreElements()) {
        System.out.print(e.nextElement());
      }
      System.out.print(")");
    }
    if (isReplacer && replaced != null) {
      System.out.print(" (replaced: " + replaced + ")");
    }
    System.out.println();
  }
}





UndoManager: getRedoPresentationName()

  
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.UndoManager;
public class Main extends JFrame {
  protected JTextArea textArea = new JTextArea();
  protected UndoManager undoManager = new UndoManager();
  protected JButton undoButton = new JButton("Undo");
  protected JButton redoButton = new JButton("Redo");
  public Main() {
    super("Undo/Redo Demo");
    undoButton.setEnabled(false);
    redoButton.setEnabled(false);
    JPanel buttonPanel = new JPanel(new GridLayout());
    buttonPanel.add(undoButton);
    buttonPanel.add(redoButton);
    JScrollPane scroller = new JScrollPane(textArea);
    getContentPane().add(buttonPanel, BorderLayout.NORTH);
    getContentPane().add(scroller, BorderLayout.CENTER);
    textArea.getDocument().addUndoableEditListener(
        new UndoableEditListener() {
          public void undoableEditHappened(UndoableEditEvent e) {
            undoManager.addEdit(e.getEdit());
            updateButtons();
          }
        });
    undoButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        try {
          undoManager.undo();
        } catch (CannotRedoException cre) {
          cre.printStackTrace();
        }
        updateButtons();
      }
    });
    redoButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        try {
          undoManager.redo();
        } catch (CannotRedoException cre) {
          cre.printStackTrace();
        }
        updateButtons();
      }
    });
    setSize(400, 300);
    setVisible(true);
  }
  public void updateButtons() {
    undoButton.setText(undoManager.getUndoPresentationName());
    redoButton.setText(undoManager.getRedoPresentationName());
    undoButton.setEnabled(undoManager.canUndo());
    redoButton.setEnabled(undoManager.canRedo());
  }
  public static void main(String argv[]) {
    new Main();
  }
}





UndoManager: getUndoPresentationName()

  
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.UndoManager;
public class Main extends JFrame {
  protected JTextArea textArea = new JTextArea();
  protected UndoManager undoManager = new UndoManager();
  protected JButton undoButton = new JButton("Undo");
  protected JButton redoButton = new JButton("Redo");
  public Main() {
    super("Undo/Redo Demo");
    undoButton.setEnabled(false);
    redoButton.setEnabled(false);
    JPanel buttonPanel = new JPanel(new GridLayout());
    buttonPanel.add(undoButton);
    buttonPanel.add(redoButton);
    JScrollPane scroller = new JScrollPane(textArea);
    getContentPane().add(buttonPanel, BorderLayout.NORTH);
    getContentPane().add(scroller, BorderLayout.CENTER);
    textArea.getDocument().addUndoableEditListener(
        new UndoableEditListener() {
          public void undoableEditHappened(UndoableEditEvent e) {
            undoManager.addEdit(e.getEdit());
            updateButtons();
          }
        });
    undoButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        try {
          undoManager.undo();
        } catch (CannotRedoException cre) {
          cre.printStackTrace();
        }
        updateButtons();
      }
    });
    redoButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        try {
          undoManager.redo();
        } catch (CannotRedoException cre) {
          cre.printStackTrace();
        }
        updateButtons();
      }
    });
    setSize(400, 300);
    setVisible(true);
  }
  public void updateButtons() {
    undoButton.setText(undoManager.getUndoPresentationName());
    redoButton.setText(undoManager.getRedoPresentationName());
    undoButton.setEnabled(undoManager.canUndo());
    redoButton.setEnabled(undoManager.canRedo());
  }
  public static void main(String argv[]) {
    new Main();
  }
}





UndoManager: redo()

 
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
public class MainClass {
  public static void main(final String args[]) {
    JFrame frame = new JFrame("Undo Sample");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextArea textArea = new JTextArea();
    JScrollPane scrollPane = new JScrollPane(textArea);
    UndoManager manager = new UndoManager();
    textArea.getDocument().addUndoableEditListener(manager);
    JToolBar toolbar = new JToolBar();
    JButton undoButton = new JButton(new UndoAction(manager, (String) UIManager
        .get("AbstractUndoableEdit.undoText")));
    toolbar.add(undoButton);
    JButton redoButton = new JButton(new RedoAction(manager, (String) UIManager
        .get("AbstractUndoableEdit.redoText")));
    toolbar.add(redoButton);    
    
    Container content = frame.getContentPane();
    content.add(toolbar, BorderLayout.NORTH);
    content.add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}
abstract class UndoRedoAction extends AbstractAction {
  UndoManager undoManager = new UndoManager();
  String errorMessage = "Cannot undo";
  String errorTitle = "Undo Problem";
  protected UndoRedoAction(UndoManager manager, String name) {
    super(name);
    undoManager = manager;
  }
  public void setErrorMessage(String newValue) {
    errorMessage = newValue;
  }
  public void setErrorTitle(String newValue) {
    errorTitle = newValue;
  }
  protected void showMessage(Object source) {
    if (source instanceof Component) {
      JOptionPane.showMessageDialog((Component) source, errorMessage, errorTitle,
          JOptionPane.WARNING_MESSAGE);
    } else {
      System.err.println(errorMessage);
    }
  }
}
class UndoAction extends UndoRedoAction {
  public UndoAction(UndoManager manager, String name) {
    super(manager, name);
    setErrorMessage("Cannot undo");
    setErrorTitle("Undo Problem");
  }
  public void actionPerformed(ActionEvent actionEvent) {
    try {
      undoManager.undo();
    } catch (CannotUndoException cannotUndoException) {
      showMessage(actionEvent.getSource());
    }
  }
}
class RedoAction extends UndoRedoAction {
  public RedoAction(UndoManager manager, String name) {
    super(manager, name);
    setErrorMessage("Cannot redo");
    setErrorTitle("Redo Problem");
  }
  public void actionPerformed(ActionEvent actionEvent) {
    try {
      undoManager.redo();
    } catch (CannotRedoException cannotRedoException) {
      showMessage(actionEvent.getSource());
    }
  }
}





UndoManager: setLimit(int l)

 
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
  public static void main(String[] args) {
    UndoManager mgr = new UndoManager();
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
    System.out.println("Insignificant edit example");
    mgr.undo();
    mgr.redo();
    System.out.println(mgr.canRedo()); // No more sig. edits
    // Show how edits that call add/replace are used.
    //
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Absorbed (by addEdit) edit example");
    mgr.undo();
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
    System.out.println("Absorbed (by replaceEdit) edit example");
    mgr.undo();
    System.out.println(mgr.canUndo());
    // Show how changing limit works.
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Changing limit example");
    mgr.undo();
    mgr.undo();
    mgr.undo(); // Now 3 undoable, 3 redoable
    mgr.setLimit(4); // Now 2 undoable, 2 redoable!
    while (mgr.canUndo())
      mgr.undo();
    while (mgr.canRedo())
      mgr.redo();
    // undoOrRedo example
    mgr.discardAllEdits();
    mgr.setLimit(1);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    System.out.println("undoOrRedo example");
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    // Show how UndoManager becomes a CompositeEdit.
    mgr.discardAllEdits();
    mgr.setLimit(100);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    System.out.println("Transform to composite example");
    mgr.end();
    mgr.undo();
    mgr.redo();
    // Show that adds are no longer allowed. Note that addEdit() returns true in
    // pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
    System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
    mgr.undo(); // note that edit 4 is not there
  }
}
class SampleUndoableEdit extends AbstractUndoableEdit {
  private boolean isSignificant;
  private boolean isReplacer;
  private int number;
  private boolean allowAdds;
  private Vector addedEdits;
  private UndoableEdit replaced;
  // Create a new edit with an identifying number. The boolean arguments define
  // the edit"s behavior.
  public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
    this.number = number;
    this.allowAdds = allowAdds;
    if (allowAdds)
      addedEdits = new Vector();
    this.isSignificant = isSignificant;
    this.isReplacer = isReplacer;
  }
  // "Undo" the edit by printing a message to the screen.
  public void undo() throws CannotUndoException {
    super.undo();
    System.out.print("Undo " + number);
    dumpState();
  }
  // "Redo" the edit by printing a message to the screen.
  public void redo() throws CannotRedoException {
    super.redo();
    System.out.print("Redo " + number);
    dumpState();
  }
  // If allowAdds is true, we store the input edit. If not, just return false.
  public boolean addEdit(UndoableEdit anEdit) {
    if (allowAdds) {
      addedEdits.addElement(anEdit);
      return true;
    } else
      return false;
  }
  // If isReplacer is true, we store the edit we are replacing.
  public boolean replaceEdit(UndoableEdit anEdit) {
    if (isReplacer) {
      replaced = anEdit;
      return true;
    } else
      return false;
  }
  // Significance is based on constructor parameter.
  public boolean isSignificant() {
    return isSignificant;
  }
  // Just return our identifier.
  public String toString() {
    return "<" + number + ">";
  }
  // Debug output.
  public void dumpState() {
    if (allowAdds && addedEdits.size() > 0) {
      Enumeration e = addedEdits.elements();
      System.out.print(" (absorbed: ");
      while (e.hasMoreElements()) {
        System.out.print(e.nextElement());
      }
      System.out.print(")");
    }
    if (isReplacer && replaced != null) {
      System.out.print(" (replaced: " + replaced + ")");
    }
    System.out.println();
  }
}





UndoManager: undo()

 
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
public class MainClass {
  public static void main(final String args[]) {
    JFrame frame = new JFrame("Undo Sample");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextArea textArea = new JTextArea();
    JScrollPane scrollPane = new JScrollPane(textArea);
    UndoManager manager = new UndoManager();
    textArea.getDocument().addUndoableEditListener(manager);
    JToolBar toolbar = new JToolBar();
    JButton undoButton = new JButton(new UndoAction(manager, (String) UIManager
        .get("AbstractUndoableEdit.undoText")));
    toolbar.add(undoButton);
    Container content = frame.getContentPane();
    content.add(toolbar, BorderLayout.NORTH);
    content.add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}
abstract class UndoRedoAction extends AbstractAction {
  UndoManager undoManager = new UndoManager();
  String errorMessage = "Cannot undo";
  String errorTitle = "Undo Problem";
  protected UndoRedoAction(UndoManager manager, String name) {
    super(name);
    undoManager = manager;
  }
  public void setErrorMessage(String newValue) {
    errorMessage = newValue;
  }
  public void setErrorTitle(String newValue) {
    errorTitle = newValue;
  }
  protected void showMessage(Object source) {
    if (source instanceof Component) {
      JOptionPane.showMessageDialog((Component) source, errorMessage, errorTitle,
          JOptionPane.WARNING_MESSAGE);
    } else {
      System.err.println(errorMessage);
    }
  }
}
class UndoAction extends UndoRedoAction {
  public UndoAction(UndoManager manager, String name) {
    super(manager, name);
    setErrorMessage("Cannot undo");
    setErrorTitle("Undo Problem");
  }
  public void actionPerformed(ActionEvent actionEvent) {
    try {
      undoManager.undo();
    } catch (CannotUndoException cannotUndoException) {
      showMessage(actionEvent.getSource());
    }
  }
}





UndoManager: undoOrRedo()

 
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
public class UndoManagerDetails {
  public static void main(String[] args) {
    UndoManager mgr = new UndoManager();
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, false, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, false, false));
    System.out.println("Insignificant edit example");
    mgr.undo();
    mgr.redo();
    System.out.println(mgr.canRedo()); // No more sig. edits
    // Show how edits that call add/replace are used.
    //
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(5, true, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Absorbed (by addEdit) edit example");
    mgr.undo();
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, true));
    System.out.println("Absorbed (by replaceEdit) edit example");
    mgr.undo();
    System.out.println(mgr.canUndo());
    // Show how changing limit works.
    mgr.discardAllEdits();
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(4, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(5, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(6, false, true, false));
    System.out.println("Changing limit example");
    mgr.undo();
    mgr.undo();
    mgr.undo(); // Now 3 undoable, 3 redoable
    mgr.setLimit(4); // Now 2 undoable, 2 redoable!
    while (mgr.canUndo())
      mgr.undo();
    while (mgr.canRedo())
      mgr.redo();
    // undoOrRedo example
    mgr.discardAllEdits();
    mgr.setLimit(1);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    System.out.println("undoOrRedo example");
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    System.out.println(mgr.getUndoOrRedoPresentationName());
    mgr.undoOrRedo();
    // Show how UndoManager becomes a CompositeEdit.
    mgr.discardAllEdits();
    mgr.setLimit(100);
    // # adds? sig? replace?
    mgr.addEdit(new SampleUndoableEdit(1, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(2, false, true, false));
    mgr.addEdit(new SampleUndoableEdit(3, false, true, false));
    System.out.println("Transform to composite example");
    mgr.end();
    mgr.undo();
    mgr.redo();
    // Show that adds are no longer allowed. Note that addEdit() returns true in
    // pre-JDK 1.2 Swing releases. This is fixed in JDK 1.2.
    System.out.println(mgr.addEdit(new SampleUndoableEdit(4, false, true, false)));
    mgr.undo(); // note that edit 4 is not there
  }
}
class SampleUndoableEdit extends AbstractUndoableEdit {
  private boolean isSignificant;
  private boolean isReplacer;
  private int number;
  private boolean allowAdds;
  private Vector addedEdits;
  private UndoableEdit replaced;
  // Create a new edit with an identifying number. The boolean arguments define
  // the edit"s behavior.
  public SampleUndoableEdit(int number, boolean allowAdds, boolean isSignificant, boolean isReplacer) {
    this.number = number;
    this.allowAdds = allowAdds;
    if (allowAdds)
      addedEdits = new Vector();
    this.isSignificant = isSignificant;
    this.isReplacer = isReplacer;
  }
  // "Undo" the edit by printing a message to the screen.
  public void undo() throws CannotUndoException {
    super.undo();
    System.out.print("Undo " + number);
    dumpState();
  }
  // "Redo" the edit by printing a message to the screen.
  public void redo() throws CannotRedoException {
    super.redo();
    System.out.print("Redo " + number);
    dumpState();
  }
  // If allowAdds is true, we store the input edit. If not, just return false.
  public boolean addEdit(UndoableEdit anEdit) {
    if (allowAdds) {
      addedEdits.addElement(anEdit);
      return true;
    } else
      return false;
  }
  // If isReplacer is true, we store the edit we are replacing.
  public boolean replaceEdit(UndoableEdit anEdit) {
    if (isReplacer) {
      replaced = anEdit;
      return true;
    } else
      return false;
  }
  // Significance is based on constructor parameter.
  public boolean isSignificant() {
    return isSignificant;
  }
  // Just return our identifier.
  public String toString() {
    return "<" + number + ">";
  }
  // Debug output.
  public void dumpState() {
    if (allowAdds && addedEdits.size() > 0) {
      Enumeration e = addedEdits.elements();
      System.out.print(" (absorbed: ");
      while (e.hasMoreElements()) {
        System.out.print(e.nextElement());
      }
      System.out.print(")");
    }
    if (isReplacer && replaced != null) {
      System.out.print(" (replaced: " + replaced + ")");
    }
    System.out.println();
  }
}