KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > JTree


1 /*
2  * @(#)JTree.java 1.176 04/07/13
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.swing;
9
10 import java.awt.*;
11 import java.awt.event.*;
12 import java.beans.*;
13 import java.io.*;
14 import java.util.*;
15 import javax.swing.event.*;
16 import javax.swing.plaf.TreeUI JavaDoc;
17 import javax.swing.tree.*;
18 import javax.swing.text.Position JavaDoc;
19 import javax.accessibility.*;
20
21
22 /**
23  * <a name="jtree_description">
24  * A control that displays a set of hierarchical data as an outline.
25  * You can find task-oriented documentation and examples of using trees in
26  * <a HREF="http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html">How to Use Trees</a>,
27  * a section in <em>The Java Tutorial.</em>
28  * <p>
29  * A specific node in a tree can be identified either by a
30  * <code>TreePath</code> (an object
31  * that encapsulates a node and all of its ancestors), or by its
32  * display row, where each row in the display area displays one node.
33  * An <i>expanded</i> node is a non-leaf node (as identified by
34  * <code>TreeModel.isLeaf(node)</code> returning false) that will displays
35  * its children when all its ancestors are <i>expanded</i>.
36  * A <i>collapsed</i>
37  * node is one which hides them. A <i>hidden</i> node is one which is
38  * under a collapsed ancestor. All of a <i>viewable</i> nodes parents
39  * are expanded, but may or may not be displayed. A <i>displayed</i> node
40  * is both viewable and in the display area, where it can be seen.
41  * <p>
42  * The following <code>JTree</code> methods use "visible" to mean "displayed":
43  * <ul>
44  * <li><code>isRootVisible()</code>
45  * <li><code>setRootVisible()</code>
46  * <li><code>scrollPathToVisible()</code>
47  * <li><code>scrollRowToVisible()</code>
48  * <li><code>getVisibleRowCount()</code>
49  * <li><code>setVisibleRowCount()</code>
50  * </ul>
51  * <p>
52  * The next group of <code>JTree</code> methods use "visible" to mean
53  * "viewable" (under an expanded parent):
54  * <ul>
55  * <li><code>isVisible()</code>
56  * <li><code>makeVisible()</code>
57  * </ul>
58  * <p>
59  * If you are interested in knowing when the selection changes implement
60  * the <code>TreeSelectionListener</code> interface and add the instance
61  * using the method <code>addTreeSelectionListener</code>.
62  * <code>valueChanged</code> will be invoked when the
63  * selection changes, that is if the user clicks twice on the same
64  * node <code>valueChanged</code> will only be invoked once.
65  * <p>
66  * If you are interested in detecting either double-click events or when
67  * a user clicks on a node, regardless of whether or not it was selected,
68  * we recommend you do the following:
69  * <pre>
70  * final JTree tree = ...;
71  *
72  * MouseListener ml = new MouseAdapter() {
73  * public void <b>mousePressed</b>(MouseEvent e) {
74  * int selRow = tree.getRowForLocation(e.getX(), e.getY());
75  * TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
76  * if(selRow != -1) {
77  * if(e.getClickCount() == 1) {
78  * mySingleClick(selRow, selPath);
79  * }
80  * else if(e.getClickCount() == 2) {
81  * myDoubleClick(selRow, selPath);
82  * }
83  * }
84  * }
85  * };
86  * tree.addMouseListener(ml);
87  * </pre>
88  * NOTE: This example obtains both the path and row, but you only need to
89  * get the one you're interested in.
90  * <p>
91  * To use <code>JTree</code> to display compound nodes
92  * (for example, nodes containing both
93  * a graphic icon and text), subclass {@link TreeCellRenderer} and use
94  * {@link #setCellRenderer} to tell the tree to use it. To edit such nodes,
95  * subclass {@link TreeCellEditor} and use {@link #setCellEditor}.
96  * <p>
97  * Like all <code>JComponent</code> classes, you can use {@link InputMap} and
98  * {@link ActionMap}
99  * to associate an {@link Action} object with a {@link KeyStroke}
100  * and execute the action under specified conditions.
101  * <p>
102  * <strong>Warning:</strong>
103  * Serialized objects of this class will not be compatible with
104  * future Swing releases. The current serialization support is
105  * appropriate for short term storage or RMI between applications running
106  * the same version of Swing. As of 1.4, support for long term storage
107  * of all JavaBeans<sup><font size="-2">TM</font></sup>
108  * has been added to the <code>java.beans</code> package.
109  * Please see {@link java.beans.XMLEncoder}.
110  *
111  * @beaninfo
112  * attribute: isContainer false
113  * description: A component that displays a set of hierarchical data as an outline.
114  *
115  * @version 1.176, 07/13/04
116  * @author Rob Davis
117  * @author Ray Ryan
118  * @author Scott Violet
119  */

120 public class JTree extends JComponent JavaDoc implements Scrollable JavaDoc, Accessible
121 {
122     /**
123      * @see #getUIClassID
124      * @see #readObject
125      */

126     private static final String JavaDoc uiClassID = "TreeUI";
127
128     /**
129      * The model that defines the tree displayed by this object.
130      */

131     transient protected TreeModel treeModel;
132
133     /**
134      * Models the set of selected nodes in this tree.
135      */

136     transient protected TreeSelectionModel selectionModel;
137
138     /**
139      * True if the root node is displayed, false if its children are
140      * the highest visible nodes.
141      */

142     protected boolean rootVisible;
143
144     /**
145      * The cell used to draw nodes. If <code>null</code>, the UI uses a default
146      * <code>cellRenderer</code>.
147      */

148     transient protected TreeCellRenderer cellRenderer;
149
150     /**
151      * Height to use for each display row. If this is <= 0 the renderer
152      * determines the height for each row.
153      */

154     protected int rowHeight;
155     private boolean rowHeightSet = false;
156
157     /**
158      * Maps from <code>TreePath</code> to <code>Boolean</code>
159      * indicating whether or not the
160      * particular path is expanded. This ONLY indicates whether a
161      * given path is expanded, and NOT if it is visible or not. That
162      * information must be determined by visiting all the parent
163      * paths and seeing if they are visible.
164      */

165     transient private Hashtable expandedState;
166
167
168     /**
169      * True if handles are displayed at the topmost level of the tree.
170      * <p>
171      * A handle is a small icon that displays adjacent to the node which
172      * allows the user to click once to expand or collapse the node. A
173      * common interface shows a plus sign (+) for a node which can be
174      * expanded and a minus sign (-) for a node which can be collapsed.
175      * Handles are always shown for nodes below the topmost level.
176      * <p>
177      * If the <code>rootVisible</code> setting specifies that the root
178      * node is to be displayed, then that is the only node at the topmost
179      * level. If the root node is not displayed, then all of its
180      * children are at the topmost level of the tree. Handles are
181      * always displayed for nodes other than the topmost.
182      * <p>
183      * If the root node isn't visible, it is generally a good to make
184      * this value true. Otherwise, the tree looks exactly like a list,
185      * and users may not know that the "list entries" are actually
186      * tree nodes.
187      *
188      * @see #rootVisible
189      */

190     protected boolean showsRootHandles;
191     private boolean showsRootHandlesSet = false;
192
193     /**
194      * Creates a new event and passed it off the
195      * <code>selectionListeners</code>.
196      */

197     protected transient TreeSelectionRedirector selectionRedirector;
198
199     /**
200      * Editor for the entries. Default is <code>null</code>
201      * (tree is not editable).
202      */

203     transient protected TreeCellEditor cellEditor;
204
205     /**
206      * Is the tree editable? Default is false.
207      */

208     protected boolean editable;
209
210     /**
211      * Is this tree a large model? This is a code-optimization setting.
212      * A large model can be used when the cell height is the same for all
213      * nodes. The UI will then cache very little information and instead
214      * continually message the model. Without a large model the UI caches
215      * most of the information, resulting in fewer method calls to the model.
216      * <p>
217      * This value is only a suggestion to the UI. Not all UIs will
218      * take advantage of it. Default value is false.
219      */

220     protected boolean largeModel;
221
222     /**
223      * Number of rows to make visible at one time. This value is used for
224      * the <code>Scrollable</code> interface. It determines the preferred
225      * size of the display area.
226      */

227     protected int visibleRowCount;
228
229     /**
230      * If true, when editing is to be stopped by way of selection changing,
231      * data in tree changing or other means <code>stopCellEditing</code>
232      * is invoked, and changes are saved. If false,
233      * <code>cancelCellEditing</code> is invoked, and changes
234      * are discarded. Default is false.
235      */

236     protected boolean invokesStopCellEditing;
237
238     /**
239      * If true, when a node is expanded, as many of the descendants are
240      * scrolled to be visible.
241      */

242     protected boolean scrollsOnExpand;
243     private boolean scrollsOnExpandSet = false;
244
245     /**
246      * Number of mouse clicks before a node is expanded.
247      */

248     protected int toggleClickCount;
249
250     /**
251      * Updates the <code>expandedState</code>.
252      */

253     transient protected TreeModelListener treeModelListener;
254
255     /**
256      * Used when <code>setExpandedState</code> is invoked,
257      * will be a <code>Stack</code> of <code>Stack</code>s.
258      */

259     transient private Stack expandedStack;
260
261     /**
262      * Lead selection path, may not be <code>null</code>.
263      */

264     private TreePath leadPath;
265
266     /**
267      * Anchor path.
268      */

269     private TreePath anchorPath;
270
271     /**
272      * True if paths in the selection should be expanded.
273      */

274     private boolean expandsSelectedPaths;
275
276     /**
277      * This is set to true for the life of the <code>setUI</code> call.
278      */

279     private boolean settingUI;
280
281     /** If true, mouse presses on selections initiate a drag operation. */
282     private boolean dragEnabled;
283
284     /**
285      * When <code>addTreeExpansionListener</code> is invoked,
286      * and <code>settingUI</code> is true, this ivar gets set to the passed in
287      * <code>Listener</code>. This listener is then notified first in
288      * <code>fireTreeCollapsed</code> and <code>fireTreeExpanded</code>.
289      * <p>This is an ugly workaround for a way to have the UI listener
290      * get notified before other listeners.
291      */

292     private transient TreeExpansionListener uiTreeExpansionListener;
293
294     /**
295      * Max number of stacks to keep around.
296      */

297     private static int TEMP_STACK_SIZE = 11;
298
299     //
300
// Bound property names
301
//
302
/** Bound property name for <code>cellRenderer</code>. */
303     public final static String JavaDoc CELL_RENDERER_PROPERTY = "cellRenderer";
304     /** Bound property name for <code>treeModel</code>. */
305     public final static String JavaDoc TREE_MODEL_PROPERTY = "model";
306     /** Bound property name for <code>rootVisible</code>. */
307     public final static String JavaDoc ROOT_VISIBLE_PROPERTY = "rootVisible";
308     /** Bound property name for <code>showsRootHandles</code>. */
309     public final static String JavaDoc SHOWS_ROOT_HANDLES_PROPERTY = "showsRootHandles";
310     /** Bound property name for <code>rowHeight</code>. */
311     public final static String JavaDoc ROW_HEIGHT_PROPERTY = "rowHeight";
312     /** Bound property name for <code>cellEditor</code>. */
313     public final static String JavaDoc CELL_EDITOR_PROPERTY = "cellEditor";
314     /** Bound property name for <code>editable</code>. */
315     public final static String JavaDoc EDITABLE_PROPERTY = "editable";
316     /** Bound property name for <code>largeModel</code>. */
317     public final static String JavaDoc LARGE_MODEL_PROPERTY = "largeModel";
318     /** Bound property name for selectionModel. */
319     public final static String JavaDoc SELECTION_MODEL_PROPERTY = "selectionModel";
320     /** Bound property name for <code>visibleRowCount</code>. */
321     public final static String JavaDoc VISIBLE_ROW_COUNT_PROPERTY = "visibleRowCount";
322     /** Bound property name for <code>messagesStopCellEditing</code>. */
323     public final static String JavaDoc INVOKES_STOP_CELL_EDITING_PROPERTY = "invokesStopCellEditing";
324     /** Bound property name for <code>scrollsOnExpand</code>. */
325     public final static String JavaDoc SCROLLS_ON_EXPAND_PROPERTY = "scrollsOnExpand";
326     /** Bound property name for <code>toggleClickCount</code>. */
327     public final static String JavaDoc TOGGLE_CLICK_COUNT_PROPERTY = "toggleClickCount";
328     /** Bound property name for <code>leadSelectionPath</code>.
329      * @since 1.3 */

330     public final static String JavaDoc LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath";
331     /** Bound property name for anchor selection path.
332      * @since 1.3 */

333     public final static String JavaDoc ANCHOR_SELECTION_PATH_PROPERTY = "anchorSelectionPath";
334     /** Bound property name for expands selected paths property
335      * @since 1.3 */

336     public final static String JavaDoc EXPANDS_SELECTED_PATHS_PROPERTY = "expandsSelectedPaths";
337
338
339     /**
340      * Creates and returns a sample <code>TreeModel</code>.
341      * Used primarily for beanbuilders to show something interesting.
342      *
343      * @return the default <code>TreeModel</code>
344      */

345     protected static TreeModel getDefaultTreeModel() {
346         DefaultMutableTreeNode root = new DefaultMutableTreeNode("JTree");
347     DefaultMutableTreeNode parent;
348
349     parent = new DefaultMutableTreeNode("colors");
350     root.add(parent);
351     parent.add(new DefaultMutableTreeNode("blue"));
352     parent.add(new DefaultMutableTreeNode("violet"));
353     parent.add(new DefaultMutableTreeNode("red"));
354     parent.add(new DefaultMutableTreeNode("yellow"));
355
356     parent = new DefaultMutableTreeNode("sports");
357     root.add(parent);
358     parent.add(new DefaultMutableTreeNode("basketball"));
359     parent.add(new DefaultMutableTreeNode("soccer"));
360     parent.add(new DefaultMutableTreeNode("football"));
361     parent.add(new DefaultMutableTreeNode("hockey"));
362
363     parent = new DefaultMutableTreeNode("food");
364     root.add(parent);
365     parent.add(new DefaultMutableTreeNode("hot dogs"));
366     parent.add(new DefaultMutableTreeNode("pizza"));
367     parent.add(new DefaultMutableTreeNode("ravioli"));
368     parent.add(new DefaultMutableTreeNode("bananas"));
369         return new DefaultTreeModel(root);
370     }
371
372     /**
373      * Returns a <code>TreeModel</code> wrapping the specified object.
374      * If the object is:<ul>
375      * <li>an array of <code>Object</code>s,
376      * <li>a <code>Hashtable</code>, or
377      * <li>a <code>Vector</code>
378      * </ul>then a new root node is created with each of the incoming
379      * objects as children. Otherwise, a new root is created with the
380      * specified object as its value.
381      *
382      * @param value the <code>Object</code> used as the foundation for
383      * the <code>TreeModel</code>
384      * @return a <code>TreeModel</code> wrapping the specified object
385      */

386     protected static TreeModel createTreeModel(Object JavaDoc value) {
387         DefaultMutableTreeNode root;
388
389         if((value instanceof Object JavaDoc[]) || (value instanceof Hashtable) ||
390            (value instanceof Vector)) {
391             root = new DefaultMutableTreeNode("root");
392             DynamicUtilTreeNode.createChildren(root, value);
393         }
394         else {
395             root = new DynamicUtilTreeNode("root", value);
396         }
397         return new DefaultTreeModel(root, false);
398     }
399
400     /**
401      * Returns a <code>JTree</code> with a sample model.
402      * The default model used by the tree defines a leaf node as any node
403      * without children.
404      *
405      * @see DefaultTreeModel#asksAllowsChildren
406      */

407     public JTree() {
408         this(getDefaultTreeModel());
409     }
410
411     /**
412      * Returns a <code>JTree</code> with each element of the
413      * specified array as the
414      * child of a new root node which is not displayed.
415      * By default, the tree defines a leaf node as any node without
416      * children.
417      *
418      * @param value an array of <code>Object</code>s
419      * @see DefaultTreeModel#asksAllowsChildren
420      */

421     public JTree(Object JavaDoc[] value) {
422         this(createTreeModel(value));
423         this.setRootVisible(false);
424         this.setShowsRootHandles(true);
425         expandRoot();
426     }
427
428     /**
429      * Returns a <code>JTree</code> with each element of the specified
430      * <code>Vector</code> as the
431      * child of a new root node which is not displayed. By default, the
432      * tree defines a leaf node as any node without children.
433      *
434      * @param value a <code>Vector</code>
435      * @see DefaultTreeModel#asksAllowsChildren
436      */

437     public JTree(Vector<?> value) {
438         this(createTreeModel(value));
439         this.setRootVisible(false);
440         this.setShowsRootHandles(true);
441         expandRoot();
442     }
443
444     /**
445      * Returns a <code>JTree</code> created from a <code>Hashtable</code>
446      * which does not display with root.
447      * Each value-half of the key/value pairs in the <code>HashTable</code>
448      * becomes a child of the new root node. By default, the tree defines
449      * a leaf node as any node without children.
450      *
451      * @param value a <code>Hashtable</code>
452      * @see DefaultTreeModel#asksAllowsChildren
453      */

454     public JTree(Hashtable<?,?> value) {
455         this(createTreeModel(value));
456         this.setRootVisible(false);
457         this.setShowsRootHandles(true);
458         expandRoot();
459     }
460
461     /**
462      * Returns a <code>JTree</code> with the specified
463      * <code>TreeNode</code> as its root,
464      * which displays the root node.
465      * By default, the tree defines a leaf node as any node without children.
466      *
467      * @param root a <code>TreeNode</code> object
468      * @see DefaultTreeModel#asksAllowsChildren
469      */

470     public JTree(TreeNode root) {
471         this(root, false);
472     }
473
474     /**
475      * Returns a <code>JTree</code> with the specified <code>TreeNode</code>
476      * as its root, which
477      * displays the root node and which decides whether a node is a
478      * leaf node in the specified manner.
479      *
480      * @param root a <code>TreeNode</code> object
481      * @param asksAllowsChildren if false, any node without children is a
482      * leaf node; if true, only nodes that do not allow
483      * children are leaf nodes
484      * @see DefaultTreeModel#asksAllowsChildren
485      */

486     public JTree(TreeNode root, boolean asksAllowsChildren) {
487         this(new DefaultTreeModel(root, asksAllowsChildren));
488     }
489
490     /**
491      * Returns an instance of <code>JTree</code> which displays the root node
492      * -- the tree is created using the specified data model.
493      *
494      * @param newModel the <code>TreeModel</code> to use as the data model
495      */

496     public JTree(TreeModel newModel) {
497         super();
498     expandedStack = new Stack();
499     toggleClickCount = 2;
500     expandedState = new Hashtable();
501         setLayout(null);
502         rowHeight = 16;
503         visibleRowCount = 20;
504         rootVisible = true;
505         selectionModel = new DefaultTreeSelectionModel();
506         cellRenderer = null;
507     scrollsOnExpand = true;
508         setOpaque(true);
509     expandsSelectedPaths = true;
510         updateUI();
511         setModel(newModel);
512     }
513
514     /**
515      * Returns the L&F object that renders this component.
516      *
517      * @return the <code>TreeUI</code> object that renders this component
518      */

519     public TreeUI JavaDoc getUI() {
520         return (TreeUI JavaDoc)ui;
521     }
522
523     /**
524      * Sets the L&F object that renders this component.
525      *
526      * @param ui the <code>TreeUI</code> L&F object
527      * @see UIDefaults#getUI
528      * @beaninfo
529      * bound: true
530      * hidden: true
531      * attribute: visualUpdate true
532      * description: The UI object that implements the Component's LookAndFeel.
533      */

534     public void setUI(TreeUI JavaDoc ui) {
535         if ((TreeUI JavaDoc)this.ui != ui) {
536         settingUI = true;
537         uiTreeExpansionListener = null;
538         try {
539         super.setUI(ui);
540         }
541         finally {
542         settingUI = false;
543         }
544         }
545     }
546
547     /**
548      * Notification from the <code>UIManager</code> that the L&F has changed.
549      * Replaces the current UI object with the latest version from the
550      * <code>UIManager</code>.
551      *
552      * @see JComponent#updateUI
553      */

554     public void updateUI() {
555         setUI((TreeUI JavaDoc)UIManager.getUI(this));
556         invalidate();
557     }
558
559
560     /**
561      * Returns the name of the L&F class that renders this component.
562      *
563      * @return the string "TreeUI"
564      * @see JComponent#getUIClassID
565      * @see UIDefaults#getUI
566      */

567     public String JavaDoc getUIClassID() {
568         return uiClassID;
569     }
570
571
572     /**
573      * Returns the current <code>TreeCellRenderer</code>
574      * that is rendering each cell.
575      *
576      * @return the <code>TreeCellRenderer</code> that is rendering each cell
577      */

578     public TreeCellRenderer getCellRenderer() {
579         return cellRenderer;
580     }
581
582     /**
583      * Sets the <code>TreeCellRenderer</code> that will be used to
584      * draw each cell.
585      *
586      * @param x the <code>TreeCellRenderer</code> that is to render each cell
587      * @beaninfo
588      * bound: true
589      * description: The TreeCellRenderer that will be used to draw
590      * each cell.
591      */

592     public void setCellRenderer(TreeCellRenderer x) {
593         TreeCellRenderer oldValue = cellRenderer;
594
595         cellRenderer = x;
596         firePropertyChange(CELL_RENDERER_PROPERTY, oldValue, cellRenderer);
597         invalidate();
598     }
599
600     /**
601       * Determines whether the tree is editable. Fires a property
602       * change event if the new setting is different from the existing
603       * setting.
604       *
605       * @param flag a boolean value, true if the tree is editable
606       * @beaninfo
607       * bound: true
608       * description: Whether the tree is editable.
609       */

610     public void setEditable(boolean flag) {
611         boolean oldValue = this.editable;
612
613         this.editable = flag;
614         firePropertyChange(EDITABLE_PROPERTY, oldValue, flag);
615         if (accessibleContext != null) {
616             accessibleContext.firePropertyChange(
617                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
618                 (oldValue ? AccessibleState.EDITABLE : null),
619                 (flag ? AccessibleState.EDITABLE : null));
620         }
621     }
622
623     /**
624      * Returns true if the tree is editable.
625      *
626      * @return true if the tree is editable
627      */

628     public boolean isEditable() {
629         return editable;
630     }
631
632     /**
633      * Sets the cell editor. A <code>null</code> value implies that the
634      * tree cannot be edited. If this represents a change in the
635      * <code>cellEditor</code>, the <code>propertyChange</code>
636      * method is invoked on all listeners.
637      *
638      * @param cellEditor the <code>TreeCellEditor</code> to use
639      * @beaninfo
640      * bound: true
641      * description: The cell editor. A null value implies the tree
642      * cannot be edited.
643      */

644     public void setCellEditor(TreeCellEditor cellEditor) {
645         TreeCellEditor oldEditor = this.cellEditor;
646
647         this.cellEditor = cellEditor;
648         firePropertyChange(CELL_EDITOR_PROPERTY, oldEditor, cellEditor);
649         invalidate();
650     }
651
652     /**
653      * Returns the editor used to edit entries in the tree.
654      *
655      * @return the <code>TreeCellEditor</code> in use,
656      * or <code>null</code> if the tree cannot be edited
657      */

658     public TreeCellEditor getCellEditor() {
659         return cellEditor;
660     }
661
662     /**
663      * Returns the <code>TreeModel</code> that is providing the data.
664      *
665      * @return the <code>TreeModel</code> that is providing the data
666      */

667     public TreeModel getModel() {
668         return treeModel;
669     }
670
671     /**
672      * Sets the <code>TreeModel</code> that will provide the data.
673      *
674      * @param newModel the <code>TreeModel</code> that is to provide the data
675      * @beaninfo
676      * bound: true
677      * description: The TreeModel that will provide the data.
678      */

679     public void setModel(TreeModel newModel) {
680         clearSelection();
681
682         TreeModel oldModel = treeModel;
683
684     if(treeModel != null && treeModelListener != null)
685         treeModel.removeTreeModelListener(treeModelListener);
686
687         if (accessibleContext != null) {
688         if (treeModel != null) {
689                 treeModel.removeTreeModelListener((TreeModelListener)accessibleContext);
690         }
691             if (newModel != null) {
692             newModel.addTreeModelListener((TreeModelListener)accessibleContext);
693         }
694         }
695
696         treeModel = newModel;
697     clearToggledPaths();
698     if(treeModel != null) {
699         if(treeModelListener == null)
700         treeModelListener = createTreeModelListener();
701         if(treeModelListener != null)
702         treeModel.addTreeModelListener(treeModelListener);
703         // Mark the root as expanded, if it isn't a leaf.
704
if(treeModel.getRoot() != null &&
705                !treeModel.isLeaf(treeModel.getRoot())) {
706         expandedState.put(new TreePath(treeModel.getRoot()),
707                   Boolean.TRUE);
708             }
709     }
710         firePropertyChange(TREE_MODEL_PROPERTY, oldModel, treeModel);
711         invalidate();
712     }
713
714     /**
715      * Returns true if the root node of the tree is displayed.
716      *
717      * @return true if the root node of the tree is displayed
718      * @see #rootVisible
719      */

720     public boolean isRootVisible() {
721         return rootVisible;
722     }
723
724     /**
725      * Determines whether or not the root node from
726      * the <code>TreeModel</code> is visible.
727      *
728      * @param rootVisible true if the root node of the tree is to be displayed
729      * @see #rootVisible
730      * @beaninfo
731      * bound: true
732      * description: Whether or not the root node
733      * from the TreeModel is visible.
734      */

735     public void setRootVisible(boolean rootVisible) {
736         boolean oldValue = this.rootVisible;
737
738         this.rootVisible = rootVisible;
739         firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, this.rootVisible);
740         if (accessibleContext != null) {
741             ((AccessibleJTree)accessibleContext).fireVisibleDataPropertyChange();
742         }
743     }
744
745     /**
746      * Sets the value of the <code>showsRootHandles</code> property,
747      * which specifies whether the node handles should be displayed.
748      * The default value of this property depends on the constructor
749      * used to create the <code>JTree</code>.
750      * Some look and feels might not support handles;
751      * they will ignore this property.
752      *
753      * @param newValue <code>true</code> if root handles should be displayed;
754      * otherwise, <code>false</code>
755      * @see #showsRootHandles
756      * @see #getShowsRootHandles
757      * @beaninfo
758      * bound: true
759      * description: Whether the node handles are to be
760      * displayed.
761      */

762     public void setShowsRootHandles(boolean newValue) {
763         boolean oldValue = showsRootHandles;
764     TreeModel model = getModel();
765
766         showsRootHandles = newValue;
767         showsRootHandlesSet = true;
768         firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue,
769                            showsRootHandles);
770         if (accessibleContext != null) {
771             ((AccessibleJTree)accessibleContext).fireVisibleDataPropertyChange();
772         }
773         invalidate();
774     }
775
776     /**
777      * Returns the value of the <code>showsRootHandles</code> property.
778      *
779      * @return the value of the <code>showsRootHandles</code> property
780      * @see #showsRootHandles
781      */

782     public boolean getShowsRootHandles()
783     {
784         return showsRootHandles;
785     }
786
787     /**
788      * Sets the height of each cell, in pixels. If the specified value
789      * is less than or equal to zero the current cell renderer is
790      * queried for each row's height.
791      *
792      * @param rowHeight the height of each cell, in pixels
793      * @beaninfo
794      * bound: true
795      * description: The height of each cell.
796      */

797     public void setRowHeight(int rowHeight)
798     {
799         int oldValue = this.rowHeight;
800
801         this.rowHeight = rowHeight;
802     rowHeightSet = true;
803         firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, this.rowHeight);
804         invalidate();
805     }
806
807     /**
808      * Returns the height of each row. If the returned value is less than
809      * or equal to 0 the height for each row is determined by the
810      * renderer.
811      *
812      */

813     public int getRowHeight()
814     {
815         return rowHeight;
816     }
817
818     /**
819      * Returns true if the height of each display row is a fixed size.
820      *
821      * @return true if the height of each row is a fixed size
822      */

823     public boolean isFixedRowHeight()
824     {
825         return (rowHeight > 0);
826     }
827
828     /**
829      * Specifies whether the UI should use a large model.
830      * (Not all UIs will implement this.) Fires a property change
831      * for the LARGE_MODEL_PROPERTY.
832      *
833      * @param newValue true to suggest a large model to the UI
834      * @see #largeModel
835      * @beaninfo
836      * bound: true
837      * description: Whether the UI should use a
838      * large model.
839      */

840     public void setLargeModel(boolean newValue) {
841         boolean oldValue = largeModel;
842
843         largeModel = newValue;
844         firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, newValue);
845     }
846
847     /**
848      * Returns true if the tree is configured for a large model.
849      *
850      * @return true if a large model is suggested
851      * @see #largeModel
852      */

853     public boolean isLargeModel() {
854         return largeModel;
855     }
856
857     /**
858      * Determines what happens when editing is interrupted by selecting
859      * another node in the tree, a change in the tree's data, or by some
860      * other means. Setting this property to <code>true</code> causes the
861      * changes to be automatically saved when editing is interrupted.
862      * <p>
863      * Fires a property change for the INVOKES_STOP_CELL_EDITING_PROPERTY.
864      *
865      * @param newValue true means that <code>stopCellEditing</code> is invoked
866      * when editing is interrupted, and data is saved; false means that
867      * <code>cancelCellEditing</code> is invoked, and changes are lost
868      * @beaninfo
869      * bound: true
870      * description: Determines what happens when editing is interrupted,
871      * selecting another node in the tree, a change in the
872      * tree's data, or some other means.
873      */

874     public void setInvokesStopCellEditing(boolean newValue) {
875         boolean oldValue = invokesStopCellEditing;
876
877         invokesStopCellEditing = newValue;
878         firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY, oldValue,
879                            newValue);
880     }
881
882     /**
883      * Returns the indicator that tells what happens when editing is
884      * interrupted.
885      *
886      * @return the indicator that tells what happens when editing is
887      * interrupted
888      * @see #setInvokesStopCellEditing
889      */

890     public boolean getInvokesStopCellEditing() {
891         return invokesStopCellEditing;
892     }
893
894     /**
895      * Sets the <code>scrollsOnExpand</code> property,
896      * which determines whether the
897      * tree might scroll to show previously hidden children.
898      * If this property is <code>true</code> (the default),
899      * when a node expands
900      * the tree can use scrolling to make
901      * the maximum possible number of the node's descendants visible.
902      * In some look and feels, trees might not need to scroll when expanded;
903      * those look and feels will ignore this property.
904      *
905      * @param newValue <code>false</code> to disable scrolling on expansion;
906      * <code>true</code> to enable it
907      * @see #getScrollsOnExpand
908      *
909      * @beaninfo
910      * bound: true
911      * description: Indicates if a node descendant should be scrolled when expanded.
912      */

913     public void setScrollsOnExpand(boolean newValue) {
914     boolean oldValue = scrollsOnExpand;
915
916     scrollsOnExpand = newValue;
917     scrollsOnExpandSet = true;
918         firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue,
919                            newValue);
920     }
921
922     /**
923      * Returns the value of the <code>scrollsOnExpand</code> property.
924      *
925      * @return the value of the <code>scrollsOnExpand</code> property
926      */

927     public boolean getScrollsOnExpand() {
928     return scrollsOnExpand;
929     }
930
931     /**
932      * Sets the number of mouse clicks before a node will expand or close.
933      * The default is two.
934      *
935      * @since 1.3
936      * @beaninfo
937      * bound: true
938      * description: Number of clicks before a node will expand/collapse.
939      */

940     public void setToggleClickCount(int clickCount) {
941     int oldCount = toggleClickCount;
942
943     toggleClickCount = clickCount;
944     firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY, oldCount,
945                clickCount);
946     }
947
948     /**
949      * Returns the number of mouse clicks needed to expand or close a node.
950      *
951      * @return number of mouse clicks before node is expanded
952      * @since 1.3
953      */

954     public int getToggleClickCount() {
955     return toggleClickCount;
956     }
957
958     /**
959      * Configures the <code>expandsSelectedPaths</code> property. If
960      * true, any time the selection is changed, either via the
961      * <code>TreeSelectionModel</code>, or the cover methods provided by
962      * <code>JTree</code>, the <code>TreePath</code>s parents will be
963      * expanded to make them visible (visible meaning the parent path is
964      * expanded, not necessarily in the visible rectangle of the
965      * <code>JTree</code>). If false, when the selection
966      * changes the nodes parent is not made visible (all its parents expanded).
967      * This is useful if you wish to have your selection model maintain paths
968      * that are not always visible (all parents expanded).
969      *
970      * @param newValue the new value for <code>expandsSelectedPaths</code>
971      *
972      * @since 1.3
973      * @beaninfo
974      * bound: true
975      * description: Indicates whether changes to the selection should make
976      * the parent of the path visible.
977      */

978     public void setExpandsSelectedPaths(boolean newValue) {
979     boolean oldValue = expandsSelectedPaths;
980
981     expandsSelectedPaths = newValue;
982     firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY, oldValue,
983                newValue);
984     }
985
986     /**
987      * Returns the <code>expandsSelectedPaths</code> property.
988      * @return true if selection changes result in the parent path being
989      * expanded
990      * @since 1.3
991      * @see #setExpandsSelectedPaths
992      */

993     public boolean getExpandsSelectedPaths() {
994     return expandsSelectedPaths;
995     }
996
997     /**
998      * Sets the <code>dragEnabled</code> property,
999      * which must be <code>true</code> to enable
1000     * automatic drag handling (the first part of drag and drop)
1001     * on this component.
1002     * The <code>transferHandler</code> property needs to be set
1003     * to a non-<code>null</code> value for the drag to do
1004     * anything. The default value of the <code>dragEnabled</code>
1005     * property
1006     * is <code>false</code>.
1007     *
1008     * <p>
1009     *
1010     * When automatic drag handling is enabled,
1011     * most look and feels begin a drag-and-drop operation
1012     * whenever the user presses the mouse button over a selection
1013     * and then moves the mouse a few pixels.
1014     * Setting this property to <code>true</code>
1015     * can therefore have a subtle effect on
1016     * how selections behave.
1017     *
1018     * <p>
1019     *
1020     * Some look and feels might not support automatic drag and drop;
1021     * they will ignore this property. You can work around such
1022     * look and feels by modifying the component
1023     * to directly call the <code>exportAsDrag</code> method of a
1024     * <code>TransferHandler</code>.
1025     *
1026     * @param b the value to set the <code>dragEnabled</code> property to
1027     * @exception HeadlessException if
1028     * <code>b</code> is <code>true</code> and
1029     * <code>GraphicsEnvironment.isHeadless()</code>
1030     * returns <code>true</code>
1031     * @see java.awt.GraphicsEnvironment#isHeadless
1032     * @see #getDragEnabled
1033     * @see #setTransferHandler
1034     * @see TransferHandler
1035     * @since 1.4
1036     *
1037     * @beaninfo
1038     * description: determines whether automatic drag handling is enabled
1039     * bound: false
1040     */

1041    public void setDragEnabled(boolean b) {
1042        if (b && GraphicsEnvironment.isHeadless()) {
1043            throw new HeadlessException();
1044        }
1045    dragEnabled = b;
1046    }
1047
1048    /**
1049     * Gets the value of the <code>dragEnabled</code> property.
1050     *