blob: 0d1d7b9f04d1fb5f3e3fbbd8d825c74eb9dbad9d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.swing.undo;
27
28import javax.swing.event.*;
29import java.util.*;
30
31/**
32 * A support class used for managing <code>UndoableEdit</code> listeners.
33 *
34 * @author Ray Ryan
35 */
36public class UndoableEditSupport {
37 protected int updateLevel;
38 protected CompoundEdit compoundEdit;
39 protected Vector<UndoableEditListener> listeners;
40 protected Object realSource;
41
42 /**
43 * Constructs an <code>UndoableEditSupport</code> object.
44 */
45 public UndoableEditSupport() {
46 this(null);
47 }
48
49 /**
50 * Constructs an <code>UndoableEditSupport</code> object.
51 *
52 * @param r an <code>Object</code>
53 */
54 public UndoableEditSupport(Object r) {
55 realSource = r == null ? this : r;
56 updateLevel = 0;
57 compoundEdit = null;
58 listeners = new Vector<UndoableEditListener>();
59 }
60
61 /**
62 * Registers an <code>UndoableEditListener</code>.
63 * The listener is notified whenever an edit occurs which can be undone.
64 *
65 * @param l an <code>UndoableEditListener</code> object
66 * @see #removeUndoableEditListener
67 */
68 public synchronized void addUndoableEditListener(UndoableEditListener l) {
69 listeners.addElement(l);
70 }
71
72 /**
73 * Removes an <code>UndoableEditListener</code>.
74 *
75 * @param l the <code>UndoableEditListener</code> object to be removed
76 * @see #addUndoableEditListener
77 */
78 public synchronized void removeUndoableEditListener(UndoableEditListener l)
79 {
80 listeners.removeElement(l);
81 }
82
83 /**
84 * Returns an array of all the <code>UndoableEditListener</code>s added
85 * to this UndoableEditSupport with addUndoableEditListener().
86 *
87 * @return all of the <code>UndoableEditListener</code>s added or an empty
88 * array if no listeners have been added
89 * @since 1.4
90 */
91 public synchronized UndoableEditListener[] getUndoableEditListeners() {
92 return (UndoableEditListener[])(listeners.toArray(
93 new UndoableEditListener[0]));
94 }
95
96 /**
97 * Called only from <code>postEdit</code> and <code>endUpdate</code>. Calls
98 * <code>undoableEditHappened</code> in all listeners. No synchronization
99 * is performed here, since the two calling methods are synchronized.
100 */
101 protected void _postEdit(UndoableEdit e) {
102 UndoableEditEvent ev = new UndoableEditEvent(realSource, e);
103 Enumeration cursor = ((Vector)listeners.clone()).elements();
104 while (cursor.hasMoreElements()) {
105 ((UndoableEditListener)cursor.nextElement()).
106 undoableEditHappened(ev);
107 }
108 }
109
110 /**
111 * DEADLOCK WARNING: Calling this method may call
112 * <code>undoableEditHappened</code> in all listeners.
113 * It is unwise to call this method from one of its listeners.
114 */
115 public synchronized void postEdit(UndoableEdit e) {
116 if (updateLevel == 0) {
117 _postEdit(e);
118 } else {
119 // PENDING(rjrjr) Throw an exception if this fails?
120 compoundEdit.addEdit(e);
121 }
122 }
123
124 /**
125 * Returns the update level value.
126 *
127 * @return an integer representing the update level
128 */
129 public int getUpdateLevel() {
130 return updateLevel;
131 }
132
133 /**
134 *
135 */
136 public synchronized void beginUpdate() {
137 if (updateLevel == 0) {
138 compoundEdit = createCompoundEdit();
139 }
140 updateLevel++;
141 }
142
143 /**
144 * Called only from <code>beginUpdate</code>.
145 * Exposed here for subclasses' use.
146 */
147 protected CompoundEdit createCompoundEdit() {
148 return new CompoundEdit();
149 }
150
151 /**
152 * DEADLOCK WARNING: Calling this method may call
153 * <code>undoableEditHappened</code> in all listeners.
154 * It is unwise to call this method from one of its listeners.
155 */
156 public synchronized void endUpdate() {
157 updateLevel--;
158 if (updateLevel == 0) {
159 compoundEdit.end();
160 _postEdit(compoundEdit);
161 compoundEdit = null;
162 }
163 }
164
165 /**
166 * Returns a string that displays and identifies this
167 * object's properties.
168 *
169 * @return a <code>String</code> representation of this object
170 */
171 public String toString() {
172 return super.toString() +
173 " updateLevel: " + updateLevel +
174 " listeners: " + listeners +
175 " compoundEdit: " + compoundEdit;
176 }
177}