1 7 8 package javax.swing.undo; 9 10 import javax.swing.event.*; 11 import javax.swing.UIManager ; 12 import java.util.*; 13 14 38 public class UndoManager extends CompoundEdit implements UndoableEditListener { 39 int indexOfNextAdd; 40 int limit; 41 42 public UndoManager() { 43 super(); 44 indexOfNextAdd = 0; 45 limit = 100; 46 edits.ensureCapacity(limit); 47 } 48 49 56 public synchronized int getLimit() { 57 return limit; 58 } 59 60 64 public synchronized void discardAllEdits() { 65 Enumeration cursor = edits.elements(); 66 while (cursor.hasMoreElements()) { 67 UndoableEdit e = (UndoableEdit )cursor.nextElement(); 68 e.die(); 69 } 70 edits = new Vector(limit); 71 indexOfNextAdd = 0; 72 } 76 77 81 protected void trimForLimit() { 82 if (limit >= 0) { 83 int size = edits.size(); 84 89 if (size > limit) { 90 int halfLimit = limit/2; 91 int keepFrom = indexOfNextAdd - 1 - halfLimit; 92 int keepTo = indexOfNextAdd - 1 + halfLimit; 93 94 99 if (keepTo - keepFrom + 1 > limit) { 100 keepFrom++; 101 } 102 103 107 if (keepFrom < 0) { 108 keepTo -= keepFrom; 109 keepFrom = 0; 110 } 111 if (keepTo >= size) { 112 int delta = size - keepTo - 1; 113 keepTo += delta; 114 keepFrom += delta; 115 } 116 117 trimEdits(keepTo+1, size-1); 119 trimEdits(0, keepFrom-1); 120 } 121 } 122 } 123 124 128 protected void trimEdits(int from, int to) { 129 if (from <= to) { 130 for (int i = to; from <= i; i--) { 133 UndoableEdit e = (UndoableEdit )edits.elementAt(i); 134 e.die(); 137 edits.removeElementAt(i); 140 } 141 142 if (indexOfNextAdd > to) { 143 indexOfNextAdd -= to-from+1; 145 } else if (indexOfNextAdd >= from) { 146 indexOfNextAdd = from; 148 } 149 150 } 152 } 153 154 162 public synchronized void setLimit(int l) { 163 if (!inProgress) throw new RuntimeException ("Attempt to call UndoManager.setLimit() after UndoManager.end() has been called"); 164 limit = l; 165 trimForLimit(); 166 } 167 168 169 173 protected UndoableEdit editToBeUndone() { 174 int i = indexOfNextAdd; 175 while (i > 0) { 176 UndoableEdit edit = (UndoableEdit )edits.elementAt(--i); 177 if (edit.isSignificant()) { 178 return edit; 179 } 180 } 181 182 return null; 183 } 184 185 189 protected UndoableEdit editToBeRedone() { 190 int count = edits.size(); 191 int i = indexOfNextAdd; 192 193 while (i < count) { 194 UndoableEdit edit = (UndoableEdit )edits.elementAt(i++); 195 if (edit.isSignificant()) { 196 return edit; 197 } 198 } 199 200 return null; 201 } 202 203 206 protected void undoTo(UndoableEdit edit) throws CannotUndoException { 207 boolean done = false; 208 while (!done) { 209 UndoableEdit next = (UndoableEdit )edits.elementAt(--indexOfNextAdd); 210 next.undo(); 211 done = next == edit; 212 } 213 } 214 215 218 protected void redoTo(UndoableEdit edit) throws CannotRedoException { 219 boolean done = false; 220 while (!done) { 221 UndoableEdit next = (UndoableEdit )edits.elementAt(indexOfNextAdd++); 222 next.redo(); 223 done = next == edit; 224 } 225 } 226 227 235 public synchronized void undoOrRedo() throws CannotRedoException , 236 CannotUndoException { 237 if (indexOfNextAdd == edits.size()) { 238 undo(); 239 } else { 240 redo(); 241 } 242 } 243 244 251 public synchronized boolean canUndoOrRedo() { 252 if (indexOfNextAdd == edits.size()) { 253 return canUndo(); 254 } else { 255 return canRedo(); 256 } 257 } 258 259 269 public synchronized void undo() throws CannotUndoException { 270 if (inProgress) { 271 UndoableEdit edit = editToBeUndone(); 272 if (edit == null) { 273 throw new CannotUndoException (); 274 } 275 undoTo(edit); 276 } else { 277 super.undo(); 278 } 279 } 280 281 285 public synchronized boolean canUndo() { 286 if (inProgress) { 287 UndoableEdit edit = editToBeUndone(); 288 return edit != null && edit.canUndo(); 289 } else { 290 return super.canUndo(); 291 } 292 } 293 294 305 public synchronized void redo() throws CannotRedoException { 306 if (inProgress) { 307 UndoableEdit edit = editToBeRedone(); 308 if (edit == null) { 309 throw new CannotRedoException (); 310 } 311 redoTo(edit); 312 } else { 313 super.redo(); 314 } 315 } 316 317 321 public synchronized boolean canRedo() { 322 if (inProgress) { 323 UndoableEdit edit = editToBeRedone(); 324 return edit != null && edit.canRedo(); 325 } else { 326 return super.canRedo(); 327 } 328 } 329 330 344 public synchronized boolean addEdit(UndoableEdit anEdit) { 345 boolean retVal; 346 347 trimEdits(indexOfNextAdd, edits.size()-1); 350 351 retVal = super.addEdit(anEdit); 352 if (inProgress) { 353 retVal = true; 354 } 355 356 indexOfNextAdd = edits.size(); 361 362 trimForLimit(); 364 365 return retVal; 366 } 367 368 369 379 public synchronized void end() { 380 super.end(); 381 this.trimEdits(indexOfNextAdd, edits.size()-1); 382 } 383 384 389 public synchronized String getUndoOrRedoPresentationName() { 390 if (indexOfNextAdd == edits.size()) { 391 return getUndoPresentationName(); 392 } else { 393 return getRedoPresentationName(); 394 } 395 } 396 397 408 public synchronized String getUndoPresentationName() { 409 if (inProgress) { 410 if (canUndo()) { 411 return editToBeUndone().getUndoPresentationName(); 412 } else { 413 return UIManager.getString("AbstractUndoableEdit.undoText"); 414 } 415 } else { 416 return super.getUndoPresentationName(); 417 } 418 } 419 420 431 public synchronized String getRedoPresentationName() { 432 if (inProgress) { 433 if (canRedo()) { 434 return editToBeRedone().getRedoPresentationName(); 435 } else { 436 return UIManager.getString("AbstractUndoableEdit.redoText"); 437 } 438 } else { 439 return super.getRedoPresentationName(); 440 } 441 } 442 443 449 public void undoableEditHappened(UndoableEditEvent e) { 450 addEdit(e.getEdit()); 451 } 452 453 459 public String toString() { 460 return super.toString() + " limit: " + limit + 461 " indexOfNextAdd: " + indexOfNextAdd; 462 } 463 } 464 | Popular Tags |