summaryrefslogtreecommitdiff
path: root/src/main/java/design
diff options
context:
space:
mode:
authorMichael Lizzio <mjl2396@rit.edu>2025-11-09 14:57:49 -0500
committerMichael Lizzio <mjl2396@rit.edu>2025-11-09 14:57:49 -0500
commitc8306a0794c470c282dd0c52e8cc06d68781dbc8 (patch)
treec1ab0e0a68a094e0b0c9afaa2c1d304ae662aa75 /src/main/java/design
parentac4a71e3b43370fe45e39ac4e735b88f2e284a14 (diff)
downloaddesignproject-design-6-c8306a0794c470c282dd0c52e8cc06d68781dbc8.tar.gz
designproject-design-6-c8306a0794c470c282dd0c52e8cc06d68781dbc8.tar.bz2
designproject-design-6-c8306a0794c470c282dd0c52e8cc06d68781dbc8.zip
Basic undo Mememto Pattern
Diffstat (limited to 'src/main/java/design')
-rw-r--r--src/main/java/design/model/undo/Memento.java4
-rw-r--r--src/main/java/design/model/undo/Originator.java7
-rw-r--r--src/main/java/design/model/undo/UndoManager.java91
3 files changed, 102 insertions, 0 deletions
diff --git a/src/main/java/design/model/undo/Memento.java b/src/main/java/design/model/undo/Memento.java
new file mode 100644
index 0000000..162c3f3
--- /dev/null
+++ b/src/main/java/design/model/undo/Memento.java
@@ -0,0 +1,4 @@
+package design.model.undo;
+
+public interface Memento {
+}
diff --git a/src/main/java/design/model/undo/Originator.java b/src/main/java/design/model/undo/Originator.java
new file mode 100644
index 0000000..63eac38
--- /dev/null
+++ b/src/main/java/design/model/undo/Originator.java
@@ -0,0 +1,7 @@
+package design.model.undo;
+
+public interface Originator {
+ Memento createMemento();
+
+ void restore(Memento memento);
+} \ No newline at end of file
diff --git a/src/main/java/design/model/undo/UndoManager.java b/src/main/java/design/model/undo/UndoManager.java
new file mode 100644
index 0000000..5c6a4a0
--- /dev/null
+++ b/src/main/java/design/model/undo/UndoManager.java
@@ -0,0 +1,91 @@
+package design.model.undo;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.List;
+import java.util.stream.Collectors;
+
+// Singleton caretaker that handles undo and redo stacks.
+public final class UndoManager {
+
+ private static final UndoManager INSTANCE = new UndoManager();
+
+ public static UndoManager instance() {
+ return INSTANCE;
+ }
+
+ private UndoManager() {
+ }
+
+ // Stack entry
+ private static class Entry {
+ final Originator originator;
+ final Memento memento;
+ final String label;
+
+ Entry(Originator originator, Memento memento, String label) {
+ this.originator = originator;
+ this.memento = memento;
+ this.label = label;
+ }
+ }
+
+ private final Deque<Entry> undoStack = new ArrayDeque<>();
+ private final Deque<Entry> redoStack = new ArrayDeque<>();
+
+ // Capture state
+ public void capture(Originator originator, String label) {
+ undoStack.push(new Entry(originator, originator.createMemento(), label));
+ redoStack.clear();
+ }
+
+ // Undo / Redo ops
+ public boolean canUndo() {
+ return !undoStack.isEmpty();
+ }
+
+ public boolean canRedo() {
+ return !redoStack.isEmpty();
+ }
+
+ public String peekUndoLabel() {
+ return canUndo() ? undoStack.peek().label : null;
+ }
+
+ public String peekRedoLabel() {
+ return canRedo() ? redoStack.peek().label : null;
+ }
+
+ public List<String> getUndoHistoryLabels() {
+ return undoStack.stream()
+ .map(e -> e.label)
+ .collect(Collectors.toList());
+ }
+
+ public void undo() {
+ if (!canUndo()) {
+ System.out.println("Nothing to undo.");
+ return;
+ }
+
+ Entry entry = undoStack.pop();
+ redoStack.push(new Entry(entry.originator, entry.originator.createMemento(), entry.label));
+ entry.originator.restore(entry.memento);
+ }
+
+ public void redo() {
+ if (!canRedo()) {
+ System.out.println("Nothing to redo.");
+ return;
+ }
+
+ Entry entry = redoStack.pop();
+ undoStack.push(new Entry(entry.originator, entry.originator.createMemento(), entry.label));
+ entry.originator.restore(entry.memento);
+ }
+
+ public void purge() {
+ undoStack.clear();
+ redoStack.clear();
+ }
+}