1:
37:
38:
39: package ;
40:
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: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66:
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: 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:
108:
116: public class BasicTreeUI
117: extends TreeUI
118: {
119:
120: protected transient Icon collapsedIcon;
121:
122:
123: protected transient Icon expandedIcon;
124:
125:
126: protected int leftChildIndent;
127:
128:
131: protected int rightChildIndent;
132:
133:
137: protected int totalChildIndent;
138:
139:
140: protected Dimension preferredMinsize;
141:
142:
143: protected int lastSelectedRow;
144:
145:
146: protected JTree tree;
147:
148:
149: protected transient TreeCellRenderer currentCellRenderer;
150:
151:
155: protected boolean createdRenderer;
156:
157:
158: protected transient TreeCellEditor cellEditor;
159:
160:
164: protected boolean createdCellEditor;
165:
166:
170: protected boolean stopEditingInCompleteEditing;
171:
172:
173: protected CellRendererPane rendererPane;
174:
175:
176: protected Dimension preferredSize;
177:
178:
179: protected boolean validCachedPreferredSize;
180:
181:
182: protected AbstractLayoutCache treeState;
183:
184:
185: protected Hashtable drawingCache;
186:
187:
192: protected boolean largeModel;
193:
194:
195: protected AbstractLayoutCache.NodeDimensions nodeDimensions;
196:
197:
198: protected TreeModel treeModel;
199:
200:
201: protected TreeSelectionModel treeSelectionModel;
202:
203:
208: protected int depthOffset;
209:
210:
213: protected Component editingComponent;
214:
215:
216: protected TreePath editingPath;
217:
218:
222: protected int editingRow;
223:
224:
225: protected boolean editorHasDifferentSize;
226:
227:
228: private Timer editorTimer = new EditorUpdateTimer();
229:
230:
231: private Object newVal;
232:
233:
234: private TreeAction action;
235:
236:
237: private boolean isEditing;
238:
239:
240: private PropertyChangeListener propertyChangeListener;
241:
242: private FocusListener focusListener;
243:
244: private TreeSelectionListener treeSelectionListener;
245:
246: private MouseInputListener mouseInputListener;
247:
248: private KeyListener keyListener;
249:
250: private PropertyChangeListener selectionModelPropertyChangeListener;
251:
252: private ComponentListener componentListener;
253:
254: private CellEditorListener cellEditorListener;
255:
256: private TreeExpansionListener treeExpansionListener;
257:
258: private TreeModelListener treeModelListener;
259:
260:
263: public BasicTreeUI()
264: {
265: drawingCache = new Hashtable();
266: nodeDimensions = createNodeDimensions();
267: configureLayoutCache();
268:
269: propertyChangeListener = createPropertyChangeListener();
270: focusListener = createFocusListener();
271: treeSelectionListener = createTreeSelectionListener();
272: mouseInputListener = new MouseInputHandler(null, null, null);
273: keyListener = createKeyListener();
274: selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener();
275: componentListener = createComponentListener();
276: cellEditorListener = createCellEditorListener();
277: treeExpansionListener = createTreeExpansionListener();
278: treeModelListener = createTreeModelListener();
279:
280: editingRow = -1;
281: lastSelectedRow = -1;
282: }
283:
284:
291: public static ComponentUI createUI(JComponent c)
292: {
293: return new BasicTreeUI();
294: }
295:
296:
301: protected Color getHashColor()
302: {
303: return UIManager.getLookAndFeelDefaults().getColor("Tree.hash");
304: }
305:
306:
312: protected void setHashColor(Color color)
313: {
314: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
315: defaults.put("Tree.hash", color);
316: }
317:
318:
324: public void setLeftChildIndent(int newAmount)
325: {
326: leftChildIndent = newAmount;
327: }
328:
329:
334: public int getLeftChildIndent(int newAmount)
335: {
336: return leftChildIndent;
337: }
338:
339:
345: public void setRightChildIndent(int newAmount)
346: {
347: rightChildIndent = newAmount;
348: }
349:
350:
355: public int getRightChildIndent()
356: {
357: return rightChildIndent;
358: }
359:
360:
366: public void setExpandedIcon(Icon newG)
367: {
368: expandedIcon = newG;
369: }
370:
371:
376: public Icon getExpandedIcon()
377: {
378: return expandedIcon;
379: }
380:
381:
387: public void setCollapsedIcon(Icon newG)
388: {
389: collapsedIcon = newG;
390: }
391:
392:
397: public Icon getCollapsedIcon()
398: {
399: return collapsedIcon;
400: }
401:
402:
408: protected void setLargeModel(boolean largeModel)
409: {
410: if (largeModel != this.largeModel)
411: {
412: tree.removeComponentListener(componentListener);
413: this.largeModel = largeModel;
414: tree.addComponentListener(componentListener);
415: }
416: }
417:
418:
423: protected boolean isLargeModel()
424: {
425: return largeModel;
426: }
427:
428:
434: protected void setRowHeight(int rowHeight)
435: {
436: treeState.setRowHeight(rowHeight);
437: }
438:
439:
444: protected int getRowHeight()
445: {
446: return treeState.getRowHeight();
447: }
448:
449:
456: protected void setCellRenderer(TreeCellRenderer tcr)
457: {
458: currentCellRenderer = tcr;
459: tree.setCellRenderer(tcr);
460: updateRenderer();
461: }
462:
463:
469: protected TreeCellRenderer getCellRenderer()
470: {
471: if (currentCellRenderer != null)
472: return currentCellRenderer;
473:
474: return createDefaultCellRenderer();
475: }
476:
477:
483: protected void setModel(TreeModel model)
484: {
485: tree.setModel(model);
486: treeModel = tree.getModel();
487: }
488:
489:
494: protected TreeModel getModel()
495: {
496: return treeModel;
497: }
498:
499:
505: protected void setRootVisible(boolean newValue)
506: {
507: tree.setRootVisible(newValue);
508: }
509:
510:
515: protected boolean isRootVisible()
516: {
517: return tree.isRootVisible();
518: }
519:
520:
526: protected void setShowsRootHandles(boolean newValue)
527: {
528: tree.setShowsRootHandles(newValue);
529: }
530:
531:
536: protected boolean getShowsRootHandles()
537: {
538: return tree.getShowsRootHandles();
539: }
540:
541:
547: protected void setCellEditor(TreeCellEditor editor)
548: {
549: cellEditor = editor;
550: createdCellEditor = true;
551: }
552:
553:
558: protected TreeCellEditor getCellEditor()
559: {
560: return cellEditor;
561: }
562:
563:
569: protected void setEditable(boolean newValue)
570: {
571: tree.setEditable(newValue);
572: }
573:
574:
579: protected boolean isEditable()
580: {
581: return tree.isEditable();
582: }
583:
584:
591: protected void setSelectionModel(TreeSelectionModel newLSM)
592: {
593: if (newLSM != null)
594: {
595: treeSelectionModel = newLSM;
596: tree.setSelectionModel(treeSelectionModel);
597: }
598: }
599:
600:
605: protected TreeSelectionModel getSelectionModel()
606: {
607: return treeSelectionModel;
608: }
609:
610:
622: public Rectangle getPathBounds(JTree tree, TreePath path)
623: {
624: if (path != null)
625: {
626: Object cell = path.getLastPathComponent();
627:
628: TreeModel mod = tree.getModel();
629: if (mod != null)
630: {
631: Object root = mod.getRoot();
632: if (!tree.isRootVisible() && tree.isExpanded(new TreePath(root)))
633: root = getNextNode(root);
634:
635: Point loc = getCellLocation(0, 0, tree, mod, cell, root);
636: return getCellBounds(loc.x, loc.y, cell);
637: }
638: }
639: return null;
640: }
641:
642:
651: public TreePath getPathForRow(JTree tree, int row)
652: {
653: TreeModel mod = tree.getModel();
654: if (mod != null)
655: {
656: Object node = mod.getRoot();
657: if (!tree.isRootVisible()
658: && tree.isExpanded(new TreePath(getPathToRoot(node, 0))))
659: node = getNextNode(node);
660:
661: for (int i = 0; i < row; i++)
662: node = getNextVisibleNode(node);
663:
664: if (node == null)
665: return null;
666:
667: return new TreePath(getPathToRoot(node, 0));
668: }
669: return null;
670: }
671:
672:
684: public int getRowForPath(JTree tree, TreePath path)
685: {
686: int row = path.getPathCount();
687: if (tree.isVisible(path))
688: return row;
689:
690: path = path.getParentPath();
691: while (row > 0 && !tree.isVisible(path))
692: {
693: path = path.getParentPath();
694: row--;
695: }
696: return row;
697: }
698:
699:
706: public int getRowCount(JTree tree)
707: {
708: TreeModel mod = tree.getModel();
709: int count = 0;
710: if (mod != null)
711: {
712: Object node = mod.getRoot();
713: if (!tree.isRootVisible()
714: && tree.isExpanded(new TreePath((getPathToRoot(node, 0)))))
715: node = getNextNode(node);
716:
717: while (node != null)
718: {
719: count++;
720: node = getNextVisibleNode(node);
721: }
722: }
723: return count;
724: }
725:
726:
740: public TreePath getClosestPathForLocation(JTree tree, int x, int y)
741: {
742:
743:
744:
745: int row = Math.round(y / getRowHeight());
746: TreePath path = getPathForRow(tree, row);
747:
748:
749: while (row > 0 && path == null)
750: {
751: --row;
752: path = getPathForRow(tree, row);
753: }
754:
755: return path;
756: }
757:
758:
766: public boolean isEditing(JTree tree)
767: {
768: return isEditing;
769: }
770:
771:
780: public boolean stopEditing(JTree tree)
781: {
782: if (isEditing(tree))
783: completeEditing(true, false, false);
784: return !isEditing(tree);
785: }
786:
787:
793: public void cancelEditing(JTree tree)
794: {
795: if (isEditing(tree))
796: completeEditing(false, true, false);
797: }
798:
799:
808: public void startEditingAtPath(JTree tree, TreePath path)
809: {
810: startEditing(path, null);
811: }
812:
813:
820: public TreePath getEditingPath(JTree tree)
821: {
822: return editingPath;
823: }
824:
825:
829: protected void prepareForUIInstall()
830: {
831:
832: }
833:
834:
838: protected void completeUIInstall()
839: {
840:
841: }
842:
843:
847: protected void completeUIUninstall()
848: {
849:
850: }
851:
852:
855: protected void installComponents()
856: {
857:
858: }
859:
860:
866: protected AbstractLayoutCache.NodeDimensions createNodeDimensions()
867: {
868:
869: return null;
870: }
871:
872:
878: protected PropertyChangeListener createPropertyChangeListener()
879: {
880: return new PropertyChangeHandler();
881: }
882:
883:
889: protected MouseListener createMouseListener()
890: {
891: return new MouseHandler();
892: }
893:
894:
900: protected FocusListener createFocusListener()
901: {
902: return new FocusHandler();
903: }
904:
905:
910: protected KeyListener createKeyListener()
911: {
912: return new KeyHandler();
913: }
914:
915:
922: protected PropertyChangeListener createSelectionModelPropertyChangeListener()
923: {
924: return new SelectionModelPropertyChangeHandler();
925: }
926:
927:
933: protected TreeSelectionListener createTreeSelectionListener()
934: {
935: return new TreeSelectionHandler();
936: }
937:
938:
943: protected CellEditorListener createCellEditorListener()
944: {
945: return new CellEditorHandler();
946: }
947:
948:
955: protected ComponentListener createComponentListener()
956: {
957: return new ComponentHandler();
958: }
959:
960:
966: protected TreeExpansionListener createTreeExpansionListener()
967: {
968: return new TreeExpansionHandler();
969: }
970:
971:
977: protected AbstractLayoutCache createLayoutCache()
978: {
979: return new FixedHeightLayoutCache();
980: }
981:
982:
987: protected CellRendererPane createCellRendererPane()
988: {
989: return new CellRendererPane();
990: }
991:
992:
997: protected TreeCellEditor createDefaultCellEditor()
998: {
999: if (currentCellRenderer != null)
1000: return new DefaultTreeCellEditor(tree,
1001: (DefaultTreeCellRenderer) currentCellRenderer,
1002: cellEditor);
1003: return new DefaultTreeCellEditor(tree,
1004: (DefaultTreeCellRenderer) createDefaultCellRenderer(),
1005: cellEditor);
1006: }
1007:
1008:
1015: protected TreeCellRenderer createDefaultCellRenderer()
1016: {
1017: return new DefaultTreeCellRenderer();
1018: }
1019:
1020:
1025: protected TreeModelListener createTreeModelListener()
1026: {
1027: return new TreeModelHandler();
1028: }
1029:
1030:
1033: protected void uninstallListeners()
1034: {
1035: tree.removePropertyChangeListener(propertyChangeListener);
1036: tree.removeFocusListener(focusListener);
1037: tree.removeTreeSelectionListener(treeSelectionListener);
1038: tree.removeMouseListener(mouseInputListener);
1039: tree.removeKeyListener(keyListener);
1040: tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
1041: tree.removeComponentListener(componentListener);
1042: tree.removeTreeExpansionListener(treeExpansionListener);
1043:
1044: TreeCellEditor tce = tree.getCellEditor();
1045: if (tce != null)
1046: tce.removeCellEditorListener(cellEditorListener);
1047: TreeModel tm = tree.getModel();
1048: if (tm != null)
1049: tm.removeTreeModelListener(treeModelListener);
1050: }
1051:
1052:
1055: protected void uninstallKeyboardActions()
1056: {
1057: }
1058:
1059:
1062: protected void uninstallComponents()
1063: {
1064:
1065: }
1066:
1067:
1073: protected int getVerticalLegBuffer()
1074: {
1075:
1076: return 0;
1077: }
1078:
1079:
1086: protected int getHorizontalLegBuffer()
1087: {
1088:
1089: return 0;
1090: }
1091:
1092:
1096: protected void updateLayoutCacheExpandedNodes()
1097: {
1098:
1099: }
1100:
1101:
1109: protected void updateExpandedDescendants(TreePath path)
1110: {
1111:
1112: }
1113:
1114:
1121: protected TreePath getLastChildPath(TreePath parent)
1122: {
1123: return ((TreePath) parent.getLastPathComponent());
1124: }
1125:
1126:
1129: protected void updateDepthOffset()
1130: {
1131:
1132: }
1133:
1134:
1139: protected void updateCellEditor()
1140: {
1141: if (tree.isEditable() && cellEditor == null)
1142: setCellEditor(createDefaultCellEditor());
1143: createdCellEditor = true;
1144: }
1145:
1146:
1149: protected void updateRenderer()
1150: {
1151:
1152: }
1153:
1154:
1158: protected void configureLayoutCache()
1159: {
1160: treeState = createLayoutCache();
1161: }
1162:
1163:
1167: protected void updateSize()
1168: {
1169:
1170: }
1171:
1172:
1179: protected void updateCachedPreferredSize()
1180: {
1181:
1182: }
1183:
1184:
1190: protected void pathWasExpanded(TreePath path)
1191: {
1192:
1193: }
1194:
1195:
1198: protected void pathWasCollapsed(TreePath path)
1199: {
1200:
1201: }
1202:
1203:
1209: protected void installDefaults(JTree tree)
1210: {
1211: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
1212:
1213: tree.setFont(defaults.getFont("Tree.font"));
1214: tree.setForeground(defaults.getColor("Tree.foreground"));
1215: tree.setBackground(defaults.getColor("Tree.background"));
1216: tree.setOpaque(true);
1217:
1218: rightChildIndent = defaults.getInt("Tree.rightChildIndent");
1219: leftChildIndent = defaults.getInt("Tree.leftChildIndent");
1220: setRowHeight(defaults.getInt("Tree.rowHeight"));
1221: tree.requestFocusInWindow(false);
1222: }
1223:
1224:
1227: protected void installKeyboardActions()
1228: {
1229: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
1230: InputMap focusInputMap = (InputMap) defaults.get("Tree.focusInputMap");
1231: InputMapUIResource parentInputMap = new InputMapUIResource();
1232: ActionMap parentActionMap = new ActionMap();
1233: action = new TreeAction();
1234: Object keys[] = focusInputMap.allKeys();
1235:
1236: for (int i = 0; i < keys.length; i++)
1237: {
1238: parentInputMap.put(
1239: KeyStroke.getKeyStroke(
1240: ((KeyStroke) keys[i]).getKeyCode(),
1241: convertModifiers(((KeyStroke) keys[i]).getModifiers())),
1242: (String) focusInputMap.get((KeyStroke) keys[i]));
1243:
1244: parentInputMap.put(
1245: KeyStroke.getKeyStroke(
1246: ((KeyStroke) keys[i]).getKeyCode(),
1247: ((KeyStroke) keys[i]).getModifiers()),
1248: (String) focusInputMap.get((KeyStroke) keys[i]));
1249:
1250: parentActionMap.put(
1251: (String) focusInputMap.get((KeyStroke) keys[i]),
1252: new ActionListenerProxy(
1253: action,
1254: (String) focusInputMap.get((KeyStroke) keys[i])));
1255:
1256: }
1257:
1258: parentInputMap.setParent(tree.getInputMap(
1259: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).getParent());
1260: parentActionMap.setParent(tree.getActionMap().getParent());
1261: tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).setParent(
1262: parentInputMap);
1263: tree.getActionMap().setParent(parentActionMap);
1264: }
1265:
1266:
1273: private int convertModifiers(int mod)
1274: {
1275: if ((mod & KeyEvent.SHIFT_DOWN_MASK) != 0)
1276: {
1277: mod |= KeyEvent.SHIFT_MASK;
1278: mod &= ~KeyEvent.SHIFT_DOWN_MASK;
1279: }
1280: if ((mod & KeyEvent.CTRL_DOWN_MASK) != 0)
1281: {
1282: mod |= KeyEvent.CTRL_MASK;
1283: mod &= ~KeyEvent.CTRL_DOWN_MASK;
1284: }
1285: if ((mod & KeyEvent.META_DOWN_MASK) != 0)
1286: {
1287: mod |= KeyEvent.META_MASK;
1288: mod &= ~KeyEvent.META_DOWN_MASK;
1289: }
1290: if ((mod & KeyEvent.ALT_DOWN_MASK) != 0)
1291: {
1292: mod |= KeyEvent.ALT_MASK;
1293: mod &= ~KeyEvent.ALT_DOWN_MASK;
1294: }
1295: if ((mod & KeyEvent.ALT_GRAPH_DOWN_MASK) != 0)
1296: {
1297: mod |= KeyEvent.ALT_GRAPH_MASK;
1298: mod &= ~KeyEvent.ALT_GRAPH_DOWN_MASK;
1299: }
1300: return mod;
1301: }
1302:
1303:
1306: protected void installListeners()
1307: {
1308: tree.addPropertyChangeListener(propertyChangeListener);
1309: tree.addFocusListener(focusListener);
1310: tree.addTreeSelectionListener(treeSelectionListener);
1311: tree.addMouseListener(mouseInputListener);
1312: tree.addKeyListener(keyListener);
1313: tree.addPropertyChangeListener(selectionModelPropertyChangeListener);
1314: tree.addComponentListener(componentListener);
1315: tree.addTreeExpansionListener(treeExpansionListener);
1316: if (treeModel != null)
1317: treeModel.addTreeModelListener(treeModelListener);
1318: }
1319:
1320:
1326: public void installUI(JComponent c)
1327: {
1328: super.installUI(c);
1329: installDefaults((JTree) c);
1330: tree = (JTree) c;
1331:
1332: currentCellRenderer = createDefaultCellRenderer();
1333: rendererPane = createCellRendererPane();
1334: createdRenderer = true;
1335:
1336: setCellEditor(createDefaultCellEditor());
1337: createdCellEditor = true;
1338: isEditing = false;
1339:
1340: TreeModel mod = tree.getModel();
1341: setModel(mod);
1342: tree.setRootVisible(true);
1343: if (mod != null)
1344: tree.expandPath(new TreePath(mod.getRoot()));
1345: treeSelectionModel = tree.getSelectionModel();
1346:
1347: installKeyboardActions();
1348: installListeners();
1349: completeUIInstall();
1350: }
1351:
1352:
1358: protected void uninstallDefaults(JTree tree)
1359: {
1360: tree.setFont(null);
1361: tree.setForeground(null);
1362: tree.setBackground(null);
1363: }
1364:
1365:
1371: public void uninstallUI(JComponent c)
1372: {
1373: uninstallDefaults((JTree) c);
1374: uninstallKeyboardActions();
1375: uninstallListeners();
1376: tree = null;
1377: completeUIUninstall();
1378: }
1379:
1380:
1393: public void paint(Graphics g, JComponent c)
1394: {
1395: JTree tree = (JTree) c;
1396:
1397: TreeModel mod = tree.getModel();
1398:
1399: if (mod != null)
1400: {
1401: Object root = mod.getRoot();
1402:
1403: if (!tree.isRootVisible())
1404: tree.expandPath(new TreePath(root));
1405:
1406: paintRecursive(g, 0, 0, 0, 0, tree, mod, root);
1407:
1408: if (hasControlIcons())
1409: paintControlIcons(g, 0, 0, 0, 0, tree, mod, root);
1410: }
1411: }
1412:
1413:
1421: protected void ensureRowsAreVisible(int beginRow, int endRow)
1422: {
1423:
1424: }
1425:
1426:
1432: public void setPreferredMinSize(Dimension newSize)
1433: {
1434:
1435: }
1436:
1437:
1442: public Dimension getPreferredMinSize()
1443: {
1444:
1445: return null;
1446: }
1447:
1448:
1458: public Dimension getPreferredSize(JComponent c)
1459: {
1460: return getPreferredSize(c, false);
1461: }
1462:
1463:
1473: public Dimension getPreferredSize(JComponent c, boolean checkConsistancy)
1474: {
1475:
1476: TreeModel model = tree.getModel();
1477: int maxWidth = 0;
1478: int count = 0;
1479: if (model != null)
1480: {
1481: Object node = model.getRoot();
1482: if (node != null)
1483: {
1484: maxWidth = (int) (getCellBounds(0, 0, node).getWidth());
1485: while (node != null)
1486: {
1487: count++;
1488: Object nextNode = getNextVisibleNode(node);
1489: if (nextNode != null)
1490: maxWidth = Math.max(maxWidth,
1491: (int) (getCellBounds(0, 0, nextNode).getWidth()));
1492: node = nextNode;
1493: }
1494: }
1495: }
1496: return new Dimension(maxWidth, (getRowHeight() * count));
1497: }
1498:
1499:
1507: public Dimension getMinimumSize(JComponent c)
1508: {
1509:
1510: return getPreferredSize(c);
1511: }
1512:
1513:
1521: public Dimension getMaximumSize(JComponent c)
1522: {
1523:
1524: return getPreferredSize(c);
1525: }
1526:
1527:
1534: protected void completeEditing()
1535: {
1536: completeEditing(false, true, false);
1537: }
1538:
1539:
1552: protected void completeEditing(boolean messageStop, boolean messageCancel,
1553: boolean messageTree)
1554: {
1555: if (messageStop)
1556: {
1557: getCellEditor().stopCellEditing();
1558: stopEditingInCompleteEditing = true;
1559: }
1560:
1561: if (messageCancel)
1562: {
1563: getCellEditor().cancelCellEditing();
1564: stopEditingInCompleteEditing = true;
1565: }
1566:
1567: if (messageTree)
1568: tree.getModel().valueForPathChanged(tree.getLeadSelectionPath(), newVal);
1569: }
1570:
1571:
1581: protected boolean startEditing(TreePath path, MouseEvent event)
1582: {
1583: int x;
1584: int y;
1585: if (event == null)
1586: {
1587: Rectangle bounds = getPathBounds(tree, path);
1588: x = bounds.x;
1589: y = bounds.y;
1590: }
1591: else
1592: {
1593: x = event.getX();
1594: y = event.getY();
1595: }
1596:
1597: updateCellEditor();
1598: TreeCellEditor ed = getCellEditor();
1599: if (ed != null && ed.shouldSelectCell(event) && ed.isCellEditable(event))
1600: {
1601: editingPath = path;
1602: editingRow = tree.getRowForPath(editingPath);
1603: Object val = editingPath.getLastPathComponent();
1604: cellEditor.addCellEditorListener(cellEditorListener);
1605: stopEditingInCompleteEditing = false;
1606: boolean expanded = tree.isExpanded(editingPath);
1607: isEditing = true;
1608: editingComponent = ed.getTreeCellEditorComponent(tree, val, true,
1609: expanded,
1610: isLeaf(editingRow),
1611: editingRow);
1612: editingComponent.getParent().setVisible(true);
1613: editingComponent.getParent().validate();
1614: tree.add(editingComponent.getParent());
1615: editingComponent.getParent().validate();
1616: ((JTextField) editingComponent).requestFocusInWindow(false);
1617: editorTimer.start();
1618: return true;
1619: }
1620: return false;
1621: }
1622:
1623:
1634: protected void checkForClickInExpandControl(TreePath path, int mouseX,
1635: int mouseY)
1636: {
1637:
1638: }
1639:
1640:
1655: protected boolean isLocationInExpandControl(TreePath path, int mouseX,
1656: int mouseY)
1657: {
1658:
1659: return false;
1660: }
1661:
1662:
1673: protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY)
1674: {
1675:
1676: }
1677:
1678:
1687: protected void toggleExpandState(TreePath path)
1688: {
1689:
1690: }
1691:
1692:
1701: protected boolean isToggleSelectionEvent(MouseEvent event)
1702: {
1703:
1704: return false;
1705: }
1706:
1707:
1716: protected boolean isMultiSelectEvent(MouseEvent event)
1717: {
1718:
1719: return false;
1720: }
1721:
1722:
1732: protected boolean isToggleEvent(MouseEvent event)
1733: {
1734:
1735: return false;
1736: }
1737:
1738:
1750: protected void selectPathForEvent(TreePath path, MouseEvent event)
1751: {
1752:
1753: }
1754:
1755:
1762: protected boolean isLeaf(int row)
1763: {
1764: TreePath pathForRow = getPathForRow(tree, row);
1765: if (pathForRow == null)
1766: return true;
1767:
1768: Object node = pathForRow.getLastPathComponent();
1769: return tree.getModel().isLeaf(node);
1770: }
1771:
1772:
1777: class TreeAction
1778: extends AbstractAction
1779: {
1780:
1781:
1787: public void actionPerformed(ActionEvent e)
1788: {
1789: TreePath lead = tree.getLeadSelectionPath();
1790:
1791: if (e.getActionCommand().equals("selectPreviousChangeLead")
1792: || e.getActionCommand().equals("selectPreviousExtendSelection")
1793: || e.getActionCommand().equals("selectPrevious")
1794: || e.getActionCommand().equals("selectNext")
1795: || e.getActionCommand().equals("selectNextExtendSelection")
1796: || e.getActionCommand().equals("selectNextChangeLead"))
1797: (new TreeIncrementAction(0, "")).actionPerformed(e);
1798: else if (e.getActionCommand().equals("selectParent")
1799: || e.getActionCommand().equals("selectChild"))
1800: (new TreeTraverseAction(0, "")).actionPerformed(e);
1801: else if (e.getActionCommand().equals("selectAll"))
1802: {
1803: TreePath[] paths = new TreePath[tree.getRowCount()];
1804:
1805: Object curr = getNextVisibleNode(tree.getModel().getRoot());
1806: int i = 0;
1807: while (curr != null && i < paths.length)
1808: {
1809: paths[i] = new TreePath(getPathToRoot(curr, 0));
1810: i++;
1811: }
1812:
1813: tree.addSelectionPaths(paths);
1814: }
1815: else if (e.getActionCommand().equals("startEditing"))
1816: tree.startEditingAtPath(lead);
1817: else if (e.getActionCommand().equals("toggle"))
1818: {
1819: if (tree.isEditing())
1820: tree.stopEditing();
1821: else
1822: {
1823: Object last = lead.getLastPathComponent();
1824: TreePath path = new TreePath(getPathToRoot(last, 0));
1825: if (!tree.getModel().isLeaf(last))
1826: {
1827: if (tree.isExpanded(path))
1828: tree.collapsePath(path);
1829: else
1830: tree.expandPath(path);
1831: }
1832: }
1833: }
1834: else if (e.getActionCommand().equals("clearSelection"))
1835: tree.clearSelection();
1836:
1837: if (tree.isEditing() && !e.getActionCommand().equals("startEditing"))
1838: tree.cancelEditing();
1839:
1840: tree.scrollPathToVisible(lead);
1841: }
1842: }
1843:
1844:
1851: private static class ActionListenerProxy
1852: extends AbstractAction
1853: {
1854: ActionListener target;
1855:
1856: String bindingCommandName;
1857:
1858: public ActionListenerProxy(ActionListener li, String cmd)
1859: {
1860: target = li;
1861: bindingCommandName = cmd;
1862: }
1863:
1864: public void actionPerformed(ActionEvent e)
1865: {
1866: ActionEvent derivedEvent = new ActionEvent(e.getSource(), e.getID(),
1867: bindingCommandName,
1868: e.getModifiers());
1869:
1870: target.actionPerformed(derivedEvent);
1871: }
1872: }
1873:
1874:
1877: private class EditorUpdateTimer
1878: extends Timer
1879: implements ActionListener
1880: {
1881:
1885: public EditorUpdateTimer()
1886: {
1887: super(300, null);
1888: addActionListener(this);
1889: }
1890:
1891:
1894: public void actionPerformed(ActionEvent ev)
1895: {
1896: Caret c = ((JTextField) editingComponent).getCaret();
1897: if (c != null)
1898: c.setVisible(!c.isVisible());
1899: tree.repaint();
1900: }
1901:
1902:
1905: public void update()
1906: {
1907: stop();
1908: Caret c = ((JTextField) editingComponent).getCaret();
1909: if (c != null)
1910: {
1911: setDelay(c.getBlinkRate());
1912: if (((JTextField) editingComponent).isEditable())
1913: start();
1914: else
1915: c.setVisible(false);
1916: }
1917: }
1918: }
1919:
1920:
1923: public class ComponentHandler
1924: extends ComponentAdapter
1925: implements ActionListener
1926: {
1927:
1930: protected Timer timer;
1931:
1932:
1933: protected JScrollBar scrollBar;
1934:
1935:
1938: public ComponentHandler()
1939: {
1940: }
1941:
1942:
1948: public void componentMoved(ComponentEvent e)
1949: {
1950: }
1951:
1952:
1956: protected void startTimer()
1957: {
1958: }
1959:
1960:
1965: protected JScrollPane getScrollPane()
1966: {
1967: return null;
1968: }
1969:
1970:
1977: public void actionPerformed(ActionEvent ae)
1978: {
1979: }
1980: }
1981:
1982:
1986: public class CellEditorHandler
1987: implements CellEditorListener
1988: {
1989:
1992: public CellEditorHandler()
1993: {
1994: }
1995:
1996:
2003: public void editingStopped(ChangeEvent e)
2004: {
2005: editingPath = null;
2006: editingRow = -1;
2007: stopEditingInCompleteEditing = false;
2008: if (editingComponent != null)
2009: {
2010: tree.remove(editingComponent.getParent());
2011: editingComponent = null;
2012: }
2013: if (cellEditor != null)
2014: {
2015: newVal = ((JTextField) getCellEditor().getCellEditorValue()).getText();
2016: completeEditing(false, false, true);
2017: if (cellEditor instanceof DefaultTreeCellEditor)
2018: tree.removeTreeSelectionListener((DefaultTreeCellEditor) cellEditor);
2019: cellEditor.removeCellEditorListener(cellEditorListener);
2020: setCellEditor(null);
2021: createdCellEditor = false;
2022: }
2023: isEditing = false;
2024: tree.requestFocusInWindow(false);
2025: editorTimer.stop();
2026: }
2027:
2028:
2035: public void editingCanceled(ChangeEvent e)
2036: {
2037: editingPath = null;
2038: editingRow = -1;
2039: stopEditingInCompleteEditing = false;
2040: if (editingComponent != null)
2041: tree.remove(editingComponent.getParent());
2042: editingComponent = null;
2043: if (cellEditor != null)
2044: {
2045: if (cellEditor instanceof DefaultTreeCellEditor)
2046: tree.removeTreeSelectionListener((DefaultTreeCellEditor) cellEditor);
2047: cellEditor.removeCellEditorListener(cellEditorListener);
2048: setCellEditor(null);
2049: createdCellEditor = false;
2050: }
2051: tree.requestFocusInWindow(false);
2052: editorTimer.stop();
2053: isEditing = false;
2054: tree.repaint();
2055: }
2056: }
2057:
2058:
2061: public class FocusHandler
2062: implements FocusListener
2063: {
2064:
2067: public FocusHandler()
2068: {
2069: }
2070:
2071:
2078: public void focusGained(FocusEvent e)
2079: {
2080: }
2081:
2082:
2089: public void focusLost(FocusEvent e)
2090: {
2091: }
2092: }
2093:
2094:
2098: public class KeyHandler
2099: extends KeyAdapter
2100: {
2101:
2102: protected Action repeatKeyAction;
2103:
2104:
2105: protected boolean isKeyDown;
2106:
2107:
2110: public KeyHandler()
2111: {
2112: }
2113:
2114:
2123: public void keyTyped(KeyEvent e)
2124: {
2125: }
2126:
2127:
2133: public void keyPressed(KeyEvent e)
2134: {
2135: }
2136:
2137:
2143: public void keyReleased(KeyEvent e)
2144: {
2145: }
2146: }
2147:
2148:
2152: public class MouseHandler
2153: extends MouseAdapter
2154: implements MouseMotionListener
2155: {
2156:
2159: public MouseHandler()
2160: {
2161: }
2162:
2163:
2169: public void mousePressed(MouseEvent e)
2170: {
2171: }
2172:
2173:
2182: public void mouseDragged(MouseEvent e)
2183: {
2184: }
2185:
2186:
2193: public void mouseMoved(MouseEvent e)
2194: {
2195: }
2196:
2197:
2203: public void mouseReleased(MouseEvent e)
2204: {
2205: }
2206: }
2207:
2208:
2213: public class MouseInputHandler
2214: implements MouseInputListener
2215: {
2216:
2217: protected Component source;
2218:
2219:
2220: protected Component destination;
2221:
2222:
2232: public MouseInputHandler(Component source, Component destination,
2233: MouseEvent e)
2234: {
2235: }
2236:
2237:
2244: public void mouseClicked(MouseEvent e)
2245: {
2246: }
2247:
2248:
2254: public void mousePressed(MouseEvent e)
2255: {
2256: Point click = e.getPoint();
2257: int row = Math.round(click.y / getRowHeight());
2258: TreePath path = getClosestPathForLocation(tree, click.x, click.y);
2259:
2260: if (path != null)
2261: {
2262: boolean inBounds = false;
2263: boolean cntlClick = false;
2264: Rectangle bounds = getPathBounds(tree, path);
2265:
2266: bounds.x -= rightChildIndent - 4;
2267: bounds.width += rightChildIndent + 4;
2268:
2269: if (bounds.contains(click.x, click.y))
2270: inBounds = true;
2271: else if (hasControlIcons()
2272: && (click.x < (bounds.x - rightChildIndent + 5) &&
2273: click.x > (bounds.x - rightChildIndent - 5)))
2274: cntlClick = true;
2275:
2276: if ((inBounds || cntlClick) && tree.isVisible(path))
2277: {
2278: selectPath(tree, path);
2279:
2280: if ((e.getClickCount() == 2 || cntlClick) && !isLeaf(row))
2281: {
2282: if (tree.isExpanded(path))
2283: tree.collapsePath(path);
2284: else
2285: tree.expandPath(path);
2286: }
2287:
2288: if (!cntlClick && tree.isEditable())
2289: startEditing(path, e);
2290: }
2291: }
2292: }
2293:
2294:
2300: public void mouseReleased(MouseEvent e)
2301: {
2302: }
2303:
2304:
2310: public void mouseEntered(MouseEvent e)
2311: {
2312: }
2313:
2314:
2320: public void mouseExited(MouseEvent e)
2321: {
2322: }
2323:
2324:
2333: public void mouseDragged(MouseEvent e)
2334: {
2335: }
2336:
2337:
2344: public void mouseMoved(MouseEvent e)
2345: {
2346: }
2347:
2348:
2351: protected void removeFromSource()
2352: {
2353: }
2354: }
2355:
2356:
2361: public class NodeDimensionsHandler
2362: extends AbstractLayoutCache.NodeDimensions
2363: {
2364:
2367: public NodeDimensionsHandler()
2368: {
2369: }
2370:
2371:
2386: public Rectangle getNodeDimensions(Object value, int row, int depth,
2387: boolean expanded, Rectangle size)
2388: {
2389: return null;
2390: }
2391:
2392:
2397: protected int getRowX(int row, int depth)
2398: {
2399: return 0;
2400: }
2401: }
2402:
2403:
2407: public class PropertyChangeHandler
2408: implements PropertyChangeListener
2409: {
2410:
2411:
2414: public PropertyChangeHandler()
2415: {
2416: }
2417:
2418:
2425: public void propertyChange(PropertyChangeEvent event)
2426: {
2427: }
2428: }
2429:
2430:
2434: public class SelectionModelPropertyChangeHandler
2435: implements PropertyChangeListener
2436: {
2437:
2438:
2441: public SelectionModelPropertyChangeHandler()
2442: {
2443: }
2444:
2445:
2452: public void propertyChange(PropertyChangeEvent event)
2453: {
2454: }
2455: }
2456:
2457:
2460: public class TreeCancelEditingAction
2461: extends AbstractAction
2462: {
2463:
2464:
2467: public TreeCancelEditingAction()
2468: {
2469: }
2470:
2471:
2477: public void actionPerformed(ActionEvent e)
2478: {
2479: }
2480:
2481:
2486: public boolean isEnabled()
2487: {
2488: return false;
2489: }
2490: }
2491:
2492:
2495: public class TreeExpansionHandler
2496: implements TreeExpansionListener
2497: {
2498:
2499:
2502: public TreeExpansionHandler()
2503: {
2504: }
2505:
2506:
2512: public void treeExpanded(TreeExpansionEvent event)
2513: {
2514: tree.repaint();
2515: }
2516:
2517:
2523: public void treeCollapsed(TreeExpansionEvent event)
2524: {
2525: tree.repaint();
2526: }
2527: }
2528:
2529:
2533: public class TreeHomeAction
2534: extends AbstractAction
2535: {
2536:
2537:
2538: protected int direction;
2539:
2540:
2548: public TreeHomeAction(int direction, String name)
2549: {
2550: }
2551:
2552:
2558: public void actionPerformed(ActionEvent e)
2559: {
2560: }
2561:
2562:
2567: public boolean isEnabled()
2568: {
2569: return false;
2570: }
2571: }
2572:
2573:
2577: public class TreeIncrementAction
2578: extends AbstractAction
2579: {
2580:
2581:
2582: protected int direction;
2583:
2584:
2592: public TreeIncrementAction(int direction, String name)
2593: {
2594: }
2595:
2596:
2602: public void actionPerformed(ActionEvent e)
2603: {
2604: Object last = tree.getLeadSelectionPath().getLastPathComponent();
2605:
2606: if (e.getActionCommand().equals("selectPreviousChangeLead"))
2607: {
2608: Object prev = getPreviousVisibleNode(last);
2609:
2610: if (prev != null)
2611: {
2612: TreePath newPath = new TreePath(getPathToRoot(prev, 0));
2613: selectPath(tree, new TreePath(getPathToRoot(prev, 0)));
2614: tree.setLeadSelectionPath(newPath);
2615: }
2616: }
2617: else if (e.getActionCommand().equals("selectPreviousExtendSelection"))
2618: {
2619: Object prev = getPreviousVisibleNode(last);
2620: if (prev != null)
2621: {
2622: TreePath newPath = new TreePath(getPathToRoot(prev, 0));
2623: tree.addSelectionPath(newPath);
2624: tree.setLeadSelectionPath(newPath);
2625: }
2626: }
2627: else if (e.getActionCommand().equals("selectPrevious"))
2628: {
2629: Object prev = getPreviousVisibleNode(last);
2630: if (prev != null)
2631: {
2632: TreePath newPath = new TreePath(getPathToRoot(prev, 0));
2633: selectPath(tree, new TreePath(getPathToRoot(prev, 0)));
2634: }
2635: }
2636: else if (e.getActionCommand().equals("selectNext"))
2637: {
2638: Object next = getNextVisibleNode(last);
2639: if (next != null)
2640: {
2641: TreePath newPath = new TreePath(getPathToRoot(next, 0));
2642: selectPath(tree, newPath);
2643: }
2644: }
2645: else if (e.getActionCommand().equals("selectNextExtendSelection"))
2646: {
2647: Object next = getNextVisibleNode(last);
2648: if (next != null)
2649: {
2650: TreePath newPath = new TreePath(getPathToRoot(next, 0));
2651: tree.addSelectionPath(newPath);
2652: tree.setLeadSelectionPath(newPath);
2653: }
2654: }
2655: else if (e.getActionCommand().equals("selectNextChangeLead"))
2656: {
2657: Object next = getNextVisibleNode(last);
2658: if (next != null)
2659: {
2660: TreePath newPath = new TreePath(getPathToRoot(next, 0));
2661: selectPath(tree, newPath);
2662: tree.setLeadSelectionPath(newPath);
2663: }
2664: }
2665: }
2666:
2667:
2672: public boolean isEnabled()
2673: {
2674: return false;
2675: }
2676: }
2677:
2678:
2681: public class TreeModelHandler
2682: implements TreeModelListener
2683: {
2684:
2687: public TreeModelHandler()
2688: {
2689: }
2690:
2691:
2704: public void treeNodesChanged(TreeModelEvent e)
2705: {
2706: tree.repaint();
2707: }
2708:
2709:
2717: public void treeNodesInserted(TreeModelEvent e)
2718: {
2719: tree.repaint();
2720: }
2721:
2722:
2733: public void treeNodesRemoved(TreeModelEvent e)
2734: {
2735: tree.repaint();
2736: }
2737:
2738:
2748: public void treeStructureChanged(TreeModelEvent e)
2749: {
2750: tree.repaint();
2751: }
2752: }
2753:
2754:
2757: public class TreePageAction
2758: extends AbstractAction
2759: {
2760:
2761: protected int direction;
2762:
2763:
2771: public TreePageAction(int direction, String name)
2772: {
2773: }
2774:
2775:
2781: public void actionPerformed(ActionEvent e)
2782: {
2783: }
2784:
2785:
2790: public boolean isEnabled()
2791: {
2792: return false;
2793: }
2794: }
2795:
2796:
2800: public class TreeSelectionHandler
2801: implements TreeSelectionListener
2802: {
2803:
2806: public TreeSelectionHandler()
2807: {
2808: }
2809:
2810:
2817: public void valueChanged(TreeSelectionEvent event)
2818: {
2819: if (tree.isEditing())
2820: tree.cancelEditing();
2821: }
2822: }
2823:
2824:
2827: public class TreeToggleAction
2828: extends AbstractAction
2829: {
2830:
2836: public TreeToggleAction(String name)
2837: {
2838: }
2839:
2840:
2846: public void actionPerformed(ActionEvent e)
2847: {
2848: }
2849:
2850:
2855: public boolean isEnabled()
2856: {
2857: return false;
2858: }
2859: }
2860:
2861:
2865: public class TreeTraverseAction
2866: extends AbstractAction
2867: {
2868:
2871: protected int direction;
2872:
2873:
2881: public TreeTraverseAction(int direction, String name)
2882: {
2883: }
2884:
2885:
2891: public void actionPerformed(ActionEvent e)
2892: {
2893: TreeModel mod = tree.getModel();
2894: Object last = tree.getLeadSelectionPath().getLastPathComponent();
2895:
2896: if (e.getActionCommand().equals("selectParent"))
2897: {
2898: TreePath path = new TreePath(getPathToRoot(last, 0));
2899: Object p = getParent(mod.getRoot(), last);
2900:
2901: if (!mod.isLeaf(last) && tree.isExpanded(path))
2902: tree.collapsePath(path);
2903: else if (p != null)
2904: selectPath(tree, new TreePath(getPathToRoot(p, 0)));
2905: }
2906: else if (e.getActionCommand().equals("selectChild"))
2907: {
2908: TreePath path = new TreePath(getPathToRoot(last, 0));
2909:
2910: if (!mod.isLeaf(last) && tree.isCollapsed(path))
2911: tree.expandPath(path);
2912: else
2913: {
2914: Object next = getNextVisibleNode(last);
2915:
2916: if (next != null)
2917: selectPath(tree, new TreePath(getPathToRoot(next, 0)));
2918: }
2919: }
2920: }
2921:
2922:
2927: public boolean isEnabled()
2928: {
2929: return false;
2930: }
2931: }
2932:
2933:
2945: Rectangle getCellBounds(int x, int y, Object cell)
2946: {
2947: if (cell != null)
2948: {
2949: String s = cell.toString();
2950: Font f = tree.getFont();
2951: FontMetrics fm = tree.getToolkit().getFontMetrics(f);
2952:
2953: if (s != null)
2954: return new Rectangle(x, y,
2955: SwingUtilities.computeStringWidth(fm, s) + 4,
2956: fm.getHeight());
2957: }
2958: return new Rectangle(x, y, 0, 0);
2959: }
2960:
2961:
2979: Point getCellLocation(int x, int y, JTree tree, TreeModel mod, Object node,
2980: Object startNode)
2981: {
2982: int rowHeight = getRowHeight();
2983: if (startNode == null || startNode.equals(node))
2984: {
2985: if (!tree.isRootVisible()
2986: && tree.isExpanded(new TreePath(mod.getRoot())))
2987: return new Point(x + ((getLevel(node)) * rightChildIndent), y);
2988:
2989: return new Point(x + ((getLevel(node) + 1) * rightChildIndent), y);
2990: }
2991:
2992: if (!mod.isLeaf(startNode)
2993: && tree.isExpanded(new TreePath(getPathToRoot(startNode, 0)))
2994: && !mod.isLeaf(startNode) && mod.getChildCount(startNode) > 0)
2995: {
2996: Object child = mod.getChild(startNode, 0);
2997: if (child != null)
2998: return getCellLocation(x, y + rowHeight, tree, mod, node, child);
2999: }
3000:
3001: return getCellLocation(x, y + rowHeight, tree, mod, node,
3002: getNextVisibleNode(startNode));
3003: }
3004:
3005:
3019: void paintNode(Graphics g, int x, int y, JTree tree, Object node,
3020: boolean isLeaf)
3021: {
3022: TreePath curr = new TreePath(getPathToRoot(node, 0));
3023: boolean selected = tree.isPathSelected(curr);
3024: boolean expanded = false;
3025: boolean hasIcons = false;
3026:
3027: if (tree.isVisible(curr))
3028: {
3029: if (!isLeaf)
3030: expanded = tree.isExpanded(curr);
3031:
3032: if (editingComponent != null && editingPath != null && isEditing(tree)
3033: && node.equals(editingPath.getLastPathComponent()))
3034: {
3035: Rectangle bounds = getPathBounds(tree, editingPath);
3036: rendererPane.paintComponent(g, editingComponent.getParent(), null,
3037: new Rectangle(0, 0, bounds.width,
3038: bounds.height));
3039: }
3040: else
3041: {
3042: TreeCellRenderer dtcr = tree.getCellRenderer();
3043: if (dtcr == null)
3044: dtcr = createDefaultCellRenderer();
3045:
3046: int row = getRowForPath(tree, curr);
3047:
3048: Component c = dtcr.getTreeCellRendererComponent(tree, node,
3049: selected, expanded,
3050: isLeaf, row, false);
3051:
3052: rendererPane.paintComponent(g, c, c.getParent(),
3053: getCellBounds(x, y, node));
3054: }
3055: }
3056: }
3057:
3058:
3080: int paintRecursive(Graphics g, int indentation, int descent, int childNumber,
3081: int depth, JTree tree, TreeModel mod, Object curr)
3082: {
3083: Rectangle clip = g.getClipBounds();
3084: if (indentation > clip.x + clip.width + rightChildIndent
3085: || descent > clip.y + clip.height + getRowHeight())
3086: return descent;
3087:
3088: int halfHeight = getRowHeight() / 2;
3089: int halfWidth = rightChildIndent / 2;
3090: int y0 = descent + halfHeight;
3091: int heightOfLine = descent + halfHeight;
3092: boolean isRootVisible = tree.isRootVisible();
3093:
3094: if (mod.isLeaf(curr))
3095: {
3096: paintNode(g, indentation + 4, descent, tree, curr, true);
3097: descent += getRowHeight();
3098: }
3099: else
3100: {
3101: if (depth > 0 || isRootVisible)
3102: {
3103: paintNode(g, indentation + 4, descent, tree, curr, false);
3104: descent += getRowHeight();
3105: y0 += halfHeight;
3106: }
3107:
3108: int max = 0;
3109: if (!mod.isLeaf(curr))
3110: max = mod.getChildCount(curr);
3111: if (tree.isExpanded(new TreePath(getPathToRoot(curr, 0))))
3112: {
3113: for (int i = 0; i < max; i++)
3114: {
3115: int indent = indentation + rightChildIndent;
3116: if (!isRootVisible && depth == 0)
3117: indent = 0;
3118: else if ((!isRootVisible && !curr.equals(mod.getRoot()))
3119: || isRootVisible)
3120: {
3121: g.setColor(getHashColor());
3122: heightOfLine = descent + halfHeight;
3123: g.drawLine(indentation + halfWidth, heightOfLine,
3124: indentation + rightChildIndent, heightOfLine);
3125: }
3126:
3127: descent = paintRecursive(g, indent, descent, i, depth + 1,
3128: tree, mod, mod.getChild(curr, i));
3129: }
3130: }
3131: }
3132:
3133: if (tree.isExpanded(new TreePath(getPathToRoot(curr, 0))))
3134: if (y0 != heightOfLine && !mod.isLeaf(curr)
3135: && mod.getChildCount(curr) > 0)
3136: {
3137: g.setColor(getHashColor());
3138: g.drawLine(indentation + halfWidth, y0, indentation + halfWidth,
3139: heightOfLine);
3140: }
3141:
3142: return descent;
3143: }
3144:
3145:
3167: int paintControlIcons(Graphics g, int indentation, int descent,
3168: int childNumber, int depth, JTree tree, TreeModel mod,
3169: Object node)
3170: {
3171: int h = descent;
3172: int rowHeight = getRowHeight();
3173: Icon ei = UIManager.getLookAndFeelDefaults().getIcon("Tree.expandedIcon");
3174: Icon ci = UIManager.getLookAndFeelDefaults().getIcon("Tree.collapsedIcon");
3175: Rectangle clip = g.getClipBounds();
3176: if (indentation > clip.x + clip.width + rightChildIndent
3177: || descent > clip.y + clip.height + getRowHeight())
3178: return descent;
3179:
3180: if (mod.isLeaf(node))
3181: descent += rowHeight;
3182: else
3183: {
3184: if (depth > 0 || tree.isRootVisible())
3185: descent += rowHeight;
3186:
3187: int max = 0;
3188: if (!mod.isLeaf(node))
3189: max = mod.getChildCount(node);
3190: if (tree.isExpanded(new TreePath(getPathToRoot(node, 0))))
3191: {
3192: if (!node.equals(mod.getRoot()))
3193: ei.paintIcon(tree, g, indentation - rightChildIndent - 3, h);
3194:
3195: for (int i = 0; i < max; i++)
3196: {
3197: int indent = indentation + rightChildIndent;
3198: if (depth == 0 && !tree.isRootVisible())
3199: indent = -1;
3200:
3201: descent = paintControlIcons(g, indent, descent, i, depth + 1,
3202: tree, mod, mod.getChild(node, i));
3203: }
3204: }
3205: else if (!node.equals(mod.getRoot()))
3206: ci.paintIcon(tree, g, indentation - rightChildIndent - 3,
3207: descent - getRowHeight());
3208: }
3209:
3210: return descent;
3211: }
3212:
3213:
3219: boolean hasControlIcons()
3220: {
3221: if (UIManager.getLookAndFeelDefaults().getIcon("Tree.expandedIcon") == null
3222: || UIManager.getLookAndFeelDefaults().getIcon("Tree.collapsedIcon") == null)
3223: return false;
3224: return true;
3225: }
3226:
3227:
3236: Object getParent(Object root, Object node)
3237: {
3238: if (root == null || node == null)
3239: return null;
3240: if (node instanceof TreeNode)
3241: return ((TreeNode) node).getParent();
3242: return findNode(root, node);
3243: }
3244:
3245:
3254: private Object findNode(Object root, Object node)
3255: {
3256: TreeModel mod = tree.getModel();
3257: int size = 0;
3258: if (!mod.isLeaf(root))
3259: size = mod.getChildCount(root);
3260: for (int i = 0; i < size; i++)
3261: {
3262: if (mod.getIndexOfChild(root, node) != -1)
3263: return root;
3264:
3265: Object n = findNode(mod.getChild(root, i), node);
3266: if (n != null)
3267: return n;
3268: }
3269: return null;
3270: }
3271:
3272:
3281: Object getNextVisibleNode(Object node)
3282: {
3283: Object next = null;
3284: TreePath current = null;
3285:
3286: if (node != null)
3287: next = getNextNode(node);
3288:
3289: if (next != null)
3290: {
3291: current = new TreePath(getPathToRoot(next, 0));
3292: if (tree.isVisible(current))
3293: return next;
3294:
3295: while (next != null && !tree.isVisible(current))
3296: {
3297: next = getNextNode(next);
3298:
3299: if (next != null)
3300: current = new TreePath(getPathToRoot(next, 0));
3301: }
3302: }
3303: return next;
3304: }
3305:
3306:
3315: Object getPreviousVisibleNode(Object node)
3316: {
3317: Object prev = null;
3318: TreePath current = null;
3319:
3320: if (node != null)
3321: prev = getPreviousNode(node);
3322:
3323: if (prev != null)
3324: {
3325: current = new TreePath(getPathToRoot(prev, 0));
3326: if (tree.isVisible(current))
3327: return prev;
3328:
3329: while (prev != null && !tree.isVisible(current))
3330: {
3331: prev = getPreviousNode(prev);
3332:
3333: if (prev != null)
3334: current = new TreePath(getPathToRoot(prev, 0));
3335: }
3336: }
3337: return prev;
3338: }
3339:
3340:
3347: Object getNextNode(Object curr)
3348: {
3349: TreeModel mod = tree.getModel();
3350: if (!mod.isLeaf(curr) && mod.getChildCount(curr) > 0)
3351: return mod.getChild(curr, 0);
3352:
3353: Object node = curr;
3354: Object sibling = null;
3355:
3356: do
3357: {
3358: sibling = getNextSibling(node);
3359: node = getParent(mod.getRoot(), node);
3360: }
3361: while (sibling == null && node != null);
3362:
3363: return sibling;
3364: }
3365:
3366:
3374: Object getPreviousNode(Object node)
3375: {
3376: TreeModel mod = tree.getModel();
3377: Object parent = getParent(mod.getRoot(), node);
3378: if (parent == null)
3379: return null;
3380:
3381: Object sibling = getPreviousSibling(node);
3382:
3383: if (sibling == null)
3384: return parent;
3385:
3386: int size = 0;
3387: if (!mod.isLeaf(sibling))
3388: size = mod.getChildCount(sibling);
3389: while (size > 0)
3390: {
3391: sibling = mod.getChild(sibling, size - 1);
3392: if (!mod.isLeaf(sibling))
3393: size = mod.getChildCount(sibling);
3394: else
3395: size = 0;
3396: }
3397:
3398: return sibling;
3399: }
3400:
3401:
3409: Object getNextSibling(Object node)
3410: {
3411: TreeModel mod = tree.getModel();
3412: Object parent = getParent(mod.getRoot(), node);
3413: if (parent == null)
3414: return null;
3415:
3416: int index = mod.getIndexOfChild(parent, node) + 1;
3417:
3418: int size = 0;
3419: if (!mod.isLeaf(parent))
3420: size = mod.getChildCount(parent);
3421: if (index == 0 || index >= size)
3422: return null;
3423:
3424: return mod.getChild(parent, index);
3425: }
3426:
3427:
3435: Object getPreviousSibling(Object node)
3436: {
3437: TreeModel mod = tree.getModel();
3438: Object parent = getParent(mod.getRoot(), node);
3439: if (parent == null)
3440: return null;
3441:
3442: int index = mod.getIndexOfChild(parent, node) - 1;
3443:
3444: int size = 0;
3445: if (!mod.isLeaf(parent))
3446: size = mod.getChildCount(parent);
3447: if (index < 0 || index >= size)
3448: return null;
3449:
3450: return mod.getChild(parent, index);
3451: }
3452:
3453:
3462: void selectPath(JTree tree, TreePath path)
3463: {
3464: if (path != null)
3465: {
3466: if (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION)
3467: {
3468: tree.addSelectionPath(path);
3469: tree.setLeadSelectionPath(path);
3470: }
3471: else if (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION)
3472: {
3473:
3474: }
3475: else
3476: {
3477: tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
3478:
3479: tree.getSelectionModel().clearSelection();
3480: tree.addSelectionPath(path);
3481: tree.setLeadSelectionPath(path);
3482: }
3483: }
3484: }
3485:
3486:
3496: Object[] getPathToRoot(Object node, int depth)
3497: {
3498: TreeModel mod = tree.getModel();
3499: if (node == null)
3500: {
3501: if (depth == 0)
3502: return null;
3503:
3504: return new Object[depth];
3505: }
3506:
3507: Object[] path = getPathToRoot(getParent(mod.getRoot(), node), depth + 1);
3508: path[path.length - depth - 1] = node;
3509: return path;
3510: }
3511:
3512:
3519: int getLevel(Object node)
3520: {
3521: int count = -1;
3522: Object current = node;
3523:
3524: do
3525: {
3526: current = getParent(tree.getModel().getRoot(), current);
3527: count++;
3528: }
3529: while (current != null);
3530:
3531: return count;
3532: }
3533:
3534:
3548: protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
3549: int bottom)
3550: {
3551: g.drawLine(x, top, x, bottom);
3552: }
3553:
3554:
3568: protected void paintHorizontalLine(Graphics g, JComponent c, int y, int left,
3569: int right)
3570: {
3571: g.drawLine(left, y, right, y);
3572: }
3573:
3574:
3589: protected void drawCentered(JComponent c, Graphics g, Icon icon, int x, int y)
3590: {
3591: int beginPositionX = x - icon.getIconWidth() / 2;
3592: int beginPositionY = y - icon.getIconHeight() / 2;
3593: icon.paintIcon(c, g, beginPositionX, beginPositionY);
3594: }
3595: }