1 15 16 package swingwtx.swing.undo; 17 18 import swingwtx.swing.event.UndoableEditEvent; 19 import swingwtx.swing.event.UndoableEditListener; 20 21 import java.util.Iterator ; 22 23 29 public class UndoManager extends CompoundEdit 30 implements UndoableEditListener 31 { 32 int limit = 100; 33 int indexOfNextAdd = 0; 34 35 public UndoManager() 36 { 37 super(); 38 } 39 40 public synchronized void setLimit(int limit) { this.limit = limit; } 41 public synchronized int getLimit() { return limit; } 42 43 44 public synchronized void discardAllEdits() 45 { 46 Iterator iterator = edits.iterator(); 48 while (iterator.hasNext()) 49 { 50 UndoableEdit undoableEdit = (UndoableEdit) iterator.next(); 51 undoableEdit.die(); 52 } 53 54 edits.clear(); 56 } 57 58 protected void undoTo(UndoableEdit undoableEdit) throws CannotUndoException 59 { 60 do 61 { 62 indexOfNextAdd--; 64 65 if (indexOfNextAdd < 0) 67 { 68 indexOfNextAdd = 0; 69 throw new CannotUndoException(); 70 } 71 72 UndoableEdit curUndoableEdit = (UndoableEdit) edits.get(indexOfNextAdd); 74 curUndoableEdit.undo(); 75 76 if (curUndoableEdit == undoableEdit) 78 break; 79 80 } while (true); 81 } 82 83 public synchronized void undo() throws CannotUndoException 84 { 85 if (isInProgress()) 86 { 87 UndoableEdit edit = editToBeUndone(); 88 if (edit == null) throw new CannotUndoException(); 89 undoTo(edit); 90 } 91 else 92 { 93 super.undo(); 94 } 95 } 96 97 protected void redoTo(UndoableEdit undoableEdit) throws CannotRedoException 98 { 99 int size = edits.size(); 100 101 do 102 { 103 UndoableEdit curUndoableEdit = (UndoableEdit) edits.get(indexOfNextAdd); 105 curUndoableEdit.redo(); 106 107 if (curUndoableEdit == undoableEdit) 109 break; 110 111 indexOfNextAdd++; 113 114 if (indexOfNextAdd >= size) 116 { 117 indexOfNextAdd = 0; 118 throw new CannotRedoException(); 119 } 120 121 } while (true); 122 } 123 124 public synchronized void redo() throws CannotRedoException 125 { 126 if (isInProgress()) 127 { 128 UndoableEdit edit = editToBeRedone(); 129 if (edit == null) throw new CannotRedoException(); 130 redoTo(edit); 131 } 132 else 133 { 134 super.redo(); 135 } 136 } 137 138 protected void trimEdits(int from, int to) 139 { 140 if (from <= to) 141 { 142 int itemsToRemove = to - from + 1; 144 while (itemsToRemove > 0) 145 { 146 ((UndoableEdit)edits.get(from)).die(); 148 edits.remove(from); 149 150 itemsToRemove--; 152 } 153 154 if (indexOfNextAdd > to) 156 indexOfNextAdd = indexOfNextAdd - to + from - 1; 157 else if (indexOfNextAdd >= from) 158 indexOfNextAdd = from; 159 } 160 } 161 162 protected void trimForLimit() 163 { 164 int size = edits.size(); 165 166 if (limit > 0 && size > limit) 167 { 168 int middle = limit / 2; 170 int high = Math.min(indexOfNextAdd+middle-1, size-1); 171 172 trimEdits(high+1, size-1); 173 trimEdits(0, high-limit); 174 } 175 } 176 177 public synchronized void undoOrRedo() throws CannotRedoException, CannotUndoException 178 { 179 if (indexOfNextAdd == edits.size()) undo(); 180 else redo(); 181 } 182 183 public synchronized boolean canUndoOrRedo() 184 { 185 return false; 186 } 187 188 public synchronized boolean canUndo() 189 { 190 boolean canUndo = false; 191 192 if (isInProgress()) 194 { 195 UndoableEdit undoableEdit = editToBeUndone(); 196 if (undoableEdit != null) canUndo = undoableEdit.canUndo(); 197 } 198 else 200 { 201 canUndo = super.canUndo(); 202 } 203 204 return canUndo; 205 } 206 207 public synchronized boolean canRedo() 208 { 209 boolean canRedo = false; 210 211 if (isInProgress()) 213 { 214 UndoableEdit undoableEdit = editToBeRedone(); 215 if (undoableEdit != null) canRedo = undoableEdit.canRedo(); 216 } 217 else 219 { 220 canRedo = super.canRedo(); 221 } 222 223 return canRedo; 224 } 225 226 public synchronized boolean addEdit(UndoableEdit undoableEdit) 227 { 228 boolean success; 229 230 trimEdits(indexOfNextAdd, edits.size()-1); 232 233 success = super.addEdit(undoableEdit); 235 indexOfNextAdd = edits.size(); 236 237 trimForLimit(); 239 240 return success; 241 } 242 243 public synchronized void end() 244 { 245 super.end(); 246 trimEdits(indexOfNextAdd, edits.size()-1); 247 } 248 249 public synchronized String getUndoOrRedoPresentationName() 250 { 251 if (indexOfNextAdd == edits.size()) return getUndoPresentationName(); 252 else return getRedoPresentationName(); 253 } 254 255 public synchronized String getUndoPresentationName() 257 { 258 String presentationName; 259 260 if (isInProgress()) 262 { 263 UndoableEdit undoableEdit = editToBeUndone(); 264 if (undoableEdit != null) 265 presentationName = undoableEdit.getUndoPresentationName(); 266 else presentationName = "Undo"; 267 } 268 else 269 presentationName = super.getUndoPresentationName(); 270 271 return presentationName; 272 } 273 274 public synchronized String getRedoPresentationName() 276 { 277 String presentationName; 278 279 if (isInProgress()) 281 { 282 UndoableEdit undoableEdit = editToBeUndone(); 283 if (undoableEdit != null) 284 presentationName = undoableEdit.getRedoPresentationName(); 285 else 286 presentationName = "Redo"; 287 } 288 else 289 presentationName = super.getRedoPresentationName(); 290 291 return presentationName; 292 } 293 294 public void undoableEditHappened(UndoableEditEvent undoableEditEvent) 295 { 296 addEdit(undoableEditEvent.getEdit()); 297 } 298 299 300 protected UndoableEdit editToBeUndone() 301 { 302 UndoableEdit undoableEdit = null; 303 304 for (int i = indexOfNextAdd-1; i >= 0; i--) 306 { 307 UndoableEdit curUndoableEdit = (UndoableEdit) edits.get(i); 308 309 if (curUndoableEdit.isSignificant()) 311 { 312 undoableEdit = curUndoableEdit; 313 break; 314 } 315 } 316 317 return undoableEdit; 318 } 319 320 321 protected UndoableEdit editToBeRedone() 322 { 323 UndoableEdit undoableEdit = null; 324 325 for (int i = indexOfNextAdd; i<edits.size(); i++) 327 { 328 UndoableEdit curUndoableEdit = (UndoableEdit) edits.get(i); 329 330 if (curUndoableEdit.isSignificant()) 332 { 333 undoableEdit = curUndoableEdit; 334 break; 335 } 336 } 337 338 return undoableEdit; 339 } 340 } 341 | Popular Tags |