UndoManagerDetails.java Source code

Java tutorial

Introduction

Here is the source code for UndoManagerDetails.java

Source

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();
    }
}