package com.kartoflane.superluminal2.undo; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import com.kartoflane.superluminal2.components.interfaces.Action; /** * A base class for undoable operations that change a single value. * Subclasses should override {@link #doUndo()} and {@link #doRedo()} in order * to implement the undo/redo handling.<br> * <br> * After instantiation, use {@link #setOld(Object)} and {@link #setCurrent(Object)} to set up the values * for before and after the operation, respectively. <br> * <br> * Optional callbacks can be added using {@link #setUndoCallback(Action)} and {@link #setRedoCallback(Action)}<br> * to have the undo manager perform additional tasks once the undo/redo operation itself is completed. * * @author kartoFlane * * @param <T> * type of the value that this edit handles */ @SuppressWarnings("serial") public abstract class ValueUndoableEdit<T> extends AbstractUndoableEdit { private Action undoCallback = null; private Action redoCallback = null; protected T old; protected T cur; /** * Sets the old value for this undoable edit. The {@link #undo()} method resets to this value. */ public void setOld(T old) { this.old = old; } /** * @return the old value for this undoable edit. The {@link #undo()} method resets to this value. */ public T getOld() { return old; } /** * Sets the current value for this undoable edit. The {@link #redo()} method resets to this value. */ public void setCurrent(T cur) { this.cur = cur; } /** * @return the current value for this undoable edit. The {@link #redo()} method resets to this value. */ public T getCurrent() { return cur; } /** * Override this to undo the operation represented by this edit.<br> * This method is called by {@link #undo()}. */ public void doUndo() { } /** * Override this to redo the operation represented by this edit.<br> * This method is called by {@link #redo()}. */ public void doRedo() { } /** * Executes {@link AbstractUndoableEdit#undo() super.undo()}, then the actions defined by the subclass, * and then the callback actions, if set.<br> * <br> * Override {@link #doUndo()} to implement the edit behaviour that would normally go here. */ @Override public final void undo() throws CannotUndoException { super.undo(); doUndo(); if (undoCallback != null) undoCallback.execute(); } /** * Executes {@link AbstractUndoableEdit#redo() super.redo()}, then the actions defined by the subclass, * and then the callback actions, if set.<br> * <br> * Override {@link #doRedo()} to implement the edit behaviour that would normally go here. */ @Override public final void redo() throws CannotRedoException { super.redo(); doRedo(); if (redoCallback != null) redoCallback.execute(); } /** * Adds an action that will be executed after {@link #doUndo()}.<br> * Can be null to remove the callback. */ public void setUndoCallback(Action a) { undoCallback = a; } /** * Adds an action that will be executed after {@link #doRedo()}.<br> * Can be null to remove the callback. */ public void setRedoCallback(Action a) { redoCallback = a; } public boolean isValuesEqual() { return old == null ? cur == null : old.equals(cur); } }