1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55:
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83: import ;
84: import ;
85:
86: public class JTree extends JComponent implements Scrollable, Accessible
87: {
88:
89:
94: protected class AccessibleJTree extends JComponent.AccessibleJComponent
95: implements AccessibleSelection, TreeSelectionListener, TreeModelListener,
96: TreeExpansionListener
97: {
98:
99:
103: protected class AccessibleJTreeNode extends AccessibleContext
104: implements Accessible, AccessibleComponent, AccessibleSelection,
105: AccessibleAction
106: {
107:
108: private JTree tree;
109: private TreePath tp;
110: private Accessible acc;
111: private AccessibleStateSet states;
112: private Vector selectionList;
113: private Vector actionList;
114: private TreeModel mod;
115: private Cursor cursor;
116:
117:
124: public AccessibleJTreeNode(JTree t, TreePath p, Accessible ap)
125: {
126: states = new AccessibleStateSet();
127: selectionList = new Vector();
128: actionList = new Vector();
129: mod = tree.getModel();
130: cursor = JTree.this.getCursor();
131:
132: tree = t;
133: tp = p;
134: acc = ap;
135:
136:
137:
138: TreePath[] selected = tree.getSelectionPaths();
139: for (int i = 0; i < selected.length; i++)
140: {
141: TreePath sel = selected[i];
142: if ((sel.getParentPath()).equals(tp))
143: selectionList.add(sel);
144: }
145:
146:
147:
148: actionList.add("EXPAND");
149: actionList.add("COLLAPSE");
150: actionList.add("EDIT");
151: actionList.add("SELECT");
152: actionList.add("DESELECT");
153: }
154:
155:
161: public void addAccessibleSelection(int i)
162: {
163: if (mod != null)
164: {
165: Object child = mod.getChild(tp.getLastPathComponent(), i);
166: if (child != null)
167: {
168: if (!states.contains(AccessibleState.MULTISELECTABLE))
169: clearAccessibleSelection();
170: selectionList.add(child);
171: tree.addSelectionPath(tp.pathByAddingChild(child));
172: }
173: }
174: }
175:
176:
182: public void addFocusListener(FocusListener l)
183: {
184: tree.addFocusListener(l);
185: }
186:
187:
192: public void addPropertyChangeListener(PropertyChangeListener l)
193: {
194:
195: }
196:
197:
201: public void clearAccessibleSelection()
202: {
203: selectionList.clear();
204: }
205:
206:
214: public boolean contains(Point p)
215: {
216: return getBounds().contains(p);
217: }
218:
219:
225: public boolean doAccessibleAction(int i)
226: {
227: if (i >= actionList.size() || i < 0)
228: return false;
229:
230: if (actionList.get(i).equals("EXPAND"))
231: tree.expandPath(tp);
232: else if (actionList.get(i).equals("COLLAPSE"))
233: tree.collapsePath(tp);
234: else if (actionList.get(i).equals("SELECT"))
235: tree.addSelectionPath(tp);
236: else if (actionList.get(i).equals("DESELECT"))
237: tree.removeSelectionPath(tp);
238: else if (actionList.get(i).equals("EDIT"))
239: tree.startEditingAtPath(tp);
240: else
241: return false;
242: return true;
243: }
244:
245:
250: public AccessibleAction getAccessibleAction()
251: {
252: return this;
253: }
254:
255:
260: public int getAccessibleActionCount()
261: {
262: return actionList.size();
263: }
264:
265:
271: public String getAccessibleActionDescription(int i)
272: {
273: if (i < 0 || i >= actionList.size())
274: return (actionList.get(i)).toString();
275: return super.getAccessibleDescription();
276: }
277:
278:
285: public Accessible getAccessibleAt(Point p)
286: {
287: TreePath acc = tree.getClosestPathForLocation(p.x, p.y);
288: if (acc != null)
289: return new AccessibleJTreeNode(tree, acc, this);
290: return null;
291: }
292:
293:
299: public Accessible getAccessibleChild(int i)
300: {
301: if (mod != null)
302: {
303: Object child = mod.getChild(tp.getLastPathComponent(), i);
304: if (child != null)
305: return new AccessibleJTreeNode(tree, tp.pathByAddingChild(child),
306: acc);
307: }
308: return null;
309: }
310:
311:
316: public int getAccessibleChildrenCount()
317: {
318: TreeModel mod = getModel();
319: if (mod != null)
320: return mod.getChildCount(tp.getLastPathComponent());
321: return 0;
322: }
323:
324:
329: public AccessibleComponent getAccessibleComponent()
330: {
331: return this;
332: }
333:
334:
339: public AccessibleContext getAccessibleContext()
340: {
341: return this;
342: }
343:
344:
349: public String getAccessibleDescription()
350: {
351: return super.getAccessibleDescription();
352: }
353:
354:
359: public int getAccessibleIndexInParent()
360: {
361: AccessibleContext parent = getAccessibleParent().getAccessibleContext();
362: if (parent != null)
363: for (int i = 0; i < parent.getAccessibleChildrenCount(); i++)
364: {
365: if ((parent.getAccessibleChild(i)).equals(this))
366: return i;
367: }
368: return -1;
369: }
370:
371:
376: public String getAccessibleName()
377: {
378: return super.getAccessibleName();
379: }
380:
381:
386: public Accessible getAccessibleParent()
387: {
388: return super.getAccessibleParent();
389: }
390:
391:
396: public AccessibleRole getAccessibleRole()
397: {
398: return AccessibleJTree.this.getAccessibleRole();
399: }
400:
401:
406: public AccessibleSelection getAccessibleSelection()
407: {
408: return this;
409: }
410:
411:
417: public Accessible getAccessibleSelection(int i)
418: {
419: if (i > 0 && i < getAccessibleSelectionCount())
420: return new AccessibleJTreeNode(tree,
421: tp.pathByAddingChild(selectionList.get(i)), acc);
422: return null;
423: }
424:
425:
430: public int getAccessibleSelectionCount()
431: {
432: return selectionList.size();
433: }
434:
435:
440: public AccessibleStateSet getAccessibleStateSet()
441: {
442: if (isVisible())
443: states.add(AccessibleState.VISIBLE);
444: if (tree.isCollapsed(tp))
445: states.add(AccessibleState.COLLAPSED);
446: if (tree.isEditable())
447: states.add(AccessibleState.EDITABLE);
448: if (mod != null &&
449: !mod.isLeaf(tp.getLastPathComponent()))
450: states.add(AccessibleState.EXPANDABLE);
451: if (tree.isExpanded(tp))
452: states.add(AccessibleState.EXPANDED);
453: if (isFocusable())
454: states.add(AccessibleState.FOCUSABLE);
455: if (hasFocus())
456: states.add(AccessibleState.FOCUSED);
457: if (tree.getSelectionModel().getSelectionMode() !=
458: TreeSelectionModel.SINGLE_TREE_SELECTION)
459: states.add(AccessibleState.MULTISELECTABLE);
460: if (tree.isOpaque())
461: states.add(AccessibleState.OPAQUE);
462: if (tree.isPathSelected(tp))
463: states.add(AccessibleState.SELECTED);
464: if (isShowing())
465: states.add(AccessibleState.SHOWING);
466:
467: states.add(AccessibleState.SELECTABLE);
468: return states;
469: }
470:
471:
476: public AccessibleText getAccessibleText()
477: {
478: return super.getAccessibleText();
479: }
480:
481:
486: public AccessibleValue getAccessibleValue()
487: {
488: return super.getAccessibleValue();
489: }
490:
491:
496: public Color getBackground()
497: {
498: return tree.getBackground();
499: }
500:
501:
506: public Rectangle getBounds()
507: {
508: return tree.getPathBounds(tp);
509: }
510:
511:
516: public Cursor getCursor()
517: {
518: return cursor;
519: }
520:
521:
526: public Font getFont()
527: {
528: return tree.getFont();
529: }
530:
531:
537: public FontMetrics getFontMetrics(Font f)
538: {
539: return tree.getFontMetrics(f);
540: }
541:
542:
547: public Color getForeground()
548: {
549: return tree.getForeground();
550: }
551:
552:
557: public Locale getLocale()
558: {
559: return tree.getLocale();
560: }
561:
562:
569: public Point getLocation()
570: {
571: return getLocationInJTree();
572: }
573:
574:
579: protected Point getLocationInJTree()
580: {
581: Rectangle bounds = tree.getPathBounds(tp);
582: return new Point(bounds.x, bounds.y);
583: }
584:
585:
590: public Point getLocationOnScreen()
591: {
592: Point loc = getLocation();
593: SwingUtilities.convertPointToScreen(loc, tree);
594: return loc;
595: }
596:
597:
602: public Dimension getSize()
603: {
604: Rectangle b = getBounds();
605: return b.getSize();
606: }
607:
608:
614: public boolean isAccessibleChildSelected(int i)
615: {
616: Object child = mod.getChild(tp.getLastPathComponent(), i);
617: if (child != null)
618: return tree.isPathSelected(tp.pathByAddingChild(child));
619: return false;
620: }
621:
622:
627: public boolean isEnabled()
628: {
629: return tree.isEnabled();
630: }
631:
632:
637: public boolean isFocusTraversable()
638: {
639: return true;
640: }
641:
642:
648: public boolean isShowing()
649: {
650: return isVisible() && tree.isShowing();
651: }
652:
653:
658: public boolean isVisible()
659: {
660: return tree.isVisible(tp);
661: }
662:
663:
669: public void removeAccessibleSelection(int i)
670: {
671: if (mod != null)
672: {
673: Object child = mod.getChild(tp.getLastPathComponent(), i);
674: if (child != null)
675: {
676: if (!states.contains(AccessibleState.MULTISELECTABLE))
677: clearAccessibleSelection();
678: if (selectionList.contains(child))
679: {
680: selectionList.remove(child);
681: tree.removeSelectionPath(tp.pathByAddingChild(child));
682: }
683: }
684: }
685: }
686:
687:
693: public void removeFocusListener(FocusListener l)
694: {
695: tree.removeFocusListener(l);
696: }
697:
698:
703: public void removePropertyChangeListener(PropertyChangeListener l)
704: {
705:
706: }
707:
708:
711: public void requestFocus()
712: {
713: tree.requestFocus();
714: }
715:
716:
720: public void selectAllAccessibleSelection()
721: {
722: Object parent = tp.getLastPathComponent();
723: if (mod != null)
724: {
725: for (int i = 0; i < mod.getChildCount(parent); i++)
726: {
727: Object child = mod.getChild(parent, i);
728: if (child != null)
729: {
730: if (!states.contains(AccessibleState.MULTISELECTABLE))
731: clearAccessibleSelection();
732: if (selectionList.contains(child))
733: {
734: selectionList.add(child);
735: tree.addSelectionPath(tp.pathByAddingChild(child));
736: }
737: }
738: }
739: }
740: }
741:
742:
747: public void setAccessibleDescription(String s)
748: {
749: super.setAccessibleDescription(s);
750: }
751:
752:
757: public void setAccessibleName(String s)
758: {
759: super.setAccessibleName(s);
760: }
761:
762:
767: public void setBackground(Color c)
768: {
769:
770: }
771:
772:
777: public void setBounds(Rectangle r)
778: {
779:
780: }
781:
782:
787: public void setCursor(Cursor c)
788: {
789: cursor = c;
790: }
791:
792:
797: public void setEnabled(boolean b)
798: {
799:
800: }
801:
802:
807: public void setFont(Font f)
808: {
809:
810: }
811:
812:
817: public void setForeground(Color c)
818: {
819:
820: }
821:
822:
827: public void setLocation(Point p)
828: {
829:
830: }
831:
832:
837: public void setSize(Dimension d)
838: {
839:
840: }
841:
842:
847: public void setVisible(boolean b)
848: {
849:
850: }
851: }
852:
853:
856: public AccessibleJTree()
857: {
858:
859: }
860:
861:
866: public void addAccessibleSelection(int i)
867: {
868: addSelectionInterval(i, i);
869: }
870:
871:
874: public void clearAccessibleSelection()
875: {
876: clearSelection();
877: }
878:
879:
882: public void fireVisibleDataPropertyChange()
883: {
884: treeDidChange();
885: }
886:
887:
894: public Accessible getAccessibleAt(Point p)
895: {
896: TreePath tp = getClosestPathForLocation(p.x, p.y);
897: if (tp != null)
898: return new AccessibleJTreeNode(JTree.this, tp, null);
899: return null;
900: }
901:
902:
908: public Accessible getAccessibleChild(int i)
909: {
910: return null;
911: }
912:
913:
918: public int getAccessibleChildrenCount()
919: {
920: TreeModel model = getModel();
921: if (model != null)
922: return model.getChildCount(model.getRoot());
923: return 0;
924: }
925:
926:
931: public int getAccessibleIndexInParent()
932: {
933: return 0;
934: }
935:
936:
941: public AccessibleRole getAccessibleRole()
942: {
943: return AccessibleRole.TREE;
944: }
945:
946:
951: public AccessibleSelection getAccessibleSelection()
952: {
953: TreeModel mod = getModel();
954: if (mod != null)
955: return (new AccessibleJTreeNode(JTree.this,
956: new TreePath(mod.getRoot()), null)).getAccessibleSelection();
957: return null;
958: }
959:
960:
965: public Accessible getAccessibleSelection(int i)
966: {
967: TreeModel mod = getModel();
968: if (mod != null)
969: return (new AccessibleJTreeNode(JTree.this,
970: new TreePath(mod.getRoot()), null)).getAccessibleSelection(i);
971: return null;
972: }
973:
974:
979: public int getAccessibleSelectionCount()
980: {
981: return getSelectionCount();
982: }
983:
984:
990: public boolean isAccessibleChildSelected(int i)
991: {
992:
993: return false;
994: }
995:
996:
1002: public void removeAccessibleSelection(int i)
1003: {
1004: removeSelectionInterval(i, i);
1005: }
1006:
1007:
1011: public void selectAllAccessibleSelection()
1012: {
1013: if (getSelectionModel().getSelectionMode() !=
1014: TreeSelectionModel.SINGLE_TREE_SELECTION)
1015: addSelectionInterval(0, getVisibleRowCount());
1016: }
1017:
1018:
1023: public void treeCollapsed(TreeExpansionEvent e)
1024: {
1025: fireTreeCollapsed(e.getPath());
1026: }
1027:
1028:
1033: public void treeExpanded(TreeExpansionEvent e)
1034: {
1035: fireTreeExpanded(e.getPath());
1036: }
1037:
1038:
1043: public void treeNodesChanged(TreeModelEvent e)
1044: {
1045:
1046: }
1047:
1048:
1053: public void treeNodesInserted(TreeModelEvent e)
1054: {
1055:
1056: }
1057:
1058:
1063: public void treeNodesRemoved(TreeModelEvent e)
1064: {
1065:
1066: }
1067:
1068:
1073: public void treeStructureChanged(TreeModelEvent e)
1074: {
1075:
1076: }
1077:
1078:
1083: public void valueChanged(TreeSelectionEvent e)
1084: {
1085: fireValueChanged(e);
1086: }
1087: }
1088:
1089: public static class DynamicUtilTreeNode extends DefaultMutableTreeNode
1090: {
1091: protected Object childValue;
1092:
1093: protected boolean loadedChildren;
1094:
1095:
1099: protected boolean hasChildren;
1100:
1101: public DynamicUtilTreeNode(Object value, Object children)
1102: {
1103: super(value);
1104: childValue = children;
1105: loadedChildren = false;
1106: }
1107:
1108: public int getChildCount()
1109: {
1110: loadChildren();
1111: return super.getChildCount();
1112: }
1113:
1114: protected void loadChildren()
1115: {
1116: if (!loadedChildren)
1117: {
1118: createChildren(this, childValue);
1119: loadedChildren = true;
1120: }
1121: }
1122:
1123: public Enumeration children()
1124: {
1125: loadChildren();
1126: return super.children();
1127: }
1128:
1129:
1137: public TreeNode getChildAt(int pos)
1138: {
1139: loadChildren();
1140: return super.getChildAt(pos);
1141: }
1142:
1143: public boolean isLeaf()
1144: {
1145: return childValue == null || !(childValue instanceof Hashtable
1146: || childValue instanceof Vector
1147: || childValue.getClass().isArray());
1148: }
1149:
1150: public static void createChildren(DefaultMutableTreeNode parent,
1151: Object children)
1152: {
1153: if (children instanceof Hashtable)
1154: {
1155: Hashtable tab = (Hashtable) children;
1156: Enumeration e = tab.keys();
1157: while (e.hasMoreElements())
1158: {
1159: Object key = e.nextElement();
1160: Object val = tab.get(key);
1161: parent.add(new DynamicUtilTreeNode(key, val));
1162: }
1163: }
1164: else if (children instanceof Vector)
1165: {
1166: Iterator i = ((Vector) children).iterator();
1167: while (i.hasNext())
1168: {
1169: Object n = i.next();
1170: parent.add(new DynamicUtilTreeNode(n, n));
1171: }
1172: }
1173: else if (children != null && children.getClass().isArray())
1174: {
1175: Object[] arr = (Object[]) children;
1176: for (int i = 0; i < arr.length; ++i)
1177: parent.add(new DynamicUtilTreeNode(arr[i], arr[i]));
1178: }
1179: }
1180: }
1181:
1182:
1186: protected class TreeModelHandler implements TreeModelListener
1187: {
1188:
1189:
1192: protected TreeModelHandler()
1193: {
1194:
1195: }
1196:
1197:
1207: public void treeNodesChanged(TreeModelEvent ev)
1208: {
1209:
1210: }
1211:
1212:
1219: public void treeNodesInserted(TreeModelEvent ev)
1220: {
1221:
1222: }
1223:
1224:
1231: public void treeNodesRemoved(TreeModelEvent ev)
1232: {
1233: if (ev != null)
1234: {
1235: TreePath parent = ev.getTreePath();
1236: Object[] children = ev.getChildren();
1237: TreeSelectionModel sm = getSelectionModel();
1238: if (children != null)
1239: {
1240: TreePath path;
1241: Vector toRemove = new Vector();
1242:
1243: for (int i = children.length - 1; i >= 0; i--)
1244: {
1245: path = parent.pathByAddingChild(children[i]);
1246: if (nodeStates.containsKey(path))
1247: toRemove.add(path);
1248:
1249: if (sm != null)
1250: removeDescendantSelectedPaths(path, true);
1251: }
1252: if (toRemove.size() > 0)
1253: removeDescendantToggledPaths(toRemove.elements());
1254: TreeModel model = getModel();
1255: if (model == null || model.isLeaf(parent.getLastPathComponent()))
1256: nodeStates.remove(parent);
1257: }
1258: }
1259: }
1260:
1261:
1268: public void treeStructureChanged(TreeModelEvent ev)
1269: {
1270: if (ev != null)
1271: {
1272: TreePath parent = ev.getTreePath();
1273: if (parent != null)
1274: {
1275: if (parent.getPathCount() == 1)
1276: {
1277:
1278: clearToggledPaths();
1279: Object root = treeModel.getRoot();
1280: if (root != null && treeModel.isLeaf(root))
1281: nodeStates.put(parent, Boolean.TRUE);
1282: }
1283: else if (nodeStates.containsKey(parent))
1284: {
1285: Vector toRemove = new Vector();
1286: boolean expanded = isExpanded(parent);
1287: toRemove.add(parent);
1288: removeDescendantToggledPaths(toRemove.elements());
1289: if (expanded)
1290: {
1291: TreeModel model = getModel();
1292: if (model != null
1293: || model.isLeaf(parent.getLastPathComponent()))
1294: collapsePath(parent);
1295: else
1296: nodeStates.put(parent, Boolean.TRUE);
1297: }
1298: }
1299: removeDescendantSelectedPaths(parent, false);
1300: }
1301: }
1302: }
1303: }
1304:
1305:
1311: protected class TreeSelectionRedirector implements TreeSelectionListener,
1312: Serializable
1313: {
1314:
1315: private static final long serialVersionUID = -3505069663646241664L;
1316:
1317:
1320: protected TreeSelectionRedirector()
1321: {
1322:
1323: }
1324:
1325:
1330: public void valueChanged(TreeSelectionEvent ev)
1331: {
1332: TreeSelectionEvent rewritten =
1333: (TreeSelectionEvent) ev.cloneWithSource(JTree.this);
1334: fireValueChanged(rewritten);
1335: }
1336: }
1337:
1338:
1341: protected static class EmptySelectionModel extends DefaultTreeSelectionModel
1342: {
1343:
1344: private static final long serialVersionUID = -5815023306225701477L;
1345:
1346:
1349: protected static final EmptySelectionModel sharedInstance =
1350: new EmptySelectionModel();
1351:
1352:
1355: protected EmptySelectionModel()
1356: {
1357:
1358: }
1359:
1360:
1365: public static EmptySelectionModel sharedInstance()
1366: {
1367: return sharedInstance;
1368: }
1369:
1370:
1375: public void setSelectionPaths(TreePath[] paths)
1376: {
1377:
1378: }
1379:
1380:
1385: public void addSelectionPaths(TreePath[] paths)
1386: {
1387:
1388: }
1389:
1390:
1395: public void removeSelectionPaths(TreePath[] paths)
1396: {
1397:
1398: }
1399: }
1400:
1401: private static final long serialVersionUID = 7559816092864483649L;
1402:
1403: public static final String CELL_EDITOR_PROPERTY = "cellEditor";
1404:
1405: public static final String CELL_RENDERER_PROPERTY = "cellRenderer";
1406:
1407: public static final String EDITABLE_PROPERTY = "editable";
1408:
1409: public static final String INVOKES_STOP_CELL_EDITING_PROPERTY =
1410: "invokesStopCellEditing";
1411:
1412: public static final String LARGE_MODEL_PROPERTY = "largeModel";
1413:
1414: public static final String ROOT_VISIBLE_PROPERTY = "rootVisible";
1415:
1416: public static final String ROW_HEIGHT_PROPERTY = "rowHeight";
1417:
1418: public static final String SCROLLS_ON_EXPAND_PROPERTY = "scrollsOnExpand";
1419:
1420: public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
1421:
1422: public static final String SHOWS_ROOT_HANDLES_PROPERTY = "showsRootHandles";
1423:
1424: public static final String TOGGLE_CLICK_COUNT_PROPERTY = "toggleClickCount";
1425:
1426: public static final String TREE_MODEL_PROPERTY = "model";
1427:
1428: public static final String VISIBLE_ROW_COUNT_PROPERTY = "visibleRowCount";
1429:
1430:
1431: public static final String ANCHOR_SELECTION_PATH_PROPERTY =
1432: "anchorSelectionPath";
1433:
1434:
1435: public static final String LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath";
1436:
1437:
1438: public static final String EXPANDS_SELECTED_PATHS_PROPERTY =
1439: "expandsSelectedPaths";
1440:
1441: private static final Object EXPANDED = Boolean.TRUE;
1442:
1443: private static final Object COLLAPSED = Boolean.FALSE;
1444:
1445: private boolean dragEnabled;
1446:
1447: private boolean expandsSelectedPaths;
1448:
1449: private TreePath anchorSelectionPath;
1450:
1451:
1458: Hashtable nodeStates = new Hashtable();
1459:
1460: protected transient TreeCellEditor cellEditor;
1461:
1462: protected transient TreeCellRenderer cellRenderer;
1463:
1464: protected boolean editable;
1465:
1466: protected boolean invokesStopCellEditing;
1467:
1468: protected boolean largeModel;
1469:
1470: protected boolean rootVisible;
1471:
1472: protected int rowHeight;
1473:
1474: protected boolean scrollsOnExpand;
1475:
1476: protected transient TreeSelectionModel selectionModel;
1477:
1478: protected boolean showsRootHandles;
1479:
1480: protected int toggleClickCount;
1481:
1482: protected transient TreeModel treeModel;
1483:
1484: protected int visibleRowCount;
1485:
1486:
1489: protected transient TreeModelListener treeModelListener;
1490:
1491:
1494: protected TreeSelectionRedirector selectionRedirector =
1495: new TreeSelectionRedirector();
1496:
1497:
1504: private boolean clientRowHeightSet = false;
1505:
1506:
1513: private boolean clientScrollsOnExpandSet = false;
1514:
1515:
1522: private boolean clientShowsRootHandlesSet = false;
1523:
1524:
1527: public JTree()
1528: {
1529: this(getDefaultTreeModel());
1530: }
1531:
1532:
1537: public JTree(Hashtable<?, ?> value)
1538: {
1539: this(createTreeModel(value));
1540: }
1541:
1542:
1547: public JTree(Object[] value)
1548: {
1549: this(createTreeModel(value));
1550: }
1551:
1552:
1557: public JTree(TreeModel model)
1558: {
1559: setRootVisible(true);
1560: setSelectionModel( new DefaultTreeSelectionModel() );
1561:
1562:
1563: nodeStates = new Hashtable();
1564:
1565:
1566: cellRenderer = null;
1567:
1568:
1569:
1570:
1571:
1572: updateUI();
1573: setModel(model);
1574: }
1575:
1576:
1581: public JTree(TreeNode root)
1582: {
1583: this(root, false);
1584: }
1585:
1586:
1594: public JTree(TreeNode root, boolean asksAllowChildren)
1595: {
1596: this(new DefaultTreeModel(root, asksAllowChildren));
1597: }
1598:
1599:
1604: public JTree(Vector<?> value)
1605: {
1606: this(createTreeModel(value));
1607: }
1608:
1609: public int getRowForPath(TreePath path)
1610: {
1611: TreeUI ui = getUI();
1612:
1613: if (ui != null)
1614: return ui.getRowForPath(this, path);
1615:
1616: return -1;
1617: }
1618:
1619: public TreePath getPathForRow(int row)
1620: {
1621: TreeUI ui = getUI();
1622: return ui != null ? ui.getPathForRow(this, row) : null;
1623: }
1624:
1625:
1633: protected TreePath[] getPathBetweenRows(int index0, int index1)
1634: {
1635: TreeUI ui = getUI();
1636:
1637: if (ui == null)
1638: return null;
1639:
1640: int minIndex = Math.min(index0, index1);
1641: int maxIndex = Math.max(index0, index1);
1642: TreePath[] paths = new TreePath[maxIndex - minIndex + 1];
1643:
1644: for (int i = minIndex; i <= maxIndex; ++i)
1645: paths[i - minIndex] = ui.getPathForRow(this, i);
1646:
1647: return paths;
1648: }
1649:
1650:
1655: protected static TreeModel createTreeModel(Object value)
1656: {
1657: return new DefaultTreeModel(new DynamicUtilTreeNode(value, value));
1658: }
1659:
1660:
1665: public TreeUI getUI()
1666: {
1667: return (TreeUI) ui;
1668: }
1669:
1670:
1675: public void setUI(TreeUI ui)
1676: {
1677: super.setUI(ui);
1678: }
1679:
1680:
1683: public void updateUI()
1684: {
1685: setUI((TreeUI) UIManager.getUI(this));
1686: }
1687:
1688:
1693: public String getUIClassID()
1694: {
1695: return "TreeUI";
1696: }
1697:
1698:
1704: public AccessibleContext getAccessibleContext()
1705: {
1706: return new AccessibleJTree();
1707: }
1708:
1709:
1714: public Dimension getPreferredScrollableViewportSize()
1715: {
1716: return getPreferredSize();
1717: }
1718:
1719:
1732: public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
1733: int direction)
1734: {
1735: int delta = 0;
1736:
1737:
1738: if (orientation == SwingConstants.VERTICAL)
1739: {
1740: int row = getClosestRowForLocation(0, visibleRect.y);
1741: if (row != -1)
1742: {
1743: Rectangle b = getRowBounds(row);
1744: if (b.y != visibleRect.y)
1745: {
1746: if (direction < 0)
1747: delta = Math.max(0, visibleRect.y - b.y);
1748: else
1749: delta = b.y + b.height - visibleRect.y;
1750: }
1751: else
1752: {
1753: if (direction < 0)
1754: {
1755: if (row != 0)
1756: {
1757: b = getRowBounds(row - 1);
1758: delta = b.height;
1759: }
1760: }
1761: else
1762: delta = b.height;
1763: }
1764: }
1765: }
1766: else
1767:
1768: delta = 4;
1769: return delta;
1770: }
1771:
1772: public int getScrollableBlockIncrement(Rectangle visibleRect,
1773: int orientation, int direction)
1774: {
1775: int block;
1776: if (orientation == SwingConstants.VERTICAL)
1777: block = visibleRect.height;
1778: else
1779: block = visibleRect.width;
1780: return block;
1781: }
1782:
1783: public boolean getScrollableTracksViewportHeight()
1784: {
1785: if (getParent() instanceof JViewport)
1786: return ((JViewport) getParent()).getHeight() > getPreferredSize().height;
1787: return false;
1788: }
1789:
1790: public boolean getScrollableTracksViewportWidth()
1791: {
1792: if (getParent() instanceof JViewport)
1793: return ((JViewport) getParent()).getWidth() > getPreferredSize().width;
1794: return false;
1795: }
1796:
1797:
1802: public void addTreeExpansionListener(TreeExpansionListener listener)
1803: {
1804: listenerList.add(TreeExpansionListener.class, listener);
1805: }
1806:
1807:
1812: public void removeTreeExpansionListener(TreeExpansionListener listener)
1813: {
1814: listenerList.remove(TreeExpansionListener.class, listener);
1815: }
1816:
1817:
1822: public TreeExpansionListener[] getTreeExpansionListeners()
1823: {
1824: return (TreeExpansionListener[]) getListeners(TreeExpansionListener.class);
1825: }
1826:
1827:
1832: public void fireTreeCollapsed(TreePath path)
1833: {
1834: TreeExpansionEvent event = new TreeExpansionEvent(this, path);
1835: TreeExpansionListener[] listeners = getTreeExpansionListeners();
1836:
1837: for (int index = 0; index < listeners.length; ++index)
1838: listeners[index].treeCollapsed(event);
1839: }
1840:
1841:
1846: public void fireTreeExpanded(TreePath path)
1847: {
1848: TreeExpansionEvent event = new TreeExpansionEvent(this, path);
1849: TreeExpansionListener[] listeners = getTreeExpansionListeners();
1850:
1851: for (int index = 0; index < listeners.length; ++index)
1852: listeners[index].treeExpanded(event);
1853: }
1854:
1855:
1860: public void addTreeSelectionListener(TreeSelectionListener listener)
1861: {
1862: listenerList.add(TreeSelectionListener.class, listener);
1863: }
1864:
1865:
1870: public void removeTreeSelectionListener(TreeSelectionListener listener)
1871: {
1872: listenerList.remove(TreeSelectionListener.class, listener);
1873: }
1874:
1875:
1880: public TreeSelectionListener[] getTreeSelectionListeners()
1881: {
1882: return (TreeSelectionListener[])
1883: getListeners(TreeSelectionListener.class);
1884: }
1885:
1886:
1891: protected void fireValueChanged(TreeSelectionEvent event)
1892: {
1893: TreeSelectionListener[] listeners = getTreeSelectionListeners();
1894:
1895: for (int index = 0; index < listeners.length; ++index)
1896: listeners[index].valueChanged(event);
1897: }
1898:
1899:
1904: public void addTreeWillExpandListener(TreeWillExpandListener listener)
1905: {
1906: listenerList.add(TreeWillExpandListener.class, listener);
1907: }
1908:
1909:
1914: public void removeTreeWillExpandListener(TreeWillExpandListener listener)
1915: {
1916: listenerList.remove(TreeWillExpandListener.class, listener);
1917: }
1918:
1919:
1924: public TreeWillExpandListener[] getTreeWillExpandListeners()
1925: {
1926: return (TreeWillExpandListener[])
1927: getListeners(TreeWillExpandListener.class);
1928: }
1929:
1930:
1935: public void fireTreeWillCollapse(TreePath path) throws ExpandVetoException
1936: {
1937: TreeExpansionEvent event = new TreeExpansionEvent(this, path);
1938: TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
1939:
1940: for (int index = 0; index < listeners.length; ++index)
1941: listeners[index].treeWillCollapse(event);
1942: }
1943:
1944:
1949: public void fireTreeWillExpand(TreePath path) throws ExpandVetoException
1950: {
1951: TreeExpansionEvent event = new TreeExpansionEvent(this, path);
1952: TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
1953:
1954: for (int index = 0; index < listeners.length; ++index)
1955: listeners[index].treeWillExpand(event);
1956: }
1957:
1958:
1963: public TreeModel getModel()
1964: {
1965: return treeModel;
1966: }
1967:
1968:
1973: public void setModel(TreeModel model)
1974: {
1975: if (treeModel == model)
1976: return;
1977:
1978:
1979: if (treeModel != null && treeModelListener != null)
1980: treeModel.removeTreeModelListener(treeModelListener);
1981:
1982:
1983: if (treeModelListener == null)
1984: treeModelListener = createTreeModelListener();
1985: if (model != null)
1986: model.addTreeModelListener(treeModelListener);
1987:
1988: TreeModel oldValue = treeModel;
1989: treeModel = model;
1990: clearToggledPaths();
1991:
1992: if (treeModel != null)
1993: {
1994: if (treeModelListener == null)
1995: treeModelListener = createTreeModelListener();
1996: if (treeModelListener != null)
1997: treeModel.addTreeModelListener(treeModelListener);
1998: Object root = treeModel.getRoot();
1999: if (root != null && !treeModel.isLeaf(root))
2000: {
2001: nodeStates.put(new TreePath(root), Boolean.TRUE);
2002: }
2003: }
2004:
2005: firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model);
2006: }
2007:
2008:
2014: public boolean isEditable()
2015: {
2016: return editable;
2017: }
2018:
2019:
2025: public void setEditable(boolean flag)
2026: {
2027: if (editable == flag)
2028: return;
2029:
2030: boolean oldValue = editable;
2031: editable = flag;
2032: firePropertyChange(EDITABLE_PROPERTY, oldValue, editable);
2033: }
2034:
2035:
2041: public boolean isRootVisible()
2042: {
2043: return rootVisible;
2044: }
2045:
2046: public void setRootVisible(boolean flag)
2047: {
2048: if (rootVisible == flag)
2049: return;
2050:
2051:
2052: if (rootVisible && !flag)
2053: {
2054: TreeSelectionModel model = getSelectionModel();
2055:
2056: TreePath rootPath = getPathForRow(0);
2057: model.removeSelectionPath(rootPath);
2058: }
2059:
2060: boolean oldValue = rootVisible;
2061: rootVisible = flag;
2062: firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
2063:
2064: }
2065:
2066: public boolean getShowsRootHandles()
2067: {
2068: return showsRootHandles;
2069: }
2070:
2071: public void setShowsRootHandles(boolean flag)
2072: {
2073: clientShowsRootHandlesSet = true;
2074:
2075: if (showsRootHandles == flag)
2076: return;
2077:
2078: boolean oldValue = showsRootHandles;
2079: showsRootHandles = flag;
2080: firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue, flag);
2081: }
2082:
2083: public TreeCellEditor getCellEditor()
2084: {
2085: return cellEditor;
2086: }
2087:
2088: public void setCellEditor(TreeCellEditor editor)
2089: {
2090: if (cellEditor == editor)
2091: return;
2092:
2093: TreeCellEditor oldValue = cellEditor;
2094: cellEditor = editor;
2095: firePropertyChange(CELL_EDITOR_PROPERTY, oldValue, editor);
2096: }
2097:
2098: public TreeCellRenderer getCellRenderer()
2099: {
2100: return cellRenderer;
2101: }
2102:
2103: public void setCellRenderer(TreeCellRenderer newRenderer)
2104: {
2105: if (cellRenderer == newRenderer)
2106: return;
2107:
2108: TreeCellRenderer oldValue = cellRenderer;
2109: cellRenderer = newRenderer;
2110: firePropertyChange(CELL_RENDERER_PROPERTY, oldValue, newRenderer);
2111: }
2112:
2113: public TreeSelectionModel getSelectionModel()
2114: {
2115: return selectionModel;
2116: }
2117:
2118: public void setSelectionModel(TreeSelectionModel model)
2119: {
2120: if (selectionModel == model)
2121: return;
2122:
2123: if( model == null )
2124: model = EmptySelectionModel.sharedInstance();
2125:
2126: if (selectionModel != null)
2127: selectionModel.removeTreeSelectionListener(selectionRedirector);
2128:
2129: TreeSelectionModel oldValue = selectionModel;
2130: selectionModel = model;
2131:
2132: selectionModel.addTreeSelectionListener(selectionRedirector);
2133:
2134: firePropertyChange(SELECTION_MODEL_PROPERTY, oldValue, model);
2135: revalidate();
2136: repaint();
2137: }
2138:
2139: public int getVisibleRowCount()
2140: {
2141: return visibleRowCount;
2142: }
2143:
2144: public void setVisibleRowCount(int rows)
2145: {
2146: if (visibleRowCount == rows)
2147: return;
2148:
2149: int oldValue = visibleRowCount;
2150: visibleRowCount = rows;
2151: firePropertyChange(VISIBLE_ROW_COUNT_PROPERTY, oldValue, rows);
2152: }
2153:
2154: public boolean isLargeModel()
2155: {
2156: return largeModel;
2157: }
2158:
2159: public void setLargeModel(boolean large)
2160: {
2161: if (largeModel == large)
2162: return;
2163:
2164: boolean oldValue = largeModel;
2165: largeModel = large;
2166: firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, large);
2167: }
2168:
2169: public int getRowHeight()
2170: {
2171: return rowHeight;
2172: }
2173:
2174: public void setRowHeight(int height)
2175: {
2176: clientRowHeightSet = true;
2177:
2178: if (rowHeight == height)
2179: return;
2180:
2181: int oldValue = rowHeight;
2182: rowHeight = height;
2183: firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, height);
2184: }
2185:
2186: public boolean isFixedRowHeight()
2187: {
2188: return rowHeight > 0;
2189: }
2190:
2191: public boolean getInvokesStopCellEditing()
2192: {
2193: return invokesStopCellEditing;
2194: }
2195:
2196: public void setInvokesStopCellEditing(boolean invoke)
2197: {
2198: if (invokesStopCellEditing == invoke)
2199: return;
2200:
2201: boolean oldValue = invokesStopCellEditing;
2202: invokesStopCellEditing = invoke;
2203: firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY,
2204: oldValue, invoke);
2205: }
2206:
2207:
2210: public int getToggleClickCount()
2211: {
2212: return toggleClickCount;
2213: }
2214:
2215:
2218: public void setToggleClickCount(int count)
2219: {
2220: if (toggleClickCount == count)
2221: return;
2222:
2223: int oldValue = toggleClickCount;
2224: toggleClickCount = count;
2225: firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY, oldValue, count);
2226: }
2227:
2228: public void scrollPathToVisible(TreePath path)
2229: {
2230: if (path == null)
2231: return;
2232: Rectangle rect = getPathBounds(path);
2233: scrollRectToVisible(rect);
2234: }
2235:
2236: public void scrollRowToVisible(int row)
2237: {
2238: scrollPathToVisible(getPathForRow(row));
2239: }
2240:
2241: public boolean getScrollsOnExpand()
2242: {
2243: return scrollsOnExpand;
2244: }
2245:
2246: public void setScrollsOnExpand(boolean scroll)
2247: {
2248: clientScrollsOnExpandSet = true;
2249: if (scrollsOnExpand == scroll)
2250: return;
2251:
2252: boolean oldValue = scrollsOnExpand;
2253: scrollsOnExpand = scroll;
2254: firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue, scroll);
2255: }
2256:
2257: public void setSelectionPath(TreePath path)
2258: {
2259: clearSelectionPathStates();
2260: selectionModel.setSelectionPath(path);
2261: }
2262:
2263: public void setSelectionPaths(TreePath[] paths)
2264: {
2265: clearSelectionPathStates();
2266: selectionModel.setSelectionPaths(paths);
2267: }
2268:
2269:
2274: private void clearSelectionPathStates()
2275: {
2276: TreePath[] oldPaths = selectionModel.getSelectionPaths();
2277: if (oldPaths != null)
2278: for (int i = 0; i < oldPaths.length; i++)
2279: nodeStates.remove(oldPaths[i]);
2280: }
2281:
2282: public void setSelectionRow(int row)
2283: {
2284: TreePath path = getPathForRow(row);
2285:
2286: if (path != null)
2287: setSelectionPath(path);
2288: }
2289:
2290: public void setSelectionRows(int[] rows)
2291: {
2292:
2293: if (rows == null || getUI() == null)
2294: return;
2295:
2296: TreePath[] paths = new TreePath[rows.length];
2297:
2298: for (int i = rows.length - 1; i >= 0; --i)
2299: paths[i] = getPathForRow(rows[i]);
2300:
2301: setSelectionPaths(paths);
2302: }
2303:
2304: public void setSelectionInterval(int index0, int index1)
2305: {
2306: TreePath[] paths = getPathBetweenRows(index0, index1);
2307:
2308: if (paths != null)
2309: setSelectionPaths(paths);
2310: }
2311:
2312: public void addSelectionPath(TreePath path)
2313: {
2314: selectionModel.addSelectionPath(path);
2315: }
2316:
2317: public void addSelectionPaths(TreePath[] paths)
2318: {
2319: selectionModel.addSelectionPaths(paths);
2320: }
2321:
2322: public void addSelectionRow(int row)
2323: {
2324: TreePath path = getPathForRow(row);
2325:
2326: if (path != null)
2327: selectionModel.addSelectionPath(path);
2328: }
2329:
2330: public void addSelectionRows(int[] rows)
2331: {
2332:
2333: if (rows == null || getUI() == null)
2334: return;
2335:
2336: TreePath[] paths = new TreePath[rows.length];
2337:
2338: for (int i = rows.length - 1; i >= 0; --i)
2339: paths[i] = getPathForRow(rows[i]);
2340:
2341: addSelectionPaths(paths);
2342: }
2343:
2344:
2352: public void addSelectionInterval(int index0, int index1)
2353: {
2354: TreePath[] paths = getPathBetweenRows(index0, index1);
2355:
2356: if (paths != null)
2357: addSelectionPaths(paths);
2358: }
2359:
2360: public void removeSelectionPath(TreePath path)
2361: {
2362: clearSelectionPathStates();
2363: selectionModel.removeSelectionPath(path);
2364: }
2365:
2366: public void removeSelectionPaths(TreePath[] paths)
2367: {
2368: clearSelectionPathStates();
2369: selectionModel.removeSelectionPaths(paths);
2370: }
2371:
2372: public void removeSelectionRow(int row)
2373: {
2374: TreePath path = getPathForRow(row);
2375:
2376: if (path != null)
2377: removeSelectionPath(path);
2378: }
2379:
2380: public void removeSelectionRows(int[] rows)
2381: {
2382: if (rows == null || getUI() == null)
2383: return;
2384:
2385: TreePath[] paths = new TreePath[rows.length];
2386:
2387: for (int i = rows.length - 1; i >= 0; --i)
2388: paths[i] = getPathForRow(rows[i]);
2389:
2390: removeSelectionPaths(paths);
2391: }
2392:
2393: public void removeSelectionInterval(int index0, int index1)
2394: {
2395: TreePath[] paths = getPathBetweenRows(index0, index1);
2396:
2397: if (paths != null)
2398: removeSelectionPaths(paths);
2399: }
2400:
2401: public void clearSelection()
2402: {
2403: selectionModel.clearSelection();
2404: setLeadSelectionPath(null);
2405: }
2406:
2407: public TreePath getLeadSelectionPath()
2408: {
2409: if (selectionModel == null)
2410: return null;
2411: else
2412: return selectionModel.getLeadSelectionPath();
2413: }
2414:
2415:
2418: public void setLeadSelectionPath(TreePath path)
2419: {
2420: if (selectionModel != null)
2421: {
2422: TreePath oldValue = selectionModel.getLeadSelectionPath();
2423: if (path == oldValue || path != null && path.equals(oldValue))
2424: return;
2425:
2426:
2427: if (path != null)
2428: {
2429: repaint(getPathBounds(path));
2430: selectionModel.addSelectionPath(path);
2431: }
2432:
2433: if (oldValue != null)
2434: repaint(getPathBounds(oldValue));
2435:
2436: firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);
2437: }
2438: }
2439:
2440:
2443: public TreePath getAnchorSelectionPath()
2444: {
2445: return anchorSelectionPath;
2446: }
2447:
2448:
2451: public void setAnchorSelectionPath(TreePath path)
2452: {
2453: if (anchorSelectionPath == path)
2454: return;
2455:
2456: TreePath oldValue = anchorSelectionPath;
2457: anchorSelectionPath = path;
2458: firePropertyChange(ANCHOR_SELECTION_PATH_PROPERTY, oldValue, path);
2459: }
2460:
2461: public int getLeadSelectionRow()
2462: {
2463: return selectionModel.getLeadSelectionRow();
2464: }
2465:
2466: public int getMaxSelectionRow()
2467: {
2468: return selectionModel.getMaxSelectionRow();
2469: }
2470:
2471: public int getMinSelectionRow()
2472: {
2473: return selectionModel.getMinSelectionRow();
2474: }
2475:
2476: public int getSelectionCount()
2477: {
2478: return selectionModel.getSelectionCount();
2479: }
2480:
2481: public TreePath getSelectionPath()
2482: {
2483: return selectionModel.getSelectionPath();
2484: }
2485:
2486: public TreePath[] getSelectionPaths()
2487: {
2488: return selectionModel.getSelectionPaths();
2489: }
2490:
2491: public int[] getSelectionRows()
2492: {
2493: return selectionModel.getSelectionRows();
2494: }
2495:
2496: public boolean isPathSelected(TreePath path)
2497: {
2498: return selectionModel.isPathSelected(path);
2499: }
2500:
2501:
2511: public boolean isRowSelected(int row)
2512: {
2513: return selectionModel.isRowSelected(row);
2514: }
2515:
2516: public boolean isSelectionEmpty()
2517: {
2518: return selectionModel.isSelectionEmpty();
2519: }
2520:
2521:
2528: public boolean getDragEnabled()
2529: {
2530: return dragEnabled;
2531: }
2532:
2533:
2540: public void setDragEnabled(boolean enabled)
2541: {
2542: dragEnabled = enabled;
2543: }
2544:
2545: public int getRowCount()
2546: {
2547: TreeUI ui = getUI();
2548:
2549: if (ui != null)
2550: return ui.getRowCount(this);
2551:
2552: return 0;
2553: }
2554:
2555: public void collapsePath(TreePath path)
2556: {
2557: try
2558: {
2559: fireTreeWillCollapse(path);
2560: }
2561: catch (ExpandVetoException ev)
2562: {
2563:
2564: }
2565: setExpandedState(path, false);
2566: fireTreeCollapsed(path);
2567: }
2568:
2569: public void collapseRow(int row)
2570: {
2571: if (row < 0 || row >= getRowCount())
2572: return;
2573:
2574: TreePath path = getPathForRow(row);
2575:
2576: if (path != null)
2577: collapsePath(path);
2578: }
2579:
2580: public void expandPath(TreePath path)
2581: {
2582:
2583:
2584: if (path == null || isExpanded(path))
2585: return;
2586:
2587: try
2588: {
2589: fireTreeWillExpand(path);
2590: }
2591: catch (ExpandVetoException ev)
2592: {
2593:
2594: }
2595:
2596: setExpandedState(path, true);
2597: fireTreeExpanded(path);
2598: }
2599:
2600: public void expandRow(int row)
2601: {
2602: if (row < 0 || row >= getRowCount())
2603: return;
2604:
2605: TreePath path = getPathForRow(row);
2606:
2607: if (path != null)
2608: expandPath(path);
2609: }
2610:
2611: public boolean isCollapsed(TreePath path)
2612: {
2613: return !isExpanded(path);
2614: }
2615:
2616: public boolean isCollapsed(int row)
2617: {
2618: if (row < 0 || row >= getRowCount())
2619: return false;
2620:
2621: TreePath path = getPathForRow(row);
2622:
2623: if (path != null)
2624: return isCollapsed(path);
2625:
2626: return false;
2627: }
2628:
2629: public boolean isExpanded(TreePath path)
2630: {
2631: if (path == null)
2632: return false;
2633:
2634: Object state = nodeStates.get(path);
2635:
2636: if ((state == null) || (state != EXPANDED))
2637: return false;
2638:
2639: TreePath parent = path.getParentPath();
2640:
2641: if (parent != null)
2642: return isExpanded(parent);
2643:
2644: return true;
2645: }
2646:
2647: public boolean isExpanded(int row)
2648: {
2649: if (row < 0 || row >= getRowCount())
2650: return false;
2651:
2652: TreePath path = getPathForRow(row);
2653:
2654: if (path != null)
2655: return isExpanded(path);
2656:
2657: return false;
2658: }
2659:
2660:
2663: public boolean getExpandsSelectedPaths()
2664: {
2665: return expandsSelectedPaths;
2666: }
2667:
2668:
2671: public void setExpandsSelectedPaths(boolean flag)
2672: {
2673: if (expandsSelectedPaths == flag)
2674: return;
2675:
2676: boolean oldValue = expandsSelectedPaths;
2677: expandsSelectedPaths = flag;
2678: firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY, oldValue, flag);
2679: }
2680:
2681: public Rectangle getPathBounds(TreePath path)
2682: {
2683: TreeUI ui = getUI();
2684:
2685: if (ui == null)
2686: return null;
2687:
2688: return ui.getPathBounds(this, path);
2689: }
2690:
2691: public Rectangle getRowBounds(int row)
2692: {
2693: TreePath path = getPathForRow(row);
2694:
2695: if (path != null)
2696: return getPathBounds(path);
2697:
2698: return null;
2699: }
2700:
2701: public boolean isEditing()
2702: {
2703: TreeUI ui = getUI();
2704:
2705: if (ui != null)
2706: return ui.isEditing(this);
2707:
2708: return false;
2709: }
2710:
2711: public boolean stopEditing()
2712: {
2713: TreeUI ui = getUI();
2714:
2715: if (isEditing())
2716: if (ui != null)
2717: return ui.stopEditing(this);
2718:
2719: return false;
2720: }
2721:
2722: public void cancelEditing()
2723: {
2724: TreeUI ui = getUI();
2725:
2726: if (isEditing())
2727: if (ui != null)
2728: ui.cancelEditing(this);
2729: }
2730:
2731: public void startEditingAtPath(TreePath path)
2732: {
2733: TreeUI ui = getUI();
2734:
2735: if (ui != null)
2736: ui.startEditingAtPath(this, path);
2737: }
2738:
2739: public TreePath getEditingPath()
2740: {
2741: TreeUI ui = getUI();
2742:
2743: if (ui != null)
2744: return ui.getEditingPath(this);
2745:
2746: return null;
2747: }
2748:
2749: public TreePath getPathForLocation(int x, int y)
2750: {
2751: TreePath path = getClosestPathForLocation(x, y);
2752:
2753: if (path != null)
2754: {
2755: Rectangle rect = getPathBounds(path);
2756:
2757: if ((rect != null) && rect.contains(x, y))
2758: return path;
2759: }
2760:
2761: return null;
2762: }
2763:
2764: public int getRowForLocation(int x, int y)
2765: {
2766: TreePath path = getPathForLocation(x, y);
2767:
2768: if (path != null)
2769: return getRowForPath(path);
2770:
2771: return -1;
2772: }
2773:
2774: public TreePath getClosestPathForLocation(int x, int y)
2775: {
2776: TreeUI ui = getUI();
2777:
2778: if (ui != null)
2779: return ui.getClosestPathForLocation(this, x, y);
2780:
2781: return null;
2782: }
2783:
2784: public int getClosestRowForLocation(int x, int y)
2785: {
2786: TreePath path = getClosestPathForLocation(x, y);
2787:
2788: if (path != null)
2789: return getRowForPath(path);
2790:
2791: return -1;
2792: }
2793:
2794: public Object getLastSelectedPathComponent()
2795: {
2796: TreePath path = getSelectionPath();
2797:
2798: if (path != null)
2799: return path.getLastPathComponent();
2800:
2801: return null;
2802: }
2803:
2804: private void doExpandParents(TreePath path, boolean state)
2805: {
2806: TreePath parent = path.getParentPath();
2807:
2808: if (!isExpanded(parent) && parent != null)
2809: doExpandParents(parent, false);
2810:
2811: nodeStates.put(path, state ? EXPANDED : COLLAPSED);
2812: }
2813:
2814: protected void setExpandedState(TreePath path, boolean state)
2815: {
2816: if (path == null)
2817: return;
2818:
2819: doExpandParents(path, state);
2820: }
2821:
2822: protected void clearToggledPaths()
2823: {
2824: nodeStates.clear();
2825: }
2826:
2827: protected Enumeration<TreePath> getDescendantToggledPaths(TreePath parent)
2828: {
2829: if (parent == null)
2830: return null;
2831:
2832: Enumeration nodes = nodeStates.keys();
2833: Vector result = new Vector();
2834:
2835: while (nodes.hasMoreElements())
2836: {
2837: TreePath path = (TreePath) nodes.nextElement();
2838:
2839: if (path.isDescendant(parent))
2840: result.addElement(path);
2841: }
2842:
2843: return result.elements();
2844: }
2845:
2846: public boolean hasBeenExpanded(TreePath path)
2847: {
2848: if (path == null)
2849: return false;
2850:
2851: return nodeStates.get(path) != null;
2852: }
2853:
2854: public boolean isVisible(TreePath path)
2855: {
2856: if (path == null)
2857: return false;
2858:
2859: TreePath parent = path.getParentPath();
2860:
2861: if (parent == null)
2862: return true;
2863:
2864: return isExpanded(parent);
2865: }
2866:
2867: public void makeVisible(TreePath path)
2868: {
2869: if (path == null)
2870: return;
2871:
2872: expandPath(path.getParentPath());
2873: }
2874:
2875: public boolean isPathEditable(TreePath path)
2876: {
2877: return isEditable();
2878: }
2879:
2880:
2885: protected TreeModelListener createTreeModelListener()
2886: {
2887: return new TreeModelHandler();
2888: }
2889:
2890:
2896: protected static TreeModel getDefaultTreeModel()
2897: {
2898: DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root node");
2899: DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child node 1");
2900: DefaultMutableTreeNode child11 =
2901: new DefaultMutableTreeNode("Child node 1.1");
2902: DefaultMutableTreeNode child12 =
2903: new DefaultMutableTreeNode("Child node 1.2");
2904: DefaultMutableTreeNode child13 =
2905: new DefaultMutableTreeNode("Child node 1.3");
2906: DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child node 2");
2907: DefaultMutableTreeNode child21 =
2908: new DefaultMutableTreeNode("Child node 2.1");
2909: DefaultMutableTreeNode child22 =
2910: new DefaultMutableTreeNode("Child node 2.2");
2911: DefaultMutableTreeNode child23 =
2912: new DefaultMutableTreeNode("Child node 2.3");
2913: DefaultMutableTreeNode child24 =
2914: new DefaultMutableTreeNode("Child node 2.4");
2915:
2916: DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("Child node 3");
2917: root.add(child1);
2918: root.add(child2);
2919: root.add(child3);
2920: child1.add(child11);
2921: child1.add(child12);
2922: child1.add(child13);
2923: child2.add(child21);
2924: child2.add(child22);
2925: child2.add(child23);
2926: child2.add(child24);
2927: return new DefaultTreeModel(root);
2928: }
2929:
2930:
2945: public String convertValueToText(Object value, boolean selected,
2946: boolean expanded, boolean leaf, int row, boolean hasFocus)
2947: {
2948: return value.toString();
2949: }
2950:
2951:
2958: protected String paramString()
2959: {
2960:
2961:
2962:
2963: return "";
2964: }
2965:
2966:
2976: public Enumeration<TreePath> getExpandedDescendants(TreePath path)
2977: {
2978: Enumeration paths = nodeStates.keys();
2979: Vector relevantPaths = new Vector();
2980: while (paths.hasMoreElements())
2981: {
2982: TreePath nextPath = (TreePath) paths.nextElement();
2983: if (nodeStates.get(nextPath) == EXPANDED
2984: && path.isDescendant(nextPath))
2985: {
2986: relevantPaths.add(nextPath);
2987: }
2988: }
2989: return relevantPaths.elements();
2990: }
2991:
2992:
3010: public TreePath getNextMatch(String prefix, int startingRow,
3011: Position.Bias bias)
3012: {
3013: if (prefix == null)
3014: throw new IllegalArgumentException("The argument 'prefix' must not be"
3015: + " null.");
3016: if (startingRow < 0)
3017: throw new IllegalArgumentException("The argument 'startingRow' must not"
3018: + " be less than zero.");
3019:
3020: int size = getRowCount();
3021: if (startingRow > size)
3022: throw new IllegalArgumentException("The argument 'startingRow' must not"
3023: + " be greater than the number of"
3024: + " elements in the TreeModel.");
3025:
3026: TreePath foundPath = null;
3027: if (bias == Position.Bias.Forward)
3028: {
3029: for (int i = startingRow; i < size; i++)
3030: {
3031: TreePath path = getPathForRow(i);
3032: Object o = path.getLastPathComponent();
3033:
3034:
3035: String item = convertValueToText(o, isRowSelected(i),
3036: isExpanded(i), treeModel.isLeaf(o),
3037: i, false);
3038: if (item.startsWith(prefix))
3039: {
3040: foundPath = path;
3041: break;
3042: }
3043: }
3044: }
3045: else
3046: {
3047: for (int i = startingRow; i >= 0; i--)
3048: {
3049: TreePath path = getPathForRow(i);
3050: Object o = path.getLastPathComponent();
3051:
3052:
3053: String item = convertValueToText(o, isRowSelected(i),
3054: isExpanded(i), treeModel.isLeaf(o), i, false);
3055: if (item.startsWith(prefix))
3056: {
3057: foundPath = path;
3058: break;
3059: }
3060: }
3061: }
3062: return foundPath;
3063: }
3064:
3065:
3080: protected boolean removeDescendantSelectedPaths(TreePath path,
3081: boolean includeSelected)
3082: {
3083: boolean removedSomething = false;
3084: TreePath[] selected = getSelectionPaths();
3085: for (int index = 0; index < selected.length; index++)
3086: {
3087: if ((selected[index] == path && includeSelected)
3088: || (selected[index].isDescendant(path)))
3089: {
3090: removeSelectionPath(selected[index]);
3091: removedSomething = true;
3092: }
3093: }
3094: return removedSomething;
3095: }
3096:
3097:
3104: protected void removeDescendantToggledPaths(Enumeration<TreePath> toRemove)
3105: {
3106: while (toRemove.hasMoreElements())
3107: {
3108: TreePath current = (TreePath) toRemove.nextElement();
3109: Enumeration descendants = getDescendantToggledPaths(current);
3110:
3111: while (descendants.hasMoreElements())
3112: {
3113: TreePath currentDes = (TreePath) descendants.nextElement();
3114: if (isExpanded(currentDes))
3115: nodeStates.remove(currentDes);
3116: }
3117: }
3118: }
3119:
3120:
3136: public void treeDidChange()
3137: {
3138: repaint();
3139: }
3140:
3141:
3155: void setUIProperty(String propertyName, Object value)
3156: {
3157: if (propertyName.equals("rowHeight"))
3158: {
3159: if (! clientRowHeightSet)
3160: {
3161: setRowHeight(((Integer) value).intValue());
3162: clientRowHeightSet = false;
3163: }
3164: }
3165: else if (propertyName.equals("scrollsOnExpand"))
3166: {
3167: if (! clientScrollsOnExpandSet)
3168: {
3169: setScrollsOnExpand(((Boolean) value).booleanValue());
3170: clientScrollsOnExpandSet = false;
3171: }
3172: }
3173: else if (propertyName.equals("showsRootHandles"))
3174: {
3175: if (! clientShowsRootHandlesSet)
3176: {
3177: setShowsRootHandles(((Boolean) value).booleanValue());
3178: clientShowsRootHandlesSet = false;
3179: }
3180: }
3181: else
3182: {
3183: super.setUIProperty(propertyName, value);
3184: }
3185: }
3186: }