1:
37:
38:
39: package ;
40:
41: import ;
42:
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: import ;
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:
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: import ;
86: import ;
87: import ;
88: import ;
89: import ;
90: import ;
91: import ;
92: import ;
93: import ;
94: import ;
95: import ;
96: import ;
97: import ;
98: import ;
99: import ;
100: import ;
101: import ;
102: import ;
103: import ;
104: import ;
105: import ;
106: import ;
107: import ;
108: import ;
109: import ;
110: import ;
111:
112:
121: public class BasicTreeUI
122: extends TreeUI
123: {
124:
130: static int WAIT_TILL_EDITING = 900;
131:
132:
133: protected transient Icon collapsedIcon;
134:
135:
136: protected transient Icon expandedIcon;
137:
138:
139: protected int leftChildIndent;
140:
141:
144: protected int rightChildIndent;
145:
146:
150: protected int totalChildIndent;
151:
152:
153: protected int lastSelectedRow;
154:
155:
156: protected JTree tree;
157:
158:
159: protected transient TreeCellRenderer currentCellRenderer;
160:
161:
165: protected boolean createdRenderer;
166:
167:
168: protected transient TreeCellEditor cellEditor;
169:
170:
174: protected boolean createdCellEditor;
175:
176:
180: protected boolean stopEditingInCompleteEditing;
181:
182:
183: protected CellRendererPane rendererPane;
184:
185:
186: protected Dimension preferredSize;
187:
188:
189: protected Dimension preferredMinSize;
190:
191:
192: protected boolean validCachedPreferredSize;
193:
194:
195: protected AbstractLayoutCache treeState;
196:
197:
198: protected Hashtable drawingCache;
199:
200:
205: protected boolean largeModel;
206:
207:
208: protected AbstractLayoutCache.NodeDimensions nodeDimensions;
209:
210:
211: protected TreeModel treeModel;
212:
213:
214: protected TreeSelectionModel treeSelectionModel;
215:
216:
221: protected int depthOffset;
222:
223:
226: protected Component editingComponent;
227:
228:
229: protected TreePath editingPath;
230:
231:
235: protected int editingRow;
236:
237:
238: protected boolean editorHasDifferentSize;
239:
240:
241: TreeAction action;
242:
243:
244: boolean isEditing;
245:
246:
247: TreePath currentVisiblePath;
248:
249:
250: int gap = 4;
251:
252:
253: int maxHeight = 0;
254:
255:
256: PropertyChangeListener propertyChangeListener;
257:
258: FocusListener focusListener;
259:
260: TreeSelectionListener treeSelectionListener;
261:
262: MouseListener mouseListener;
263:
264: KeyListener keyListener;
265:
266: PropertyChangeListener selectionModelPropertyChangeListener;
267:
268: ComponentListener componentListener;
269:
270: CellEditorListener cellEditorListener;
271:
272: TreeExpansionListener treeExpansionListener;
273:
274: TreeModelListener treeModelListener;
275:
276:
281: Timer startEditTimer;
282:
283:
288: static final MouseEvent EDIT = new MouseEvent(new Label(), 7, 7, 7, 7, 7, 7,
289: false);
290:
291:
294: public BasicTreeUI()
295: {
296: validCachedPreferredSize = false;
297: drawingCache = new Hashtable();
298: nodeDimensions = createNodeDimensions();
299: configureLayoutCache();
300:
301: propertyChangeListener = createPropertyChangeListener();
302: focusListener = createFocusListener();
303: treeSelectionListener = createTreeSelectionListener();
304: mouseListener = createMouseListener();
305: keyListener = createKeyListener();
306: selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener();
307: componentListener = createComponentListener();
308: cellEditorListener = createCellEditorListener();
309: treeExpansionListener = createTreeExpansionListener();
310: treeModelListener = createTreeModelListener();
311:
312: editingRow = - 1;
313: lastSelectedRow = - 1;
314: }
315:
316:
322: public static ComponentUI createUI(JComponent c)
323: {
324: return new BasicTreeUI();
325: }
326:
327:
332: protected Color getHashColor()
333: {
334: return UIManager.getColor("Tree.hash");
335: }
336:
337:
342: protected void setHashColor(Color color)
343: {
344:
345: UIManager.put("Tree.hash", color);
346: }
347:
348:
353: public void setLeftChildIndent(int newAmount)
354: {
355: leftChildIndent = newAmount;
356: }
357:
358:
363: public int getLeftChildIndent()
364: {
365: return leftChildIndent;
366: }
367:
368:
373: public void setRightChildIndent(int newAmount)
374: {
375: rightChildIndent = newAmount;
376: }
377:
378:
383: public int getRightChildIndent()
384: {
385: return rightChildIndent;
386: }
387:
388:
393: public void setExpandedIcon(Icon newG)
394: {
395: expandedIcon = newG;
396: }
397:
398:
403: public Icon getExpandedIcon()
404: {
405: return expandedIcon;
406: }
407:
408:
413: public void setCollapsedIcon(Icon newG)
414: {
415: collapsedIcon = newG;
416: }
417:
418:
423: public Icon getCollapsedIcon()
424: {
425: return collapsedIcon;
426: }
427:
428:
433: protected void setLargeModel(boolean largeModel)
434: {
435: if (largeModel != this.largeModel)
436: {
437: tree.removeComponentListener(componentListener);
438: this.largeModel = largeModel;
439: tree.addComponentListener(componentListener);
440: }
441: }
442:
443:
448: protected boolean isLargeModel()
449: {
450: return largeModel;
451: }
452:
453:
458: protected void setRowHeight(int rowHeight)
459: {
460: if (rowHeight == 0)
461: rowHeight = getMaxHeight(tree);
462: treeState.setRowHeight(rowHeight);
463: }
464:
465:
470: protected int getRowHeight()
471: {
472: return tree.getRowHeight();
473: }
474:
475:
481: protected void setCellRenderer(TreeCellRenderer tcr)
482: {
483: currentCellRenderer = tcr;
484: updateRenderer();
485: }
486:
487:
493: protected TreeCellRenderer getCellRenderer()
494: {
495: if (currentCellRenderer != null)
496: return currentCellRenderer;
497:
498: return createDefaultCellRenderer();
499: }
500:
501:
506: protected void setModel(TreeModel model)
507: {
508: tree.setModel(model);
509: treeModel = tree.getModel();
510: treeState.setModel(treeModel);
511: }
512:
513:
518: protected TreeModel getModel()
519: {
520: return treeModel;
521: }
522:
523:
528: protected void setRootVisible(boolean newValue)
529: {
530: tree.setRootVisible(newValue);
531: }
532:
533:
538: protected boolean isRootVisible()
539: {
540: return tree.isRootVisible();
541: }
542:
543:
548: protected void setShowsRootHandles(boolean newValue)
549: {
550: tree.setShowsRootHandles(newValue);
551: }
552:
553:
558: protected boolean getShowsRootHandles()
559: {
560: return tree.getShowsRootHandles();
561: }
562:
563:
568: protected void setCellEditor(TreeCellEditor editor)
569: {
570: cellEditor = editor;
571: createdCellEditor = true;
572: }
573:
574:
579: protected TreeCellEditor getCellEditor()
580: {
581: return cellEditor;
582: }
583:
584:
589: protected void setEditable(boolean newValue)
590: {
591: tree.setEditable(newValue);
592: }
593:
594:
599: protected boolean isEditable()
600: {
601: return tree.isEditable();
602: }
603:
604:
610: protected void setSelectionModel(TreeSelectionModel newLSM)
611: {
612: if (newLSM != null)
613: {
614: treeSelectionModel = newLSM;
615: tree.setSelectionModel(treeSelectionModel);
616: }
617: }
618:
619:
624: protected TreeSelectionModel getSelectionModel()
625: {
626: return treeSelectionModel;
627: }
628:
629:
639: public Rectangle getPathBounds(JTree tree, TreePath path)
640: {
641: return treeState.getBounds(path, new Rectangle());
642: }
643:
644:
650: int getMaxHeight(JTree tree)
651: {
652: if (maxHeight != 0)
653: return maxHeight;
654:
655: Icon e = UIManager.getIcon("Tree.openIcon");
656: Icon c = UIManager.getIcon("Tree.closedIcon");
657: Icon l = UIManager.getIcon("Tree.leafIcon");
658: int rc = getRowCount(tree);
659: int iconHeight = 0;
660:
661: for (int row = 0; row < rc; row++)
662: {
663: if (isLeaf(row))
664: iconHeight = l.getIconHeight();
665: else if (tree.isExpanded(row))
666: iconHeight = e.getIconHeight();
667: else
668: iconHeight = c.getIconHeight();
669:
670: maxHeight = Math.max(maxHeight, iconHeight + gap);
671: }
672:
673: treeState.setRowHeight(maxHeight);
674: return maxHeight;
675: }
676:
677:
684: public TreePath getPathForRow(JTree tree, int row)
685: {
686: return treeState.getPathForRow(row);
687: }
688:
689:
699: public int getRowForPath(JTree tree, TreePath path)
700: {
701: return treeState.getRowForPath(path);
702: }
703:
704:
710: public int getRowCount(JTree tree)
711: {
712: return treeState.getRowCount();
713: }
714:
715:
726: public TreePath getClosestPathForLocation(JTree tree, int x, int y)
727: {
728: return treeState.getPathClosestTo(x, y);
729: }
730:
731:
738: public boolean isEditing(JTree tree)
739: {
740: return isEditing;
741: }
742:
743:
751: public boolean stopEditing(JTree tree)
752: {
753: if (isEditing(tree))
754: {
755: completeEditing(false, false, true);
756: finish();
757: }
758: return ! isEditing(tree);
759: }
760:
761:
766: public void cancelEditing(JTree tree)
767: {
768:
769:
770:
771: completeEditing(false, false, false);
772: finish();
773: }
774:
775:
782: public void startEditingAtPath(JTree tree, TreePath path)
783: {
784: startEditing(path, null);
785: }
786:
787:
793: public TreePath getEditingPath(JTree tree)
794: {
795: return editingPath;
796: }
797:
798:
802: protected void prepareForUIInstall()
803: {
804:
805: }
806:
807:
811: protected void completeUIInstall()
812: {
813:
814: }
815:
816:
820: protected void completeUIUninstall()
821: {
822:
823: }
824:
825:
828: protected void installComponents()
829: {
830: currentCellRenderer = createDefaultCellRenderer();
831: rendererPane = createCellRendererPane();
832: createdRenderer = true;
833: setCellRenderer(currentCellRenderer);
834: }
835:
836:
843: protected AbstractLayoutCache.NodeDimensions createNodeDimensions()
844: {
845: return new NodeDimensionsHandler();
846: }
847:
848:
854: protected PropertyChangeListener createPropertyChangeListener()
855: {
856: return new PropertyChangeHandler();
857: }
858:
859:
865: protected MouseListener createMouseListener()
866: {
867: return new MouseHandler();
868: }
869:
870:
876: protected FocusListener createFocusListener()
877: {
878: return new FocusHandler();
879: }
880:
881:
886: protected KeyListener createKeyListener()
887: {
888: return new KeyHandler();
889: }
890:
891:
898: protected PropertyChangeListener createSelectionModelPropertyChangeListener()
899: {
900: return new SelectionModelPropertyChangeHandler();
901: }
902:
903:
909: protected TreeSelectionListener createTreeSelectionListener()
910: {
911: return new TreeSelectionHandler();
912: }
913:
914:
919: protected CellEditorListener createCellEditorListener()
920: {
921: return new CellEditorHandler();
922: }
923:
924:
931: protected ComponentListener createComponentListener()
932: {
933: return new ComponentHandler();
934: }
935:
936:
942: protected TreeExpansionListener createTreeExpansionListener()
943: {
944: return new TreeExpansionHandler();
945: }
946:
947:
953: protected AbstractLayoutCache createLayoutCache()
954: {
955: return new VariableHeightLayoutCache();
956: }
957:
958:
963: protected CellRendererPane createCellRendererPane()
964: {
965: return new CellRendererPane();
966: }
967:
968:
973: protected TreeCellEditor createDefaultCellEditor()
974: {
975: if (currentCellRenderer != null)
976: return new DefaultTreeCellEditor(
977: tree,
978: (DefaultTreeCellRenderer) currentCellRenderer,
979: cellEditor);
980: return new DefaultTreeCellEditor(
981: tree,
982: (DefaultTreeCellRenderer) createDefaultCellRenderer(),
983: cellEditor);
984: }
985:
986:
993: protected TreeCellRenderer createDefaultCellRenderer()
994: {
995: return new DefaultTreeCellRenderer();
996: }
997:
998:
1003: protected TreeModelListener createTreeModelListener()
1004: {
1005: return new TreeModelHandler();
1006: }
1007:
1008:
1011: protected void uninstallListeners()
1012: {
1013: tree.removePropertyChangeListener(propertyChangeListener);
1014: tree.removeFocusListener(focusListener);
1015: tree.removeTreeSelectionListener(treeSelectionListener);
1016: tree.removeMouseListener(mouseListener);
1017: tree.removeKeyListener(keyListener);
1018: tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
1019: tree.removeComponentListener(componentListener);
1020: tree.removeTreeExpansionListener(treeExpansionListener);
1021:
1022: TreeCellEditor tce = tree.getCellEditor();
1023: if (tce != null)
1024: tce.removeCellEditorListener(cellEditorListener);
1025: if (treeModel != null)
1026: treeModel.removeTreeModelListener(treeModelListener);
1027: }
1028:
1029:
1032: protected void uninstallKeyboardActions()
1033: {
1034: action = null;
1035: tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).setParent(
1036: null);
1037: tree.getActionMap().setParent(null);
1038: }
1039:
1040:
1043: protected void uninstallComponents()
1044: {
1045: currentCellRenderer = null;
1046: rendererPane = null;
1047: createdRenderer = false;
1048: setCellRenderer(currentCellRenderer);
1049: }
1050:
1051:
1057: protected int getVerticalLegBuffer()
1058: {
1059: return getRowHeight() / 2;
1060: }
1061:
1062:
1069: protected int getHorizontalLegBuffer()
1070: {
1071: return rightChildIndent / 2;
1072: }
1073:
1074:
1078: protected void updateLayoutCacheExpandedNodes()
1079: {
1080: if (treeModel != null)
1081: updateExpandedDescendants(new TreePath(treeModel.getRoot()));
1082: }
1083:
1084:
1091: protected void updateExpandedDescendants(TreePath path)
1092: {
1093: Enumeration expanded = tree.getExpandedDescendants(path);
1094: while (expanded.hasMoreElements())
1095: treeState.setExpandedState(((TreePath) expanded.nextElement()), true);
1096: }
1097:
1098:
1104: protected TreePath getLastChildPath(TreePath parent)
1105: {
1106: return ((TreePath) parent.getLastPathComponent());
1107: }
1108:
1109:
1112: protected void updateDepthOffset()
1113: {
1114: depthOffset += getVerticalLegBuffer();
1115: }
1116:
1117:
1122: protected void updateCellEditor()
1123: {
1124: if (tree.isEditable() && cellEditor == null)
1125: setCellEditor(createDefaultCellEditor());
1126: createdCellEditor = true;
1127: }
1128:
1129:
1132: protected void updateRenderer()
1133: {
1134: if (tree != null)
1135: {
1136: if (tree.getCellRenderer() == null)
1137: {
1138: if (currentCellRenderer == null)
1139: currentCellRenderer = createDefaultCellRenderer();
1140: tree.setCellRenderer(currentCellRenderer);
1141: }
1142: }
1143: }
1144:
1145:
1150: protected void configureLayoutCache()
1151: {
1152: treeState = createLayoutCache();
1153: treeState.setNodeDimensions(nodeDimensions);
1154: }
1155:
1156:
1160: protected void updateSize()
1161: {
1162: preferredSize = null;
1163: updateCachedPreferredSize();
1164: tree.treeDidChange();
1165: }
1166:
1167:
1171: protected void updateCachedPreferredSize()
1172: {
1173: validCachedPreferredSize = false;
1174: }
1175:
1176:
1181: protected void pathWasExpanded(TreePath path)
1182: {
1183: validCachedPreferredSize = false;
1184: treeState.setExpandedState(path, true);
1185: tree.repaint();
1186: }
1187:
1188:
1191: protected void pathWasCollapsed(TreePath path)
1192: {
1193: validCachedPreferredSize = false;
1194: treeState.setExpandedState(path, false);
1195: tree.repaint();
1196: }
1197:
1198:
1201: protected void installDefaults()
1202: {
1203: LookAndFeel.installColorsAndFont(tree, "Tree.background",
1204: "Tree.foreground", "Tree.font");
1205: tree.setOpaque(true);
1206:
1207: rightChildIndent = UIManager.getInt("Tree.rightChildIndent");
1208: leftChildIndent = UIManager.getInt("Tree.leftChildIndent");
1209: setRowHeight(UIManager.getInt("Tree.rowHeight"));
1210: tree.setRowHeight(getRowHeight());
1211: tree.setScrollsOnExpand(UIManager.getBoolean("Tree.scrollsOnExpand"));
1212: setExpandedIcon(UIManager.getIcon("Tree.expandedIcon"));
1213: setCollapsedIcon(UIManager.getIcon("Tree.collapsedIcon"));
1214: }
1215:
1216:
1219: protected void installKeyboardActions()
1220: {
1221: InputMap focusInputMap = (InputMap) UIManager.get("Tree.focusInputMap");
1222: InputMapUIResource parentInputMap = new InputMapUIResource();
1223: ActionMap parentActionMap = new ActionMapUIResource();
1224: action = new TreeAction();
1225: Object keys[] = focusInputMap.allKeys();
1226:
1227: for (int i = 0; i < keys.length; i++)
1228: {
1229: parentInputMap.put(
1230: KeyStroke.getKeyStroke(
1231: ((KeyStroke) keys[i]).getKeyCode(),
1232: convertModifiers(((KeyStroke) keys[i]).getModifiers())),
1233: (String) focusInputMap.get((KeyStroke) keys[i]));
1234:
1235: parentInputMap.put(
1236: KeyStroke.getKeyStroke(
1237: ((KeyStroke) keys[i]).getKeyCode(),
1238: ((KeyStroke) keys[i]).getModifiers()),
1239: (String) focusInputMap.get((KeyStroke) keys[i]));
1240:
1241: parentActionMap.put(
1242: (String) focusInputMap.get((KeyStroke) keys[i]),
1243: new ActionListenerProxy(
1244: action,
1245: (String) focusInputMap.get((KeyStroke) keys[i])));
1246:
1247: }
1248:
1249: parentInputMap.setParent(tree.getInputMap(
1250: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).getParent());
1251: parentActionMap.setParent(tree.getActionMap().getParent());
1252: tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).setParent(
1253: parentInputMap);
1254: tree.getActionMap().setParent(parentActionMap);
1255: }
1256:
1257:
1263: private int convertModifiers(int mod)
1264: {
1265: if ((mod & KeyEvent.SHIFT_DOWN_MASK) != 0)
1266: {
1267: mod |= KeyEvent.SHIFT_MASK;
1268: mod &= ~ KeyEvent.SHIFT_DOWN_MASK;
1269: }
1270: if ((mod & KeyEvent.CTRL_DOWN_MASK) != 0)
1271: {
1272: mod |= KeyEvent.CTRL_MASK;
1273: mod &= ~ KeyEvent.CTRL_DOWN_MASK;
1274: }
1275: if ((mod & KeyEvent.META_DOWN_MASK) != 0)
1276: {
1277: mod |= KeyEvent.META_MASK;
1278: mod &= ~ KeyEvent.META_DOWN_MASK;
1279: }
1280: if ((mod & KeyEvent.ALT_DOWN_MASK) != 0)
1281: {
1282: mod |= KeyEvent.ALT_MASK;
1283: mod &= ~ KeyEvent.ALT_DOWN_MASK;
1284: }
1285: if ((mod & KeyEvent.ALT_GRAPH_DOWN_MASK) != 0)
1286: {
1287: mod |= KeyEvent.ALT_GRAPH_MASK;
1288: mod &= ~ KeyEvent.ALT_GRAPH_DOWN_MASK;
1289: }
1290: return mod;
1291: }
1292:
1293:
1296: protected void installListeners()
1297: {
1298: tree.addPropertyChangeListener(propertyChangeListener);
1299: tree.addFocusListener(focusListener);
1300: tree.addTreeSelectionListener(treeSelectionListener);
1301: tree.addMouseListener(mouseListener);
1302: tree.addKeyListener(keyListener);
1303: tree.addPropertyChangeListener(selectionModelPropertyChangeListener);
1304: tree.addComponentListener(componentListener);
1305: tree.addTreeExpansionListener(treeExpansionListener);
1306: if (treeModel != null)
1307: treeModel.addTreeModelListener(treeModelListener);
1308: }
1309:
1310:
1315: public void installUI(JComponent c)
1316: {
1317: tree = (JTree) c;
1318: treeModel = tree.getModel();
1319:
1320: prepareForUIInstall();
1321: super.installUI(c);
1322: installDefaults();
1323: installComponents();
1324: installKeyboardActions();
1325: installListeners();
1326:
1327: setCellEditor(createDefaultCellEditor());
1328: createdCellEditor = true;
1329: isEditing = false;
1330:
1331: setModel(tree.getModel());
1332: treeSelectionModel = tree.getSelectionModel();
1333: setRootVisible(tree.isRootVisible());
1334: treeState.setRootVisible(tree.isRootVisible());
1335:
1336: completeUIInstall();
1337: }
1338:
1339:
1342: protected void uninstallDefaults()
1343: {
1344: tree.setFont(null);
1345: tree.setForeground(null);
1346: tree.setBackground(null);
1347: }
1348:
1349:
1354: public void uninstallUI(JComponent c)
1355: {
1356: prepareForUIUninstall();
1357: uninstallDefaults();
1358: uninstallKeyboardActions();
1359: uninstallListeners();
1360: tree = null;
1361: uninstallComponents();
1362: completeUIUninstall();
1363: }
1364:
1365:
1376: public void paint(Graphics g, JComponent c)
1377: {
1378: JTree tree = (JTree) c;
1379:
1380: int rows = treeState.getRowCount();
1381:
1382: if (rows == 0)
1383:
1384: return;
1385:
1386: Rectangle clip = g.getClipBounds();
1387:
1388: Insets insets = tree.getInsets();
1389:
1390: if (clip != null && treeModel != null)
1391: {
1392: int startIndex = tree.getClosestRowForLocation(clip.x, clip.y);
1393: int endIndex = tree.getClosestRowForLocation(clip.x + clip.width,
1394: clip.y + clip.height);
1395:
1396:
1397:
1398:
1399: if (endIndex < rows)
1400: for (int i = endIndex + 1; i < rows; i++)
1401: {
1402: TreePath path = treeState.getPathForRow(i);
1403: if (isLastChild(path))
1404: paintVerticalPartOfLeg(g, clip, insets, path);
1405: }
1406:
1407:
1408:
1409:
1410: int n = endIndex - startIndex + 1;
1411: Rectangle[] bounds = new Rectangle[n];
1412: boolean[] isLeaf = new boolean[n];
1413: boolean[] isExpanded = new boolean[n];
1414: TreePath[] path = new TreePath[n];
1415: int k;
1416:
1417: k = 0;
1418: for (int i = startIndex; i <= endIndex; i++, k++)
1419: {
1420: path[k] = treeState.getPathForRow(i);
1421: isLeaf[k] = treeModel.isLeaf(path[k].getLastPathComponent());
1422: isExpanded[k] = tree.isExpanded(path[k]);
1423: bounds[k] = getPathBounds(tree, path[k]);
1424:
1425: paintHorizontalPartOfLeg(g, clip, insets, bounds[k], path[k], i,
1426: isExpanded[k], false, isLeaf[k]);
1427: if (isLastChild(path[k]))
1428: paintVerticalPartOfLeg(g, clip, insets, path[k]);
1429: }
1430:
1431: k = 0;
1432: for (int i = startIndex; i <= endIndex; i++, k++)
1433: {
1434: paintRow(g, clip, insets, bounds[k], path[k], i, isExpanded[k],
1435: false, isLeaf[k]);
1436: }
1437: }
1438: }
1439:
1440:
1443: private boolean isLastChild(TreePath path)
1444: {
1445: if (path instanceof GnuPath)
1446: {
1447:
1448:
1449: return ((GnuPath) path).isLastChild;
1450: }
1451: else
1452: {
1453:
1454: TreePath parent = path.getParentPath();
1455: if (parent == null)
1456: return false;
1457: int childCount = treeState.getVisibleChildCount(parent);
1458: int p = treeModel.getIndexOfChild(parent, path.getLastPathComponent());
1459: return p == childCount - 1;
1460: }
1461: }
1462:
1463:
1469: protected void ensureRowsAreVisible(int beginRow, int endRow)
1470: {
1471: if (beginRow < endRow)
1472: {
1473: int temp = endRow;
1474: endRow = beginRow;
1475: beginRow = temp;
1476: }
1477:
1478: for (int i = beginRow; i < endRow; i++)
1479: {
1480: TreePath path = getPathForRow(tree, i);
1481: if (! tree.isVisible(path))
1482: tree.makeVisible(path);
1483: }
1484: }
1485:
1486:
1491: public void setPreferredMinSize(Dimension newSize)
1492: {
1493: preferredMinSize = newSize;
1494: }
1495:
1496:
1501: public Dimension getPreferredMinSize()
1502: {
1503: if (preferredMinSize == null)
1504: return getPreferredSize(tree);
1505: else
1506: return preferredMinSize;
1507: }
1508:
1509:
1518: public Dimension getPreferredSize(JComponent c)
1519: {
1520: return getPreferredSize(c, false);
1521: }
1522:
1523:
1531: public Dimension getPreferredSize(JComponent c, boolean checkConsistancy)
1532: {
1533: if (! validCachedPreferredSize)
1534: {
1535: Rectangle size = tree.getBounds();
1536:
1537: preferredSize = new Dimension(treeState.getPreferredWidth(size),
1538: treeState.getPreferredHeight());
1539: validCachedPreferredSize = true;
1540: }
1541: return preferredSize;
1542: }
1543:
1544:
1551: public Dimension getMinimumSize(JComponent c)
1552: {
1553: return preferredMinSize = getPreferredSize(c);
1554: }
1555:
1556:
1563: public Dimension getMaximumSize(JComponent c)
1564: {
1565: return getPreferredSize(c);
1566: }
1567:
1568:
1575: protected void completeEditing()
1576: {
1577: completeEditing(false, true, false);
1578: }
1579:
1580:
1590: protected void completeEditing(boolean messageStop, boolean messageCancel,
1591: boolean messageTree)
1592: {
1593: if (messageStop)
1594: {
1595: getCellEditor().stopCellEditing();
1596: stopEditingInCompleteEditing = true;
1597: }
1598:
1599: if (messageCancel)
1600: {
1601: getCellEditor().cancelCellEditing();
1602: stopEditingInCompleteEditing = true;
1603: }
1604:
1605: if (messageTree)
1606: {
1607: TreeCellEditor editor = getCellEditor();
1608: if (editor != null)
1609: {
1610: Object value = editor.getCellEditorValue();
1611: treeModel.valueForPathChanged(tree.getLeadSelectionPath(), value);
1612: }
1613: }
1614: }
1615:
1616:
1624: protected boolean startEditing(TreePath path, MouseEvent event)
1625: {
1626: updateCellEditor();
1627: TreeCellEditor ed = getCellEditor();
1628:
1629: if (ed != null && (event == EDIT || ed.shouldSelectCell(event))
1630: && ed.isCellEditable(event))
1631: {
1632: Rectangle bounds = getPathBounds(tree, path);
1633:
1634:
1635: bounds.width = tree.getWidth() - bounds.x;
1636:
1637: editingPath = path;
1638: editingRow = tree.getRowForPath(editingPath);
1639:
1640: Object value = editingPath.getLastPathComponent();
1641:
1642: stopEditingInCompleteEditing = false;
1643: boolean expanded = tree.isExpanded(editingPath);
1644: isEditing = true;
1645: editingComponent = ed.getTreeCellEditorComponent(tree, value, true,
1646: expanded,
1647: isLeaf(editingRow),
1648: editingRow);
1649:
1650:
1651:
1652: tree.removeAll();
1653:
1654:
1655:
1656: Component container = editingComponent.getParent();
1657: container.setBounds(bounds);
1658: tree.add(container);
1659: editingComponent.requestFocus();
1660:
1661: return true;
1662: }
1663: return false;
1664: }
1665:
1666:
1674: protected void checkForClickInExpandControl(TreePath path, int mouseX,
1675: int mouseY)
1676: {
1677: if (isLocationInExpandControl(path, mouseX, mouseY))
1678: toggleExpandState(path);
1679: }
1680:
1681:
1693: protected boolean isLocationInExpandControl(TreePath path, int mouseX,
1694: int mouseY)
1695: {
1696: boolean cntlClick = false;
1697: int row = getRowForPath(tree, path);
1698:
1699: if (! isLeaf(row))
1700: {
1701: Rectangle bounds = getPathBounds(tree, path);
1702:
1703: if (hasControlIcons()
1704: && (mouseX < bounds.x)
1705: && (mouseX > (bounds.x - getCurrentControlIcon(path).getIconWidth() - gap)))
1706: cntlClick = true;
1707: }
1708: return cntlClick;
1709: }
1710:
1711:
1719: protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY)
1720: {
1721: toggleExpandState(path);
1722: }
1723:
1724:
1732: protected void toggleExpandState(TreePath path)
1733: {
1734: if (tree.isExpanded(path))
1735: tree.collapsePath(path);
1736: else
1737: tree.expandPath(path);
1738: }
1739:
1740:
1751: protected boolean isToggleSelectionEvent(MouseEvent event)
1752: {
1753: return
1754: (tree.getSelectionModel().getSelectionMode() !=
1755: TreeSelectionModel.SINGLE_TREE_SELECTION) &&
1756: ((event.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0);
1757: }
1758:
1759:
1770: protected boolean isMultiSelectEvent(MouseEvent event)
1771: {
1772: return
1773: (tree.getSelectionModel().getSelectionMode() !=
1774: TreeSelectionModel.SINGLE_TREE_SELECTION) &&
1775: ((event.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0);
1776: }
1777:
1778:
1787: protected boolean isToggleEvent(MouseEvent event)
1788: {
1789: return true;
1790: }
1791:
1792:
1805: protected void selectPathForEvent(TreePath path, MouseEvent event)
1806: {
1807: if (isToggleSelectionEvent(event))
1808: {
1809:
1810: if (tree.isPathSelected(path))
1811: tree.removeSelectionPath(path);
1812: else
1813: {
1814: tree.addSelectionPath(path);
1815: tree.setAnchorSelectionPath(path);
1816: }
1817: }
1818: else if (isMultiSelectEvent(event))
1819: {
1820:
1821: TreePath anchor = tree.getAnchorSelectionPath();
1822: if (anchor != null)
1823: {
1824: int aRow = getRowForPath(tree, anchor);
1825: tree.addSelectionInterval(aRow, getRowForPath(tree, path));
1826: }
1827: else
1828: tree.addSelectionPath(path);
1829: }
1830: else
1831: {
1832:
1833: tree.setSelectionPath(path);
1834: tree.setAnchorSelectionPath(path);
1835: }
1836: }
1837:
1838:
1844: protected boolean isLeaf(int row)
1845: {
1846: TreePath pathForRow = getPathForRow(tree, row);
1847: if (pathForRow == null)
1848: return true;
1849:
1850: Object node = pathForRow.getLastPathComponent();
1851: return treeModel.isLeaf(node);
1852: }
1853:
1854:
1859: class TreeAction
1860: extends AbstractAction
1861: {
1862:
1863:
1868: public void actionPerformed(ActionEvent e)
1869: {
1870: String command = e.getActionCommand();
1871: TreePath lead = tree.getLeadSelectionPath();
1872:
1873: if (command.equals("selectPreviousChangeLead")
1874: || command.equals("selectPreviousExtendSelection")
1875: || command.equals("selectPrevious") || command.equals("selectNext")
1876: || command.equals("selectNextExtendSelection")
1877: || command.equals("selectNextChangeLead"))
1878: (new TreeIncrementAction(0, "")).actionPerformed(e);
1879: else if (command.equals("selectParent") || command.equals("selectChild"))
1880: (new TreeTraverseAction(0, "")).actionPerformed(e);
1881: else if (command.equals("selectAll"))
1882: {
1883: TreePath[] paths = new TreePath[treeState.getRowCount()];
1884: for (int i = 0; i < paths.length; i++)
1885: paths[i] = treeState.getPathForRow(i);
1886: tree.addSelectionPaths(paths);
1887: }
1888: else if (command.equals("startEditing"))
1889: tree.startEditingAtPath(lead);
1890: else if (command.equals("toggle"))
1891: {
1892: if (tree.isEditing())
1893: tree.stopEditing();
1894: else
1895: {
1896: Object last = lead.getLastPathComponent();
1897: TreePath path = new TreePath(getPathToRoot(last, 0));
1898: if (! treeModel.isLeaf(last))
1899: toggleExpandState(path);
1900: }
1901: }
1902: else if (command.equals("clearSelection"))
1903: tree.clearSelection();
1904:
1905: if (tree.isEditing() && ! command.equals("startEditing"))
1906: tree.stopEditing();
1907:
1908: tree.scrollPathToVisible(tree.getLeadSelectionPath());
1909: }
1910: }
1911:
1912:
1919: private static class ActionListenerProxy
1920: extends AbstractAction
1921: {
1922: ActionListener target;
1923:
1924: String bindingCommandName;
1925:
1926: public ActionListenerProxy(ActionListener li, String cmd)
1927: {
1928: target = li;
1929: bindingCommandName = cmd;
1930: }
1931:
1932: public void actionPerformed(ActionEvent e)
1933: {
1934: ActionEvent derivedEvent = new ActionEvent(e.getSource(), e.getID(),
1935: bindingCommandName,
1936: e.getModifiers());
1937:
1938: target.actionPerformed(derivedEvent);
1939: }
1940: }
1941:
1942:
1945: public class ComponentHandler
1946: extends ComponentAdapter
1947: implements ActionListener
1948: {
1949:
1952: protected Timer timer;
1953:
1954:
1955: protected JScrollBar scrollBar;
1956:
1957:
1960: public ComponentHandler()
1961: {
1962:
1963: }
1964:
1965:
1970: public void componentMoved(ComponentEvent e)
1971: {
1972:
1973: }
1974:
1975:
1979: protected void startTimer()
1980: {
1981:
1982: }
1983:
1984:
1989: protected JScrollPane getScrollPane()
1990: {
1991: return null;
1992: }
1993:
1994:
2000: public void actionPerformed(ActionEvent ae)
2001: {
2002:
2003: }
2004: }
2005:
2006:
2010: public class CellEditorHandler
2011: implements CellEditorListener
2012: {
2013:
2016: public CellEditorHandler()
2017: {
2018:
2019: }
2020:
2021:
2027: public void editingStopped(ChangeEvent e)
2028: {
2029: stopEditing(tree);
2030: }
2031:
2032:
2038: public void editingCanceled(ChangeEvent e)
2039: {
2040: cancelEditing(tree);
2041: }
2042: }
2043:
2044:
2047: public class FocusHandler
2048: implements FocusListener
2049: {
2050:
2053: public FocusHandler()
2054: {
2055:
2056: }
2057:
2058:
2066: public void focusGained(FocusEvent e)
2067: {
2068: repaintLeadRow();
2069: }
2070:
2071:
2079: public void focusLost(FocusEvent e)
2080: {
2081: repaintLeadRow();
2082: }
2083:
2084:
2087: void repaintLeadRow()
2088: {
2089: TreePath lead = tree.getLeadSelectionPath();
2090: if (lead!=null)
2091: tree.repaint(tree.getPathBounds(lead));
2092: }
2093: }
2094:
2095:
2099: public class KeyHandler
2100: extends KeyAdapter
2101: {
2102:
2103: protected Action repeatKeyAction;
2104:
2105:
2106: protected boolean isKeyDown;
2107:
2108:
2111: public KeyHandler()
2112: {
2113:
2114: }
2115:
2116:
2124: public void keyTyped(KeyEvent e)
2125: {
2126:
2127: }
2128:
2129:
2134: public void keyPressed(KeyEvent e)
2135: {
2136:
2137: }
2138:
2139:
2144: public void keyReleased(KeyEvent e)
2145: {
2146:
2147: }
2148: }
2149:
2150:
2154: public class MouseHandler
2155: extends MouseAdapter
2156: implements MouseMotionListener
2157: {
2158:
2161: public MouseHandler()
2162: {
2163:
2164: }
2165:
2166:
2171: public void mousePressed(MouseEvent e)
2172: {
2173:
2174:
2175: if (startEditTimer != null)
2176: {
2177: startEditTimer.stop();
2178: startEditTimer = null;
2179: }
2180:
2181: Point click = e.getPoint();
2182: TreePath path = getClosestPathForLocation(tree, click.x, click.y);
2183:
2184: if (path != null)
2185: {
2186: Rectangle bounds = getPathBounds(tree, path);
2187: int row = getRowForPath(tree, path);
2188:
2189:
2190: if (tree.isEditing() && row != editingRow)
2191: cancelEditing(tree);
2192:
2193: boolean cntlClick = isLocationInExpandControl(path, click.x, click.y);
2194:
2195: boolean isLeaf = isLeaf(row);
2196:
2197: TreeCellRenderer tcr = getCellRenderer();
2198: Icon icon;
2199: if (isLeaf)
2200: icon = UIManager.getIcon("Tree.leafIcon");
2201: else if (tree.isExpanded(path))
2202: icon = UIManager.getIcon("Tree.openIcon");
2203: else
2204: icon = UIManager.getIcon("Tree.closedIcon");
2205:
2206: if (tcr instanceof DefaultTreeCellRenderer)
2207: {
2208: Icon tmp = ((DefaultTreeCellRenderer) tcr).getIcon();
2209: if (tmp != null)
2210: icon = tmp;
2211: }
2212:
2213:
2214: if (icon != null)
2215: bounds.width += icon.getIconWidth() + gap * 2;
2216:
2217: boolean inBounds = bounds.contains(click.x, click.y);
2218: if ((inBounds || cntlClick) && tree.isVisible(path))
2219: {
2220: if (inBounds)
2221: {
2222: TreePath currentLead = tree.getLeadSelectionPath();
2223: if (currentLead != null && currentLead.equals(path)
2224: && e.getClickCount() == 1 && tree.isEditable())
2225: {
2226:
2227: final TreePath editPath = path;
2228:
2229: if (startEditTimer != null)
2230: startEditTimer.stop();
2231:
2232: startEditTimer = new Timer(WAIT_TILL_EDITING,
2233: new ActionListener()
2234: {
2235: public void actionPerformed(ActionEvent e)
2236: {
2237: startEditing(editPath, EDIT);
2238: }
2239: });
2240: startEditTimer.setRepeats(false);
2241: startEditTimer.start();
2242: }
2243: else
2244: {
2245: if (e.getClickCount() == 2 && ! isLeaf(row))
2246: toggleExpandState(path);
2247: else
2248: selectPathForEvent(path, e);
2249: }
2250: }
2251:
2252: if (cntlClick)
2253: {
2254: handleExpandControlClick(path, click.x, click.y);
2255: if (cellEditor != null)
2256: cellEditor.cancelCellEditing();
2257: tree.scrollPathToVisible(path);
2258: }
2259: else if (tree.isEditable())
2260: startEditing(path, e);
2261: }
2262: }
2263: }
2264:
2265:
2273: public void mouseDragged(MouseEvent e)
2274: {
2275:
2276: }
2277:
2278:
2284: public void mouseMoved(MouseEvent e)
2285: {
2286:
2287: }
2288:
2289:
2294: public void mouseReleased(MouseEvent e)
2295: {
2296:
2297: }
2298: }
2299:
2300:
2305: public class MouseInputHandler
2306: implements MouseInputListener
2307: {
2308:
2309: protected Component source;
2310:
2311:
2312: protected Component destination;
2313:
2314:
2321: public MouseInputHandler(Component source, Component destination,
2322: MouseEvent e)
2323: {
2324: this.source = source;
2325: this.destination = destination;
2326: }
2327:
2328:
2334: public void mouseClicked(MouseEvent e)
2335: {
2336:
2337: }
2338:
2339:
2344: public void mousePressed(MouseEvent e)
2345: {
2346:
2347: }
2348:
2349:
2354: public void mouseReleased(MouseEvent e)
2355: {
2356:
2357: }
2358:
2359:
2364: public void mouseEntered(MouseEvent e)
2365: {
2366:
2367: }
2368:
2369:
2374: public void mouseExited(MouseEvent e)
2375: {
2376:
2377: }
2378:
2379:
2387: public void mouseDragged(MouseEvent e)
2388: {
2389:
2390: }
2391:
2392:
2398: public void mouseMoved(MouseEvent e)
2399: {
2400:
2401: }
2402:
2403:
2406: protected void removeFromSource()
2407: {
2408:
2409: }
2410: }
2411:
2412:
2417: public class NodeDimensionsHandler
2418: extends AbstractLayoutCache.NodeDimensions
2419: {
2420:
2423: public NodeDimensionsHandler()
2424: {
2425:
2426: }
2427:
2428:
2441: public Rectangle getNodeDimensions(Object cell, int row, int depth,
2442: boolean expanded, Rectangle size)
2443: {
2444: if (size == null || cell == null)
2445: return null;
2446:
2447: String s = cell.toString();
2448: Font f = tree.getFont();
2449: FontMetrics fm = tree.getToolkit().getFontMetrics(f);
2450:
2451: if (s != null)
2452: {
2453: size.x = getRowX(row, depth);
2454: size.width = SwingUtilities.computeStringWidth(fm, s);
2455: size.width = size.width + getCurrentControlIcon(null).getIconWidth()
2456: + gap;
2457: size.height = getMaxHeight(tree);
2458: size.y = size.height * row;
2459: }
2460:
2461: return size;
2462: }
2463:
2464:
2469: protected int getRowX(int row, int depth)
2470: {
2471: int iw = getCurrentControlIcon(null).getIconWidth();
2472: return depth * (rightChildIndent + iw/2);
2473: }
2474: }
2475:
2476:
2480: public class PropertyChangeHandler
2481: implements PropertyChangeListener
2482: {
2483:
2484:
2487: public PropertyChangeHandler()
2488: {
2489:
2490: }
2491:
2492:
2498: public void propertyChange(PropertyChangeEvent event)
2499: {
2500: String property = event.getPropertyName();
2501: if (property.equals(JTree.ROOT_VISIBLE_PROPERTY))
2502: {
2503: validCachedPreferredSize = false;
2504: treeState.setRootVisible(tree.isRootVisible());
2505: tree.repaint();
2506: }
2507: else if (property.equals(JTree.SELECTION_MODEL_PROPERTY))
2508: {
2509: treeSelectionModel = tree.getSelectionModel();
2510: treeSelectionModel.setRowMapper(treeState);
2511: }
2512: else if (property.equals(JTree.TREE_MODEL_PROPERTY))
2513: {
2514: treeModel = tree.getModel();
2515: treeModel.addTreeModelListener(treeModelListener);
2516: }
2517: }
2518: }
2519:
2520:
2524: public class SelectionModelPropertyChangeHandler
2525: implements PropertyChangeListener
2526: {
2527:
2528:
2531: public SelectionModelPropertyChangeHandler()
2532: {
2533:
2534: }
2535:
2536:
2542: public void propertyChange(PropertyChangeEvent event)
2543: {
2544:
2545: }
2546: }
2547:
2548:
2551: public class TreeCancelEditingAction
2552: extends AbstractAction
2553: {
2554:
2555:
2558: public TreeCancelEditingAction(String name)
2559: {
2560:
2561: }
2562:
2563:
2568: public void actionPerformed(ActionEvent e)
2569: {
2570:
2571: }
2572:
2573:
2578: public boolean isEnabled()
2579: {
2580:
2581: return false;
2582: }
2583: }
2584:
2585:
2588: public class TreeExpansionHandler
2589: implements TreeExpansionListener
2590: {
2591:
2592:
2595: public TreeExpansionHandler()
2596: {
2597:
2598: }
2599:
2600:
2605: public void treeExpanded(TreeExpansionEvent event)
2606: {
2607: validCachedPreferredSize = false;
2608: treeState.setExpandedState(event.getPath(), true);
2609: tree.revalidate();
2610: tree.repaint();
2611: }
2612:
2613:
2618: public void treeCollapsed(TreeExpansionEvent event)
2619: {
2620: validCachedPreferredSize = false;
2621: treeState.setExpandedState(event.getPath(), false);
2622: tree.revalidate();
2623: tree.repaint();
2624: }
2625: }
2626:
2627:
2631: public class TreeHomeAction
2632: extends AbstractAction
2633: {
2634:
2635:
2636: protected int direction;
2637:
2638:
2644: public TreeHomeAction(int direction, String name)
2645: {
2646:
2647: }
2648:
2649:
2654: public void actionPerformed(ActionEvent e)
2655: {
2656:
2657: }
2658:
2659:
2664: public boolean isEnabled()
2665: {
2666:
2667: return false;
2668: }
2669: }
2670:
2671:
2675: public class TreeIncrementAction
2676: extends AbstractAction
2677: {
2678:
2679:
2680: protected int direction;
2681:
2682:
2688: public TreeIncrementAction(int direction, String name)
2689: {
2690:
2691: }
2692:
2693:
2698: public void actionPerformed(ActionEvent e)
2699: {
2700: TreePath currentPath = tree.getLeadSelectionPath();
2701: int currentRow;
2702:
2703: if (currentPath != null)
2704: currentRow = treeState.getRowForPath(currentPath);
2705: else
2706: currentRow = 0;
2707:
2708: int rows = treeState.getRowCount();
2709:
2710: int nextRow = currentRow + 1;
2711: int prevRow = currentRow - 1;
2712: boolean hasNext = nextRow < rows;
2713: boolean hasPrev = prevRow >= 0 && rows > 0;
2714: TreePath newPath;
2715: String command = e.getActionCommand();
2716:
2717: if (command.equals("selectPreviousChangeLead") && hasPrev)
2718: {
2719: newPath = treeState.getPathForRow(prevRow);
2720: tree.setSelectionPath(newPath);
2721: tree.setAnchorSelectionPath(newPath);
2722: tree.setLeadSelectionPath(newPath);
2723: }
2724: else if (command.equals("selectPreviousExtendSelection") && hasPrev)
2725: {
2726: newPath = treeState.getPathForRow(prevRow);
2727:
2728:
2729:
2730: if (tree.isPathSelected(newPath))
2731: tree.getSelectionModel().removeSelectionPath(currentPath);
2732:
2733:
2734:
2735: tree.addSelectionPath(newPath);
2736: tree.setLeadSelectionPath(newPath);
2737: }
2738: else if (command.equals("selectPrevious") && hasPrev)
2739: {
2740: newPath = treeState.getPathForRow(prevRow);
2741: tree.setSelectionPath(newPath);
2742: }
2743: else if (command.equals("selectNext") && hasNext)
2744: {
2745: newPath = treeState.getPathForRow(nextRow);
2746: tree.setSelectionPath(newPath);
2747: }
2748: else if (command.equals("selectNextExtendSelection") && hasNext)
2749: {
2750: newPath = treeState.getPathForRow(nextRow);
2751:
2752:
2753:
2754: if (tree.isPathSelected(newPath))
2755: tree.getSelectionModel().removeSelectionPath(currentPath);
2756:
2757:
2758:
2759: tree.addSelectionPath(newPath);
2760:
2761: tree.setLeadSelectionPath(newPath);
2762: }
2763: else if (command.equals("selectNextChangeLead") && hasNext)
2764: {
2765: newPath = treeState.getPathForRow(nextRow);
2766: tree.setSelectionPath(newPath);
2767: tree.setAnchorSelectionPath(newPath);
2768: tree.setLeadSelectionPath(newPath);
2769: }
2770: }
2771:
2772:
2777: public boolean isEnabled()
2778: {
2779:
2780: return false;
2781: }
2782: }
2783:
2784:
2787: public class TreeModelHandler
2788: implements TreeModelListener
2789: {
2790:
2793: public TreeModelHandler()
2794: {
2795:
2796: }
2797:
2798:
2810: public void treeNodesChanged(TreeModelEvent e)
2811: {
2812: validCachedPreferredSize = false;
2813: treeState.treeNodesChanged(e);
2814: tree.repaint();
2815: }
2816:
2817:
2824: public void treeNodesInserted(TreeModelEvent e)
2825: {
2826: validCachedPreferredSize = false;
2827: treeState.treeNodesInserted(e);
2828: tree.repaint();
2829: }
2830:
2831:
2841: public void treeNodesRemoved(TreeModelEvent e)
2842: {
2843: validCachedPreferredSize = false;
2844: treeState.treeNodesRemoved(e);
2845: tree.repaint();
2846: }
2847:
2848:
2857: public void treeStructureChanged(TreeModelEvent e)
2858: {
2859: if (e.getPath().length == 1
2860: && ! e.getPath()[0].equals(treeModel.getRoot()))
2861: tree.expandPath(new TreePath(treeModel.getRoot()));
2862: validCachedPreferredSize = false;
2863: treeState.treeStructureChanged(e);
2864: tree.repaint();
2865: }
2866: }
2867:
2868:
2871: public class TreePageAction
2872: extends AbstractAction
2873: {
2874:
2875: protected int direction;
2876:
2877:
2883: public TreePageAction(int direction, String name)
2884: {
2885: this.direction = direction;
2886: }
2887:
2888:
2893: public void actionPerformed(ActionEvent e)
2894: {
2895:
2896: }
2897:
2898:
2903: public boolean isEnabled()
2904: {
2905: return false;
2906: }
2907: }
2908:
2909:
2913: public class TreeSelectionHandler
2914: implements TreeSelectionListener
2915: {
2916:
2919: public TreeSelectionHandler()
2920: {
2921:
2922: }
2923:
2924:
2930: public void valueChanged(TreeSelectionEvent event)
2931: {
2932: if (tree.isEditing())
2933: tree.cancelEditing();
2934:
2935: TreePath op = event.getOldLeadSelectionPath();
2936: TreePath np = event.getNewLeadSelectionPath();
2937:
2938:
2939: if (op != np)
2940: {
2941: Rectangle o = treeState.getBounds(event.getOldLeadSelectionPath(),
2942: new Rectangle());
2943: Rectangle n = treeState.getBounds(event.getNewLeadSelectionPath(),
2944: new Rectangle());
2945:
2946: if (o!=null)
2947: tree.repaint(o);
2948: if (n!=null)
2949: tree.repaint(n);
2950: }
2951: }
2952: }
2953:
2954:
2957: public class TreeToggleAction
2958: extends AbstractAction
2959: {
2960:
2965: public TreeToggleAction(String name)
2966: {
2967:
2968: }
2969:
2970:
2975: public void actionPerformed(ActionEvent e)
2976: {
2977:
2978: }
2979:
2980:
2985: public boolean isEnabled()
2986: {
2987: return false;
2988: }
2989: }
2990:
2991:
2995: public class TreeTraverseAction
2996: extends AbstractAction
2997: {
2998:
3001: protected int direction;
3002:
3003:
3009: public TreeTraverseAction(int direction, String name)
3010: {
3011: this.direction = direction;
3012: }
3013:
3014:
3019: public void actionPerformed(ActionEvent e)
3020: {
3021: TreePath current = tree.getLeadSelectionPath();
3022: if (current == null)
3023: return;
3024:
3025: if (e.getActionCommand().equals("selectParent"))
3026: {
3027: if (current == null)
3028: return;
3029:
3030: if (tree.isExpanded(current))
3031: {
3032: tree.collapsePath(current);
3033: }
3034: else
3035: {
3036:
3037:
3038:
3039: TreePath parent = current.getParentPath();
3040: if (parent != null &&
3041: !(parent.getPathCount()==1 && !tree.isRootVisible()) )
3042: tree.setSelectionPath(parent);
3043: }
3044: }
3045: else if (e.getActionCommand().equals("selectChild"))
3046: {
3047: Object node = current.getLastPathComponent();
3048: int nc = treeModel.getChildCount(node);
3049: if (nc == 0 || treeState.isExpanded(current))
3050: {
3051:
3052:
3053: int nextRow = tree.getLeadSelectionRow() + 1;
3054: if (nextRow <= tree.getRowCount())
3055: tree.setSelectionRow(nextRow);
3056: }
3057: else
3058: {
3059: tree.expandPath(current);
3060: }
3061: }
3062: }
3063:
3064:
3069: public boolean isEnabled()
3070: {
3071:
3072: return false;
3073: }
3074: }
3075:
3076:
3082: boolean hasControlIcons()
3083: {
3084: if (expandedIcon != null || collapsedIcon != null)
3085: return true;
3086: return false;
3087: }
3088:
3089:
3095: Icon getCurrentControlIcon(TreePath path)
3096: {
3097: if (tree.isExpanded(path))
3098: return expandedIcon;
3099: return collapsedIcon;
3100: }
3101:
3102:
3109: Object getParent(Object root, Object node)
3110: {
3111: if (root == null || node == null || root.equals(node))
3112: return null;
3113:
3114: if (node instanceof TreeNode)
3115: return ((TreeNode) node).getParent();
3116: return findNode(root, node);
3117: }
3118:
3119:
3126: private Object findNode(Object root, Object node)
3127: {
3128: if (! treeModel.isLeaf(root) && ! root.equals(node))
3129: {
3130: int size = treeModel.getChildCount(root);
3131: for (int j = 0; j < size; j++)
3132: {
3133: Object child = treeModel.getChild(root, j);
3134: if (node.equals(child))
3135: return root;
3136:
3137: Object n = findNode(child, node);
3138: if (n != null)
3139: return n;
3140: }
3141: }
3142: return null;
3143: }
3144:
3145:
3152: void selectPath(JTree tree, TreePath path)
3153: {
3154: if (path != null)
3155: {
3156: tree.setSelectionPath(path);
3157: tree.setLeadSelectionPath(path);
3158: tree.makeVisible(path);
3159: tree.scrollPathToVisible(path);
3160: }
3161: }
3162:
3163:
3171: Object[] getPathToRoot(Object node, int depth)
3172: {
3173: if (node == null)
3174: {
3175: if (depth == 0)
3176: return null;
3177:
3178: return new Object[depth];
3179: }
3180:
3181: Object[] path = getPathToRoot(getParent(treeModel.getRoot(), node),
3182: depth + 1);
3183: path[path.length - depth - 1] = node;
3184: return path;
3185: }
3186:
3187:
3196: protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
3197: int bottom)
3198: {
3199:
3200: g.setColor(getHashColor());
3201: g.drawLine(x, top, x, bottom);
3202: }
3203:
3204:
3213: protected void paintHorizontalLine(Graphics g, JComponent c, int y, int left,
3214: int right)
3215: {
3216:
3217: g.setColor(getHashColor());
3218: g.drawLine(left, y, right, y);
3219: }
3220:
3221:
3230: protected void drawCentered(Component c, Graphics g, Icon icon, int x, int y)
3231: {
3232: x -= icon.getIconWidth() / 2;
3233: y -= icon.getIconHeight() / 2;
3234:
3235: if (x < 0)
3236: x = 0;
3237: if (y < 0)
3238: y = 0;
3239:
3240: icon.paintIcon(c, g, x, y);
3241: }
3242:
3243:
3251: protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2)
3252: {
3253: g.setColor(getHashColor());
3254: for (int i = x1; i < x2; i += 2)
3255: g.drawLine(i, y, i + 1, y);
3256: }
3257:
3258:
3266: protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2)
3267: {
3268: g.setColor(getHashColor());
3269: for (int i = y1; i < y2; i += 2)
3270: g.drawLine(x, i, x, i + 1);
3271: }
3272:
3273:
3287: protected void paintExpandControl(Graphics g, Rectangle clipBounds,
3288: Insets insets, Rectangle bounds,
3289: TreePath path, int row, boolean isExpanded,
3290: boolean hasBeenExpanded, boolean isLeaf)
3291: {
3292: if (shouldPaintExpandControl(path, row, isExpanded, hasBeenExpanded, isLeaf))
3293: {
3294: Icon icon = getCurrentControlIcon(path);
3295: int iconW = icon.getIconWidth();
3296: int x = bounds.x - iconW - gap;
3297: icon.paintIcon(tree, g, x, bounds.y + bounds.height / 2
3298: - icon.getIconHeight() / 2);
3299: }
3300: }
3301:
3302:
3317: protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
3318: Insets insets, Rectangle bounds,
3319: TreePath path, int row,
3320: boolean isExpanded,
3321: boolean hasBeenExpanded,
3322: boolean isLeaf)
3323: {
3324: if (row != 0)
3325: {
3326: Icon icon = getCurrentControlIcon(path);
3327: int iconW = icon.getIconWidth();
3328: paintHorizontalLine(g, tree, bounds.y + bounds.height / 2,
3329: bounds.x - iconW/2 - gap, bounds.x - gap);
3330: }
3331: }
3332:
3333:
3342: protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,
3343: Insets insets, TreePath path)
3344: {
3345: Rectangle bounds = getPathBounds(tree, path);
3346: TreePath parent = path.getParentPath();
3347: if (parent != null)
3348: {
3349: Rectangle parentBounds = getPathBounds(tree, parent);
3350: paintVerticalLine(g, tree, parentBounds.x + 2* gap,
3351: parentBounds.y + parentBounds.height / 2,
3352: bounds.y + bounds.height / 2);
3353: }
3354: }
3355:
3356:
3370: protected void paintRow(Graphics g, Rectangle clipBounds, Insets insets,
3371: Rectangle bounds, TreePath path, int row,
3372: boolean isExpanded, boolean hasBeenExpanded,
3373: boolean isLeaf)
3374: {
3375: boolean selected = tree.isPathSelected(path);
3376: boolean hasIcons = false;
3377: Object node = path.getLastPathComponent();
3378:
3379: paintExpandControl(g, clipBounds, insets, bounds, path, row, isExpanded,
3380: hasBeenExpanded, isLeaf);
3381:
3382: TreeCellRenderer dtcr = tree.getCellRenderer();
3383: if (dtcr == null)
3384: dtcr = createDefaultCellRenderer();
3385:
3386: boolean focused = false;
3387: if (treeSelectionModel!= null)
3388: focused = treeSelectionModel.getLeadSelectionRow() == row
3389: && tree.isFocusOwner();
3390:
3391: Component c = dtcr.getTreeCellRendererComponent(tree, node, selected,
3392: isExpanded, isLeaf, row,
3393: focused);
3394:
3395: rendererPane.paintComponent(g, c, c.getParent(), bounds);
3396: }
3397:
3398:
3401: protected void prepareForUIUninstall()
3402: {
3403:
3404: }
3405:
3406:
3416: protected boolean shouldPaintExpandControl(TreePath path, int row,
3417: boolean isExpanded,
3418: boolean hasBeenExpanded,
3419: boolean isLeaf)
3420: {
3421: Object node = path.getLastPathComponent();
3422: return (! isLeaf && hasControlIcons());
3423: }
3424:
3425:
3428: void finish()
3429: {
3430: treeState.invalidatePathBounds(treeState.getPathForRow(editingRow));
3431: editingPath = null;
3432: editingRow = - 1;
3433: stopEditingInCompleteEditing = false;
3434: isEditing = false;
3435: Rectangle bounds = editingComponent.getParent().getBounds();
3436: tree.removeAll();
3437: validCachedPreferredSize = false;
3438:
3439: tree.repaint(bounds);
3440: editingComponent = null;
3441: tree.requestFocus();
3442: }
3443: }