2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java
.awt
.Dimension
;
42 import java
.awt
.Rectangle
;
43 import java
.util
.Enumeration
;
44 import java
.util
.Hashtable
;
45 import java
.util
.Iterator
;
46 import java
.util
.Vector
;
48 import javax
.accessibility
.Accessible
;
49 import javax
.accessibility
.AccessibleContext
;
50 import javax
.swing
.event
.TreeExpansionEvent
;
51 import javax
.swing
.event
.TreeExpansionListener
;
52 import javax
.swing
.event
.TreeSelectionEvent
;
53 import javax
.swing
.event
.TreeSelectionListener
;
54 import javax
.swing
.event
.TreeWillExpandListener
;
55 import javax
.swing
.plaf
.TreeUI
;
56 import javax
.swing
.tree
.DefaultMutableTreeNode
;
57 import javax
.swing
.tree
.DefaultTreeCellRenderer
;
58 import javax
.swing
.tree
.DefaultTreeModel
;
59 import javax
.swing
.tree
.ExpandVetoException
;
60 import javax
.swing
.tree
.TreeCellEditor
;
61 import javax
.swing
.tree
.TreeCellRenderer
;
62 import javax
.swing
.tree
.TreeModel
;
63 import javax
.swing
.tree
.TreeNode
;
64 import javax
.swing
.tree
.TreePath
;
65 import javax
.swing
.tree
.TreeSelectionModel
;
68 public class JTree
extends JComponent
69 implements Scrollable
, Accessible
71 private static final long serialVersionUID
= 7559816092864483649L;
73 public static final String CELL_EDITOR_PROPERTY
= "cellEditor";
74 public static final String CELL_RENDERER_PROPERTY
= "cellRenderer";
75 public static final String EDITABLE_PROPERTY
= "editable";
76 public static final String INVOKES_STOP_CELL_EDITING_PROPERTY
= "invokesStopCellEditing";
77 public static final String LARGE_MODEL_PROPERTY
= "largeModel";
78 public static final String ROOT_VISIBLE_PROPERTY
= "rootVisible";
79 public static final String ROW_HEIGHT_PROPERTY
= "rowHeight";
80 public static final String SCROLLS_ON_EXPAND_PROPERTY
= "scrollsOnExpand";
81 public static final String SELECTION_MODEL_PROPERTY
= "selectionModel";
82 public static final String SHOWS_ROOT_HANDLES_PROPERTY
= "showsRootHandles";
83 public static final String TOGGLE_CLICK_COUNT_PROPERTY
= "toggleClickCount";
84 public static final String TREE_MODEL_PROPERTY
= "model";
85 public static final String VISIBLE_ROW_COUNT_PROPERTY
= "visibleRowCount";
88 public static final String ANCHOR_SELECTION_PATH_PROPERTY
= "anchorSelectionPath";
90 public static final String LEAD_SELECTION_PATH_PROPERTY
= "leadSelectionPath";
92 public static final String EXPANDS_SELECTED_PATHS_PROPERTY
= "expandsSelectedPaths";
94 private static final Object EXPANDED
= new Object();
95 private static final Object COLLAPSED
= new Object();
97 private boolean dragEnabled
;
98 private boolean expandsSelectedPaths
;
99 private TreePath anchorSelectionPath
;
100 private TreePath leadSelectionPath
;
103 * This contains the state of all nodes in the tree. Al/ entries map the
104 * TreePath of a note to to its state. Valid states are EXPANDED and
105 * COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.
107 private Hashtable nodeStates
;
109 protected transient TreeCellEditor cellEditor
;
110 protected transient TreeCellRenderer cellRenderer
;
111 protected boolean editable
;
112 protected boolean invokesStopCellEditing
;
113 protected boolean largeModel
;
114 protected boolean rootVisible
;
115 protected int rowHeight
;
116 protected boolean scrollsOnExpand
;
117 protected transient TreeSelectionModel selectionModel
;
118 protected boolean showsRootHandles
;
119 protected int toggleClickCount
;
120 protected transient TreeModel treeModel
;
121 protected int visibleRowCount
;
124 * Creates a new <code>JTree</code> object.
128 this(createTreeModel(null));
132 * Creates a new <code>JTree</code> object.
134 * @param value the initial nodes in the tree
136 public JTree(Hashtable value
)
138 this(createTreeModel(value
));
142 * Creates a new <code>JTree</code> object.
144 * @param value the initial nodes in the tree
146 public JTree(Object
[] value
)
148 this(createTreeModel(value
));
152 * Creates a new <code>JTree</code> object.
154 * @param model the model to use
156 public JTree(TreeModel model
)
159 setCellRenderer(new DefaultTreeCellRenderer());
164 * Creates a new <code>JTree</code> object.
166 * @param root the root node
168 public JTree(TreeNode root
)
174 * Creates a new <code>JTree</code> object.
176 * @param root the root node
177 * @param asksAllowChildren if false, all nodes without children are leaf nodes.
178 * If true, only nodes that do not allow children are leaf nodes.
180 public JTree(TreeNode root
, boolean asksAllowChildren
)
182 this(new DefaultTreeModel(root
, asksAllowChildren
));
186 * Creates a new <code>JTree</code> object.
188 * @param value the initial nodes in the tree
190 public JTree(Vector value
)
192 this(createTreeModel(value
));
195 public static class DynamicUtilTreeNode
196 extends DefaultMutableTreeNode
198 protected Object childValue
;
199 protected boolean loadedChildren
;
202 * Currently not set or used by this class.
203 * It might be set and used in later versions of this class.
205 protected boolean hasChildren
;
207 public DynamicUtilTreeNode(Object value
,
211 childValue
= children
;
212 loadedChildren
= false;
215 public int getChildCount()
218 return super.getChildCount();
221 protected void loadChildren()
225 createChildren(this, childValue
);
226 loadedChildren
= true;
230 public Enumeration
children()
233 return super.children();
236 public boolean isLeaf()
238 return (childValue
== null ||
239 !(childValue
instanceof Hashtable
240 || childValue
instanceof Vector
241 || childValue
.getClass().isArray()));
244 public static void createChildren(DefaultMutableTreeNode parent
,
247 if (children
instanceof Hashtable
)
249 Hashtable tab
= (Hashtable
) children
;
250 Enumeration e
= tab
.keys();
251 while (e
.hasMoreElements())
253 Object key
= e
.nextElement();
254 Object val
= tab
.get(key
);
255 parent
.add(new DynamicUtilTreeNode(key
, val
));
258 else if (children
instanceof Vector
)
260 Iterator i
= ((Vector
)children
).iterator();
264 parent
.add(new DynamicUtilTreeNode(n
,n
));
267 else if (children
.getClass().isArray())
269 Object
[] arr
= (Object
[]) children
;
270 for (int i
= 0; i
< arr
.length
; ++i
)
271 parent
.add(new DynamicUtilTreeNode(arr
[i
], arr
[i
]));
276 public int getRowForPath(TreePath path
)
281 return ui
.getRowForPath(this, path
);
286 public TreePath
getPathForRow(int row
)
289 return ui
!= null ? ui
.getPathForRow(this, row
) : null;
292 protected TreePath
[] getPathBetweenRows(int index0
, int index1
)
299 int minIndex
= Math
.min(index0
, index1
);
300 int maxIndex
= Math
.max(index0
, index1
);
301 TreePath
[] paths
= new TreePath
[maxIndex
- minIndex
+ 1];
303 for (int i
= minIndex
; i
<= maxIndex
; ++i
)
304 paths
[i
- minIndex
] = ui
.getPathForRow(this, i
);
310 * Creates a new <code>TreeModel</code> object.
312 * @param value the values stored in the model
314 protected static TreeModel
createTreeModel(Object value
)
316 return new DefaultTreeModel(new DynamicUtilTreeNode(value
, value
));
320 * Return the UI associated with this <code>JTree</code> object.
322 * @return the associated <code>TreeUI</code> object
324 public TreeUI
getUI()
330 * Sets the UI associated with this <code>JTree</code> object.
332 * @param ui the <code>TreeUI</code> to associate
334 public void setUI(TreeUI ui
)
340 * This method resets the UI used to the Look and Feel defaults..
342 public void updateUI()
344 setUI((TreeUI
) UIManager
.getUI(this));
350 * This method returns the String ID of the UI class of Separator.
352 * @return The UI class' String ID.
354 public String
getUIClassID()
360 * Gets the AccessibleContext associated with this <code>JToggleButton</code>.
362 * @return the associated context
364 public AccessibleContext
getAccessibleContext()
370 * Returns the preferred viewport size..
372 * @return the preferred size
374 public Dimension
getPreferredScrollableViewportSize()
379 public int getScrollableUnitIncrement(Rectangle visibleRect
,
380 int orientation
, int direction
)
385 public int getScrollableBlockIncrement(Rectangle visibleRect
,
386 int orientation
, int direction
)
391 public boolean getScrollableTracksViewportWidth()
396 public boolean getScrollableTracksViewportHeight()
402 * Adds a <code>TreeExpansionListener</code> object to the tree.
404 * @param listener the listener to add
406 public void addTreeExpansionListener(TreeExpansionListener listener
)
408 listenerList
.add(TreeExpansionListener
.class, listener
);
412 * Removes a <code>TreeExpansionListener</code> object from the tree.
414 * @param listener the listener to remove
416 public void removeTreeExpansionListener(TreeExpansionListener listener
)
418 listenerList
.remove(TreeExpansionListener
.class, listener
);
422 * Returns all added <code>TreeExpansionListener</code> objects.
424 * @return an array of listeners
426 public TreeExpansionListener
[] getTreeExpansionListeners()
428 return (TreeExpansionListener
[]) getListeners(TreeExpansionListener
.class);
432 * Notifies all listeners that the tree was collapsed.
434 * @param path the path to the node that was collapsed
436 public void fireTreeCollapsed(TreePath path
)
438 TreeExpansionEvent event
= new TreeExpansionEvent(this, path
);
439 TreeExpansionListener
[] listeners
= getTreeExpansionListeners();
441 for (int index
= 0; index
< listeners
.length
; ++index
)
442 listeners
[index
].treeCollapsed(event
);
446 * Notifies all listeners that the tree was expanded.
448 * @param path the path to the node that was expanded
450 public void fireTreeExpanded(TreePath path
)
452 TreeExpansionEvent event
= new TreeExpansionEvent(this, path
);
453 TreeExpansionListener
[] listeners
= getTreeExpansionListeners();
455 for (int index
= 0; index
< listeners
.length
; ++index
)
456 listeners
[index
].treeExpanded(event
);
460 * Adds a <code>TreeSelctionListener</code> object to the tree.
462 * @param listener the listener to add
464 public void addTreeSelectionListener(TreeSelectionListener listener
)
466 listenerList
.add(TreeSelectionListener
.class, listener
);
470 * Removes a <code>TreeSelectionListener</code> object from the tree.
472 * @param listener the listener to remove
474 public void removeTreeSelectionListener(TreeSelectionListener listener
)
476 listenerList
.remove(TreeSelectionListener
.class, listener
);
480 * Returns all added <code>TreeSelectionListener</code> objects.
482 * @return an array of listeners
484 public TreeSelectionListener
[] getTreeSelectionListeners()
486 return (TreeSelectionListener
[]) getListeners(TreeSelectionListener
.class);
490 * Notifies all listeners when the selection of the tree changed.
492 * @param event the event to send
494 protected void fireValueChanged(TreeSelectionEvent event
)
496 TreeSelectionListener
[] listeners
= getTreeSelectionListeners();
498 for (int index
= 0; index
< listeners
.length
; ++index
)
499 listeners
[index
].valueChanged(event
);
503 * Adds a <code>TreeWillExpandListener</code> object to the tree.
505 * @param listener the listener to add
507 public void addTreeWillExpandListener(TreeWillExpandListener listener
)
509 listenerList
.add(TreeWillExpandListener
.class, listener
);
513 * Removes a <code>TreeWillExpandListener</code> object from the tree.
515 * @param listener the listener to remove
517 public void removeTreeWillExpandListener(TreeWillExpandListener listener
)
519 listenerList
.remove(TreeWillExpandListener
.class, listener
);
523 * Returns all added <code>TreeWillExpandListener</code> objects.
525 * @return an array of listeners
527 public TreeWillExpandListener
[] getTreeWillExpandListeners()
529 return (TreeWillExpandListener
[]) getListeners(TreeWillExpandListener
.class);
533 * Notifies all listeners that the tree will collapse.
535 * @param path the path to the node that will collapse
537 public void fireTreeWillCollapse(TreePath path
)
538 throws ExpandVetoException
540 TreeExpansionEvent event
= new TreeExpansionEvent(this, path
);
541 TreeWillExpandListener
[] listeners
= getTreeWillExpandListeners();
543 for (int index
= 0; index
< listeners
.length
; ++index
)
544 listeners
[index
].treeWillCollapse(event
);
548 * Notifies all listeners that the tree will expand.
550 * @param path the path to the node that will expand
552 public void fireTreeWillExpand(TreePath path
)
553 throws ExpandVetoException
555 TreeExpansionEvent event
= new TreeExpansionEvent(this, path
);
556 TreeWillExpandListener
[] listeners
= getTreeWillExpandListeners();
558 for (int index
= 0; index
< listeners
.length
; ++index
)
559 listeners
[index
].treeWillExpand(event
);
563 * Returns the model of this <code>JTree</code> object.
565 * @return the associated <code>TreeModel</code>
567 public TreeModel
getModel()
573 * Sets the model to use in <code>JTree</code>.
575 * @param model the <code>TreeModel</code> to use
577 public void setModel(TreeModel model
)
579 if (treeModel
== model
)
582 TreeModel oldValue
= treeModel
;
584 firePropertyChange(TREE_MODEL_PROPERTY
, oldValue
, model
);
588 * Checks if this <code>JTree</code> object is editable.
590 * @return <code>true</code> if this tree object is editable,
591 * <code>false</code> otherwise
593 public boolean isEditable()
599 * Sets the <code>editable</code> property.
601 * @param flag <code>true</code> to make this tree object editable,
602 * <code>false</code> otherwise
604 public void setEditable(boolean flag
)
606 if (editable
== flag
)
609 boolean oldValue
= editable
;
611 firePropertyChange(EDITABLE_PROPERTY
, oldValue
, editable
);
615 * Checks if the root element is visible.
617 * @return <code>true</code> if the root element is visible,
618 * <code>false</code> otherwise
620 public boolean isRootVisible()
625 public void setRootVisible(boolean flag
)
627 if (rootVisible
== flag
)
630 boolean oldValue
= rootVisible
;
632 firePropertyChange(ROOT_VISIBLE_PROPERTY
, oldValue
, flag
);
635 public boolean getShowsRootHandles()
637 return showsRootHandles
;
640 public void setShowsRootHandles(boolean flag
)
642 if (showsRootHandles
== flag
)
645 boolean oldValue
= showsRootHandles
;
646 showsRootHandles
= flag
;
647 firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY
, oldValue
, flag
);
650 public TreeCellEditor
getCellEditor()
655 public void setCellEditor(TreeCellEditor editor
)
657 if (cellEditor
== editor
)
660 TreeCellEditor oldValue
= cellEditor
;
662 firePropertyChange(CELL_EDITOR_PROPERTY
, oldValue
, editor
);
665 public TreeCellRenderer
getCellRenderer()
670 public void setCellRenderer(TreeCellRenderer newRenderer
)
672 if (cellRenderer
== newRenderer
)
675 TreeCellRenderer oldValue
= cellRenderer
;
676 cellRenderer
= newRenderer
;
677 firePropertyChange(CELL_RENDERER_PROPERTY
, oldValue
, newRenderer
);
680 public TreeSelectionModel
getSelectionModel()
682 return selectionModel
;
685 public void setSelectionModel(TreeSelectionModel model
)
687 if (selectionModel
== model
)
690 TreeSelectionModel oldValue
= selectionModel
;
691 selectionModel
= model
;
692 firePropertyChange(SELECTION_MODEL_PROPERTY
, oldValue
, model
);
695 public int getVisibleRowCount()
697 return visibleRowCount
;
700 public void setVisibleRowCount(int rows
)
702 if (visibleRowCount
== rows
)
705 int oldValue
= visibleRowCount
;
706 visibleRowCount
= rows
;
707 firePropertyChange(VISIBLE_ROW_COUNT_PROPERTY
, oldValue
, rows
);
710 public boolean isLargeModel()
715 public void setLargeModel(boolean large
)
717 if (largeModel
== large
)
720 boolean oldValue
= largeModel
;
722 firePropertyChange(LARGE_MODEL_PROPERTY
, oldValue
, large
);
725 public int getRowHeight()
730 public void setRowHeight(int height
)
732 if (rowHeight
== height
)
735 int oldValue
= rowHeight
;
737 firePropertyChange(ROW_HEIGHT_PROPERTY
, oldValue
, height
);
740 public boolean isFixedRowHeight()
742 return rowHeight
> 0;
745 public boolean getInvokesStopCellEditing()
747 return invokesStopCellEditing
;
750 public void setInvokesStopCellEditing(boolean invoke
)
752 if (invokesStopCellEditing
== invoke
)
755 boolean oldValue
= invokesStopCellEditing
;
756 invokesStopCellEditing
= invoke
;
757 firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY
, oldValue
, invoke
);
763 public int getToggleClickCount()
765 return toggleClickCount
;
771 public void setToggleClickCount(int count
)
773 if (toggleClickCount
== count
)
776 int oldValue
= toggleClickCount
;
777 toggleClickCount
= count
;
778 firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY
, oldValue
, count
);
781 public void scrollPathToVisible(TreePath path
)
786 Rectangle rect
= getPathBounds(path
);
791 scrollRectToVisible(rect
);
794 public void scrollRowToVisible(int row
)
796 scrollPathToVisible(getPathForRow(row
));
799 public boolean getScrollsOnExpand()
801 return scrollsOnExpand
;
804 public void setScrollsOnExpand(boolean scroll
)
806 if (scrollsOnExpand
== scroll
)
809 boolean oldValue
= scrollsOnExpand
;
810 scrollsOnExpand
= scroll
;
811 firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY
, oldValue
, scroll
);
814 public void setSelectionPath(TreePath path
)
816 selectionModel
.setSelectionPath(path
);
819 public void setSelectionPaths(TreePath
[] paths
)
821 selectionModel
.setSelectionPaths(paths
);
824 public void setSelectionRow(int row
)
826 TreePath path
= getPathForRow(row
);
829 selectionModel
.setSelectionPath(path
);
832 public void setSelectionRows(int[] rows
)
834 // Make sure we have an UI so getPathForRow() does not return null.
835 if (rows
== null || getUI() == null)
838 TreePath
[] paths
= new TreePath
[rows
.length
];
840 for (int i
= rows
.length
- 1; i
>= 0; --i
)
841 paths
[i
] = getPathForRow(rows
[i
]);
843 setSelectionPaths(paths
);
846 public void setSelectionInterval(int index0
, int index1
)
848 TreePath
[] paths
= getPathBetweenRows(index0
, index1
);
851 setSelectionPaths(paths
);
854 public void addSelectionPath(TreePath path
)
856 selectionModel
.addSelectionPath(path
);
859 public void addSelectionPaths(TreePath
[] paths
)
861 selectionModel
.addSelectionPaths(paths
);
864 public void addSelectionRow(int row
)
866 TreePath path
= getPathForRow(row
);
869 selectionModel
.addSelectionPath(path
);
872 public void addSelectionRows(int[] rows
)
874 // Make sure we have an UI so getPathForRow() does not return null.
875 if (rows
== null || getUI() == null)
878 TreePath
[] paths
= new TreePath
[rows
.length
];
880 for (int i
= rows
.length
- 1; i
>= 0; --i
)
881 paths
[i
] = getPathForRow(rows
[i
]);
883 addSelectionPaths(paths
);
886 public void addSelectionInterval(int index0
, int index1
)
888 TreePath
[] paths
= getPathBetweenRows(index0
, index1
);
891 addSelectionPaths(paths
);
894 public void removeSelectionPath(TreePath path
)
896 selectionModel
.removeSelectionPath(path
);
899 public void removeSelectionPaths(TreePath
[] paths
)
901 selectionModel
.removeSelectionPaths(paths
);
904 public void removeSelectionRow(int row
)
906 TreePath path
= getPathForRow(row
);
909 selectionModel
.removeSelectionPath(path
);
912 public void removeSelectionRows(int[] rows
)
914 // Make sure we have an UI so getPathForRow() does not return null.
915 if (rows
== null || getUI() == null)
918 TreePath
[] paths
= new TreePath
[rows
.length
];
920 for (int i
= rows
.length
- 1; i
>= 0; --i
)
921 paths
[i
] = getPathForRow(rows
[i
]);
923 removeSelectionPaths(paths
);
926 public void removeSelectionInterval(int index0
, int index1
)
928 TreePath
[] paths
= getPathBetweenRows(index0
, index1
);
931 removeSelectionPaths(paths
);
934 public void clearSelection()
936 selectionModel
.clearSelection();
939 public TreePath
getLeadSelectionPath()
941 return leadSelectionPath
;
947 public void setLeadSelectionPath(TreePath path
)
949 if (leadSelectionPath
== path
)
952 TreePath oldValue
= leadSelectionPath
;
953 leadSelectionPath
= path
;
954 firePropertyChange(LEAD_SELECTION_PATH_PROPERTY
, oldValue
, path
);
960 public TreePath
getAnchorSelectionPath()
962 return anchorSelectionPath
;
968 public void setAnchorSelectionPath(TreePath path
)
970 if (anchorSelectionPath
== path
)
973 TreePath oldValue
= anchorSelectionPath
;
974 anchorSelectionPath
= path
;
975 firePropertyChange(ANCHOR_SELECTION_PATH_PROPERTY
, oldValue
, path
);
978 public int getLeadSelectionRow()
980 return selectionModel
.getLeadSelectionRow();
983 public int getMaxSelectionRow()
985 return selectionModel
.getMaxSelectionRow();
988 public int getMinSelectionRow()
990 return selectionModel
.getMinSelectionRow();
993 public int getSelectionCount()
995 return selectionModel
.getSelectionCount();
998 public TreePath
getSelectionPath()
1000 return selectionModel
.getSelectionPath();
1003 public TreePath
[] getSelectionPaths()
1005 return selectionModel
.getSelectionPaths();
1008 public int[] getSelectionRows()
1010 return selectionModel
.getSelectionRows();
1013 public boolean isPathSelected(TreePath path
)
1015 return selectionModel
.isPathSelected(path
);
1018 public boolean isRowSelected(int row
)
1020 return selectionModel
.isRowSelected(row
);
1023 public boolean isSelectionEmpty()
1025 return selectionModel
.isSelectionEmpty();
1029 * Return the value of the <code>dragEnabled</code> property.
1035 public boolean getDragEnabled()
1041 * Set the <code>dragEnabled</code> property.
1043 * @param enabled new value
1047 public void setDragEnabled(boolean enabled
)
1049 dragEnabled
= enabled
;
1052 public int getRowCount()
1054 TreeUI ui
= getUI();
1057 return ui
.getRowCount(this);
1062 public void collapsePath(TreePath path
)
1064 setExpandedState(path
, false);
1067 public void collapseRow(int row
)
1069 if (row
< 0 || row
>= getRowCount())
1072 TreePath path
= getPathForRow(row
);
1078 public void expandPath(TreePath path
)
1080 // Don't expand if last path component is a leaf node.
1082 || (treeModel
.isLeaf(path
.getLastPathComponent())))
1085 setExpandedState(path
, true);
1088 public void expandRow(int row
)
1090 if (row
< 0 || row
>= getRowCount())
1093 TreePath path
= getPathForRow(row
);
1099 public boolean isCollapsed(TreePath path
)
1101 return ! isExpanded(path
);
1104 public boolean isCollapsed(int row
)
1106 if (row
< 0 || row
>= getRowCount())
1109 TreePath path
= getPathForRow(row
);
1112 return isCollapsed(path
);
1117 public boolean isExpanded(TreePath path
)
1122 Object state
= nodeStates
.get(path
);
1124 if ((state
== null) || (state
!= EXPANDED
))
1127 TreePath parent
= path
.getParentPath();
1130 return isExpanded(parent
);
1135 public boolean isExpanded(int row
)
1137 if (row
< 0 || row
>= getRowCount())
1140 TreePath path
= getPathForRow(row
);
1143 return isExpanded(path
);
1151 public boolean getExpandsSelectedPaths()
1153 return expandsSelectedPaths
;
1159 public void setExpandsSelectedPaths(boolean flag
)
1161 if (expandsSelectedPaths
== flag
)
1164 boolean oldValue
= expandsSelectedPaths
;
1165 expandsSelectedPaths
= flag
;
1166 firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY
, oldValue
, flag
);
1169 public Rectangle
getPathBounds(TreePath path
)
1171 TreeUI ui
= getUI();
1176 return ui
.getPathBounds(this, path
);
1179 public Rectangle
getRowBounds(int row
)
1181 TreePath path
= getPathForRow(row
);
1184 return getPathBounds(path
);
1189 public boolean isEditing()
1191 TreeUI ui
= getUI();
1194 return ui
.isEditing(this);
1199 public boolean stopEditing()
1201 TreeUI ui
= getUI();
1204 return ui
.stopEditing(this);
1209 public void cancelEditing()
1211 TreeUI ui
= getUI();
1214 ui
.cancelEditing(this);
1217 public void startEditingAtPath(TreePath path
)
1219 TreeUI ui
= getUI();
1222 ui
.startEditingAtPath(this, path
);
1225 public TreePath
getEditingPath()
1227 TreeUI ui
= getUI();
1230 return ui
.getEditingPath(this);
1235 public TreePath
getPathForLocation(int x
, int y
)
1237 TreePath path
= getClosestPathForLocation(x
, y
);
1241 Rectangle rect
= getPathBounds(path
);
1243 if ((rect
!= null) && rect
.contains(x
, y
))
1250 public int getRowForLocation(int x
, int y
)
1252 TreePath path
= getPathForLocation(x
, y
);
1255 return getRowForPath(path
);
1260 public TreePath
getClosestPathForLocation(int x
, int y
)
1262 TreeUI ui
= getUI();
1265 return ui
.getClosestPathForLocation(this, x
, y
);
1270 public int getClosestRowForLocation(int x
, int y
)
1272 TreePath path
= getClosestPathForLocation(x
, y
);
1275 return getRowForPath(path
);
1280 public Object
getLastSelectedPathComponent()
1282 TreePath path
= getSelectionPath();
1285 return path
.getLastPathComponent();
1290 private void checkExpandParents(TreePath path
)
1291 throws ExpandVetoException
1293 TreePath parent
= path
.getParentPath();
1296 checkExpandParents(parent
);
1298 fireTreeWillExpand(path
);
1301 private void doExpandParents(TreePath path
, boolean state
)
1303 TreePath parent
= path
.getParentPath();
1305 if (isExpanded(parent
))
1309 doExpandParents(parent
, false);
1311 nodeStates
.put(path
, state ? EXPANDED
: COLLAPSED
);
1314 protected void setExpandedState(TreePath path
, boolean state
)
1319 TreePath parent
= path
.getParentPath();
1323 while (parent
!= null)
1324 checkExpandParents(parent
);
1326 catch (ExpandVetoException e
)
1328 // Expansion vetoed.
1332 doExpandParents(path
, state
);
1335 protected void clearToggledPaths()
1340 protected Enumeration
getDescendantToggledPaths(TreePath parent
)
1345 Enumeration nodes
= nodeStates
.keys();
1346 Vector result
= new Vector();
1348 while (nodes
.hasMoreElements())
1350 TreePath path
= (TreePath
) nodes
.nextElement();
1352 if (path
.isDescendant(parent
))
1353 result
.addElement(path
);
1356 return result
.elements();
1359 public boolean hasBeenExpanded(TreePath path
)
1364 return nodeStates
.get(path
) != null;
1367 public boolean isVisible(TreePath path
)
1372 TreePath parent
= path
.getParentPath();
1375 return true; // Is root node.
1377 return isExpanded(parent
);
1380 public void makeVisible(TreePath path
)
1385 expandPath(path
.getParentPath());
1388 public boolean isPathEditable(TreePath path
)
1390 return isEditable();