/* * @(#)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(); } }