1 /* 2 * Copyright (c) 1997, 2003, 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.event; 27 28 import java.util.EventObject; 29 import javax.swing.tree.TreePath; 30 31 32 /** 33 * Encapsulates information describing changes to a tree model, and 34 * used to notify tree model listeners of the change. 35 * For more information and examples see 36 * <a 37 href="http://java.sun.com/docs/books/tutorial/uiswing/events/treemodellistener.html">How to Write a Tree Model Listener</a>, 38 * a section in <em>The Java Tutorial.</em> 39 * <p> 40 * <strong>Warning:</strong> 41 * Serialized objects of this class will not be compatible with 42 * future Swing releases. The current serialization support is 43 * appropriate for short term storage or RMI between applications running 44 * the same version of Swing. As of 1.4, support for long term storage 45 * of all JavaBeans<sup><font size="-2">TM</font></sup> 46 * has been added to the <code>java.beans</code> package. 47 * Please see {@link java.beans.XMLEncoder}. 48 * 49 * @author Rob Davis 50 * @author Ray Ryan 51 * @author Scott Violet 52 */ 53 public class TreeModelEvent extends EventObject { 54 /** Path to the parent of the nodes that have changed. */ 55 protected TreePath path; 56 /** Indices identifying the position of where the children were. */ 57 protected int[] childIndices; 58 /** Children that have been removed. */ 59 protected Object[] children; 60 61 /** 62 * Used to create an event when nodes have been changed, inserted, or 63 * removed, identifying the path to the parent of the modified items as 64 * an array of Objects. All of the modified objects are siblings which are 65 * direct descendents (not grandchildren) of the specified parent. 66 * The positions at which the inserts, deletes, or changes occurred are 67 * specified by an array of <code>int</code>. The indexes in that array 68 * must be in order, from lowest to highest. 69 * <p> 70 * For changes, the indexes in the model correspond exactly to the indexes 71 * of items currently displayed in the UI. As a result, it is not really 72 * critical if the indexes are not in their exact order. But after multiple 73 * inserts or deletes, the items currently in the UI no longer correspond 74 * to the items in the model. It is therefore critical to specify the 75 * indexes properly for inserts and deletes. 76 * <p> 77 * For inserts, the indexes represent the <i>final</i> state of the tree, 78 * after the inserts have occurred. Since the indexes must be specified in 79 * order, the most natural processing methodology is to do the inserts 80 * starting at the lowest index and working towards the highest. Accumulate 81 * a Vector of <code>Integer</code> objects that specify the 82 * insert-locations as you go, then convert the Vector to an 83 * array of <code>int</code> to create the event. When the postition-index 84 * equals zero, the node is inserted at the beginning of the list. When the 85 * position index equals the size of the list, the node is "inserted" at 86 * (appended to) the end of the list. 87 * <p> 88 * For deletes, the indexes represent the <i>initial</i> state of the tree, 89 * before the deletes have occurred. Since the indexes must be specified in 90 * order, the most natural processing methodology is to use a delete-counter. 91 * Start by initializing the counter to zero and start work through the 92 * list from lowest to higest. Every time you do a delete, add the current 93 * value of the delete-counter to the index-position where the delete occurred, 94 * and append the result to a Vector of delete-locations, using 95 * <code>addElement()</code>. Then increment the delete-counter. The index 96 * positions stored in the Vector therefore reflect the effects of all previous 97 * deletes, so they represent each object's position in the initial tree. 98 * (You could also start at the highest index and working back towards the 99 * 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, int[] childIndices, 129 Object[] children) 130 { 131 this(source, (path == null) ? null : new TreePath(path), childIndices, children); 132 } 133 134 /** 135 * Used to create an event when nodes have been changed, inserted, or 136 * removed, identifying the path to the parent of the modified items as 137 * a TreePath object. For more information on how to specify the indexes 138 * and objects, see 139 * <code>TreeModelEvent(Object,Object[],int[],Object[])</code>. 140 * 141 * @param source the Object responsible for generating the event (typically 142 * the creator of the event object passes <code>this</code> 143 * for its value) 144 * @param path a TreePath object that identifies the path to the 145 * parent of the modified item(s) 146 * @param childIndices an array of <code>int</code> that specifies the 147 * index values of the modified items 148 * @param children an array of Object containing the inserted, removed, or 149 * changed objects 150 * 151 * @see #TreeModelEvent(Object,Object[],int[],Object[]) 152 */ 153 public TreeModelEvent(Object source, TreePath path, int[] childIndices, 154 Object[] children) 155 { 156 super(source); 157 this.path = path; 158 this.childIndices = childIndices; 159 this.children = children; 160 } 161 162 /** 163 * Used to create an event when the node structure has changed in some way, 164 * identifying the path to the root of a modified subtree as an array of 165 * Objects. A structure change event might involve nodes swapping position, 166 * for example, or it might encapsulate multiple inserts and deletes in the 167 * subtree stemming from the node, where the changes may have taken place at 168 * different levels of the subtree. 169 * <blockquote> 170 * <b>Note:</b><br> 171 * JTree collapses all nodes under the specified node, so that only its 172 * immediate children are visible. 173 * </blockquote> 174 * 175 * @param source the Object responsible for generating the event (typically 176 * the creator of the event object passes <code>this</code> 177 * for its value) 178 * @param path an array of Object identifying the path to the root of the 179 * modified subtree, where the first element of the array is 180 * the object stored at the root node and the last element 181 * is the object stored at the changed node 182 * @see TreePath 183 */ 184 public TreeModelEvent(Object source, Object[] path) 185 { 186 this(source, (path == null) ? null : new TreePath(path)); 187 } 188 189 /** 190 * Used to create an event when the node structure has changed in some way, 191 * identifying the path to the root of the modified subtree as a TreePath 192 * object. For more information on this event specification, see 193 * <code>TreeModelEvent(Object,Object[])</code>. 194 * 195 * @param source the Object responsible for generating the event (typically 196 * the creator of the event object passes <code>this</code> 197 * for its value) 198 * @param path a TreePath object that identifies the path to the 199 * change. In the DefaultTreeModel, 200 * this object contains an array of user-data objects, 201 * but a subclass of TreePath could use some totally 202 * different mechanism -- for example, a node ID number 203 * 204 * @see #TreeModelEvent(Object,Object[]) 205 */ 206 public TreeModelEvent(Object source, TreePath path) 207 { 208 super(source); 209 this.path = path; 210 this.childIndices = new int[0]; 211 } 212 213 /** 214 * For all events, except treeStructureChanged, 215 * returns the parent of the changed nodes. 216 * For treeStructureChanged events, returns the ancestor of the 217 * structure that has changed. This and 218 * <code>getChildIndices</code> are used to get a list of the effected 219 * nodes. 220 * <p> 221 * The one exception to this is a treeNodesChanged event that is to 222 * identify the root, in which case this will return the root 223 * and <code>getChildIndices</code> will return null. 224 * 225 * @return the TreePath used in identifying the changed nodes. 226 * @see TreePath#getLastPathComponent 227 */ 228 public TreePath getTreePath() { return path; } 229 230 /** 231 * Convenience method to get the array of objects from the TreePath 232 * instance that this event wraps. 233 * 234 * @return an array of Objects, where the first Object is the one 235 * stored at the root and the last object is the one 236 * stored at the node identified by the path 237 */ 238 public Object[] getPath() { 239 if(path != null) 240 return path.getPath(); 241 return null; 242 } 243 244 /** 245 * Returns the objects that are children of the node identified by 246 * <code>getPath</code> at the locations specified by 247 * <code>getChildIndices</code>. If this is a removal event the 248 * returned objects are no longer children of the parent node. 249 * 250 * @return an array of Object containing the children specified by 251 * the event 252 * @see #getPath 253 * @see #getChildIndices 254 */ 255 public Object[] getChildren() { 256 if(children != null) { 257 int cCount = children.length; 258 Object[] retChildren = new Object[cCount]; 259 260 System.arraycopy(children, 0, retChildren, 0, cCount); 261 return retChildren; 262 } 263 return null; 264 } 265 266 /** 267 * Returns the values of the child indexes. If this is a removal event 268 * the indexes point to locations in the initial list where items 269 * were removed. If it is an insert, the indices point to locations 270 * in the final list where the items were added. For node changes, 271 * the indices point to the locations of the modified nodes. 272 * 273 * @return an array of <code>int</code> containing index locations for 274 * the children specified by the event 275 */ 276 public int[] getChildIndices() { 277 if(childIndices != null) { 278 int cCount = childIndices.length; 279 int[] retArray = new int[cCount]; 280 281 System.arraycopy(childIndices, 0, retArray, 0, cCount); 282 return retArray; 283 } 284 return null; 285 } 286 287 /** 288 * Returns a string that displays and identifies this object's 289 * properties. 290 * 291 * @return a String representation of this object 292 */ 293 public String toString() { 294 StringBuffer retBuffer = new StringBuffer(); 295 296 retBuffer.append(getClass().getName() + " " + 297 Integer.toString(hashCode())); 298 if(path != null) 299 retBuffer.append(" path " + path); 300 if(childIndices != null) { 301 retBuffer.append(" indices [ "); 302 for(int counter = 0; counter < childIndices.length; counter++) 303 retBuffer.append(Integer.toString(childIndices[counter])+ " "); 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 }