// CS 349 Undo Demo import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.Field; import java.util.Observable; import javax.swing.undo.*; // A simple model that is undoable public class Model extends Observable { // Undo manager private UndoManager undoManager; // Model data private int value; private int min; private int max; Model(int value, int min, int max) { undoManager = new UndoManager(); this.value = value; this.min = min; this.max = max; } public void updateViews() { setChanged(); notifyObservers(); } public int getValue() { return value; } public void setValue(int v) { System.out.println("Model: set value to " + v); // create undoable edit UndoableEdit undoableEdit = new AbstractUndoableEdit() { // capture variables for closure final int oldValue = value; final int newValue = v; // Method that is called when we must redo the undone action public void redo() throws CannotRedoException { super.redo(); value = newValue; System.out.println("Model: redo value to " + value); setChanged(); notifyObservers(); } public void undo() throws CannotUndoException { super.undo(); value = oldValue; System.out.println("Model: undo value to " + value); setChanged(); notifyObservers(); } }; // Add this undoable edit to the undo manager undoManager.addEdit(undoableEdit); // finally, set the value and notify views value = v; setChanged(); notifyObservers(); } public void incrementValue() { System.out.println("Model: increment value "); // constrain value to valid range if (value + 1 > max) return; // create undoable edit UndoableEdit undoableEdit = new AbstractUndoableEdit() { // Method that is called when we must redo the undone action public void redo() throws CannotRedoException { super.redo(); value = value + 1; System.out.println("Model: redo value to " + value); setChanged(); notifyObservers(); } public void undo() throws CannotUndoException { super.undo(); value = value - 1; System.out.println("Model: undo value to " + value); setChanged(); notifyObservers(); } }; // Add this undoable edit to the undo manager undoManager.addEdit(undoableEdit); value = value + 1; setChanged(); notifyObservers(); } public void decrementValue() { System.out.println("Model: decrement value "); // constrain value to valid range if (value - 1 < min) return; // create undoable edit UndoableEdit undoableEdit = new AbstractUndoableEdit() { // Method that is called when we must redo the undone action public void redo() throws CannotRedoException { super.redo(); value = value - 1; System.out.println("Model: redo value to " + value); setChanged(); notifyObservers(); } public void undo() throws CannotUndoException { super.undo(); value = value + 1; System.out.println("Model: undo value to " + value); setChanged(); notifyObservers(); } }; // Add this undoable edit to the undo manager undoManager.addEdit(undoableEdit); value = value - 1; setChanged(); notifyObservers(); } // could make these settable and undoable too public int getMin() { return min; } public int getMax() { return max; } // undo and redo methods // - - - - - - - - - - - - - - public void undo() { if (canUndo()) undoManager.undo(); } public void redo() { if (canRedo()) undoManager.redo(); } public boolean canUndo() { return undoManager.canUndo(); } public boolean canRedo() { return undoManager.canRedo(); } }