1 /* 2 * Copyright (c) 1997, 2014, 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://docs.oracle.com/javase/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™ 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 @SuppressWarnings("serial") // Same-version serialization only 54 public class TreeModelEvent extends EventObject { 55 /** Path to the parent of the nodes that have changed. */ 56 protected TreePath path; 57 /** Indices identifying the position of where the children were. */ 58 protected int[] childIndices; 59 /** Children that have been removed. */ 60 protected Object[] children; 61 62 /** 63 * Used to create an event when nodes have been changed, inserted, or 64 * removed, identifying the path to the parent of the modified items as 65 * an array of Objects. All of the modified objects are siblings which are 66 * direct descendents (not grandchildren) of the specified parent. 67 * The positions at which the inserts, deletes, or changes occurred are 68 * specified by an array of <code>int</code>. The indexes in that array 69 * must be in order, from lowest to highest. 70 * <p> 71 * For changes, the indexes in the model correspond exactly to the indexes 72 * of items currently displayed in the UI. As a result, it is not really 73 * critical if the indexes are not in their exact order. But after multiple 74 * inserts or deletes, the items currently in the UI no longer correspond 75 * to the items in the model. It is therefore critical to specify the 76 * indexes properly for inserts and deletes. 77 * <p> 78 * For inserts, the indexes represent the <i>final</i> state of the tree, 79 * after the inserts have occurred. Since the indexes must be specified in 80 * order, the most natural processing methodology is to do the inserts 81 * starting at the lowest index and working towards the highest. Accumulate 82 * a Vector of <code>Integer</code> objects that specify the 83 * insert-locations as you go, then convert the Vector to an 84 * array of <code>int</code> to create the event. When the postition-index 85 * equals zero, the node is inserted at the beginning of the list. When the 86 * position index equals the size of the list, the node is "inserted" at 87 * (appended to) the end of the list. 88 * <p> 89 * For deletes, the indexes represent the <i>initial</i> state of the tree, 90 * before the deletes have occurred. Since the indexes must be specified in 91 * order, the most natural processing methodology is to use a delete-counter. 92 * Start by initializing the counter to zero and start work through the 93 * list from lowest to highest. Every time you do a delete, add the current 94 * value of the delete-counter to the index-position where the delete occurred, 95 * and append the result to a Vector of delete-locations, using 96 * <code>addElement()</code>. Then increment the delete-counter. The index 97 * positions stored in the Vector therefore reflect the effects of all previous 98 * deletes, so they represent each object's position in the initial tree. 99 * (You could also start at the highest index and working back towards the 100 * lowest, accumulating a Vector of delete-locations as you go using the 101 * <code>insertElementAt(Integer, 0)</code>.) However you produce the Vector 102 * of initial-positions, you then need to convert the Vector of <code>Integer</code> 103 * objects to an array of <code>int</code> to create the event. 104 * <p> 105 * <b>Notes:</b><ul style="list-style-type:none"> 106 * <li>Like the <code>insertNodeInto</code> method in the 107 * <code>DefaultTreeModel</code> class, <code>insertElementAt</code> 108 * appends to the <code>Vector</code> when the index matches the size 109 * of the vector. So you can use <code>insertElementAt(Integer, 0)</code> 110 * even when the vector is empty.</li> 111 * <li>To create a node changed event for the root node, specify the parent 112 * and the child indices as <code>null</code>.</li> 113 * </ul> 114 * 115 * @param source the Object responsible for generating the event (typically 116 * the creator of the event object passes <code>this</code> 117 * for its value) 118 * @param path an array of Object identifying the path to the 119 * parent of the modified item(s), where the first element 120 * of the array is the Object stored at the root node and 121 * the last element is the Object stored at the parent node 122 * @param childIndices an array of <code>int</code> that specifies the 123 * index values of the removed items. The indices must be 124 * in sorted order, from lowest to highest 125 * @param children an array of Object containing the inserted, removed, or 126 * changed objects 127 * @see TreePath 128 */ 129 public TreeModelEvent(Object source, Object[] path, int[] childIndices, 130 Object[] children) 131 { 132 this(source, (path == null) ? null : new TreePath(path), childIndices, children); 133 } 134 135 /** 136 * Used to create an event when nodes have been changed, inserted, or 137 * removed, identifying the path to the parent of the modified items as 138 * a TreePath object. For more information on how to specify the indexes 139 * and objects, see 140 * <code>TreeModelEvent(Object,Object[],int[],Object[])</code>. 141 * 142 * @param source the Object responsible for generating the event (typically 143 * the creator of the event object passes <code>this</code> 144 * for its value) 145 * @param path a TreePath object that identifies the path to the 146 * parent of the modified item(s) 147 * @param childIndices an array of <code>int</code> that specifies the 148 * index values of the modified items 149 * @param children an array of Object containing the inserted, removed, or 150 * changed objects 151 * 152 * @see #TreeModelEvent(Object,Object[],int[],Object[]) 153 */ 154 public TreeModelEvent(Object source, TreePath path, int[] childIndices, 155 Object[] children) 156 { 157 super(source); 158 this.path = path; 159 this.childIndices = childIndices; 160 this.children = children; 161 } 162 163 /** 164 * Used to create an event when the node structure has changed in some way, 165 * identifying the path to the root of a modified subtree as an array of 166 * Objects. A structure change event might involve nodes swapping position, 167 * for example, or it might encapsulate multiple inserts and deletes in the 168 * subtree stemming from the node, where the changes may have taken place at 169 * different levels of the subtree. 170 * <blockquote> 171 * <b>Note:</b><br> 172 * JTree collapses all nodes under the specified node, so that only its 173 * immediate children are visible. 174 * </blockquote> 175 * 176 * @param source the Object responsible for generating the event (typically 177 * the creator of the event object passes <code>this</code> 178 * for its value) 179 * @param path an array of Object identifying the path to the root of the 180 * modified subtree, where the first element of the array is 181 * the object stored at the root node and the last element 182 * is the object stored at the changed node 183 * @see TreePath 184 */ 185 public TreeModelEvent(Object source, Object[] path) 186 { 187 this(source, (path == null) ? null : new TreePath(path)); 188 } 189 190 /** 191 * Used to create an event when the node structure has changed in some way, 192 * identifying the path to the root of the modified subtree as a TreePath 193 * object. For more information on this event specification, see 194 * <code>TreeModelEvent(Object,Object[])</code>. 195 * 196 * @param source the Object responsible for generating the event (typically 197 * the creator of the event object passes <code>this</code> 198 * for its value) 199 * @param path a TreePath object that identifies the path to the 200 * change. In the DefaultTreeModel, 201 * this object contains an array of user-data objects, 202 * but a subclass of TreePath could use some totally 203 * different mechanism -- for example, a node ID number 204 * 205 * @see #TreeModelEvent(Object,Object[]) 206 */ 207 public TreeModelEvent(Object source, TreePath path) 208 { 209 super(source); 210 this.path = path; 211 this.childIndices = new int[0]; 212 } 213 214 /** 215 * For all events, except treeStructureChanged, 216 * returns the parent of the changed nodes. 217 * For treeStructureChanged events, returns the ancestor of the 218 * structure that has changed. This and 219 * <code>getChildIndices</code> are used to get a list of the effected 220 * nodes. 221 * <p> 222 * The one exception to this is a treeNodesChanged event that is to 223 * identify the root, in which case this will return the root 224 * and <code>getChildIndices</code> will return null. 225 * 226 * @return the TreePath used in identifying the changed nodes. 227 * @see TreePath#getLastPathComponent 228 */ 229 public TreePath getTreePath() { return path; } 230 231 /** 232 * Convenience method to get the array of objects from the TreePath 233 * instance that this event wraps. 234 * 235 * @return an array of Objects, where the first Object is the one 236 * stored at the root and the last object is the one 237 * stored at the node identified by the path 238 */ 239 public Object[] getPath() { 240 if(path != null) 241 return path.getPath(); 242 return null; 243 } 244 245 /** 246 * Returns the objects that are children of the node identified by 247 * <code>getPath</code> at the locations specified by 248 * <code>getChildIndices</code>. If this is a removal event the 249 * returned objects are no longer children of the parent node. 250 * 251 * @return an array of Object containing the children specified by 252 * the event 253 * @see #getPath 254 * @see #getChildIndices 255 */ 256 public Object[] getChildren() { 257 if(children != null) { 258 int cCount = children.length; 259 Object[] retChildren = new Object[cCount]; 260 261 System.arraycopy(children, 0, retChildren, 0, cCount); 262 return retChildren; 263 } 264 return null; 265 } 266 267 /** 268 * Returns the values of the child indexes. If this is a removal event 269 * the indexes point to locations in the initial list where items 270 * were removed. If it is an insert, the indices point to locations 271 * in the final list where the items were added. For node changes, 272 * the indices point to the locations of the modified nodes. 273 * 274 * @return an array of <code>int</code> containing index locations for 275 * the children specified by the event 276 */ 277 public int[] getChildIndices() { 278 if(childIndices != null) { 279 int cCount = childIndices.length; 280 int[] retArray = new int[cCount]; 281 282 System.arraycopy(childIndices, 0, retArray, 0, cCount); 283 return retArray; 284 } 285 return null; 286 } 287 288 /** 289 * Returns a string that displays and identifies this object's 290 * properties. 291 * 292 * @return a String representation of this object 293 */ 294 public String toString() { 295 StringBuilder sb = new StringBuilder(); 296 297 sb.append(getClass().getName()).append(' ').append(Integer.toString(hashCode())); 298 if(path != null) 299 sb.append(" path ").append(path); 300 if(childIndices != null) { 301 sb.append(" indices [ "); 302 for(int counter = 0; counter < childIndices.length; counter++) 303 sb.append(Integer.toString(childIndices[counter])).append(' '); 304 sb.append(']'); 305 } 306 if(children != null) { 307 sb.append(" children [ "); 308 for(int counter = 0; counter < children.length; counter++) 309 sb.append(children[counter]).append(' '); 310 sb.append(']'); 311 } 312 return sb.toString(); 313 } 314 }