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:
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: import ;
108:
109:
118: public class BasicTreeUI
119: extends TreeUI
120: {
121:
127: static int WAIT_TILL_EDITING = 900;
128:
129:
130: protected transient Icon collapsedIcon;
131:
132:
133: protected transient Icon expandedIcon;
134:
135:
136: protected int leftChildIndent;
137:
138:
141: protected int rightChildIndent;
142:
143:
147: protected int totalChildIndent;
148:
149:
150: protected int lastSelectedRow;
151:
152:
153: protected JTree tree;
154:
155:
156: protected transient TreeCellRenderer currentCellRenderer;
157:
158:
162: protected boolean createdRenderer;
163:
164:
165: protected transient TreeCellEditor cellEditor;
166:
167:
171: protected boolean createdCellEditor;
172:
173:
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<TreePath, Boolean> 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: boolean isEditing;
242:
243:
244: TreePath currentVisiblePath;
245:
246:
247: int gap = 4;
248:
249:
250: int maxHeight;
251:
252:
253: Color hashColor;
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:
279: static Icon nullIcon;
280:
281:
286: static final MouseEvent EDIT = new MouseEvent(new Label(), 7, 7, 7, 7, 7, 7,
287: false);
288:
289:
292: public BasicTreeUI()
293: {
294: validCachedPreferredSize = false;
295: drawingCache = new Hashtable();
296: nodeDimensions = createNodeDimensions();
297: configureLayoutCache();
298:
299: editingRow = - 1;
300: lastSelectedRow = - 1;
301: }
302:
303:
309: public static ComponentUI createUI(JComponent c)
310: {
311: return new BasicTreeUI();
312: }
313:
314:
319: protected Color getHashColor()
320: {
321: return hashColor;
322: }
323:
324:
329: protected void setHashColor(Color color)
330: {
331: hashColor = color;
332: }
333:
334:
339: public void setLeftChildIndent(int newAmount)
340: {
341: leftChildIndent = newAmount;
342: }
343:
344:
349: public int getLeftChildIndent()
350: {
351: return leftChildIndent;
352: }
353:
354:
359: public void setRightChildIndent(int newAmount)
360: {
361: rightChildIndent = newAmount;
362: }
363:
364:
369: public int getRightChildIndent()
370: {
371: return rightChildIndent;
372: }
373:
374:
379: public void setExpandedIcon(Icon newG)
380: {
381: expandedIcon = newG;
382: }
383:
384:
389: public Icon getExpandedIcon()
390: {
391: return expandedIcon;
392: }
393:
394:
399: public void setCollapsedIcon(Icon newG)
400: {
401: collapsedIcon = newG;
402: }
403:
404:
409: public Icon getCollapsedIcon()
410: {
411: return collapsedIcon;
412: }
413:
414:
419: protected void setLargeModel(boolean largeModel)
420: {
421: if (largeModel != this.largeModel)
422: {
423: completeEditing();
424: tree.removeComponentListener(componentListener);
425: this.largeModel = largeModel;
426: tree.addComponentListener(componentListener);
427: }
428: }
429:
430:
435: protected boolean isLargeModel()
436: {
437: return largeModel;
438: }
439:
440:
445: protected void setRowHeight(int rowHeight)
446: {
447: completeEditing();
448: if (rowHeight == 0)
449: rowHeight = getMaxHeight(tree);
450: treeState.setRowHeight(rowHeight);
451: }
452:
453:
458: protected int getRowHeight()
459: {
460: return tree.getRowHeight();
461: }
462:
463:
469: protected void setCellRenderer(TreeCellRenderer tcr)
470: {
471:
472: completeEditing();
473:
474:
475: updateRenderer();
476:
477:
478: if (treeState != null)
479: {
480: treeState.invalidateSizes();
481: updateSize();
482: }
483: }
484:
485:
491: protected TreeCellRenderer getCellRenderer()
492: {
493: if (currentCellRenderer != null)
494: return currentCellRenderer;
495:
496: return createDefaultCellRenderer();
497: }
498:
499:
504: protected void setModel(TreeModel model)
505: {
506: completeEditing();
507:
508: if (treeModel != null && treeModelListener != null)
509: treeModel.removeTreeModelListener(treeModelListener);
510:
511: treeModel = tree.getModel();
512:
513: if (treeModel != null && treeModelListener != null)
514: treeModel.addTreeModelListener(treeModelListener);
515:
516: if (treeState != null)
517: {
518: treeState.setModel(treeModel);
519: updateLayoutCacheExpandedNodes();
520: updateSize();
521: }
522: }
523:
524:
529: protected TreeModel getModel()
530: {
531: return treeModel;
532: }
533:
534:
539: protected void setRootVisible(boolean newValue)
540: {
541: completeEditing();
542: tree.setRootVisible(newValue);
543: }
544:
545:
550: protected boolean isRootVisible()
551: {
552: return tree.isRootVisible();
553: }
554:
555:
560: protected void setShowsRootHandles(boolean newValue)
561: {
562: completeEditing();
563: updateDepthOffset();
564: if (treeState != null)
565: {
566: treeState.invalidateSizes();
567: updateSize();
568: }
569: }
570:
571:
576: protected boolean getShowsRootHandles()
577: {
578: return tree.getShowsRootHandles();
579: }
580:
581:
586: protected void setCellEditor(TreeCellEditor editor)
587: {
588: updateCellEditor();
589: }
590:
591:
596: protected TreeCellEditor getCellEditor()
597: {
598: return cellEditor;
599: }
600:
601:
606: protected void setEditable(boolean newValue)
607: {
608: updateCellEditor();
609: }
610:
611:
616: protected boolean isEditable()
617: {
618: return tree.isEditable();
619: }
620:
621:
627: protected void setSelectionModel(TreeSelectionModel newLSM)
628: {
629: completeEditing();
630: if (newLSM != null)
631: {
632: treeSelectionModel = newLSM;
633: tree.setSelectionModel(treeSelectionModel);
634: }
635: }
636:
637:
642: protected TreeSelectionModel getSelectionModel()
643: {
644: return treeSelectionModel;
645: }
646:
647:
657: public Rectangle getPathBounds(JTree tree, TreePath path)
658: {
659: Rectangle bounds = null;
660: if (tree != null && treeState != null)
661: {
662: bounds = treeState.getBounds(path, null);
663: Insets i = tree.getInsets();
664: if (bounds != null && i != null)
665: {
666: bounds.x += i.left;
667: bounds.y += i.top;
668: }
669: }
670: return bounds;
671: }
672:
673:
679: int getMaxHeight(JTree tree)
680: {
681: if (maxHeight != 0)
682: return maxHeight;
683:
684: Icon e = UIManager.getIcon("Tree.openIcon");
685: Icon c = UIManager.getIcon("Tree.closedIcon");
686: Icon l = UIManager.getIcon("Tree.leafIcon");
687: int rc = getRowCount(tree);
688: int iconHeight = 0;
689:
690: for (int row = 0; row < rc; row++)
691: {
692: if (isLeaf(row))
693: iconHeight = l.getIconHeight();
694: else if (tree.isExpanded(row))
695: iconHeight = e.getIconHeight();
696: else
697: iconHeight = c.getIconHeight();
698:
699: maxHeight = Math.max(maxHeight, iconHeight + gap);
700: }
701:
702: treeState.setRowHeight(maxHeight);
703: return maxHeight;
704: }
705:
706:
709: Icon getNodeIcon(TreePath path)
710: {
711: Object node = path.getLastPathComponent();
712: if (treeModel.isLeaf(node))
713: return UIManager.getIcon("Tree.leafIcon");
714: else if (treeState.getExpandedState(path))
715: return UIManager.getIcon("Tree.openIcon");
716: else
717: return UIManager.getIcon("Tree.closedIcon");
718: }
719:
720:
727: public TreePath getPathForRow(JTree tree, int row)
728: {
729: return treeState.getPathForRow(row);
730: }
731:
732:
742: public int getRowForPath(JTree tree, TreePath path)
743: {
744: return treeState.getRowForPath(path);
745: }
746:
747:
753: public int getRowCount(JTree tree)
754: {
755: return treeState.getRowCount();
756: }
757:
758:
769: public TreePath getClosestPathForLocation(JTree tree, int x, int y)
770: {
771: return treeState.getPathClosestTo(x, y);
772: }
773:
774:
781: public boolean isEditing(JTree tree)
782: {
783: return isEditing;
784: }
785:
786:
794: public boolean stopEditing(JTree tree)
795: {
796: boolean ret = false;
797: if (editingComponent != null && cellEditor.stopCellEditing())
798: {
799: completeEditing(false, false, true);
800: ret = true;
801: }
802: return ret;
803: }
804:
805:
810: public void cancelEditing(JTree tree)
811: {
812:
813:
814:
815: if (editingComponent != null)
816: completeEditing(false, true, false);
817: }
818:
819:
826: public void startEditingAtPath(JTree tree, TreePath path)
827: {
828: tree.scrollPathToVisible(path);
829: if (path != null && tree.isVisible(path))
830: startEditing(path, null);
831: }
832:
833:
839: public TreePath getEditingPath(JTree tree)
840: {
841: return editingPath;
842: }
843:
844:
848: protected void prepareForUIInstall()
849: {
850: lastSelectedRow = -1;
851: preferredSize = new Dimension();
852: largeModel = tree.isLargeModel();
853: preferredSize = new Dimension();
854: stopEditingInCompleteEditing = true;
855: setModel(tree.getModel());
856: }
857:
858:
862: protected void completeUIInstall()
863: {
864: setShowsRootHandles(tree.getShowsRootHandles());
865: updateRenderer();
866: updateDepthOffset();
867: setSelectionModel(tree.getSelectionModel());
868: configureLayoutCache();
869: treeState.setRootVisible(tree.isRootVisible());
870: treeSelectionModel.setRowMapper(treeState);
871: updateSize();
872: }
873:
874:
878: protected void completeUIUninstall()
879: {
880: tree = null;
881: }
882:
883:
886: protected void installComponents()
887: {
888: currentCellRenderer = createDefaultCellRenderer();
889: rendererPane = createCellRendererPane();
890: createdRenderer = true;
891: setCellRenderer(currentCellRenderer);
892: }
893:
894:
901: protected AbstractLayoutCache.NodeDimensions createNodeDimensions()
902: {
903: return new NodeDimensionsHandler();
904: }
905:
906:
912: protected PropertyChangeListener createPropertyChangeListener()
913: {
914: return new PropertyChangeHandler();
915: }
916:
917:
923: protected MouseListener createMouseListener()
924: {
925: return new MouseHandler();
926: }
927:
928:
934: protected FocusListener createFocusListener()
935: {
936: return new FocusHandler();
937: }
938:
939:
944: protected KeyListener createKeyListener()
945: {
946: return new KeyHandler();
947: }
948:
949:
956: protected PropertyChangeListener createSelectionModelPropertyChangeListener()
957: {
958: return new SelectionModelPropertyChangeHandler();
959: }
960:
961:
967: protected TreeSelectionListener createTreeSelectionListener()
968: {
969: return new TreeSelectionHandler();
970: }
971:
972:
977: protected CellEditorListener createCellEditorListener()
978: {
979: return new CellEditorHandler();
980: }
981:
982:
989: protected ComponentListener createComponentListener()
990: {
991: return new ComponentHandler();
992: }
993:
994:
1000: protected TreeExpansionListener createTreeExpansionListener()
1001: {
1002: return new TreeExpansionHandler();
1003: }
1004:
1005:
1011: protected AbstractLayoutCache createLayoutCache()
1012: {
1013: return new VariableHeightLayoutCache();
1014: }
1015:
1016:
1021: protected CellRendererPane createCellRendererPane()
1022: {
1023: return new CellRendererPane();
1024: }
1025:
1026:
1031: protected TreeCellEditor createDefaultCellEditor()
1032: {
1033: DefaultTreeCellEditor ed;
1034: if (currentCellRenderer != null
1035: && currentCellRenderer instanceof DefaultTreeCellRenderer)
1036: ed = new DefaultTreeCellEditor(tree,
1037: (DefaultTreeCellRenderer) currentCellRenderer);
1038: else
1039: ed = new DefaultTreeCellEditor(tree, null);
1040: return ed;
1041: }
1042:
1043:
1050: protected TreeCellRenderer createDefaultCellRenderer()
1051: {
1052: return new DefaultTreeCellRenderer();
1053: }
1054:
1055:
1060: protected TreeModelListener createTreeModelListener()
1061: {
1062: return new TreeModelHandler();
1063: }
1064:
1065:
1068: protected void uninstallListeners()
1069: {
1070: tree.removePropertyChangeListener(propertyChangeListener);
1071: tree.removeFocusListener(focusListener);
1072: tree.removeTreeSelectionListener(treeSelectionListener);
1073: tree.removeMouseListener(mouseListener);
1074: tree.removeKeyListener(keyListener);
1075: tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
1076: tree.removeComponentListener(componentListener);
1077: tree.removeTreeExpansionListener(treeExpansionListener);
1078:
1079: TreeCellEditor tce = tree.getCellEditor();
1080: if (tce != null)
1081: tce.removeCellEditorListener(cellEditorListener);
1082: if (treeModel != null)
1083: treeModel.removeTreeModelListener(treeModelListener);
1084: }
1085:
1086:
1089: protected void uninstallKeyboardActions()
1090: {
1091: tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).setParent(
1092: null);
1093: tree.getActionMap().setParent(null);
1094: }
1095:
1096:
1099: protected void uninstallComponents()
1100: {
1101: currentCellRenderer = null;
1102: rendererPane = null;
1103: createdRenderer = false;
1104: setCellRenderer(currentCellRenderer);
1105: }
1106:
1107:
1113: protected int getVerticalLegBuffer()
1114: {
1115: return getRowHeight() / 2;
1116: }
1117:
1118:
1125: protected int getHorizontalLegBuffer()
1126: {
1127: return rightChildIndent / 2;
1128: }
1129:
1130:
1134: protected void updateLayoutCacheExpandedNodes()
1135: {
1136: if (treeModel != null && treeModel.getRoot() != null)
1137: updateExpandedDescendants(new TreePath(treeModel.getRoot()));
1138: }
1139:
1140:
1147: protected void updateExpandedDescendants(TreePath path)
1148: {
1149: completeEditing();
1150: Enumeration expanded = tree.getExpandedDescendants(path);
1151: while (expanded.hasMoreElements())
1152: treeState.setExpandedState((TreePath) expanded.nextElement(), true);
1153: }
1154:
1155:
1161: protected TreePath getLastChildPath(TreePath parent)
1162: {
1163: return (TreePath) parent.getLastPathComponent();
1164: }
1165:
1166:
1169: protected void updateDepthOffset()
1170: {
1171: depthOffset += getVerticalLegBuffer();
1172: }
1173:
1174:
1179: protected void updateCellEditor()
1180: {
1181: completeEditing();
1182: TreeCellEditor newEd = null;
1183: if (tree != null && tree.isEditable())
1184: {
1185: newEd = tree.getCellEditor();
1186: if (newEd == null)
1187: {
1188: newEd = createDefaultCellEditor();
1189: if (newEd != null)
1190: {
1191: tree.setCellEditor(newEd);
1192: createdCellEditor = true;
1193: }
1194: }
1195: }
1196:
1197: if (newEd != cellEditor)
1198: {
1199: if (cellEditor != null && cellEditorListener != null)
1200: cellEditor.removeCellEditorListener(cellEditorListener);
1201: cellEditor = newEd;
1202: if (cellEditorListener == null)
1203: cellEditorListener = createCellEditorListener();
1204: if (cellEditor != null && cellEditorListener != null)
1205: cellEditor.addCellEditorListener(cellEditorListener);
1206: createdCellEditor = false;
1207: }
1208: }
1209:
1210:
1213: protected void updateRenderer()
1214: {
1215: if (tree != null)
1216: {
1217: TreeCellRenderer rend = tree.getCellRenderer();
1218: if (rend != null)
1219: {
1220: createdRenderer = false;
1221: currentCellRenderer = rend;
1222: if (createdCellEditor)
1223: tree.setCellEditor(null);
1224: }
1225: else
1226: {
1227: tree.setCellRenderer(createDefaultCellRenderer());
1228: createdRenderer = true;
1229: }
1230: }
1231: else
1232: {
1233: currentCellRenderer = null;
1234: createdRenderer = false;
1235: }
1236:
1237: updateCellEditor();
1238: }
1239:
1240:
1245: protected void configureLayoutCache()
1246: {
1247: treeState = createLayoutCache();
1248: treeState.setNodeDimensions(nodeDimensions);
1249: }
1250:
1251:
1255: protected void updateSize()
1256: {
1257: preferredSize = null;
1258: updateCachedPreferredSize();
1259: tree.treeDidChange();
1260: }
1261:
1262:
1266: protected void updateCachedPreferredSize()
1267: {
1268: validCachedPreferredSize = false;
1269: }
1270:
1271:
1276: protected void pathWasExpanded(TreePath path)
1277: {
1278: validCachedPreferredSize = false;
1279: treeState.setExpandedState(path, true);
1280: tree.repaint();
1281: }
1282:
1283:
1286: protected void pathWasCollapsed(TreePath path)
1287: {
1288: validCachedPreferredSize = false;
1289: treeState.setExpandedState(path, false);
1290: tree.repaint();
1291: }
1292:
1293:
1296: protected void installDefaults()
1297: {
1298: LookAndFeel.installColorsAndFont(tree, "Tree.background",
1299: "Tree.foreground", "Tree.font");
1300:
1301: hashColor = UIManager.getColor("Tree.hash");
1302: if (hashColor == null)
1303: hashColor = Color.black;
1304:
1305: tree.setOpaque(true);
1306:
1307: rightChildIndent = UIManager.getInt("Tree.rightChildIndent");
1308: leftChildIndent = UIManager.getInt("Tree.leftChildIndent");
1309: totalChildIndent = rightChildIndent + leftChildIndent;
1310: setRowHeight(UIManager.getInt("Tree.rowHeight"));
1311: tree.setRowHeight(getRowHeight());
1312: tree.setScrollsOnExpand(UIManager.getBoolean("Tree.scrollsOnExpand"));
1313: setExpandedIcon(UIManager.getIcon("Tree.expandedIcon"));
1314: setCollapsedIcon(UIManager.getIcon("Tree.collapsedIcon"));
1315: }
1316:
1317:
1320: protected void installKeyboardActions()
1321: {
1322: InputMap focusInputMap =
1323: (InputMap) SharedUIDefaults.get("Tree.focusInputMap");
1324: SwingUtilities.replaceUIInputMap(tree, JComponent.WHEN_FOCUSED,
1325: focusInputMap);
1326: InputMap ancestorInputMap =
1327: (InputMap) SharedUIDefaults.get("Tree.ancestorInputMap");
1328: SwingUtilities.replaceUIInputMap(tree,
1329: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
1330: ancestorInputMap);
1331:
1332: SwingUtilities.replaceUIActionMap(tree, getActionMap());
1333: }
1334:
1335:
1340: private ActionMap getActionMap()
1341: {
1342: ActionMap am = (ActionMap) UIManager.get("Tree.actionMap");
1343: if (am == null)
1344: {
1345: am = createDefaultActions();
1346: UIManager.getLookAndFeelDefaults().put("Tree.actionMap", am);
1347: }
1348: return am;
1349: }
1350:
1351:
1356: private ActionMap createDefaultActions()
1357: {
1358: ActionMapUIResource am = new ActionMapUIResource();
1359: Action action;
1360:
1361:
1362: action = new TreeHomeAction(-1, "selectFirst");
1363: am.put(action.getValue(Action.NAME), action);
1364: action = new TreeHomeAction(-1, "selectFirstChangeLead");
1365: am.put(action.getValue(Action.NAME), action);
1366: action = new TreeHomeAction(-1, "selectFirstExtendSelection");
1367: am.put(action.getValue(Action.NAME), action);
1368: action = new TreeHomeAction(1, "selectLast");
1369: am.put(action.getValue(Action.NAME), action);
1370: action = new TreeHomeAction(1, "selectLastChangeLead");
1371: am.put(action.getValue(Action.NAME), action);
1372: action = new TreeHomeAction(1, "selectLastExtendSelection");
1373: am.put(action.getValue(Action.NAME), action);
1374:
1375:
1376: action = new TreeIncrementAction(-1, "selectPrevious");
1377: am.put(action.getValue(Action.NAME), action);
1378: action = new TreeIncrementAction(-1, "selectPreviousExtendSelection");
1379: am.put(action.getValue(Action.NAME), action);
1380: action = new TreeIncrementAction(-1, "selectPreviousChangeLead");
1381: am.put(action.getValue(Action.NAME), action);
1382: action = new TreeIncrementAction(1, "selectNext");
1383: am.put(action.getValue(Action.NAME), action);
1384: action = new TreeIncrementAction(1, "selectNextExtendSelection");
1385: am.put(action.getValue(Action.NAME), action);
1386: action = new TreeIncrementAction(1, "selectNextChangeLead");
1387: am.put(action.getValue(Action.NAME), action);
1388:
1389:
1390: action = new TreeTraverseAction(-1, "selectParent");
1391: am.put(action.getValue(Action.NAME), action);
1392: action = new TreeTraverseAction(1, "selectChild");
1393: am.put(action.getValue(Action.NAME), action);
1394:
1395:
1396: action = new TreeToggleAction("toggleAndAnchor");
1397: am.put(action.getValue(Action.NAME), action);
1398:
1399:
1400: action = new TreePageAction(-1, "scrollUpChangeSelection");
1401: am.put(action.getValue(Action.NAME), action);
1402: action = new TreePageAction(-1, "scrollUpExtendSelection");
1403: am.put(action.getValue(Action.NAME), action);
1404: action = new TreePageAction(-1, "scrollUpChangeLead");
1405: am.put(action.getValue(Action.NAME), action);
1406: action = new TreePageAction(1, "scrollDownChangeSelection");
1407: am.put(action.getValue(Action.NAME), action);
1408: action = new TreePageAction(1, "scrollDownExtendSelection");
1409: am.put(action.getValue(Action.NAME), action);
1410: action = new TreePageAction(1, "scrollDownChangeLead");
1411: am.put(action.getValue(Action.NAME), action);
1412:
1413:
1414: action = new TreeStartEditingAction("startEditing");
1415: am.put(action.getValue(Action.NAME), action);
1416: action = new TreeCancelEditingAction("cancel");
1417: am.put(action.getValue(Action.NAME), action);
1418:
1419:
1420: return am;
1421: }
1422:
1423:
1429: private int convertModifiers(int mod)
1430: {
1431: if ((mod & KeyEvent.SHIFT_DOWN_MASK) != 0)
1432: {
1433: mod |= KeyEvent.SHIFT_MASK;
1434: mod &= ~ KeyEvent.SHIFT_DOWN_MASK;
1435: }
1436: if ((mod & KeyEvent.CTRL_DOWN_MASK) != 0)
1437: {
1438: mod |= KeyEvent.CTRL_MASK;
1439: mod &= ~ KeyEvent.CTRL_DOWN_MASK;
1440: }
1441: if ((mod & KeyEvent.META_DOWN_MASK) != 0)
1442: {
1443: mod |= KeyEvent.META_MASK;
1444: mod &= ~ KeyEvent.META_DOWN_MASK;
1445: }
1446: if ((mod & KeyEvent.ALT_DOWN_MASK) != 0)
1447: {
1448: mod |= KeyEvent.ALT_MASK;
1449: mod &= ~ KeyEvent.ALT_DOWN_MASK;
1450: }
1451: if ((mod & KeyEvent.ALT_GRAPH_DOWN_MASK) != 0)
1452: {
1453: mod |= KeyEvent.ALT_GRAPH_MASK;
1454: mod &= ~ KeyEvent.ALT_GRAPH_DOWN_MASK;
1455: }
1456: return mod;
1457: }
1458:
1459:
1462: protected void installListeners()
1463: {
1464: propertyChangeListener = createPropertyChangeListener();
1465: tree.addPropertyChangeListener(propertyChangeListener);
1466:
1467: focusListener = createFocusListener();
1468: tree.addFocusListener(focusListener);
1469:
1470: treeSelectionListener = createTreeSelectionListener();
1471: tree.addTreeSelectionListener(treeSelectionListener);
1472:
1473: mouseListener = createMouseListener();
1474: tree.addMouseListener(mouseListener);
1475:
1476: keyListener = createKeyListener();
1477: tree.addKeyListener(keyListener);
1478:
1479: selectionModelPropertyChangeListener =
1480: createSelectionModelPropertyChangeListener();
1481: if (treeSelectionModel != null
1482: && selectionModelPropertyChangeListener != null)
1483: {
1484: treeSelectionModel.addPropertyChangeListener(
1485: selectionModelPropertyChangeListener);
1486: }
1487:
1488: componentListener = createComponentListener();
1489: tree.addComponentListener(componentListener);
1490:
1491: treeExpansionListener = createTreeExpansionListener();
1492: tree.addTreeExpansionListener(treeExpansionListener);
1493:
1494: treeModelListener = createTreeModelListener();
1495: if (treeModel != null)
1496: treeModel.addTreeModelListener(treeModelListener);
1497:
1498: cellEditorListener = createCellEditorListener();
1499: }
1500:
1501:
1506: public void installUI(JComponent c)
1507: {
1508: tree = (JTree) c;
1509:
1510: prepareForUIInstall();
1511: installDefaults();
1512: installComponents();
1513: installKeyboardActions();
1514: installListeners();
1515: completeUIInstall();
1516: }
1517:
1518:
1521: protected void uninstallDefaults()
1522: {
1523: tree.setFont(null);
1524: tree.setForeground(null);
1525: tree.setBackground(null);
1526: }
1527:
1528:
1533: public void uninstallUI(JComponent c)
1534: {
1535: completeEditing();
1536:
1537: prepareForUIUninstall();
1538: uninstallDefaults();
1539: uninstallKeyboardActions();
1540: uninstallListeners();
1541: uninstallComponents();
1542: completeUIUninstall();
1543: }
1544:
1545:
1556: public void paint(Graphics g, JComponent c)
1557: {
1558: JTree tree = (JTree) c;
1559:
1560: int rows = treeState.getRowCount();
1561:
1562: if (rows == 0)
1563:
1564: return;
1565:
1566: Rectangle clip = g.getClipBounds();
1567:
1568: Insets insets = tree.getInsets();
1569:
1570: if (clip != null && treeModel != null)
1571: {
1572: int startIndex = tree.getClosestRowForLocation(clip.x, clip.y);
1573: int endIndex = tree.getClosestRowForLocation(clip.x + clip.width,
1574: clip.y + clip.height);
1575:
1576:
1577:
1578: if (endIndex < rows)
1579: for (int i = endIndex + 1; i < rows; i++)
1580: {
1581: TreePath path = treeState.getPathForRow(i);
1582: if (isLastChild(path))
1583: paintVerticalPartOfLeg(g, clip, insets, path);
1584: }
1585:
1586:
1587:
1588:
1589: int n = endIndex - startIndex + 1;
1590: Rectangle[] bounds = new Rectangle[n];
1591: boolean[] isLeaf = new boolean[n];
1592: boolean[] isExpanded = new boolean[n];
1593: TreePath[] path = new TreePath[n];
1594: int k;
1595:
1596: k = 0;
1597: for (int i = startIndex; i <= endIndex; i++, k++)
1598: {
1599: path[k] = treeState.getPathForRow(i);
1600: if (path[k] != null)
1601: {
1602: isLeaf[k] = treeModel.isLeaf(path[k].getLastPathComponent());
1603: isExpanded[k] = tree.isExpanded(path[k]);
1604: bounds[k] = getPathBounds(tree, path[k]);
1605:
1606: paintHorizontalPartOfLeg(g, clip, insets, bounds[k], path[k],
1607: i, isExpanded[k], false, isLeaf[k]);
1608: }
1609: if (isLastChild(path[k]))
1610: paintVerticalPartOfLeg(g, clip, insets, path[k]);
1611: }
1612:
1613: k = 0;
1614: for (int i = startIndex; i <= endIndex; i++, k++)
1615: {
1616: if (path[k] != null)
1617: paintRow(g, clip, insets, bounds[k], path[k], i, isExpanded[k],
1618: false, isLeaf[k]);
1619: }
1620: }
1621: }
1622:
1623:
1626: private boolean isLastChild(TreePath path)
1627: {
1628: if (path == null)
1629: return false;
1630: else if (path instanceof GnuPath)
1631: {
1632:
1633:
1634: return ((GnuPath) path).isLastChild;
1635: }
1636: else
1637: {
1638:
1639: TreePath parent = path.getParentPath();
1640: if (parent == null)
1641: return false;
1642: int childCount = treeState.getVisibleChildCount(parent);
1643: int p = treeModel.getIndexOfChild(parent, path.getLastPathComponent());
1644: return p == childCount - 1;
1645: }
1646: }
1647:
1648:
1654: protected void ensureRowsAreVisible(int beginRow, int endRow)
1655: {
1656: if (beginRow < endRow)
1657: {
1658: int temp = endRow;
1659: endRow = beginRow;
1660: beginRow = temp;
1661: }
1662:
1663: for (int i = beginRow; i < endRow; i++)
1664: {
1665: TreePath path = getPathForRow(tree, i);
1666: if (! tree.isVisible(path))
1667: tree.makeVisible(path);
1668: }
1669: }
1670:
1671:
1676: public void setPreferredMinSize(Dimension newSize)
1677: {
1678: preferredMinSize = newSize;
1679: }
1680:
1681:
1686: public Dimension getPreferredMinSize()
1687: {
1688: if (preferredMinSize == null)
1689: return getPreferredSize(tree);
1690: else
1691: return preferredMinSize;
1692: }
1693:
1694:
1703: public Dimension getPreferredSize(JComponent c)
1704: {
1705: return getPreferredSize(c, false);
1706: }
1707:
1708:
1716: public Dimension getPreferredSize(JComponent c, boolean checkConsistancy)
1717: {
1718: if (! validCachedPreferredSize)
1719: {
1720: Rectangle size = tree.getBounds();
1721:
1722: preferredSize = new Dimension(treeState.getPreferredWidth(size),
1723: treeState.getPreferredHeight());
1724: validCachedPreferredSize = true;
1725: }
1726: return preferredSize;
1727: }
1728:
1729:
1736: public Dimension getMinimumSize(JComponent c)
1737: {
1738: return preferredMinSize = getPreferredSize(c);
1739: }
1740:
1741:
1748: public Dimension getMaximumSize(JComponent c)
1749: {
1750: return getPreferredSize(c);
1751: }
1752:
1753:
1760: protected void completeEditing()
1761: {
1762: if (tree.getInvokesStopCellEditing() && stopEditingInCompleteEditing
1763: && editingComponent != null)
1764: cellEditor.stopCellEditing();
1765:
1766: completeEditing(false, true, false);
1767: }
1768:
1769:
1779: protected void completeEditing(boolean messageStop, boolean messageCancel,
1780: boolean messageTree)
1781: {
1782:
1783: if (stopEditingInCompleteEditing && editingComponent != null)
1784: {
1785: Component comp = editingComponent;
1786: TreePath p = editingPath;
1787: editingComponent = null;
1788: editingPath = null;
1789: if (messageStop)
1790: cellEditor.stopCellEditing();
1791: else if (messageCancel)
1792: cellEditor.cancelCellEditing();
1793:
1794: tree.remove(comp);
1795:
1796: if (editorHasDifferentSize)
1797: {
1798: treeState.invalidatePathBounds(p);
1799: updateSize();
1800: }
1801: else
1802: {
1803:
1804: Rectangle b = getPathBounds(tree, p);
1805: tree.repaint(0, b.y, tree.getWidth(), b.height);
1806: }
1807:
1808: if (messageTree)
1809: {
1810: Object value = cellEditor.getCellEditorValue();
1811: treeModel.valueForPathChanged(p, value);
1812: }
1813: }
1814: }
1815:
1816:
1824: protected boolean startEditing(TreePath path, MouseEvent event)
1825: {
1826:
1827: if (isEditing(tree) && tree.getInvokesStopCellEditing()
1828: && ! stopEditing(tree))
1829: return false;
1830:
1831: completeEditing();
1832: TreeCellEditor ed = cellEditor;
1833: if (ed != null && tree.isPathEditable(path))
1834: {
1835: if (ed.isCellEditable(event))
1836: {
1837: editingRow = getRowForPath(tree, path);
1838: Object value = path.getLastPathComponent();
1839: boolean isSelected = tree.isPathSelected(path);
1840: boolean isExpanded = tree.isExpanded(editingPath);
1841: boolean isLeaf = treeModel.isLeaf(value);
1842: editingComponent = ed.getTreeCellEditorComponent(tree, value,
1843: isSelected,
1844: isExpanded,
1845: isLeaf,
1846: editingRow);
1847:
1848: Rectangle bounds = getPathBounds(tree, path);
1849:
1850: Dimension size = editingComponent.getPreferredSize();
1851: int rowHeight = getRowHeight();
1852: if (size.height != bounds.height && rowHeight > 0)
1853: size.height = rowHeight;
1854:
1855: if (size.width != bounds.width || size.height != bounds.height)
1856: {
1857: editorHasDifferentSize = true;
1858: treeState.invalidatePathBounds(path);
1859: updateSize();
1860: }
1861: else
1862: editorHasDifferentSize = false;
1863:
1864:
1865:
1866: tree.add(editingComponent);
1867: editingComponent.setBounds(bounds.x, bounds.y, size.width,
1868: size.height);
1869: editingComponent.validate();
1870: editingPath = path;
1871:
1872: if (ed.shouldSelectCell(event))
1873: {
1874: stopEditingInCompleteEditing = false;
1875: tree.setSelectionRow(editingRow);
1876: stopEditingInCompleteEditing = true;
1877: }
1878:
1879: editorRequestFocus(editingComponent);
1880:
1881:
1882: if (event instanceof MouseEvent)
1883: {
1884: Point p = SwingUtilities.convertPoint(tree, event.getX(), event.getY(),
1885: editingComponent);
1886: Component active =
1887: SwingUtilities.getDeepestComponentAt(editingComponent, p.x, p.y);
1888: if (active != null)
1889: {
1890: MouseInputHandler ih = new MouseInputHandler(tree, active, event);
1891:
1892: }
1893: }
1894:
1895: return true;
1896: }
1897: else
1898: editingComponent = null;
1899: }
1900: return false;
1901: }
1902:
1903:
1909: private void editorRequestFocus(Component c)
1910: {
1911: if (c instanceof Container)
1912: {
1913:
1914:
1915: Container cont = (Container) c;
1916: if (cont.getComponentCount() > 0)
1917: cont.getComponent(0).requestFocus();
1918: }
1919: else if (c.isFocusable())
1920: c.requestFocus();
1921:
1922: }
1923:
1924:
1932: protected void checkForClickInExpandControl(TreePath path, int mouseX,
1933: int mouseY)
1934: {
1935: if (isLocationInExpandControl(path, mouseX, mouseY))
1936: handleExpandControlClick(path, mouseX, mouseY);
1937: }
1938:
1939:
1951: protected boolean isLocationInExpandControl(TreePath path, int mouseX,
1952: int mouseY)
1953: {
1954: boolean cntlClick = false;
1955: if (! treeModel.isLeaf(path.getLastPathComponent()))
1956: {
1957: int width;
1958: Icon expandedIcon = getExpandedIcon();
1959: if (expandedIcon != null)
1960: width = expandedIcon.getIconWidth();
1961: else
1962:
1963:
1964: width = 18;
1965:
1966: Insets i = tree.getInsets();
1967:
1968: int depth;
1969: if (isRootVisible())
1970: depth = path.getPathCount()-1;
1971: else
1972: depth = path.getPathCount()-2;
1973:
1974: int left = getRowX(tree.getRowForPath(path), depth)
1975: - width + i.left;
1976: cntlClick = mouseX >= left && mouseX <= left + width;
1977: }
1978: return cntlClick;
1979: }
1980:
1981:
1989: protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY)
1990: {
1991: toggleExpandState(path);
1992: }
1993:
1994:
2002: protected void toggleExpandState(TreePath path)
2003: {
2004:
2005: if (treeState.isExpanded(path))
2006: tree.collapsePath(path);
2007: else
2008: tree.expandPath(path);
2009: }
2010:
2011:
2022: protected boolean isToggleSelectionEvent(MouseEvent event)
2023: {
2024: return
2025: (tree.getSelectionModel().getSelectionMode() !=
2026: TreeSelectionModel.SINGLE_TREE_SELECTION) &&
2027: ((event.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0);
2028: }
2029:
2030:
2041: protected boolean isMultiSelectEvent(MouseEvent event)
2042: {
2043: return
2044: (tree.getSelectionModel().getSelectionMode() !=
2045: TreeSelectionModel.SINGLE_TREE_SELECTION) &&
2046: ((event.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0);
2047: }
2048:
2049:
2058: protected boolean isToggleEvent(MouseEvent event)
2059: {
2060: boolean toggle = false;
2061: if (SwingUtilities.isLeftMouseButton(event))
2062: {
2063: int clickCount = tree.getToggleClickCount();
2064: if (clickCount > 0 && event.getClickCount() == clickCount)
2065: toggle = true;
2066: }
2067: return toggle;
2068: }
2069:
2070:
2083: protected void selectPathForEvent(TreePath path, MouseEvent event)
2084: {
2085: if (isToggleSelectionEvent(event))
2086: {
2087:
2088: if (tree.isPathSelected(path))
2089: tree.removeSelectionPath(path);
2090: else
2091: {
2092: tree.addSelectionPath(path);
2093: tree.setAnchorSelectionPath(path);
2094: }
2095: }
2096: else if (isMultiSelectEvent(event))
2097: {
2098:
2099: TreePath anchor = tree.getAnchorSelectionPath();
2100: if (anchor != null)
2101: {
2102: int aRow = getRowForPath(tree, anchor);
2103: tree.addSelectionInterval(aRow, getRowForPath(tree, path));
2104: }
2105: else
2106: tree.addSelectionPath(path);
2107: }
2108: else
2109: {
2110:
2111: tree.setSelectionPath(path);
2112: if (isToggleEvent(event))
2113: toggleExpandState(path);
2114: }
2115: }
2116:
2117:
2123: protected boolean isLeaf(int row)
2124: {
2125: TreePath pathForRow = getPathForRow(tree, row);
2126: if (pathForRow == null)
2127: return true;
2128:
2129: Object node = pathForRow.getLastPathComponent();
2130: return treeModel.isLeaf(node);
2131: }
2132:
2133:
2136: class TreeStartEditingAction
2137: extends AbstractAction
2138: {
2139:
2144: public TreeStartEditingAction(String name)
2145: {
2146: super(name);
2147: }
2148:
2149:
2154: public void actionPerformed(ActionEvent e)
2155: {
2156: TreePath lead = tree.getLeadSelectionPath();
2157: if (!tree.isEditing())
2158: tree.startEditingAtPath(lead);
2159: }
2160: }
2161:
2162:
2165: public class ComponentHandler
2166: extends ComponentAdapter
2167: implements ActionListener
2168: {
2169:
2172: protected Timer timer;
2173:
2174:
2175: protected JScrollBar scrollBar;
2176:
2177:
2180: public ComponentHandler()
2181: {
2182:
2183: }
2184:
2185:
2190: public void componentMoved(ComponentEvent e)
2191: {
2192: if (timer == null)
2193: {
2194: JScrollPane scrollPane = getScrollPane();
2195: if (scrollPane == null)
2196: updateSize();
2197: else
2198: {
2199:
2200:
2201:
2202: scrollBar = scrollPane.getVerticalScrollBar();
2203: if (scrollBar == null || !scrollBar.getValueIsAdjusting())
2204: {
2205:
2206: scrollBar = scrollPane.getHorizontalScrollBar();
2207: if (scrollBar != null && scrollBar.getValueIsAdjusting())
2208: startTimer();
2209: else
2210: updateSize();
2211: }
2212: else
2213: {
2214: startTimer();
2215: }
2216: }
2217: }
2218: }
2219:
2220:
2224: protected void startTimer()
2225: {
2226: if (timer == null)
2227: {
2228: timer = new Timer(200, this);
2229: timer.setRepeats(true);
2230: }
2231: timer.start();
2232: }
2233:
2234:
2239: protected JScrollPane getScrollPane()
2240: {
2241: JScrollPane found = null;
2242: Component p = tree.getParent();
2243: while (p != null && !(p instanceof JScrollPane))
2244: p = p.getParent();
2245: if (p instanceof JScrollPane)
2246: found = (JScrollPane) p;
2247: return found;
2248: }
2249:
2250:
2256: public void actionPerformed(ActionEvent ae)
2257: {
2258: if (scrollBar == null || !scrollBar.getValueIsAdjusting())
2259: {
2260: if (timer != null)
2261: timer.stop();
2262: updateSize();
2263: timer = null;
2264: scrollBar = null;
2265: }
2266: }
2267: }
2268:
2269:
2273: public class CellEditorHandler
2274: implements CellEditorListener
2275: {
2276:
2279: public CellEditorHandler()
2280: {
2281:
2282: }
2283:
2284:
2290: public void editingStopped(ChangeEvent e)
2291: {
2292: completeEditing(false, false, true);
2293: }
2294:
2295:
2301: public void editingCanceled(ChangeEvent e)
2302: {
2303: completeEditing(false, false, false);
2304: }
2305: }
2306:
2307:
2310: public class FocusHandler
2311: implements FocusListener
2312: {
2313:
2316: public FocusHandler()
2317: {
2318:
2319: }
2320:
2321:
2329: public void focusGained(FocusEvent e)
2330: {
2331: repaintLeadRow();
2332: }
2333:
2334:
2342: public void focusLost(FocusEvent e)
2343: {
2344: repaintLeadRow();
2345: }
2346:
2347:
2350: void repaintLeadRow()
2351: {
2352: TreePath lead = tree.getLeadSelectionPath();
2353: if (lead != null)
2354: tree.repaint(tree.getPathBounds(lead));
2355: }
2356: }
2357:
2358:
2362: public class KeyHandler
2363: extends KeyAdapter
2364: {
2365:
2366: protected Action repeatKeyAction;
2367:
2368:
2369: protected boolean isKeyDown;
2370:
2371:
2374: public KeyHandler()
2375: {
2376:
2377: }
2378:
2379:
2387: public void keyTyped(KeyEvent e)
2388: {
2389: char typed = Character.toLowerCase(e.getKeyChar());
2390: for (int row = tree.getLeadSelectionRow() + 1;
2391: row < tree.getRowCount(); row++)
2392: {
2393: if (checkMatch(row, typed))
2394: {
2395: tree.setSelectionRow(row);
2396: tree.scrollRowToVisible(row);
2397: return;
2398: }
2399: }
2400:
2401:
2402: for (int row = 0; row < tree.getLeadSelectionRow(); row++)
2403: {
2404: if (checkMatch(row, typed))
2405: {
2406: tree.setSelectionRow(row);
2407: tree.scrollRowToVisible(row);
2408: return;
2409: }
2410: }
2411: }
2412:
2413:
2420: boolean checkMatch(int row, char typed)
2421: {
2422: TreePath path = treeState.getPathForRow(row);
2423: String node = path.getLastPathComponent().toString();
2424: if (node.length() > 0)
2425: {
2426: char x = node.charAt(0);
2427: if (typed == Character.toLowerCase(x))
2428: return true;
2429: }
2430: return false;
2431: }
2432:
2433:
2438: public void keyPressed(KeyEvent e)
2439: {
2440:
2441: }
2442:
2443:
2448: public void keyReleased(KeyEvent e)
2449: {
2450:
2451: }
2452: }
2453:
2454:
2458: public class MouseHandler
2459: extends MouseAdapter
2460: implements MouseMotionListener
2461: {
2462:
2463:
2466: private boolean selectedOnPress;
2467:
2468:
2471: public MouseHandler()
2472: {
2473:
2474: }
2475:
2476:
2481: public void mousePressed(MouseEvent e)
2482: {
2483: if (! e.isConsumed())
2484: {
2485: handleEvent(e);
2486: selectedOnPress = true;
2487: }
2488: else
2489: {
2490: selectedOnPress = false;
2491: }
2492: }
2493:
2494:
2502: public void mouseDragged(MouseEvent e)
2503: {
2504:
2505: }
2506:
2507:
2513: public void mouseMoved(MouseEvent e)
2514: {
2515:
2516: }
2517:
2518:
2523: public void mouseReleased(MouseEvent e)
2524: {
2525: if (! e.isConsumed() && ! selectedOnPress)
2526: handleEvent(e);
2527: }
2528:
2529:
2534: private void handleEvent(MouseEvent e)
2535: {
2536: if (tree != null && tree.isEnabled())
2537: {
2538:
2539: if (isEditing(tree) && tree.getInvokesStopCellEditing()
2540: && ! stopEditing(tree))
2541: return;
2542:
2543:
2544: tree.requestFocusInWindow();
2545:
2546: int x = e.getX();
2547: int y = e.getY();
2548: TreePath path = getClosestPathForLocation(tree, x, y);
2549: if (path != null)
2550: {
2551: Rectangle b = getPathBounds(tree, path);
2552: if (y <= b.y + b.height)
2553: {
2554: if (SwingUtilities.isLeftMouseButton(e))
2555: checkForClickInExpandControl(path, x, y);
2556: if (x > b.x && x <= b.x + b.width)
2557: {
2558: if (! startEditing(path, e))
2559: selectPathForEvent(path, e);
2560: }
2561: }
2562: }
2563: }
2564: }
2565: }
2566:
2567:
2572: public class MouseInputHandler
2573: implements MouseInputListener
2574: {
2575:
2576: protected Component source;
2577:
2578:
2579: protected Component destination;
2580:
2581:
2588: public MouseInputHandler(Component source, Component destination,
2589: MouseEvent e)
2590: {
2591: this.source = source;
2592: this.destination = destination;
2593: source.addMouseListener(this);
2594: source.addMouseMotionListener(this);
2595: dispatch(e);
2596: }
2597:
2598:
2604: public void mouseClicked(MouseEvent e)
2605: {
2606: dispatch(e);
2607: }
2608:
2609:
2614: public void mousePressed(MouseEvent e)
2615: {
2616:
2617: }
2618:
2619:
2624: public void mouseReleased(MouseEvent e)
2625: {
2626: dispatch(e);
2627: removeFromSource();
2628: }
2629:
2630:
2635: public void mouseEntered(MouseEvent e)
2636: {
2637: if (! SwingUtilities.isLeftMouseButton(e))
2638: removeFromSource();
2639: }
2640:
2641:
2646: public void mouseExited(MouseEvent e)
2647: {
2648: if (! SwingUtilities.isLeftMouseButton(e))
2649: removeFromSource();
2650: }
2651:
2652:
2660: public void mouseDragged(MouseEvent e)
2661: {
2662: dispatch(e);
2663: }
2664:
2665:
2671: public void mouseMoved(MouseEvent e)
2672: {
2673: removeFromSource();
2674: }
2675:
2676:
2679: protected void removeFromSource()
2680: {
2681: if (source != null)
2682: {
2683: source.removeMouseListener(this);
2684: source.removeMouseMotionListener(this);
2685: }
2686: source = null;
2687: destination = null;
2688: }
2689:
2690:
2695: private void dispatch(MouseEvent e)
2696: {
2697: if (destination != null)
2698: {
2699: MouseEvent e2 = SwingUtilities.convertMouseEvent(source, e,
2700: destination);
2701: destination.dispatchEvent(e2);
2702: }
2703: }
2704: }
2705:
2706:
2711: public class NodeDimensionsHandler
2712: extends AbstractLayoutCache.NodeDimensions
2713: {
2714:
2717: public NodeDimensionsHandler()
2718: {
2719:
2720: }
2721:
2722:
2735: public Rectangle getNodeDimensions(Object cell, int row, int depth,
2736: boolean expanded, Rectangle size)
2737: {
2738: Dimension prefSize;
2739: if (editingComponent != null && editingRow == row)
2740: {
2741:
2742: prefSize = editingComponent.getPreferredSize();
2743: int rowHeight = getRowHeight();
2744: if (rowHeight > 0 && rowHeight != prefSize.height)
2745: prefSize.height = rowHeight;
2746: }
2747: else
2748: {
2749:
2750: Component rend =
2751: currentCellRenderer.getTreeCellRendererComponent(tree, cell,
2752: tree.isRowSelected(row),
2753: expanded,
2754: treeModel.isLeaf(cell),
2755: row, false);
2756:
2757: rendererPane.add(rend);
2758: rend.validate();
2759: prefSize = rend.getPreferredSize();
2760: }
2761: if (size != null)
2762: {
2763: size.x = getRowX(row, depth);
2764:
2765: size.y = prefSize.height * row;
2766: size.width = prefSize.width;
2767: size.height = prefSize.height;
2768: }
2769: else
2770:
2771: size = new Rectangle(getRowX(row, depth), prefSize.height * row, prefSize.width,
2772: prefSize.height);
2773:
2774: return size;
2775: }
2776:
2777:
2782: protected int getRowX(int row, int depth)
2783: {
2784: return BasicTreeUI.this.getRowX(row, depth);
2785: }
2786: }
2787:
2788:
2792: public class PropertyChangeHandler
2793: implements PropertyChangeListener
2794: {
2795:
2796:
2799: public PropertyChangeHandler()
2800: {
2801:
2802: }
2803:
2804:
2810: public void propertyChange(PropertyChangeEvent event)
2811: {
2812: String property = event.getPropertyName();
2813: if (property.equals(JTree.ROOT_VISIBLE_PROPERTY))
2814: {
2815: validCachedPreferredSize = false;
2816: treeState.setRootVisible(tree.isRootVisible());
2817: tree.repaint();
2818: }
2819: else if (property.equals(JTree.SELECTION_MODEL_PROPERTY))
2820: {
2821: treeSelectionModel = tree.getSelectionModel();
2822: treeSelectionModel.setRowMapper(treeState);
2823: }
2824: else if (property.equals(JTree.TREE_MODEL_PROPERTY))
2825: {
2826: setModel(tree.getModel());
2827: }
2828: else if (property.equals(JTree.CELL_RENDERER_PROPERTY))
2829: {
2830: setCellRenderer(tree.getCellRenderer());
2831:
2832: if (treeState != null)
2833: treeState.invalidateSizes();
2834: }
2835: else if (property.equals(JTree.EDITABLE_PROPERTY))
2836: setEditable(((Boolean) event.getNewValue()).booleanValue());
2837:
2838: }
2839: }
2840:
2841:
2845: public class SelectionModelPropertyChangeHandler
2846: implements PropertyChangeListener
2847: {
2848:
2849:
2852: public SelectionModelPropertyChangeHandler()
2853: {
2854:
2855: }
2856:
2857:
2863: public void propertyChange(PropertyChangeEvent event)
2864: {
2865: treeSelectionModel.resetRowSelection();
2866: }
2867: }
2868:
2869:
2872: public class TreeCancelEditingAction
2873: extends AbstractAction
2874: {
2875:
2880: public TreeCancelEditingAction(String name)
2881: {
2882: super(name);
2883: }
2884:
2885:
2891: public void actionPerformed(ActionEvent e)
2892: {
2893: if (isEnabled() && tree.isEditing())
2894: tree.cancelEditing();
2895: }
2896: }
2897:
2898:
2901: public class TreeExpansionHandler
2902: implements TreeExpansionListener
2903: {
2904:
2905:
2908: public TreeExpansionHandler()
2909: {
2910:
2911: }
2912:
2913:
2918: public void treeExpanded(TreeExpansionEvent event)
2919: {
2920: validCachedPreferredSize = false;
2921: treeState.setExpandedState(event.getPath(), true);
2922:
2923: maxHeight = 0;
2924: tree.revalidate();
2925: tree.repaint();
2926: }
2927:
2928:
2933: public void treeCollapsed(TreeExpansionEvent event)
2934: {
2935: completeEditing();
2936: validCachedPreferredSize = false;
2937: treeState.setExpandedState(event.getPath(), false);
2938:
2939: maxHeight = 0;
2940: tree.revalidate();
2941: tree.repaint();
2942: }
2943: }
2944:
2945:
2949: public class TreeHomeAction
2950: extends AbstractAction
2951: {
2952:
2953:
2954: protected int direction;
2955:
2956:
2963: public TreeHomeAction(int dir, String name)
2964: {
2965: direction = dir;
2966: putValue(Action.NAME, name);
2967: }
2968:
2969:
2974: public void actionPerformed(ActionEvent e)
2975: {
2976: if (tree != null)
2977: {
2978: String command = (String) getValue(Action.NAME);
2979: if (command.equals("selectFirst"))
2980: {
2981: ensureRowsAreVisible(0, 0);
2982: tree.setSelectionInterval(0, 0);
2983: }
2984: if (command.equals("selectFirstChangeLead"))
2985: {
2986: ensureRowsAreVisible(0, 0);
2987: tree.setLeadSelectionPath(getPathForRow(tree, 0));
2988: }
2989: if (command.equals("selectFirstExtendSelection"))
2990: {
2991: ensureRowsAreVisible(0, 0);
2992: TreePath anchorPath = tree.getAnchorSelectionPath();
2993: if (anchorPath == null)
2994: tree.setSelectionInterval(0, 0);
2995: else
2996: {
2997: int anchorRow = getRowForPath(tree, anchorPath);
2998: tree.setSelectionInterval(0, anchorRow);
2999: tree.setAnchorSelectionPath(anchorPath);
3000: tree.setLeadSelectionPath(getPathForRow(tree, 0));
3001: }
3002: }
3003: else if (command.equals("selectLast"))
3004: {
3005: int end = getRowCount(tree) - 1;
3006: ensureRowsAreVisible(end, end);
3007: tree.setSelectionInterval(end, end);
3008: }
3009: else if (command.equals("selectLastChangeLead"))
3010: {
3011: int end = getRowCount(tree) - 1;
3012: ensureRowsAreVisible(end, end);
3013: tree.setLeadSelectionPath(getPathForRow(tree, end));
3014: }
3015: else if (command.equals("selectLastExtendSelection"))
3016: {
3017: int end = getRowCount(tree) - 1;
3018: ensureRowsAreVisible(end, end);
3019: TreePath anchorPath = tree.getAnchorSelectionPath();
3020: if (anchorPath == null)
3021: tree.setSelectionInterval(end, end);
3022: else
3023: {
3024: int anchorRow = getRowForPath(tree, anchorPath);
3025: tree.setSelectionInterval(end, anchorRow);
3026: tree.setAnchorSelectionPath(anchorPath);
3027: tree.setLeadSelectionPath(getPathForRow(tree, end));
3028: }
3029: }
3030: }
3031:
3032:
3033: tree.scrollPathToVisible(tree.getLeadSelectionPath());
3034: }
3035:
3036:
3041: public boolean isEnabled()
3042: {
3043: return (tree != null) && tree.isEnabled();
3044: }
3045: }
3046:
3047:
3051: public class TreeIncrementAction
3052: extends AbstractAction
3053: {
3054:
3055:
3058: protected int direction;
3059:
3060:
3066: public TreeIncrementAction(int dir, String name)
3067: {
3068: direction = dir;
3069: putValue(Action.NAME, name);
3070: }
3071:
3072:
3077: public void actionPerformed(ActionEvent e)
3078: {
3079: TreePath currentPath = tree.getLeadSelectionPath();
3080: int currentRow;
3081:
3082: if (currentPath != null)
3083: currentRow = treeState.getRowForPath(currentPath);
3084: else
3085: currentRow = 0;
3086:
3087: int rows = treeState.getRowCount();
3088:
3089: int nextRow = currentRow + 1;
3090: int prevRow = currentRow - 1;
3091: boolean hasNext = nextRow < rows;
3092: boolean hasPrev = prevRow >= 0 && rows > 0;
3093: TreePath newPath;
3094: String command = (String) getValue(Action.NAME);
3095:
3096: if (command.equals("selectPreviousChangeLead") && hasPrev)
3097: {
3098: newPath = treeState.getPathForRow(prevRow);
3099: tree.setSelectionPath(newPath);
3100: tree.setAnchorSelectionPath(newPath);
3101: tree.setLeadSelectionPath(newPath);
3102: }
3103: else if (command.equals("selectPreviousExtendSelection") && hasPrev)
3104: {
3105: newPath = treeState.getPathForRow(prevRow);
3106:
3107:
3108:
3109: if (tree.isPathSelected(newPath))
3110: tree.getSelectionModel().removeSelectionPath(currentPath);
3111:
3112:
3113:
3114: tree.addSelectionPath(newPath);
3115: tree.setLeadSelectionPath(newPath);
3116: }
3117: else if (command.equals("selectPrevious") && hasPrev)
3118: {
3119: newPath = treeState.getPathForRow(prevRow);
3120: tree.setSelectionPath(newPath);
3121: }
3122: else if (command.equals("selectNext") && hasNext)
3123: {
3124: newPath = treeState.getPathForRow(nextRow);
3125: tree.setSelectionPath(newPath);
3126: }
3127: else if (command.equals("selectNextExtendSelection") && hasNext)
3128: {
3129: newPath = treeState.getPathForRow(nextRow);
3130:
3131:
3132:
3133: if (tree.isPathSelected(newPath))
3134: tree.getSelectionModel().removeSelectionPath(currentPath);
3135:
3136:
3137:
3138: tree.addSelectionPath(newPath);
3139:
3140: tree.setLeadSelectionPath(newPath);
3141: }
3142: else if (command.equals("selectNextChangeLead") && hasNext)
3143: {
3144: newPath = treeState.getPathForRow(nextRow);
3145: tree.setSelectionPath(newPath);
3146: tree.setAnchorSelectionPath(newPath);
3147: tree.setLeadSelectionPath(newPath);
3148: }
3149:
3150:
3151: tree.scrollPathToVisible(tree.getLeadSelectionPath());
3152: }
3153:
3154:
3159: public boolean isEnabled()
3160: {
3161: return (tree != null) && tree.isEnabled();
3162: }
3163: }
3164:
3165:
3168: public class TreeModelHandler
3169: implements TreeModelListener
3170: {
3171:
3174: public TreeModelHandler()
3175: {
3176:
3177: }
3178:
3179:
3191: public void treeNodesChanged(TreeModelEvent e)
3192: {
3193: validCachedPreferredSize = false;
3194: treeState.treeNodesChanged(e);
3195: tree.repaint();
3196: }
3197:
3198:
3205: public void treeNodesInserted(TreeModelEvent e)
3206: {
3207: validCachedPreferredSize = false;
3208: treeState.treeNodesInserted(e);
3209: tree.repaint();
3210: }
3211:
3212:
3222: public void treeNodesRemoved(TreeModelEvent e)
3223: {
3224: validCachedPreferredSize = false;
3225: treeState.treeNodesRemoved(e);
3226: tree.repaint();
3227: }
3228:
3229:
3238: public void treeStructureChanged(TreeModelEvent e)
3239: {
3240: if (e.getPath().length == 1
3241: && ! e.getPath()[0].equals(treeModel.getRoot()))
3242: tree.expandPath(new TreePath(treeModel.getRoot()));
3243: validCachedPreferredSize = false;
3244: treeState.treeStructureChanged(e);
3245: tree.repaint();
3246: }
3247: }
3248:
3249:
3252: public class TreePageAction
3253: extends AbstractAction
3254: {
3255:
3256: protected int direction;
3257:
3258:
3264: public TreePageAction(int direction, String name)
3265: {
3266: this.direction = direction;
3267: putValue(Action.NAME, name);
3268: }
3269:
3270:
3275: public void actionPerformed(ActionEvent e)
3276: {
3277: String command = (String) getValue(Action.NAME);
3278: boolean extendSelection = command.equals("scrollUpExtendSelection")
3279: || command.equals("scrollDownExtendSelection");
3280: boolean changeSelection = command.equals("scrollUpChangeSelection")
3281: || command.equals("scrollDownChangeSelection");
3282:
3283:
3284: if (!extendSelection && !changeSelection
3285: && tree.getSelectionModel().getSelectionMode() !=
3286: TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION)
3287: {
3288: changeSelection = true;
3289: }
3290:
3291: int rowCount = getRowCount(tree);
3292: if (rowCount > 0 && treeSelectionModel != null)
3293: {
3294: Dimension maxSize = tree.getSize();
3295: TreePath lead = tree.getLeadSelectionPath();
3296: TreePath newPath = null;
3297: Rectangle visible = tree.getVisibleRect();
3298: if (direction == -1)
3299: {
3300: newPath = getClosestPathForLocation(tree, visible.x, visible.y);
3301: if (newPath.equals(lead))
3302: {
3303: visible.y = Math.max(0, visible.y - visible.height);
3304: newPath = getClosestPathForLocation(tree, visible.x,
3305: visible.y);
3306: }
3307: }
3308: else
3309: {
3310: visible.y = Math.min(maxSize.height,
3311: visible.y + visible.height - 1);
3312: newPath = getClosestPathForLocation(tree, visible.x, visible.y);
3313: if (newPath.equals(lead))
3314: {
3315: visible.y = Math.min(maxSize.height,
3316: visible.y + visible.height - 1);
3317: newPath = getClosestPathForLocation(tree, visible.x,
3318: visible.y);
3319: }
3320: }
3321:
3322:
3323: Rectangle newVisible = getPathBounds(tree, newPath);
3324: newVisible.x = visible.x;
3325: newVisible.width = visible.width;
3326: if (direction == -1)
3327: {
3328: newVisible.height = visible.height;
3329: }
3330: else
3331: {
3332: newVisible.y -= visible.height - newVisible.height;
3333: newVisible.height = visible.height;
3334: }
3335:
3336: if (extendSelection)
3337: {
3338:
3339: TreePath anchorPath = tree.getAnchorSelectionPath();
3340: if (anchorPath == null)
3341: {
3342: tree.setSelectionPath(newPath);
3343: }
3344: else
3345: {
3346: int newIndex = getRowForPath(tree, newPath);
3347: int anchorIndex = getRowForPath(tree, anchorPath);
3348: tree.setSelectionInterval(Math.min(anchorIndex, newIndex),
3349: Math.max(anchorIndex, newIndex));
3350: tree.setAnchorSelectionPath(anchorPath);
3351: tree.setLeadSelectionPath(newPath);
3352: }
3353: }
3354: else if (changeSelection)
3355: {
3356: tree.setSelectionPath(newPath);
3357: }
3358: else
3359: {
3360: tree.setLeadSelectionPath(newPath);
3361: }
3362:
3363: tree.scrollRectToVisible(newVisible);
3364: }
3365: }
3366:
3367:
3372: public boolean isEnabled()
3373: {
3374: return (tree != null) && tree.isEnabled();
3375: }
3376: }
3377:
3378:
3382: public class TreeSelectionHandler
3383: implements TreeSelectionListener
3384: {
3385:
3388: public TreeSelectionHandler()
3389: {
3390:
3391: }
3392:
3393:
3399: public void valueChanged(TreeSelectionEvent event)
3400: {
3401: completeEditing();
3402:
3403: TreePath op = event.getOldLeadSelectionPath();
3404: TreePath np = event.getNewLeadSelectionPath();
3405:
3406:
3407: if (op != np)
3408: {
3409: Rectangle o = treeState.getBounds(event.getOldLeadSelectionPath(),
3410: new Rectangle());
3411: Rectangle n = treeState.getBounds(event.getNewLeadSelectionPath(),
3412: new Rectangle());
3413:
3414: if (o != null)
3415: tree.repaint(o);
3416: if (n != null)
3417: tree.repaint(n);
3418: }
3419: }
3420: }
3421:
3422:
3425: public class TreeToggleAction
3426: extends AbstractAction
3427: {
3428:
3433: public TreeToggleAction(String name)
3434: {
3435: putValue(Action.NAME, name);
3436: }
3437:
3438:
3443: public void actionPerformed(ActionEvent e)
3444: {
3445: int selected = tree.getLeadSelectionRow();
3446: if (selected != -1 && isLeaf(selected))
3447: {
3448: TreePath anchorPath = tree.getAnchorSelectionPath();
3449: TreePath leadPath = tree.getLeadSelectionPath();
3450: toggleExpandState(getPathForRow(tree, selected));
3451:
3452:
3453: tree.setLeadSelectionPath(leadPath);
3454: tree.setAnchorSelectionPath(anchorPath);
3455:
3456:
3457: tree.scrollPathToVisible(tree.getLeadSelectionPath());
3458: }
3459: }
3460:
3461:
3466: public boolean isEnabled()
3467: {
3468: return (tree != null) && tree.isEnabled();
3469: }
3470: }
3471:
3472:
3476: public class TreeTraverseAction
3477: extends AbstractAction
3478: {
3479:
3482: protected int direction;
3483:
3484:
3490: public TreeTraverseAction(int direction, String name)
3491: {
3492: this.direction = direction;
3493: putValue(Action.NAME, name);
3494: }
3495:
3496:
3501: public void actionPerformed(ActionEvent e)
3502: {
3503: TreePath current = tree.getLeadSelectionPath();
3504: if (current == null)
3505: return;
3506:
3507: String command = (String) getValue(Action.NAME);
3508: if (command.equals("selectParent"))
3509: {
3510: if (current == null)
3511: return;
3512:
3513: if (tree.isExpanded(current))
3514: {
3515: tree.collapsePath(current);
3516: }
3517: else
3518: {
3519:
3520:
3521:
3522: TreePath parent = current.getParentPath();
3523: if (parent != null &&
3524: ! (parent.getPathCount() == 1 && ! tree.isRootVisible()))
3525: tree.setSelectionPath(parent);
3526: }
3527: }
3528: else if (command.equals("selectChild"))
3529: {
3530: Object node = current.getLastPathComponent();
3531: int nc = treeModel.getChildCount(node);
3532: if (nc == 0 || treeState.isExpanded(current))
3533: {
3534:
3535:
3536: int nextRow = tree.getLeadSelectionRow() + 1;
3537: if (nextRow <= tree.getRowCount())
3538: tree.setSelectionRow(nextRow);
3539: }
3540: else
3541: {
3542: tree.expandPath(current);
3543: }
3544: }
3545:
3546:
3547: tree.scrollPathToVisible(tree.getLeadSelectionPath());
3548: }
3549:
3550:
3555: public boolean isEnabled()
3556: {
3557: return (tree != null) && tree.isEnabled();
3558: }
3559: }
3560:
3561:
3567: boolean hasControlIcons()
3568: {
3569: if (expandedIcon != null || collapsedIcon != null)
3570: return true;
3571: return false;
3572: }
3573:
3574:
3580: Icon getCurrentControlIcon(TreePath path)
3581: {
3582: if (hasControlIcons())
3583: {
3584: if (tree.isExpanded(path))
3585: return expandedIcon;
3586: else
3587: return collapsedIcon;
3588: }
3589: else
3590: {
3591: if (nullIcon == null)
3592: nullIcon = new Icon()
3593: {
3594: public int getIconHeight()
3595: {
3596: return 0;
3597: }
3598:
3599: public int getIconWidth()
3600: {
3601: return 0;
3602: }
3603:
3604: public void paintIcon(Component c, Graphics g, int x, int y)
3605: {
3606:
3607: }
3608: };
3609: return nullIcon;
3610: }
3611: }
3612:
3613:
3620: Object getParent(Object root, Object node)
3621: {
3622: if (root == null || node == null || root.equals(node))
3623: return null;
3624:
3625: if (node instanceof TreeNode)
3626: return ((TreeNode) node).getParent();
3627: return findNode(root, node);
3628: }
3629:
3630:
3637: private Object findNode(Object root, Object node)
3638: {
3639: if (! treeModel.isLeaf(root) && ! root.equals(node))
3640: {
3641: int size = treeModel.getChildCount(root);
3642: for (int j = 0; j < size; j++)
3643: {
3644: Object child = treeModel.getChild(root, j);
3645: if (node.equals(child))
3646: return root;
3647:
3648: Object n = findNode(child, node);
3649: if (n != null)
3650: return n;
3651: }
3652: }
3653: return null;
3654: }
3655:
3656:
3663: void selectPath(JTree tree, TreePath path)
3664: {
3665: if (path != null)
3666: {
3667: tree.setSelectionPath(path);
3668: tree.setLeadSelectionPath(path);
3669: tree.makeVisible(path);
3670: tree.scrollPathToVisible(path);
3671: }
3672: }
3673:
3674:
3682: Object[] getPathToRoot(Object node, int depth)
3683: {
3684: if (node == null)
3685: {
3686: if (depth == 0)
3687: return null;
3688:
3689: return new Object[depth];
3690: }
3691:
3692: Object[] path = getPathToRoot(getParent(treeModel.getRoot(), node),
3693: depth + 1);
3694: path[path.length - depth - 1] = node;
3695: return path;
3696: }
3697:
3698:
3707: protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
3708: int bottom)
3709: {
3710:
3711: g.setColor(getHashColor());
3712: g.drawLine(x, top, x, bottom);
3713: }
3714:
3715:
3724: protected void paintHorizontalLine(Graphics g, JComponent c, int y, int left,
3725: int right)
3726: {
3727:
3728: g.setColor(getHashColor());
3729: g.drawLine(left, y, right, y);
3730: }
3731:
3732:
3741: protected void drawCentered(Component c, Graphics g, Icon icon, int x, int y)
3742: {
3743: x -= icon.getIconWidth() / 2;
3744: y -= icon.getIconHeight() / 2;
3745:
3746: if (x < 0)
3747: x = 0;
3748: if (y < 0)
3749: y = 0;
3750:
3751: icon.paintIcon(c, g, x, y);
3752: }
3753:
3754:
3762: protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2)
3763: {
3764: g.setColor(getHashColor());
3765: for (int i = x1; i < x2; i += 2)
3766: g.drawLine(i, y, i + 1, y);
3767: }
3768:
3769:
3777: protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2)
3778: {
3779: g.setColor(getHashColor());
3780: for (int i = y1; i < y2; i += 2)
3781: g.drawLine(x, i, x, i + 1);
3782: }
3783:
3784:
3798: protected void paintExpandControl(Graphics g, Rectangle clipBounds,
3799: Insets insets, Rectangle bounds,
3800: TreePath path, int row, boolean isExpanded,
3801: boolean hasBeenExpanded, boolean isLeaf)
3802: {
3803: if (shouldPaintExpandControl(path, row, isExpanded, hasBeenExpanded, isLeaf))
3804: {
3805: Icon icon = getCurrentControlIcon(path);
3806: int iconW = icon.getIconWidth();
3807: int x = bounds.x - iconW - gap;
3808: icon.paintIcon(tree, g, x, bounds.y + bounds.height / 2
3809: - icon.getIconHeight() / 2);
3810: }
3811: }
3812:
3813:
3828: protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
3829: Insets insets, Rectangle bounds,
3830: TreePath path, int row,
3831: boolean isExpanded,
3832: boolean hasBeenExpanded,
3833: boolean isLeaf)
3834: {
3835: if (row != 0)
3836: {
3837: paintHorizontalLine(g, tree, bounds.y + bounds.height / 2,
3838: bounds.x - leftChildIndent - gap, bounds.x - gap);
3839: }
3840: }
3841:
3842:
3851: protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,
3852: Insets insets, TreePath path)
3853: {
3854: Rectangle bounds = getPathBounds(tree, path);
3855: TreePath parent = path.getParentPath();
3856:
3857: boolean paintLine;
3858: if (isRootVisible())
3859: paintLine = parent != null;
3860: else
3861: paintLine = parent != null && parent.getPathCount() > 1;
3862: if (paintLine)
3863: {
3864: Rectangle parentBounds = getPathBounds(tree, parent);
3865: paintVerticalLine(g, tree, parentBounds.x + 2 * gap,
3866: parentBounds.y + parentBounds.height / 2,
3867: bounds.y + bounds.height / 2);
3868: }
3869: }
3870:
3871:
3885: protected void paintRow(Graphics g, Rectangle clipBounds, Insets insets,
3886: Rectangle bounds, TreePath path, int row,
3887: boolean isExpanded, boolean hasBeenExpanded,
3888: boolean isLeaf)
3889: {
3890: boolean selected = tree.isPathSelected(path);
3891: boolean hasIcons = false;
3892: Object node = path.getLastPathComponent();
3893:
3894: paintExpandControl(g, clipBounds, insets, bounds, path, row, isExpanded,
3895: hasBeenExpanded, isLeaf);
3896:
3897: TreeCellRenderer dtcr = currentCellRenderer;
3898:
3899: boolean focused = false;
3900: if (treeSelectionModel != null)
3901: focused = treeSelectionModel.getLeadSelectionRow() == row
3902: && tree.isFocusOwner();
3903:
3904: Component c = dtcr.getTreeCellRendererComponent(tree, node, selected,
3905: isExpanded, isLeaf, row,
3906: focused);
3907:
3908: rendererPane.paintComponent(g, c, c.getParent(), bounds);
3909: }
3910:
3911:
3914: protected void prepareForUIUninstall()
3915: {
3916:
3917: }
3918:
3919:
3929: protected boolean shouldPaintExpandControl(TreePath path, int row,
3930: boolean isExpanded,
3931: boolean hasBeenExpanded,
3932: boolean isLeaf)
3933: {
3934: Object node = path.getLastPathComponent();
3935: return ! isLeaf && hasControlIcons();
3936: }
3937:
3938:
3943: protected int getRowX(int row, int depth)
3944: {
3945: return depth * totalChildIndent;
3946: }
3947: }