/[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.9 by mkoch, Wed Dec 29 11:15:02 2004 UTC revision 1.10 by langel, Wed Jun 29 13:20:01 2005 UTC
# Line 1  Line 1 
1  /* BasicTreeUI.java --  /* BasicTreeUI.java --
2     Copyright (C) 2002, 2003, 2004  Free Software Foundation, Inc.  Copyright (C) 2002, 2004  Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 35  this exception to your version of the li Line 35  this exception to your version of the li
35  obligated to do so.  If you do not wish to do so, delete this  obligated to do so.  If you do not wish to do so, delete this
36  exception statement from your version. */  exception statement from your version. */
37    
   
38  package javax.swing.plaf.basic;  package javax.swing.plaf.basic;
39    
40  import java.awt.Color;  import java.awt.Color;
41  import java.awt.Component;  import java.awt.Component;
42  import java.awt.Dimension;  import java.awt.Dimension;
43  import java.awt.Graphics;  import java.awt.Graphics;
44    import java.awt.Point;
45  import java.awt.Rectangle;  import java.awt.Rectangle;
46    import java.awt.event.ActionEvent;
47    import java.awt.event.ActionListener;
48    import java.awt.event.ComponentAdapter;
49    import java.awt.event.ComponentEvent;
50    import java.awt.event.ComponentListener;
51    import java.awt.event.FocusEvent;
52    import java.awt.event.FocusListener;
53    import java.awt.event.KeyAdapter;
54    import java.awt.event.KeyEvent;
55    import java.awt.event.KeyListener;
56    import java.awt.event.MouseAdapter;
57    import java.awt.event.MouseEvent;
58    import java.awt.event.MouseListener;
59    import java.awt.event.MouseMotionListener;
60    
61    import java.beans.PropertyChangeEvent;
62    import java.beans.PropertyChangeListener;
63    
64    import javax.swing.AbstractAction;
65    import javax.swing.Action;
66    import javax.swing.CellRendererPane;
67    import javax.swing.Icon;
68  import javax.swing.JComponent;  import javax.swing.JComponent;
69    import javax.swing.JScrollBar;
70    import javax.swing.JScrollPane;
71  import javax.swing.JTree;  import javax.swing.JTree;
72    import javax.swing.Timer;
73  import javax.swing.UIDefaults;  import javax.swing.UIDefaults;
74  import javax.swing.UIManager;  import javax.swing.UIManager;
75    import javax.swing.event.CellEditorListener;
76    import javax.swing.event.ChangeEvent;
77    import javax.swing.event.MouseInputListener;
78    import javax.swing.event.TreeExpansionEvent;
79    import javax.swing.event.TreeExpansionListener;
80    import javax.swing.event.TreeModelEvent;
81    import javax.swing.event.TreeModelListener;
82    import javax.swing.event.TreeSelectionEvent;
83    import javax.swing.event.TreeSelectionListener;
84  import javax.swing.plaf.ComponentUI;  import javax.swing.plaf.ComponentUI;
85  import javax.swing.plaf.TreeUI;  import javax.swing.plaf.TreeUI;
86    import javax.swing.tree.AbstractLayoutCache;
87    import javax.swing.tree.FixedHeightLayoutCache;
88    import javax.swing.tree.DefaultMutableTreeNode;
89    import javax.swing.tree.DefaultTreeCellEditor;
90    import javax.swing.tree.DefaultTreeCellRenderer;
91    import javax.swing.tree.TreeCellEditor;
92    import javax.swing.tree.TreeCellRenderer;
93    import javax.swing.tree.TreeSelectionModel;
94  import javax.swing.tree.TreeModel;  import javax.swing.tree.TreeModel;
95    import javax.swing.tree.TreeNode;
96  import javax.swing.tree.TreePath;  import javax.swing.tree.TreePath;
97    
98    import java.util.Enumeration;
99    import java.util.Hashtable;
100    
101  /**  /**
102   * A delegate providing the user interface for <code>JTree</code>   * A delegate providing the user interface for <code>JTree</code> according to
103   * according to the Basic look and feel. The current implementation   * the Basic look and feel.
104   * of GNU Classpath does really work; it is just a stub that allows   *
  * compiling the code.  
  *  
105   * @see javax.swing.JTree   * @see javax.swing.JTree
  *  
106   * @author Sascha Brawer (brawer@dandelis.ch)   * @author Sascha Brawer (brawer@dandelis.ch)
107     * @author Lillian Angel (langel@redhat.com)
108   */   */
109  public class BasicTreeUI  public class BasicTreeUI
110    extends TreeUI                  extends TreeUI
111  {  {
112    
113    /**          /** Collapse Icon for the tree. */
114     * Determines the geometric extent of the label that is          protected transient Icon collapsedIcon;
115     * drawn for a path.  
116     *          /** Expanded Icon for the tree. */
117     * @param tree the <code>JTree</code> for which this delegate          protected transient Icon expandedIcon;
118     *        object provides the user interface.  
119     *          /** Distance between left margin and where vertical dashes will be drawn. */
120     * @param path the path whose label extent is requested.          protected int leftChildIndent;
121     *  
122     * @return a rectangle enclosing the label, or <code>null</code>          /**
123     *         if <code>path</code> contains invalid nodes.           * Distance between leftChildIndent and where cell contents will be drawn.
124     */           */
125    public Rectangle getPathBounds(JTree tree, TreePath path)          protected int rightChildIndent;
126    {  
127      return null;   // FIXME: not implemented          /**
128    }           * Total fistance that will be indented. The sum of leftChildIndent and
129             * rightChildIndent .
130             */
131    /**          protected int totalChildIndent;
132     * Creates a <code>TreePath</code> for the specified row.  
133     *          /** Minimum preferred size. */
134     * @param tree the <code>JTree</code> for which this delegate          protected Dimension preferredMinsize;
135     *        object provides the user interface.  
136     *          /** Index of the row that was last selected. */
137     * @param row the index of the row, which should be a number          protected int lastSelectedRow;
138     *        in the range <code>[0, getRowCount(tree) - 1]</code>.  
139     *          /** Component that we're going to be drawing onto. */
140     * @return a <code>TreePath</code> for the specified row, or          protected JTree tree;
141     *         <code>null</code> if <code>row</code> is outside  
142     *         the valid range.          /** Renderer that is being used to do the actual cell drawing. */
143     */          protected transient TreeCellRenderer currentCellRenderer;
144    public TreePath getPathForRow(JTree tree, int row)  
145    {          /**
146      return null;  // FIXME: not implemented           * Set to true if the renderer that is currently in the tree was created by
147    }           * this instance.
148             */
149            protected boolean createdRenderer;
150    /**  
151     * Determines in which row a <code>TreePath</code> is currently          /** Editor for the tree. */
152     * being displayed.          protected transient TreeCellEditor cellEditor;
153     *  
154     * @param tree the <code>JTree</code> for which this delegate          /**
155     *        object provides the user interface.           * Set to true if editor that is currently in the tree was created by this
156     *           * instance.
157     * @param path the path for which the caller wants to know           */
158     *        in which row it is being displayed.          protected boolean createdCellEditor;
159     *  
160     * @return a number in the range <code>[0, getRowCount(tree)          /**
161     *         - 1]</code> if the path is currently on display;           * Set to false when editing and shouldSelectCall() returns true meaning the
162     *         <code>-1</code> if the path is not shown to the           * node should be selected before editing, used in completeEditing.
163     *        user.           */
164     */          protected boolean stopEditingInCompleteEditing;
165    public int getRowForPath(JTree tree, TreePath path)  
166    {          /** Used to paint the TreeCellRenderer. */
167      return -1;  // FIXME: not implemented          protected CellRendererPane rendererPane;
168    }  
169            /** Size needed to completely display all the nodes. */
170            protected Dimension preferredSize;
171    /**  
172     * Counts how many rows are currently displayed.          /** Is the preferredSize valid? */
173     *          protected boolean validCachedPreferredSize;
174     * @param tree the <code>JTree</code> for which this delegate  
175     *        object provides the user interface.          /** Object responsible for handling sizing and expanded issues. */
176     *          protected AbstractLayoutCache treeState;
177     * @return the number of visible rows.  
178     */          /** Used for minimizing the drawing of vertical lines. */
179    public int getRowCount(JTree tree)          protected Hashtable drawingCache;
180    {  
181      return 0;  // FIXME: not implemented          /**
182    }           * True if doing optimizations for a largeModel. Subclasses that don't
183             * support this may wish to override createLayoutCache to not return a
184             * FixedHeightLayoutCache instance.
185    /**           */
186     * Finds the path that is closest to the specified position.          protected boolean largeModel;
187     *  
188     * <p><img src="../doc-files/TreeUI-1.png" width="300" height="250"          /** Responsible for telling the TreeState the size needed for a node. */
189     * alt="[A screen shot of a JTree]" />          protected AbstractLayoutCache.NodeDimensions nodeDimensions;
190     *  
191     * <p>As shown by the above illustration, the bounds of the          /** Used to determine what to display. */
192     * closest path do not necessarily need to contain the passed          protected TreeModel treeModel;
193     * location.  
194     *          /** Model maintaining the selection. */
195     * @param tree the <code>JTree</code> for which this delegate          protected TreeSelectionModel treeSelectionModel;
196     *        object provides the user interface.  
197     *          /**
198     * @param x the horizontal location, relative to the origin           * How much the depth should be offset to properly calculate x locations.
199     *        of <code>tree</code>.           * This is based on whether or not the root is visible, and if the root
200     *           * handles are visible.
201     * @param y the vertical location, relative to the origin           */
202     *        of <code>tree</code>.          protected int depthOffset;
203     *  
204     * @return the closest path, or <code>null</code> if the          /**
205     *         tree is currenlty not displaying any paths at all.           * When editing, this will be the Component that is doing the actual
206     */           * editing.
207    public TreePath getClosestPathForLocation(JTree tree,           */
208                                              int x, int y)          protected Component editingComponent;
209    {  
210      return null;  // FIXME: not implemented          /** Path that is being edited. */
211    }          protected TreePath editingPath;
212    
213            /**
214    /**           * Row that is being edited. Should only be referenced if editingComponent
215     * Determines whether the user is currently editing a tree cell.           * is null.
216     *           */
217     * @param tree the <code>JTree</code> for which this delegate          protected int editingRow;
218     *        object provides the user interface.  
219     *          /** Set to true if the editor has a different size than the renderer. */
220     * @see #getEditingPath          protected boolean editorHasDifferentSize;
221     */  
222    public boolean isEditing(JTree tree)          /** Listeners */
223    {          private PropertyChangeListener propertyChangeListener;
224      return false;  // FIXME: not implemented  
225    }          private FocusListener focusListener;
226    
227            private TreeSelectionListener treeSelectionListener;
228    /**  
229     * Stops editing a tree cell, committing the entered value into the          private MouseInputListener mouseInputListener;
230     * tree&#x2019;s model. If no editing session is active, or if the  
231     * active editor does not agree to stopping, nothing happens.  In          private KeyListener keyListener;
232     * some look and feels, this action happens when the user has  
233     * pressed the enter key.          private PropertyChangeListener selectionModelPropertyChangeListener;
234     *  
235     * @param tree the <code>JTree</code> for which this delegate          private ComponentListener componentListener;
236     *        object provides the user interface.  
237     *          private CellEditorListener cellEditorListener;
238     * @return <code>false</code> if the editing still goes on because  
239     *         the cell editor has objected to stopping the session;          private TreeExpansionListener treeExpansionListener;
240     *         <code>true</code> if editing has been stopped.  
241     */          private TreeModelListener treeModelListener;
242    public boolean stopEditing(JTree tree)  
243    {          /**
244      return true;  // FIXME: not implemented           * Creates a new BasicTreeUI object.
245    }           */
246            public BasicTreeUI()
247    /**          {
248     * Cancels editing a tree cell, discarding any entered value.                  drawingCache = new Hashtable();
249     * If no editing session is active, nothing happens. The cell                  cellEditor = createDefaultCellEditor();
250     * editor is not given an opportunity to veto the canceling.                  currentCellRenderer = createDefaultCellRenderer();
251     * In some look and feels, this action happens when the user has                  nodeDimensions = createNodeDimensions();
252     * pressed the escape key.                  rendererPane = createCellRendererPane();
253     *                  configureLayoutCache();
254     * @param tree the <code>JTree</code> for which this delegate  
255     *        object provides the user interface.                  propertyChangeListener = createPropertyChangeListener();
256     */                  focusListener = createFocusListener();
257    public void cancelEditing(JTree tree)                  treeSelectionListener = createTreeSelectionListener();
258    {                  mouseInputListener = new MouseInputHandler(null, null, null);
259      // FIXME: not implemented                  keyListener = createKeyListener();
260    }                  selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener();
261                    componentListener = createComponentListener();
262                    cellEditorListener = createCellEditorListener();
263    /**                  treeExpansionListener = createTreeExpansionListener();
264     * Starts a session to edit a tree cell. If the cell editor                  treeModelListener = createTreeModelListener();
265     * rejects editing the cell, it will just be selected.  
266     *                  createdRenderer = true;
267     * @param tree the <code>JTree</code> for which this delegate                  createdCellEditor = true;
268     *        object provides the user interface.                  editingRow = -1;
269     *                  lastSelectedRow = -1;
270     * @param path the cell to edit.          }
271     */  
272    public void startEditingAtPath(JTree tree, TreePath path)          /**
273    {           * Returns an instance of the UI delegate for the specified component.
274      // FIXME: not implemented           *
275    }           * @param c the <code>JComponent</code> for which we need a UI delegate
276             *        for.
277             * @return the <code>ComponentUI</code> for c.
278    /**           */
279     * Retrieves the tree cell that is currently being edited.          public static ComponentUI createUI(JComponent c)
280     *          {
281     * @return the currently edited path, or <code>null</code>                  return new BasicTreeUI();
282     *         if no editing session is currently active.          }
283     */  
284    public TreePath getEditingPath(JTree tree)          /**
285    {           * Returns the Hash color.
286      return null;  // FIXME: not implemented           *
287    }           * @return the <code>Color</code> of the Hash.
288             */
289    public static ComponentUI createUI(JComponent c)          protected Color getHashColor()
290    {          {
291      return new BasicTreeUI();                  return UIManager.getLookAndFeelDefaults().getColor("Tree.hash");
292    }          }
293    
294    int rightChildIndent;          /**
295    int leftChildIndent;           * Sets the Hash color.
296    int rowHeight;           *
297    Color hashColor;           * @param the <code>Color</code> to set the Hash to.
298             */
299    protected void installDefaults(JTree tree)          protected void setHashColor(Color color)
300    {          {
301      UIDefaults defaults = UIManager.getLookAndFeelDefaults();                  // FIXME: not implemented
302    
303      tree.setFont(defaults.getFont("Tree.font"));          }
304      tree.setForeground(defaults.getColor("Tree.foreground"));  
305      tree.setBackground(defaults.getColor("Tree.background"));          /**
306      tree.setOpaque(true);           * Sets the left child's indent value.
307             *
308      hashColor = defaults.getColor("Tree.hash");           * @param newAmount is the new indent value for the left child.
309      rightChildIndent = defaults.getInt("Tree.rightChildIndent");           */
310      leftChildIndent = defaults.getInt("Tree.leftChildIndent");          public void setLeftChildIndent(int newAmount)
311      rowHeight = defaults.getInt("Tree.rowHeight");          {
312    }                  leftChildIndent = newAmount;
313            }
314    protected void installKeyboardActions()  
315    {          /**
316    }           * Returns the indent value for the left child.
317             *
318    protected void installListeners()           * @return the indent value for the left child.
319    {           */
320    }          public int getLeftChildIndent(int newAmount)
321            {
322    public void installUI(JComponent c)                  return leftChildIndent;
323    {          }
324      installDefaults((JTree) c);  
325    }          /**
326             * Sets the right child's indent value.
327             *
328    protected void uninstallDefaults(JTree tree)           * @param newAmount is the new indent value for the right child.
329    {           */
330      tree.setFont(null);          public void setRightChildIndent(int newAmount)
331      tree.setForeground(null);          {
332      tree.setBackground(null);                  rightChildIndent = newAmount;
333            }
334      tree.setCellRenderer(null);  
335    }          /**
336             * Returns the indent value for the right child.
337    public void uninstallUI(JComponent c)           *
338    {           * @return the indent value for the right child.
339      uninstallDefaults((JTree) c);           */
340    }          public int getRightChildIndent(int newAmount)
341            {
342    public Dimension getPreferredSize(JComponent c)                  return rightChildIndent;
343    {          }
344      return new Dimension(200,200);  
345    }          /**
346             * Sets the expanded icon.
347    protected void paintLeaf(Graphics g, int x, int y, JTree tree, Object leaf)           *
348    {           * @param newG is the new expanded icon.
349      Component c = tree.getCellRenderer().getTreeCellRendererComponent(tree,           */
350                                                                        leaf,          public void setExpandedIcon(Icon newG)
351                                                                        false, // selected          {
352                                                                        false, // expanded                  expandedIcon = newG;
353                                                                        true,  // leaf          }
354                                                                        0,     // row  
355                                                                        false  // hasFocus          /**
356                                                                        );           * Returns the current expanded icon.
357      g.translate(x, y);           *
358      c.paint(g);           * @return the current expanded icon.
359      g.translate(-x, -y);           */
360    }          public Icon getExpandedIcon()
361            {
362    protected void paintNonLeaf(Graphics g, int x, int y, JTree tree, Object nonLeaf)                  return expandedIcon;
363    {          }
364      Component c = tree.getCellRenderer().getTreeCellRendererComponent(tree,  
365                                                                        nonLeaf,          /**
366                                                                        false, // selected           * Sets the collapsed icon.
367                                                                        false, // expanded           *
368                                                                        false, // leaf           * @param newG is the new collapsed icon.
369                                                                        0,     // row           */
370                                                                        false  // hasFocus          public void setCollapsedIcon(Icon newG)
371                                                                        );          {
372      g.translate(x, y);                  collapsedIcon = newG;
373      c.paint(g);          }
374      g.translate(-x, -y);  
375    }          /**
376             * Returns the current collapsed icon.
377    protected int paintRecursive(Graphics g,           *
378                                 int indentation,           * @return the current collapsed icon.
379                                 int descent,           */
380                                 int childNumber,          public Icon getCollapsedIcon()
381                                 int depth,          {
382                                 JTree tree,                  return collapsedIcon;
383                                 TreeModel mod,          }
384                                 Object curr)  
385    {          /**
386      Rectangle clip = g.getClipBounds();           * Updates the componentListener, if necessary.
387      if (indentation > clip.x + clip.width + rightChildIndent ||           *
388          descent > clip.y + clip.height + rowHeight)           * @param largeModel sets this.largeModel to it.
389        return descent;           */
390            protected void setLargeModel(boolean largeModel)
391            {
392      int halfHeight = rowHeight / 2;                  if (largeModel != this.largeModel)
393      int halfWidth = rightChildIndent / 2;                  {
394      int y0 = descent + halfHeight;                          tree.removeComponentListener(componentListener);
395                                    this.largeModel = largeModel;
396      if (mod.isLeaf(curr))                          tree.addComponentListener(componentListener);
397        {                  }
398          paintLeaf(g, indentation, descent, tree, curr);          }
399          descent += rowHeight;  
400        }          /**
401      else           * Returns true if largeModel is set
402        {           *
403          if (depth > 0 || tree.isRootVisible())           * @return true if largeModel is set, otherwise false.
404            {           */
405              paintNonLeaf(g, indentation, descent, tree, curr);          protected boolean isLargeModel()
406              descent += rowHeight;          {
407              y0 += halfHeight;                  return largeModel;
408            }          }
409          int max = mod.getChildCount(curr);  
410          for (int i = 0; i < max; ++i)          /**
411            {           * Sets the row height.
412              g.setColor(hashColor);           *
413              g.drawLine(indentation + halfWidth,        descent + halfHeight,           * @param rowHeight is the height to set this.rowHeight to.
414                         indentation + rightChildIndent, descent + halfHeight);           */
415              descent = paintRecursive(g,          protected void setRowHeight(int rowHeight)
416                                       indentation + rightChildIndent, descent,          {
417                                       i, depth+1,                  treeState.setRowHeight(rowHeight);
418                                       tree, mod, mod.getChild(curr, i));          }
419            }  
420        }          /**
421             * Returns the current row height.
422      int y1 = descent - halfHeight;           *
423      if (y0 != y1)           * @return current row height.
424        {           */
425          g.setColor(hashColor);          protected int getRowHeight()
426          g.drawLine(indentation + halfWidth, y0,          {
427                     indentation + halfWidth, y1);                  return treeState.getRowHeight();
428        }          }
429    
430      return descent;          /**
431    }           * Sets the TreeCellRenderer to <code>tcr</code>. This invokes
432             * <code>updateRenderer</code>.
433    public void paint(Graphics g, JComponent c)           *
434    {           * @param tcr is the new TreeCellRenderer.
435      JTree tree = (JTree) c;           */
436      TreeModel mod = tree.getModel();          protected void setCellRenderer(TreeCellRenderer tcr)
437      g.translate(10, 10);          {
438      paintRecursive(g, 0, 0, 0, 0, tree, mod, mod.getRoot());                  currentCellRenderer = tcr;
439      g.translate(-10, -10);                  updateRenderer();
440    }          }
441  }  
442            /**
443             * Return currentCellRenderer, which will either be the trees renderer, or
444             * defaultCellRenderer, which ever was not null.
445             *
446             * @return the current Cell Renderer
447             */
448            protected TreeCellRenderer getCellRenderer()
449            {
450                    if (currentCellRenderer != null)
451                            return currentCellRenderer;
452    
453                    return createDefaultCellRenderer();
454            }
455    
456            /**
457             * Sets the tree's model.
458             *
459             * @param model to set the treeModel to.
460             */
461            protected void setModel(TreeModel model)
462            {
463                    treeState.setModel(model);
464                    treeModel = model;
465            }
466    
467            /**
468             * Returns the tree's model
469             *
470             * @return treeModel
471             */
472            protected TreeModel getModel()
473            {
474                    return treeModel;
475            }
476    
477            /**
478             * Sets the root to being visible.
479             *
480             * @param newValue sets the visibility of the root
481             */
482            protected void setRootVisible(boolean newValue)
483            {
484                    treeState.setRootVisible(newValue);
485            }
486    
487            /**
488             * Returns true if the root is visible.
489             *
490             * @return true if the root is visible.
491             */
492            protected boolean isRootVisible()
493            {
494                    return treeState.isRootVisible();
495            }
496    
497            /**
498             * Determines whether the node handles are to be displayed.
499             *
500             * @param newValue sets whether or not node handles should be displayed.
501             */
502            protected void setShowsRootHandles(boolean newValue)
503            {
504                    tree.setShowsRootHandles(newValue);
505            }
506    
507            /**
508             * Returns true if the node handles are to be displayed.
509             *
510             * @return true if the node handles are to be displayed.
511             */
512            protected boolean getShowsRootHandles()
513            {
514                    return tree.getShowsRootHandles();
515            }
516    
517            /**
518             * Sets the cell editor.
519             *
520             * @param editor to set the cellEditor to.
521             */
522            protected void setCellEditor(TreeCellEditor editor)
523            {
524                    cellEditor = editor;
525            }
526    
527            /**
528             * Returns the <code>TreeCellEditor</code> for this tree.
529             *
530             * @return the cellEditor for this tree.
531             */
532            protected TreeCellEditor getCellEditor()
533            {
534                    return cellEditor;
535            }
536    
537            /**
538             * Configures the receiver to allow, or not allow, editing.
539             *
540             * @param newValue sets the receiver to allow editing if true.
541             */
542            protected void setEditable(boolean newValue)
543            {
544                    tree.setEditable(newValue);
545            }
546    
547            /**
548             * Returns true if the receiver allows editing.
549             *
550             * @return true if the receiver allows editing.
551             */
552            protected boolean isEditable()
553            {
554                    return tree.isEditable();
555            }
556    
557            /**
558             * Resets the selection model. The appropriate listeners are installed on
559             * the model.
560             *
561             * @param newLSM resets the selection model.
562             */
563            protected void setSelectionModel(TreeSelectionModel newLSM)
564            {
565                    if (newLSM != null)
566                    {
567                            tree
568                                            .removePropertyChangeListener(selectionModelPropertyChangeListener);
569                            treeSelectionModel = newLSM;
570                            treeState.setSelectionModel(newLSM);
571                            tree
572                                            .addPropertyChangeListener(selectionModelPropertyChangeListener);
573                            tree.setSelectionModel(treeSelectionModel);
574                    }
575            }
576    
577            /**
578             * Returns the current selection model.
579             *
580             * @return the current selection model.
581             */
582            protected TreeSelectionModel getSelectionModel()
583            {
584                    return treeSelectionModel;
585            }
586    
587            /**
588             * Returns the Rectangle enclosing the label portion that the last item in
589             * path will be drawn to. Will return null if any component in path is
590             * currently valid.
591             *
592             * @param tree is the current tree the path will be drawn to.
593             * @param path is the current path the tree to draw to.
594             * @return the Rectangle enclosing the label portion that the last item in
595             *         the path will be drawn to.
596             */
597            public Rectangle getPathBounds(JTree tree, TreePath path)
598            {
599                    // FIXME: not implemented
600                    return null;
601            }
602            
603            /**
604             * Returns the path for passed in row. If row is not visible null is
605             * returned.
606             *
607             * @param tree is the current tree to return path for.
608             * @param row is the row number of the row to return.
609             * @return the path for passed in row. If row is not visible null is
610             *         returned.
611             */
612            public TreePath getPathForRow(JTree tree, int row)
613            {
614                    // FIXME: check visibility when expand/collapse is implemented
615                    DefaultMutableTreeNode pathForRow = ((DefaultMutableTreeNode) (tree
616                                    .getModel()).getRoot());
617                    for (int i = 0; i < row; i++)
618                    {
619                            if (pathForRow != null)
620                                    pathForRow = pathForRow.getNextNode();
621                    }
622                    return new TreePath(pathForRow.getPath());
623            }
624    
625            /**
626             * Returns the row that the last item identified in path is visible at. Will
627             * return -1 if any of the elments in the path are not currently visible.
628             *
629             * @param tree is the current tree to return the row for.
630             * @param path is the path used to find the row.
631             * @return the row that the last item identified in path is visible at. Will
632             *         return -1 if any of the elments in the path are not currently
633             *         visible.
634             */
635            public int getRowForPath(JTree tree, TreePath path)
636            {
637                    // FIXME: check visibility
638                    // right now, just returns last element because
639                    // expand/collapse is not implemented
640                    return path.length - 1;
641            }
642    
643            /**
644             * Returns the number of rows that are being displayed.
645             *
646             * @param tree is the current tree to return the number of rows for.
647             * @return the number of rows being displayed.
648             */
649            public int getRowCount(JTree tree)
650            {
651                    return treeState.getRowCount();
652            }
653    
654            /**
655             * Returns the path to the node that is closest to x,y. If there is nothing
656             * currently visible this will return null, otherwise it'll always return a
657             * valid path. If you need to test if the returned object is exactly at x,y
658             * you should get the bounds for the returned path and test x,y against
659             * that.
660             *
661             * @param tree the tree to search for the closest path
662             * @param x is the x coordinate of the location to search
663             * @param y is the y coordinate of the location to search
664             * @return the tree path closes to x,y.
665             */
666            public TreePath getClosestPathForLocation(JTree tree, int x, int y)
667            {
668                    return treeState.getPathClosestTo(x, y);
669            }
670    
671            /**
672             * Returns true if the tree is being edited. The item that is being edited
673             * can be returned by getEditingPath().
674             *
675             * @param tree is the tree to check for editing.
676             * @return true if the tree is being edited.
677             */
678            public boolean isEditing(JTree tree)
679            {
680                    // FIXME: not implemented
681                    return false;
682            }
683    
684            /**
685             * Stops the current editing session. This has no effect if the tree is not
686             * being edited. Returns true if the editor allows the editing session to
687             * stop.
688             *
689             * @param tree is the tree to stop the editing on
690             * @return true if the editor allows the editing session to stop.
691             */
692            public boolean stopEditing(JTree tree)
693            {
694                    // FIXME: not implemented
695                    return false;
696            }
697    
698            /**
699             * Cancels the current editing session.
700             *
701             * @param tree is the tree to cancel the editing session on.
702             */
703            public void cancelEditing(JTree tree)
704            {
705                    // FIXME: not implemented
706            }
707    
708            /**
709             * Selects the last item in path and tries to edit it. Editing will fail if
710             * the CellEditor won't allow it for the selected item.
711             *
712             * @param tree is the tree to edit on.
713             * @param path is the path in tree to edit on.
714             */
715            public void startEditingAtPath(JTree tree, TreePath path)
716            {
717                    // FIXME: not implemented
718            }
719    
720            /**
721             * Returns the path to the element that is being editted.
722             *
723             * @param tree is the tree to get the editing path from.
724             * @return the path that is being edited.
725             */
726            public TreePath getEditingPath(JTree tree)
727            {
728                    // FIXME: not implemented
729                    return null;
730            }
731    
732            /**
733             * Invoked after the tree instance variable has been set, but before any
734             * default/listeners have been installed.
735             */
736            protected void prepareForUIInstall()
737            {
738                    // FIXME: not implemented
739            }
740    
741            /**
742             * Invoked from installUI after all the defaults/listeners have been
743             * installed.
744             */
745            protected void completeUIInstall()
746            {
747                    // FIXME: not implemented
748            }
749    
750            /**
751             * Invoked from uninstallUI after all the defaults/listeners have been
752             * uninstalled.
753             */
754            protected void completeUIUninstall()
755            {
756                    // FIXME: not implemented
757            }
758    
759            /**
760             * Installs the subcomponents of the tree, which is the renderer pane.
761             */
762            protected void installComponents()
763            {
764                    // FIXME: not implemented
765            }
766    
767            /**
768             * Creates an instance of NodeDimensions that is able to determine the size
769             * of a given node in the tree.
770             *
771             * @return the NodeDimensions of a given node in the tree
772             */
773            protected AbstractLayoutCache.NodeDimensions createNodeDimensions()
774            {
775                    // FIXME: not implemented
776                    return null;
777            }
778    
779            /**
780             * Creates a listener that is reponsible for the updates the UI based on how
781             * the tree changes.
782             *
783             * @return the PropertyChangeListener that is reposnsible for the updates
784             */
785            protected PropertyChangeListener createPropertyChangeListener()
786            {
787                    return new PropertyChangeHandler();
788            }
789    
790            /**
791             * Creates the listener responsible for updating the selection based on
792             * mouse events.
793             *
794             * @return the MouseListener responsible for updating.
795             */
796            protected MouseListener createMouseListener()
797            {
798                    return new MouseHandler();
799            }
800    
801            /**
802             * Creates the listener that is responsible for updating the display when
803             * focus is lost/grained.
804             *
805             * @return the FocusListener responsible for updating.
806             */
807            protected FocusListener createFocusListener()
808            {
809                    return new FocusHandler();
810            }
811    
812            /**
813             * Creates the listener reponsible for getting key events from the tree.
814             *
815             * @return the KeyListener responsible for getting key events.
816             */
817            protected KeyListener createKeyListener()
818            {
819                    return new KeyHandler();
820            }
821    
822            /**
823             * Creates the listener responsible for getting property change events from
824             * the selection model.
825             *
826             * @returns the PropertyChangeListener reponsible for getting property
827             *          change events from the selection model.
828             */
829            protected PropertyChangeListener createSelectionModelPropertyChangeListener()
830            {
831                    return new SelectionModelPropertyChangeHandler();
832            }
833    
834            /**
835             * Creates the listener that updates the display based on selection change
836             * methods.
837             *
838             * @return the TreeSelectionListener responsible for updating.
839             */
840            protected TreeSelectionListener createTreeSelectionListener()
841            {
842                    return new TreeSelectionHandler();
843            }
844    
845            /**
846             * Creates a listener to handle events from the current editor
847             *
848             * @return the CellEditorListener that handles events from the current
849             *         editor
850             */
851            protected CellEditorListener createCellEditorListener()
852            {
853                    return new CellEditorHandler();
854            }
855    
856            /**
857             * Creates and returns a new ComponentHandler. This is used for the large
858             * model to mark the validCachedPreferredSize as invalid when the component
859             * moves.
860             *
861             * @return a new ComponentHandler.
862             */
863            protected ComponentListener createComponentListener()
864            {
865                    return new ComponentHandler();
866            }
867    
868            /**
869             * Creates and returns the object responsible for updating the treestate
870             * when a nodes expanded state changes.
871             *
872             * @return the TreeExpansionListener responsible for updating the treestate
873             */
874            protected TreeExpansionListener createTreeExpansionListener()
875            {
876                    return new TreeExpansionHandler();
877            }
878    
879            /**
880             * Creates the object responsible for managing what is expanded, as well as
881             * the size of nodes.
882             *
883             * @return the object responsible for managing what is expanded.
884             */
885            protected AbstractLayoutCache createLayoutCache()
886            {
887                    return new FixedHeightLayoutCache();
888            }
889    
890            /**
891             * Returns the renderer pane that renderer components are placed in.
892             *
893             * @return the rendererpane that render components are placed in.
894             */
895            protected CellRendererPane createCellRendererPane()
896            {
897                    return new CellRendererPane();
898            }
899    
900            /**
901             * Creates a default cell editor.
902             *
903             * @return the default cell editor.
904             */
905            protected TreeCellEditor createDefaultCellEditor()
906            {
907                    return new DefaultTreeCellEditor(tree,
908                                    (DefaultTreeCellRenderer) createDefaultCellRenderer(),
909                                    cellEditor);
910            }
911    
912            /**
913             * Returns the default cell renderer that is used to do the stamping of each
914             * node.
915             *
916             * @return the default cell renderer that is used to do the stamping of each
917             *         node.
918             */
919            protected TreeCellRenderer createDefaultCellRenderer()
920            {
921                    return new DefaultTreeCellRenderer();
922            }
923    
924            /**
925             * Returns a listener that can update the tree when the model changes.
926             *
927             * @return a listener that can update the tree when the model changes.
928             */
929            protected TreeModelListener createTreeModelListener()
930            {
931                    return new TreeModelHandler();
932            }
933    
934            /**
935             * Uninstall all registered listeners
936             */
937            protected void uninstallListeners()
938            {
939                    tree.removePropertyChangeListener(propertyChangeListener);
940                    tree.removeFocusListener(focusListener);
941                    tree.removeTreeSelectionListener(treeSelectionListener);
942                    tree.removeMouseListener(mouseInputListener);
943                    tree.removeKeyListener(keyListener);
944                    tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
945                    tree.removeComponentListener(componentListener);
946                    tree.getCellEditor().removeCellEditorListener(cellEditorListener);
947                    tree.removeTreeExpansionListener(treeExpansionListener);
948                    tree.getModel().removeTreeModelListener(treeModelListener);
949            }
950    
951            /**
952             * Uninstall all keyboard actions.
953             */
954            protected void uninstallKeyboardActions()
955            {
956            }
957    
958            /**
959             * Uninstall the rendererPane.
960             */
961            protected void uninstallComponents()
962            {
963                    // FIXME: not implemented
964            }
965    
966            /**
967             * The vertical element of legs between nodes starts at the bottom of the
968             * parent node by default. This method makes the leg start below that.
969             *
970             * @return the vertical leg buffer
971             */
972            protected int getVerticalLegBuffer()
973            {
974                    // FIXME: not implemented
975                    return 0;
976            }
977    
978            /**
979             * The horizontal element of legs between nodes starts at the right of the
980             * left-hand side of the child node by default. This method makes the leg
981             * end before that.
982             *
983             * @return the horizontal leg buffer
984             */
985            protected int getHorizontalLegBuffer()
986            {
987                    // FIXME: not implemented
988                    return 0;
989            }
990    
991            /**
992             * Make all the nodes that are expanded in JTree expanded in LayoutCache.
993             * This invokes update ExpandedDescendants with the root path.
994             */
995            protected void updateLayoutCacheExpandedNodes()
996            {
997                    // FIXME: not implemented
998            }
999    
1000            /**
1001             * Updates the expanded state of all the descendants of the
1002             * <code>path</code> by getting the expanded descendants from the tree and
1003             * forwarding to the tree state.
1004             *
1005             * @param path the path used to update the expanded states
1006             */
1007            protected void updateExpandedDescendants(TreePath path)
1008            {
1009                    // FIXME: not implemented
1010            }
1011    
1012            /**
1013             * Returns a path to the last child of <code>parent</code>
1014             *
1015             * @param parent is the topmost path to specified
1016             * @return a path to the last child of parent
1017             */
1018            protected TreePath getLastChildPath(TreePath parent)
1019            {
1020                    return ((TreePath) parent.getLastPathComponent());
1021            }
1022    
1023            /**
1024             * Updates how much each depth should be offset by.
1025             */
1026            protected void updateDepthOffset()
1027            {
1028                    // FIXME: not implemented
1029            }
1030    
1031            /**
1032             * Updates the cellEditor based on editability of the JTree that we're
1033             * contained in. Ig the tree is editable but doesn't have a cellEditor, a
1034             * basic one will be used.
1035             */
1036            protected void updateCellEditor()
1037            {
1038                    // FIXME: not implemented
1039            }
1040    
1041            /**
1042             * Messaged from the tree we're in when the renderer has changed.
1043             */
1044            protected void updateRenderer()
1045            {
1046                    // FIXME: not implemented
1047            }
1048    
1049            /**
1050             * Resets the treeState instance based on the tree we're providing the look
1051             * and feel for.
1052             */
1053            protected void configureLayoutCache()
1054            {
1055                    treeState = createLayoutCache();
1056            }
1057    
1058            /**
1059             * Marks the cached size as being invalid, and messages the tree with
1060             * <code>treeDidChange</code>.
1061             */
1062            protected void updateSize()
1063            {
1064                    // FIXME: not implemented
1065            }
1066    
1067            /**
1068             * Updates the <code>preferredSize</code> instance variable, which is
1069             * returned from <code>getPreferredSize()</code>. For left to right
1070             * orientations, the size is determined from the current
1071             * AbstractLayoutCache. For RTL orientations, the preferred size becomes the
1072             * width minus the minimum x position.
1073             */
1074            protected void updateCachedPreferredSize()
1075            {
1076                    // FIXME: not implemented
1077            }
1078    
1079            /**
1080             * Messaged from the VisibleTreeNode after it has been expanded.
1081             *
1082             * @param path is the path that has been expanded.
1083             */
1084            protected void pathWasExpanded(TreePath path)
1085            {
1086                    // FIXME: not implemented
1087            }
1088    
1089            /**
1090             * Messaged from the VisibleTreeNode after it has collapsed
1091             */
1092            protected void pathWasCollapsed(TreePath path)
1093            {
1094                    // FIXME: not implemented
1095            }
1096    
1097            protected void installDefaults(JTree tree)
1098            {
1099                    UIDefaults defaults = UIManager.getLookAndFeelDefaults();
1100    
1101                    tree.setFont(defaults.getFont("Tree.font"));
1102                    tree.setForeground(defaults.getColor("Tree.foreground"));
1103                    tree.setBackground(defaults.getColor("Tree.background"));
1104                    tree.setOpaque(true);
1105    
1106                    rightChildIndent = defaults.getInt("Tree.rightChildIndent");
1107                    leftChildIndent = defaults.getInt("Tree.leftChildIndent");
1108                    setRowHeight(defaults.getInt("Tree.rowHeight"));
1109            }
1110    
1111            protected void installKeyboardActions()
1112            {
1113            }
1114    
1115            protected void installListeners()
1116            {
1117                    tree.addPropertyChangeListener(propertyChangeListener);
1118                    tree.addFocusListener(focusListener);
1119                    tree.addTreeSelectionListener(treeSelectionListener);
1120                    tree.addMouseListener(mouseInputListener);
1121                    tree.addKeyListener(keyListener);
1122                    tree.addPropertyChangeListener(selectionModelPropertyChangeListener);
1123                    tree.addComponentListener(componentListener);
1124                    cellEditor.addCellEditorListener(cellEditorListener);
1125                    tree.addTreeExpansionListener(treeExpansionListener);
1126                    treeModel.addTreeModelListener(treeModelListener);
1127            }
1128    
1129            public void installUI(JComponent c)
1130            {
1131                    super.installUI(c);
1132                    installDefaults((JTree) c);
1133                    tree = (JTree) c;
1134                    setModel(tree.getModel());
1135                    treeSelectionModel = tree.getSelectionModel();
1136                    installListeners();
1137                    installKeyboardActions();
1138                    completeUIInstall();
1139            }
1140    
1141            protected void uninstallDefaults(JTree tree)
1142            {
1143                    UIDefaults defaults = UIManager.getLookAndFeelDefaults();
1144                    tree.setFont(null);
1145                    tree.setForeground(null);
1146                    tree.setBackground(null);
1147                    tree.setCellRenderer(null);
1148            }
1149    
1150            public void uninstallUI(JComponent c)
1151            {
1152                    uninstallDefaults((JTree) c);
1153                    uninstallKeyboardActions();
1154                    uninstallListeners();
1155                    tree = null;
1156                    completeUIUninstall();
1157            }
1158    
1159            public void paint(Graphics g, JComponent c)
1160            {
1161                    JTree tree = (JTree) c;
1162                    TreeModel mod = tree.getModel();
1163                    g.translate(10, 10);
1164                    paintRecursive(g, 0, 0, 0, 0, tree, mod, mod.getRoot());
1165                    g.translate(-10, -10);
1166            }
1167    
1168            /**
1169             * Ensures that the rows identified by beginRow through endRow are visible.
1170             *
1171             * @param beginRow is the first row
1172             * @param endRow is the last row
1173             */
1174            protected void ensureRowsAreVisible(int beginRow, int endRow)
1175            {
1176                    // FIXME: not implemented
1177            }
1178    
1179            /**
1180             * Sets the preferred minimum size.
1181             *
1182             * @param newSize is the new preferred minimum size.
1183             */
1184            public void setPreferredMinSize(Dimension newSize)
1185            {
1186                    // FIXME: not implemented
1187            }
1188    
1189            /**
1190             * Gets the preferred minimum size.
1191             *
1192             * @returns the preferred minimum size.
1193             */
1194            public Dimension getPreferredMinSize()
1195            {
1196                    // FIXME: not implemented
1197                    return null;
1198            }
1199    
1200            /**
1201             * Returns the preferred size to properly display the tree, this is a cover
1202             * method for getPreferredSize(c, false).
1203             *
1204             * @param c the component whose preferred size is being queried; this
1205             *        argument is often ignored but might be used if the UI object is
1206             *        stateless and shared by multiple components
1207             * @return the preferred size
1208             */
1209            public Dimension getPreferredSize(JComponent c)
1210            {
1211                    return getPreferredSize(c, false);
1212            }
1213    
1214            /**
1215             * Returns the preferred size to represent the tree in c. If
1216             * checkConsistancy is true, checkConsistancy is messaged first.
1217             *
1218             * @param c the component whose preferred size is being queried.
1219             * @param checkConsistancy if true must check consistancy
1220             * @return the preferred size
1221             */
1222            public Dimension getPreferredSize(JComponent c, boolean checkConsistancy)
1223            {
1224                    // FIXME: not implemented
1225                    return new Dimension(200, 900);
1226            }
1227    
1228            /**
1229             * Returns the minimum size for this component. Which will be the min
1230             * preferred size or (0,0).
1231             *
1232             * @param c the component whose min size is being queried.
1233             * @returns the preferred size or null
1234             */
1235            public Dimension getMinimumSize(JComponent c)
1236            {
1237                    // FIXME: not implemented
1238                    return new Dimension(200, 900);
1239            }
1240    
1241            /**
1242             * Returns the maximum size for the component, which will be the preferred
1243             * size if the instance is currently in JTree or (0,0).
1244             *
1245             * @param c the component whose preferred size is being queried
1246             * @return the max size or null
1247             */
1248            public Dimension getMaximumSize(JComponent c)
1249            {
1250                    // FIXME: not implemented
1251                    return new Dimension(200, 900);
1252            }
1253    
1254            /**
1255             * Messages to stop the editing session. If the UI the receiver is providing
1256             * the look and feel for returns true from
1257             * <code>getInvokesStopCellEditing</code>, stopCellEditing will be
1258             * invoked on the current editor. Then completeEditing will be messaged with
1259             * false, true, false to cancel any lingering editing.
1260             */
1261            protected void completeEditing()
1262            {
1263                    // FIXME: not implemented
1264            }
1265    
1266            /**
1267             * Stops the editing session. If messageStop is true, the editor is messaged
1268             * with stopEditing, if messageCancel is true the editor is messaged with
1269             * cancelEditing. If messageTree is true, the treeModel is messaged with
1270             * valueForPathChanged.
1271             *
1272             * @param messageStop message to stop editing
1273             * @param messageCancel message to cancel editing
1274             * @param messageTree message to treeModel
1275             */
1276            protected void completeEditing(boolean messageStop, boolean messageCancel,
1277                            boolean messageTree)
1278            {
1279                    // FIXME: not implemented
1280            }
1281    
1282            /**
1283             * Will start editing for node if there is a cellEditor and shouldSelectCall
1284             * returns true. This assumes that path is valid and visible.
1285             *
1286             * @param path is the path to start editing
1287             * @param event is the MouseEvent performed on the path
1288             * @return true if successful
1289             */
1290            protected boolean startEditing(TreePath path, MouseEvent event)
1291            {
1292                    // FIXME: not implemented
1293                    return false;
1294            }
1295    
1296            /**
1297             * If the <code>mouseX</code> and <code>mouseY</code> are in the expand
1298             * or collapse region of the row, this will toggle the row.
1299             *
1300             * @param path the path we are concerned with
1301             * @param mouseX is the cursor's x position
1302             * @param mouseY is the cursor's y position
1303             */
1304            protected void checkForClickInExpandControl(TreePath path, int mouseX,
1305                            int mouseY)
1306            {
1307                    // FIXME: not implemented
1308            }
1309    
1310            /**
1311             * Returns true if the <code>mouseX</code> and <code>mouseY</code> fall
1312             * in the area of row that is used to expand/collpse the node and the node
1313             * at row does not represent a leaf.
1314             *
1315             * @param path the path we are concerned with
1316             * @param mouseX is the cursor's x position
1317             * @param mouseY is the cursor's y position
1318             * @return true if the <code>mouseX</code> and <code>mouseY</code> fall
1319             *         in the area of row that is used to expand/collpse the node and
1320             *         the node at row does not represent a leaf.
1321             */
1322            protected boolean isLocationInExpandControl(TreePath path, int mouseX,
1323                            int mouseY)
1324            {
1325                    // FIXME: not implemented
1326                    return false;
1327            }
1328    
1329            /**
1330             * Messaged when the user clicks the particular row, this invokes
1331             * toggleExpandState.
1332             *
1333             * @param path the path we are concerned with
1334             * @param mouseX is the cursor's x position
1335             * @param mouseY is the cursor's y position
1336             */
1337            protected void handleExpandControlClick(TreePath path, int mouseX,
1338                            int mouseY)
1339            {
1340                    // FIXME: not implemented
1341            }
1342    
1343            /**
1344             * Expands path if it is not expanded, or collapses row if it is expanded.
1345             * If expanding a path and JTree scroll on expand, ensureRowsAreVisible is
1346             * invoked to scroll as many of the children to visible as possible (tries
1347             * to scroll to last visible descendant of path).
1348             *
1349             * @param path the path we are concerned with
1350             */
1351            protected void toggleExpandState(TreePath path)
1352            {
1353                    // FIXME: not implemented
1354            }
1355    
1356            /**
1357             * Returning true signifies a mouse event on the node should toggle the
1358             * selection of only the row under the mouse.
1359             *
1360             * @param event is the MouseEvent performed on the row.
1361             * @return true signifies a mouse event on the node should toggle the
1362             *         selection of only the row under the mouse.
1363             */
1364            protected boolean isToggleSelectionEvent(MouseEvent event)
1365            {
1366                    // FIXME: not implemented
1367                    return false;
1368            }
1369    
1370            /**
1371             * Returning true signifies a mouse event on the node should select from the
1372             * anchor point.
1373             *
1374             * @param event is the MouseEvent performed on the node.
1375             * @return true signifies a mouse event on the node should select from the
1376             *         anchor point.
1377             */
1378            protected boolean isMultiSelectEvent(MouseEvent event)
1379            {
1380                    // FIXME: not implemented
1381                    return false;
1382            }
1383    
1384            /**
1385             * Returning true indicates the row under the mouse should be toggled based
1386             * on the event. This is invoked after checkForClickInExpandControl,
1387             * implying the location is not in the expand (toggle) control.
1388             *
1389             * @param event is the MouseEvent performed on the row.
1390             * @return true indicates the row under the mouse should be toggled based on
1391             *         the event.
1392             */
1393            protected boolean isToggleEvent(MouseEvent event)
1394            {
1395                    // FIXME: not implemented
1396                    return false;
1397            }
1398    
1399            /**
1400             * Messaged to update the selection based on a MouseEvent over a particular
1401             * row. If the even is a toggle selection event, the row is either selected,
1402             * or deselected. If the event identifies a multi selection event, the
1403             * selection is updated from the anchor point. Otherwise, the row is
1404             * selected, and if the even specified a toggle event the row is
1405             * expanded/collapsed.
1406             *
1407             * @param path is the path selected for an event
1408             * @param event is the MouseEvent performed on the path.
1409             */
1410            protected void selectPathForEvent(TreePath path, MouseEvent event)
1411            {
1412                    // FIXME: not implemented
1413            }
1414    
1415            /**
1416             * Returns true if the node at <code>row</code> is a leaf.
1417             *
1418             * @param row is the row we are concerned with.
1419             * @return true if the node at <code>row</code> is a leaf.
1420             */
1421            protected boolean isLeaf(int row)
1422            {
1423                    return false;
1424                    // FIXME: not implemented
1425            }
1426    
1427            /* * INTERNAL CLASSES * */
1428    
1429            /**
1430             * Updates the preferred size when scrolling, if necessary.
1431             */
1432            public class ComponentHandler
1433                            extends ComponentAdapter
1434                            implements ActionListener
1435            {
1436                    /**
1437                     * Timer used when inside a scrollpane and the scrollbar is adjusting
1438                     */
1439                    protected Timer timer;
1440    
1441                    /** ScrollBar that is being adjusted */
1442                    protected JScrollBar scrollBar;
1443    
1444                    /**
1445                     * Constructor
1446                     */
1447                    public ComponentHandler()
1448                    {
1449                    }
1450    
1451                    /**
1452                     * Invoked when the component's position changes.
1453                     *
1454                     * @param e the event that occurs when moving the component
1455                     */
1456                    public void componentMoved(ComponentEvent e)
1457                    {
1458                    }
1459    
1460                    /**
1461                     * Creats, if necessary, and starts a Timer to check if needed to resize
1462                     * the bounds
1463                     */
1464                    protected void startTimer()
1465                    {
1466                    }
1467    
1468                    /**
1469                     * Returns the JScrollPane housing the JTree, or null if one isn't
1470                     * found.
1471                     *
1472                     * @return JScrollPane housing the JTree, or null if one isn't found.
1473                     */
1474                    protected JScrollPane getScrollPane()
1475                    {
1476                            return null;
1477                    }
1478    
1479                    /**
1480                     * Public as a result of Timer. If the scrollBar is null, or not
1481                     * adjusting, this stops the timer and updates the sizing.
1482                     *
1483                     * @param ae is the action performed
1484                     */
1485                    public void actionPerformed(ActionEvent ae)
1486                    {
1487                    }
1488            }// ComponentHandler
1489    
1490            /**
1491             * Listener responsible for getting cell editing events and updating the
1492             * tree accordingly.
1493             */
1494            public class CellEditorHandler
1495                            implements CellEditorListener
1496            {
1497                    /**
1498                     * Constructor
1499                     */
1500                    public CellEditorHandler()
1501                    {
1502                    }
1503    
1504                    /**
1505                     * Messaged when editing has stopped in the tree. Tells the listeners
1506                     * editing has stopped.
1507                     *
1508                     * @param e is the notification event
1509                     */
1510                    public void editingStopped(ChangeEvent e)
1511                    {
1512                    }
1513    
1514                    /**
1515                     * Messaged when editing has been canceled in the tree. This tells the
1516                     * listeners the editor has canceled editing.
1517                     *
1518                     * @param e is the notification event
1519                     */
1520                    public void editingCanceled(ChangeEvent e)
1521                    {
1522                    }
1523            }// CellEditorHandler
1524    
1525            /**
1526             * Repaints the lead selection row when focus is lost/grained.
1527             */
1528            public class FocusHandler
1529                            implements FocusListener
1530            {
1531                    /**
1532                     * Constructor
1533                     */
1534                    public FocusHandler()
1535                    {
1536                    }
1537    
1538                    /**
1539                     * Invoked when focus is activated on the tree we're in, redraws the
1540                     * lead row. Invoked when a component gains the keyboard focus.
1541                     *
1542                     * @param e is the focus event that is activated
1543                     */
1544                    public void focusGained(FocusEvent e)
1545                    {
1546                    }
1547    
1548                    /**
1549                     * Invoked when focus is deactivated on the tree we're in, redraws the
1550                     * lead row. Invoked when a component loses the keyboard focus.
1551                     *
1552                     * @param e is the focus event that is deactivated
1553                     */
1554                    public void focusLost(FocusEvent e)
1555                    {
1556                    }
1557            }// FocusHandler
1558    
1559            /**
1560             * This is used to get multiple key down events to appropriately genereate
1561             * events.
1562             */
1563            public class KeyHandler
1564                            extends KeyAdapter
1565            {
1566                    /** Key code that is being generated for. */
1567                    protected Action repeatKeyAction;
1568    
1569                    /** Set to true while keyPressed is active */
1570                    protected boolean isKeyDown;
1571    
1572                    /**
1573                     * Constructor
1574                     */
1575                    public KeyHandler()
1576                    {
1577                    }
1578    
1579                    /**
1580                     * Invoked when a key has been typed. Moves the keyboard focus to the
1581                     * first element whose first letter matches the alphanumeric key pressed
1582                     * by the user. Subsequent same key presses move the keyboard focus to
1583                     * the next object that starts with the same letter.
1584                     *
1585                     * @param e the key typed
1586                     */
1587                    public void keyTyped(KeyEvent e)
1588                    {
1589                    }
1590    
1591                    /**
1592                     * Invoked when a key has been pressed.
1593                     *
1594                     * @param e the key pressed
1595                     */
1596                    public void keyPressed(KeyEvent e)
1597                    {
1598                    }
1599    
1600                    /**
1601                     * Invoked when a key has been released
1602                     *
1603                     * @param e the key released
1604                     */
1605                    public void keyReleased(KeyEvent e)
1606                    {
1607                    }
1608            }// KeyHandler
1609    
1610            /**
1611             * MouseListener is responsible for updating the selevtion based on mouse
1612             * events.
1613             */
1614            public class MouseHandler
1615                            extends MouseAdapter
1616                            implements MouseMotionListener
1617            {
1618                    /**
1619                     * Constructor
1620                     */
1621                    public MouseHandler()
1622                    {
1623                    }
1624    
1625                    /**
1626                     * Invoked when a mouse button has been pressed on a component.
1627                     *
1628                     * @param e is the mouse event that occured
1629                     */
1630                    public void mousePressed(MouseEvent e)
1631                    {
1632                    }
1633    
1634                    /**
1635                     * Invoked when a mouse button is pressed on a component and then
1636                     * dragged. MOUSE_DRAGGED events will continue to be delivered to the
1637                     * component where the drag originated until the mouse button is
1638                     * released (regardless of whether the mouse position is within the
1639                     * bounds of the component).
1640                     *
1641                     * @param e is the mouse event that occured
1642                     */
1643                    public void mouseDragged(MouseEvent e)
1644                    {
1645                    }
1646    
1647                    /**
1648                     * Invoked when the mouse button has been moved on a component (with no
1649                     * buttons no down).
1650                     *
1651                     * @param e the mouse event that occured
1652                     */
1653                    public void mouseMoved(MouseEvent e)
1654                    {
1655                    }
1656    
1657                    /**
1658                     * Invoked when a mouse button has been released on a component.
1659                     *
1660                     * @param e is the mouse event that occured
1661                     */
1662                    public void mouseReleased(MouseEvent e)
1663                    {
1664                    }
1665            }// MouseHandler
1666    
1667            /**
1668             * MouseInputHandler handles passing all mouse events, including mouse
1669             * motion events, until the mouse is released to the destination it is
1670             * constructed with.
1671             */
1672            public class MouseInputHandler
1673                            implements MouseInputListener
1674            {
1675                    /** Source that events are coming from */
1676                    protected Component source;
1677    
1678                    /** Destination that receives all events. */
1679                    protected Component destination;
1680    
1681                    /**
1682                     * Constructor
1683                     *
1684                     * @param source that events are coming from
1685                     * @param destination that receives all events
1686                     * @param event is the event received
1687                     */
1688                    public MouseInputHandler(Component source, Component destination,
1689                                    MouseEvent e)
1690                    {
1691                    }
1692    
1693                    /**
1694                     * Invoked when the mouse button has been clicked (pressed and released)
1695                     * on a component.
1696                     *
1697                     * @param e mouse event that occured
1698                     */
1699                    public void mouseClicked(MouseEvent e)
1700                    {
1701                            Point click = e.getPoint();
1702                            int row = ((int) click.getY() / getRowHeight()) - 1;
1703                        
1704                            if (BasicTreeUI.this.tree.getSelectionModel().getSelectionMode() == treeSelectionModel.SINGLE_TREE_SELECTION)
1705                                    BasicTreeUI.this.tree.addSelectionRow(row);
1706                            else if (BasicTreeUI.this.tree.isRowSelected(row))
1707                                    BasicTreeUI.this.tree.removeSelectionRow(row);
1708                            // FIXME: add in selection for more than 1 row, or an entire
1709                            // path
1710                    }
1711    
1712                    /**
1713                     * Invoked when a mouse button has been pressed on a component.
1714                     *
1715                     * @param e mouse event that occured
1716                     */
1717                    public void mousePressed(MouseEvent e)
1718                    {
1719                    }
1720    
1721                    /**
1722                     * Invoked when a mouse button has been released on a component.
1723                     *
1724                     * @param e mouse event that occured
1725                     */
1726                    public void mouseReleased(MouseEvent e)
1727                    {
1728                    }
1729    
1730                    /**
1731                     * Invoked when the mouse enters a component.
1732                     *
1733                     * @param e mouse event that occured
1734                     */
1735                    public void mouseEntered(MouseEvent e)
1736                    {
1737                    }
1738    
1739                    /**
1740                     * Invoked when the mouse exits a component.
1741                     *
1742                     * @param e mouse event that occured
1743                     */
1744                    public void mouseExited(MouseEvent e)
1745                    {
1746                    }
1747    
1748                    /**
1749                     * Invoked when a mouse button is pressed on a component and then
1750                     * dragged. MOUSE_DRAGGED events will continue to be delivered to the
1751                     * component where the drag originated until the mouse button is
1752                     * released (regardless of whether the mouse position is within the
1753                     * bounds of the component).
1754                     *
1755                     * @param e mouse event that occured
1756                     */
1757                    public void mouseDragged(MouseEvent e)
1758                    {
1759                    }
1760    
1761                    /**
1762                     * Invoked when the mouse cursor has been moved onto a component but no
1763                     * buttons have been pushed.
1764                     *
1765                     * @param e mouse event that occured
1766                     */
1767                    public void mouseMoved(MouseEvent e)
1768                    {
1769                    }
1770    
1771                    /**
1772                     * Removes event from the source
1773                     */
1774                    protected void removeFromSource()
1775                    {
1776                    }
1777            }// MouseInputHandler
1778    
1779            /**
1780             * Class responsible for getting size of node, method is forwarded to
1781             * BasicTreeUI method. X location does not include insets, that is handled
1782             * in getPathBounds.
1783             */
1784            public class NodeDimensionsHandler
1785                            extends AbstractLayoutCache.NodeDimensions
1786            {
1787                    /**
1788                     * Constructor
1789                     */
1790                    public NodeDimensionsHandler()
1791                    {
1792                    }
1793    
1794                    /**
1795                     * Responsible for getting the size of a particular node.
1796                     *
1797                     * @param value the value to be represented
1798                     * @param row row being queried
1799                     * @param depth the depth of the row
1800                     * @param expanded true if row is expanded
1801                     * @param size a Rectangle containing the size needed to represent value
1802                     * @return containing the node dimensions, or null if node has no
1803                     *         dimension
1804                     */
1805                    public Rectangle getNodeDimensions(Object value, int row, int depth,
1806                                    boolean expanded, Rectangle size)
1807                    {
1808                            return null;
1809                    }
1810    
1811                    /**
1812                     * Returns the amount to indent the given row
1813                     *
1814                     * @return amount to indent the given row.
1815                     */
1816                    protected int getRowX(int row, int depth)
1817                    {
1818                            return 0;
1819                    }
1820            }// NodeDimensionsHandler
1821    
1822            /**
1823             * PropertyChangeListener for the tree. Updates the appropriate varaible, or
1824             * TreeState, based on what changes.
1825             */
1826            public class PropertyChangeHandler
1827                            implements PropertyChangeListener
1828            {
1829    
1830                    /**
1831                     * Constructor
1832                     */
1833                    public PropertyChangeHandler()
1834                    {
1835                    }
1836    
1837                    /**
1838                     * This method gets called when a bound property is changed.
1839                     *
1840                     * @param event A PropertyChangeEvent object describing the event source
1841                     *        and the property that has changed.
1842                     */
1843                    public void propertyChange(PropertyChangeEvent event)
1844                    {
1845                    }
1846            }// PropertyChangeHandler
1847    
1848            /**
1849             * Listener on the TreeSelectionModel, resets the row selection if any of
1850             * the properties of the model change.
1851             */
1852            public class SelectionModelPropertyChangeHandler
1853                            implements PropertyChangeListener
1854            {
1855    
1856                    /**
1857                     * Constructor
1858                     */
1859                    public SelectionModelPropertyChangeHandler()
1860                    {
1861                    }
1862    
1863                    /**
1864                     * This method gets called when a bound property is changed.
1865                     *
1866                     * @param event A PropertyChangeEvent object describing the event source
1867                     *        and the property that has changed.
1868                     */
1869                    public void propertyChange(PropertyChangeEvent event)
1870                    {
1871                    }
1872            }// SelectionModelPropertyChangeHandler
1873    
1874            /**
1875             * ActionListener that invokes cancelEditing when action performed.
1876             */
1877            public class TreeCancelEditingAction
1878                            extends AbstractAction
1879            {
1880    
1881                    /**
1882                     * Constructor
1883                     */
1884                    public TreeCancelEditingAction()
1885                    {
1886                    }
1887    
1888                    /**
1889                     * Invoked when an action occurs.
1890                     *
1891                     * @param e event that occured
1892                     */
1893                    public void actionPerformed(ActionEvent e)
1894                    {
1895                    }
1896    
1897                    /**
1898                     * Returns true if the action is enabled.
1899                     *
1900                     * @return true if the action is enabled, false otherwise
1901                     */
1902                    public boolean isEnabled()
1903                    {
1904                            return false;
1905                    }
1906            }// TreeCancelEditingAction
1907    
1908            /**
1909             * Updates the TreeState in response to nodes expanding/collapsing.
1910             */
1911            public class TreeExpansionHandler
1912                            implements TreeExpansionListener
1913            {
1914    
1915                    /**
1916                     * Constructor
1917                     */
1918                    public TreeExpansionHandler()
1919                    {
1920                    }
1921    
1922                    /**
1923                     * Called whenever an item in the tree has been expanded.
1924                     *
1925                     * @param event is the event that occured
1926                     */
1927                    public void treeExpanded(TreeExpansionEvent event)
1928                    {
1929                    }
1930    
1931                    /**
1932                     * Called whenever an item in the tree has been collapsed.
1933                     *
1934                     * @param event is the event that occured
1935                     */
1936                    public void treeCollapsed(TreeExpansionEvent event)
1937                    {
1938                    }
1939            }// TreeExpansionHandler
1940    
1941            /**
1942             * TreeHomeAction is used to handle end/home actions. Scrolls either the
1943             * first or last cell to be visible based on direction.
1944             */
1945            public class TreeHomeAction
1946                            extends AbstractAction
1947            {
1948    
1949                    /** direction is either home or end */
1950                    protected int direction;
1951    
1952                    /**
1953                     * Constructor
1954                     *
1955                     * @param direction - it is home or end
1956                     * @param name is the name of the direction
1957                     */
1958                    public TreeHomeAction(int direction, String name)
1959                    {
1960                    }
1961    
1962                    /**
1963                     * Invoked when an action occurs.
1964                     *
1965                     * @param e is the event that occured
1966                     */
1967                    public void actionPerformed(ActionEvent e)
1968                    {
1969                    }
1970    
1971                    /**
1972                     * Returns true if the action is enabled.
1973                     *
1974                     * @return true if the action is enabled.
1975                     */
1976                    public boolean isEnabled()
1977                    {
1978                            return false;
1979                    }
1980            }// TreeHomeAction
1981    
1982            /**
1983             * TreeIncrementAction is used to handle up/down actions. Selection is moved
1984             * up or down based on direction.
1985             */
1986            public class TreeIncrementAction
1987                            extends AbstractAction
1988            {
1989    
1990                    /** Specifies the direction to adjust the selection by. */
1991                    protected int direction;
1992    
1993                    /**
1994                     * Constructor
1995                     *
1996                     * @param direction up or down
1997                     * @param name is the name of the direction
1998                     */
1999                    public TreeIncrementAction(int direction, String name)
2000                    {
2001                    }
2002    
2003                    /**
2004                     * Invoked when an action occurs.
2005                     *
2006                     * @param e is the event that occured
2007                     */
2008                    public void actionPerformed(ActionEvent e)
2009                    {
2010                    }
2011    
2012                    /**
2013                     * Returns true if the action is enabled.
2014                     *
2015                     * @return true if the action is enabled.
2016                     */
2017                    public boolean isEnabled()
2018                    {
2019                            return false;
2020                    }
2021            }// TreeIncrementAction
2022    
2023            /**
2024             * Forwards all TreeModel events to the TreeState.
2025             */
2026            public class TreeModelHandler
2027                            implements TreeModelListener
2028            {
2029                    /**
2030                     * Constructor
2031                     */
2032                    public TreeModelHandler()
2033                    {
2034                    }
2035    
2036                    /**
2037                     * Invoked after a node (or a set of siblings) has changed in some way.
2038                     * The node(s) have not changed locations in the tree or altered their
2039                     * children arrays, but other attributes have changed and may affect
2040                     * presentation. Example: the name of a file has changed, but it is in
2041                     * the same location in the file system. To indicate the root has
2042                     * changed, childIndices and children will be null. Use e.getPath() to
2043                     * get the parent of the changed node(s). e.getChildIndices() returns
2044                     * the index(es) of the changed node(s).
2045                     *
2046                     * @param e is the event that occured
2047                     */
2048                    public void treeNodesChanged(TreeModelEvent e)
2049                    {
2050                    }
2051    
2052                    /**
2053                     * Invoked after nodes have been inserted into the tree. Use e.getPath()
2054                     * to get the parent of the new node(s). e.getChildIndices() returns the
2055                     * index(es) of the new node(s) in ascending order.
2056                     *
2057                     * @param e is the event that occured
2058                     */
2059                    public void treeNodesInserted(TreeModelEvent e)
2060                    {
2061                    }
2062    
2063                    /**
2064                     * Invoked after nodes have been removed from the tree. Note that if a
2065                     * subtree is removed from the tree, this method may only be invoked
2066                     * once for the root of the removed subtree, not once for each
2067                     * individual set of siblings removed. Use e.getPath() to get the former
2068                     * parent of the deleted node(s). e.getChildIndices() returns, in
2069                     * ascending order, the index(es) the node(s) had before being deleted.
2070                     *
2071                     * @param e is the event that occured
2072                     */
2073                    public void treeNodesRemoved(TreeModelEvent e)
2074                    {
2075                    }
2076    
2077                    /**
2078                     * Invoked after the tree has drastically changed structure from a given
2079                     * node down. If the path returned by e.getPath() is of length one and
2080                     * the first element does not identify the current root node the first
2081                     * element should become the new root of the tree. Use e.getPath() to
2082                     * get the path to the node. e.getChildIndices() returns null.
2083                     *
2084                     * @param e is the event that occured
2085                     */
2086                    public void treeStructureChanged(TreeModelEvent e)
2087                    {
2088                    }
2089            }// TreeModelHandler
2090    
2091            /**
2092             * TreePageAction handles page up and page down events.
2093             */
2094            public class TreePageAction
2095                            extends AbstractAction
2096            {
2097                    /** Specifies the direction to adjust the selection by. */
2098                    protected int direction;
2099    
2100                    /**
2101                     * Constructor
2102                     *
2103                     * @param direction up or down
2104                     * @param name is the name of the direction
2105                     */
2106                    public TreePageAction(int direction, String name)
2107                    {
2108                    }
2109    
2110                    /**
2111                     * Invoked when an action occurs.
2112                     *
2113                     * @param e is the event that occured
2114                     */
2115                    public void actionPerformed(ActionEvent e)
2116                    {
2117                    }
2118    
2119                    /**
2120                     * Returns true if the action is enabled.
2121                     *
2122                     * @return true if the action is enabled.
2123                     */
2124                    public boolean isEnabled()
2125                    {
2126                            return false;
2127                    }
2128            }// TreePageAction
2129    
2130            /**
2131             * Listens for changes in the selection model and updates the display
2132             * accordingly.
2133             */
2134            public class TreeSelectionHandler
2135                            implements TreeSelectionListener
2136            {
2137                    /**
2138                     * Constructor
2139                     */
2140                    public TreeSelectionHandler()
2141                    {
2142                    }
2143    
2144                    /**
2145                     * Messaged when the selection changes in the tree we're displaying for.
2146                     * Stops editing, messages super and displays the changed paths.
2147                     *
2148                     * @param event the event that characterizes the change.
2149                     */
2150                    public void valueChanged(TreeSelectionEvent event)
2151                    {
2152                    }
2153            }// TreeSelectionHandler
2154    
2155            /**
2156             * For the first selected row expandedness will be toggled.
2157             */
2158            public class TreeToggleAction
2159                            extends AbstractAction
2160            {
2161                    /**
2162                     * Constructor
2163                     *
2164                     * @param name is the name of <code>Action</code> field
2165                     */
2166                    public TreeToggleAction(String name)
2167                    {
2168                    }
2169    
2170                    /**
2171                     * Invoked when an action occurs.
2172                     *
2173                     * @param e the event that occured
2174                     */
2175                    public void actionPerformed(ActionEvent e)
2176                    {
2177                    }
2178    
2179                    /**
2180                     * Returns true if the action is enabled.
2181                     *
2182                     * @return true if the action is enabled, false otherwise
2183                     */
2184                    public boolean isEnabled()
2185                    {
2186                            return false;
2187                    }
2188            } // TreeToggleAction
2189    
2190            /**
2191             * TreeTraverseAction is the action used for left/right keys. Will toggle
2192             * the expandedness of a node, as well as potentially incrementing the
2193             * selection.
2194             */
2195            public class TreeTraverseAction
2196                            extends AbstractAction
2197            {
2198                    /**
2199                     * Determines direction to traverse, 1 means expand, -1 means collapse.
2200                     */
2201                    protected int direction;
2202    
2203                    /**
2204                     * Constructor
2205                     *
2206                     * @param direction to traverse
2207                     * @param name is the name of the direction
2208                     */
2209                    public TreeTraverseAction(int direction, String name)
2210                    {
2211                    }
2212    
2213                    /**
2214                     * Invoked when an action occurs.
2215                     *
2216                     * @param e the event that occured
2217                     */
2218                    public void actionPerformed(ActionEvent e)
2219                    {
2220                    }
2221    
2222                    /**
2223                     * Returns true if the action is enabled.
2224                     *
2225                     * @return true if the action is enabled, false otherwise
2226                     */
2227                    public boolean isEnabled()
2228                    {
2229                            return false;
2230                    }
2231            } // TreeTraverseAction
2232    
2233            /* * HELPER METHODS FOR PAINTING * */
2234    
2235            private void paintLeaf(Graphics g, int x, int y, JTree tree, Object leaf)
2236            {
2237                    Component c = tree.getCellRenderer().getTreeCellRendererComponent(tree,
2238                                    leaf, false, false, true, 0, false);
2239                    g.translate(x, y);
2240                    c.paint(g);
2241                    g.translate(-x, -y);
2242            }
2243    
2244            private void paintNonLeaf(Graphics g, int x, int y, JTree tree,
2245                            Object nonLeaf)
2246            {
2247                    Component c = tree.getCellRenderer().getTreeCellRendererComponent(tree,
2248                                    nonLeaf, false, false, false, 0, false);
2249                    g.translate(x, y);
2250                    c.paint(g);
2251                    g.translate(-x, -y);
2252            }
2253    
2254            private int paintRecursive(Graphics g, int indentation, int descent,
2255                            int childNumber, int depth, JTree tree, TreeModel mod, Object curr)
2256            {
2257                    Rectangle clip = g.getClipBounds();
2258                    if (indentation > clip.x + clip.width + rightChildIndent
2259                                    || descent > clip.y + clip.height + getRowHeight())
2260                            return descent;
2261    
2262                    int halfHeight = getRowHeight() / 2;
2263                    int halfWidth = rightChildIndent / 2;
2264                    int y0 = descent + halfHeight;
2265    
2266                    if (mod.isLeaf(curr))
2267                    {
2268                            paintLeaf(g, indentation, descent, tree, curr);
2269                            descent += getRowHeight();
2270                    } else
2271                    {
2272                            if (depth > 0 || tree.isRootVisible())
2273                            {
2274                                    paintNonLeaf(g, indentation, descent, tree, curr);
2275                                    descent += getRowHeight();
2276                                    y0 += halfHeight;
2277                            }
2278                            int max = mod.getChildCount(curr);
2279                            for (int i = 0; i < max; ++i)
2280                            {
2281                                    g.setColor(getHashColor());
2282                                    g.drawLine(indentation + halfWidth, descent + halfHeight,
2283                                                    indentation + rightChildIndent, descent + halfHeight);
2284                                    descent = paintRecursive(g, indentation + rightChildIndent,
2285                                                    descent, i, depth + 1, tree, mod, mod.getChild(curr, i));
2286                            }
2287                    }
2288    
2289                    int y1 = descent - halfHeight;
2290                    if (y0 != y1)
2291                    {
2292                            g.setColor(getHashColor());
2293                            g
2294                                            .drawLine(indentation + halfWidth, y0, indentation
2295                                                            + halfWidth, y1);
2296                    }
2297    
2298                    return descent;
2299            }
2300    
2301    } // BasicTreeUI

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10

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