1 33 34 package edu.rice.cs.drjava.model.definitions; 35 36 import javax.swing.undo.*; 37 import javax.swing.SwingUtilities ; 38 import java.util.LinkedList ; 39 40 import edu.rice.cs.drjava.model.GlobalEventNotifier; 41 import edu.rice.cs.util.swing.Utilities; 42 43 50 public class CompoundUndoManager extends UndoManager { 51 52 private static volatile int counter = 0; 53 54 private final int id; 55 56 57 private final LinkedList <CompoundEdit> _compoundEdits; 58 59 60 private final LinkedList <Integer > _keys; 61 62 63 private volatile int _nextKey; 64 65 66 private volatile UndoableEdit _savePoint; 67 68 69 private final GlobalEventNotifier _notifier; 70 71 72 public CompoundUndoManager(GlobalEventNotifier notifier) { 73 super(); 74 counter++; 75 id = counter; 76 _compoundEdits = new LinkedList <CompoundEdit>(); 77 _keys = new LinkedList <Integer >(); 78 _nextKey = 0; 79 _savePoint = null; 80 _notifier = notifier; 81 } 82 83 86 public synchronized int startCompoundEdit() { 87 _compoundEdits.add(0, new CompoundEdit()); 88 _keys.add(0, new Integer (_nextKey)); 89 if (_nextKey < Integer.MAX_VALUE) _nextKey++; 90 else _nextKey = Integer.MIN_VALUE; 91 return _keys.get(0).intValue(); 92 } 93 94 97 public synchronized void endLastCompoundEdit() { 98 if (_keys.size() == 0) return; 99 endCompoundEdit(_keys.get(0).intValue()); 101 } 102 103 106 public synchronized void endCompoundEdit(int key) { 107 if (_keys.size() == 0) return; 108 109 if (_keys.get(0) == key) { 110 _keys.remove(0); 111 final CompoundEdit ce = _compoundEdits.remove(0); 112 113 ce.end(); 114 if (ce.canUndo()) { 115 if (! _compoundEditInProgress()) { 116 super.addEdit(ce); 117 _notifyUndoHappened(); 118 } 119 else _compoundEdits.get(0).addEdit(ce); 120 } 121 } 122 else throw new IllegalStateException ("Improperly nested compound edits."); 123 } 124 125 128 public synchronized CompoundEdit getLastCompoundEdit() { return _compoundEdits.get(0); } 129 130 133 public UndoableEdit getNextUndo() { return editToBeUndone(); } 134 135 138 public UndoableEdit getNextRedo() { return editToBeRedone(); } 139 140 144 public synchronized boolean addEdit(UndoableEdit e) { 145 if (_compoundEditInProgress()) { 146 return _compoundEdits.get(0).addEdit(e); 148 } 149 else { 150 boolean result = super.addEdit(e); 151 _notifyUndoHappened(); 152 return result; 153 } 154 } 155 156 159 public synchronized boolean _compoundEditInProgress() { return ! _compoundEdits.isEmpty(); } 160 161 164 public synchronized boolean canUndo() { return _compoundEditInProgress() || super.canUndo(); } 165 166 169 public synchronized String getUndoPresentationName() { 170 if (_compoundEditInProgress()) return "Undo Previous Command"; 171 return super.getUndoPresentationName(); 172 } 173 174 175 public synchronized void undo() { 176 endCompoundEdit(); 177 super.undo(); 178 } 179 180 185 public synchronized void undo(int key) { 186 if (_keys.get(0) == key) { 187 final CompoundEdit ce = _compoundEdits.get(0); 188 _compoundEdits.remove(0); 189 _keys.remove(0); 190 191 192 SwingUtilities.invokeLater(new Runnable () { 193 public void run() { 194 ce.end(); 195 ce.undo(); 196 ce.die(); 197 } 198 }); } 200 else throw new IllegalArgumentException ("Bad undo key " + key + "!"); 201 } 202 203 204 public synchronized void redo() { 205 endCompoundEdit(); super.redo(); 207 } 208 209 211 private void _notifyUndoHappened() { 212 SwingUtilities.invokeLater(new Runnable () { public void run() { _notifier.undoableEditHappened(); } }); 214 } 215 216 217 private synchronized void endCompoundEdit() { 218 Integer [] keys = _keys.toArray(new Integer [_keys.size()]); if (_compoundEditInProgress()) { 220 for (int key: keys) endCompoundEdit(key); 221 } 222 } 223 224 225 public synchronized void documentSaved() { 226 endCompoundEdit(); 227 _savePoint = editToBeUndone(); 228 } 230 231 234 public synchronized boolean isModified() { 235 return editToBeUndone() != _savePoint; 237 } 238 239 public String toString() { return "(CompoundUndoManager: " + id + ")"; } 240 241 242 } 246 | Popular Tags |