001: /*
002: * Copyright (c) 2000, Jacob Smullyan.
003: *
004: * This is part of SkunkDAV, a WebDAV client. See http://skunkdav.sourceforge.net/
005: * for the latest version.
006: *
007: * SkunkDAV is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License as published
009: * by the Free Software Foundation; either version 2, or (at your option)
010: * any later version.
011: *
012: * SkunkDAV is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with SkunkDAV; see the file COPYING. If not, write to the Free
019: * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
020: * 02111-1307, USA.
021: */
022:
023: package org.skunk.dav.client.gui.editor;
024:
025: import java.util.ArrayList;
026: import javax.swing.event.ChangeEvent;
027: import javax.swing.event.ChangeListener;
028: import javax.swing.event.UndoableEditEvent;
029: import javax.swing.event.UndoableEditListener;
030: import javax.swing.undo.CannotRedoException;
031: import javax.swing.undo.CannotUndoException;
032: import javax.swing.undo.UndoableEdit;
033: import javax.swing.undo.UndoableEditSupport;
034: import javax.swing.undo.UndoManager;
035:
036: /**
037: * the conventional extension of UndoManager to support
038: * monitoring its state with a change listener.
039: */
040: public class DAVEditorUndoManager extends UndoManager {
041: private ArrayList listeners = new ArrayList();
042: private ChangeEvent changeEvent = new ChangeEvent(this );
043: private boolean inUpdate = false;
044: private HarkeningUndoSupport support = new HarkeningUndoSupport(
045: this );
046:
047: public synchronized void setLimit(int limit) {
048: super .setLimit(limit);
049: fireChangeEvent();
050: }
051:
052: public void undoableEditHappened(UndoableEditEvent ugh) {
053: if (!inUpdate)
054: super .undoableEditHappened(ugh);
055: else
056: support.undoableEditHappened(ugh);
057: }
058:
059: public synchronized void discardAllEdits() {
060: super .discardAllEdits();
061: fireChangeEvent();
062: }
063:
064: public synchronized void undo() throws CannotUndoException {
065: super .undo();
066: fireChangeEvent();
067: }
068:
069: public synchronized void redo() throws CannotRedoException {
070: super .redo();
071: fireChangeEvent();
072: }
073:
074: public void beginUpdate() {
075: inUpdate = true;
076: support.beginUpdate();
077: }
078:
079: public void endUpdate() {
080: inUpdate = false;
081: support.endUpdate();
082: }
083:
084: public synchronized boolean addEdit(UndoableEdit edit) {
085: boolean added = super .addEdit(edit);
086: fireChangeEvent();
087: return added;
088: }
089:
090: public void addChangeListener(ChangeListener chigger) {
091: listeners.add(chigger);
092: }
093:
094: public void removeChangeListener(ChangeListener chigger) {
095: listeners.remove(chigger);
096: }
097:
098: protected void fireChangeEvent() {
099: //by obtaining an array, I avoid any concurrent modification exceptions
100: //that might be thrown if a listener removes itself when called.
101: Object[] listenerArray = listeners.toArray();
102: for (int i = 0; i < listenerArray.length; i++)
103: ((ChangeListener) listenerArray[i])
104: .stateChanged(changeEvent);
105: }
106:
107: /**
108: * a filter which receives UndoableEditEvents and then farms them out to the undo manager,
109: * after optionally coalescing them into CompoundEdits
110: */
111: class HarkeningUndoSupport extends UndoableEditSupport implements
112: UndoableEditListener {
113: HarkeningUndoSupport(UndoableEditListener l) {
114: this .addUndoableEditListener(l);
115: }
116:
117: public void undoableEditHappened(UndoableEditEvent ugh) {
118: postEdit(ugh.getEdit());
119: }
120: }
121: }
|