/[classpath]/classpath/javax/swing/plaf/basic/BasicTreeUI.java
ViewVC logotype

Diff of /classpath/javax/swing/plaf/basic/BasicTreeUI.java

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

revision 1.49 by langel, Thu Jul 28 19:37:54 2005 UTC revision 1.50 by roehrijn, Sun Jul 31 01:42:14 2005 UTC
# Line 107  import javax.swing.tree.TreeSelectionMod Line 107  import javax.swing.tree.TreeSelectionMod
107   * @author Sascha Brawer (brawer@dandelis.ch)   * @author Sascha Brawer (brawer@dandelis.ch)
108   * @author Lillian Angel (langel@redhat.com)   * @author Lillian Angel (langel@redhat.com)
109   */   */
110  public class BasicTreeUI  public class BasicTreeUI extends TreeUI
       extends TreeUI  
111  {  {
112      /** Collapse Icon for the tree. */
113     /** Collapse Icon for the tree. */    protected transient Icon collapsedIcon;
114     protected transient Icon collapsedIcon;    
115      /** Expanded Icon for the tree. */
116     /** Expanded Icon for the tree. */    protected transient Icon expandedIcon;
117     protected transient Icon expandedIcon;    
118      /** Distance between left margin and where vertical dashes will be drawn. */
119     /** Distance between left margin and where vertical dashes will be drawn. */    protected int leftChildIndent;
120     protected int leftChildIndent;    
121      /**
122     /**     * Distance between leftChildIndent and where cell contents will be drawn.
123      * Distance between leftChildIndent and where cell contents will be drawn.     */
124      */    protected int rightChildIndent;
125     protected int rightChildIndent;    
126      /**
127     /**     * Total fistance that will be indented. The sum of leftChildIndent and
128      * Total fistance that will be indented. The sum of leftChildIndent and     * rightChildIndent .
129      * rightChildIndent .     */
130      */    protected int totalChildIndent;
131     protected int totalChildIndent;    
132      /** Minimum preferred size. */
133     /** Minimum preferred size. */    protected Dimension preferredMinsize;
134     protected Dimension preferredMinsize;    
135      /** Index of the row that was last selected. */
136     /** Index of the row that was last selected. */    protected int lastSelectedRow;
137     protected int lastSelectedRow;    
138      /** Component that we're going to be drawing onto. */
139     /** Component that we're going to be drawing onto. */    protected JTree tree;
140     protected JTree tree;    
141      /** Renderer that is being used to do the actual cell drawing. */
142     /** Renderer that is being used to do the actual cell drawing. */    protected transient TreeCellRenderer currentCellRenderer;
143     protected transient TreeCellRenderer currentCellRenderer;    
144      /**
145     /**     * Set to true if the renderer that is currently in the tree was created by
146      * Set to true if the renderer that is currently in the tree was created by     * this instance.
147      * this instance.     */
148      */    protected boolean createdRenderer;
149     protected boolean createdRenderer;    
150      /** Editor for the tree. */
151     /** Editor for the tree. */    protected transient TreeCellEditor cellEditor;
152     protected transient TreeCellEditor cellEditor;    
153      /**
154     /**     * Set to true if editor that is currently in the tree was created by this
155      * Set to true if editor that is currently in the tree was created by this     * instance.
156      * instance.     */
157      */    protected boolean createdCellEditor;
158     protected boolean createdCellEditor;    
159      /**
160     /**     * Set to false when editing and shouldSelectCall() returns true meaning the
161      * Set to false when editing and shouldSelectCall() returns true meaning the     * node should be selected before editing, used in completeEditing.
162      * node should be selected before editing, used in completeEditing.     */
163      */    protected boolean stopEditingInCompleteEditing;
164     protected boolean stopEditingInCompleteEditing;    
165      /** Used to paint the TreeCellRenderer. */
166     /** Used to paint the TreeCellRenderer. */    protected CellRendererPane rendererPane;
167     protected CellRendererPane rendererPane;    
168      /** Size needed to completely display all the nodes. */
169     /** Size needed to completely display all the nodes. */    protected Dimension preferredSize;
170     protected Dimension preferredSize;    
171      /** Is the preferredSize valid? */
172     /** Is the preferredSize valid? */    protected boolean validCachedPreferredSize;
173     protected boolean validCachedPreferredSize;    
174      /** Object responsible for handling sizing and expanded issues. */
175     /** Object responsible for handling sizing and expanded issues. */    protected AbstractLayoutCache treeState;
176     protected AbstractLayoutCache treeState;    
177      /** Used for minimizing the drawing of vertical lines. */
178     /** Used for minimizing the drawing of vertical lines. */    protected Hashtable drawingCache;
179     protected Hashtable drawingCache;    
180      /**
181     /**     * True if doing optimizations for a largeModel. Subclasses that don't
182      * True if doing optimizations for a largeModel. Subclasses that don't     * support this may wish to override createLayoutCache to not return a
183      * support this may wish to override createLayoutCache to not return a     * FixedHeightLayoutCache instance.
184      * FixedHeightLayoutCache instance.     */
185      */    protected boolean largeModel;
186     protected boolean largeModel;    
187      /** Responsible for telling the TreeState the size needed for a node. */
188     /** Responsible for telling the TreeState the size needed for a node. */    protected AbstractLayoutCache.NodeDimensions nodeDimensions;
189     protected AbstractLayoutCache.NodeDimensions nodeDimensions;    
190      /** Used to determine what to display. */
191     /** Used to determine what to display. */    protected TreeModel treeModel;
192     protected TreeModel treeModel;    
193      /** Model maintaining the selection. */
194     /** Model maintaining the selection. */    protected TreeSelectionModel treeSelectionModel;
195     protected TreeSelectionModel treeSelectionModel;    
196      /**
197     /**     * How much the depth should be offset to properly calculate x locations.
198      * How much the depth should be offset to properly calculate x locations.     * This is based on whether or not the root is visible, and if the root
199      * This is based on whether or not the root is visible, and if the root     * handles are visible.
200      * handles are visible.     */
201      */    protected int depthOffset;
202     protected int depthOffset;    
203      /**
204     /**     * When editing, this will be the Component that is doing the actual editing.
205      * When editing, this will be the Component that is doing the actual editing.     */
206      */    protected Component editingComponent;
207     protected Component editingComponent;    
208      /** Path that is being edited. */
209     /** Path that is being edited. */    protected TreePath editingPath;
210     protected TreePath editingPath;    
211      /**
212     /**     * Row that is being edited. Should only be referenced if editingComponent is
213      * Row that is being edited. Should only be referenced if editingComponent is     * null.
214      * null.     */
215      */    protected int editingRow;
216     protected int editingRow;    
217      /** Set to true if the editor has a different size than the renderer. */
218     /** Set to true if the editor has a different size than the renderer. */    protected boolean editorHasDifferentSize;
219     protected boolean editorHasDifferentSize;    
220      /** Listeners */
221     /** Listeners */    private PropertyChangeListener propertyChangeListener;
222     private PropertyChangeListener propertyChangeListener;    private FocusListener focusListener;
223     private FocusListener focusListener;    private TreeSelectionListener treeSelectionListener;
224     private TreeSelectionListener treeSelectionListener;    private MouseInputListener mouseInputListener;
225     private MouseInputListener mouseInputListener;    private KeyListener keyListener;
226     private KeyListener keyListener;    private PropertyChangeListener selectionModelPropertyChangeListener;
227     private PropertyChangeListener selectionModelPropertyChangeListener;    private ComponentListener componentListener;
228     private ComponentListener componentListener;    private CellEditorListener cellEditorListener;
229     private CellEditorListener cellEditorListener;    private TreeExpansionListener treeExpansionListener;
230     private TreeExpansionListener treeExpansionListener;    private TreeModelListener treeModelListener;
231     private TreeModelListener treeModelListener;    
232      /**
233     /**     * Creates a new BasicTreeUI object.
234      * Creates a new BasicTreeUI object.     */
235      */    public BasicTreeUI()
236     public BasicTreeUI()    {
237     {      drawingCache = new Hashtable();
238        drawingCache = new Hashtable();      cellEditor = createDefaultCellEditor();
239        cellEditor = createDefaultCellEditor();      currentCellRenderer = createDefaultCellRenderer();
240        currentCellRenderer = createDefaultCellRenderer();      nodeDimensions = createNodeDimensions();
241        nodeDimensions = createNodeDimensions();      rendererPane = createCellRendererPane();
242        rendererPane = createCellRendererPane();      configureLayoutCache();
243        configureLayoutCache();      
244        propertyChangeListener = createPropertyChangeListener();
245        propertyChangeListener = createPropertyChangeListener();      focusListener = createFocusListener();
246        focusListener = createFocusListener();      treeSelectionListener = createTreeSelectionListener();
247        treeSelectionListener = createTreeSelectionListener();      mouseInputListener = new MouseInputHandler(null, null, null);
248        mouseInputListener = new MouseInputHandler(null, null, null);      keyListener = createKeyListener();
249        keyListener = createKeyListener();      selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener();
250        selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener();      componentListener = createComponentListener();
251        componentListener = createComponentListener();      cellEditorListener = createCellEditorListener();
252        cellEditorListener = createCellEditorListener();      treeExpansionListener = createTreeExpansionListener();
253        treeExpansionListener = createTreeExpansionListener();      treeModelListener = createTreeModelListener();
254        treeModelListener = createTreeModelListener();      
255        createdRenderer = true;
256        createdRenderer = true;      createdCellEditor = true;
257        createdCellEditor = true;      editingRow = -1;
258        editingRow = -1;      lastSelectedRow = -1;
259        lastSelectedRow = -1;    }
260     }    
261      /**
262     /**     * Returns an instance of the UI delegate for the specified component.
263      * Returns an instance of the UI delegate for the specified component.     *
264      *     * @param c the <code>JComponent</code> for which we need a UI delegate
265      * @param c the <code>JComponent</code> for which we need a UI delegate     *        for.
266      *        for.     * @return the <code>ComponentUI</code> for c.
267      * @return the <code>ComponentUI</code> for c.     */
268      */    public static ComponentUI createUI(JComponent c)
269     public static ComponentUI createUI(JComponent c)    {
270     {      return new BasicTreeUI();
271        return new BasicTreeUI();    }
272     }    
273      /**
274     /**     * Returns the Hash color.
275      * Returns the Hash color.     *
276      *     * @return the <code>Color</code> of the Hash.
277      * @return the <code>Color</code> of the Hash.     */
278      */    protected Color getHashColor()
279     protected Color getHashColor()    {
280     {      return UIManager.getLookAndFeelDefaults().getColor("Tree.hash");
281        return UIManager.getLookAndFeelDefaults().getColor("Tree.hash");    }
282     }    
283      /**
284     /**     * Sets the Hash color.
285      * Sets the Hash color.     *
286      *     * @param color the <code>Color</code> to set the Hash to.
287      * @param color the <code>Color</code> to set the Hash to.     */
288      */    protected void setHashColor(Color color)
289     protected void setHashColor(Color color)    {
290     {      // FIXME: not implemented
291        // FIXME: not implemented      
292      }
293     }    
294      /**
295     /**     * Sets the left child's indent value.
296      * Sets the left child's indent value.     *
297      *     * @param newAmount is the new indent value for the left child.
298      * @param newAmount is the new indent value for the left child.     */
299      */    public void setLeftChildIndent(int newAmount)
300     public void setLeftChildIndent(int newAmount)    {
301     {      leftChildIndent = newAmount;
302        leftChildIndent = newAmount;    }
303     }    
304      /**
305     /**     * Returns the indent value for the left child.
306      * Returns the indent value for the left child.     *
307      *     * @return the indent value for the left child.
308      * @return the indent value for the left child.     */
309      */    public int getLeftChildIndent(int newAmount)
310     public int getLeftChildIndent(int newAmount)    {
311     {      return leftChildIndent;
312        return leftChildIndent;    }
313     }    
314      /**
315     /**     * Sets the right child's indent value.
316      * Sets the right child's indent value.     *
317      *     * @param newAmount is the new indent value for the right child.
318      * @param newAmount is the new indent value for the right child.     */
319      */    public void setRightChildIndent(int newAmount)
320     public void setRightChildIndent(int newAmount)    {
321     {      rightChildIndent = newAmount;
322        rightChildIndent = newAmount;    }
323     }    
324      /**
325     /**     * Returns the indent value for the right child.
326      * Returns the indent value for the right child.     *
327      *     * @return the indent value for the right child.
328      * @return the indent value for the right child.     */
329      */    public int getRightChildIndent(int newAmount)
330     public int getRightChildIndent(int newAmount)    {
331     {      return rightChildIndent;
332        return rightChildIndent;    }
333     }    
334      /**
335     /**     * Sets the expanded icon.
336      * Sets the expanded icon.     *
337      *     * @param newG is the new expanded icon.
338      * @param newG is the new expanded icon.     */
339      */    public void setExpandedIcon(Icon newG)
340     public void setExpandedIcon(Icon newG)    {
341     {      expandedIcon = newG;
342        expandedIcon = newG;    }
343     }    
344      /**
345     /**     * Returns the current expanded icon.
346      * Returns the current expanded icon.     *
347      *     * @return the current expanded icon.
348      * @return the current expanded icon.     */
349      */    public Icon getExpandedIcon()
350     public Icon getExpandedIcon()    {
351     {      return expandedIcon;
352        return expandedIcon;    }
353     }    
354      /**
355     /**     * Sets the collapsed icon.
356      * Sets the collapsed icon.     *
357      *     * @param newG is the new collapsed icon.
358      * @param newG is the new collapsed icon.     */
359      */    public void setCollapsedIcon(Icon newG)
360     public void setCollapsedIcon(Icon newG)    {
361     {      collapsedIcon = newG;
362        collapsedIcon = newG;    }
363     }    
364      /**
365     /**     * Returns the current collapsed icon.
366      * Returns the current collapsed icon.     *
367      *     * @return the current collapsed icon.
368      * @return the current collapsed icon.     */
369      */    public Icon getCollapsedIcon()
370     public Icon getCollapsedIcon()    {
371     {      return collapsedIcon;
372        return collapsedIcon;    }
373     }    
374      /**
375     /**     * Updates the componentListener, if necessary.
376      * Updates the componentListener, if necessary.     *
377      *     * @param largeModel sets this.largeModel to it.
378      * @param largeModel sets this.largeModel to it.     */
379      */    protected void setLargeModel(boolean largeModel)
380     protected void setLargeModel(boolean largeModel)    {
381     {      if (largeModel != this.largeModel)
382        if (largeModel != this.largeModel)        {
383        {          tree.removeComponentListener(componentListener);
384           tree.removeComponentListener(componentListener);          this.largeModel = largeModel;
385           this.largeModel = largeModel;          tree.addComponentListener(componentListener);
386           tree.addComponentListener(componentListener);        }
387        }    }
388     }    
389      /**
390     /**     * Returns true if largeModel is set
391      * Returns true if largeModel is set     *
392      *     * @return true if largeModel is set, otherwise false.
393      * @return true if largeModel is set, otherwise false.     */
394      */    protected boolean isLargeModel()
395     protected boolean isLargeModel()    {
396     {      return largeModel;
397        return largeModel;    }
398     }    
399      /**
400     /**     * Sets the row height.
401      * Sets the row height.     *
402      *     * @param rowHeight is the height to set this.rowHeight to.
403      * @param rowHeight is the height to set this.rowHeight to.     */
404      */    protected void setRowHeight(int rowHeight)
405     protected void setRowHeight(int rowHeight)    {
406     {      treeState.setRowHeight(rowHeight);
407        treeState.setRowHeight(rowHeight);    }
408     }    
409      /**
410     /**     * Returns the current row height.
411      * Returns the current row height.     *
412      *     * @return current row height.
413      * @return current row height.     */
414      */    protected int getRowHeight()
415     protected int getRowHeight()    {
416     {      return treeState.getRowHeight();
417        return treeState.getRowHeight();    }
418     }    
419      /**
420     /**     * Sets the TreeCellRenderer to <code>tcr</code>. This invokes
421      * Sets the TreeCellRenderer to <code>tcr</code>. This invokes     * <code>updateRenderer</code>.
422      * <code>updateRenderer</code>.     *
423      *     * @param tcr is the new TreeCellRenderer.
424      * @param tcr is the new TreeCellRenderer.     */
425      */    protected void setCellRenderer(TreeCellRenderer tcr)
426     protected void setCellRenderer(TreeCellRenderer tcr)    {
427     {      currentCellRenderer = tcr;
428        currentCellRenderer = tcr;      updateRenderer();
429        updateRenderer();    }
430     }    
431      /**
432     /**     * Return currentCellRenderer, which will either be the trees renderer, or
433      * Return currentCellRenderer, which will either be the trees renderer, or     * defaultCellRenderer, which ever was not null.
434      * defaultCellRenderer, which ever was not null.     *
435      *     * @return the current Cell Renderer
436      * @return the current Cell Renderer     */
437      */    protected TreeCellRenderer getCellRenderer()
438     protected TreeCellRenderer getCellRenderer()    {
439     {      if (currentCellRenderer != null)
440        if (currentCellRenderer != null)        return currentCellRenderer;
441           return currentCellRenderer;      
442        return createDefaultCellRenderer();
443        return createDefaultCellRenderer();    }
444     }    
445      /**
446     /**     * Sets the tree's model.
447      * Sets the tree's model.     *
448      *     * @param model to set the treeModel to.
449      * @param model to set the treeModel to.     */
450      */    protected void setModel(TreeModel model)
451     protected void setModel(TreeModel model)    {
452     {      tree.setModel(model);
453        tree.setModel(model);      treeModel = model;
454        treeModel = model;    }
455     }    
456      /**
457     /**     * Returns the tree's model
458      * Returns the tree's model     *
459      *     * @return treeModel
460      * @return treeModel     */
461      */    protected TreeModel getModel()
462     protected TreeModel getModel()    {
463     {      return treeModel;
464        return treeModel;    }
465     }    
466      /**
467     /**     * Sets the root to being visible.
468      * Sets the root to being visible.     *
469      *     * @param newValue sets the visibility of the root
470      * @param newValue sets the visibility of the root     */
471      */    protected void setRootVisible(boolean newValue)
472     protected void setRootVisible(boolean newValue)    {
473     {      tree.setRootVisible(newValue);
474        tree.setRootVisible(newValue);    }
475     }    
476      /**
477     /**     * Returns true if the root is visible.
478      * Returns true if the root is visible.     *
479      *     * @return true if the root is visible.
480      * @return true if the root is visible.     */
481      */    protected boolean isRootVisible()
482     protected boolean isRootVisible()    {
483     {      return tree.isRootVisible();
484        return tree.isRootVisible();    }
485     }    
486      /**
487     /**     * Determines whether the node handles are to be displayed.
488      * Determines whether the node handles are to be displayed.     *
489      *     * @param newValue sets whether or not node handles should be displayed.
490      * @param newValue sets whether or not node handles should be displayed.     */
491      */    protected void setShowsRootHandles(boolean newValue)
492     protected void setShowsRootHandles(boolean newValue)    {
493     {      tree.setShowsRootHandles(newValue);
494        tree.setShowsRootHandles(newValue);    }
495     }    
496      /**
497     /**     * Returns true if the node handles are to be displayed.
498      * Returns true if the node handles are to be displayed.     *
499      *     * @return true if the node handles are to be displayed.
500      * @return true if the node handles are to be displayed.     */
501      */    protected boolean getShowsRootHandles()
502     protected boolean getShowsRootHandles()    {
503     {      return tree.getShowsRootHandles();
504        return tree.getShowsRootHandles();    }
505     }    
506      /**
507     /**     * Sets the cell editor.
508      * Sets the cell editor.     *
509      *     * @param editor to set the cellEditor to.
510      * @param editor to set the cellEditor to.     */
511      */    protected void setCellEditor(TreeCellEditor editor)
512     protected void setCellEditor(TreeCellEditor editor)    {
513     {      cellEditor = editor;
514        cellEditor = editor;    }
515     }    
516      /**
517     /**     * Returns the <code>TreeCellEditor</code> for this tree.
518      * Returns the <code>TreeCellEditor</code> for this tree.     *
519      *     * @return the cellEditor for this tree.
520      * @return the cellEditor for this tree.     */
521      */    protected TreeCellEditor getCellEditor()
522     protected TreeCellEditor getCellEditor()    {
523     {      return cellEditor;
524        return cellEditor;    }
525     }    
526      /**
527     /**     * Configures the receiver to allow, or not allow, editing.
528      * Configures the receiver to allow, or not allow, editing.     *
529      *     * @param newValue sets the receiver to allow editing if true.
530      * @param newValue sets the receiver to allow editing if true.     */
531      */    protected void setEditable(boolean newValue)
532     protected void setEditable(boolean newValue)    {
533     {      tree.setEditable(newValue);
534        tree.setEditable(newValue);    }
535     }    
536      /**
537     /**     * Returns true if the receiver allows editing.
538      * Returns true if the receiver allows editing.     *
539      *     * @return true if the receiver allows editing.
540      * @return true if the receiver allows editing.     */
541      */    protected boolean isEditable()
542     protected boolean isEditable()    {
543     {      return tree.isEditable();
544        return tree.isEditable();    }
545     }    
546      /**
547     /**     * Resets the selection model. The appropriate listeners are installed on the
548      * Resets the selection model. The appropriate listeners are installed on the     * model.
549      * model.     *
550      *     * @param newLSM resets the selection model.
551      * @param newLSM resets the selection model.     */
552      */    protected void setSelectionModel(TreeSelectionModel newLSM)
553     protected void setSelectionModel(TreeSelectionModel newLSM)    {
554     {      if (newLSM != null)
555        if (newLSM != null)        {
556        {          treeSelectionModel = newLSM;
557           treeSelectionModel = newLSM;          tree.setSelectionModel(treeSelectionModel);
558           tree.setSelectionModel(treeSelectionModel);        }
559        }    }
560     }    
561      /**
562     /**     * Returns the current selection model.
563      * Returns the current selection model.     *
564      *     * @return the current selection model.
565      * @return the current selection model.     */
566      */    protected TreeSelectionModel getSelectionModel()
567     protected TreeSelectionModel getSelectionModel()    {
568     {      return treeSelectionModel;
569        return treeSelectionModel;    }
570     }    
571      /**
572     /**     * Returns the Rectangle enclosing the label portion that the last item in
573      * Returns the Rectangle enclosing the label portion that the last item in     * path will be drawn to. Will return null if any component in path is
574      * path will be drawn to. Will return null if any component in path is     * currently valid.
575      * currently valid.     *
576      *     * @param tree is the current tree the path will be drawn to.
577      * @param tree is the current tree the path will be drawn to.     * @param path is the current path the tree to draw to.
578      * @param path is the current path the tree to draw to.     * @return the Rectangle enclosing the label portion that the last item in
579      * @return the Rectangle enclosing the label portion that the last item in     *         the path will be drawn to.
580      *         the path will be drawn to.     */
581      */    public Rectangle getPathBounds(JTree tree, TreePath path)
582     public Rectangle getPathBounds(JTree tree, TreePath path)    {
583     {      if (path != null)
584        if (path != null)        {
585        {          Object cell = path.getLastPathComponent();
586           Object cell = path.getLastPathComponent();          TreeModel mod = tree.getModel();
587           TreeModel mod = tree.getModel();          DefaultMutableTreeNode root = (DefaultMutableTreeNode) mod.getRoot();
588           DefaultMutableTreeNode root = (DefaultMutableTreeNode) mod.getRoot();          if (!tree.isRootVisible()
589           if (!tree.isRootVisible()              && tree.isExpanded(new TreePath(root)))
590                 && tree.isExpanded(new TreePath(root)))            root = root.getNextNode();
591              root = root.getNextNode();          
592            Point loc = getCellLocation(0, 0, tree, mod, cell, root);
593           Point loc = getCellLocation(0, 0, tree, mod, cell, root);          return getCellBounds(loc.x, loc.y, cell);
594           return getCellBounds(loc.x, loc.y, cell);        }
595        }      return null;
596        return null;    }
597     }    
598      /**
599     /**     * Returns the path for passed in row. If row is not visible null is
600      * Returns the path for passed in row. If row is not visible null is     * returned.
601      * returned.     *
602      *     * @param tree is the current tree to return path for.
603      * @param tree is the current tree to return path for.     * @param row is the row number of the row to return.
604      * @param row is the row number of the row to return.     * @return the path for passed in row. If row is not visible null is
605      * @return the path for passed in row. If row is not visible null is     *         returned.
606      *         returned.     */
607      */    public TreePath getPathForRow(JTree tree, int row)
608     public TreePath getPathForRow(JTree tree, int row)    {
609     {      DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel())
610        DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel())          .getRoot());
611              .getRoot());      if (!tree.isRootVisible()
612        if (!tree.isRootVisible()          && tree.isExpanded(new TreePath(((DefaultMutableTreeNode) node)
613              && tree.isExpanded(new TreePath(((DefaultMutableTreeNode) node)                                          .getPath())))
614                    .getPath())))        node = node.getNextNode();
615           node = node.getNextNode();      
616        for (int i = 0; i < row; i++)
617        for (int i = 0; i < row; i++)        node = getNextVisibleNode(node);
618           node = getNextVisibleNode(node);      
619        // in case nothing was found
620        // in case nothing was found      if (node == null)
       if (node == null)  
          return null;  
   
       // something was found  
       return new TreePath(node.getPath());  
    }  
   
    /**  
     * Returns the row that the last item identified in path is visible at. Will  
     * return -1 if any of the elments in the path are not currently visible.  
     *  
     * @param tree is the current tree to return the row for.  
     * @param path is the path used to find the row.  
     * @return the row that the last item identified in path is visible at. Will  
     *         return -1 if any of the elments in the path are not currently  
     *         visible.  
     */  
    public int getRowForPath(JTree tree, TreePath path)  
    {  
       // FIXME: check visibility  
       // right now, just returns last element because  
       // expand/collapse is not implemented  
       return path.getPathCount() - 1;  
    }  
   
    /**  
     * Returns the number of rows that are being displayed.  
     *  
     * @param tree is the current tree to return the number of rows for.  
     * @return the number of rows being displayed.  
     */  
    public int getRowCount(JTree tree)  
    {  
       DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel())  
             .getRoot());  
       if (!tree.isRootVisible()  
             && tree.isExpanded(new TreePath(((DefaultMutableTreeNode) node)  
                   .getPath())))  
          node = node.getNextNode();  
         
       int count = 0;  
         
       while (node != null)  
       {  
          count++;  
          node = getNextVisibleNode(node);  
       }  
         
       return count;  
    }  
   
    /**  
     * Returns the path to the node that is closest to x,y. If there is nothing  
     * currently visible this will return null, otherwise it'll always return a  
     * valid path. If you need to test if the returned object is exactly at x,y  
     * you should get the bounds for the returned path and test x,y against that.  
     *  
     * @param tree the tree to search for the closest path  
     * @param x is the x coordinate of the location to search  
     * @param y is the y coordinate of the location to search  
     * @return the tree path closes to x,y.  
     */  
    public TreePath getClosestPathForLocation(JTree tree, int x, int y)  
    {  
       //FIXME: what if root is hidden? should not depend on (0,0)  
       // should start counting rows from where root is.  
         
       int row = Math.round(y / getRowHeight());  
       TreePath path = getPathForRow(tree, row);  
         
       // no row is visible at this node  
       while (row > 0 && path == null)  
       {  
          --row;  
          path = getPathForRow(tree, row);  
       }  
         
       return path;  
    }  
   
    /**  
     * Returns true if the tree is being edited. The item that is being edited  
     * can be returned by getEditingPath().  
     *  
     * @param tree is the tree to check for editing.  
     * @return true if the tree is being edited.  
     */  
    public boolean isEditing(JTree tree)  
    {  
       // FIXME: not implemented  
       return false;  
    }  
   
    /**  
     * Stops the current editing session. This has no effect if the tree is not  
     * being edited. Returns true if the editor allows the editing session to  
     * stop.  
     *  
     * @param tree is the tree to stop the editing on  
     * @return true if the editor allows the editing session to stop.  
     */  
    public boolean stopEditing(JTree tree)  
    {  
       // FIXME: not implemented  
       return false;  
    }  
   
    /**  
     * Cancels the current editing session.  
     *  
     * @param tree is the tree to cancel the editing session on.  
     */  
    public void cancelEditing(JTree tree)  
    {  
       // FIXME: not implemented  
    }  
   
    /**  
     * Selects the last item in path and tries to edit it. Editing will fail if  
     * the CellEditor won't allow it for the selected item.  
     *  
     * @param tree is the tree to edit on.  
     * @param path is the path in tree to edit on.  
     */  
    public void startEditingAtPath(JTree tree, TreePath path)  
    {  
       // FIXME: not implemented  
    }  
   
    /**  
     * Returns the path to the element that is being editted.  
     *  
     * @param tree is the tree to get the editing path from.  
     * @return the path that is being edited.  
     */  
    public TreePath getEditingPath(JTree tree)  
    {  
       // FIXME: not implemented  
       return null;  
    }  
   
    /**  
     * Invoked after the tree instance variable has been set, but before any  
     * default/listeners have been installed.  
     */  
    protected void prepareForUIInstall()  
    {  
       // FIXME: not implemented  
    }  
   
    /**  
     * Invoked from installUI after all the defaults/listeners have been  
     * installed.  
     */  
    protected void completeUIInstall()  
    {  
       // FIXME: not implemented  
    }  
   
    /**  
     * Invoked from uninstallUI after all the defaults/listeners have been  
     * uninstalled.  
     */  
    protected void completeUIUninstall()  
    {  
       // FIXME: not implemented  
    }  
   
    /**  
     * Installs the subcomponents of the tree, which is the renderer pane.  
     */  
    protected void installComponents()  
    {  
       // FIXME: not implemented  
    }  
   
    /**  
     * Creates an instance of NodeDimensions that is able to determine the size  
     * of a given node in the tree.  
     *  
     * @return the NodeDimensions of a given node in the tree  
     */  
    protected AbstractLayoutCache.NodeDimensions createNodeDimensions()  
    {  
       // FIXME: not implemented  
621        return null;        return null;
622     }      
623        // something was found
624     /**      return new TreePath(node.getPath());
625      * Creates a listener that is reponsible for the updates the UI based on how    }
626      * the tree changes.    
627      *    /**
628      * @return the PropertyChangeListener that is reposnsible for the updates     * Returns the row that the last item identified in path is visible at. Will
629      */     * return -1 if any of the elments in the path are not currently visible.
630     protected PropertyChangeListener createPropertyChangeListener()     *
631     {     * @param tree is the current tree to return the row for.
632        return new PropertyChangeHandler();     * @param path is the path used to find the row.
633     }     * @return the row that the last item identified in path is visible at. Will
634       *         return -1 if any of the elments in the path are not currently
635     /**     *         visible.
636      * Creates the listener responsible for updating the selection based on mouse     */
637      * events.    public int getRowForPath(JTree tree, TreePath path)
638      *    {
639      * @return the MouseListener responsible for updating.      // FIXME: check visibility
640      */      // right now, just returns last element because
641     protected MouseListener createMouseListener()      // expand/collapse is not implemented
642     {      return path.getPathCount() - 1;
643        return new MouseHandler();    }
644     }    
645      /**
646     /**     * Returns the number of rows that are being displayed.
647      * Creates the listener that is responsible for updating the display when     *
648      * focus is lost/grained.     * @param tree is the current tree to return the number of rows for.
649      *     * @return the number of rows being displayed.
650      * @return the FocusListener responsible for updating.     */
651      */    public int getRowCount(JTree tree)
652     protected FocusListener createFocusListener()    {
653     {      DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel())
654        return new FocusHandler();          .getRoot());
655     }      if (!tree.isRootVisible()
656            && tree.isExpanded(new TreePath(((DefaultMutableTreeNode) node)
657     /**                                          .getPath())))
658      * Creates the listener reponsible for getting key events from the tree.        node = node.getNextNode();
659      *      
660      * @return the KeyListener responsible for getting key events.      int count = 0;
661      */      
662     protected KeyListener createKeyListener()      while (node != null)
663     {        {
664        return new KeyHandler();          count++;
665     }          node = getNextVisibleNode(node);
666          }
667     /**      
668      * Creates the listener responsible for getting property change events from      return count;
669      * the selection model.    }
670      *    
671      * @returns the PropertyChangeListener reponsible for getting property change    /**
672      *          events from the selection model.     * Returns the path to the node that is closest to x,y. If there is nothing
673      */     * currently visible this will return null, otherwise it'll always return a
674     protected PropertyChangeListener createSelectionModelPropertyChangeListener()     * valid path. If you need to test if the returned object is exactly at x,y
675     {     * you should get the bounds for the returned path and test x,y against that.
676        return new SelectionModelPropertyChangeHandler();     *
677     }     * @param tree the tree to search for the closest path
678       * @param x is the x coordinate of the location to search
679     /**     * @param y is the y coordinate of the location to search
680      * Creates the listener that updates the display based on selection change     * @return the tree path closes to x,y.
681      * methods.     */
682      *    public TreePath getClosestPathForLocation(JTree tree, int x, int y)
683      * @return the TreeSelectionListener responsible for updating.    {
684      */      //FIXME: what if root is hidden? should not depend on (0,0)
685     protected TreeSelectionListener createTreeSelectionListener()      // should start counting rows from where root is.
686     {      
687        return new TreeSelectionHandler();      int row = Math.round(y / getRowHeight());
688     }      TreePath path = getPathForRow(tree, row);
689        
690     /**      // no row is visible at this node
691      * Creates a listener to handle events from the current editor      while (row > 0 && path == null)
692      *        {
693      * @return the CellEditorListener that handles events from the current editor          --row;
694      */          path = getPathForRow(tree, row);
695     protected CellEditorListener createCellEditorListener()        }
696     {      
697        return new CellEditorHandler();      return path;
698     }    }
699      
700     /**    /**
701      * Creates and returns a new ComponentHandler. This is used for the large     * Returns true if the tree is being edited. The item that is being edited
702      * model to mark the validCachedPreferredSize as invalid when the component     * can be returned by getEditingPath().
703      * moves.     *
704      *     * @param tree is the tree to check for editing.
705      * @return a new ComponentHandler.     * @return true if the tree is being edited.
706      */     */
707     protected ComponentListener createComponentListener()    public boolean isEditing(JTree tree)
708     {    {
709        return new ComponentHandler();      // FIXME: not implemented
710     }      return false;
711      }
712     /**    
713      * Creates and returns the object responsible for updating the treestate when    /**
714      * a nodes expanded state changes.     * Stops the current editing session. This has no effect if the tree is not
715      *     * being edited. Returns true if the editor allows the editing session to
716      * @return the TreeExpansionListener responsible for updating the treestate     * stop.
717      */     *
718     protected TreeExpansionListener createTreeExpansionListener()     * @param tree is the tree to stop the editing on
719     {     * @return true if the editor allows the editing session to stop.
720        return new TreeExpansionHandler();     */
721     }    public boolean stopEditing(JTree tree)
722      {
723     /**      // FIXME: not implemented
724      * Creates the object responsible for managing what is expanded, as well as      return false;
725      * the size of nodes.    }
726      *    
727      * @return the object responsible for managing what is expanded.    /**
728      */     * Cancels the current editing session.
729     protected AbstractLayoutCache createLayoutCache()     *
730     {     * @param tree is the tree to cancel the editing session on.
731        return new FixedHeightLayoutCache();     */
732     }    public void cancelEditing(JTree tree)
733      {
734     /**      // FIXME: not implemented
735      * Returns the renderer pane that renderer components are placed in.    }
736      *    
737      * @return the rendererpane that render components are placed in.    /**
738      */     * Selects the last item in path and tries to edit it. Editing will fail if
739     protected CellRendererPane createCellRendererPane()     * the CellEditor won't allow it for the selected item.
740     {     *
741        return new CellRendererPane();     * @param tree is the tree to edit on.
742     }     * @param path is the path in tree to edit on.
743       */
744     /**    public void startEditingAtPath(JTree tree, TreePath path)
745      * Creates a default cell editor.    {
746      *      // FIXME: not implemented
747      * @return the default cell editor.    }
748      */    
749     protected TreeCellEditor createDefaultCellEditor()    /**
750     {     * Returns the path to the element that is being editted.
751        return new DefaultTreeCellEditor(tree,     *
752              (DefaultTreeCellRenderer) createDefaultCellRenderer(), cellEditor);     * @param tree is the tree to get the editing path from.
753     }     * @return the path that is being edited.
754       */
755     /**    public TreePath getEditingPath(JTree tree)
756      * Returns the default cell renderer that is used to do the stamping of each    {
757      * node.      // FIXME: not implemented
758      *      return null;
759      * @return the default cell renderer that is used to do the stamping of each    }
760      *         node.    
761      */    /**
762     protected TreeCellRenderer createDefaultCellRenderer()     * Invoked after the tree instance variable has been set, but before any
763     {     * default/listeners have been installed.
764        return new DefaultTreeCellRenderer();     */
765     }    protected void prepareForUIInstall()
766      {
767     /**      // FIXME: not implemented
768      * Returns a listener that can update the tree when the model changes.    }
769      *    
770      * @return a listener that can update the tree when the model changes.    /**
771      */     * Invoked from installUI after all the defaults/listeners have been
772     protected TreeModelListener createTreeModelListener()     * installed.
773     {     */
774        return new TreeModelHandler();    protected void completeUIInstall()
775     }    {
776        // FIXME: not implemented
777     /**    }
778      * Uninstall all registered listeners    
779      */    /**
780     protected void uninstallListeners()     * Invoked from uninstallUI after all the defaults/listeners have been
781     {     * uninstalled.
782        tree.removePropertyChangeListener(propertyChangeListener);     */
783        tree.removeFocusListener(focusListener);    protected void completeUIUninstall()
784        tree.removeTreeSelectionListener(treeSelectionListener);    {
785        tree.removeMouseListener(mouseInputListener);      // FIXME: not implemented
786        tree.removeKeyListener(keyListener);    }
787        tree.removePropertyChangeListener(selectionModelPropertyChangeListener);    
788        tree.removeComponentListener(componentListener);    /**
789        tree.removeTreeExpansionListener(treeExpansionListener);     * Installs the subcomponents of the tree, which is the renderer pane.
790             */
791        TreeCellEditor tce = tree.getCellEditor();    protected void installComponents()
792        if (tce != null)    {
793           tce.removeCellEditorListener(cellEditorListener);      // FIXME: not implemented
794        TreeModel tm = tree.getModel();    }
795        if (tm != null)    
796           tm.removeTreeModelListener(treeModelListener);    /**
797     }     * Creates an instance of NodeDimensions that is able to determine the size
798       * of a given node in the tree.
799     /**     *
800      * Uninstall all keyboard actions.     * @return the NodeDimensions of a given node in the tree
801      */     */
802     protected void uninstallKeyboardActions()    protected AbstractLayoutCache.NodeDimensions createNodeDimensions()
803     {    {
804     }      // FIXME: not implemented
805        return null;
806     /**    }
807      * Uninstall the rendererPane.    
808      */    /**
809     protected void uninstallComponents()     * Creates a listener that is reponsible for the updates the UI based on how
810     {     * the tree changes.
811        // FIXME: not implemented     *
812     }     * @return the PropertyChangeListener that is reposnsible for the updates
813       */
814     /**    protected PropertyChangeListener createPropertyChangeListener()
815      * The vertical element of legs between nodes starts at the bottom of the    {
816      * parent node by default. This method makes the leg start below that.      return new PropertyChangeHandler();
817      *    }
818      * @return the vertical leg buffer    
819      */    /**
820     protected int getVerticalLegBuffer()     * Creates the listener responsible for updating the selection based on mouse
821     {     * events.
822        // FIXME: not implemented     *
823        return 0;     * @return the MouseListener responsible for updating.
824     }     */
825      protected MouseListener createMouseListener()
826     /**    {
827      * The horizontal element of legs between nodes starts at the right of the      return new MouseHandler();
828      * left-hand side of the child node by default. This method makes the leg end    }
829      * before that.    
830      *    /**
831      * @return the horizontal leg buffer     * Creates the listener that is responsible for updating the display when
832      */     * focus is lost/grained.
833     protected int getHorizontalLegBuffer()     *
834     {     * @return the FocusListener responsible for updating.
835        // FIXME: not implemented     */
836        return 0;    protected FocusListener createFocusListener()
837     }    {
838        return new FocusHandler();
839     /**    }
840      * Make all the nodes that are expanded in JTree expanded in LayoutCache.    
841      * This invokes update ExpandedDescendants with the root path.    /**
842      */     * Creates the listener reponsible for getting key events from the tree.
843     protected void updateLayoutCacheExpandedNodes()     *
844     {     * @return the KeyListener responsible for getting key events.
845        // FIXME: not implemented     */
846     }    protected KeyListener createKeyListener()
847      {
848     /**      return new KeyHandler();
849      * Updates the expanded state of all the descendants of the <code>path</code>    }
850      * by getting the expanded descendants from the tree and forwarding to the    
851      * tree state.    /**
852      *     * Creates the listener responsible for getting property change events from
853      * @param path the path used to update the expanded states     * the selection model.
854      */     *
855     protected void updateExpandedDescendants(TreePath path)     * @returns the PropertyChangeListener reponsible for getting property change
856     {     *          events from the selection model.
857        // FIXME: not implemented     */
858     }    protected PropertyChangeListener createSelectionModelPropertyChangeListener()
859      {
860     /**      return new SelectionModelPropertyChangeHandler();
861      * Returns a path to the last child of <code>parent</code>    }
862      *    
863      * @param parent is the topmost path to specified    /**
864      * @return a path to the last child of parent     * Creates the listener that updates the display based on selection change
865      */     * methods.
866     protected TreePath getLastChildPath(TreePath parent)     *
867     {     * @return the TreeSelectionListener responsible for updating.
868        return ((TreePath) parent.getLastPathComponent());     */
869     }    protected TreeSelectionListener createTreeSelectionListener()
870      {
871     /**      return new TreeSelectionHandler();
872      * Updates how much each depth should be offset by.    }
873      */    
874     protected void updateDepthOffset()    /**
875     {     * Creates a listener to handle events from the current editor
876        // FIXME: not implemented     *
877     }     * @return the CellEditorListener that handles events from the current editor
878       */
879     /**    protected CellEditorListener createCellEditorListener()
880      * Updates the cellEditor based on editability of the JTree that we're    {
881      * contained in. Ig the tree is editable but doesn't have a cellEditor, a      return new CellEditorHandler();
882      * basic one will be used.    }
883      */    
884     protected void updateCellEditor()    /**
885     {     * Creates and returns a new ComponentHandler. This is used for the large
886        // FIXME: not implemented     * model to mark the validCachedPreferredSize as invalid when the component
887     }     * moves.
888       *
889     /**     * @return a new ComponentHandler.
890      * Messaged from the tree we're in when the renderer has changed.     */
891      */    protected ComponentListener createComponentListener()
892     protected void updateRenderer()    {
893     {      return new ComponentHandler();
894        // FIXME: not implemented    }
895     }    
896      /**
897     /**     * Creates and returns the object responsible for updating the treestate when
898      * Resets the treeState instance based on the tree we're providing the look     * a nodes expanded state changes.
899      * and feel for.     *
900      */     * @return the TreeExpansionListener responsible for updating the treestate
901     protected void configureLayoutCache()     */
902     {    protected TreeExpansionListener createTreeExpansionListener()
903        treeState = createLayoutCache();    {
904     }      return new TreeExpansionHandler();
905      }
906     /**    
907      * Marks the cached size as being invalid, and messages the tree with    /**
908      * <code>treeDidChange</code>.     * Creates the object responsible for managing what is expanded, as well as
909      */     * the size of nodes.
910     protected void updateSize()     *
911     {     * @return the object responsible for managing what is expanded.
912        // FIXME: not implemented     */
913     }    protected AbstractLayoutCache createLayoutCache()
914      {
915     /**      return new FixedHeightLayoutCache();
916      * Updates the <code>preferredSize</code> instance variable, which is    }
917      * returned from <code>getPreferredSize()</code>. For left to right    
918      * orientations, the size is determined from the current AbstractLayoutCache.    /**
919      * For RTL orientations, the preferred size becomes the width minus the     * Returns the renderer pane that renderer components are placed in.
920      * minimum x position.     *
921      */     * @return the rendererpane that render components are placed in.
922     protected void updateCachedPreferredSize()     */
923     {    protected CellRendererPane createCellRendererPane()
924        // FIXME: not implemented    {
925     }      return new CellRendererPane();
926      }
927     /**    
928      * Messaged from the VisibleTreeNode after it has been expanded.    /**
929      *     * Creates a default cell editor.
930      * @param path is the path that has been expanded.     *
931      */     * @return the default cell editor.
932     protected void pathWasExpanded(TreePath path)     */
933     {    protected TreeCellEditor createDefaultCellEditor()
934        // FIXME: not implemented    {
935     }      return new DefaultTreeCellEditor(tree,
936                                         (DefaultTreeCellRenderer) createDefaultCellRenderer(), cellEditor);
937     /**    }
938      * Messaged from the VisibleTreeNode after it has collapsed    
939      */    /**
940     protected void pathWasCollapsed(TreePath path)     * Returns the default cell renderer that is used to do the stamping of each
941     {     * node.
942        // FIXME: not implemented     *
943     }     * @return the default cell renderer that is used to do the stamping of each
944       *         node.
945     /**     */
946      * Install all defaults for the tree.    protected TreeCellRenderer createDefaultCellRenderer()
947      *    {
948      * @param tree is the JTree to install defaults for      return new DefaultTreeCellRenderer();
949      */    }
950     protected void installDefaults(JTree tree)    
951     {    /**
952        UIDefaults defaults = UIManager.getLookAndFeelDefaults();     * Returns a listener that can update the tree when the model changes.
953       *
954        tree.setFont(defaults.getFont("Tree.font"));     * @return a listener that can update the tree when the model changes.
955        tree.setForeground(defaults.getColor("Tree.foreground"));     */
956        tree.setBackground(defaults.getColor("Tree.background"));    protected TreeModelListener createTreeModelListener()
957        tree.setOpaque(true);    {
958        return new TreeModelHandler();
959        rightChildIndent = defaults.getInt("Tree.rightChildIndent");    }
960        leftChildIndent = defaults.getInt("Tree.leftChildIndent");    
961        setRowHeight(defaults.getInt("Tree.rowHeight"));    /**
962     }     * Uninstall all registered listeners
963       */
964     /**    protected void uninstallListeners()
965      * Install all keyboard actions for this    {
966      */      tree.removePropertyChangeListener(propertyChangeListener);
967     protected void installKeyboardActions()      tree.removeFocusListener(focusListener);
968     {      tree.removeTreeSelectionListener(treeSelectionListener);
969     }      tree.removeMouseListener(mouseInputListener);
970        tree.removeKeyListener(keyListener);
971     /**      tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
972      * Install all listeners for this      tree.removeComponentListener(componentListener);
973      */      tree.removeTreeExpansionListener(treeExpansionListener);
974     protected void installListeners()      
975     {      TreeCellEditor tce = tree.getCellEditor();
976        tree.addPropertyChangeListener(propertyChangeListener);      if (tce != null)
977        tree.addFocusListener(focusListener);        tce.removeCellEditorListener(cellEditorListener);
978        tree.addTreeSelectionListener(treeSelectionListener);      TreeModel tm = tree.getModel();
979        tree.addMouseListener(mouseInputListener);      if (tm != null)
980        tree.addKeyListener(keyListener);        tm.removeTreeModelListener(treeModelListener);
981        tree.addPropertyChangeListener(selectionModelPropertyChangeListener);    }
982        tree.addComponentListener(componentListener);    
983        cellEditor.addCellEditorListener(cellEditorListener);    /**
984        tree.addTreeExpansionListener(treeExpansionListener);     * Uninstall all keyboard actions.
985        treeModel.addTreeModelListener(treeModelListener);     */
986     }    protected void uninstallKeyboardActions()
987      {
988     /**    }
989      * Install the UI for the component    
990      *    /**
991      * @param c the component to install UI for     * Uninstall the rendererPane.
992      */     */
993     public void installUI(JComponent c)    protected void uninstallComponents()
994     {    {
995        super.installUI(c);      // FIXME: not implemented
996        installDefaults((JTree) c);    }
997        tree = (JTree) c;    
998        setModel(tree.getModel());    /**
999        tree.setRootVisible(true);     * The vertical element of legs between nodes starts at the bottom of the
1000        tree.expandPath(new TreePath(tree.getModel().getRoot()));     * parent node by default. This method makes the leg start below that.
1001        treeSelectionModel = tree.getSelectionModel();     *
1002        installListeners();     * @return the vertical leg buffer
1003        installKeyboardActions();     */
1004        completeUIInstall();    protected int getVerticalLegBuffer()
1005     }    {
1006        // FIXME: not implemented
1007     /**      return 0;
1008      * Uninstall the defaults for the tree    }
1009      *    
1010      * @param tree to uninstall defaults for    /**
1011      */     * The horizontal element of legs between nodes starts at the right of the
1012     protected void uninstallDefaults(JTree tree)     * left-hand side of the child node by default. This method makes the leg end
1013     {     * before that.
1014        UIDefaults defaults = UIManager.getLookAndFeelDefaults();     *
1015        tree.setFont(null);     * @return the horizontal leg buffer
1016        tree.setForeground(null);     */
1017        tree.setBackground(null);    protected int getHorizontalLegBuffer()
1018        tree.setCellRenderer(null);    {
1019     }      // FIXME: not implemented
1020        return 0;
1021     /**    }
1022      * Uninstall the UI for the component    
1023      *    /**
1024      * @param c the component to uninstall UI for     * Make all the nodes that are expanded in JTree expanded in LayoutCache.
1025      */     * This invokes update ExpandedDescendants with the root path.
1026     public void uninstallUI(JComponent c)     */
1027     {    protected void updateLayoutCacheExpandedNodes()
1028        uninstallDefaults((JTree) c);    {
1029        uninstallKeyboardActions();      // FIXME: not implemented
1030        uninstallListeners();    }
1031        tree = null;    
1032        completeUIUninstall();    /**
1033     }     * Updates the expanded state of all the descendants of the <code>path</code>
1034       * by getting the expanded descendants from the tree and forwarding to the
1035     /**     * tree state.
1036      * Paints the specified component appropriate for the look and feel. This     *
1037      * method is invoked from the ComponentUI.update method when the specified     * @param path the path used to update the expanded states
1038      * component is being painted. Subclasses should override this method and use     */
1039      * the specified Graphics object to render the content of the component.    protected void updateExpandedDescendants(TreePath path)
1040      *    {
1041      * @param g the Graphics context in which to paint      // FIXME: not implemented
1042      * @param c the component being painted; this argument is often ignored, but    }
1043      *        might be used if the UI object is stateless and shared by multiple    
1044      *        components    /**
1045      */     * Returns a path to the last child of <code>parent</code>
1046     public void paint(Graphics g, JComponent c)     *
1047     {     * @param parent is the topmost path to specified
1048        JTree tree = (JTree) c;     * @return a path to the last child of parent
1049        TreeModel mod = tree.getModel();     */
1050        Object root = mod.getRoot();    protected TreePath getLastChildPath(TreePath parent)
1051            {
1052        if (!tree.isRootVisible())      return ((TreePath) parent.getLastPathComponent());
1053           tree.expandPath(new TreePath(root));    }
1054            
1055        paintRecursive(g, 0, 0, 0, 0, tree, mod, root);    /**
1056             * Updates how much each depth should be offset by.
1057        if (hasControlIcons())     */
1058           paintControlIcons(g, 0, 0, 0, 0, tree, mod, root);    protected void updateDepthOffset()
1059     }    {
1060        // FIXME: not implemented
1061     /**    }
1062      * Ensures that the rows identified by beginRow through endRow are visible.    
1063      *    /**
1064      * @param beginRow is the first row     * Updates the cellEditor based on editability of the JTree that we're
1065      * @param endRow is the last row     * contained in. Ig the tree is editable but doesn't have a cellEditor, a
1066      */     * basic one will be used.
1067     protected void ensureRowsAreVisible(int beginRow, int endRow)     */
1068     {    protected void updateCellEditor()
1069        // FIXME: not implemented    {
1070     }      // FIXME: not implemented
1071      }
1072     /**    
1073      * Sets the preferred minimum size.    /**
1074      *     * Messaged from the tree we're in when the renderer has changed.
1075      * @param newSize is the new preferred minimum size.     */
1076      */    protected void updateRenderer()
1077     public void setPreferredMinSize(Dimension newSize)    {
1078     {      // FIXME: not implemented
1079        // FIXME: not implemented    }
1080     }    
1081      /**
1082     /**     * Resets the treeState instance based on the tree we're providing the look
1083      * Gets the preferred minimum size.     * and feel for.
1084      *     */
1085      * @returns the preferred minimum size.    protected void configureLayoutCache()
1086      */    {
1087     public Dimension getPreferredMinSize()      treeState = createLayoutCache();
1088     {    }
1089        // FIXME: not implemented    
1090        return null;    /**
1091     }     * Marks the cached size as being invalid, and messages the tree with
1092       * <code>treeDidChange</code>.
1093     /**     */
1094      * Returns the preferred size to properly display the tree, this is a cover    protected void updateSize()
1095      * method for getPreferredSize(c, false).    {
1096      *      // FIXME: not implemented
1097      * @param c the component whose preferred size is being queried; this    }
1098      *        argument is often ignored but might be used if the UI object is    
1099      *        stateless and shared by multiple components    /**
1100      * @return the preferred size     * Updates the <code>preferredSize</code> instance variable, which is
1101      */     * returned from <code>getPreferredSize()</code>. For left to right
1102     public Dimension getPreferredSize(JComponent c)     * orientations, the size is determined from the current AbstractLayoutCache.
1103     {     * For RTL orientations, the preferred size becomes the width minus the
1104        return getPreferredSize(c, false);     * minimum x position.
1105     }     */
1106      protected void updateCachedPreferredSize()
1107     /**    {
1108      * Returns the preferred size to represent the tree in c. If checkConsistancy      // FIXME: not implemented
1109      * is true, checkConsistancy is messaged first.    }
1110      *    
1111      * @param c the component whose preferred size is being queried.    /**
1112      * @param checkConsistancy if true must check consistancy     * Messaged from the VisibleTreeNode after it has been expanded.
1113      * @return the preferred size     *
1114      */     * @param path is the path that has been expanded.
1115     public Dimension getPreferredSize(JComponent c, boolean checkConsistancy)     */
1116     {    protected void pathWasExpanded(TreePath path)
1117        // FIXME: checkConsistancy not implemented, c not used    {
1118        TreeNode node = ((TreeNode) (tree.getModel())      // FIXME: not implemented
1119              .getRoot());    }
1120        int maxWidth = 0;    
1121        int count = 0;    /**
1122        if (node != null)     * Messaged from the VisibleTreeNode after it has collapsed
1123        {     */
1124           maxWidth = (int) (getCellBounds(0, 0, node).getWidth());    protected void pathWasCollapsed(TreePath path)
1125           while (node != null)    {
1126           {      // FIXME: not implemented
1127      }
1128      
1129      /**
1130       * Install all defaults for the tree.
1131       *
1132       * @param tree is the JTree to install defaults for
1133       */
1134      protected void installDefaults(JTree tree)
1135      {
1136        UIDefaults defaults = UIManager.getLookAndFeelDefaults();
1137        
1138        tree.setFont(defaults.getFont("Tree.font"));
1139        tree.setForeground(defaults.getColor("Tree.foreground"));
1140        tree.setBackground(defaults.getColor("Tree.background"));
1141        tree.setOpaque(true);
1142        
1143        rightChildIndent = defaults.getInt("Tree.rightChildIndent");
1144        leftChildIndent = defaults.getInt("Tree.leftChildIndent");
1145        setRowHeight(defaults.getInt("Tree.rowHeight"));
1146      }
1147      
1148      /**
1149       * Install all keyboard actions for this
1150       */
1151      protected void installKeyboardActions()
1152      {
1153      }
1154      
1155      /**
1156       * Install all listeners for this
1157       */
1158      protected void installListeners()
1159      {
1160        tree.addPropertyChangeListener(propertyChangeListener);
1161        tree.addFocusListener(focusListener);
1162        tree.addTreeSelectionListener(treeSelectionListener);
1163        tree.addMouseListener(mouseInputListener);
1164        tree.addKeyListener(keyListener);
1165        tree.addPropertyChangeListener(selectionModelPropertyChangeListener);
1166        tree.addComponentListener(componentListener);
1167        cellEditor.addCellEditorListener(cellEditorListener);
1168        tree.addTreeExpansionListener(treeExpansionListener);
1169        treeModel.addTreeModelListener(treeModelListener);
1170      }
1171      
1172      /**
1173       * Install the UI for the component
1174       *
1175       * @param c the component to install UI for
1176       */
1177      public void installUI(JComponent c)
1178      {
1179        super.installUI(c);
1180        installDefaults((JTree) c);
1181        tree = (JTree) c;
1182        setModel(tree.getModel());
1183        tree.setRootVisible(true);
1184        tree.expandPath(new TreePath(tree.getModel().getRoot()));
1185        treeSelectionModel = tree.getSelectionModel();
1186        installListeners();
1187        installKeyboardActions();
1188        completeUIInstall();
1189      }
1190      
1191      /**
1192       * Uninstall the defaults for the tree
1193       *
1194       * @param tree to uninstall defaults for
1195       */
1196      protected void uninstallDefaults(JTree tree)
1197      {
1198        UIDefaults defaults = UIManager.getLookAndFeelDefaults();
1199        tree.setFont(null);
1200        tree.setForeground(null);
1201        tree.setBackground(null);
1202        tree.setCellRenderer(null);
1203      }
1204      
1205      /**
1206       * Uninstall the UI for the component
1207       *
1208       * @param c the component to uninstall UI for
1209       */
1210      public void uninstallUI(JComponent c)
1211      {
1212        uninstallDefaults((JTree) c);
1213        uninstallKeyboardActions();
1214        uninstallListeners();
1215        tree = null;
1216        completeUIUninstall();
1217      }
1218      
1219      /**
1220       * Paints the specified component appropriate for the look and feel. This
1221       * method is invoked from the ComponentUI.update method when the specified
1222       * component is being painted. Subclasses should override this method and use
1223       * the specified Graphics object to render the content of the component.
1224       *
1225       * @param g the Graphics context in which to paint
1226       * @param c the component being painted; this argument is often ignored, but
1227       *        might be used if the UI object is stateless and shared by multiple
1228       *        components
1229       */
1230      public void paint(Graphics g, JComponent c)
1231      {
1232        JTree tree = (JTree) c;
1233        TreeModel mod = tree.getModel();
1234        Object root = mod.getRoot();
1235        
1236        if (!tree.isRootVisible())
1237          tree.expandPath(new TreePath(root));
1238        
1239        paintRecursive(g, 0, 0, 0, 0, tree, mod, root);
1240        
1241        if (hasControlIcons())
1242          paintControlIcons(g, 0, 0, 0, 0, tree, mod, root);
1243      }
1244      
1245      /**
1246       * Ensures that the rows identified by beginRow through endRow are visible.
1247       *
1248       * @param beginRow is the first row
1249       * @param endRow is the last row
1250       */
1251      protected void ensureRowsAreVisible(int beginRow, int endRow)
1252      {
1253        // FIXME: not implemented
1254      }
1255      
1256      /**
1257       * Sets the preferred minimum size.
1258       *
1259       * @param newSize is the new preferred minimum size.
1260       */
1261      public void setPreferredMinSize(Dimension newSize)
1262      {
1263        // FIXME: not implemented
1264      }
1265      
1266      /**
1267       * Gets the preferred minimum size.
1268       *
1269       * @returns the preferred minimum size.
1270       */
1271      public Dimension getPreferredMinSize()
1272      {
1273        // FIXME: not implemented
1274        return null;
1275      }
1276      
1277      /**
1278       * Returns the preferred size to properly display the tree, this is a cover
1279       * method for getPreferredSize(c, false).
1280       *
1281       * @param c the component whose preferred size is being queried; this
1282       *        argument is often ignored but might be used if the UI object is
1283       *        stateless and shared by multiple components
1284       * @return the preferred size
1285       */
1286      public Dimension getPreferredSize(JComponent c)
1287      {
1288        return getPreferredSize(c, false);
1289      }
1290      
1291      /**
1292       * Returns the preferred size to represent the tree in c. If checkConsistancy
1293       * is true, checkConsistancy is messaged first.
1294       *
1295       * @param c the component whose preferred size is being queried.
1296       * @param checkConsistancy if true must check consistancy
1297       * @return the preferred size
1298       */
1299      public Dimension getPreferredSize(JComponent c, boolean checkConsistancy)
1300      {
1301        // FIXME: checkConsistancy not implemented, c not used
1302        TreeNode node = ((TreeNode) (tree.getModel())
1303            .getRoot());
1304        int maxWidth = 0;
1305        int count = 0;
1306        if (node != null)
1307          {
1308            maxWidth = (int) (getCellBounds(0, 0, node).getWidth());
1309            while (node != null)
1310              {
1311              count++;              count++;
1312              DefaultMutableTreeNode nextNode = getNextVisibleNode(              DefaultMutableTreeNode nextNode = getNextVisibleNode(
1313                    new DefaultMutableTreeNode(node));                                                                   new DefaultMutableTreeNode(node));
1314              if (nextNode != null)              if (nextNode != null)
1315                 maxWidth = Math.max(maxWidth, (int) (getCellBounds(0, 0, nextNode)                maxWidth = Math.max(maxWidth, (int) (getCellBounds(0, 0, nextNode)
1316                       .getWidth()));                    .getWidth()));
1317              node = nextNode;              node = nextNode;
1318           }            }
1319        }        }
1320        return new Dimension(maxWidth, (getRowHeight() * count));      return new Dimension(maxWidth, (getRowHeight() * count));
1321     }    }
1322      
1323     /**    /**
1324      * Returns the minimum size for this component. Which will be the min     * Returns the minimum size for this component. Which will be the min
1325      * preferred size or (0,0).     * preferred size or (0,0).
1326      *     *
1327      * @param c the component whose min size is being queried.     * @param c the component whose min size is being queried.
1328      * @returns the preferred size or null     * @returns the preferred size or null
1329      */     */
1330     public Dimension getMinimumSize(JComponent c)    public Dimension getMinimumSize(JComponent c)
1331     {    {
1332        // FIXME: not implemented      // FIXME: not implemented
1333        return getPreferredSize(c);      return getPreferredSize(c);
1334     }    }
1335      
1336     /**    /**
1337      * Returns the maximum size for the component, which will be the preferred     * Returns the maximum size for the component, which will be the preferred
1338      * size if the instance is currently in JTree or (0,0).     * size if the instance is currently in JTree or (0,0).
1339      *     *
1340      * @param c the component whose preferred size is being queried     * @param c the component whose preferred size is being queried
1341      * @return the max size or null     * @return the max size or null
1342      */     */
1343     public Dimension getMaximumSize(JComponent c)    public Dimension getMaximumSize(JComponent c)
1344     {    {
1345        // FIXME: not implemented      // FIXME: not implemented
1346        return getPreferredSize(c);      return getPreferredSize(c);
1347     }    }
1348      
1349     /**    /**
1350      * Messages to stop the editing session. If the UI the receiver is providing     * Messages to stop the editing session. If the UI the receiver is providing
1351      * the look and feel for returns true from     * the look and feel for returns true from
1352      * <code>getInvokesStopCellEditing</code>, stopCellEditing will be invoked     * <code>getInvokesStopCellEditing</code>, stopCellEditing will be invoked
1353      * on the current editor. Then completeEditing will be messaged with false,     * on the current editor. Then completeEditing will be messaged with false,
1354      * true, false to cancel any lingering editing.     * true, false to cancel any lingering editing.
1355      */     */
1356     protected void completeEditing()    protected void completeEditing()
1357     {    {
1358        // FIXME: not implemented      // FIXME: not implemented
1359     }    }
1360      
1361     /**    /**
1362      * Stops the editing session. If messageStop is true, the editor is messaged     * Stops the editing session. If messageStop is true, the editor is messaged
1363      * with stopEditing, if messageCancel is true the editor is messaged with     * with stopEditing, if messageCancel is true the editor is messaged with
1364      * cancelEditing. If messageTree is true, the treeModel is messaged with     * cancelEditing. If messageTree is true, the treeModel is messaged with
1365      * valueForPathChanged.     * valueForPathChanged.
1366      *     *
1367      * @param messageStop message to stop editing     * @param messageStop message to stop editing
1368      * @param messageCancel message to cancel editing     * @param messageCancel message to cancel editing
1369      * @param messageTree message to treeModel     * @param messageTree message to treeModel
1370      */     */
1371     protected void completeEditing(boolean messageStop, boolean messageCancel,    protected void completeEditing(boolean messageStop, boolean messageCancel,
1372           boolean messageTree)                                   boolean messageTree)
1373     {    {
1374        // FIXME: not implemented      // FIXME: not implemented
1375     }    }
1376      
1377     /**    /**
1378      * Will start editing for node if there is a cellEditor and shouldSelectCall     * Will start editing for node if there is a cellEditor and shouldSelectCall
1379      * returns true. This assumes that path is valid and visible.     * returns true. This assumes that path is valid and visible.
1380      *     *
1381      * @param path is the path to start editing     * @param path is the path to start editing
1382      * @param event is the MouseEvent performed on the path     * @param event is the MouseEvent performed on the path
1383      * @return true if successful     * @return true if successful
1384      */     */
1385     protected boolean startEditing(TreePath path, MouseEvent event)    protected boolean startEditing(TreePath path, MouseEvent event)
1386     {    {
1387        // FIXME: not implemented      // FIXME: not implemented
1388        return false;      return false;
1389     }    }
1390      
1391     /**    /**
1392      * If the <code>mouseX</code> and <code>mouseY</code> are in the expand     * If the <code>mouseX</code> and <code>mouseY</code> are in the expand
1393      * or collapse region of the row, this will toggle the row.     * or collapse region of the row, this will toggle the row.
1394      *     *
1395      * @param path the path we are concerned with     * @param path the path we are concerned with
1396      * @param mouseX is the cursor's x position     * @param mouseX is the cursor's x position
1397      * @param mouseY is the cursor's y position     * @param mouseY is the cursor's y position
1398      */     */
1399     protected void checkForClickInExpandControl(TreePath path, int mouseX,    protected void checkForClickInExpandControl(TreePath path, int mouseX,
1400           int mouseY)                                                int mouseY)
1401     {    {
1402        // FIXME: not implemented      // FIXME: not implemented
1403     }    }
1404      
1405     /**    /**
1406      * Returns true if the <code>mouseX</code> and <code>mouseY</code> fall     * Returns true if the <code>mouseX</code> and <code>mouseY</code> fall
1407      * in the area of row that is used to expand/collpse the node and the node at     * in the area of row that is used to expand/collpse the node and the node at
1408      * row does not represent a leaf.     * row does not represent a leaf.
1409      *     *
1410      * @param path the path we are concerned with     * @param path the path we are concerned with
1411      * @param mouseX is the cursor's x position     * @param mouseX is the cursor's x position
1412      * @param mouseY is the cursor's y position     * @param mouseY is the cursor's y position
1413      * @return true if the <code>mouseX</code> and <code>mouseY</code> fall     * @return true if the <code>mouseX</code> and <code>mouseY</code> fall
1414      *         in the area of row that is used to expand/collpse the node and the     *         in the area of row that is used to expand/collpse the node and the
1415      *         node at row does not represent a leaf.     *         node at row does not represent a leaf.
1416      */     */
1417     protected boolean isLocationInExpandControl(TreePath path, int mouseX,    protected boolean isLocationInExpandControl(TreePath path, int mouseX,
1418           int mouseY)                                                int mouseY)
1419     {    {
1420        // FIXME: not implemented      // FIXME: not implemented
1421        return false;      return false;
1422     }    }
1423      
1424     /**    /**
1425      * Messaged when the user clicks the particular row, this invokes     * Messaged when the user clicks the particular row, this invokes
1426      * toggleExpandState.     * toggleExpandState.
1427      *     *
1428      * @param path the path we are concerned with     * @param path the path we are concerned with
1429      * @param mouseX is the cursor's x position     * @param mouseX is the cursor's x position
1430      * @param mouseY is the cursor's y position     * @param mouseY is the cursor's y position
1431      */     */
1432     protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY)    protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY)
1433     {    {
1434        // FIXME: not implemented      // FIXME: not implemented
1435     }    }
1436      
1437     /**    /**
1438      * Expands path if it is not expanded, or collapses row if it is expanded. If     * Expands path if it is not expanded, or collapses row if it is expanded. If
1439      * expanding a path and JTree scroll on expand, ensureRowsAreVisible is     * expanding a path and JTree scroll on expand, ensureRowsAreVisible is
1440      * invoked to scroll as many of the children to visible as possible (tries to     * invoked to scroll as many of the children to visible as possible (tries to
1441      * scroll to last visible descendant of path).     * scroll to last visible descendant of path).
1442      *     *
1443      * @param path the path we are concerned with     * @param path the path we are concerned with
1444      */     */
1445     protected void toggleExpandState(TreePath path)    protected void toggleExpandState(TreePath path)
1446     {    {
1447        // FIXME: not implemented      // FIXME: not implemented
1448     }    }
1449      
1450     /**    /**
1451      * Returning true signifies a mouse event on the node should toggle the     * Returning true signifies a mouse event on the node should toggle the
1452      * selection of only the row under the mouse.     * selection of only the row under the mouse.
1453      *     *
1454      * @param event is the MouseEvent performed on the row.     * @param event is the MouseEvent performed on the row.
1455      * @return true signifies a mouse event on the node should toggle the     * @return true signifies a mouse event on the node should toggle the
1456      *         selection of only the row under the mouse.     *         selection of only the row under the mouse.
1457      */     */
1458     protected boolean isToggleSelectionEvent(MouseEvent event)    protected boolean isToggleSelectionEvent(MouseEvent event)
1459     {    {
1460        // FIXME: not implemented      // FIXME: not implemented
1461        return false;      return false;
1462     }    }
1463      
1464     /**    /**
1465      * Returning true signifies a mouse event on the node should select from the     * Returning true signifies a mouse event on the node should select from the
1466      * anchor point.     * anchor point.
1467      *     *
1468      * @param event is the MouseEvent performed on the node.     * @param event is the MouseEvent performed on the node.
1469      * @return true signifies a mouse event on the node should select from the     * @return true signifies a mouse event on the node should select from the
1470      *         anchor point.     *         anchor point.
1471      */     */
1472     protected boolean isMultiSelectEvent(MouseEvent event)    protected boolean isMultiSelectEvent(MouseEvent event)
1473     {    {
1474        // FIXME: not implemented      // FIXME: not implemented
1475        return false;      return false;
1476     }    }
1477      
1478     /**    /**
1479      * Returning true indicates the row under the mouse should be toggled based     * Returning true indicates the row under the mouse should be toggled based
1480      * on the event. This is invoked after checkForClickInExpandControl, implying     * on the event. This is invoked after checkForClickInExpandControl, implying
1481      * the location is not in the expand (toggle) control.     * the location is not in the expand (toggle) control.
1482      *     *
1483      * @param event is the MouseEvent performed on the row.     * @param event is the MouseEvent performed on the row.
1484      * @return true indicates the row under the mouse should be toggled based on     * @return true indicates the row under the mouse should be toggled based on
1485      *         the event.     *         the event.
1486      */     */
1487     protected boolean isToggleEvent(MouseEvent event)    protected boolean isToggleEvent(MouseEvent event)
1488     {    {
1489        // FIXME: not implemented      // FIXME: not implemented
1490        return false;      return false;
1491     }    }
1492      
1493     /**    /**
1494      * Messaged to update the selection based on a MouseEvent over a particular     * Messaged to update the selection based on a MouseEvent over a particular
1495      * row. If the even is a toggle selection event, the row is either selected,     * row. If the even is a toggle selection event, the row is either selected,
1496      * or deselected. If the event identifies a multi selection event, the     * or deselected. If the event identifies a multi selection event, the
1497      * selection is updated from the anchor point. Otherwise, the row is     * selection is updated from the anchor point. Otherwise, the row is
1498      * selected, and if the even specified a toggle event the row is     * selected, and if the even specified a toggle event the row is
1499      * expanded/collapsed.     * expanded/collapsed.
1500      *     *
1501      * @param path is the path selected for an event     * @param path is the path selected for an event
1502      * @param event is the MouseEvent performed on the path.     * @param event is the MouseEvent performed on the path.
1503      */     */
1504     protected void selectPathForEvent(TreePath path, MouseEvent event)    protected void selectPathForEvent(TreePath path, MouseEvent event)
1505     {    {
1506        // FIXME: not implemented      // FIXME: not implemented
1507     }    }
1508      
1509     /**    /**
1510      * Returns true if the node at <code>row</code> is a leaf.     * Returns true if the node at <code>row</code> is a leaf.
1511      *     *
1512      * @param row is the row we are concerned with.     * @param row is the row we are concerned with.
1513      * @return true if the node at <code>row</code> is a leaf.     * @return true if the node at <code>row</code> is a leaf.
1514      */     */
1515     protected boolean isLeaf(int row)    protected boolean isLeaf(int row)
1516     {    {
1517        TreePath pathForRow = getPathForRow(tree, row);      TreePath pathForRow = getPathForRow(tree, row);
1518        if (pathForRow == null)      if (pathForRow == null)
1519           return true;        return true;
1520        
1521        Object node = pathForRow.getLastPathComponent();      Object node = pathForRow.getLastPathComponent();
1522        
1523        if (node instanceof TreeNode)      if (node instanceof TreeNode)
1524           return ((TreeNode) node).isLeaf();        return ((TreeNode) node).isLeaf();
1525        else      else
1526           return true;        return true;
1527     }    }
1528      
1529     /**    /**
1530      * Updates the preferred size when scrolling, if necessary.     * Updates the preferred size when scrolling, if necessary.
1531      */     */
1532     public class ComponentHandler    public class ComponentHandler
1533           extends ComponentAdapter    extends ComponentAdapter
1534           implements ActionListener    implements ActionListener
1535     {    {
1536        /**      /**
1537         * Timer used when inside a scrollpane and the scrollbar is adjusting       * Timer used when inside a scrollpane and the scrollbar is adjusting
1538         */       */
1539        protected Timer timer;      protected Timer timer;
1540        
1541        /** ScrollBar that is being adjusted */      /** ScrollBar that is being adjusted */
1542        protected JScrollBar scrollBar;      protected JScrollBar scrollBar;
1543        
1544        /**      /**
1545         * Constructor       * Constructor
1546         */       */
1547        public ComponentHandler()      public ComponentHandler()
1548        {      {
1549        }      }
1550        
1551        /**      /**
1552         * Invoked when the component's position changes.       * Invoked when the component's position changes.
1553         *       *
1554         * @param e the event that occurs when moving the component       * @param e the event that occurs when moving the component
1555         */       */
1556        public void componentMoved(ComponentEvent e)      public void componentMoved(ComponentEvent e)
1557        {      {
1558        }      }
1559        
1560        /**      /**
1561         * Creats, if necessary, and starts a Timer to check if needed to resize       * Creats, if necessary, and starts a Timer to check if needed to resize
1562         * the bounds       * the bounds
1563         */       */
1564        protected void startTimer()      protected void startTimer()
1565        {      {
1566        }      }
1567        
1568        /**      /**
1569         * Returns the JScrollPane housing the JTree, or null if one isn't found.       * Returns the JScrollPane housing the JTree, or null if one isn't found.
1570         *       *
1571         * @return JScrollPane housing the JTree, or null if one isn't found.       * @return JScrollPane housing the JTree, or null if one isn't found.
1572         */       */
1573        protected JScrollPane getScrollPane()      protected JScrollPane getScrollPane()
1574        {      {
1575           return null;        return null;
1576        }      }
1577        
1578        /**      /**
1579         * Public as a result of Timer. If the scrollBar is null, or not       * Public as a result of Timer. If the scrollBar is null, or not
1580         * adjusting, this stops the timer and updates the sizing.       * adjusting, this stops the timer and updates the sizing.
1581         *       *
1582         * @param ae is the action performed       * @param ae is the action performed
1583         */       */
1584        public void actionPerformed(ActionEvent ae)      public void actionPerformed(ActionEvent ae)
1585        {      {
1586        }      }
1587     }// ComponentHandler    }// ComponentHandler
1588      
1589     /**    /**
1590      * Listener responsible for getting cell editing events and updating the tree     * Listener responsible for getting cell editing events and updating the tree
1591      * accordingly.     * accordingly.
1592      */     */
1593     public class CellEditorHandler    public class CellEditorHandler
1594           implements CellEditorListener    implements CellEditorListener
1595     {    {
1596        /**      /**
1597         * Constructor       * Constructor
1598         */       */
1599        public CellEditorHandler()      public CellEditorHandler()
1600        {      {
1601        }      }
1602        
1603        /**      /**
1604         * Messaged when editing has stopped in the tree. Tells the listeners       * Messaged when editing has stopped in the tree. Tells the listeners
1605         * editing has stopped.       * editing has stopped.
1606         *       *
1607         * @param e is the notification event       * @param e is the notification event
1608         */       */
1609        public void editingStopped(ChangeEvent e)      public void editingStopped(ChangeEvent e)
1610        {      {
1611        }      }
1612        
1613        /**      /**
1614         * Messaged when editing has been canceled in the tree. This tells the       * Messaged when editing has been canceled in the tree. This tells the
1615         * listeners the editor has canceled editing.       * listeners the editor has canceled editing.
1616         *       *
1617         * @param e is the notification event       * @param e is the notification event
1618         */       */
1619        public void editingCanceled(ChangeEvent e)      public void editingCanceled(ChangeEvent e)
1620        {      {
1621        }      }
1622     }// CellEditorHandler    }// CellEditorHandler
1623      
1624     /**    /**
1625      * Repaints the lead selection row when focus is lost/grained.     * Repaints the lead selection row when focus is lost/grained.
1626      */     */
1627     public class FocusHandler    public class FocusHandler
1628           implements FocusListener    implements FocusListener
1629     {    {
1630        /**      /**
1631         * Constructor       * Constructor
1632         */       */
1633        public FocusHandler()      public FocusHandler()
1634        {      {
1635        }      }
1636        
1637        /**      /**
1638         * Invoked when focus is activated on the tree we're in, redraws the lead       * Invoked when focus is activated on the tree we're in, redraws the lead
1639         * row. Invoked when a component gains the keyboard focus.       * row. Invoked when a component gains the keyboard focus.
1640         *       *
1641         * @param e is the focus event that is activated       * @param e is the focus event that is activated
1642         */       */
1643        public void focusGained(FocusEvent e)      public void focusGained(FocusEvent e)
1644        {      {
1645        }      }
1646        
1647        /**      /**
1648         * Invoked when focus is deactivated on the tree we're in, redraws the       * Invoked when focus is deactivated on the tree we're in, redraws the
1649         * lead row. Invoked when a component loses the keyboard focus.       * lead row. Invoked when a component loses the keyboard focus.
1650         *       *
1651         * @param e is the focus event that is deactivated       * @param e is the focus event that is deactivated
1652         */       */
1653        public void focusLost(FocusEvent e)      public void focusLost(FocusEvent e)
1654        {      {
1655        }      }
1656     }// FocusHandler    }// FocusHandler
1657      
1658     /**    /**
1659      * This is used to get multiple key down events to appropriately genereate     * This is used to get multiple key down events to appropriately genereate
1660      * events.     * events.
1661      */     */
1662     public class KeyHandler    public class KeyHandler
1663           extends KeyAdapter    extends KeyAdapter
1664     {    {
1665        /** Key code that is being generated for. */      /** Key code that is being generated for. */
1666        protected Action repeatKeyAction;      protected Action repeatKeyAction;
1667        
1668        /** Set to true while keyPressed is active */      /** Set to true while keyPressed is active */
1669        protected boolean isKeyDown;      protected boolean isKeyDown;
1670        
1671        /**      /**
1672         * Constructor       * Constructor
1673         */       */
1674        public KeyHandler()      public KeyHandler()
1675        {      {
1676        }      }
1677        
1678        /**      /**
1679         * Invoked when a key has been typed. Moves the keyboard focus to the       * Invoked when a key has been typed. Moves the keyboard focus to the
1680         * first element whose first letter matches the alphanumeric key pressed       * first element whose first letter matches the alphanumeric key pressed
1681         * by the user. Subsequent same key presses move the keyboard focus to the       * by the user. Subsequent same key presses move the keyboard focus to the
1682         * next object that starts with the same letter.       * next object that starts with the same letter.
1683         *       *
1684         * @param e the key typed       * @param e the key typed
1685         */       */
1686        public void keyTyped(KeyEvent e)      public void keyTyped(KeyEvent e)
1687        {      {
1688        }      }
1689        
1690        /**      /**
1691         * Invoked when a key has been pressed.       * Invoked when a key has been pressed.
1692         *       *
1693         * @param e the key pressed       * @param e the key pressed
1694         */       */
1695        public void keyPressed(KeyEvent e)      public void keyPressed(KeyEvent e)
1696        {      {
1697           TreePath start = BasicTreeUI.this.tree.getLeadSelectionPath();        TreePath start = BasicTreeUI.this.tree.getLeadSelectionPath();
1698           DefaultMutableTreeNode last = null;        DefaultMutableTreeNode last = null;
1699           if (start != null)        if (start != null)
1700              last = (DefaultMutableTreeNode) start.getLastPathComponent();          last = (DefaultMutableTreeNode) start.getLastPathComponent();
1701          
1702           if (last != null)        if (last != null)
1703           {          {
1704              // DOWN, KP_DOWN            // DOWN, KP_DOWN
1705              if (e.getKeyCode() == KeyEvent.VK_DOWN            if (e.getKeyCode() == KeyEvent.VK_DOWN
1706                    || e.getKeyCode() == KeyEvent.VK_KP_DOWN)                || e.getKeyCode() == KeyEvent.VK_KP_DOWN)
1707              {              {
1708                 DefaultMutableTreeNode next = (DefaultMutableTreeNode)                DefaultMutableTreeNode next = (DefaultMutableTreeNode)
1709                    BasicTreeUI.this.getNextVisibleNode(last);                BasicTreeUI.this.getNextVisibleNode(last);
1710                 if (next != null)                if (next != null)
1711                 {                  {
1712                    TreePath newPath = new TreePath(next.getPath());                    TreePath newPath = new TreePath(next.getPath());
1713                    BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, newPath);                    BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, newPath);
1714                    if (e.isControlDown())                    if (e.isControlDown())
1715                       tree.setLeadSelectionPath(newPath);                      tree.setLeadSelectionPath(newPath);
1716                    else if (!next.isLeaf() && e.isShiftDown())                    else if (!next.isLeaf() && e.isShiftDown())
1717                    {                      {
1718                       BasicTreeUI.this.tree.expandPath(newPath);                        BasicTreeUI.this.tree.expandPath(newPath);
1719                       BasicTreeUI.this.tree.fireTreeExpanded(newPath);                        BasicTreeUI.this.tree.fireTreeExpanded(newPath);
1720                    }                      }
1721                 }                  }
1722              }              }
1723              // UP, KP_UP            // UP, KP_UP
1724              else if (e.getKeyCode() == KeyEvent.VK_UP            else if (e.getKeyCode() == KeyEvent.VK_UP
1725                    || e.getKeyCode() == KeyEvent.VK_KP_UP)                || e.getKeyCode() == KeyEvent.VK_KP_UP)
1726              {              {
1727                 DefaultMutableTreeNode prev = (DefaultMutableTreeNode)                DefaultMutableTreeNode prev = (DefaultMutableTreeNode)
1728                    BasicTreeUI.this.getPreviousVisibleNode(last);                BasicTreeUI.this.getPreviousVisibleNode(last);
1729                  
1730                 if (prev != null)                if (prev != null)
1731                 {                  {
1732                    TreePath newPath = new TreePath(prev.getPath());                    TreePath newPath = new TreePath(prev.getPath());
1733                    BasicTreeUI.this.selectPath(BasicTreeUI.this.tree,                    BasicTreeUI.this.selectPath(BasicTreeUI.this.tree,
1734                          new TreePath(prev.getPath()));                                                new TreePath(prev.getPath()));
1735                    if (e.isControlDown())                    if (e.isControlDown())
1736                       tree.setLeadSelectionPath(newPath);                      tree.setLeadSelectionPath(newPath);
1737                    else if (!prev.isLeaf() && e.isShiftDown())                    else if (!prev.isLeaf() && e.isShiftDown())
1738                    {                      {
1739                       BasicTreeUI.this.tree.expandPath(newPath);                        BasicTreeUI.this.tree.expandPath(newPath);
1740                       BasicTreeUI.this.tree.fireTreeExpanded(newPath);                        BasicTreeUI.this.tree.fireTreeExpanded(newPath);
1741                    }                      }
1742                 }                  }
1743              }              }
1744              // LEFT, KP_LEFT            // LEFT, KP_LEFT
1745              else if (e.getKeyCode() == KeyEvent.VK_LEFT            else if (e.getKeyCode() == KeyEvent.VK_LEFT
1746                    || e.getKeyCode() == KeyEvent.VK_KP_LEFT)                || e.getKeyCode() == KeyEvent.VK_KP_LEFT)
1747              {              {
1748                 TreePath path = new TreePath(last.getPath());                TreePath path = new TreePath(last.getPath());
1749                 DefaultMutableTreeNode p = (DefaultMutableTreeNode) last                DefaultMutableTreeNode p = (DefaultMutableTreeNode) last
1750                       .getParent();                .getParent();
1751                  
1752                 if (!last.isLeaf() && BasicTreeUI.this.tree.isExpanded(path))                if (!last.isLeaf() && BasicTreeUI.this.tree.isExpanded(path))
1753                 {                  {
1754                    BasicTreeUI.this.tree.collapsePath(path);                    BasicTreeUI.this.tree.collapsePath(path);
1755                    BasicTreeUI.this.tree.fireTreeCollapsed(path);                    BasicTreeUI.this.tree.fireTreeCollapsed(path);
1756                 }                  }
1757                 else if (p != null)                else if (p != null)
1758                    BasicTreeUI.this.selectPath(BasicTreeUI.this.tree,                  BasicTreeUI.this.selectPath(BasicTreeUI.this.tree,
1759                          new TreePath(p.getPath()));                                              new TreePath(p.getPath()));
1760              }              }
1761              // RIGHT, KP_RIGHT            // RIGHT, KP_RIGHT
1762              else if (e.getKeyCode() == KeyEvent.VK_RIGHT            else if (e.getKeyCode() == KeyEvent.VK_RIGHT
1763                    || e.getKeyCode() == KeyEvent.VK_KP_RIGHT)                || e.getKeyCode() == KeyEvent.VK_KP_RIGHT)
1764              {              {
1765                 TreePath path = new TreePath(last.getPath());                TreePath path = new TreePath(last.getPath());
1766                  
1767                 if (!last.isLeaf() && BasicTreeUI.this.tree.isCollapsed(path))                if (!last.isLeaf() && BasicTreeUI.this.tree.isCollapsed(path))
1768                 {                  {
1769                    BasicTreeUI.this.tree.expandPath(path);                    BasicTreeUI.this.tree.expandPath(path);
1770                    BasicTreeUI.this.tree.fireTreeExpanded(path);                    BasicTreeUI.this.tree.fireTreeExpanded(path);
1771                 }                  }
1772                 else                else
1773                 {                  {
1774                    DefaultMutableTreeNode next = (DefaultMutableTreeNode)                    DefaultMutableTreeNode next = (DefaultMutableTreeNode)
1775                       BasicTreeUI.this.getNextVisibleNode(last);                    BasicTreeUI.this.getNextVisibleNode(last);
1776                      
1777                    if (next != null)                    if (next != null)
1778                       BasicTreeUI.this.selectPath(BasicTreeUI.this.tree,                      BasicTreeUI.this.selectPath(BasicTreeUI.this.tree,
1779                             new TreePath(next.getPath()));                                                  new TreePath(next.getPath()));
1780                 }                  }
1781              }              }
1782              // Enter            // Enter
1783              else if (e.getKeyCode() == KeyEvent.VK_ENTER)            else if (e.getKeyCode() == KeyEvent.VK_ENTER)
1784              {              {
1785                 TreePath path = new TreePath(last.getPath());                TreePath path = new TreePath(last.getPath());
1786                 if (!last.isLeaf())                if (!last.isLeaf())
1787                 {                  {
1788                    if (BasicTreeUI.this.tree.isExpanded(path))                    if (BasicTreeUI.this.tree.isExpanded(path))
1789                    {                      {
1790                       BasicTreeUI.this.tree.collapsePath(path);                        BasicTreeUI.this.tree.collapsePath(path);
1791                       BasicTreeUI.this.tree.fireTreeCollapsed(path);                        BasicTreeUI.this.tree.fireTreeCollapsed(path);
1792                    }                      }
1793                    else                    else
1794                    {                      {
1795                       BasicTreeUI.this.tree.expandPath(path);                        BasicTreeUI.this.tree.expandPath(path);
1796                       BasicTreeUI.this.tree.fireTreeExpanded(path);                        BasicTreeUI.this.tree.fireTreeExpanded(path);
1797                    }                      }
1798                 }                  }
1799              }              }
1800           }          }
1801        }      }
1802        
1803        /**      /**
1804         * Invoked when a key has been released       * Invoked when a key has been released
1805         *       *
1806         * @param e the key released       * @param e the key released
1807         */       */
1808        public void keyReleased(KeyEvent e)      public void keyReleased(KeyEvent e)
1809        {      {
1810        }      }
1811     }// KeyHandler    }// KeyHandler
1812      
1813     /**    /**
1814      * MouseListener is responsible for updating the selevtion based on mouse     * MouseListener is responsible for updating the selevtion based on mouse
1815      * events.     * events.
1816      */     */
1817     public class MouseHandler    public class MouseHandler
1818           extends MouseAdapter    extends MouseAdapter
1819           implements MouseMotionListener    implements MouseMotionListener
1820     {    {
1821        /**      /**
1822         * Constructor       * Constructor
1823         */       */
1824        public MouseHandler()      public MouseHandler()
1825        {      {
1826        }      }
1827        
1828        /**      /**
1829         * Invoked when a mouse button has been pressed on a component.       * Invoked when a mouse button has been pressed on a component.
1830         *       *
1831         * @param e is the mouse event that occured       * @param e is the mouse event that occured
1832         */       */
1833        public void mousePressed(MouseEvent e)      public void mousePressed(MouseEvent e)
1834        {      {
1835        }      }
1836        
1837        /**      /**
1838         * Invoked when a mouse button is pressed on a component and then dragged.       * Invoked when a mouse button is pressed on a component and then dragged.
1839         * MOUSE_DRAGGED events will continue to be delivered to the component       * MOUSE_DRAGGED events will continue to be delivered to the component
1840         * where the drag originated until the mouse button is released       * where the drag originated until the mouse button is released
1841         * (regardless of whether the mouse position is within the bounds of the       * (regardless of whether the mouse position is within the bounds of the
1842         * component).       * component).
1843         *       *
1844         * @param e is the mouse event that occured       * @param e is the mouse event that occured
1845         */       */
1846        public void mouseDragged(MouseEvent e)      public void mouseDragged(MouseEvent e)
1847        {      {
1848        }      }
1849        
1850        /**      /**
1851         * Invoked when the mouse button has been moved on a component (with no       * Invoked when the mouse button has been moved on a component (with no
1852         * buttons no down).       * buttons no down).
1853         *       *
1854         * @param e the mouse event that occured       * @param e the mouse event that occured
1855         */       */
1856        public void mouseMoved(MouseEvent e)      public void mouseMoved(MouseEvent e)
1857        {      {
1858        }      }
1859        
1860        /**      /**
1861         * Invoked when a mouse button has been released on a component.       * Invoked when a mouse button has been released on a component.
1862         *       *
1863         * @param e is the mouse event that occured       * @param e is the mouse event that occured
1864         */       */
1865        public void mouseReleased(MouseEvent e)      public void mouseReleased(MouseEvent e)
1866        {      {
1867        }      }
1868     }// MouseHandler    }// MouseHandler
1869      
1870     /**    /**
1871      * MouseInputHandler handles passing all mouse events, including mouse motion     * MouseInputHandler handles passing all mouse events, including mouse motion
1872      * events, until the mouse is released to the destination it is constructed     * events, until the mouse is released to the destination it is constructed
1873      * with.     * with.
1874      */     */
1875     public class MouseInputHandler    public class MouseInputHandler
1876           implements MouseInputListener    implements MouseInputListener
1877     {    {
1878        /** Source that events are coming from */      /** Source that events are coming from */
1879        protected Component source;      protected Component source;
1880        
1881        /** Destination that receives all events. */      /** Destination that receives all events. */
1882        protected Component destination;      protected Component destination;
1883        
1884        /** Number of mouse clicks on a non-leaf */
1885        private int clickCount = 0;
1886        
1887        /** The last non-leaf cell that was clicked */
1888        private Object lastClicked = null;
1889        
1890        /**
1891         * Constructor
1892         *
1893         * @param source that events are coming from
1894         * @param destination that receives all events
1895         * @param e is the event received
1896         */
1897        public MouseInputHandler(Component source, Component destination,
1898                                 MouseEvent e)
1899        {
1900        }
1901        
1902        /**
1903         * Invoked when the mouse button has been clicked (pressed and released)
1904         * on a component.
1905         *
1906         * @param e mouse event that occured
1907         */
1908        public void mouseClicked(MouseEvent e)
1909        {
1910          Point click = e.getPoint();
1911          int row = Math.round(click.y / BasicTreeUI.this.getRowHeight());
1912          TreePath path = BasicTreeUI.this.getClosestPathForLocation(tree,
1913                                                                     click.x, click.y);
1914                
1915        /** Number of mouse clicks on a non-leaf */        if (path != null)
1916        private int clickCount = 0;          {
1917                    boolean inBounds = false;
1918        /** The last non-leaf cell that was clicked */            boolean cntlClick = false;
1919        private Object lastClicked = null;            Rectangle bounds = BasicTreeUI.this.getPathBounds(
1920                                                                BasicTreeUI.this.tree, path);
1921        /**            
1922         * Constructor            bounds.x -= rightChildIndent - 4;
1923         *            bounds.width += rightChildIndent + 4;
1924         * @param source that events are coming from            
1925         * @param destination that receives all events            if (bounds.contains(click.x, click.y))
1926         * @param e is the event received              inBounds = true;
1927         */            else if (BasicTreeUI.this.hasControlIcons()
1928        public MouseInputHandler(Component source, Component destination,                && (click.x < (bounds.x - rightChildIndent + 5) &&
1929              MouseEvent e)                    click.x > (bounds.x - rightChildIndent - 5)))
1930        {              cntlClick = true;
1931        }            
1932              if ((inBounds || cntlClick)
1933        /**                && BasicTreeUI.this.tree.isVisible(path))
        * Invoked when the mouse button has been clicked (pressed and released)  
        * on a component.  
        *  
        * @param e mouse event that occured  
        */  
       public void mouseClicked(MouseEvent e)  
       {  
          Point click = e.getPoint();  
          int row = Math.round(click.y / BasicTreeUI.this.getRowHeight());  
          TreePath path = BasicTreeUI.this.getClosestPathForLocation(tree,  
                click.x, click.y);  
   
          if (path != null)  
          {  
             boolean inBounds = false;  
             boolean cntlClick = false;  
             Rectangle bounds = BasicTreeUI.this.getPathBounds(  
                   BasicTreeUI.this.tree, path);  
               
             bounds.x -= rightChildIndent - 4;  
             bounds.width += rightChildIndent + 4;  
   
             if (bounds.contains(click.x, click.y))  
                inBounds = true;  
             else if (BasicTreeUI.this.hasControlIcons()  
                   && (click.x < (bounds.x - rightChildIndent + 5) &&  
                         click.x > (bounds.x - rightChildIndent - 5)))  
                cntlClick = true;  
   
             if ((inBounds || cntlClick)  
                   && BasicTreeUI.this.tree.isVisible(path))  
1934              {              {
1935                 if (!cntlClick && !BasicTreeUI.this.isLeaf(row))                if (!cntlClick && !BasicTreeUI.this.isLeaf(row))
1936                 {                  {
1937                    Object cell = path.getLastPathComponent();                    Object cell = path.getLastPathComponent();
1938                    if (lastClicked != null && lastClicked.equals(cell))                    if (lastClicked != null && lastClicked.equals(cell))
1939                       clickCount = 2;                      clickCount = 2;
1940                    else                    else
1941                    {                      {
1942                       lastClicked = cell;                        lastClicked = cell;
1943                       clickCount = 1;                        clickCount = 1;
1944                    }                      }
1945                 }                  }
1946                  
1947                 if (clickCount == 2 || cntlClick == true)                if (clickCount == 2 || cntlClick == true)
1948                 {                  {
1949                    clickCount = 0;                    clickCount = 0;
1950                    lastClicked = null;                    lastClicked = null;
1951                    BasicTreeUI.this.tree.getSelectionModel().clearSelection();                    BasicTreeUI.this.tree.getSelectionModel().clearSelection();
1952                    if (BasicTreeUI.this.tree.isExpanded(path))                    if (BasicTreeUI.this.tree.isExpanded(path))
1953                    {                      {
1954                       BasicTreeUI.this.tree.collapsePath(path);                        BasicTreeUI.this.tree.collapsePath(path);
1955                       BasicTreeUI.this.tree.fireTreeCollapsed(path);                        BasicTreeUI.this.tree.fireTreeCollapsed(path);
1956                    }                      }
1957                    else                    else
1958                    {                      {
1959                       BasicTreeUI.this.tree.expandPath(path);                        BasicTreeUI.this.tree.expandPath(path);
1960                       BasicTreeUI.this.tree.fireTreeExpanded(path);                        BasicTreeUI.this.tree.fireTreeExpanded(path);
1961                    }                      }
1962                 }                  }
1963                  
1964                 BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, path);                BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, path);
1965              }              }
1966           }          }
1967        }      }
1968        
1969        /**      /**
1970         * Invoked when a mouse button has been pressed on a component.       * Invoked when a mouse button has been pressed on a component.
1971         *       *
1972         * @param e mouse event that occured       * @param e mouse event that occured
1973         */       */
1974        public void mousePressed(MouseEvent e)      public void mousePressed(MouseEvent e)
1975        {      {
1976        }      }
1977        
1978        /**      /**
1979         * Invoked when a mouse button has been released on a component.       * Invoked when a mouse button has been released on a component.
1980         *       *
1981         * @param e mouse event that occured       * @param e mouse event that occured
1982         */       */
1983        public void mouseReleased(MouseEvent e)      public void mouseReleased(MouseEvent e)
1984        {      {
1985        }      }
1986        
1987        /**      /**
1988         * Invoked when the mouse enters a component.       * Invoked when the mouse enters a component.
1989         *       *
1990         * @param e mouse event that occured       * @param e mouse event that occured
1991         */       */
1992        public void mouseEntered(MouseEvent e)      public void mouseEntered(MouseEvent e)
1993        {      {
1994        }      }
1995        
1996        /**      /**
1997         * Invoked when the mouse exits a component.       * Invoked when the mouse exits a component.
1998         *       *
1999         * @param e mouse event that occured       * @param e mouse event that occured
2000         */       */
2001        public void mouseExited(MouseEvent e)      public void mouseExited(MouseEvent e)
2002        {      {
2003        }      }
2004        
2005        /**      /**
2006         * Invoked when a mouse button is pressed on a component and then dragged.       * Invoked when a mouse button is pressed on a component and then dragged.
2007         * MOUSE_DRAGGED events will continue to be delivered to the component       * MOUSE_DRAGGED events will continue to be delivered to the component
2008         * where the drag originated until the mouse button is released       * where the drag originated until the mouse button is released
2009         * (regardless of whether the mouse position is within the bounds of the       * (regardless of whether the mouse position is within the bounds of the
2010         * component).       * component).
2011         *       *
2012         * @param e mouse event that occured       * @param e mouse event that occured
2013         */       */
2014        public void mouseDragged(MouseEvent e)      public void mouseDragged(MouseEvent e)
2015        {      {
2016        }      }
2017        
2018        /**      /**
2019         * Invoked when the mouse cursor has been moved onto a component but no       * Invoked when the mouse cursor has been moved onto a component but no
2020         * buttons have been pushed.       * buttons have been pushed.
2021         *       *
2022         * @param e mouse event that occured       * @param e mouse event that occured
2023         */       */
2024        public void mouseMoved(MouseEvent e)      public void mouseMoved(MouseEvent e)
2025        {      {
2026        }      }
2027        
2028        /**      /**
2029         * Removes event from the source       * Removes event from the source
2030         */       */
2031        protected void removeFromSource()      protected void removeFromSource()
2032        {      {
2033        }      }
2034     }// MouseInputHandler    }// MouseInputHandler
2035      
2036     /**    /**
2037      * Class responsible for getting size of node, method is forwarded to     * Class responsible for getting size of node, method is forwarded to
2038      * BasicTreeUI method. X location does not include insets, that is handled in     * BasicTreeUI method. X location does not include insets, that is handled in
2039      * getPathBounds.     * getPathBounds.
2040      */     */
2041     public class NodeDimensionsHandler    public class NodeDimensionsHandler
2042           extends AbstractLayoutCache.NodeDimensions    extends AbstractLayoutCache.NodeDimensions
2043     {    {
2044        /**      /**
2045         * Constructor       * Constructor
2046         */       */
2047        public NodeDimensionsHandler()      public NodeDimensionsHandler()
2048        {      {
2049        }      }
2050        
2051        /**      /**
2052         * Responsible for getting the size of a particular node.       * Responsible for getting the size of a particular node.
2053         *       *
2054         * @param value the value to be represented       * @param value the value to be represented
2055         * @param row row being queried       * @param row row being queried
2056         * @param depth the depth of the row       * @param depth the depth of the row
2057         * @param expanded true if row is expanded       * @param expanded true if row is expanded
2058         * @param size a Rectangle containing the size needed to represent value       * @param size a Rectangle containing the size needed to represent value
2059         * @return containing the node dimensions, or null if node has no       * @return containing the node dimensions, or null if node has no
2060         *         dimension       *         dimension
2061         */       */
2062        public Rectangle getNodeDimensions(Object value, int row, int depth,      public Rectangle getNodeDimensions(Object value, int row, int depth,
2063              boolean expanded, Rectangle size)                                         boolean expanded, Rectangle size)
2064        {      {
2065           return null;        return null;
2066        }      }
2067        
2068        /**      /**
2069         * Returns the amount to indent the given row       * Returns the amount to indent the given row
2070         *       *
2071         * @return amount to indent the given row.       * @return amount to indent the given row.
2072         */       */
2073        protected int getRowX(int row, int depth)      protected int getRowX(int row, int depth)
2074        {      {
2075           return 0;        return 0;
2076        }      }
2077     }// NodeDimensionsHandler    }// NodeDimensionsHandler
2078      
2079     /**    /**
2080      * PropertyChangeListener for the tree. Updates the appropriate varaible, or     * PropertyChangeListener for the tree. Updates the appropriate varaible, or
2081      * TreeState, based on what changes.     * TreeState, based on what changes.
2082      */     */
2083     public class PropertyChangeHandler    public class PropertyChangeHandler
2084           implements PropertyChangeListener    implements PropertyChangeListener
2085     {    {
2086        
2087        /**      /**
2088         * Constructor       * Constructor
2089         */       */
2090        public PropertyChangeHandler()      public PropertyChangeHandler()
2091        {      {
2092        }      }
2093        
2094        /**      /**
2095         * This method gets called when a bound property is changed.       * This method gets called when a bound property is changed.
2096         *       *
2097         * @param event A PropertyChangeEvent object describing the event source       * @param event A PropertyChangeEvent object describing the event source
2098         *        and the property that has changed.       *        and the property that has changed.
2099         */       */
2100        public void propertyChange(PropertyChangeEvent event)      public void propertyChange(PropertyChangeEvent event)
2101        {      {
2102        }      }
2103     }// PropertyChangeHandler    }// PropertyChangeHandler
2104      
2105     /**    /**
2106      * Listener on the TreeSelectionModel, resets the row selection if any of the     * Listener on the TreeSelectionModel, resets the row selection if any of the
2107      * properties of the model change.     * properties of the model change.
2108      */     */
2109     public class SelectionModelPropertyChangeHandler    public class SelectionModelPropertyChangeHandler
2110           implements PropertyChangeListener    implements PropertyChangeListener
2111     {    {
2112        
2113        /**      /**
2114         * Constructor       * Constructor
2115         */       */
2116        public SelectionModelPropertyChangeHandler()      public SelectionModelPropertyChangeHandler()
2117        {      {
2118        }      }
2119        
2120        /**      /**
2121         * This method gets called when a bound property is changed.       * This method gets called when a bound property is changed.
2122         *       *
2123         * @param event A PropertyChangeEvent object describing the event source       * @param event A PropertyChangeEvent object describing the event source
2124         *        and the property that has changed.       *        and the property that has changed.
2125         */       */
2126        public void propertyChange(PropertyChangeEvent event)      public void propertyChange(PropertyChangeEvent event)
2127        {      {
2128        }      }
2129     }// SelectionModelPropertyChangeHandler    }// SelectionModelPropertyChangeHandler
2130      
2131     /**    /**
2132      * ActionListener that invokes cancelEditing when action performed.     * ActionListener that invokes cancelEditing when action performed.
2133      */     */
2134     public class TreeCancelEditingAction    public class TreeCancelEditingAction
2135           extends AbstractAction    extends AbstractAction
2136     {    {
2137        
2138        /**      /**
2139         * Constructor       * Constructor
2140         */       */
2141        public TreeCancelEditingAction()      public TreeCancelEditingAction()
2142        {      {
2143        }      }
2144        
2145        /**      /**
2146         * Invoked when an action occurs.       * Invoked when an action occurs.
2147         *       *
2148         * @param e event that occured       * @param e event that occured
2149         */       */
2150        public void actionPerformed(ActionEvent e)      public void actionPerformed(ActionEvent e)
2151        {      {
2152        }      }
2153        
2154        /**      /**
2155         * Returns true if the action is enabled.       * Returns true if the action is enabled.
2156         *       *
2157         * @return true if the action is enabled, false otherwise       * @return true if the action is enabled, false otherwise
2158         */       */
2159        public boolean isEnabled()      public boolean isEnabled()
2160        {      {
2161           return false;        return false;
2162        }      }
2163     }// TreeCancelEditingAction    }// TreeCancelEditingAction
2164      
2165     /**    /**
2166      * Updates the TreeState in response to nodes expanding/collapsing.     * Updates the TreeState in response to nodes expanding/collapsing.
2167      */     */
2168     public class TreeExpansionHandler    public class TreeExpansionHandler
2169           implements TreeExpansionListener    implements TreeExpansionListener
2170     {    {
2171        
2172        /**      /**
2173         * Constructor       * Constructor
2174         */       */
2175        public TreeExpansionHandler()      public TreeExpansionHandler()
2176        {      {
2177        }      }
2178        
2179        /**      /**
2180         * Called whenever an item in the tree has been expanded.       * Called whenever an item in the tree has been expanded.
2181         *       *
2182         * @param event is the event that occured       * @param event is the event that occured
2183         */       */
2184        public void treeExpanded(TreeExpansionEvent event)      public void treeExpanded(TreeExpansionEvent event)
2185        {      {
2186           BasicTreeUI.this.tree.repaint();        BasicTreeUI.this.tree.repaint();
2187        }      }
2188        
2189        /**      /**
2190         * Called whenever an item in the tree has been collapsed.       * Called whenever an item in the tree has been collapsed.
2191         *       *
2192         * @param event is the event that occured       * @param event is the event that occured
2193         */       */
2194        public void treeCollapsed(TreeExpansionEvent event)      public void treeCollapsed(TreeExpansionEvent event)
2195        {      {
2196           BasicTreeUI.this.tree.repaint();        BasicTreeUI.this.tree.repaint();
2197        }      }
2198     }// TreeExpansionHandler    }// TreeExpansionHandler
2199      
2200     /**    /**
2201      * TreeHomeAction is used to handle end/home actions. Scrolls either the     * TreeHomeAction is used to handle end/home actions. Scrolls either the
2202      * first or last cell to be visible based on direction.     * first or last cell to be visible based on direction.
2203      */     */
2204     public class TreeHomeAction    public class TreeHomeAction
2205           extends AbstractAction    extends AbstractAction
2206     {    {
2207        
2208        /** direction is either home or end */      /** direction is either home or end */
2209        protected int direction;      protected int direction;
2210        
2211        /**      /**
2212         * Constructor       * Constructor
2213         *       *
2214         * @param direction - it is home or end       * @param direction - it is home or end
2215         * @param name is the name of the direction       * @param name is the name of the direction
2216         */       */
2217        public TreeHomeAction(int direction, String name)      public TreeHomeAction(int direction, String name)
2218        {      {
2219        }      }
2220        
2221        /**      /**
2222         * Invoked when an action occurs.       * Invoked when an action occurs.
2223         *       *
2224         * @param e is the event that occured       * @param e is the event that occured
2225         */       */
2226        public void actionPerformed(ActionEvent e)      public void actionPerformed(ActionEvent e)
2227        {      {
2228        }      }
2229        
2230        /**      /**
2231         * Returns true if the action is enabled.       * Returns true if the action is enabled.
2232         *       *
2233         * @return true if the action is enabled.       * @return true if the action is enabled.
2234         */       */
2235        public boolean isEnabled()      public boolean isEnabled()
2236        {      {
2237           return false;        return false;
2238        }      }
2239     }// TreeHomeAction    }// TreeHomeAction
2240      
2241     /**    /**
2242      * TreeIncrementAction is used to handle up/down actions. Selection is moved     * TreeIncrementAction is used to handle up/down actions. Selection is moved
2243      * up or down based on direction.     * up or down based on direction.
2244      */     */
2245     public class TreeIncrementAction    public class TreeIncrementAction
2246           extends AbstractAction    extends AbstractAction
2247     {    {
2248        
2249        /** Specifies the direction to adjust the selection by. */      /** Specifies the direction to adjust the selection by. */
2250        protected int direction;      protected int direction;
2251        
2252        /**      /**
2253         * Constructor       * Constructor
2254         *       *
2255         * @param direction up or down       * @param direction up or down
2256         * @param name is the name of the direction       * @param name is the name of the direction
2257         */       */
2258        public TreeIncrementAction(int direction, String name)      public TreeIncrementAction(int direction, String name)
2259        {      {
2260        }      }
2261        
2262        /**      /**
2263         * Invoked when an action occurs.       * Invoked when an action occurs.
2264         *       *
2265         * @param e is the event that occured       * @param e is the event that occured
2266         */       */
2267        public void actionPerformed(ActionEvent e)      public void actionPerformed(ActionEvent e)
2268        {      {
2269        }      }
2270        
2271        /**      /**
2272         * Returns true if the action is enabled.       * Returns true if the action is enabled.
2273         *       *
2274         * @return true if the action is enabled.       * @return true if the action is enabled.
2275         */       */
2276        public boolean isEnabled()      public boolean isEnabled()
2277        {      {
2278           return false;        return false;
2279        }      }
2280     }// TreeIncrementAction    }// TreeIncrementAction
2281      
2282     /**    /**
2283      * Forwards all TreeModel events to the TreeState.     * Forwards all TreeModel events to the TreeState.
2284      */     */
2285     public class TreeModelHandler    public class TreeModelHandler
2286           implements TreeModelListener    implements TreeModelListener
2287     {    {
2288        /**      /**
2289         * Constructor       * Constructor
2290         */       */
2291        public TreeModelHandler()      public TreeModelHandler()
2292        {      {
2293        }      }
2294        
2295        /**      /**
2296         * Invoked after a node (or a set of siblings) has changed in some way.       * Invoked after a node (or a set of siblings) has changed in some way.
2297         * The node(s) have not changed locations in the tree or altered their       * The node(s) have not changed locations in the tree or altered their
2298         * children arrays, but other attributes have changed and may affect       * children arrays, but other attributes have changed and may affect
2299         * presentation. Example: the name of a file has changed, but it is in the       * presentation. Example: the name of a file has changed, but it is in the
2300         * same location in the file system. To indicate the root has changed,       * same location in the file system. To indicate the root has changed,
2301         * childIndices and children will be null. Use e.getPath() to get the       * childIndices and children will be null. Use e.getPath() to get the
2302         * parent of the changed node(s). e.getChildIndices() returns the       * parent of the changed node(s). e.getChildIndices() returns the
2303         * index(es) of the changed node(s).       * index(es) of the changed node(s).
2304         *       *
2305         * @param e is the event that occured       * @param e is the event that occured
2306         */       */
2307        public void treeNodesChanged(TreeModelEvent e)      public void treeNodesChanged(TreeModelEvent e)
2308        {      {
2309        }      }
2310        
2311        /**      /**
2312         * Invoked after nodes have been inserted into the tree. Use e.getPath()       * Invoked after nodes have been inserted into the tree. Use e.getPath()
2313         * to get the parent of the new node(s). e.getChildIndices() returns the       * to get the parent of the new node(s). e.getChildIndices() returns the
2314         * index(es) of the new node(s) in ascending order.       * index(es) of the new node(s) in ascending order.
2315         *       *
2316         * @param e is the event that occured       * @param e is the event that occured
2317         */       */
2318        public void treeNodesInserted(TreeModelEvent e)      public void treeNodesInserted(TreeModelEvent e)
2319        {      {
2320        }      }
2321        
2322        /**      /**
2323         * Invoked after nodes have been removed from the tree. Note that if a       * Invoked after nodes have been removed from the tree. Note that if a
2324         * subtree is removed from the tree, this method may only be invoked once       * subtree is removed from the tree, this method may only be invoked once
2325         * for the root of the removed subtree, not once for each individual set       * for the root of the removed subtree, not once for each individual set
2326         * of siblings removed. Use e.getPath() to get the former parent of the       * of siblings removed. Use e.getPath() to get the former parent of the
2327         * deleted node(s). e.getChildIndices() returns, in ascending order, the       * deleted node(s). e.getChildIndices() returns, in ascending order, the
2328         * index(es) the node(s) had before being deleted.       * index(es) the node(s) had before being deleted.
2329         *       *
2330         * @param e is the event that occured       * @param e is the event that occured
2331         */       */
2332        public void treeNodesRemoved(TreeModelEvent e)      public void treeNodesRemoved(TreeModelEvent e)
2333        {      {
2334        }      }
2335        
2336        /**      /**
2337         * Invoked after the tree has drastically changed structure from a given       * Invoked after the tree has drastically changed structure from a given
2338         * node down. If the path returned by e.getPath() is of length one and the       * node down. If the path returned by e.getPath() is of length one and the
2339         * first element does not identify the current root node the first element       * first element does not identify the current root node the first element
2340         * should become the new root of the tree. Use e.getPath() to get the path       * should become the new root of the tree. Use e.getPath() to get the path
2341         * to the node. e.getChildIndices() returns null.       * to the node. e.getChildIndices() returns null.
2342         *       *
2343         * @param e is the event that occured       * @param e is the event that occured
2344         */       */
2345        public void treeStructureChanged(TreeModelEvent e)      public void treeStructureChanged(TreeModelEvent e)
2346        {      {
2347        }      }
2348     }// TreeModelHandler    }// TreeModelHandler
2349      
2350     /**    /**
2351      * TreePageAction handles page up and page down events.     * TreePageAction handles page up and page down events.
2352      */     */
2353     public class TreePageAction    public class TreePageAction
2354           extends AbstractAction    extends AbstractAction
2355     {    {
2356        /** Specifies the direction to adjust the selection by. */      /** Specifies the direction to adjust the selection by. */
2357        protected int direction;      protected int direction;
2358        
2359        /**      /**
2360         * Constructor       * Constructor
2361         *       *
2362         * @param direction up or down       * @param direction up or down
2363         * @param name is the name of the direction       * @param name is the name of the direction
2364         */       */
2365        public TreePageAction(int direction, String name)      public TreePageAction(int direction, String name)
2366        {      {
2367        }      }
2368        
2369        /**      /**
2370         * Invoked when an action occurs.       * Invoked when an action occurs.
2371         *       *
2372         * @param e is the event that occured       * @param e is the event that occured
2373         */       */
2374        public void actionPerformed(ActionEvent e)      public void actionPerformed(ActionEvent e)
2375        {      {
2376        }      }
2377        
2378        /**      /**
2379         * Returns true if the action is enabled.       * Returns true if the action is enabled.
2380         *       *
2381         * @return true if the action is enabled.       * @return true if the action is enabled.
2382         */       */
2383        public boolean isEnabled()      public boolean isEnabled()
2384        {      {
2385           return false;        return false;
2386        }      }
2387     }// TreePageAction    }// TreePageAction
2388      
2389     /**    /**
2390      * Listens for changes in the selection model and updates the display     * Listens for changes in the selection model and updates the display
2391      * accordingly.     * accordingly.
2392      */     */
2393     public class TreeSelectionHandler    public class TreeSelectionHandler
2394           implements TreeSelectionListener    implements TreeSelectionListener
2395     {    {
2396        /**      /**
2397         * Constructor       * Constructor
2398         */       */
2399        public TreeSelectionHandler()      public TreeSelectionHandler()
2400        {      {
2401        }      }
2402        
2403        /**      /**
2404         * Messaged when the selection changes in the tree we're displaying for.       * Messaged when the selection changes in the tree we're displaying for.
2405         * Stops editing, messages super and displays the changed paths.       * Stops editing, messages super and displays the changed paths.
2406         *       *
2407         * @param event the event that characterizes the change.       * @param event the event that characterizes the change.
2408         */       */
2409        public void valueChanged(TreeSelectionEvent event)      public void valueChanged(TreeSelectionEvent event)
2410        {      {
2411        }      }
2412     }// TreeSelectionHandler    }// TreeSelectionHandler
2413      
2414     /**    /**
2415      * For the first selected row expandedness will be toggled.     * For the first selected row expandedness will be toggled.
2416      */     */
2417     public class TreeToggleAction    public class TreeToggleAction
2418           extends AbstractAction    extends AbstractAction
2419     {    {
2420        /**      /**
2421         * Constructor       * Constructor
2422         *       *
2423         * @param name is the name of <code>Action</code> field       * @param name is the name of <code>Action</code> field
2424         */       */
2425        public TreeToggleAction(String name)      public TreeToggleAction(String name)
2426        {      {
2427        }      }
2428        
2429        /**      /**
2430         * Invoked when an action occurs.       * Invoked when an action occurs.
2431         *       *
2432         * @param e the event that occured       * @param e the event that occured
2433         */       */
2434        public void actionPerformed(ActionEvent e)      public void actionPerformed(ActionEvent e)
2435        {      {
2436        }      }
2437        
2438        /**      /**
2439         * Returns true if the action is enabled.       * Returns true if the action is enabled.
2440         *       *
2441         * @return true if the action is enabled, false otherwise       * @return true if the action is enabled, false otherwise
2442         */       */
2443        public boolean isEnabled()      public boolean isEnabled()
2444        {      {
2445           return false;        return false;
2446        }      }
2447     } // TreeToggleAction    } // TreeToggleAction
2448      
2449     /**    /**
2450      * TreeTraverseAction is the action used for left/right keys. Will toggle     * TreeTraverseAction is the action used for left/right keys. Will toggle
2451      * the expandedness of a node, as well as potentially incrementing the     * the expandedness of a node, as well as potentially incrementing the
2452      * selection.     * selection.
2453      */     */
2454     public class TreeTraverseAction    public class TreeTraverseAction
2455           extends AbstractAction    extends AbstractAction
2456     {    {
2457        /**      /**
2458         * Determines direction to traverse, 1 means expand, -1 means collapse.       * Determines direction to traverse, 1 means expand, -1 means collapse.
2459         */       */
2460        protected int direction;      protected int direction;
2461        
2462        /**      /**
2463         * Constructor       * Constructor
2464         *       *
2465         * @param direction to traverse       * @param direction to traverse
2466         * @param name is the name of the direction       * @param name is the name of the direction
2467         */       */
2468        public TreeTraverseAction(int direction, String name)      public TreeTraverseAction(int direction, String name)
2469        {      {
2470        }      }
2471        
2472        /**      /**
2473         * Invoked when an action occurs.       * Invoked when an action occurs.
2474         *       *
2475         * @param e the event that occured       * @param e the event that occured
2476         */       */
2477        public void actionPerformed(ActionEvent e)      public void actionPerformed(ActionEvent e)
2478        {      {
2479        }      }
2480        
2481        /**      /**
2482         * Returns true if the action is enabled.       * Returns true if the action is enabled.
2483         *       *
2484         * @return true if the action is enabled, false otherwise       * @return true if the action is enabled, false otherwise
2485         */       */
2486        public boolean isEnabled()      public boolean isEnabled()
2487        {      {
2488           return false;        return false;
2489        }      }
2490     } // TreeTraverseAction    } // TreeTraverseAction
2491      
2492     /**    /**
2493      * Returns the cell bounds for painting selected cells     * Returns the cell bounds for painting selected cells
2494      * Package private for use in inner classes.     * Package private for use in inner classes.
2495      *     *
2496      * @param x is the x location of the cell     * @param x is the x location of the cell
2497      * @param y is the y location of the cell     * @param y is the y location of the cell
2498      * @param cell is the Object to get the bounds for     * @param cell is the Object to get the bounds for
2499      *     *
2500      * @returns Rectangle that represents the cell bounds     * @returns Rectangle that represents the cell bounds
2501      */     */
2502     Rectangle getCellBounds(int x, int y, Object cell)    Rectangle getCellBounds(int x, int y, Object cell)
2503     {    {
2504        if (cell != null)      if (cell != null)
2505        {        {
2506           String s = cell.toString();          String s = cell.toString();
2507           Font f = tree.getFont();          Font f = tree.getFont();
2508           FontMetrics fm = tree.getToolkit().getFontMetrics(tree.getFont());          FontMetrics fm = tree.getToolkit().getFontMetrics(tree.getFont());
2509            
2510           if (s != null)          if (s != null)
2511              return new Rectangle(x, y, SwingUtilities.computeStringWidth(fm, s) + 4,            return new Rectangle(x, y, SwingUtilities.computeStringWidth(fm, s) + 4,
2512                    fm.getHeight());                                 fm.getHeight());
2513        }        }
2514        return new Rectangle(x, y, 0, 0);      return new Rectangle(x, y, 0, 0);
2515     }    }
2516        
2517     /**    /**
2518      * Retrieves the location of some node, recursively starting at from     * Retrieves the location of some node, recursively starting at from
2519      * some node.     * some node.
2520      * Package private for use in inner classes.     * Package private for use in inner classes.
2521      *     *
2522      * @param x is the starting x position, offset     * @param x is the starting x position, offset
2523      * @param y is the starting y position, offset     * @param y is the starting y position, offset
2524      * @param tree is the tree to traverse     * @param tree is the tree to traverse
2525      * @param mod is the TreeModel to use     * @param mod is the TreeModel to use
2526      * @param node is the node to get the location for     * @param node is the node to get the location for
2527      * @param startNode is the node to start searching from     * @param startNode is the node to start searching from
2528      *     *
2529      * @return Point - the location of node     * @return Point - the location of node
2530      */     */
2531     Point getCellLocation(int x, int y, JTree tree, TreeModel mod,    Point getCellLocation(int x, int y, JTree tree, TreeModel mod,
2532           Object node, Object startNode)                          Object node, Object startNode)
2533     {    {
2534        int rowHeight = getRowHeight();      int rowHeight = getRowHeight();
2535        if (startNode == null || startNode.equals(node))      if (startNode == null || startNode.equals(node))
2536        {        {
2537           if (!tree.isRootVisible() && tree.isExpanded(new TreePath(mod.getRoot())))          if (!tree.isRootVisible() && tree.isExpanded(new TreePath(mod.getRoot())))
2538              return new Point(x + ((((DefaultMutableTreeNode) node).getLevel())            return new Point(x + ((((DefaultMutableTreeNode) node).getLevel())
2539                    * rightChildIndent), y);                * rightChildIndent), y);
2540                    
2541           return new Point(x + ((((DefaultMutableTreeNode) node).getLevel() + 1)          return new Point(x + ((((DefaultMutableTreeNode) node).getLevel() + 1)
2542                 * rightChildIndent), y);              * rightChildIndent), y);
2543        }        }
2544        
2545        if (!mod.isLeaf(startNode)      if (!mod.isLeaf(startNode)
2546              && tree.isExpanded(new TreePath(          && tree.isExpanded(new TreePath(
2547                    ((DefaultMutableTreeNode) startNode).getPath())))                                          ((DefaultMutableTreeNode) startNode).getPath())))
2548        {        {
2549           Object child = mod.getChild(startNode, 0);          Object child = mod.getChild(startNode, 0);
2550           if (child != null)          if (child != null)
2551              return getCellLocation(x, y + rowHeight, tree, mod,            return getCellLocation(x, y + rowHeight, tree, mod,
2552                    node, child);                                   node, child);
2553        }        }
2554              
2555           return getCellLocation(x, y + rowHeight, tree, mod, node,      return getCellLocation(x, y + rowHeight, tree, mod, node,
2556                 getNextVisibleNode((DefaultMutableTreeNode) startNode));                             getNextVisibleNode((DefaultMutableTreeNode) startNode));
2557     }    }
2558        
2559     /**    /**
2560      * Paints a node in the tree Package private for use in inner classes.     * Paints a node in the tree Package private for use in inner classes.
2561      *     *
2562      * @param g the Graphics context in which to paint     * @param g the Graphics context in which to paint
2563      * @param x the x location of the node     * @param x the x location of the node
2564      * @param y the y location of the node     * @param y the y location of the node
2565      * @param tree the tree to draw on     * @param tree the tree to draw on
2566      * @param node the object to draw     * @param node the object to draw
2567      */     */
2568     void paintNode(Graphics g, int x, int y, JTree tree, Object node,    void paintNode(Graphics g, int x, int y, JTree tree, Object node,
2569           boolean isLeaf)                   boolean isLeaf)
2570     {    {
2571        TreePath curr = new TreePath(((DefaultMutableTreeNode) node).getPath());      TreePath curr = new TreePath(((DefaultMutableTreeNode) node).getPath());
2572        boolean selected = tree.isPathSelected(curr);      boolean selected = tree.isPathSelected(curr);
2573        boolean expanded = false;      boolean expanded = false;
2574        boolean hasIcons = false;      boolean hasIcons = false;
2575              
2576        if (tree.isVisible(curr))      if (tree.isVisible(curr))
2577        {        {
2578           DefaultTreeCellRenderer dtcr = (DefaultTreeCellRenderer) tree          DefaultTreeCellRenderer dtcr = (DefaultTreeCellRenderer) tree
2579                 .getCellRenderer();          .getCellRenderer();
2580            
2581           if (!isLeaf)          if (!isLeaf)
2582              expanded = tree.isExpanded(curr);            expanded = tree.isExpanded(curr);
2583                    
2584           Icon icon = null;          Icon icon = null;
2585           if (!isLeaf && expanded)          if (!isLeaf && expanded)
2586              icon = dtcr.getOpenIcon();            icon = dtcr.getOpenIcon();
2587           else if (!isLeaf && !expanded)          else if (!isLeaf && !expanded)
2588              icon = dtcr.getClosedIcon();            icon = dtcr.getClosedIcon();
2589           else          else
2590              icon = dtcr.getLeafIcon();            icon = dtcr.getLeafIcon();
2591                    
2592           if (icon.getIconHeight() > -1 && icon.getIconWidth() > -1)          if (icon.getIconHeight() > -1 && icon.getIconWidth() > -1)
2593              hasIcons = true;            hasIcons = true;
2594                    
2595           Component c = dtcr.getTreeCellRendererComponent(tree, node, selected,          Component c = dtcr.getTreeCellRendererComponent(tree, node, selected,
2596                 expanded, isLeaf, 0, false);                                                          expanded, isLeaf, 0, false);
2597            
2598           if (hasIcons)          if (hasIcons)
2599           {            {
2600              if (selected)              if (selected)
2601              {                {
2602                 Rectangle cell = getPathBounds(tree, curr);                  Rectangle cell = getPathBounds(tree, curr);
2603                 g.setColor(dtcr.getBackgroundSelectionColor());                  g.setColor(dtcr.getBackgroundSelectionColor());
2604                 g.fillRect(cell.x + icon.getIconWidth()/2, cell.y, cell.width,                  g.fillRect(cell.x + icon.getIconWidth()/2, cell.y, cell.width,
2605                       cell.height);                             cell.height);
2606                                  
2607                 if (curr.equals(tree.getLeadSelectionPath()))                  if (curr.equals(tree.getLeadSelectionPath()))
2608                 {                    {
2609                    g.setColor(UIManager.getLookAndFeelDefaults().getColor(                      g.setColor(UIManager.getLookAndFeelDefaults().getColor(
2610                          "Tree.selectionBorderColor"));                      "Tree.selectionBorderColor"));
2611                    g.drawRect(cell.x + icon.getIconWidth()/2, cell.y,                      g.drawRect(cell.x + icon.getIconWidth()/2, cell.y,
2612                          cell.width, cell.height);                                 cell.width, cell.height);
2613                 }                    }
2614              }                }
2615                  
2616              g.translate(x, y);              g.translate(x, y);
2617              c.paint(g);              c.paint(g);
2618              g.translate(-x, -y);              g.translate(-x, -y);
2619           }            }
2620           else          else
2621              rendererPane.paintComponent(g, c, c.getParent(),            rendererPane.paintComponent(g, c, c.getParent(),
2622                    getCellBounds(x, y, node));                                        getCellBounds(x, y, node));
2623        }        }
2624     }    }
2625      
2626     /**    /**
2627      * Recursively paints all elements of the tree Package private for use in     * Recursively paints all elements of the tree Package private for use in
2628      * inner classes.     * inner classes.
2629      *     *
2630      * @param g the Graphics context in which to paint     * @param g the Graphics context in which to paint
2631      * @param indentation of the current object     * @param indentation of the current object
2632      * @param descent is the number of elements drawn     * @param descent is the number of elements drawn
2633      * @param childNumber is the index of the current child in the tree     * @param childNumber is the index of the current child in the tree
2634      * @param depth is the depth of the current object in the tree     * @param depth is the depth of the current object in the tree
2635      * @param tree is the tree to draw to     * @param tree is the tree to draw to
2636      * @param mod is the TreeModel we are using to draw     * @param mod is the TreeModel we are using to draw
2637      * @param curr is the current object to draw     * @param curr is the current object to draw
2638      *     *
2639      * @return int - current descent of the tree     * @return int - current descent of the tree
2640      */     */
2641     int paintRecursive(Graphics g, int indentation, int descent,    int paintRecursive(Graphics g, int indentation, int descent,
2642           int childNumber, int depth, JTree tree, TreeModel mod, Object curr)                       int childNumber, int depth, JTree tree, TreeModel mod, Object curr)
2643     {    {
2644        Rectangle clip = g.getClipBounds();      Rectangle clip = g.getClipBounds();
2645        if (indentation > clip.x + clip.width + rightChildIndent      if (indentation > clip.x + clip.width + rightChildIndent
2646              || descent > clip.y + clip.height + getRowHeight())          || descent > clip.y + clip.height + getRowHeight())
2647           return descent;        return descent;
2648        
2649        int halfHeight = getRowHeight() / 2;      int halfHeight = getRowHeight() / 2;
2650        int halfWidth = rightChildIndent / 2;      int halfWidth = rightChildIndent / 2;
2651        int y0 = descent + halfHeight;      int y0 = descent + halfHeight;
2652        int heightOfLine = descent + halfHeight;      int heightOfLine = descent + halfHeight;
2653        boolean isRootVisible = tree.isRootVisible();      boolean isRootVisible = tree.isRootVisible();
2654              
2655        if (mod.isLeaf(curr))      if (mod.isLeaf(curr))
2656        {        {
2657           paintNode(g, indentation + 4, descent, tree, curr, true);          paintNode(g, indentation + 4, descent, tree, curr, true);
2658           descent += getRowHeight();          descent += getRowHeight();
2659        }        }
2660        else      else
2661        {        {
2662           if (depth > 0 || isRootVisible)          if (depth > 0 || isRootVisible)
2663           {            {
2664              paintNode(g, indentation + 4, descent, tree, curr, false);              paintNode(g, indentation + 4, descent, tree, curr, false);
2665              descent += getRowHeight();              descent += getRowHeight();
2666              y0 += halfHeight;              y0 += halfHeight;
2667           }            }
2668            
2669           int max = mod.getChildCount(curr);          int max = mod.getChildCount(curr);
2670           if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) curr)          if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) curr)
2671                 .getPath())))                                           .getPath())))
2672           {            {
2673              for (int i = 0; i < max; ++i)              for (int i = 0; i < max; ++i)
2674              {                {
2675                 int indent = indentation + rightChildIndent;                  int indent = indentation + rightChildIndent;
2676                 if (!isRootVisible && depth == 0)                  if (!isRootVisible && depth == 0)
2677                    indent = 0;                    indent = 0;
2678                 else if ((!isRootVisible && !curr.equals(mod.getRoot())) ||                  else if ((!isRootVisible && !curr.equals(mod.getRoot())) ||
2679                       isRootVisible)                      isRootVisible)
2680                 {                    {
2681                    g.setColor(getHashColor());                      g.setColor(getHashColor());
2682                    heightOfLine = descent + halfHeight;                      heightOfLine = descent + halfHeight;
2683                    g.drawLine(indentation + halfWidth, heightOfLine, indentation                      g.drawLine(indentation + halfWidth, heightOfLine, indentation
2684                          + rightChildIndent, heightOfLine);                                 + rightChildIndent, heightOfLine);
2685                 }                    }
2686                                      
2687                 descent = paintRecursive(g, indent,                  descent = paintRecursive(g, indent,
2688                       descent, i, depth + 1, tree, mod, mod.getChild(curr, i));                                           descent, i, depth + 1, tree, mod, mod.getChild(curr, i));
2689              }                }
2690           }            }
2691        }        }
2692        
2693        if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) curr)      if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) curr)
2694              .getPath())))                                       .getPath())))
2695           if (y0 != heightOfLine)        if (y0 != heightOfLine)
2696           {          {
2697              g.setColor(getHashColor());            g.setColor(getHashColor());
2698              g.drawLine(indentation + halfWidth, y0, indentation + halfWidth,            g.drawLine(indentation + halfWidth, y0, indentation + halfWidth,
2699                    heightOfLine);                       heightOfLine);
2700           }          }
2701              
2702        return descent;
2703      }
2704      
2705      /**
2706       * Recursively paints all the control icons on the tree.
2707       * Package private for use in inner classes.
2708       *
2709       * @param g the Graphics context in which to paint
2710       * @param indentation of the current object
2711       * @param descent is the number of elements drawn
2712       * @param childNumber is the index of the current child in the tree
2713       * @param depth is the depth of the current object in the tree
2714       * @param tree is the tree to draw to
2715       * @param mod is the TreeModel we are using to draw
2716       * @param curr is the current object to draw
2717       *
2718       * @return int - current descent of the tree
2719       */
2720      int paintControlIcons(Graphics g, int indentation, int descent,
2721                            int childNumber, int depth, JTree tree, TreeModel mod, Object node)
2722      {
2723        int h = descent;
2724        int rowHeight = getRowHeight();
2725        Icon ei = UIManager.getLookAndFeelDefaults()
2726        .getIcon("Tree.expandedIcon");
2727        Icon ci = UIManager.getLookAndFeelDefaults()
2728        .getIcon("Tree.collapsedIcon");
2729        Rectangle clip = g.getClipBounds();
2730        if (indentation > clip.x + clip.width + rightChildIndent
2731            || descent > clip.y + clip.height + getRowHeight())
2732        return descent;        return descent;
2733     }      
2734          if (mod.isLeaf(node))
2735     /**        descent += rowHeight;
2736      * Recursively paints all the control icons on the tree.      else
2737      * Package private for use in inner classes.        {
2738      *          if (depth > 0 || tree.isRootVisible())
2739      * @param g the Graphics context in which to paint            descent += rowHeight;
2740      * @param indentation of the current object          
2741      * @param descent is the number of elements drawn          int max = mod.getChildCount(node);
2742      * @param childNumber is the index of the current child in the tree          if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) node)
2743      * @param depth is the depth of the current object in the tree                                           .getPath())))
2744      * @param tree is the tree to draw to            {
     * @param mod is the TreeModel we are using to draw  
     * @param curr is the current object to draw  
     *  
     * @return int - current descent of the tree  
     */  
    int paintControlIcons(Graphics g, int indentation, int descent,  
          int childNumber, int depth, JTree tree, TreeModel mod, Object node)  
    {  
       int h = descent;  
       int rowHeight = getRowHeight();  
       Icon ei = UIManager.getLookAndFeelDefaults()  
          .getIcon("Tree.expandedIcon");  
       Icon ci = UIManager.getLookAndFeelDefaults()  
          .getIcon("Tree.collapsedIcon");  
       Rectangle clip = g.getClipBounds();  
       if (indentation > clip.x + clip.width + rightChildIndent  
             || descent > clip.y + clip.height + getRowHeight())  
          return descent;  
         
       if (mod.isLeaf(node))  
          descent += rowHeight;  
       else  
       {  
          if (depth > 0 || tree.isRootVisible())  
             descent += rowHeight;  
           
          int max = mod.getChildCount(node);  
          if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) node)  
                .getPath())))  
          {  
2745              if (!node.equals(mod.getRoot()))              if (!node.equals(mod.getRoot()))
2746                 ei.paintIcon(tree, g, indentation - rightChildIndent - 3, h);                ei.paintIcon(tree, g, indentation - rightChildIndent - 3, h);
2747                            
2748              for (int i = 0; i < max; ++i)              for (int i = 0; i < max; ++i)
2749              {                {
2750                 int indent = indentation + rightChildIndent;                  int indent = indentation + rightChildIndent;
2751                 if (depth == 0 && !tree.isRootVisible())                  if (depth == 0 && !tree.isRootVisible())
2752                    indent = -1;                    indent = -1;
2753                                  
2754                 descent = paintControlIcons(g, indent,                  descent = paintControlIcons(g, indent,
2755                       descent, i, depth + 1, tree, mod, mod.getChild(node, i));                                              descent, i, depth + 1, tree, mod, mod.getChild(node, i));
2756              }                }
2757           }            }
2758           else if (!node.equals(mod.getRoot()))          else if (!node.equals(mod.getRoot()))
2759              ci.paintIcon(tree, g, indentation - rightChildIndent - 3,            ci.paintIcon(tree, g, indentation - rightChildIndent - 3,
2760                    descent - getRowHeight());                         descent - getRowHeight());
2761        }        }
2762              
2763        return descent;      return descent;
2764     }    }
2765        
2766     /**    /**
2767      * Returns true if the LookAndFeel implements the control icons     * Returns true if the LookAndFeel implements the control icons
2768      * Package private for use in inner classes.     * Package private for use in inner classes.
2769      *     *
2770      * @return true if control icons are visible     * @return true if control icons are visible
2771      */     */
2772     boolean hasControlIcons()    boolean hasControlIcons()
2773     {    {
2774        if (UIManager.getLookAndFeelDefaults().      if (UIManager.getLookAndFeelDefaults().
2775              getIcon("Tree.expandedIcon") == null ||          getIcon("Tree.expandedIcon") == null ||
2776                    UIManager.getLookAndFeelDefaults().          UIManager.getLookAndFeelDefaults().
2777                       getIcon("Tree.collapsedIcon") == null)          getIcon("Tree.collapsedIcon") == null)
2778           return false;        return false;
2779        return true;      return true;
2780     }    }
2781        
2782     /**    /**
2783      * Get next visible node in the tree.     * Get next visible node in the tree.
2784      * Package private for use in inner classes.     * Package private for use in inner classes.
2785      *     *
2786      * @param the current node     * @param the current node
2787      * @return the next visible node in the JTree. Return null if there are no     * @return the next visible node in the JTree. Return null if there are no
2788      *         more.     *         more.
2789      */     */
2790     DefaultMutableTreeNode getNextVisibleNode(DefaultMutableTreeNode node)    DefaultMutableTreeNode getNextVisibleNode(DefaultMutableTreeNode node)
2791     {    {
2792        DefaultMutableTreeNode next = null;      DefaultMutableTreeNode next = null;
2793        TreePath current = null;      TreePath current = null;
2794        
2795        if (node != null)      if (node != null)
2796           next = node.getNextNode();        next = node.getNextNode();
2797        
2798        if (next != null)      if (next != null)
2799        {        {
2800           current = new TreePath(next.getPath());          current = new TreePath(next.getPath());
2801           if (tree.isVisible(current))          if (tree.isVisible(current))
2802              return next;            return next;
2803            
2804           while (next != null && !tree.isVisible(current))          while (next != null && !tree.isVisible(current))
2805           {            {
2806              next = next.getNextNode();              next = next.getNextNode();
2807                
2808              if (next != null)              if (next != null)
2809                 current = new TreePath(next.getPath());                current = new TreePath(next.getPath());
2810           }            }
2811        }        }
2812        return next;      return next;
2813     }    }
2814      
2815     /**    /**
2816      * Get previous visible node in the tree.     * Get previous visible node in the tree.
2817      * Package private for use in inner classes.     * Package private for use in inner classes.
2818      *     *
2819      * @param the current node     * @param the current node
2820      * @return the next visible node in the JTree. Return null if there are no     * @return the next visible node in the JTree. Return null if there are no
2821      *         more.     *         more.
2822      */     */
2823     DefaultMutableTreeNode getPreviousVisibleNode    DefaultMutableTreeNode getPreviousVisibleNode
2824                                               (DefaultMutableTreeNode node)    (DefaultMutableTreeNode node)
2825     {    {
2826        DefaultMutableTreeNode prev = null;      DefaultMutableTreeNode prev = null;
2827        TreePath current = null;      TreePath current = null;
2828        
2829        if (node != null)      if (node != null)
2830           prev = node.getPreviousNode();        prev = node.getPreviousNode();
2831        
2832        if (prev != null)      if (prev != null)
2833        {        {
2834           current = new TreePath(prev.getPath());          current = new TreePath(prev.getPath());
2835           if (tree.isVisible(current))          if (tree.isVisible(current))
2836              return prev;            return prev;
2837            
2838           while (prev != null && !tree.isVisible(current))          while (prev != null && !tree.isVisible(current))
2839           {            {
2840              prev = prev.getPreviousNode();              prev = prev.getPreviousNode();
2841                
2842              if (prev != null)              if (prev != null)
2843                 current = new TreePath(prev.getPath());                current = new TreePath(prev.getPath());
2844           }            }
2845        }        }
2846        return prev;      return prev;
2847     }    }
2848        
2849     /**    /**
2850      * Selects the specified path in the tree depending on modes.     * Selects the specified path in the tree depending on modes.
2851      * Package private for use in inner classes.     * Package private for use in inner classes.
2852      *     *
2853      * @param tree is the tree we are selecting the path in     * @param tree is the tree we are selecting the path in
2854      * @param path is the path we are selecting     * @param path is the path we are selecting
2855      */     */
2856     void selectPath(JTree tree, TreePath path)    void selectPath(JTree tree, TreePath path)
2857     {    {
2858        if (path != null)      if (path != null)
2859        {        {
2860           if (tree.isPathSelected(path))          if (tree.isPathSelected(path))
2861              tree.removeSelectionPath(path);            tree.removeSelectionPath(path);
2862           else if (tree.getSelectionModel().getSelectionMode()          else if (tree.getSelectionModel().getSelectionMode()
2863                 == TreeSelectionModel.SINGLE_TREE_SELECTION)              == TreeSelectionModel.SINGLE_TREE_SELECTION)
2864           {            {
2865              tree.getSelectionModel().clearSelection();              tree.getSelectionModel().clearSelection();
2866              tree.addSelectionPath(path);              tree.addSelectionPath(path);
2867              tree.setLeadSelectionPath(path);              tree.setLeadSelectionPath(path);
2868           }            }
2869           else if (tree.getSelectionModel().getSelectionMode()          else if (tree.getSelectionModel().getSelectionMode()
2870                 == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION)              == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION)
2871           {            {
2872              // TODO              // TODO
2873           }            }
2874           else          else
2875           {            {
2876              tree.getSelectionModel().setSelectionMode(              tree.getSelectionModel().setSelectionMode(
2877                    TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);                                                        TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
2878              tree.addSelectionPath(path);              tree.addSelectionPath(path);
2879              tree.setLeadSelectionPath(path);              tree.setLeadSelectionPath(path);
2880           }            }
2881        }        }
2882     }    }
2883  } // BasicTreeUI  } // BasicTreeUI

Legend:
Removed from v.1.49  
changed lines
  Added in v.1.50

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