/*
* Copyright (c) 1997, 2013, 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="https://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™
* 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
*/
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: - getAllowsChildren.getAllowsChildren
- TreeModel.isLeaf
- setAsksAllowsChildren
/**
* 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.
/**
* 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.
*/
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.
/**
* Sets the root to <code>root</code>. A null <code>root</code> implies
* the tree is to display nothing, and is legal.
*/
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> >= 0 &&
* <i>index</i> < 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 TreeNode
s 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.
/**
* 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.
*/
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.
/**
* 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.
*/
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.
/**
* Invoke this method after you've changed how node is to be
* represented in the tree.
*/
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 TreeNode
s 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.
/**
* 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.
*/
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.
/**
* 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.
*/
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.
/**
* Invoke this method after you've changed how the children identified by
* childIndicies are to be represented in the tree.
*/
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.
/**
* Invoke this method if you've totally changed the children of
* node and its children's children... This will post a
* treeStructureChanged event.
*/
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
/**
* 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
*/
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 TreeModelListener
s
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 FooListener
s
upon this model.
FooListener
s 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; this parameter
should specify an interface that descends from
java.util.EventListener
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
FooListener
s 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 listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* <code>java.util.EventListener</code>
* @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 {
s.defaultReadObject();
Vector values = (Vector)s.readObject();
int indexCounter = 0;
int maxCounter = values.size();
if(indexCounter < maxCounter && values.elementAt(indexCounter).
equals("root")) {
root = (TreeNode)values.elementAt(++indexCounter);
indexCounter++;
}
}
} // End of class DefaultTreeModel