/*
 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.swing.tree;

import java.util.*;
import java.beans.ConstructorProperties;
import java.io.*;
import javax.swing.event.*;

A simple tree data model that uses TreeNodes. For further information and examples that use DefaultTreeModel, see How to Use Trees in The Java Tutorial.

Warning: Serialized objects of this class will not be compatible with future Swing releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Swing. As of 1.4, support for long term storage of all JavaBeans™ has been added to the java.beans package. Please see XMLEncoder.

Author:Rob Davis, Ray Ryan, Scott Violet
/** * A simple tree data model that uses TreeNodes. * For further information and examples that use DefaultTreeModel, * see <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html">How to Use Trees</a> * in <em>The Java Tutorial.</em> * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans&trade; * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @author Rob Davis * @author Ray Ryan * @author Scott Violet */
@SuppressWarnings("serial") // Same-version serialization only public class DefaultTreeModel implements Serializable, TreeModel {
Root of the tree.
/** Root of the tree. */
protected TreeNode root;
Listeners.
/** Listeners. */
protected EventListenerList listenerList = new EventListenerList();
Determines how the isLeaf method figures out if a node is a leaf node. If true, a node is a leaf node if it does not allow children. (If it allows children, it is not a leaf node, even if no children are present.) That lets you distinguish between folder nodes and file nodes in a file system, for example.

If this value is false, then any node which has no children is a leaf node, and any node may acquire children.

See Also:
/** * Determines how the <code>isLeaf</code> method figures * out if a node is a leaf node. If true, a node is a leaf * node if it does not allow children. (If it allows * children, it is not a leaf node, even if no children * are present.) That lets you distinguish between <i>folder</i> * nodes and <i>file</i> nodes in a file system, for example. * <p> * If this value is false, then any node which has no * children is a leaf node, and any node may acquire * children. * * @see TreeNode#getAllowsChildren * @see TreeModel#isLeaf * @see #setAsksAllowsChildren */
protected boolean asksAllowsChildren;
Creates a tree in which any node can have children.
Params:
  • root – a TreeNode object that is the root of the tree
See Also:
/** * Creates a tree in which any node can have children. * * @param root a TreeNode object that is the root of the tree * @see #DefaultTreeModel(TreeNode, boolean) */
@ConstructorProperties({"root"}) public DefaultTreeModel(TreeNode root) { this(root, false); }
Creates a tree specifying whether any node can have children, or whether only certain nodes can have children.
Params:
  • root – a TreeNode object that is the root of the tree
  • asksAllowsChildren – a boolean, false if any node can have children, true if each node is asked to see if it can have children
See Also:
/** * Creates a tree specifying whether any node can have children, * or whether only certain nodes can have children. * * @param root a TreeNode object that is the root of the tree * @param asksAllowsChildren a boolean, false if any node can * have children, true if each node is asked to see if * it can have children * @see #asksAllowsChildren */
public DefaultTreeModel(TreeNode root, boolean asksAllowsChildren) { super(); this.root = root; this.asksAllowsChildren = asksAllowsChildren; }
Sets whether or not to test leafness by asking getAllowsChildren() or isLeaf() to the TreeNodes. If newvalue is true, getAllowsChildren() is messaged, otherwise isLeaf() is messaged.
Params:
  • newValue – if true, getAllowsChildren() is messaged, otherwise isLeaf() is messaged
/** * Sets whether or not to test leafness by asking getAllowsChildren() * or isLeaf() to the TreeNodes. If newvalue is true, getAllowsChildren() * is messaged, otherwise isLeaf() is messaged. * * @param newValue if true, getAllowsChildren() is messaged, otherwise * isLeaf() is messaged */
public void setAsksAllowsChildren(boolean newValue) { asksAllowsChildren = newValue; }
Tells how leaf nodes are determined.
See Also:
Returns:true if only nodes which do not allow children are leaf nodes, false if nodes which have no children (even if allowed) are leaf nodes
/** * Tells how leaf nodes are determined. * * @return true if only nodes which do not allow children are * leaf nodes, false if nodes which have no children * (even if allowed) are leaf nodes * @see #asksAllowsChildren */
public boolean asksAllowsChildren() { return asksAllowsChildren; }
Sets the root to root. A null root implies the tree is to display nothing, and is legal.
Params:
  • root – new value of tree root
/** * Sets the root to <code>root</code>. A null <code>root</code> implies * the tree is to display nothing, and is legal. * * @param root new value of tree root */
public void setRoot(TreeNode root) { Object oldRoot = this.root; this.root = root; if (root == null && oldRoot != null) { fireTreeStructureChanged(this, null); } else { nodeStructureChanged(root); } }
Returns the root of the tree. Returns null only if the tree has no nodes.
Returns: the root of the tree
/** * Returns the root of the tree. Returns null only if the tree has * no nodes. * * @return the root of the tree */
public Object getRoot() { return root; }
Returns the index of child in parent. If either the parent or child is null, returns -1.
Params:
  • parent – a note in the tree, obtained from this data source
  • child – the node we are interested in
Returns:the index of the child in the parent, or -1 if either the parent or the child is null
/** * Returns the index of child in parent. * If either the parent or child is <code>null</code>, returns -1. * @param parent a note in the tree, obtained from this data source * @param child the node we are interested in * @return the index of the child in the parent, or -1 * if either the parent or the child is <code>null</code> */
public int getIndexOfChild(Object parent, Object child) { if(parent == null || child == null) return -1; return ((TreeNode)parent).getIndex((TreeNode)child); }
Returns the child of parent at index index in the parent's child array. parent must be a node previously obtained from this data source. This should not return null if index is a valid index for parent (that is index >= 0 && index < getChildCount(parent)).
Params:
  • parent – a node in the tree, obtained from this data source
Returns: the child of parent at index index
/** * Returns the child of <I>parent</I> at index <I>index</I> in the parent's * child array. <I>parent</I> must be a node previously obtained from * this data source. This should not return null if <i>index</i> * is a valid index for <i>parent</i> (that is <i>index</i> &gt;= 0 &amp;&amp; * <i>index</i> &lt; getChildCount(<i>parent</i>)). * * @param parent a node in the tree, obtained from this data source * @return the child of <I>parent</I> at index <I>index</I> */
public Object getChild(Object parent, int index) { return ((TreeNode)parent).getChildAt(index); }
Returns the number of children of parent. Returns 0 if the node is a leaf or if it has no children. parent must be a node previously obtained from this data source.
Params:
  • parent – a node in the tree, obtained from this data source
Returns: the number of children of the node parent
/** * Returns the number of children of <I>parent</I>. Returns 0 if the node * is a leaf or if it has no children. <I>parent</I> must be a node * previously obtained from this data source. * * @param parent a node in the tree, obtained from this data source * @return the number of children of the node <I>parent</I> */
public int getChildCount(Object parent) { return ((TreeNode)parent).getChildCount(); }
Returns whether the specified node is a leaf node. The way the test is performed depends on the askAllowsChildren setting.
Params:
  • node – the node to check
See Also:
Returns:true if the node is a leaf node
/** * Returns whether the specified node is a leaf node. * The way the test is performed depends on the * <code>askAllowsChildren</code> setting. * * @param node the node to check * @return true if the node is a leaf node * * @see #asksAllowsChildren * @see TreeModel#isLeaf */
public boolean isLeaf(Object node) { if(asksAllowsChildren) return !((TreeNode)node).getAllowsChildren(); return ((TreeNode)node).isLeaf(); }
Invoke this method if you've modified the TreeNodes upon which this model depends. The model will notify all of its listeners that the model has changed.
/** * Invoke this method if you've modified the {@code TreeNode}s upon which * this model depends. The model will notify all of its listeners that the * model has changed. */
public void reload() { reload(root); }
This sets the user object of the TreeNode identified by path and posts a node changed. If you use custom user objects in the TreeModel you're going to need to subclass this and set the user object of the changed node to something meaningful.
/** * This sets the user object of the TreeNode identified by path * and posts a node changed. If you use custom user objects in * the TreeModel you're going to need to subclass this and * set the user object of the changed node to something meaningful. */
public void valueForPathChanged(TreePath path, Object newValue) { MutableTreeNode aNode = (MutableTreeNode)path.getLastPathComponent(); aNode.setUserObject(newValue); nodeChanged(aNode); }
Invoked this to insert newChild at location index in parents children. This will then message nodesWereInserted to create the appropriate event. This is the preferred way to add children as it will create the appropriate event.
Params:
  • newChild – child node to be inserted
  • parent – node to which children new node will be added
  • index – index of parent's children
/** * Invoked this to insert newChild at location index in parents children. * This will then message nodesWereInserted to create the appropriate * event. This is the preferred way to add children as it will create * the appropriate event. * * @param newChild child node to be inserted * @param parent node to which children new node will be added * @param index index of parent's children */
public void insertNodeInto(MutableTreeNode newChild, MutableTreeNode parent, int index){ parent.insert(newChild, index); int[] newIndexs = new int[1]; newIndexs[0] = index; nodesWereInserted(parent, newIndexs); }
Message this to remove node from its parent. This will message nodesWereRemoved to create the appropriate event. This is the preferred way to remove a node as it handles the event creation for you.
Params:
  • node – the node to be removed from it's parrent
/** * Message this to remove node from its parent. This will message * nodesWereRemoved to create the appropriate event. This is the * preferred way to remove a node as it handles the event creation * for you. * * @param node the node to be removed from it's parrent */
public void removeNodeFromParent(MutableTreeNode node) { MutableTreeNode parent = (MutableTreeNode)node.getParent(); if(parent == null) throw new IllegalArgumentException("node does not have a parent."); int[] childIndex = new int[1]; Object[] removedArray = new Object[1]; childIndex[0] = parent.getIndex(node); parent.remove(childIndex[0]); removedArray[0] = node; nodesWereRemoved(parent, childIndex, removedArray); }
Invoke this method after you've changed how node is to be represented in the tree.
Params:
  • node – the changed node
/** * Invoke this method after you've changed how node is to be * represented in the tree. * * @param node the changed node */
public void nodeChanged(TreeNode node) { if(listenerList != null && node != null) { TreeNode parent = node.getParent(); if(parent != null) { int anIndex = parent.getIndex(node); if(anIndex != -1) { int[] cIndexs = new int[1]; cIndexs[0] = anIndex; nodesChanged(parent, cIndexs); } } else if (node == getRoot()) { nodesChanged(node, null); } } }
Invoke this method if you've modified the TreeNodes upon which this model depends. The model will notify all of its listeners that the model has changed below the given node.
Params:
  • node – the node below which the model has changed
/** * Invoke this method if you've modified the {@code TreeNode}s upon which * this model depends. The model will notify all of its listeners that the * model has changed below the given node. * * @param node the node below which the model has changed */
public void reload(TreeNode node) { if(node != null) { fireTreeStructureChanged(this, getPathToRoot(node), null, null); } }
Invoke this method after you've inserted some TreeNodes into node. childIndices should be the index of the new elements and must be sorted in ascending order.
Params:
  • node – parent node which children count been incremented
  • childIndices – indexes of inserted children
/** * Invoke this method after you've inserted some TreeNodes into * node. childIndices should be the index of the new elements and * must be sorted in ascending order. * * @param node parent node which children count been incremented * @param childIndices indexes of inserted children */
public void nodesWereInserted(TreeNode node, int[] childIndices) { if(listenerList != null && node != null && childIndices != null && childIndices.length > 0) { int cCount = childIndices.length; Object[] newChildren = new Object[cCount]; for(int counter = 0; counter < cCount; counter++) newChildren[counter] = node.getChildAt(childIndices[counter]); fireTreeNodesInserted(this, getPathToRoot(node), childIndices, newChildren); } }
Invoke this method after you've removed some TreeNodes from node. childIndices should be the index of the removed elements and must be sorted in ascending order. And removedChildren should be the array of the children objects that were removed.
Params:
  • node – parent node which childred were removed
  • childIndices – indexes of removed childs
  • removedChildren – array of the children objects that were removed
/** * Invoke this method after you've removed some TreeNodes from * node. childIndices should be the index of the removed elements and * must be sorted in ascending order. And removedChildren should be * the array of the children objects that were removed. * * @param node parent node which childred were removed * @param childIndices indexes of removed childs * @param removedChildren array of the children objects that were removed */
public void nodesWereRemoved(TreeNode node, int[] childIndices, Object[] removedChildren) { if(node != null && childIndices != null) { fireTreeNodesRemoved(this, getPathToRoot(node), childIndices, removedChildren); } }
Invoke this method after you've changed how the children identified by childIndicies are to be represented in the tree.
Params:
  • node – changed node
  • childIndices – indexes of changed children
/** * Invoke this method after you've changed how the children identified by * childIndicies are to be represented in the tree. * * @param node changed node * @param childIndices indexes of changed children */
public void nodesChanged(TreeNode node, int[] childIndices) { if(node != null) { if (childIndices != null) { int cCount = childIndices.length; if(cCount > 0) { Object[] cChildren = new Object[cCount]; for(int counter = 0; counter < cCount; counter++) cChildren[counter] = node.getChildAt (childIndices[counter]); fireTreeNodesChanged(this, getPathToRoot(node), childIndices, cChildren); } } else if (node == getRoot()) { fireTreeNodesChanged(this, getPathToRoot(node), null, null); } } }
Invoke this method if you've totally changed the children of node and its children's children... This will post a treeStructureChanged event.
Params:
  • node – changed node
/** * Invoke this method if you've totally changed the children of * node and its children's children... This will post a * treeStructureChanged event. * * @param node changed node */
public void nodeStructureChanged(TreeNode node) { if(node != null) { fireTreeStructureChanged(this, getPathToRoot(node), null, null); } }
Builds the parents of node up to and including the root node, where the original node is the last element in the returned array. The length of the returned array gives the node's depth in the tree.
Params:
  • aNode – the TreeNode to get the path for
Returns:an array of TreeNodes giving the path from the root
/** * Builds the parents of node up to and including the root node, * where the original node is the last element in the returned array. * The length of the returned array gives the node's depth in the * tree. * * @param aNode the TreeNode to get the path for * @return an array of TreeNodes giving the path from the root */
public TreeNode[] getPathToRoot(TreeNode aNode) { return getPathToRoot(aNode, 0); }
Builds the parents of node up to and including the root node, where the original node is the last element in the returned array. The length of the returned array gives the node's depth in the tree.
Params:
  • aNode – the TreeNode to get the path for
  • depth – an int giving the number of steps already taken towards the root (on recursive calls), used to size the returned array
Returns:an array of TreeNodes giving the path from the root to the specified node
/** * Builds the parents of node up to and including the root node, * where the original node is the last element in the returned array. * The length of the returned array gives the node's depth in the * tree. * * @param aNode the TreeNode to get the path for * @param depth an int giving the number of steps already taken towards * the root (on recursive calls), used to size the returned array * @return an array of TreeNodes giving the path from the root to the * specified node */
protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) { TreeNode[] retNodes; // This method recurses, traversing towards the root in order // size the array. On the way back, it fills in the nodes, // starting from the root and working back to the original node. /* Check for null, in case someone passed in a null node, or they passed in an element that isn't rooted at root. */ if(aNode == null) { if(depth == 0) return null; else retNodes = new TreeNode[depth]; } else { depth++; if(aNode == root) retNodes = new TreeNode[depth]; else retNodes = getPathToRoot(aNode.getParent(), depth); retNodes[retNodes.length - depth] = aNode; } return retNodes; } // // Events //
Adds a listener for the TreeModelEvent posted after the tree changes.
Params:
  • l – the listener to add
See Also:
  • removeTreeModelListener
/** * Adds a listener for the TreeModelEvent posted after the tree changes. * * @see #removeTreeModelListener * @param l the listener to add */
public void addTreeModelListener(TreeModelListener l) { listenerList.add(TreeModelListener.class, l); }
Removes a listener previously added with addTreeModelListener().
Params:
  • l – the listener to remove
See Also:
  • addTreeModelListener
/** * Removes a listener previously added with <B>addTreeModelListener()</B>. * * @see #addTreeModelListener * @param l the listener to remove */
public void removeTreeModelListener(TreeModelListener l) { listenerList.remove(TreeModelListener.class, l); }
Returns an array of all the tree model listeners registered on this model.
See Also:
Returns:all of this model's TreeModelListeners or an empty array if no tree model listeners are currently registered
Since:1.4
/** * Returns an array of all the tree model listeners * registered on this model. * * @return all of this model's <code>TreeModelListener</code>s * or an empty * array if no tree model listeners are currently registered * * @see #addTreeModelListener * @see #removeTreeModelListener * * @since 1.4 */
public TreeModelListener[] getTreeModelListeners() { return listenerList.getListeners(TreeModelListener.class); }
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.
Params:
  • source – the source of the TreeModelEvent; typically this
  • path – the path to the parent of the nodes that changed; use null to identify the root has changed
  • childIndices – the indices of the changed elements
  • children – the changed elements
/** * Notifies all listeners that have registered interest for * notification on this event type. The event instance * is lazily created using the parameters passed into * the fire method. * * @param source the source of the {@code TreeModelEvent}; * typically {@code this} * @param path the path to the parent of the nodes that changed; use * {@code null} to identify the root has changed * @param childIndices the indices of the changed elements * @param children the changed elements */
protected void fireTreeNodesChanged(Object source, Object[] path, int[] childIndices, Object[] children) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==TreeModelListener.class) { // Lazily create the event: if (e == null) e = new TreeModelEvent(source, path, childIndices, children); ((TreeModelListener)listeners[i+1]).treeNodesChanged(e); } } }
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.
Params:
  • source – the source of the TreeModelEvent; typically this
  • path – the path to the parent the nodes were added to
  • childIndices – the indices of the new elements
  • children – the new elements
/** * Notifies all listeners that have registered interest for * notification on this event type. The event instance * is lazily created using the parameters passed into * the fire method. * * @param source the source of the {@code TreeModelEvent}; * typically {@code this} * @param path the path to the parent the nodes were added to * @param childIndices the indices of the new elements * @param children the new elements */
protected void fireTreeNodesInserted(Object source, Object[] path, int[] childIndices, Object[] children) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==TreeModelListener.class) { // Lazily create the event: if (e == null) e = new TreeModelEvent(source, path, childIndices, children); ((TreeModelListener)listeners[i+1]).treeNodesInserted(e); } } }
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.
Params:
  • source – the source of the TreeModelEvent; typically this
  • path – the path to the parent the nodes were removed from
  • childIndices – the indices of the removed elements
  • children – the removed elements
/** * Notifies all listeners that have registered interest for * notification on this event type. The event instance * is lazily created using the parameters passed into * the fire method. * * @param source the source of the {@code TreeModelEvent}; * typically {@code this} * @param path the path to the parent the nodes were removed from * @param childIndices the indices of the removed elements * @param children the removed elements */
protected void fireTreeNodesRemoved(Object source, Object[] path, int[] childIndices, Object[] children) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==TreeModelListener.class) { // Lazily create the event: if (e == null) e = new TreeModelEvent(source, path, childIndices, children); ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e); } } }
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.
Params:
  • source – the source of the TreeModelEvent; typically this
  • path – the path to the parent of the structure that has changed; use null to identify the root has changed
  • childIndices – the indices of the affected elements
  • children – the affected elements
/** * Notifies all listeners that have registered interest for * notification on this event type. The event instance * is lazily created using the parameters passed into * the fire method. * * @param source the source of the {@code TreeModelEvent}; * typically {@code this} * @param path the path to the parent of the structure that has changed; * use {@code null} to identify the root has changed * @param childIndices the indices of the affected elements * @param children the affected elements */
protected void fireTreeStructureChanged(Object source, Object[] path, int[] childIndices, Object[] children) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==TreeModelListener.class) { // Lazily create the event: if (e == null) e = new TreeModelEvent(source, path, childIndices, children); ((TreeModelListener)listeners[i+1]).treeStructureChanged(e); } } }
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.
Params:
  • source – the source of the TreeModelEvent; typically this
  • path – the path to the parent of the structure that has changed; use null to identify the root has changed
/** * Notifies all listeners that have registered interest for * notification on this event type. The event instance * is lazily created using the parameters passed into * the fire method. * * @param source the source of the {@code TreeModelEvent}; * typically {@code this} * @param path the path to the parent of the structure that has changed; * use {@code null} to identify the root has changed */
private void fireTreeStructureChanged(Object source, TreePath path) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); TreeModelEvent e = null; // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==TreeModelListener.class) { // Lazily create the event: if (e == null) e = new TreeModelEvent(source, path); ((TreeModelListener)listeners[i+1]).treeStructureChanged(e); } } }
Returns an array of all the objects currently registered as FooListeners upon this model. FooListeners are registered using the addFooListener method.

You can specify the listenerType argument with a class literal, such as FooListener.class. For example, you can query a DefaultTreeModel m for its tree model listeners with the following code:

TreeModelListener[] tmls = (TreeModelListener[])(m.getListeners(TreeModelListener.class));
If no such listeners exist, this method returns an empty array.
Params:
  • listenerType – the type of listeners requested
Type parameters:
  • <T> – the listener type
Throws:
  • ClassCastException – if listenerType doesn't specify a class or interface that implements java.util.EventListener
See Also:
Returns:an array of all objects registered as FooListeners on this component, or an empty array if no such listeners have been added
Since:1.3
/** * Returns an array of all the objects currently registered * as <code><em>Foo</em>Listener</code>s * upon this model. * <code><em>Foo</em>Listener</code>s are registered using the * <code>add<em>Foo</em>Listener</code> method. * * <p> * * You can specify the <code>listenerType</code> argument * with a class literal, * such as * <code><em>Foo</em>Listener.class</code>. * For example, you can query a * <code>DefaultTreeModel</code> <code>m</code> * for its tree model listeners with the following code: * * <pre>TreeModelListener[] tmls = (TreeModelListener[])(m.getListeners(TreeModelListener.class));</pre> * * If no such listeners exist, this method returns an empty array. * * @param <T> the listener type * @param listenerType the type of listeners requested * @return an array of all objects registered as * <code><em>Foo</em>Listener</code>s on this component, * or an empty array if no such * listeners have been added * @exception ClassCastException if <code>listenerType</code> * doesn't specify a class or interface that implements * <code>java.util.EventListener</code> * * @see #getTreeModelListeners * * @since 1.3 */
public <T extends EventListener> T[] getListeners(Class<T> listenerType) { return listenerList.getListeners(listenerType); } // Serialization support. private void writeObject(ObjectOutputStream s) throws IOException { Vector<Object> values = new Vector<Object>(); s.defaultWriteObject(); // Save the root, if its Serializable. if(root != null && root instanceof Serializable) { values.addElement("root"); values.addElement(root); } s.writeObject(values); } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { ObjectInputStream.GetField f = s.readFields(); EventListenerList newListenerList = (EventListenerList) f.get("listenerList", null); if (newListenerList == null) { throw new InvalidObjectException("Null listenerList"); } listenerList = newListenerList; asksAllowsChildren = f.get("asksAllowsChildren", false); Vector<?> values = (Vector)s.readObject(); int indexCounter = 0; int maxCounter = values.size(); if(indexCounter < maxCounter && values.elementAt(indexCounter). equals("root")) { TreeNode newRoot = (TreeNode)values.elementAt(++indexCounter); if (newRoot == null) { throw new InvalidObjectException("Null root"); } root = newRoot; indexCounter++; } } } // End of class DefaultTreeModel