Lines 93-99
Link Here
|
93 |
|
93 |
|
94 |
/** An undo manager which fires a change event each time it consumes a new undoable edit. |
94 |
/** An undo manager which fires a change event each time it consumes a new undoable edit. |
95 |
*/ |
95 |
*/ |
96 |
public static class Manager extends UndoManager implements UndoRedo { |
96 |
public static class Manager extends UndoGroupManager implements UndoRedo { |
97 |
static final long serialVersionUID = 6721367974521509720L; |
97 |
static final long serialVersionUID = 6721367974521509720L; |
98 |
|
98 |
|
99 |
private final ChangeSupport cs = new ChangeSupport(this); |
99 |
private final ChangeSupport cs = new ChangeSupport(this); |
Lines 251-255
Link Here
|
251 |
public String getRedoPresentationName() { |
251 |
public String getRedoPresentationName() { |
252 |
return ""; // NOI18N |
252 |
return ""; // NOI18N |
253 |
} |
253 |
} |
|
|
254 |
} |
255 |
|
256 |
/** <tt>UndoGroupManager</tt> extends {@link UndoManager} |
257 |
* and allows explicit control of what |
258 |
* <tt>UndoableEdit</tt>s are coalesced into compound edits, |
259 |
* rather than using the rules defined by the edits themselves. |
260 |
* Other than the default usage, special handling is initiated by invoking |
261 |
* <tt>beginUndoGroup()</tt>. |
262 |
* <p> |
263 |
* Three use cases are supported. |
264 |
* </p> |
265 |
* <ol> |
266 |
* <li> Default behavior is defined by {@link UndoManager}.</li> |
267 |
* <li> <tt>UnddoableEdit</tt>s issued between {@link #beginUndoGroup} |
268 |
* and {@link endUndoGroup} are placed into a single {@link CompoundEdit}. |
269 |
* Thus <tt>undo()</tt> and <tt>redo()</tt> treat them atomically.</li> |
270 |
* <li> Use {@link commitUndoGroup} to place any accumulated |
271 |
* <tt>UndoableEdit</tt>s into a <tt>CompoundEdit</tt>; |
272 |
* an application could do this at strategic points, such as EndOfLine |
273 |
* input or cursor movement. In this way, the application can accumulate |
274 |
* large chunks, but this behavior would not be enabled unless |
275 |
* <tt>beginUndoGroup</tt> is first invoked.</li> |
276 |
* </ol> |
277 |
* Note that the semantics of {@link UndoManager} are preserved at all |
278 |
* times, so certain methods, such as <tt>undo()</tt>, automatically issue |
279 |
* <tt>commitUndoGroup()</tt>. |
280 |
* @see UndoManager |
281 |
*/ |
282 |
public static class UndoGroupManager extends UndoManager { |
283 |
/** signals that edits should be accumulated */ |
284 |
private boolean buildUndoGroup; |
285 |
/** accumulate edits here in undoGroup */ |
286 |
private CompoundEdit undoGroup; |
287 |
|
288 |
/** |
289 |
* Direct this <tt>UndoGroupManager</tt> to begin coalescing any |
290 |
* <tt>UndoableEdit</tt>s that are added into a <tt>CompoundEdit</tt>. |
291 |
* <p>If edits are already being coalesced and some have been |
292 |
* accumulated, they are commited as an atomic group and a new |
293 |
* group is started. |
294 |
* @see #addEdit |
295 |
* @see #endUndoGroup |
296 |
* @see #commitUndoGroup |
297 |
*/ |
298 |
public synchronized void beginUndoGroup() { |
299 |
commitUndoGroup(); |
300 |
buildUndoGroup = true; |
301 |
} |
302 |
|
303 |
/** |
304 |
* Direct this <tt>UndoGroupManager</tt> to stop coalescing edits. |
305 |
* {@link #commitUndoGroup} is invoked to save accumulated edits as |
306 |
* an atomic group. |
307 |
* Until <tt>beginUndoGroupManager</tt> is invoked, |
308 |
* received <tt>UndoableEdit</tt>s are added singly. |
309 |
* <p> |
310 |
* This has no effect if edits are not being coalesced, for example |
311 |
* if <tt>beginUndoGroup</tt> has not been called. |
312 |
* @see #commitUndoGroup |
313 |
*/ |
314 |
public synchronized void endUndoGroup() { |
315 |
buildUndoGroup = false; |
316 |
commitUndoGroup(); |
317 |
} |
318 |
|
319 |
/** |
320 |
* Commit any accumulated <tt>UndoableEdit</tt>s as an atomic |
321 |
* <tt>undo</tt>/<tt>redo</tt> group. {@link CompoundEdit#end} |
322 |
* is invoked on the <tt>CompoundEdit</tt> and it is added as a single |
323 |
* <tt>UndoableEdit</tt> to this <tt>UndoManager</tt>. |
324 |
* <p> |
325 |
* If edits are currently being coalesced, a new undo group is started. |
326 |
* This has no effect if edits are not being coalesced, for example |
327 |
* <tt>beginUndoGroup</tt> has not been called. |
328 |
*/ |
329 |
public synchronized void commitUndoGroup() { |
330 |
if(undoGroup == null) { |
331 |
return; |
332 |
} |
333 |
// super.addEdit may end up in this.addEdit, |
334 |
// so buildUndoGroup must be false |
335 |
boolean restoreBuildUndoGroup = buildUndoGroup; |
336 |
buildUndoGroup = false; |
337 |
|
338 |
undoGroup.end(); |
339 |
super.addEdit(undoGroup); |
340 |
undoGroup = null; |
341 |
|
342 |
buildUndoGroup = restoreBuildUndoGroup; |
343 |
} |
344 |
|
345 |
|
346 |
/** |
347 |
* If this <tt>UndoManager</tt> is coalescing edits then add |
348 |
* <tt>anEdit</tt> to the accumulating <tt>CompoundEdit</tt>. |
349 |
* Otherwise, add it to this UndoManager. In either case the |
350 |
* edit is saved for later <tt>undo</tt> or <tt>redo</tt>. |
351 |
* @return {@inheritDoc} |
352 |
* @see #beginUndoGroup |
353 |
* @see #endUndoGroup |
354 |
* @see #commitUndoGroup |
355 |
*/ |
356 |
public synchronized boolean addEdit(UndoableEdit anEdit) { |
357 |
if(!isInProgress()) |
358 |
return false; |
359 |
if(buildUndoGroup) { |
360 |
if(undoGroup == null) |
361 |
undoGroup = new CompoundEdit(); |
362 |
return undoGroup.addEdit(anEdit); |
363 |
} else { |
364 |
return super.addEdit(anEdit); |
365 |
} |
366 |
} |
367 |
|
368 |
/** {@inheritDoc} */ |
369 |
public synchronized void discardAllEdits() { |
370 |
commitUndoGroup(); |
371 |
super.discardAllEdits(); |
372 |
} |
373 |
|
374 |
// |
375 |
// TODO: limits |
376 |
// |
377 |
|
378 |
/** {@inheritDoc} */ |
379 |
public synchronized void undoOrRedo() { |
380 |
commitUndoGroup(); |
381 |
super.undoOrRedo(); |
382 |
} |
383 |
|
384 |
/** {@inheritDoc} */ |
385 |
public synchronized boolean canUndoOrRedo() { |
386 |
if(undoGroup != null) |
387 |
return true; |
388 |
return super.canUndoOrRedo(); |
389 |
} |
390 |
|
391 |
/** {@inheritDoc} */ |
392 |
public synchronized void undo() { |
393 |
commitUndoGroup(); |
394 |
super.undo(); |
395 |
} |
396 |
|
397 |
/** {@inheritDoc} */ |
398 |
public synchronized boolean canUndo() { |
399 |
if(undoGroup != null) |
400 |
return true; |
401 |
return super.canUndo(); |
402 |
} |
403 |
|
404 |
/** {@inheritDoc} */ |
405 |
public synchronized void redo() { |
406 |
if(undoGroup != null) |
407 |
throw new CannotRedoException(); |
408 |
super.redo(); |
409 |
} |
410 |
|
411 |
/** {@inheritDoc} */ |
412 |
public synchronized boolean canRedo() { |
413 |
if(undoGroup != null) |
414 |
return false; |
415 |
return super.canRedo(); |
416 |
} |
417 |
|
418 |
/** {@inheritDoc} */ |
419 |
public synchronized void end() { |
420 |
commitUndoGroup(); |
421 |
super.end(); |
422 |
} |
423 |
|
424 |
/** {@inheritDoc} */ |
425 |
public synchronized String getUndoOrRedoPresentationName() { |
426 |
if(undoGroup != null) |
427 |
return undoGroup.getUndoPresentationName(); |
428 |
return super.getUndoOrRedoPresentationName(); |
429 |
} |
430 |
|
431 |
/** {@inheritDoc} */ |
432 |
public synchronized String getUndoPresentationName() { |
433 |
if(undoGroup != null) |
434 |
return undoGroup.getUndoPresentationName(); |
435 |
return super.getUndoPresentationName(); |
436 |
} |
437 |
|
438 |
/** {@inheritDoc} */ |
439 |
public synchronized String getRedoPresentationName() { |
440 |
if(undoGroup != null) |
441 |
return undoGroup.getRedoPresentationName(); |
442 |
return super.getRedoPresentationName(); |
443 |
} |
444 |
|
445 |
/** {@inheritDoc} */ |
446 |
public boolean isSignificant() { |
447 |
if(undoGroup != null && undoGroup.isSignificant()) { |
448 |
return true; |
449 |
} |
450 |
return super.isSignificant(); |
451 |
} |
452 |
|
453 |
/** {@inheritDoc} */ |
454 |
public synchronized void die() { |
455 |
commitUndoGroup(); |
456 |
super.die(); |
457 |
} |
458 |
|
459 |
/** {@inheritDoc} */ |
460 |
public String getPresentationName() { |
461 |
if(undoGroup != null) |
462 |
return undoGroup.getPresentationName(); |
463 |
return super.getPresentationName(); |
464 |
} |
465 |
|
466 |
// The protected methods are only accessed from |
467 |
// synchronized methods that commitUndoGroup, |
468 |
// they do not need to be in this class |
469 |
/*protected UndoableEdit editToBeUndone() { |
470 |
if(undoGroup != null) |
471 |
return null; |
472 |
return super.editToBeUndone(); |
473 |
} |
474 |
|
475 |
protected UndoableEdit editToBeRedone() { |
476 |
if(undoGroup != null) |
477 |
return null; |
478 |
return super.editToBeRedone(); |
479 |
} |
480 |
|
481 |
protected void undoTo(UndoableEdit edit) { |
482 |
if(undoGroup != null) |
483 |
throw new CannotUndoException(); |
484 |
super.undoTo(edit); |
485 |
} |
486 |
|
487 |
protected void redoTo(UndoableEdit edit) { |
488 |
if(undoGroup != null) |
489 |
throw new CannotRedoException(); |
490 |
super.redoTo(edit); |
491 |
}*/ |
254 |
} |
492 |
} |
255 |
} |
493 |
} |