001 /*
002 * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.swing.undo;
027
028 import javax.swing.event.*;
029 import java.util.*;
030
031 /**
032 * A support class used for managing <code>UndoableEdit</code> listeners.
033 *
034 * @author Ray Ryan
035 * @version 1.27 05/05/07
036 */
037 public class UndoableEditSupport {
038 protected int updateLevel;
039 protected CompoundEdit compoundEdit;
040 protected Vector<UndoableEditListener> listeners;
041 protected Object realSource;
042
043 /**
044 * Constructs an <code>UndoableEditSupport</code> object.
045 */
046 public UndoableEditSupport() {
047 this (null);
048 }
049
050 /**
051 * Constructs an <code>UndoableEditSupport</code> object.
052 *
053 * @param r an <code>Object</code>
054 */
055 public UndoableEditSupport(Object r) {
056 realSource = r == null ? this : r;
057 updateLevel = 0;
058 compoundEdit = null;
059 listeners = new Vector<UndoableEditListener>();
060 }
061
062 /**
063 * Registers an <code>UndoableEditListener</code>.
064 * The listener is notified whenever an edit occurs which can be undone.
065 *
066 * @param l an <code>UndoableEditListener</code> object
067 * @see #removeUndoableEditListener
068 */
069 public synchronized void addUndoableEditListener(
070 UndoableEditListener l) {
071 listeners.addElement(l);
072 }
073
074 /**
075 * Removes an <code>UndoableEditListener</code>.
076 *
077 * @param l the <code>UndoableEditListener</code> object to be removed
078 * @see #addUndoableEditListener
079 */
080 public synchronized void removeUndoableEditListener(
081 UndoableEditListener l) {
082 listeners.removeElement(l);
083 }
084
085 /**
086 * Returns an array of all the <code>UndoableEditListener</code>s added
087 * to this UndoableEditSupport with addUndoableEditListener().
088 *
089 * @return all of the <code>UndoableEditListener</code>s added or an empty
090 * array if no listeners have been added
091 * @since 1.4
092 */
093 public synchronized UndoableEditListener[] getUndoableEditListeners() {
094 return (UndoableEditListener[]) (listeners
095 .toArray(new UndoableEditListener[0]));
096 }
097
098 /**
099 * Called only from <code>postEdit</code> and <code>endUpdate</code>. Calls
100 * <code>undoableEditHappened</code> in all listeners. No synchronization
101 * is performed here, since the two calling methods are synchronized.
102 */
103 protected void _postEdit(UndoableEdit e) {
104 UndoableEditEvent ev = new UndoableEditEvent(realSource, e);
105 Enumeration cursor = ((Vector) listeners.clone()).elements();
106 while (cursor.hasMoreElements()) {
107 ((UndoableEditListener) cursor.nextElement())
108 .undoableEditHappened(ev);
109 }
110 }
111
112 /**
113 * DEADLOCK WARNING: Calling this method may call
114 * <code>undoableEditHappened</code> in all listeners.
115 * It is unwise to call this method from one of its listeners.
116 */
117 public synchronized void postEdit(UndoableEdit e) {
118 if (updateLevel == 0) {
119 _postEdit(e);
120 } else {
121 // PENDING(rjrjr) Throw an exception if this fails?
122 compoundEdit.addEdit(e);
123 }
124 }
125
126 /**
127 * Returns the update level value.
128 *
129 * @return an integer representing the update level
130 */
131 public int getUpdateLevel() {
132 return updateLevel;
133 }
134
135 /**
136 *
137 */
138 public synchronized void beginUpdate() {
139 if (updateLevel == 0) {
140 compoundEdit = createCompoundEdit();
141 }
142 updateLevel++;
143 }
144
145 /**
146 * Called only from <code>beginUpdate</code>.
147 * Exposed here for subclasses' use.
148 */
149 protected CompoundEdit createCompoundEdit() {
150 return new CompoundEdit();
151 }
152
153 /**
154 * DEADLOCK WARNING: Calling this method may call
155 * <code>undoableEditHappened</code> in all listeners.
156 * It is unwise to call this method from one of its listeners.
157 */
158 public synchronized void endUpdate() {
159 updateLevel--;
160 if (updateLevel == 0) {
161 compoundEdit.end();
162 _postEdit(compoundEdit);
163 compoundEdit = null;
164 }
165 }
166
167 /**
168 * Returns a string that displays and identifies this
169 * object's properties.
170 *
171 * @return a <code>String</code> representation of this object
172 */
173 public String toString() {
174 return super .toString() + " updateLevel: " + updateLevel
175 + " listeners: " + listeners + " compoundEdit: "
176 + compoundEdit;
177 }
178 }
|