001 /*
002 * Copyright 1997-2003 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.event;
027
028 import java.util.EventObject;
029 import javax.swing.tree.TreePath;
030
031 /**
032 * Encapsulates information describing changes to a tree model, and
033 * used to notify tree model listeners of the change.
034 * For more information and examples see
035 * <a
036 href="http://java.sun.com/docs/books/tutorial/uiswing/events/treemodellistener.html">How to Write a Tree Model Listener</a>,
037 * a section in <em>The Java Tutorial.</em>
038 * <p>
039 * <strong>Warning:</strong>
040 * Serialized objects of this class will not be compatible with
041 * future Swing releases. The current serialization support is
042 * appropriate for short term storage or RMI between applications running
043 * the same version of Swing. As of 1.4, support for long term storage
044 * of all JavaBeans<sup><font size="-2">TM</font></sup>
045 * has been added to the <code>java.beans</code> package.
046 * Please see {@link java.beans.XMLEncoder}.
047 *
048 * @version 1.40 05/05/07
049 * @author Rob Davis
050 * @author Ray Ryan
051 * @author Scott Violet
052 */
053 public class TreeModelEvent extends EventObject {
054 /** Path to the parent of the nodes that have changed. */
055 protected TreePath path;
056 /** Indices identifying the position of where the children were. */
057 protected int[] childIndices;
058 /** Children that have been removed. */
059 protected Object[] children;
060
061 /**
062 * Used to create an event when nodes have been changed, inserted, or
063 * removed, identifying the path to the parent of the modified items as
064 * an array of Objects. All of the modified objects are siblings which are
065 * direct descendents (not grandchildren) of the specified parent.
066 * The positions at which the inserts, deletes, or changes occurred are
067 * specified by an array of <code>int</code>. The indexes in that array
068 * must be in order, from lowest to highest.
069 * <p>
070 * For changes, the indexes in the model correspond exactly to the indexes
071 * of items currently displayed in the UI. As a result, it is not really
072 * critical if the indexes are not in their exact order. But after multiple
073 * inserts or deletes, the items currently in the UI no longer correspond
074 * to the items in the model. It is therefore critical to specify the
075 * indexes properly for inserts and deletes.
076 * <p>
077 * For inserts, the indexes represent the <i>final</i> state of the tree,
078 * after the inserts have occurred. Since the indexes must be specified in
079 * order, the most natural processing methodology is to do the inserts
080 * starting at the lowest index and working towards the highest. Accumulate
081 * a Vector of <code>Integer</code> objects that specify the
082 * insert-locations as you go, then convert the Vector to an
083 * array of <code>int</code> to create the event. When the postition-index
084 * equals zero, the node is inserted at the beginning of the list. When the
085 * position index equals the size of the list, the node is "inserted" at
086 * (appended to) the end of the list.
087 * <p>
088 * For deletes, the indexes represent the <i>initial</i> state of the tree,
089 * before the deletes have occurred. Since the indexes must be specified in
090 * order, the most natural processing methodology is to use a delete-counter.
091 * Start by initializing the counter to zero and start work through the
092 * list from lowest to higest. Every time you do a delete, add the current
093 * value of the delete-counter to the index-position where the delete occurred,
094 * and append the result to a Vector of delete-locations, using
095 * <code>addElement()</code>. Then increment the delete-counter. The index
096 * positions stored in the Vector therefore reflect the effects of all previous
097 * deletes, so they represent each object's position in the initial tree.
098 * (You could also start at the highest index and working back towards the
099 * lowest, accumulating a Vector of delete-locations as you go using the
100 * <code>insertElementAt(Integer, 0)</code>.) However you produce the Vector
101 * of initial-positions, you then need to convert the Vector of <code>Integer</code>
102 * objects to an array of <code>int</code> to create the event.
103 * <p>
104 * <b>Notes:</b><ul>
105 * <li>Like the <code>insertNodeInto</code> method in the
106 * <code>DefaultTreeModel</code> class, <code>insertElementAt</code>
107 * appends to the <code>Vector</code> when the index matches the size
108 * of the vector. So you can use <code>insertElementAt(Integer, 0)</code>
109 * even when the vector is empty.
110 * <ul>To create a node changed event for the root node, specify the parent
111 * and the child indices as <code>null</code>.
112 * </ul>
113 *
114 * @param source the Object responsible for generating the event (typically
115 * the creator of the event object passes <code>this</code>
116 * for its value)
117 * @param path an array of Object identifying the path to the
118 * parent of the modified item(s), where the first element
119 * of the array is the Object stored at the root node and
120 * the last element is the Object stored at the parent node
121 * @param childIndices an array of <code>int</code> that specifies the
122 * index values of the removed items. The indices must be
123 * in sorted order, from lowest to highest
124 * @param children an array of Object containing the inserted, removed, or
125 * changed objects
126 * @see TreePath
127 */
128 public TreeModelEvent(Object source, Object[] path,
129 int[] childIndices, Object[] children) {
130 this (source, new TreePath(path), childIndices, children);
131 }
132
133 /**
134 * Used to create an event when nodes have been changed, inserted, or
135 * removed, identifying the path to the parent of the modified items as
136 * a TreePath object. For more information on how to specify the indexes
137 * and objects, see
138 * <code>TreeModelEvent(Object,Object[],int[],Object[])</code>.
139 *
140 * @param source the Object responsible for generating the event (typically
141 * the creator of the event object passes <code>this</code>
142 * for its value)
143 * @param path a TreePath object that identifies the path to the
144 * parent of the modified item(s)
145 * @param childIndices an array of <code>int</code> that specifies the
146 * index values of the modified items
147 * @param children an array of Object containing the inserted, removed, or
148 * changed objects
149 *
150 * @see #TreeModelEvent(Object,Object[],int[],Object[])
151 */
152 public TreeModelEvent(Object source, TreePath path,
153 int[] childIndices, Object[] children) {
154 super (source);
155 this .path = path;
156 this .childIndices = childIndices;
157 this .children = children;
158 }
159
160 /**
161 * Used to create an event when the node structure has changed in some way,
162 * identifying the path to the root of a modified subtree as an array of
163 * Objects. A structure change event might involve nodes swapping position,
164 * for example, or it might encapsulate multiple inserts and deletes in the
165 * subtree stemming from the node, where the changes may have taken place at
166 * different levels of the subtree.
167 * <blockquote>
168 * <b>Note:</b><br>
169 * JTree collapses all nodes under the specified node, so that only its
170 * immediate children are visible.
171 * </blockquote>
172 *
173 * @param source the Object responsible for generating the event (typically
174 * the creator of the event object passes <code>this</code>
175 * for its value)
176 * @param path an array of Object identifying the path to the root of the
177 * modified subtree, where the first element of the array is
178 * the object stored at the root node and the last element
179 * is the object stored at the changed node
180 * @see TreePath
181 */
182 public TreeModelEvent(Object source, Object[] path) {
183 this (source, new TreePath(path));
184 }
185
186 /**
187 * Used to create an event when the node structure has changed in some way,
188 * identifying the path to the root of the modified subtree as a TreePath
189 * object. For more information on this event specification, see
190 * <code>TreeModelEvent(Object,Object[])</code>.
191 *
192 * @param source the Object responsible for generating the event (typically
193 * the creator of the event object passes <code>this</code>
194 * for its value)
195 * @param path a TreePath object that identifies the path to the
196 * change. In the DefaultTreeModel,
197 * this object contains an array of user-data objects,
198 * but a subclass of TreePath could use some totally
199 * different mechanism -- for example, a node ID number
200 *
201 * @see #TreeModelEvent(Object,Object[])
202 */
203 public TreeModelEvent(Object source, TreePath path) {
204 super (source);
205 this .path = path;
206 this .childIndices = new int[0];
207 }
208
209 /**
210 * For all events, except treeStructureChanged,
211 * returns the parent of the changed nodes.
212 * For treeStructureChanged events, returns the ancestor of the
213 * structure that has changed. This and
214 * <code>getChildIndices</code> are used to get a list of the effected
215 * nodes.
216 * <p>
217 * The one exception to this is a treeNodesChanged event that is to
218 * identify the root, in which case this will return the root
219 * and <code>getChildIndices</code> will return null.
220 *
221 * @return the TreePath used in identifying the changed nodes.
222 * @see TreePath#getLastPathComponent
223 */
224 public TreePath getTreePath() {
225 return path;
226 }
227
228 /**
229 * Convenience method to get the array of objects from the TreePath
230 * instance that this event wraps.
231 *
232 * @return an array of Objects, where the first Object is the one
233 * stored at the root and the last object is the one
234 * stored at the node identified by the path
235 */
236 public Object[] getPath() {
237 if (path != null)
238 return path.getPath();
239 return null;
240 }
241
242 /**
243 * Returns the objects that are children of the node identified by
244 * <code>getPath</code> at the locations specified by
245 * <code>getChildIndices</code>. If this is a removal event the
246 * returned objects are no longer children of the parent node.
247 *
248 * @return an array of Object containing the children specified by
249 * the event
250 * @see #getPath
251 * @see #getChildIndices
252 */
253 public Object[] getChildren() {
254 if (children != null) {
255 int cCount = children.length;
256 Object[] retChildren = new Object[cCount];
257
258 System.arraycopy(children, 0, retChildren, 0, cCount);
259 return retChildren;
260 }
261 return null;
262 }
263
264 /**
265 * Returns the values of the child indexes. If this is a removal event
266 * the indexes point to locations in the initial list where items
267 * were removed. If it is an insert, the indices point to locations
268 * in the final list where the items were added. For node changes,
269 * the indices point to the locations of the modified nodes.
270 *
271 * @return an array of <code>int</code> containing index locations for
272 * the children specified by the event
273 */
274 public int[] getChildIndices() {
275 if (childIndices != null) {
276 int cCount = childIndices.length;
277 int[] retArray = new int[cCount];
278
279 System.arraycopy(childIndices, 0, retArray, 0, cCount);
280 return retArray;
281 }
282 return null;
283 }
284
285 /**
286 * Returns a string that displays and identifies this object's
287 * properties.
288 *
289 * @return a String representation of this object
290 */
291 public String toString() {
292 StringBuffer retBuffer = new StringBuffer();
293
294 retBuffer.append(getClass().getName() + " "
295 + Integer.toString(hashCode()));
296 if (path != null)
297 retBuffer.append(" path " + path);
298 if (childIndices != null) {
299 retBuffer.append(" indices [ ");
300 for (int counter = 0; counter < childIndices.length; counter++)
301 retBuffer.append(Integer
302 .toString(childIndices[counter])
303 + " ");
304 retBuffer.append("]");
305 }
306 if (children != null) {
307 retBuffer.append(" children [ ");
308 for (int counter = 0; counter < children.length; counter++)
309 retBuffer.append(children[counter] + " ");
310 retBuffer.append("]");
311 }
312 return retBuffer.toString();
313 }
314 }
|