aspect Undo { public static boolean Program.DEBUG_UNDO = false; private static boolean Program.RECORDING_CHANGES = false; public static long Program.undoActionCount = 0; public static boolean Program.isRecordingASTChanges() { return RECORDING_CHANGES; } public static void Program.startRecordingASTChangesAndFlush() { RECORDING_CHANGES = true; undoStack = new Stack(); } public static void Program.stopRecordingASTChangesAndFlush() { RECORDING_CHANGES = false; undoStack = new Stack(); } // CheckPoints private static ASTUndoCheckPoint Program.lastCheckPoint = null; public static ASTUndoCheckPoint Program.createASTUndoCheckPoint() { if (!isRecordingASTChanges()) startRecordingASTChangesAndFlush(); ASTUndoCheckPoint cp = new ASTUndoCheckPoint(); lastCheckPoint = cp; undoStack.push(cp); return cp; } class ASTUndoCheckPoint extends ASTModification { @Override public void undo() { } @Override public void redo() { } @Override public String toString() { return "ASTUndoCheckPoint"; } } // General ASTModification public abstract class ASTModification { public abstract void undo(); public abstract void redo(); } /* * Undo Stack * * problem with non-static stack: creating new subtrees that are not attached to the * main tree with a Program root node -> no undo in the new subtree */ private static Stack Program.undoStack = new Stack(); public static Stack Program.getUndoStack() { return undoStack; } public static Stack Program.cloneUndoStack() { return (Stack) (undoStack != null ? undoStack.clone() : null); } // Undo-ing public static void Program.addUndoAction(ASTModification action) { undoStack.push(action); undoActionCount++; } public static void Program.undoAll() { undoUntil(null); } public static void Program.undoUntilLastCheckPoint() { undoUntil(lastCheckPoint); } public static void Program.undoUntil(ASTUndoCheckPoint cp) { if (DEBUG_UNDO) System.out.print("Undoing " + undoStack.size() + " actions... "); while (!undoStack.isEmpty()) { ASTModification mod = undoStack.pop(); mod.undo(); if (cp != null && cp.equals(mod)) break; } if (DEBUG_UNDO) System.out.println("done."); if (DEBUG_UNDO) System.out.println("Total undo actions: " + undoActionCount); } }