1 /* 2 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing.undo; 27 28 import javax.swing.event.*; 29 import java.util.*; 30 31 /** 32 * A support class used for managing <code>UndoableEdit</code> listeners. 33 * 34 * @author Ray Ryan 35 */ 36 public 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 listeners.toArray(new UndoableEditListener[0]); 93 } 94 95 /** 96 * Called only from <code>postEdit</code> and <code>endUpdate</code>. Calls 97 * <code>undoableEditHappened</code> in all listeners. No synchronization 98 * is performed here, since the two calling methods are synchronized. 99 */ 100 protected void _postEdit(UndoableEdit e) { 101 UndoableEditEvent ev = new UndoableEditEvent(realSource, e); 102 Enumeration cursor = ((Vector)listeners.clone()).elements(); 103 while (cursor.hasMoreElements()) { 104 ((UndoableEditListener)cursor.nextElement()). 105 undoableEditHappened(ev); 106 } 107 } 108 109 /** 110 * DEADLOCK WARNING: Calling this method may call 111 * <code>undoableEditHappened</code> in all listeners. 112 * It is unwise to call this method from one of its listeners. 113 */ 114 public synchronized void postEdit(UndoableEdit e) { 115 if (updateLevel == 0) { 116 _postEdit(e); 117 } else { 118 // PENDING(rjrjr) Throw an exception if this fails? 119 compoundEdit.addEdit(e); 120 } 121 } 122 123 /** 124 * Returns the update level value. 125 * 126 * @return an integer representing the update level 127 */ 128 public int getUpdateLevel() { 129 return updateLevel; 130 } 131 132 /** 133 * 134 */ 135 public synchronized void beginUpdate() { 136 if (updateLevel == 0) { 137 compoundEdit = createCompoundEdit(); 138 } 139 updateLevel++; 140 } 141 142 /** 143 * Called only from <code>beginUpdate</code>. 144 * Exposed here for subclasses' use. 145 */ 146 protected CompoundEdit createCompoundEdit() { 147 return new CompoundEdit(); 148 } 149 150 /** 151 * DEADLOCK WARNING: Calling this method may call 152 * <code>undoableEditHappened</code> in all listeners. 153 * It is unwise to call this method from one of its listeners. 154 */ 155 public synchronized void endUpdate() { 156 updateLevel--; 157 if (updateLevel == 0) { 158 compoundEdit.end(); 159 _postEdit(compoundEdit); 160 compoundEdit = null; 161 } 162 } 163 164 /** 165 * Returns a string that displays and identifies this 166 * object's properties. 167 * 168 * @return a <code>String</code> representation of this object 169 */ 170 public String toString() { 171 return super.toString() + 172 " updateLevel: " + updateLevel + 173 " listeners: " + listeners + 174 " compoundEdit: " + compoundEdit; 175 } 176 }