1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
/*
* @(#)DelayUndoManager.java 12/31/2007
*
* Copyright 2002 - 2007 JIDE Software Inc. All rights reserved.
*/
package com.jidesoft.swing;
import javax.swing.*;
import javax.swing.undo.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* An undo manager that aggregates UndoableEdits into one CompoundEdit if they are executed very close to each other. By
* default, the gap is 500 ms. You can control it by passing in a different number in the constructor.
*/
public class DelayUndoManager extends UndoManager {
private static final long serialVersionUID = -2910365359251677780L;
private int _delay = 500;
private CompoundEdit _cache;
private static final Logger LOGGER = Logger.getLogger(DelayUndoManager.class.getName());
protected Timer _timer;
public DelayUndoManager() {
}
public DelayUndoManager(int delay) {
_delay = delay;
}
/**
* Checks if there are pending edits in the DelayUndoManager.
*
* @return true if there are pending edits. Otherwise false.
*/
public boolean isCacheEmpty() {
return _cache == null;
}
/**
* Commits the cached edit.
*/
public synchronized void commitCache() {
if (_cache != null) {
_cache.end();
addEditWithoutCaching();
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Commit cache: " + _cache);
}
_cache = null;
}
}
/**
* Calls super.addEdit without caching.
*/
public void addEditWithoutCaching() {
DelayUndoManager.super.addEdit(_cache);
}
public synchronized void discardCache() {
_cache = null;
if (_timer != null) {
_timer.stop();
_timer = null;
}
}
@Override
public synchronized boolean addEdit(UndoableEdit anEdit) {
if (_cache == null) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Create cache: " + anEdit);
}
_cache = new CompoundEdit();
boolean ret = _cache.addEdit(anEdit);
if (ret) {
_timer = new Timer(_delay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
commitCache();
}
});
_timer.setRepeats(false);
_timer.start();
}
return ret;
}
else {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Add to cache: " + anEdit);
}
if (_timer != null) {
_timer.restart();
}
return _cache.addEdit(anEdit);
}
}
/**
* Override to commit the cache before checking undo status.
*
* @return true if an undo operation would be successful now, false otherwise
*/
@Override
public synchronized boolean canUndo() {
commitCache();
return super.canUndo();
}
/**
* Override to commit the cache before checking redo status.
*
* @return true if an redo operation would be successful now, false otherwise
*/
@Override
public synchronized boolean canRedo() {
commitCache();
return super.canRedo();
}
/**
* Override to commit the cache before undo.
*
* @throws CannotUndoException
*/
@Override
public synchronized void undo() throws CannotUndoException {
commitCache();
super.undo();
}
/**
* Override to commit the cache before redo.
*
* @throws CannotRedoException
*/
@Override
public synchronized void redo() throws CannotRedoException {
commitCache();
super.redo();
}
@Override
public synchronized void discardAllEdits() {
super.discardAllEdits();
discardCache();
}
}
|