/[classpath]/classpath/javax/swing/JTree.java
ViewVC logotype

Diff of /classpath/javax/swing/JTree.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.37 by abalkiss, Fri Sep 2 18:38:20 2005 UTC revision 1.38 by rabbit78, Tue Sep 13 09:17:20 2005 UTC
# Line 72  public class JTree Line 72  public class JTree
72                  extends JComponent                  extends JComponent
73                          implements Scrollable, Accessible                          implements Scrollable, Accessible
74  {  {
         /**  
          * Listens to the model of the JTree and updates the property  
          * <code>expandedState</code> if nodes are removed or changed.  
          */  
         protected class TreeModelHandler  
                         implements  
                         TreeModelListener  
         {  
   
                 /**  
                  * Creates a new instance of TreeModelHandler.  
                  */  
                 protected TreeModelHandler()  
                 {  
                 }  
   
                 /**  
                  * Notifies when a node has changed in some ways. This does not include  
                  * that a node has changed its location or changed it's children. It  
                  * only means that some attributes of the node have changed that might  
                  * affect its presentation.  
                  *  
                  * This method is called after the actual change occured.  
                  *  
                  * @param ev the TreeModelEvent describing the change  
                  */  
                 public void treeNodesChanged(TreeModelEvent ev)  
                 {  
                         // nothing to do here  
                 }  
   
                 /**  
                  * Notifies when a node is inserted into the tree.  
                  *  
                  * This method is called after the actual change occured.  
                  *  
                  * @param ev the TreeModelEvent describing the change  
                  */  
                 public void treeNodesInserted(TreeModelEvent ev)  
                 {  
                         // nothing to do here  
                 }  
   
                 /**  
                  * Notifies when a node is removed from the tree.  
                  *  
                  * This method is called after the actual change occured.  
                  *  
                  * @param ev the TreeModelEvent describing the change  
                  */  
                 public void treeNodesRemoved(TreeModelEvent ev)  
                 {  
                         // TODO: The API docs suggest that this method should do something  
                         // but I cannot really see what has to be done here ...  
                 }  
   
                 /**  
                  * Notifies when the structure of the tree is changed.  
                  *  
                  * This method is called after the actual change occured.  
                  *  
                  * @param ev the TreeModelEvent describing the change  
                  */  
                 public void treeStructureChanged(TreeModelEvent ev)  
                 {  
                         // set state of new path  
                         TreePath path = ev.getTreePath();  
                         setExpandedState(path, isExpanded(path));  
                 }  
         } // TreeModelHandler  
   
         /**  
          * This redirects TreeSelectionEvents and rewrites the source of it to be  
          * this JTree. This is typically done when the tree model generates an  
          * event, but the JTree object associated with that model should be listed  
          * as the actual source of the event.  
          */  
         protected class TreeSelectionRedirector  
                         implements  
                         TreeSelectionListener,  
                         Serializable  
         {  
                 /** The serial version UID. */  
                 private static final long serialVersionUID = -3505069663646241664L;  
   
                 /**  
                  * Creates a new instance of TreeSelectionRedirector  
                  */  
                 protected TreeSelectionRedirector()  
                 {  
                 }  
   
                 /**  
                  * Notifies when the tree selection changes.  
                  *  
                  * @param ev the TreeSelectionEvent that describes the change  
                  */  
                 public void valueChanged(TreeSelectionEvent ev)  
                 {  
                         TreeSelectionEvent rewritten = (TreeSelectionEvent) ev  
                                         .cloneWithSource(JTree.this);  
                         fireValueChanged(rewritten);  
                         JTree.this.repaint();  
                 }  
         } // TreeSelectionRedirector  
75    
76          /**    public static class DynamicUtilTreeNode extends DefaultMutableTreeNode
77           * A TreeModel that does not allow anything to be selected.    {
78        protected Object childValue;
79    
80        protected boolean loadedChildren;
81    
82        /**
83         * Currently not set or used by this class. It might be set and used in
84         * later versions of this class.
85         */
86        protected boolean hasChildren;
87    
88        public DynamicUtilTreeNode(Object value, Object children)
89        {
90          super(value);
91          childValue = children;
92          loadedChildren = false;
93        }
94    
95        public int getChildCount()
96        {
97          loadChildren();
98          return super.getChildCount();
99        }
100    
101        protected void loadChildren()
102        {
103          if (!loadedChildren)
104            {
105              createChildren(this, childValue);
106              loadedChildren = true;
107            }
108        }
109    
110        public Enumeration children()
111        {
112          loadChildren();
113          return super.children();
114        }
115    
116        /**
117         * Returns the child node at position <code>pos</code>. Subclassed
118         * here to load the children if necessary.
119         *
120         * @param pos the position of the child node to fetch
121         *
122         * @return the childnode at the specified position
123         */
124        public TreeNode getChildAt(int pos)
125        {
126          loadChildren();
127          return super.getChildAt(pos);
128        }
129    
130        public boolean isLeaf()
131        {
132          return (childValue == null || !(childValue instanceof Hashtable
133              || childValue instanceof Vector || childValue.getClass()
134              .isArray()));
135        }
136    
137        public static void createChildren(DefaultMutableTreeNode parent,
138                                          Object children)
139        {
140          if (children instanceof Hashtable)
141            {
142              Hashtable tab = (Hashtable) children;
143              Enumeration e = tab.keys();
144              while (e.hasMoreElements())
145                {
146                  Object key = e.nextElement();
147                  Object val = tab.get(key);
148                  parent.add(new DynamicUtilTreeNode(key, val));
149                }
150            }
151          else if (children instanceof Vector)
152            {
153              Iterator i = ((Vector) children).iterator();
154              while (i.hasNext())
155                {
156                  Object n = i.next();
157                  parent.add(new DynamicUtilTreeNode(n, n));
158                }
159            }
160          else if (children != null && children.getClass().isArray())
161            {
162              Object[] arr = (Object[]) children;
163              for (int i = 0; i < arr.length; ++i)
164                parent.add(new DynamicUtilTreeNode(arr[i], arr[i]));
165            }
166        }
167      }
168    
169      /**
170       * Listens to the model of the JTree and updates the property
171       * <code>expandedState</code> if nodes are removed or changed.
172       */
173      protected class TreeModelHandler implements TreeModelListener
174      {
175    
176        /**
177         * Creates a new instance of TreeModelHandler.
178         */
179        protected TreeModelHandler()
180        {
181        }
182    
183        /**
184         * Notifies when a node has changed in some ways. This does not include
185         * that a node has changed its location or changed it's children. It
186         * only means that some attributes of the node have changed that might
187         * affect its presentation.
188         *
189         * This method is called after the actual change occured.
190         *
191         * @param ev the TreeModelEvent describing the change
192         */
193        public void treeNodesChanged(TreeModelEvent ev)
194        {
195          // Nothing to do here.
196        }
197    
198        /**
199         * Notifies when a node is inserted into the tree.
200         *
201         * This method is called after the actual change occured.
202         *
203         * @param ev the TreeModelEvent describing the change
204         */
205        public void treeNodesInserted(TreeModelEvent ev)
206        {
207          // nothing to do here
208        }
209    
210        /**
211         * Notifies when a node is removed from the tree.
212         *
213         * This method is called after the actual change occured.
214         *
215         * @param ev the TreeModelEvent describing the change
216           */           */
217          protected static class EmptySelectionModel      public void treeNodesRemoved(TreeModelEvent ev)
218                          extends      {
219                                  DefaultTreeSelectionModel        // TODO: The API docs suggest that this method should do something
220          {        // but I cannot really see what has to be done here ...
221                  /** The serial version UID. */      }
                 private static final long serialVersionUID = -5815023306225701477L;  
   
                 /**  
                  * The shared instance of this model.  
                  */  
                 protected static final EmptySelectionModel sharedInstance = new EmptySelectionModel();  
   
                 /**  
                  * Creates a new instance of EmptySelectionModel.  
                  */  
                 protected EmptySelectionModel()  
                 {  
                 }  
   
                 /**  
                  * Returns the shared instance of EmptySelectionModel.  
                  *  
                  * @return the shared instance of EmptySelectionModel  
                  */  
                 public static EmptySelectionModel sharedInstance()  
                 {  
                         return sharedInstance;  
                 }  
   
                 /**  
                  * This catches attempts to set a selection and sets nothing instead.  
                  *  
                  * @param paths not used here  
                  */  
                 public void setSelectionPaths(TreePath[] paths)  
                 {  
                         // we don't allow selections in this class  
                 }  
   
                 /**  
                  * This catches attempts to add something to the selection.  
                  *  
                  * @param paths not used here  
                  */  
                 public void addSelectionPaths(TreePath[] paths)  
                 {  
                         // we don't allow selections in this class  
                 }  
   
                 /**  
                  * This catches attempts to remove something from the selection.  
                  *  
                  * @param paths not used here  
                  */  
                 public void removeSelectionPaths(TreePath[] paths)  
                 {  
                         // we don't allow selections in this class  
                 }  
         }// EmptySelectionModel  
   
         private static final long serialVersionUID = 7559816092864483649L;  
         public static final String CELL_EDITOR_PROPERTY = "cellEditor";  
         public static final String CELL_RENDERER_PROPERTY = "cellRenderer";  
         public static final String EDITABLE_PROPERTY = "editable";  
         public static final String INVOKES_STOP_CELL_EDITING_PROPERTY = "invokesStopCellEditing";  
         public static final String LARGE_MODEL_PROPERTY = "largeModel";  
         public static final String ROOT_VISIBLE_PROPERTY = "rootVisible";  
         public static final String ROW_HEIGHT_PROPERTY = "rowHeight";  
         public static final String SCROLLS_ON_EXPAND_PROPERTY = "scrollsOnExpand";  
         public static final String SELECTION_MODEL_PROPERTY = "selectionModel";  
         public static final String SHOWS_ROOT_HANDLES_PROPERTY = "showsRootHandles";  
         public static final String TOGGLE_CLICK_COUNT_PROPERTY = "toggleClickCount";  
         public static final String TREE_MODEL_PROPERTY = "model";  
         public static final String VISIBLE_ROW_COUNT_PROPERTY = "visibleRowCount";  
222    
223          /** @since 1.3 */      /**
224          public static final String ANCHOR_SELECTION_PATH_PROPERTY = "anchorSelectionPath";       * Notifies when the structure of the tree is changed.
225         *
226         * This method is called after the actual change occured.
227         *
228         * @param ev the TreeModelEvent describing the change
229         */
230        public void treeStructureChanged(TreeModelEvent ev)
231        {
232          // Set state of new path.
233          TreePath path = ev.getTreePath();
234          setExpandedState(path, isExpanded(path));
235        }
236      }
237    
238          /** @since 1.3 */    /**
239          public static final String LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath";     * This redirects TreeSelectionEvents and rewrites the source of it to be
240       * this JTree. This is typically done when the tree model generates an
241       * event, but the JTree object associated with that model should be listed
242       * as the actual source of the event.
243       */
244      protected class TreeSelectionRedirector implements TreeSelectionListener,
245                                                         Serializable
246      {
247        /** The serial version UID. */
248        private static final long serialVersionUID = -3505069663646241664L;
249    
250        /**
251         * Creates a new instance of TreeSelectionRedirector
252         */
253        protected TreeSelectionRedirector()
254        {
255        }
256    
257        /**
258         * Notifies when the tree selection changes.
259         *
260         * @param ev the TreeSelectionEvent that describes the change
261         */
262        public void valueChanged(TreeSelectionEvent ev)
263        {
264          TreeSelectionEvent rewritten =
265            (TreeSelectionEvent) ev.cloneWithSource(JTree.this);
266          fireValueChanged(rewritten);
267          JTree.this.repaint();
268        }
269      }
270    
271      /**
272       * A TreeModel that does not allow anything to be selected.
273       */
274      protected static class EmptySelectionModel extends DefaultTreeSelectionModel
275      {
276        /** The serial version UID. */
277        private static final long serialVersionUID = -5815023306225701477L;
278    
279        /**
280         * The shared instance of this model.
281         */
282        protected static final EmptySelectionModel sharedInstance =
283          new EmptySelectionModel();
284    
285        /**
286         * Creates a new instance of EmptySelectionModel.
287         */
288        protected EmptySelectionModel()
289        {
290        }
291    
292        /**
293         * Returns the shared instance of EmptySelectionModel.
294         *
295         * @return the shared instance of EmptySelectionModel
296         */
297        public static EmptySelectionModel sharedInstance()
298        {
299          return sharedInstance;
300        }
301    
302        /**
303         * This catches attempts to set a selection and sets nothing instead.
304         *
305         * @param paths not used here
306         */
307        public void setSelectionPaths(TreePath[] paths)
308        {
309          // We don't allow selections in this class.
310        }
311    
312        /**
313         * This catches attempts to add something to the selection.
314         *
315         * @param paths not used here
316         */
317        public void addSelectionPaths(TreePath[] paths)
318        {
319          // We don't allow selections in this class.
320        }
321    
322        /**
323         * This catches attempts to remove something from the selection.
324         *
325         * @param paths not used here
326         */
327        public void removeSelectionPaths(TreePath[] paths)
328        {
329          // We don't allow selections in this class.
330        }
331      }
332    
333      private static final long serialVersionUID = 7559816092864483649L;
334    
335      public static final String CELL_EDITOR_PROPERTY = "cellEditor";
336    
337      public static final String CELL_RENDERER_PROPERTY = "cellRenderer";
338    
339      public static final String EDITABLE_PROPERTY = "editable";
340    
341      public static final String INVOKES_STOP_CELL_EDITING_PROPERTY =
342        "invokesStopCellEditing";
343    
344      public static final String LARGE_MODEL_PROPERTY = "largeModel";
345    
346      public static final String ROOT_VISIBLE_PROPERTY = "rootVisible";
347    
348      public static final String ROW_HEIGHT_PROPERTY = "rowHeight";
349    
350      public static final String SCROLLS_ON_EXPAND_PROPERTY = "scrollsOnExpand";
351    
352      public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
353    
354      public static final String SHOWS_ROOT_HANDLES_PROPERTY = "showsRootHandles";
355    
356      public static final String TOGGLE_CLICK_COUNT_PROPERTY = "toggleClickCount";
357    
358      public static final String TREE_MODEL_PROPERTY = "model";
359    
360      public static final String VISIBLE_ROW_COUNT_PROPERTY = "visibleRowCount";
361    
362      /** @since 1.3 */
363      public static final String ANCHOR_SELECTION_PATH_PROPERTY =
364        "anchorSelectionPath";
365    
366          /** @since 1.3 */          /** @since 1.3 */
367          public static final String EXPANDS_SELECTED_PATHS_PROPERTY = "expandsSelectedPaths";    public static final String LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath";
         private static final Object EXPANDED = new Object();  
         private static final Object COLLAPSED = new Object();  
         private boolean dragEnabled;  
         private boolean expandsSelectedPaths;  
         private TreePath anchorSelectionPath;  
         private TreePath leadSelectionPath;  
   
         /*  
          * This contains the state of all nodes in the tree. Al/ entries map the  
          * TreePath of a note to to its state. Valid states are EXPANDED and  
          * COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.  
          */  
         private Hashtable nodeStates = new Hashtable();  
         protected transient TreeCellEditor cellEditor;  
         protected transient TreeCellRenderer cellRenderer;  
         protected boolean editable;  
         protected boolean invokesStopCellEditing;  
         protected boolean largeModel;  
         protected boolean rootVisible;  
         protected int rowHeight;  
         protected boolean scrollsOnExpand;  
         protected transient TreeSelectionModel selectionModel;  
         protected boolean showsRootHandles;  
         protected int toggleClickCount;  
         protected transient TreeModel treeModel;  
         protected int visibleRowCount;  
368    
369          /**    /** @since 1.3 */
370           * Handles TreeModelEvents to update the expandedState.    public static final String EXPANDS_SELECTED_PATHS_PROPERTY =
371           */      "expandsSelectedPaths";
         protected transient TreeModelListener treeModelListener;  
372    
373          /**    private static final Object EXPANDED = new Object();
          * Redirects TreeSelectionEvents so that the source is this JTree.  
          */  
         protected TreeSelectionRedirector selectionRedirector =  
                                                                                 new TreeSelectionRedirector();  
374    
375          /**    private static final Object COLLAPSED = new Object();
          * Creates a new <code>JTree</code> object.  
          */  
         public JTree()  
         {  
                 this(createTreeModel(null));  
         }  
   
         /**  
          * Creates a new <code>JTree</code> object.  
          *  
          * @param value the initial nodes in the tree  
          */  
         public JTree(Hashtable value)  
         {  
                 this(createTreeModel(value));  
         }  
   
         /**  
          * Creates a new <code>JTree</code> object.  
          *  
          * @param value the initial nodes in the tree  
          */  
         public JTree(Object[] value)  
         {  
                 this(createTreeModel(value));  
         }  
   
         /**  
          * Creates a new <code>JTree</code> object.  
          *  
          * @param model the model to use  
          */  
         public JTree(TreeModel model)  
         {  
                 setModel(model);  
                 setSelectionModel(EmptySelectionModel.sharedInstance());  
                 setCellRenderer(new DefaultTreeCellRenderer());  
                 updateUI();  
         }  
   
         /**  
          * Creates a new <code>JTree</code> object.  
          *  
          * @param root the root node  
          */  
         public JTree(TreeNode root)  
         {  
                 this(root, false);  
         }  
   
         /**  
          * Creates a new <code>JTree</code> object.  
          *  
          * @param root the root node  
          * @param asksAllowChildren if false, all nodes without children are leaf  
          *        nodes. If true, only nodes that do not allow children are leaf  
          *        nodes.  
          */  
         public JTree(TreeNode root, boolean asksAllowChildren)  
         {  
                 this(new DefaultTreeModel(root, asksAllowChildren));  
         }  
   
         /**  
          * Creates a new <code>JTree</code> object.  
          *  
          * @param value the initial nodes in the tree  
          */  
         public JTree(Vector value)  
         {  
                 this(createTreeModel(value));  
         }  
   
         public static class DynamicUtilTreeNode  
                         extends  
                                 DefaultMutableTreeNode  
         {  
                 protected Object childValue;  
                 protected boolean loadedChildren;  
   
                 /**  
                  * Currently not set or used by this class. It might be set and used in  
                  * later versions of this class.  
                  */  
                 protected boolean hasChildren;  
   
                 public DynamicUtilTreeNode(Object value, Object children)  
                 {  
                         super(value);  
                         childValue = children;  
                         loadedChildren = false;  
                 }  
   
                 public int getChildCount()  
                 {  
                         loadChildren();  
                         return super.getChildCount();  
                 }  
   
                 protected void loadChildren()  
                 {  
                         if (!loadedChildren)  
                         {  
                                 createChildren(this, childValue);  
                                 loadedChildren = true;  
                         }  
                 }  
   
                 public Enumeration children()  
                 {  
                         loadChildren();  
                         return super.children();  
                 }  
   
                 /**  
                  * Returns the child node at position <code>pos</code>. Subclassed  
                  * here to load the children if necessary.  
                  *  
                  * @param pos the position of the child node to fetch  
                  *  
                  * @return the childnode at the specified position  
                  */  
                 public TreeNode getChildAt(int pos)  
                 {  
                         loadChildren();  
                         return super.getChildAt(pos);  
                 }  
   
                 public boolean isLeaf()  
                 {  
                         return (childValue == null || !(childValue instanceof Hashtable  
                                         || childValue instanceof Vector || childValue.getClass()  
                                         .isArray()));  
                 }  
   
                 public static void createChildren(DefaultMutableTreeNode parent,  
                                 Object children)  
                 {  
                         if (children instanceof Hashtable)  
                         {  
                                 Hashtable tab = (Hashtable) children;  
                                 Enumeration e = tab.keys();  
                                 while (e.hasMoreElements())  
                                 {  
                                         Object key = e.nextElement();  
                                         Object val = tab.get(key);  
                                         parent.add(new DynamicUtilTreeNode(key, val));  
                                 }  
                         } else if (children instanceof Vector)  
                         {  
                                 Iterator i = ((Vector) children).iterator();  
                                 while (i.hasNext())  
                                 {  
                                         Object n = i.next();  
                                         parent.add(new DynamicUtilTreeNode(n, n));  
                                 }  
                         } else if (children != null && children.getClass().isArray())  
                         {  
                                 Object[] arr = (Object[]) children;  
                                 for (int i = 0; i < arr.length; ++i)  
                                         parent.add(new DynamicUtilTreeNode(arr[i], arr[i]));  
                         }  
                 }  
         }  
   
         public int getRowForPath(TreePath path)  
         {  
                 TreeUI ui = getUI();  
   
                 if (ui != null)  
                         return ui.getRowForPath(this, path);  
   
                 return -1;  
         }  
   
         public TreePath getPathForRow(int row)  
         {  
                 TreeUI ui = getUI();  
                 return ui != null ? ui.getPathForRow(this, row) : null;  
         }  
   
         protected TreePath[] getPathBetweenRows(int index0, int index1)  
         {  
                 TreeUI ui = getUI();  
   
                 if (ui == null)  
                         return null;  
   
                 int minIndex = Math.min(index0, index1);  
                 int maxIndex = Math.max(index0, index1);  
                 TreePath[] paths = new TreePath[maxIndex - minIndex + 1];  
   
                 for (int i = minIndex; i <= maxIndex; ++i)  
                         paths[i - minIndex] = ui.getPathForRow(this, i);  
   
                 return paths;  
         }  
   
         /**  
          * Creates a new <code>TreeModel</code> object.  
          *  
          * @param value the values stored in the model  
          */  
         protected static TreeModel createTreeModel(Object value)  
         {  
                 return new DefaultTreeModel(new DynamicUtilTreeNode(value, value));  
         }  
   
         /**  
          * Return the UI associated with this <code>JTree</code> object.  
          *  
          * @return the associated <code>TreeUI</code> object  
          */  
         public TreeUI getUI()  
         {  
                 return (TreeUI) ui;  
         }  
   
         /**  
          * Sets the UI associated with this <code>JTree</code> object.  
          *  
          * @param ui the <code>TreeUI</code> to associate  
          */  
         public void setUI(TreeUI ui)  
         {  
                 super.setUI(ui);  
         }  
376    
377          /**    private boolean dragEnabled;
378           * This method resets the UI used to the Look and Feel defaults..  
379           */    private boolean expandsSelectedPaths;
380          public void updateUI()  
381          {    private TreePath anchorSelectionPath;
382                  setUI((TreeUI) UIManager.getUI(this));  
383                  revalidate();    private TreePath leadSelectionPath;
384                  repaint();  
385          }    /**
386       * This contains the state of all nodes in the tree. Al/ entries map the
387          /**     * TreePath of a note to to its state. Valid states are EXPANDED and
388           * This method returns the String ID of the UI class of Separator.     * COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.
389           *     */
390           * @return The UI class' String ID.    private Hashtable nodeStates = new Hashtable();
391           */  
392          public String getUIClassID()    protected transient TreeCellEditor cellEditor;
393          {  
394                  return "TreeUI";    protected transient TreeCellRenderer cellRenderer;
395          }  
396      protected boolean editable;
397          /**  
398           * Gets the AccessibleContext associated with this    protected boolean invokesStopCellEditing;
399           * <code>JToggleButton</code>.  
400           *    protected boolean largeModel;
401           * @return the associated context  
402           */    protected boolean rootVisible;
403          public AccessibleContext getAccessibleContext()  
404          {    protected int rowHeight;
405                  return null;  
406          }    protected boolean scrollsOnExpand;
407    
408          /**    protected transient TreeSelectionModel selectionModel;
409           * Returns the preferred viewport size.  
410           *    protected boolean showsRootHandles;
411           * @return the preferred size  
412           */    protected int toggleClickCount;
413          public Dimension getPreferredScrollableViewportSize()  
414          {    protected transient TreeModel treeModel;
415            return new Dimension (getPreferredSize().width, getVisibleRowCount()*getRowHeight());  
416          }    protected int visibleRowCount;
417    
418          public int getScrollableUnitIncrement(Rectangle visibleRect,    /**
419                          int orientation, int direction)     * Handles TreeModelEvents to update the expandedState.
420          {     */
421                  return 1;    protected transient TreeModelListener treeModelListener;
422          }  
423      /**
424          public int getScrollableBlockIncrement(Rectangle visibleRect,     * Redirects TreeSelectionEvents so that the source is this JTree.
425                          int orientation, int direction)     */
426          {    protected TreeSelectionRedirector selectionRedirector =
427                  return 1;      new TreeSelectionRedirector();
428          }  
429      /**
430       * Creates a new <code>JTree</code> object.
431       */
432      public JTree()
433      {
434        this(createTreeModel(null));
435      }
436    
437      /**
438       * Creates a new <code>JTree</code> object.
439       *
440       * @param value the initial nodes in the tree
441       */
442      public JTree(Hashtable value)
443      {
444        this(createTreeModel(value));
445      }
446    
447      /**
448       * Creates a new <code>JTree</code> object.
449       *
450       * @param value the initial nodes in the tree
451       */
452      public JTree(Object[] value)
453      {
454        this(createTreeModel(value));
455      }
456    
457      /**
458       * Creates a new <code>JTree</code> object.
459       *
460       * @param model the model to use
461       */
462      public JTree(TreeModel model)
463      {
464        setModel(model);
465        setSelectionModel(EmptySelectionModel.sharedInstance());
466        setCellRenderer(new DefaultTreeCellRenderer());
467        updateUI();
468      }
469    
470      /**
471       * Creates a new <code>JTree</code> object.
472       *
473       * @param root the root node
474       */
475      public JTree(TreeNode root)
476      {
477        this(root, false);
478      }
479    
480      /**
481       * Creates a new <code>JTree</code> object.
482       *
483       * @param root the root node
484       * @param asksAllowChildren if false, all nodes without children are leaf
485       *        nodes. If true, only nodes that do not allow children are leaf
486       *        nodes.
487       */
488      public JTree(TreeNode root, boolean asksAllowChildren)
489      {
490        this(new DefaultTreeModel(root, asksAllowChildren));
491      }
492    
493      /**
494       * Creates a new <code>JTree</code> object.
495       *
496       * @param value the initial nodes in the tree
497       */
498      public JTree(Vector value)
499      {
500        this(createTreeModel(value));
501      }
502    
503      public int getRowForPath(TreePath path)
504      {
505        TreeUI ui = getUI();
506    
507        if (ui != null)
508          return ui.getRowForPath(this, path);
509    
510        return -1;
511      }
512    
513      public TreePath getPathForRow(int row)
514      {
515        TreeUI ui = getUI();
516        return ui != null ? ui.getPathForRow(this, row) : null;
517      }
518    
519      protected TreePath[] getPathBetweenRows(int index0, int index1)
520      {
521        TreeUI ui = getUI();
522    
523        if (ui == null)
524          return null;
525    
526        int minIndex = Math.min(index0, index1);
527        int maxIndex = Math.max(index0, index1);
528        TreePath[] paths = new TreePath[maxIndex - minIndex + 1];
529    
530        for (int i = minIndex; i <= maxIndex; ++i)
531          paths[i - minIndex] = ui.getPathForRow(this, i);
532    
533        return paths;
534      }
535    
536      /**
537       * Creates a new <code>TreeModel</code> object.
538       *
539       * @param value the values stored in the model
540       */
541      protected static TreeModel createTreeModel(Object value)
542      {
543        return new DefaultTreeModel(new DynamicUtilTreeNode(value, value));
544      }
545    
546      /**
547       * Return the UI associated with this <code>JTree</code> object.
548       *
549       * @return the associated <code>TreeUI</code> object
550       */
551      public TreeUI getUI()
552      {
553        return (TreeUI) ui;
554      }
555    
556      /**
557       * Sets the UI associated with this <code>JTree</code> object.
558       *
559       * @param ui the <code>TreeUI</code> to associate
560       */
561      public void setUI(TreeUI ui)
562      {
563        super.setUI(ui);
564      }
565    
566      /**
567       * This method resets the UI used to the Look and Feel defaults..
568       */
569      public void updateUI()
570      {
571        setUI((TreeUI) UIManager.getUI(this));
572        revalidate();
573        repaint();
574      }
575    
576      /**
577       * This method returns the String ID of the UI class of Separator.
578       *
579       * @return The UI class' String ID.
580       */
581      public String getUIClassID()
582      {
583        return "TreeUI";
584      }
585    
586      /**
587       * Gets the AccessibleContext associated with this
588       * <code>JToggleButton</code>.
589       *
590       * @return the associated context
591       */
592      public AccessibleContext getAccessibleContext()
593      {
594        return null;
595      }
596    
597      /**
598       * Returns the preferred viewport size.
599       *
600       * @return the preferred size
601       */
602      public Dimension getPreferredScrollableViewportSize()
603      {
604        return new Dimension (getPreferredSize().width, getVisibleRowCount()*getRowHeight());
605      }
606    
607      public int getScrollableUnitIncrement(Rectangle visibleRect,
608                                            int orientation, int direction)
609      {
610        return 1;
611      }
612    
613      public int getScrollableBlockIncrement(Rectangle visibleRect,
614                                             int orientation, int direction)
615      {
616        return 1;
617      }
618    
619    public boolean getScrollableTracksViewportWidth()    public boolean getScrollableTracksViewportWidth()
620    {    {
# Line 590  public class JTree Line 622  public class JTree
622        return ((JViewport) getParent()).getHeight() > getPreferredSize().height;        return ((JViewport) getParent()).getHeight() > getPreferredSize().height;
623      return false;      return false;
624    }    }
625      
626    public boolean getScrollableTracksViewportHeight()    public boolean getScrollableTracksViewportHeight()
627    {    {
628      if (getParent() instanceof JViewport)      if (getParent() instanceof JViewport)
# Line 598  public class JTree Line 630  public class JTree
630      return false;      return false;
631    }    }
632    
633          /**    /**
634           * Adds a <code>TreeExpansionListener</code> object to the tree.     * Adds a <code>TreeExpansionListener</code> object to the tree.
635           *     *
636           * @param listener the listener to add     * @param listener the listener to add
637           */     */
638          public void addTreeExpansionListener(TreeExpansionListener listener)    public void addTreeExpansionListener(TreeExpansionListener listener)
639          {    {
640                  listenerList.add(TreeExpansionListener.class, listener);      listenerList.add(TreeExpansionListener.class, listener);
641          }    }
642    
643          /**    /**
644           * Removes a <code>TreeExpansionListener</code> object from the tree.     * Removes a <code>TreeExpansionListener</code> object from the tree.
645           *     *
646           * @param listener the listener to remove     * @param listener the listener to remove
647           */     */
648          public void removeTreeExpansionListener(TreeExpansionListener listener)    public void removeTreeExpansionListener(TreeExpansionListener listener)
649          {    {
650                  listenerList.remove(TreeExpansionListener.class, listener);      listenerList.remove(TreeExpansionListener.class, listener);
651          }    }
652    
653          /**    /**
654           * Returns all added <code>TreeExpansionListener</code> objects.     * Returns all added <code>TreeExpansionListener</code> objects.
655           *     *
656           * @return an array of listeners     * @return an array of listeners
657           */     */
658          public TreeExpansionListener[] getTreeExpansionListeners()    public TreeExpansionListener[] getTreeExpansionListeners()
659          {    {
660                  return (TreeExpansionListener[]) getListeners(TreeExpansionListener.class);      return (TreeExpansionListener[]) getListeners(TreeExpansionListener.class);
661          }    }
662    
663          /**    /**
664           * Notifies all listeners that the tree was collapsed.     * Notifies all listeners that the tree was collapsed.
665           *     *
666           * @param path the path to the node that was collapsed     * @param path the path to the node that was collapsed
667           */     */
668          public void fireTreeCollapsed(TreePath path)    public void fireTreeCollapsed(TreePath path)
669          {    {
670                  TreeExpansionEvent event = new TreeExpansionEvent(this, path);      TreeExpansionEvent event = new TreeExpansionEvent(this, path);
671                  TreeExpansionListener[] listeners = getTreeExpansionListeners();      TreeExpansionListener[] listeners = getTreeExpansionListeners();
672    
673                  for (int index = 0; index < listeners.length; ++index)      for (int index = 0; index < listeners.length; ++index)
674                          listeners[index].treeCollapsed(event);        listeners[index].treeCollapsed(event);
675          }    }
676    
677          /**    /**
678           * Notifies all listeners that the tree was expanded.     * Notifies all listeners that the tree was expanded.
679           *     *
680           * @param path the path to the node that was expanded     * @param path the path to the node that was expanded
681           */     */
682          public void fireTreeExpanded(TreePath path)    public void fireTreeExpanded(TreePath path)
683          {    {
684                  TreeExpansionEvent event = new TreeExpansionEvent(this, path);      TreeExpansionEvent event = new TreeExpansionEvent(this, path);
685                  TreeExpansionListener[] listeners = getTreeExpansionListeners();      TreeExpansionListener[] listeners = getTreeExpansionListeners();
686    
687                  for (int index = 0; index < listeners.length; ++index)      for (int index = 0; index < listeners.length; ++index)
688                          listeners[index].treeExpanded(event);        listeners[index].treeExpanded(event);
689          }    }
690    
691          /**    /**
692           * Adds a <code>TreeSelctionListener</code> object to the tree.     * Adds a <code>TreeSelctionListener</code> object to the tree.
693           *     *
694           * @param listener the listener to add     * @param listener the listener to add
695           */     */
696          public void addTreeSelectionListener(TreeSelectionListener listener)    public void addTreeSelectionListener(TreeSelectionListener listener)
697          {    {
698        listenerList.add(TreeSelectionListener.class, listener);      listenerList.add(TreeSelectionListener.class, listener);
699          }    }
700    
701          /**    /**
702           * Removes a <code>TreeSelectionListener</code> object from the tree.     * Removes a <code>TreeSelectionListener</code> object from the tree.
703           *     *
704           * @param listener the listener to remove     * @param listener the listener to remove
705           */     */
706          public void removeTreeSelectionListener(TreeSelectionListener listener)    public void removeTreeSelectionListener(TreeSelectionListener listener)
707          {    {
708                  listenerList.remove(TreeSelectionListener.class, listener);      listenerList.remove(TreeSelectionListener.class, listener);
709          }    }
710    
711          /**    /**
712           * Returns all added <code>TreeSelectionListener</code> objects.     * Returns all added <code>TreeSelectionListener</code> objects.
713           *     *
714           * @return an array of listeners     * @return an array of listeners
715           */     */
716          public TreeSelectionListener[] getTreeSelectionListeners()    public TreeSelectionListener[] getTreeSelectionListeners()
717          {    {
718                  return (TreeSelectionListener[])      return (TreeSelectionListener[])
719                                          getListeners(TreeSelectionListener.class);      getListeners(TreeSelectionListener.class);
720          }    }
721    
722          /**    /**
723           * Notifies all listeners when the selection of the tree changed.     * Notifies all listeners when the selection of the tree changed.
724           *     *
725           * @param event the event to send     * @param event the event to send
726           */     */
727          protected void fireValueChanged(TreeSelectionEvent event)    protected void fireValueChanged(TreeSelectionEvent event)
728          {    {
729                  TreeSelectionListener[] listeners = getTreeSelectionListeners();      TreeSelectionListener[] listeners = getTreeSelectionListeners();
730    
731                  for (int index = 0; index < listeners.length; ++index)      for (int index = 0; index < listeners.length; ++index)
732                          listeners[index].valueChanged(event);        listeners[index].valueChanged(event);
733          }    }
734    
735          /**    /**
736           * Adds a <code>TreeWillExpandListener</code> object to the tree.     * Adds a <code>TreeWillExpandListener</code> object to the tree.
737           *     *
738           * @param listener the listener to add     * @param listener the listener to add
739           */     */
740          public void addTreeWillExpandListener(TreeWillExpandListener listener)    public void addTreeWillExpandListener(TreeWillExpandListener listener)
741          {    {
742                  listenerList.add(TreeWillExpandListener.class, listener);      listenerList.add(TreeWillExpandListener.class, listener);
743          }    }
744    
745          /**    /**
746           * Removes a <code>TreeWillExpandListener</code> object from the tree.     * Removes a <code>TreeWillExpandListener</code> object from the tree.
747           *     *
748           * @param listener the listener to remove     * @param listener the listener to remove
749           */     */
750          public void removeTreeWillExpandListener(TreeWillExpandListener listener)    public void removeTreeWillExpandListener(TreeWillExpandListener listener)
751          {    {
752                  listenerList.remove(TreeWillExpandListener.class, listener);      listenerList.remove(TreeWillExpandListener.class, listener);
753          }    }
754    
755          /**    /**
756           * Returns all added <code>TreeWillExpandListener</code> objects.     * Returns all added <code>TreeWillExpandListener</code> objects.
757           *     *
758           * @return an array of listeners     * @return an array of listeners
759           */     */
760          public TreeWillExpandListener[] getTreeWillExpandListeners()    public TreeWillExpandListener[] getTreeWillExpandListeners()
761          {    {
762                  return (TreeWillExpandListener[])      return (TreeWillExpandListener[])
763                                          getListeners(TreeWillExpandListener.class);      getListeners(TreeWillExpandListener.class);
764          }    }
765    
766          /**    /**
767           * Notifies all listeners that the tree will collapse.     * Notifies all listeners that the tree will collapse.
768           *     *
769           * @param path the path to the node that will collapse     * @param path the path to the node that will collapse
770           */     */
771          public void fireTreeWillCollapse(TreePath path) throws ExpandVetoException    public void fireTreeWillCollapse(TreePath path) throws ExpandVetoException
772          {    {
773                  TreeExpansionEvent event = new TreeExpansionEvent(this, path);      TreeExpansionEvent event = new TreeExpansionEvent(this, path);
774                  TreeWillExpandListener[] listeners = getTreeWillExpandListeners();      TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
775    
776                  for (int index = 0; index < listeners.length; ++index)      for (int index = 0; index < listeners.length; ++index)
777                          listeners[index].treeWillCollapse(event);        listeners[index].treeWillCollapse(event);
778          }    }
779    
780          /**    /**
781           * Notifies all listeners that the tree will expand.     * Notifies all listeners that the tree will expand.
782           *     *
783           * @param path the path to the node that will expand     * @param path the path to the node that will expand
784           */     */
785          public void fireTreeWillExpand(TreePath path) throws ExpandVetoException    public void fireTreeWillExpand(TreePath path) throws ExpandVetoException
786          {    {
787                  TreeExpansionEvent event = new TreeExpansionEvent(this, path);      TreeExpansionEvent event = new TreeExpansionEvent(this, path);
788                  TreeWillExpandListener[] listeners = getTreeWillExpandListeners();      TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
789    
790                  for (int index = 0; index < listeners.length; ++index)      for (int index = 0; index < listeners.length; ++index)
791                          listeners[index].treeWillExpand(event);        listeners[index].treeWillExpand(event);
792          }    }
793    
794          /**    /**
795           * Returns the model of this <code>JTree</code> object.     * Returns the model of this <code>JTree</code> object.
796           *     *
797           * @return the associated <code>TreeModel</code>     * @return the associated <code>TreeModel</code>
798           */     */
799          public TreeModel getModel()    public TreeModel getModel()
800          {    {
801                  return treeModel;      return treeModel;
802          }    }
803    
804          /**    /**
805           * Sets the model to use in <code>JTree</code>.     * Sets the model to use in <code>JTree</code>.
806           *     *
807           * @param model the <code>TreeModel</code> to use     * @param model the <code>TreeModel</code> to use
808           */     */
809          public void setModel(TreeModel model)    public void setModel(TreeModel model)
810          {    {
811                  if (treeModel == model)      if (treeModel == model)
812                          return;        return;
813        
814                  // add treeModelListener to the new model      // add treeModelListener to the new model
815                  if (treeModelListener == null)      if (treeModelListener == null)
816                          treeModelListener = createTreeModelListener();        treeModelListener = createTreeModelListener();
817                  if (model != null) // as setModel(null) is allowed      if (model != null) // as setModel(null) is allowed
818                          model.addTreeModelListener(treeModelListener);        model.addTreeModelListener(treeModelListener);
819        
820      TreeModel oldValue = treeModel;      TreeModel oldValue = treeModel;
821      treeModel = model;      treeModel = model;
822    
823      firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model);      firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model);
824          }    }
825    
826          /**    /**
827           * Checks if this <code>JTree</code> object is editable.     * Checks if this <code>JTree</code> object is editable.
828           *     *
829           * @return <code>true</code> if this tree object is editable,     * @return <code>true</code> if this tree object is editable,
830           *         <code>false</code> otherwise     *         <code>false</code> otherwise
831           */     */
832          public boolean isEditable()    public boolean isEditable()
833          {    {
834                  return editable;      return editable;
835          }    }
   
         /**  
          * Sets the <code>editable</code> property.  
          *  
          * @param flag <code>true</code> to make this tree object editable,  
          *        <code>false</code> otherwise  
          */  
         public void setEditable(boolean flag)  
         {  
                 if (editable == flag)  
                         return;  
   
                 boolean oldValue = editable;  
                 editable = flag;  
                 firePropertyChange(EDITABLE_PROPERTY, oldValue, editable);  
         }  
   
         /**  
          * Checks if the root element is visible.  
          *  
          * @return <code>true</code> if the root element is visible,  
          *         <code>false</code> otherwise  
          */  
         public boolean isRootVisible()  
         {  
                 return rootVisible;  
         }  
   
         public void setRootVisible(boolean flag)  
         {  
                 if (rootVisible == flag)  
                         return;  
   
                 boolean oldValue = rootVisible;  
                 rootVisible = flag;  
                 firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);  
         }  
   
         public boolean getShowsRootHandles()  
         {  
                 return showsRootHandles;  
         }  
   
         public void setShowsRootHandles(boolean flag)  
         {  
                 if (showsRootHandles == flag)  
                         return;  
   
                 boolean oldValue = showsRootHandles;  
                 showsRootHandles = flag;  
                 firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue, flag);  
         }  
   
         public TreeCellEditor getCellEditor()  
         {  
   
                 return cellEditor;  
         }  
   
         public void setCellEditor(TreeCellEditor editor)  
         {  
                 if (cellEditor == editor)  
                         return;  
   
                 TreeCellEditor oldValue = cellEditor;  
                 cellEditor = editor;  
                 firePropertyChange(CELL_EDITOR_PROPERTY, oldValue, editor);  
         }  
   
         public TreeCellRenderer getCellRenderer()  
         {  
                 return cellRenderer;  
         }  
   
         public void setCellRenderer(TreeCellRenderer newRenderer)  
         {  
                 if (cellRenderer == newRenderer)  
                         return;  
   
                 TreeCellRenderer oldValue = cellRenderer;  
                 cellRenderer = newRenderer;  
                 firePropertyChange(CELL_RENDERER_PROPERTY, oldValue, newRenderer);  
         }  
   
         public TreeSelectionModel getSelectionModel()  
         {  
                 return selectionModel;  
         }  
   
         public void setSelectionModel(TreeSelectionModel model)  
         {  
                 if (selectionModel == model)  
                         return;  
   
                 if (selectionModel != null)  
                         selectionModel.removeTreeSelectionListener(selectionRedirector);  
   
                 TreeSelectionModel oldValue = selectionModel;  
                 selectionModel = model;  
   
                 if (selectionModel != null)  
                         selectionModel.addTreeSelectionListener(selectionRedirector);  
   
                 firePropertyChange(SELECTION_MODEL_PROPERTY, oldValue, model);  
                 revalidate();  
                 repaint();  
         }  
   
         public int getVisibleRowCount()  
         {  
                 return visibleRowCount;  
         }  
   
         public void setVisibleRowCount(int rows)  
         {  
                 if (visibleRowCount == rows)  
                         return;  
   
                 int oldValue = visibleRowCount;  
                 visibleRowCount = rows;  
                 firePropertyChange(VISIBLE_ROW_COUNT_PROPERTY, oldValue, rows);  
         }  
   
         public boolean isLargeModel()  
         {  
                 return largeModel;  
         }  
   
         public void setLargeModel(boolean large)  
         {  
                 if (largeModel == large)  
                         return;  
   
                 boolean oldValue = largeModel;  
                 largeModel = large;  
                 firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, large);  
         }  
   
         public int getRowHeight()  
         {  
   
                 return rowHeight;  
         }  
   
         public void setRowHeight(int height)  
         {  
                 if (rowHeight == height)  
                         return;  
   
                 int oldValue = rowHeight;  
                 rowHeight = height;  
                 firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, height);  
         }  
   
         public boolean isFixedRowHeight()  
         {  
                 return rowHeight > 0;  
         }  
   
         public boolean getInvokesStopCellEditing()  
         {  
                 return invokesStopCellEditing;  
         }  
   
         public void setInvokesStopCellEditing(boolean invoke)  
         {  
                 if (invokesStopCellEditing == invoke)  
                         return;  
   
                 boolean oldValue = invokesStopCellEditing;  
                 invokesStopCellEditing = invoke;  
                 firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY,  
                                                                                                 oldValue, invoke);  
         }  
836    
837          /**    /**
838           * @since 1.3     * Sets the <code>editable</code> property.
839           */     *
840          public int getToggleClickCount()     * @param flag <code>true</code> to make this tree object editable,
841          {     *        <code>false</code> otherwise
842                  return toggleClickCount;     */
843          }    public void setEditable(boolean flag)
844      {
845        if (editable == flag)
846          return;
847    
848          /**      boolean oldValue = editable;
849           * @since 1.3      editable = flag;
850           */      firePropertyChange(EDITABLE_PROPERTY, oldValue, editable);
851          public void setToggleClickCount(int count)    }
         {  
                 if (toggleClickCount == count)  
                         return;  
   
                 int oldValue = toggleClickCount;  
                 toggleClickCount = count;  
                 firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY, oldValue, count);  
         }  
   
         public void scrollPathToVisible(TreePath path)  
         {  
                 if (path == null)  
                         return;  
   
                 Rectangle rect = getPathBounds(path);  
   
                 if (rect == null)  
                         return;  
   
                 scrollRectToVisible(rect);  
         }  
   
         public void scrollRowToVisible(int row)  
         {  
                 scrollPathToVisible(getPathForRow(row));  
         }  
   
         public boolean getScrollsOnExpand()  
         {  
                 return scrollsOnExpand;  
         }  
   
         public void setScrollsOnExpand(boolean scroll)  
         {  
                 if (scrollsOnExpand == scroll)  
                         return;  
   
                 boolean oldValue = scrollsOnExpand;  
                 scrollsOnExpand = scroll;  
                 firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue, scroll);  
         }  
   
         public void setSelectionPath(TreePath path)  
         {  
                 selectionModel.setSelectionPath(path);  
         }  
   
         public void setSelectionPaths(TreePath[] paths)  
         {  
                 selectionModel.setSelectionPaths(paths);  
         }  
   
         public void setSelectionRow(int row)  
         {  
                 TreePath path = getPathForRow(row);  
   
                 if (path != null)  
                         selectionModel.setSelectionPath(path);  
         }  
   
         public void setSelectionRows(int[] rows)  
         {  
                 // Make sure we have an UI so getPathForRow() does not return null.  
                 if (rows == null || getUI() == null)  
                         return;  
   
                 TreePath[] paths = new TreePath[rows.length];  
   
                 for (int i = rows.length - 1; i >= 0; --i)  
                         paths[i] = getPathForRow(rows[i]);  
   
                 setSelectionPaths(paths);  
         }  
   
         public void setSelectionInterval(int index0, int index1)  
         {  
                 TreePath[] paths = getPathBetweenRows(index0, index1);  
   
                 if (paths != null)  
                         setSelectionPaths(paths);  
         }  
   
         public void addSelectionPath(TreePath path)  
         {  
                 selectionModel.addSelectionPath(path);  
         }  
   
         public void addSelectionPaths(TreePath[] paths)  
         {  
                 selectionModel.addSelectionPaths(paths);  
         }  
   
         public void addSelectionRow(int row)  
         {  
                 TreePath path = getPathForRow(row);  
   
                 if (path != null)  
                         selectionModel.addSelectionPath(path);  
         }  
   
         public void addSelectionRows(int[] rows)  
         {  
                 // Make sure we have an UI so getPathForRow() does not return null.  
                 if (rows == null || getUI() == null)  
                         return;  
   
                 TreePath[] paths = new TreePath[rows.length];  
   
                 for (int i = rows.length - 1; i >= 0; --i)  
                         paths[i] = getPathForRow(rows[i]);  
   
                 addSelectionPaths(paths);  
         }  
   
         public void addSelectionInterval(int index0, int index1)  
         {  
                 TreePath[] paths = getPathBetweenRows(index0, index1);  
   
                 if (paths != null)  
                         addSelectionPaths(paths);  
         }  
   
         public void removeSelectionPath(TreePath path)  
         {  
                 selectionModel.removeSelectionPath(path);  
         }  
   
         public void removeSelectionPaths(TreePath[] paths)  
         {  
                 selectionModel.removeSelectionPaths(paths);  
         }  
   
         public void removeSelectionRow(int row)  
         {  
                 TreePath path = getPathForRow(row);  
   
                 if (path != null)  
                         selectionModel.removeSelectionPath(path);  
         }  
   
         public void removeSelectionRows(int[] rows)  
         {  
                 if (rows == null || getUI() == null)  
                         return;  
   
                 TreePath[] paths = new TreePath[rows.length];  
   
                 for (int i = rows.length - 1; i >= 0; --i)  
                         paths[i] = getPathForRow(rows[i]);  
   
                 removeSelectionPaths(paths);  
         }  
   
         public void removeSelectionInterval(int index0, int index1)  
         {  
                 TreePath[] paths = getPathBetweenRows(index0, index1);  
   
                 if (paths != null)  
                         removeSelectionPaths(paths);  
         }  
   
         public void clearSelection()  
         {  
                 selectionModel.clearSelection();  
       setLeadSelectionPath(null);  
         }  
   
         public TreePath getLeadSelectionPath()  
         {  
                 return leadSelectionPath;  
         }  
852    
853          /**    /**
854           * @since 1.3     * Checks if the root element is visible.
855           */     *
856          public void setLeadSelectionPath(TreePath path)     * @return <code>true</code> if the root element is visible,
857          {     *         <code>false</code> otherwise
858                  if (leadSelectionPath == path)     */
859                          return;    public boolean isRootVisible()
860      {
861                  TreePath oldValue = leadSelectionPath;      return rootVisible;
862                  leadSelectionPath = path;    }
                 firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);  
         }  
863    
864          /**    public void setRootVisible(boolean flag)
865           * @since 1.3    {
866           */      if (rootVisible == flag)
867          public TreePath getAnchorSelectionPath()        return;
         {  
                 return anchorSelectionPath;  
         }  
868    
869          /**      boolean oldValue = rootVisible;
870           * @since 1.3      rootVisible = flag;
871           */      firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
872          public void setAnchorSelectionPath(TreePath path)    }
         {  
                 if (anchorSelectionPath == path)  
                         return;  
   
                 TreePath oldValue = anchorSelectionPath;  
                 anchorSelectionPath = path;  
                 firePropertyChange(ANCHOR_SELECTION_PATH_PROPERTY, oldValue, path);  
         }  
   
         public int getLeadSelectionRow()  
         {  
                 return selectionModel.getLeadSelectionRow();  
         }  
   
         public int getMaxSelectionRow()  
         {  
                 return selectionModel.getMaxSelectionRow();  
         }  
   
         public int getMinSelectionRow()  
         {  
                 return selectionModel.getMinSelectionRow();  
         }  
   
         public int getSelectionCount()  
         {  
                 return selectionModel.getSelectionCount();  
         }  
   
         public TreePath getSelectionPath()  
         {  
                 return selectionModel.getSelectionPath();  
         }  
   
         public TreePath[] getSelectionPaths()  
         {  
                 return selectionModel.getSelectionPaths();  
         }  
   
         public int[] getSelectionRows()  
         {  
                 return selectionModel.getSelectionRows();  
         }  
   
         public boolean isPathSelected(TreePath path)  
         {  
                 return selectionModel.isPathSelected(path);  
         }  
   
         public boolean isRowSelected(int row)  
         {  
                 return selectionModel.isPathSelected(getPathForRow(row));  
         }  
   
         public boolean isSelectionEmpty()  
         {  
                 return selectionModel.isSelectionEmpty();  
         }  
   
         /**  
          * Return the value of the <code>dragEnabled</code> property.  
          *  
          * @return the value  
          *  
          * @since 1.4  
          */  
         public boolean getDragEnabled()  
         {  
                 return dragEnabled;  
         }  
   
         /**  
          * Set the <code>dragEnabled</code> property.  
          *  
          * @param enabled new value  
          *  
          * @since 1.4  
          */  
         public void setDragEnabled(boolean enabled)  
         {  
873    
874                  dragEnabled = enabled;    public boolean getShowsRootHandles()
875          }    {
876        return showsRootHandles;
877      }
878    
879          public int getRowCount()    public void setShowsRootHandles(boolean flag)
880          {    {
881                  TreeUI ui = getUI();      if (showsRootHandles == flag)
882          return;
883        
884        boolean oldValue = showsRootHandles;
885        showsRootHandles = flag;
886        firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue, flag);
887      }
888    
889                  if (ui != null)    public TreeCellEditor getCellEditor()
890                          return ui.getRowCount(this);    {
891        return cellEditor;
892      }
893    
894                  return 0;    public void setCellEditor(TreeCellEditor editor)
895          }    {
896        if (cellEditor == editor)
897          return;
898    
899          public void collapsePath(TreePath path)      TreeCellEditor oldValue = cellEditor;
900      {      cellEditor = editor;
901        try      firePropertyChange(CELL_EDITOR_PROPERTY, oldValue, editor);
902          {    }
           fireTreeWillCollapse(path);  
         }  
       catch (ExpandVetoException ev)  
         {  
         }  
       setExpandedState(path, false);  
       fireTreeCollapsed(path);  
     }  
903    
904          public void collapseRow(int row)    public TreeCellRenderer getCellRenderer()
905          {    {
906                  if (row < 0 || row >= getRowCount())      return cellRenderer;
907                          return;    }
   
                 TreePath path = getPathForRow(row);  
   
                 if (path != null)  
                         collapsePath(path);  
         }  
908    
909          public void expandPath(TreePath path)    public void setCellRenderer(TreeCellRenderer newRenderer)
910      {    {
911        // Don't expand if last path component is a leaf node.      if (cellRenderer == newRenderer)
912        if ((path == null) || (treeModel.isLeaf(path.getLastPathComponent())))        return;
         return;  
     
       try  
         {  
           fireTreeWillExpand(path);  
         }  
       catch (ExpandVetoException ev)  
         {  
         }  
     
       setExpandedState(path, true);  
       fireTreeExpanded(path);  
     }  
913    
914          public void expandRow(int row)      TreeCellRenderer oldValue = cellRenderer;
915          {      cellRenderer = newRenderer;
916                  if (row < 0 || row >= getRowCount())      firePropertyChange(CELL_RENDERER_PROPERTY, oldValue, newRenderer);
917                          return;    }
918    
919                  TreePath path = getPathForRow(row);    public TreeSelectionModel getSelectionModel()
920      {
921        return selectionModel;
922      }
923    
924                  if (path != null)    public void setSelectionModel(TreeSelectionModel model)
925                          expandPath(path);    {
926          }      if (selectionModel == model)
927          return;
928    
929          public boolean isCollapsed(TreePath path)      if (selectionModel != null)
930          {        selectionModel.removeTreeSelectionListener(selectionRedirector);
                 return !isExpanded(path);  
         }  
931    
932          public boolean isCollapsed(int row)      TreeSelectionModel oldValue = selectionModel;
933          {      selectionModel = model;
                 if (row < 0 || row >= getRowCount())  
                         return false;  
934    
935                  TreePath path = getPathForRow(row);      if (selectionModel != null)
936          selectionModel.addTreeSelectionListener(selectionRedirector);
937    
938                  if (path != null)      firePropertyChange(SELECTION_MODEL_PROPERTY, oldValue, model);
939                          return isCollapsed(path);      revalidate();
940        repaint();
941      }
942    
943                  return false;    public int getVisibleRowCount()
944          }    {
945        return visibleRowCount;
946      }
947    
948          public boolean isExpanded(TreePath path)    public void setVisibleRowCount(int rows)
949          {    {
950                  if (path == null)      if (visibleRowCount == rows)
951                          return false;        return;
952    
953                  Object state = nodeStates.get(path);      int oldValue = visibleRowCount;
954        visibleRowCount = rows;
955        firePropertyChange(VISIBLE_ROW_COUNT_PROPERTY, oldValue, rows);
956      }
957    
958                  if ((state == null) || (state != EXPANDED))    public boolean isLargeModel()
959                          return false;    {
960        return largeModel;
961      }
962    
963                  TreePath parent = path.getParentPath();    public void setLargeModel(boolean large)
964      {
965        if (largeModel == large)
966          return;
967    
968                  if (parent != null)      boolean oldValue = largeModel;
969                          return isExpanded(parent);      largeModel = large;
970        firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, large);
971      }
972    
973                  return true;    public int getRowHeight()
974          }    {
975        return rowHeight;
976      }
977    
978          public boolean isExpanded(int row)    public void setRowHeight(int height)
979          {    {
980                  if (row < 0 || row >= getRowCount())      if (rowHeight == height)
981                          return false;        return;
982    
983                  TreePath path = getPathForRow(row);      int oldValue = rowHeight;
984        rowHeight = height;
985        firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, height);
986      }
987    
988                  if (path != null)    public boolean isFixedRowHeight()
989                          return isExpanded(path);    {
990        return rowHeight > 0;
991      }
992    
993                  return false;    public boolean getInvokesStopCellEditing()
994          }    {
995        return invokesStopCellEditing;
996      }
997    
998          /**    public void setInvokesStopCellEditing(boolean invoke)
999           * @since 1.3    {
1000           */      if (invokesStopCellEditing == invoke)
1001          public boolean getExpandsSelectedPaths()        return;
         {  
                 return expandsSelectedPaths;  
         }  
1002    
1003          /**      boolean oldValue = invokesStopCellEditing;
1004           * @since 1.3      invokesStopCellEditing = invoke;
1005           */      firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY,
1006          public void setExpandsSelectedPaths(boolean flag)                         oldValue, invoke);
1007          {    }
                 if (expandsSelectedPaths == flag)  
                         return;  
1008    
1009                  boolean oldValue = expandsSelectedPaths;    /**
1010                  expandsSelectedPaths = flag;     * @since 1.3
1011                  firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY, oldValue, flag);     */
1012          }    public int getToggleClickCount()
1013      {
1014        return toggleClickCount;
1015      }
1016    
1017      /**
1018       * @since 1.3
1019       */
1020      public void setToggleClickCount(int count)
1021      {
1022        if (toggleClickCount == count)
1023          return;
1024    
1025        int oldValue = toggleClickCount;
1026        toggleClickCount = count;
1027        firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY, oldValue, count);
1028      }
1029    
1030      public void scrollPathToVisible(TreePath path)
1031      {
1032        if (path == null)
1033          return;
1034    
1035          public Rectangle getPathBounds(TreePath path)      Rectangle rect = getPathBounds(path);
         {  
                 TreeUI ui = getUI();  
1036    
1037                  if (ui == null)      if (rect == null)
1038                          return null;        return;
1039    
1040        scrollRectToVisible(rect);
1041      }
1042    
1043                  return ui.getPathBounds(this, path);    public void scrollRowToVisible(int row)
1044          }    {
1045        scrollPathToVisible(getPathForRow(row));
1046      }
1047    
1048      public boolean getScrollsOnExpand()
1049      {
1050        return scrollsOnExpand;
1051      }
1052    
1053      public void setScrollsOnExpand(boolean scroll)
1054      {
1055        if (scrollsOnExpand == scroll)
1056          return;
1057    
1058        boolean oldValue = scrollsOnExpand;
1059        scrollsOnExpand = scroll;
1060        firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue, scroll);
1061      }
1062    
1063      public void setSelectionPath(TreePath path)
1064      {
1065        selectionModel.setSelectionPath(path);
1066      }
1067    
1068      public void setSelectionPaths(TreePath[] paths)
1069      {
1070        selectionModel.setSelectionPaths(paths);
1071      }
1072    
1073      public void setSelectionRow(int row)
1074      {
1075        TreePath path = getPathForRow(row);
1076    
1077        if (path != null)
1078          selectionModel.setSelectionPath(path);
1079      }
1080    
1081      public void setSelectionRows(int[] rows)
1082      {
1083        // Make sure we have an UI so getPathForRow() does not return null.
1084        if (rows == null || getUI() == null)
1085          return;
1086    
1087        TreePath[] paths = new TreePath[rows.length];
1088    
1089        for (int i = rows.length - 1; i >= 0; --i)
1090          paths[i] = getPathForRow(rows[i]);
1091    
1092        setSelectionPaths(paths);
1093      }
1094    
1095      public void setSelectionInterval(int index0, int index1)
1096      {
1097        TreePath[] paths = getPathBetweenRows(index0, index1);
1098    
1099          public Rectangle getRowBounds(int row)      if (paths != null)
1100          {        setSelectionPaths(paths);
1101                  TreePath path = getPathForRow(row);    }
1102    
1103                  if (path != null)    public void addSelectionPath(TreePath path)
1104                          return getPathBounds(path);    {
1105        selectionModel.addSelectionPath(path);
1106      }
1107    
1108                  return null;    public void addSelectionPaths(TreePath[] paths)
1109          }    {
1110        selectionModel.addSelectionPaths(paths);
1111      }
1112    
1113          public boolean isEditing()    public void addSelectionRow(int row)
1114          {    {
1115                  TreeUI ui = getUI();      TreePath path = getPathForRow(row);
1116    
1117                  if (ui != null)      if (path != null)
1118                          return ui.isEditing(this);        selectionModel.addSelectionPath(path);
1119      }
1120    
1121                  return false;    public void addSelectionRows(int[] rows)
1122          }    {
1123        // Make sure we have an UI so getPathForRow() does not return null.
1124        if (rows == null || getUI() == null)
1125          return;
1126    
1127          public boolean stopEditing()      TreePath[] paths = new TreePath[rows.length];
         {  
                 TreeUI ui = getUI();  
1128    
1129                  if (ui != null)      for (int i = rows.length - 1; i >= 0; --i)
1130                          return ui.stopEditing(this);        paths[i] = getPathForRow(rows[i]);
1131    
1132                  return false;      addSelectionPaths(paths);
1133          }    }
1134    
1135          public void cancelEditing()    public void addSelectionInterval(int index0, int index1)
1136          {    {
1137                  TreeUI ui = getUI();      TreePath[] paths = getPathBetweenRows(index0, index1);
1138    
1139                  if (ui != null)      if (paths != null)
1140                          ui.cancelEditing(this);        addSelectionPaths(paths);
1141          }    }
1142    
1143          public void startEditingAtPath(TreePath path)    public void removeSelectionPath(TreePath path)
1144          {    {
1145                  TreeUI ui = getUI();      selectionModel.removeSelectionPath(path);
1146      }
1147    
1148                  if (ui != null)    public void removeSelectionPaths(TreePath[] paths)
1149                          ui.startEditingAtPath(this, path);    {
1150          }      selectionModel.removeSelectionPaths(paths);
1151      }
1152    
1153          public TreePath getEditingPath()    public void removeSelectionRow(int row)
1154          {    {
1155                  TreeUI ui = getUI();      TreePath path = getPathForRow(row);
1156    
1157                  if (ui != null)      if (path != null)
1158                          return ui.getEditingPath(this);        selectionModel.removeSelectionPath(path);
1159      }
1160    
1161                  return null;    public void removeSelectionRows(int[] rows)
1162          }    {
1163        if (rows == null || getUI() == null)
1164          return;
1165    
1166          public TreePath getPathForLocation(int x, int y)      TreePath[] paths = new TreePath[rows.length];
         {  
                 TreePath path = getClosestPathForLocation(x, y);  
1167    
1168                  if (path != null)      for (int i = rows.length - 1; i >= 0; --i)
1169                  {        paths[i] = getPathForRow(rows[i]);
                         Rectangle rect = getPathBounds(path);  
1170    
1171                          if ((rect != null) && rect.contains(x, y))      removeSelectionPaths(paths);
1172                                  return path;    }
                 }  
1173    
1174                  return null;    public void removeSelectionInterval(int index0, int index1)
1175          }    {
1176        TreePath[] paths = getPathBetweenRows(index0, index1);
1177    
1178          public int getRowForLocation(int x, int y)      if (paths != null)
1179          {        removeSelectionPaths(paths);
1180                  TreePath path = getPathForLocation(x, y);    }
1181    
1182                  if (path != null)    public void clearSelection()
1183                          return getRowForPath(path);    {
1184        selectionModel.clearSelection();
1185        setLeadSelectionPath(null);
1186      }
1187    
1188                  return -1;    public TreePath getLeadSelectionPath()
1189          }    {
1190        return leadSelectionPath;
1191      }
1192    
1193          public TreePath getClosestPathForLocation(int x, int y)    /**
1194          {     * @since 1.3
1195                  TreeUI ui = getUI();     */
1196      public void setLeadSelectionPath(TreePath path)
1197      {
1198        if (leadSelectionPath == path)
1199          return;
1200        
1201        TreePath oldValue = leadSelectionPath;
1202        leadSelectionPath = path;
1203        firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);
1204      }
1205    
1206                  if (ui != null)    /**
1207                          return ui.getClosestPathForLocation(this, x, y);     * @since 1.3
1208       */
1209      public TreePath getAnchorSelectionPath()
1210      {
1211        return anchorSelectionPath;
1212      }
1213    
1214                  return null;    /**
1215          }     * @since 1.3
1216       */
1217      public void setAnchorSelectionPath(TreePath path)
1218      {
1219        if (anchorSelectionPath == path)
1220          return;
1221    
1222          public int getClosestRowForLocation(int x, int y)      TreePath oldValue = anchorSelectionPath;
1223          {      anchorSelectionPath = path;
1224                  TreePath path = getClosestPathForLocation(x, y);      firePropertyChange(ANCHOR_SELECTION_PATH_PROPERTY, oldValue, path);
1225      }
1226    
1227                  if (path != null)    public int getLeadSelectionRow()
1228                          return getRowForPath(path);    {
1229        return selectionModel.getLeadSelectionRow();
1230      }
1231    
1232                  return -1;    public int getMaxSelectionRow()
1233          }    {
1234        return selectionModel.getMaxSelectionRow();
1235      }
1236    
1237          public Object getLastSelectedPathComponent()    public int getMinSelectionRow()
1238          {    {
1239                  TreePath path = getSelectionPath();      return selectionModel.getMinSelectionRow();
1240      }
1241    
1242                  if (path != null)    public int getSelectionCount()
1243                          return path.getLastPathComponent();    {
1244        return selectionModel.getSelectionCount();
1245      }
1246    
1247                  return null;    public TreePath getSelectionPath()
1248          }    {
1249        return selectionModel.getSelectionPath();
1250      }
1251    
1252          private void doExpandParents(TreePath path, boolean state)    public TreePath[] getSelectionPaths()
1253          {    {
1254                  TreePath parent = path.getParentPath();              return selectionModel.getSelectionPaths();
1255              }
                 if (!isExpanded(parent) && parent != null)  
                         doExpandParents(parent, false);  
1256    
1257                  nodeStates.put(path, state ? EXPANDED : COLLAPSED);    public int[] getSelectionRows()
1258          }    {
1259        return selectionModel.getSelectionRows();
1260      }
1261    
1262          protected void setExpandedState(TreePath path, boolean state)    public boolean isPathSelected(TreePath path)
1263          {    {
1264                  if (path == null)      return selectionModel.isPathSelected(path);
1265                          return;    }
                 TreePath parent = path.getParentPath();  
1266    
1267                  doExpandParents(path, state);    public boolean isRowSelected(int row)
1268          }    {
1269        return selectionModel.isPathSelected(getPathForRow(row));
1270      }
1271    
1272          protected void clearToggledPaths()    public boolean isSelectionEmpty()
1273          {    {
1274                  nodeStates.clear();      return selectionModel.isSelectionEmpty();
1275          }    }
1276    
1277          protected Enumeration getDescendantToggledPaths(TreePath parent)    /**
1278          {     * Return the value of the <code>dragEnabled</code> property.
1279                  if (parent == null)     *
1280                          return null;     * @return the value
1281       *
1282       * @since 1.4
1283       */
1284      public boolean getDragEnabled()
1285      {
1286        return dragEnabled;
1287      }
1288    
1289                  Enumeration nodes = nodeStates.keys();    /**
1290                  Vector result = new Vector();     * Set the <code>dragEnabled</code> property.
1291       *
1292       * @param enabled new value
1293       *
1294       * @since 1.4
1295       */
1296      public void setDragEnabled(boolean enabled)
1297      {
1298        dragEnabled = enabled;
1299      }
1300    
1301                  while (nodes.hasMoreElements())    public int getRowCount()
1302                  {    {
1303                          TreePath path = (TreePath) nodes.nextElement();      TreeUI ui = getUI();
1304    
1305                          if (path.isDescendant(parent))      if (ui != null)
1306                                  result.addElement(path);        return ui.getRowCount(this);
                 }  
1307    
1308                  return result.elements();      return 0;
1309          }    }
1310    
1311          public boolean hasBeenExpanded(TreePath path)    public void collapsePath(TreePath path)
1312          {    {
1313                  if (path == null)      try
1314                          return false;        {
1315            fireTreeWillCollapse(path);
1316          }
1317        catch (ExpandVetoException ev)
1318          {
1319          }
1320        setExpandedState(path, false);
1321        fireTreeCollapsed(path);
1322      }
1323    
1324                  return nodeStates.get(path) != null;    public void collapseRow(int row)
1325          }    {
1326        if (row < 0 || row >= getRowCount())
1327          return;
1328    
1329          public boolean isVisible(TreePath path)      TreePath path = getPathForRow(row);
         {  
                 if (path == null)  
                         return false;  
1330    
1331                  TreePath parent = path.getParentPath();      if (path != null)
1332          collapsePath(path);
1333      }
1334    
1335                  if (parent == null)    public void expandPath(TreePath path)
1336                          return true; // Is root node.    {
1337        // Don't expand if last path component is a leaf node.
1338        if ((path == null) || (treeModel.isLeaf(path.getLastPathComponent())))
1339          return;
1340    
1341        try
1342          {
1343            fireTreeWillExpand(path);
1344          }
1345        catch (ExpandVetoException ev)
1346          {
1347          }
1348    
1349                  return isExpanded(parent);      setExpandedState(path, true);
1350          }      fireTreeExpanded(path);
1351      }
1352    
1353          public void makeVisible(TreePath path)    public void expandRow(int row)
1354          {    {
1355                  if (path == null)      if (row < 0 || row >= getRowCount())
1356                          return;        return;
1357    
1358                  expandPath(path.getParentPath());      TreePath path = getPathForRow(row);
         }  
1359    
1360          public boolean isPathEditable(TreePath path)      if (path != null)
1361          {        expandPath(path);
1362                  return isEditable();    }
         }  
1363    
1364          /**    public boolean isCollapsed(TreePath path)
1365           * Creates and returns an instance of {@link TreeModelHandler}.    {
1366           *      return !isExpanded(path);
1367           * @returns an instance of {@link TreeModelHandler}    }
1368           */  
1369          protected TreeModelListener createTreeModelListener()    public boolean isCollapsed(int row)
1370          {    {
1371                  return new TreeModelHandler();      if (row < 0 || row >= getRowCount())
1372          }        return false;
1373    
1374          /**      TreePath path = getPathForRow(row);
1375           * Returns a sample TreeModel that can be used in a JTree. This can be used  
1376           * in Bean- or GUI-Builders to show something interesting.      if (path != null)
1377           *        return isCollapsed(path);
1378           * @return a sample TreeModel that can be used in a JTree  
1379           */      return false;
1380          protected static TreeModel getDefaultTreeModel()    }
1381          {  
1382                  DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root node");    public boolean isExpanded(TreePath path)
1383                  DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(    {
1384                                  "Child node 1");      if (path == null)
1385                  DefaultMutableTreeNode child11 = new DefaultMutableTreeNode(        return false;
1386                                  "Child node 1.1");  
1387                  DefaultMutableTreeNode child12 = new DefaultMutableTreeNode(      Object state = nodeStates.get(path);
1388                                  "Child node 1.2");  
1389                  DefaultMutableTreeNode child13 = new DefaultMutableTreeNode(      if ((state == null) || (state != EXPANDED))
1390                                  "Child node 1.3");        return false;
1391                  DefaultMutableTreeNode child2 = new DefaultMutableTreeNode(  
1392                                  "Child node 2");      TreePath parent = path.getParentPath();
1393                  DefaultMutableTreeNode child21 = new DefaultMutableTreeNode(  
1394                                  "Child node 2.1");      if (parent != null)
1395                  DefaultMutableTreeNode child22 = new DefaultMutableTreeNode(        return isExpanded(parent);
1396                                  "Child node 2.2");  
1397                  DefaultMutableTreeNode child23 = new DefaultMutableTreeNode(      return true;
1398                                  "Child node 2.3");    }
1399                  DefaultMutableTreeNode child24 = new DefaultMutableTreeNode(  
1400                                  "Child node 2.4");    public boolean isExpanded(int row)
1401      {
1402                  DefaultMutableTreeNode child3 = new DefaultMutableTreeNode(      if (row < 0 || row >= getRowCount())
1403                                  "Child node 3");        return false;
1404                  root.add(child1);  
1405                  root.add(child2);      TreePath path = getPathForRow(row);
1406                  root.add(child3);  
1407                  child1.add(child11);      if (path != null)
1408                  child1.add(child12);        return isExpanded(path);
1409                  child1.add(child13);  
1410                  child2.add(child21);      return false;
1411                  child2.add(child22);    }
1412                  child2.add(child23);  
1413                  child2.add(child24);    /**
1414                  return new DefaultTreeModel(root);     * @since 1.3
1415          }     */
1416      public boolean getExpandsSelectedPaths()
1417          /**    {
1418           * Converts the specified value to a String. This is used by the renderers      return expandsSelectedPaths;
1419           * of this JTree and its nodes.    }
1420           *  
1421           * This implementation simply returns <code>value.toString()</code> and    /**
1422           * ignores all other parameters. Subclass this method to control the     * @since 1.3
1423           * conversion.     */
1424           *    public void setExpandsSelectedPaths(boolean flag)
1425           * @param value the value that is converted to a String    {
1426           * @param selected indicates if that value is selected or not      if (expandsSelectedPaths == flag)
1427           * @param expanded indicates if that value is expanded or not        return;
1428           * @param leaf indicates if that value is a leaf node or not  
1429           * @param row the row of the node      boolean oldValue = expandsSelectedPaths;
1430           * @param hasFocus indicates if that node has focus or not      expandsSelectedPaths = flag;
1431           */      firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY, oldValue, flag);
1432          public String convertValueToText(Object value, boolean selected,    }
1433                          boolean expanded, boolean leaf, int row, boolean hasFocus)  
1434          {    public Rectangle getPathBounds(TreePath path)
1435                  return value.toString();    {
1436          }      TreeUI ui = getUI();
1437    
1438          /**      if (ui == null)
1439           * A String representation of this JTree. This is intended to be used for        return null;
1440           * debugging. The returned string may be empty but may not be  
1441           * <code>null</code>.      return ui.getPathBounds(this, path);
1442           *    }
1443           * @return a String representation of this JTree  
1444           */    public Rectangle getRowBounds(int row)
1445          public String paramString()    {
1446          {      TreePath path = getPathForRow(row);
1447                  // TODO: this is completely legal, but it would possibly be nice  
1448                  // to return some more content, like the tree structure, some properties      if (path != null)
1449                  // etc ...        return getPathBounds(path);
1450                  return "";  
1451          }      return null;
1452      }
1453          /**  
1454           * Returns all TreePath objects which are a descendants of the given path    public boolean isEditing()
1455           * and are exapanded at the moment of the execution of this method. If the    {
1456           * state of any node is beeing toggled while this method is executing this      TreeUI ui = getUI();
1457           * change may be left unaccounted.  
1458           *      if (ui != null)
1459           * @param path The parent of this request        return ui.isEditing(this);
1460           * @return An Enumeration containing TreePath objects  
1461           */      return false;
1462          public Enumeration getExpandedDescendants(TreePath path)    }
1463          {  
1464                  Enumeration paths = nodeStates.keys();    public boolean stopEditing()
1465                  Vector relevantPaths = new Vector();    {
1466                  while (paths.hasMoreElements())      TreeUI ui = getUI();
1467                  {  
1468                          TreePath nextPath = (TreePath) paths.nextElement();      if (ui != null)
1469                          if (nodeStates.get(nextPath) == EXPANDED        return ui.stopEditing(this);
1470                                          && path.isDescendant(nextPath))  
1471                          {      return false;
1472                                  relevantPaths.add(nextPath);    }
1473                          }  
1474                  }    public void cancelEditing()
1475                  return relevantPaths.elements();    {
1476          }      TreeUI ui = getUI();
1477    
1478          /**      if (ui != null)
1479           * Returns the next table element (beginning from the row        ui.cancelEditing(this);
1480           * <code>startingRow</code> that starts with <code>prefix</code>.    }
1481           * Searching is done in the direction specified by <code>bias</code>.  
1482           *    public void startEditingAtPath(TreePath path)
1483           * @param prefix the prefix to search for in the cell values    {
1484           * @param startingRow the index of the row where to start searching from      TreeUI ui = getUI();
1485           * @param bias the search direction, either {@link Position.Bias#Forward} or  
1486           *        {@link Position.Bias#Backward}      if (ui != null)
1487           *        ui.startEditingAtPath(this, path);
1488           * @return the path to the found element or -1 if no such element has been    }
1489           *         found  
1490           *    public TreePath getEditingPath()
1491           * @throws IllegalArgumentException if prefix is <code>null</code> or    {
1492           *         startingRow is not valid      TreeUI ui = getUI();
1493           *  
1494           * @since 1.4      if (ui != null)
1495           */        return ui.getEditingPath(this);
1496          public TreePath getNextMatch(String prefix, int startingRow,  
1497                          Position.Bias bias)      return null;
1498          {    }
1499                  if (prefix == null)  
1500                          throw new IllegalArgumentException(    public TreePath getPathForLocation(int x, int y)
1501                                          "The argument 'prefix' must not be" + " null.");    {
1502                  if (startingRow < 0)      TreePath path = getClosestPathForLocation(x, y);
1503                          throw new IllegalArgumentException(  
1504                                          "The argument 'startingRow' must not"      if (path != null)
1505                                                          + " be less than zero.");        {
1506            Rectangle rect = getPathBounds(path);
1507                  int size = getRowCount();  
1508                  if (startingRow > size)          if ((rect != null) && rect.contains(x, y))
1509                          throw new IllegalArgumentException(            return path;
1510                                          "The argument 'startingRow' must not"        }
1511                                                          + " be greater than the number of"  
1512                                                          + " elements in the TreeModel.");      return null;
1513      }
1514                  TreePath foundPath = null;  
1515                  if (bias == Position.Bias.Forward)    public int getRowForLocation(int x, int y)
1516                  {    {
1517                          for (int i = startingRow; i < size; i++)      TreePath path = getPathForLocation(x, y);
1518                          {  
1519                                  TreePath path = getPathForRow(i);      if (path != null)
1520                                  Object o = path.getLastPathComponent();        return getRowForPath(path);
1521                                  // FIXME: in the following call to convertValueToText the  
1522                                  // last argument (hasFocus) should be done right.      return -1;
1523                                  String item = convertValueToText(o, isRowSelected(i),    }
1524                                                  isExpanded(i), treeModel.isLeaf(o), i, false);  
1525                                  if (item.startsWith(prefix))    public TreePath getClosestPathForLocation(int x, int y)
1526                                  {    {
1527                                          foundPath = path;      TreeUI ui = getUI();
1528                                          break;  
1529                                  }      if (ui != null)
1530                          }        return ui.getClosestPathForLocation(this, x, y);
1531                  } else  
1532                  {      return null;
1533                          for (int i = startingRow; i >= 0; i--)    }
1534                          {  
1535                                  TreePath path = getPathForRow(i);    public int getClosestRowForLocation(int x, int y)
1536                                  Object o = path.getLastPathComponent();    {
1537                                  // FIXME: in the following call to convertValueToText the      TreePath path = getClosestPathForLocation(x, y);
1538                                  // last argument (hasFocus) should be done right.  
1539                                  String item = convertValueToText(o, isRowSelected(i),      if (path != null)
1540                                                  isExpanded(i), treeModel.isLeaf(o), i, false);        return getRowForPath(path);
1541                                  if (item.startsWith(prefix))  
1542                                  {      return -1;
1543                                          foundPath = path;    }
1544                                          break;  
1545                                  }    public Object getLastSelectedPathComponent()
1546                          }    {
1547                  }      TreePath path = getSelectionPath();
1548                  return foundPath;  
1549          }      if (path != null)
1550          return path.getLastPathComponent();
1551          /**  
1552           * Removes any paths in the current set of selected paths that are      return null;
1553           * descendants of <code>path</code>. If <code>includePath</code> is set    }
1554           * to <code>true</code> and <code>path</code> itself is selected, then  
1555           * it will be removed too.    private void doExpandParents(TreePath path, boolean state)
1556           *    {
1557           * @param path the path from which selected descendants are to be removed      TreePath parent = path.getParentPath();            
1558           * @param includeSelected if <code>true</code> then <code>path</code> itself  
1559           *        will also be remove if it's selected      if (!isExpanded(parent) && parent != null)
1560           *        doExpandParents(parent, false);
1561           * @return <code>true</code> if something has been removed,  
1562           *         <code>false</code> otherwise      nodeStates.put(path, state ? EXPANDED : COLLAPSED);
1563           *    }
1564           * @since 1.3  
1565           */    protected void setExpandedState(TreePath path, boolean state)
1566          protected boolean removeDescendantSelectedPaths(TreePath path,    {
1567                          boolean includeSelected)      if (path == null)
1568          {        return;
1569                  boolean removedSomething = false;      TreePath parent = path.getParentPath();
1570                  TreePath[] selected = getSelectionPaths();  
1571                  for (int index = 0; index < selected.length; index++)      doExpandParents(path, state);
1572                  {    }
1573                          if ((selected[index] == path && includeSelected)  
1574                                          || (selected[index].isDescendant(path)))    protected void clearToggledPaths()
1575                          {    {
1576                                  removeSelectionPath(selected[index]);      nodeStates.clear();
1577                                  removedSomething = true;    }
1578                          }  
1579                  }    protected Enumeration getDescendantToggledPaths(TreePath parent)
1580                  return removedSomething;    {
1581          }      if (parent == null)
1582          return null;
1583    
1584        Enumeration nodes = nodeStates.keys();
1585        Vector result = new Vector();
1586    
1587        while (nodes.hasMoreElements())
1588          {
1589            TreePath path = (TreePath) nodes.nextElement();
1590    
1591            if (path.isDescendant(parent))
1592              result.addElement(path);
1593          }
1594    
1595        return result.elements();
1596      }
1597    
1598      public boolean hasBeenExpanded(TreePath path)
1599      {
1600        if (path == null)
1601          return false;
1602    
1603        return nodeStates.get(path) != null;
1604      }
1605    
1606      public boolean isVisible(TreePath path)
1607      {
1608        if (path == null)
1609          return false;
1610    
1611        TreePath parent = path.getParentPath();
1612    
1613        if (parent == null)
1614          return true; // Is root node.
1615    
1616        return isExpanded(parent);
1617      }
1618    
1619      public void makeVisible(TreePath path)
1620      {
1621        if (path == null)
1622          return;
1623    
1624        expandPath(path.getParentPath());
1625      }
1626    
1627      public boolean isPathEditable(TreePath path)
1628      {
1629        return isEditable();
1630      }
1631    
1632      /**
1633       * Creates and returns an instance of {@link TreeModelHandler}.
1634       *
1635       * @returns an instance of {@link TreeModelHandler}
1636       */
1637      protected TreeModelListener createTreeModelListener()
1638      {
1639        return new TreeModelHandler();
1640      }
1641    
1642      /**
1643       * Returns a sample TreeModel that can be used in a JTree. This can be used
1644       * in Bean- or GUI-Builders to show something interesting.
1645       *
1646       * @return a sample TreeModel that can be used in a JTree
1647       */
1648      protected static TreeModel getDefaultTreeModel()
1649      {
1650        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root node");
1651        DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child node 1");
1652        DefaultMutableTreeNode child11 =
1653          new DefaultMutableTreeNode("Child node 1.1");
1654        DefaultMutableTreeNode child12 =
1655          new DefaultMutableTreeNode("Child node 1.2");
1656        DefaultMutableTreeNode child13 =
1657          new DefaultMutableTreeNode("Child node 1.3");
1658        DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child node 2");
1659        DefaultMutableTreeNode child21 =
1660          new DefaultMutableTreeNode("Child node 2.1");
1661        DefaultMutableTreeNode child22 =
1662          new DefaultMutableTreeNode("Child node 2.2");
1663        DefaultMutableTreeNode child23 =
1664          new DefaultMutableTreeNode("Child node 2.3");
1665        DefaultMutableTreeNode child24 =
1666          new DefaultMutableTreeNode("Child node 2.4");
1667    
1668        DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("Child node 3");
1669        root.add(child1);
1670        root.add(child2);
1671        root.add(child3);
1672        child1.add(child11);
1673        child1.add(child12);
1674        child1.add(child13);
1675        child2.add(child21);
1676        child2.add(child22);
1677        child2.add(child23);
1678        child2.add(child24);
1679        return new DefaultTreeModel(root);
1680      }
1681    
1682      /**
1683       * Converts the specified value to a String. This is used by the renderers
1684       * of this JTree and its nodes.
1685       *
1686       * This implementation simply returns <code>value.toString()</code> and
1687       * ignores all other parameters. Subclass this method to control the
1688       * conversion.
1689       *
1690       * @param value the value that is converted to a String
1691       * @param selected indicates if that value is selected or not
1692       * @param expanded indicates if that value is expanded or not
1693       * @param leaf indicates if that value is a leaf node or not
1694       * @param row the row of the node
1695       * @param hasFocus indicates if that node has focus or not
1696       */
1697      public String convertValueToText(Object value, boolean selected,
1698                                       boolean expanded, boolean leaf, int row, boolean hasFocus)
1699      {
1700        return value.toString();
1701      }
1702    
1703      /**
1704       * A String representation of this JTree. This is intended to be used for
1705       * debugging. The returned string may be empty but may not be
1706       * <code>null</code>.
1707       *
1708       * @return a String representation of this JTree
1709       */
1710      public String paramString()
1711      {
1712        // TODO: this is completely legal, but it would possibly be nice
1713        // to return some more content, like the tree structure, some properties
1714        // etc ...
1715        return "";
1716      }
1717    
1718      /**
1719       * Returns all TreePath objects which are a descendants of the given path
1720       * and are exapanded at the moment of the execution of this method. If the
1721       * state of any node is beeing toggled while this method is executing this
1722       * change may be left unaccounted.
1723       *
1724       * @param path The parent of this request
1725       *
1726       * @return An Enumeration containing TreePath objects
1727       */
1728      public Enumeration getExpandedDescendants(TreePath path)
1729      {
1730        Enumeration paths = nodeStates.keys();
1731        Vector relevantPaths = new Vector();
1732        while (paths.hasMoreElements())
1733          {
1734            TreePath nextPath = (TreePath) paths.nextElement();
1735            if (nodeStates.get(nextPath) == EXPANDED
1736                && path.isDescendant(nextPath))
1737              {
1738                relevantPaths.add(nextPath);
1739              }
1740          }
1741        return relevantPaths.elements();
1742      }
1743    
1744      /**
1745       * Returns the next table element (beginning from the row
1746       * <code>startingRow</code> that starts with <code>prefix</code>.
1747       * Searching is done in the direction specified by <code>bias</code>.
1748       *
1749       * @param prefix the prefix to search for in the cell values
1750       * @param startingRow the index of the row where to start searching from
1751       * @param bias the search direction, either {@link Position.Bias#Forward} or
1752       *        {@link Position.Bias#Backward}
1753       *
1754       * @return the path to the found element or -1 if no such element has been
1755       *         found
1756       *
1757       * @throws IllegalArgumentException if prefix is <code>null</code> or
1758       *         startingRow is not valid
1759       *
1760       * @since 1.4
1761       */
1762      public TreePath getNextMatch(String prefix, int startingRow,
1763                                   Position.Bias bias)
1764      {
1765        if (prefix == null)
1766          throw new IllegalArgumentException("The argument 'prefix' must not be"
1767                                             + " null.");
1768        if (startingRow < 0)
1769          throw new IllegalArgumentException("The argument 'startingRow' must not"
1770                                             + " be less than zero.");
1771    
1772        int size = getRowCount();
1773        if (startingRow > size)
1774          throw new IllegalArgumentException("The argument 'startingRow' must not"
1775                                             + " be greater than the number of"
1776                                             + " elements in the TreeModel.");
1777    
1778        TreePath foundPath = null;
1779        if (bias == Position.Bias.Forward)
1780          {
1781            for (int i = startingRow; i < size; i++)
1782              {
1783                TreePath path = getPathForRow(i);
1784                Object o = path.getLastPathComponent();
1785                // FIXME: in the following call to convertValueToText the
1786                // last argument (hasFocus) should be done right.
1787                String item = convertValueToText(o, isRowSelected(i),
1788                                                 isExpanded(i), treeModel.isLeaf(o),
1789                                                 i, false);
1790                if (item.startsWith(prefix))
1791                  {
1792                    foundPath = path;
1793                    break;
1794                  }
1795              }
1796          }
1797        else
1798          {
1799            for (int i = startingRow; i >= 0; i--)
1800              {
1801                TreePath path = getPathForRow(i);
1802                Object o = path.getLastPathComponent();
1803                // FIXME: in the following call to convertValueToText the
1804                // last argument (hasFocus) should be done right.
1805                String item = convertValueToText(o, isRowSelected(i),
1806                                                 isExpanded(i), treeModel.isLeaf(o), i, false);
1807                if (item.startsWith(prefix))
1808                  {
1809                    foundPath = path;
1810                    break;
1811                  }
1812              }
1813          }
1814        return foundPath;
1815      }
1816    
1817      /**
1818       * Removes any paths in the current set of selected paths that are
1819       * descendants of <code>path</code>. If <code>includePath</code> is set
1820       * to <code>true</code> and <code>path</code> itself is selected, then
1821       * it will be removed too.
1822       *
1823       * @param path the path from which selected descendants are to be removed
1824       * @param includeSelected if <code>true</code> then <code>path</code> itself
1825       *        will also be remove if it's selected
1826       *
1827       * @return <code>true</code> if something has been removed,
1828       *         <code>false</code> otherwise
1829       *
1830       * @since 1.3
1831       */
1832      protected boolean removeDescendantSelectedPaths(TreePath path,
1833                                                      boolean includeSelected)
1834      {
1835        boolean removedSomething = false;
1836        TreePath[] selected = getSelectionPaths();
1837        for (int index = 0; index < selected.length; index++)
1838          {
1839            if ((selected[index] == path && includeSelected)
1840                || (selected[index].isDescendant(path)))
1841              {
1842                removeSelectionPath(selected[index]);
1843                removedSomething = true;
1844              }
1845          }
1846        return removedSomething;
1847      }
1848  }  }

Legend:
Removed from v.1.37  
changed lines
  Added in v.1.38

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26