package de.synolo.lib.fw.cmd; import java.util.Stack; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyBooleanWrapper; public class UndoManager { private Stack undoStack; private Stack redoStack; private ReadOnlyBooleanWrapper undoAvailalableProperty = new ReadOnlyBooleanWrapper(false); private ReadOnlyBooleanWrapper redoAvailalableProperty = new ReadOnlyBooleanWrapper(false); private int max; public UndoManager(int maxCommands) { this.max = maxCommands; this.undoStack = new Stack<>(); this.redoStack = new Stack<>(); } public UndoManager() { this(100); } public int getMaxCommands() { return this.max; } public void setMaxCommands(int max) { this.max = max; } public boolean isUndoAvailable() { return !this.undoStack.isEmpty(); } public ReadOnlyBooleanProperty undoAvailableProperty() { return this.undoAvailalableProperty.getReadOnlyProperty(); } public boolean isRedoAvailable() { return !this.redoStack.isEmpty(); } public ReadOnlyBooleanProperty redoAvailableProperty() { return this.redoAvailalableProperty.getReadOnlyProperty(); } public void execute(Command cmd) { Command last = null; if(!this.undoStack.isEmpty() && (last = this.undoStack.peek()) != null) { if(last.isCollapsable(cmd)) { last.collapse(cmd); return; }else { this.redoStack.clear(); this.undoStack.push(cmd); } }else if(cmd.isUndoable()) { this.redoStack.clear(); this.undoStack.push(cmd); } if(this.undoStack.size() > this.max) { this.undoStack.remove(0); } cmd.execute(); update(); } public void undo() { System.out.println("undo..."); if(isUndoAvailable()) { Command cmd = this.undoStack.pop(); this.redoStack.push(cmd); cmd.undo(); } update(); } public void redo() { if(isRedoAvailable()) { Command cmd = this.redoStack.pop(); this.undoStack.push(cmd); cmd.redo(); } update(); } private void update() { this.undoAvailalableProperty.set(isUndoAvailable()); this.redoAvailalableProperty.set(isRedoAvailable()); System.out.println(this.undoStack); } }