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:
284: public BasicTreeUI()
285: {
286: validCachedPreferredSize = false;
287: drawingCache = new Hashtable();
288: nodeDimensions = createNodeDimensions();
289: configureLayoutCache();
290:
291: editingRow = - 1;
292: lastSelectedRow = - 1;
293: }
294:
295:
301: public static ComponentUI createUI(JComponent c)
302: {
303: return new BasicTreeUI();
304: }
305:
306:
311: protected Color getHashColor()
312: {
313: return hashColor;
314: }
315:
316:
321: protected void setHashColor(Color color)
322: {
323: hashColor = color;
324: }
325:
326:
331: public void setLeftChildIndent(int newAmount)
332: {
333: leftChildIndent = newAmount;
334: }
335:
336:
341: public int getLeftChildIndent()
342: {
343: return leftChildIndent;
344: }
345:
346:
351: public void setRightChildIndent(int newAmount)
352: {
353: rightChildIndent = newAmount;
354: }
355:
356:
361: public int getRightChildIndent()
362: {
363: return rightChildIndent;
364: }
365:
366:
371: public void setExpandedIcon(Icon newG)
372: {
373: expandedIcon = newG;
374: }
375:
376:
381: public Icon getExpandedIcon()
382: {
383: return expandedIcon;
384: }
385:
386:
391: public void setCollapsedIcon(Icon newG)
392: {
393: collapsedIcon = newG;
394: }
395:
396:
401: public Icon getCollapsedIcon()
402: {
403: return collapsedIcon;
404: }
405:
406:
411: protected void setLargeModel(boolean largeModel)
412: {
413: if (largeModel != this.largeModel)
414: {
415: completeEditing();
416: tree.removeComponentListener(componentListener);
417: this.largeModel = largeModel;
418: tree.addComponentListener(componentListener);
419: }
420: }
421:
422:
427: protected boolean isLargeModel()
428: {
429: return largeModel;
430: }
431:
432:
437: protected void setRowHeight(int rowHeight)
438: {
439: completeEditing();
440: if (rowHeight == 0)
441: rowHeight = getMaxHeight(tree);
442: treeState.setRowHeight(rowHeight);
443: }
444:
445:
450: protected int getRowHeight()
451: {
452: return tree.getRowHeight();
453: }
454:
455:
461: protected void setCellRenderer(TreeCellRenderer tcr)
462: {
463:
464: completeEditing();
465:
466:
467: updateRenderer();
468:
469:
470: if (treeState != null)
471: {
472: treeState.invalidateSizes();
473: updateSize();
474: }
475: }
476:
477:
483: protected TreeCellRenderer getCellRenderer()
484: {
485: if (currentCellRenderer != null)
486: return currentCellRenderer;
487:
488: return createDefaultCellRenderer();
489: }
490:
491:
496: protected void setModel(TreeModel model)
497: {
498: completeEditing();
499:
500: if (treeModel != null && treeModelListener != null)
501: treeModel.removeTreeModelListener(treeModelListener);
502:
503: treeModel = tree.getModel();
504:
505: if (treeModel != null && treeModelListener != null)
506: treeModel.addTreeModelListener(treeModelListener);
507:
508: if (treeState != null)
509: {
510: treeState.setModel(treeModel);
511: updateLayoutCacheExpandedNodes();
512: updateSize();
513: }
514: }
515:
516:
521: protected TreeModel getModel()
522: {
523: return treeModel;
524: }
525:
526:
531: protected void setRootVisible(boolean newValue)
532: {
533: completeEditing();
534: tree.setRootVisible(newValue);
535: }
536:
537:
542: protected boolean isRootVisible()
543: {
544: return tree.isRootVisible();
545: }
546:
547:
552: protected void setShowsRootHandles(boolean newValue)
553: {
554: completeEditing();
555: updateDepthOffset();
556: if (treeState != null)
557: {
558: treeState.invalidateSizes();
559: updateSize();
560: }
561: }
562:
563:
568: protected boolean getShowsRootHandles()
569: {
570: return tree.getShowsRootHandles();
571: }
572:
573:
578: protected void setCellEditor(TreeCellEditor editor)
579: {
580: updateCellEditor();
581: }
582:
583:
588: protected TreeCellEditor getCellEditor()
589: {
590: return cellEditor;
591: }
592:
593:
598: protected void setEditable(boolean newValue)
599: {
600: updateCellEditor();
601: }
602:
603:
608: protected boolean isEditable()
609: {
610: return tree.isEditable();
611: }
612:
613:
619: protected void setSelectionModel(TreeSelectionModel newLSM)
620: {
621: completeEditing();
622: if (newLSM != null)
623: {
624: treeSelectionModel = newLSM;
625: tree.setSelectionModel(treeSelectionModel);
626: }
627: }
628:
629:
634: protected TreeSelectionModel getSelectionModel()
635: {
636: return treeSelectionModel;
637: }
638:
639:
649: public Rectangle getPathBounds(JTree tree, TreePath path)
650: {
651: Rectangle bounds = null;
652: if (tree != null && treeState != null)
653: {
654: bounds = treeState.getBounds(path, null);
655: Insets i = tree.getInsets();
656: if (bounds != null && i != null)
657: {
658: bounds.x += i.left;
659: bounds.y += i.top;
660: }
661: }
662: return bounds;
663: }
664:
665:
671: int getMaxHeight(JTree tree)
672: {
673: if (maxHeight != 0)
674: return maxHeight;
675:
676: Icon e = UIManager.getIcon("Tree.openIcon");
677: Icon c = UIManager.getIcon("Tree.closedIcon");
678: Icon l = UIManager.getIcon("Tree.leafIcon");
679: int rc = getRowCount(tree);
680: int iconHeight = 0;
681:
682: for (int row = 0; row < rc; row++)
683: {
684: if (isLeaf(row))
685: iconHeight = l.getIconHeight();
686: else if (tree.isExpanded(row))
687: iconHeight = e.getIconHeight();
688: else
689: iconHeight = c.getIconHeight();
690:
691: maxHeight = Math.max(maxHeight, iconHeight + gap);
692: }
693:
694: treeState.setRowHeight(maxHeight);
695: return maxHeight;
696: }
697:
698:
701: Icon getNodeIcon(TreePath path)
702: {
703: Object node = path.getLastPathComponent();
704: if (treeModel.isLeaf(node))
705: return UIManager.getIcon("Tree.leafIcon");
706: else if (treeState.getExpandedState(path))
707: return UIManager.getIcon("Tree.openIcon");
708: else
709: return UIManager.getIcon("Tree.closedIcon");
710: }
711:
712:
719: public TreePath getPathForRow(JTree tree, int row)
720: {
721: return treeState.getPathForRow(row);
722: }
723:
724:
734: public int getRowForPath(JTree tree, TreePath path)
735: {
736: return treeState.getRowForPath(path);
737: }
738:
739:
745: public int getRowCount(JTree tree)
746: {
747: return treeState.getRowCount();
748: }
749:
750:
761: public TreePath getClosestPathForLocation(JTree tree, int x, int y)
762: {
763: return treeState.getPathClosestTo(x, y);
764: }
765:
766:
773: public boolean isEditing(JTree tree)
774: {
775: return isEditing;
776: }
777:
778:
786: public boolean stopEditing(JTree tree)
787: {
788: boolean ret = false;
789: if (editingComponent != null && cellEditor.stopCellEditing())
790: {
791: completeEditing(false, false, true);
792: ret = true;
793: }
794: return ret;
795: }
796:
797:
802: public void cancelEditing(JTree tree)
803: {
804:
805:
806:
807: if (editingComponent != null)
808: completeEditing(false, true, false);
809: }
810:
811:
818: public void startEditingAtPath(JTree tree, TreePath path)
819: {
820: tree.scrollPathToVisible(path);
821: if (path != null && tree.isVisible(path))
822: startEditing(path, null);
823: }
824:
825:
831: public TreePath getEditingPath(JTree tree)
832: {
833: return editingPath;
834: }
835:
836:
840: protected void prepareForUIInstall()
841: {
842: lastSelectedRow = -1;
843: preferredSize = new Dimension();
844: largeModel = tree.isLargeModel();
845: preferredSize = new Dimension();
846: stopEditingInCompleteEditing = true;
847: setModel(tree.getModel());
848: }
849:
850:
854: protected void completeUIInstall()
855: {
856: setShowsRootHandles(tree.getShowsRootHandles());
857: updateRenderer();
858: updateDepthOffset();
859: setSelectionModel(tree.getSelectionModel());
860: configureLayoutCache();
861: treeState.setRootVisible(tree.isRootVisible());
862: treeSelectionModel.setRowMapper(treeState);
863: updateSize();
864: }
865:
866:
870: protected void completeUIUninstall()
871: {
872: tree = null;
873: }
874:
875:
878: protected void installComponents()
879: {
880: currentCellRenderer = createDefaultCellRenderer();
881: rendererPane = createCellRendererPane();
882: createdRenderer = true;
883: setCellRenderer(currentCellRenderer);
884: }
885:
886:
893: protected AbstractLayoutCache.NodeDimensions createNodeDimensions()
894: {
895: return new NodeDimensionsHandler();
896: }
897:
898:
904: protected PropertyChangeListener createPropertyChangeListener()
905: {
906: return new PropertyChangeHandler();
907: }
908:
909:
915: protected MouseListener createMouseListener()
916: {
917: return new MouseHandler();
918: }
919:
920:
926: protected FocusListener createFocusListener()
927: {
928: return new FocusHandler();
929: }
930:
931:
936: protected KeyListener createKeyListener()
937: {
938: return new KeyHandler();
939: }
940:
941:
948: protected PropertyChangeListener createSelectionModelPropertyChangeListener()
949: {
950: return new SelectionModelPropertyChangeHandler();
951: }
952:
953:
959: protected TreeSelectionListener createTreeSelectionListener()
960: {
961: return new TreeSelectionHandler();
962: }
963:
964:
969: protected CellEditorListener createCellEditorListener()
970: {
971: return new CellEditorHandler();
972: }
973:
974:
981: protected ComponentListener createComponentListener()
982: {
983: return new ComponentHandler();
984: }
985:
986:
992: protected TreeExpansionListener createTreeExpansionListener()
993: {
994: return new TreeExpansionHandler();
995: }
996:
997:
1003: protected AbstractLayoutCache createLayoutCache()
1004: {
1005: return new VariableHeightLayoutCache();
1006: }
1007:
1008:
1013: protected CellRendererPane createCellRendererPane()
1014: {
1015: return new CellRendererPane();
1016: }
1017:
1018:
1023: protected TreeCellEditor createDefaultCellEditor()
1024: {
1025: DefaultTreeCellEditor ed;
1026: if (currentCellRenderer != null
1027: && currentCellRenderer instanceof DefaultTreeCellRenderer)
1028: ed = new DefaultTreeCellEditor(tree,
1029: (DefaultTreeCellRenderer) currentCellRenderer);
1030: else
1031: ed = new DefaultTreeCellEditor(tree, null);
1032: return ed;
1033: }
1034:
1035:
1042: protected TreeCellRenderer createDefaultCellRenderer()
1043: {
1044: return new DefaultTreeCellRenderer();
1045: }
1046:
1047:
1052: protected TreeModelListener createTreeModelListener()
1053: {
1054: return new TreeModelHandler();
1055: }
1056:
1057:
1060: protected void uninstallListeners()
1061: {
1062: tree.removePropertyChangeListener(propertyChangeListener);
1063: tree.removeFocusListener(focusListener);
1064: tree.removeTreeSelectionListener(treeSelectionListener);
1065: tree.removeMouseListener(mouseListener);
1066: tree.removeKeyListener(keyListener);
1067: tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
1068: tree.removeComponentListener(componentListener);
1069: tree.removeTreeExpansionListener(treeExpansionListener);
1070:
1071: TreeCellEditor tce = tree.getCellEditor();
1072: if (tce != null)
1073: tce.removeCellEditorListener(cellEditorListener);
1074: if (treeModel != null)
1075: treeModel.removeTreeModelListener(treeModelListener);
1076: }
1077:
1078:
1081: protected void uninstallKeyboardActions()
1082: {
1083: tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).setParent(
1084: null);
1085: tree.getActionMap().setParent(null);
1086: }
1087:
1088:
1091: protected void uninstallComponents()
1092: {
1093: currentCellRenderer = null;
1094: rendererPane = null;
1095: createdRenderer = false;
1096: setCellRenderer(currentCellRenderer);
1097: }
1098:
1099:
1105: protected int getVerticalLegBuffer()
1106: {
1107: return getRowHeight() / 2;
1108: }
1109:
1110:
1117: protected int getHorizontalLegBuffer()
1118: {
1119: return rightChildIndent / 2;
1120: }
1121:
1122:
1126: protected void updateLayoutCacheExpandedNodes()
1127: {
1128: if (treeModel != null && treeModel.getRoot() != null)
1129: updateExpandedDescendants(new TreePath(treeModel.getRoot()));
1130: }
1131:
1132:
1139: protected void updateExpandedDescendants(TreePath path)
1140: {
1141: completeEditing();
1142: Enumeration expanded = tree.getExpandedDescendants(path);
1143: while (expanded.hasMoreElements())
1144: treeState.setExpandedState((TreePath) expanded.nextElement(), true);
1145: }
1146:
1147:
1153: protected TreePath getLastChildPath(TreePath parent)
1154: {
1155: return (TreePath) parent.getLastPathComponent();
1156: }
1157:
1158:
1161: protected void updateDepthOffset()
1162: {
1163: depthOffset += getVerticalLegBuffer();
1164: }
1165:
1166:
1171: protected void updateCellEditor()
1172: {
1173: completeEditing();
1174: TreeCellEditor newEd = null;
1175: if (tree != null && tree.isEditable())
1176: {
1177: newEd = tree.getCellEditor();
1178: if (newEd == null)
1179: {
1180: newEd = createDefaultCellEditor();
1181: if (newEd != null)
1182: {
1183: tree.setCellEditor(newEd);
1184: createdCellEditor = true;
1185: }
1186: }
1187: }
1188:
1189: if (newEd != cellEditor)
1190: {
1191: if (cellEditor != null && cellEditorListener != null)
1192: cellEditor.removeCellEditorListener(cellEditorListener);
1193: cellEditor = newEd;
1194: if (cellEditorListener == null)
1195: cellEditorListener = createCellEditorListener();
1196: if (cellEditor != null && cellEditorListener != null)
1197: cellEditor.addCellEditorListener(cellEditorListener);
1198: createdCellEditor = false;
1199: }
1200: }
1201:
1202:
1205: protected void updateRenderer()
1206: {
1207: if (tree != null)
1208: {
1209: TreeCellRenderer rend = tree.getCellRenderer();
1210: if (rend != null)
1211: {
1212: createdRenderer = false;
1213: currentCellRenderer = rend;
1214: if (createdCellEditor)
1215: tree.setCellEditor(null);
1216: }
1217: else
1218: {
1219: tree.setCellRenderer(createDefaultCellRenderer());
1220: createdRenderer = true;
1221: }
1222: }
1223: else
1224: {
1225: currentCellRenderer = null;
1226: createdRenderer = false;
1227: }
1228:
1229: updateCellEditor();
1230: }
1231:
1232:
1237: protected void configureLayoutCache()
1238: {
1239: treeState = createLayoutCache();
1240: treeState.setNodeDimensions(nodeDimensions);
1241: }
1242:
1243:
1247: protected void updateSize()
1248: {
1249: preferredSize = null;
1250: updateCachedPreferredSize();
1251: tree.treeDidChange();
1252: }
1253:
1254:
1258: protected void updateCachedPreferredSize()
1259: {
1260: validCachedPreferredSize = false;
1261: }
1262:
1263:
1268: protected void pathWasExpanded(TreePath path)
1269: {
1270: validCachedPreferredSize = false;
1271: treeState.setExpandedState(path, true);
1272: tree.repaint();
1273: }
1274:
1275:
1278: protected void pathWasCollapsed(TreePath path)
1279: {
1280: validCachedPreferredSize = false;
1281: treeState.setExpandedState(path, false);
1282: tree.repaint();
1283: }
1284:
1285:
1288: protected void installDefaults()
1289: {
1290: LookAndFeel.installColorsAndFont(tree, "Tree.background",
1291: "Tree.foreground", "Tree.font");
1292:
1293: hashColor = UIManager.getColor("Tree.hash");
1294: if (hashColor == null)
1295: hashColor = Color.black;
1296:
1297: tree.setOpaque(true);
1298:
1299: rightChildIndent = UIManager.getInt("Tree.rightChildIndent");
1300: leftChildIndent = UIManager.getInt("Tree.leftChildIndent");
1301: totalChildIndent = rightChildIndent + leftChildIndent;
1302: setRowHeight(UIManager.getInt("Tree.rowHeight"));
1303: tree.setRowHeight(getRowHeight());
1304: tree.setScrollsOnExpand(UIManager.getBoolean("Tree.scrollsOnExpand"));
1305: setExpandedIcon(UIManager.getIcon("Tree.expandedIcon"));
1306: setCollapsedIcon(UIManager.getIcon("Tree.collapsedIcon"));
1307: }
1308:
1309:
1312: protected void installKeyboardActions()
1313: {
1314: InputMap focusInputMap =
1315: (InputMap) SharedUIDefaults.get("Tree.focusInputMap");
1316: SwingUtilities.replaceUIInputMap(tree, JComponent.WHEN_FOCUSED,
1317: focusInputMap);
1318: InputMap ancestorInputMap =
1319: (InputMap) SharedUIDefaults.get("Tree.ancestorInputMap");
1320: SwingUtilities.replaceUIInputMap(tree,
1321: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
1322: ancestorInputMap);
1323:
1324: SwingUtilities.replaceUIActionMap(tree, getActionMap());
1325: }
1326:
1327:
1332: private ActionMap getActionMap()
1333: {
1334: ActionMap am = (ActionMap) UIManager.get("Tree.actionMap");
1335: if (am == null)
1336: {
1337: am = createDefaultActions();
1338: UIManager.getLookAndFeelDefaults().put("Tree.actionMap", am);
1339: }
1340: return am;
1341: }
1342:
1343:
1348: private ActionMap createDefaultActions()
1349: {
1350: ActionMapUIResource am = new ActionMapUIResource();
1351: Action action;
1352:
1353:
1354: action = new TreeHomeAction(-1, "selectFirst");
1355: am.put(action.getValue(Action.NAME), action);
1356: action = new TreeHomeAction(-1, "selectFirstChangeLead");
1357: am.put(action.getValue(Action.NAME), action);
1358: action = new TreeHomeAction(-1, "selectFirstExtendSelection");
1359: am.put(action.getValue(Action.NAME), action);
1360: action = new TreeHomeAction(1, "selectLast");
1361: am.put(action.getValue(Action.NAME), action);
1362: action = new TreeHomeAction(1, "selectLastChangeLead");
1363: am.put(action.getValue(Action.NAME), action);
1364: action = new TreeHomeAction(1, "selectLastExtendSelection");
1365: am.put(action.getValue(Action.NAME), action);
1366:
1367:
1368: action = new TreeIncrementAction(-1, "selectPrevious");
1369: am.put(action.getValue(Action.NAME), action);
1370: action = new TreeIncrementAction(-1, "selectPreviousExtendSelection");
1371: am.put(action.getValue(Action.NAME), action);
1372: action = new TreeIncrementAction(-1, "selectPreviousChangeLead");
1373: am.put(action.getValue(Action.NAME), action);
1374: action = new TreeIncrementAction(1, "selectNext");
1375: am.put(action.getValue(Action.NAME), action);
1376: action = new TreeIncrementAction(1, "selectNextExtendSelection");
1377: am.put(action.getValue(Action.NAME), action);
1378: action = new TreeIncrementAction(1, "selectNextChangeLead");
1379: am.put(action.getValue(Action.NAME), action);
1380:
1381:
1382: action = new TreeTraverseAction(-1, "selectParent");
1383: am.put(action.getValue(Action.NAME), action);
1384: action = new TreeTraverseAction(1, "selectChild");
1385: am.put(action.getValue(Action.NAME), action);
1386:
1387:
1388: action = new TreeToggleAction("toggleAndAnchor");
1389: am.put(action.getValue(Action.NAME), action);
1390:
1391:
1392: action = new TreePageAction(-1, "scrollUpChangeSelection");
1393: am.put(action.getValue(Action.NAME), action);
1394: action = new TreePageAction(-1, "scrollUpExtendSelection");
1395: am.put(action.getValue(Action.NAME), action);
1396: action = new TreePageAction(-1, "scrollUpChangeLead");
1397: am.put(action.getValue(Action.NAME), action);
1398: action = new TreePageAction(1, "scrollDownChangeSelection");
1399: am.put(action.getValue(Action.NAME), action);
1400: action = new TreePageAction(1, "scrollDownExtendSelection");
1401: am.put(action.getValue(Action.NAME), action);
1402: action = new TreePageAction(1, "scrollDownChangeLead");
1403: am.put(action.getValue(Action.NAME), action);
1404:
1405:
1406: action = new TreeStartEditingAction("startEditing");
1407: am.put(action.getValue(Action.NAME), action);
1408: action = new TreeCancelEditingAction("cancel");
1409: am.put(action.getValue(Action.NAME), action);
1410:
1411:
1412: return am;
1413: }
1414:
1415:
1421: private int convertModifiers(int mod)
1422: {
1423: if ((mod & KeyEvent.SHIFT_DOWN_MASK) != 0)
1424: {
1425: mod |= KeyEvent.SHIFT_MASK;
1426: mod &= ~ KeyEvent.SHIFT_DOWN_MASK;
1427: }
1428: if ((mod & KeyEvent.CTRL_DOWN_MASK) != 0)
1429: {
1430: mod |= KeyEvent.CTRL_MASK;
1431: mod &= ~ KeyEvent.CTRL_DOWN_MASK;
1432: }
1433: if ((mod & KeyEvent.META_DOWN_MASK) != 0)
1434: {
1435: mod |= KeyEvent.META_MASK;
1436: mod &= ~ KeyEvent.META_DOWN_MASK;
1437: }
1438: if ((mod & KeyEvent.ALT_DOWN_MASK) != 0)
1439: {
1440: mod |= KeyEvent.ALT_MASK;
1441: mod &= ~ KeyEvent.ALT_DOWN_MASK;
1442: }
1443: if ((mod & KeyEvent.ALT_GRAPH_DOWN_MASK) != 0)
1444: {
1445: mod |= KeyEvent.ALT_GRAPH_MASK;
1446: mod &= ~ KeyEvent.ALT_GRAPH_DOWN_MASK;
1447: }
1448: return mod;
1449: }
1450:
1451:
1454: protected void installListeners()
1455: {
1456: propertyChangeListener = createPropertyChangeListener();
1457: tree.addPropertyChangeListener(propertyChangeListener);
1458:
1459: focusListener = createFocusListener();
1460: tree.addFocusListener(focusListener);
1461:
1462: treeSelectionListener = createTreeSelectionListener();
1463: tree.addTreeSelectionListener(treeSelectionListener);
1464:
1465: mouseListener = createMouseListener();
1466: tree.addMouseListener(mouseListener);
1467:
1468: keyListener = createKeyListener();
1469: tree.addKeyListener(keyListener);
1470:
1471: selectionModelPropertyChangeListener =
1472: createSelectionModelPropertyChangeListener();
1473: if (treeSelectionModel != null
1474: && selectionModelPropertyChangeListener != null)
1475: {
1476: treeSelectionModel.addPropertyChangeListener(
1477: selectionModelPropertyChangeListener);
1478: }
1479:
1480: componentListener = createComponentListener();
1481: tree.addComponentListener(componentListener);
1482:
1483: treeExpansionListener = createTreeExpansionListener();
1484: tree.addTreeExpansionListener(treeExpansionListener);
1485:
1486: treeModelListener = createTreeModelListener();
1487: if (treeModel != null)
1488: treeModel.addTreeModelListener(treeModelListener);
1489:
1490: cellEditorListener = createCellEditorListener();
1491: }
1492:
1493:
1498: public void installUI(JComponent c)
1499: {
1500: tree = (JTree) c;
1501:
1502: prepareForUIInstall();
1503: installDefaults();
1504: installComponents();
1505: installKeyboardActions();
1506: installListeners();
1507: completeUIInstall();
1508: }
1509:
1510:
1513: protected void uninstallDefaults()
1514: {
1515: tree.setFont(null);
1516: tree.setForeground(null);
1517: tree.setBackground(null);
1518: }
1519:
1520:
1525: public void uninstallUI(JComponent c)
1526: {
1527: completeEditing();
1528:
1529: prepareForUIUninstall();
1530: uninstallDefaults();
1531: uninstallKeyboardActions();
1532: uninstallListeners();
1533: uninstallComponents();
1534: completeUIUninstall();
1535: }
1536:
1537:
1548: public void paint(Graphics g, JComponent c)
1549: {
1550: JTree tree = (JTree) c;
1551:
1552: int rows = treeState.getRowCount();
1553:
1554: if (rows == 0)
1555:
1556: return;
1557:
1558: Rectangle clip = g.getClipBounds();
1559:
1560: Insets insets = tree.getInsets();
1561:
1562: if (clip != null && treeModel != null)
1563: {
1564: int startIndex = tree.getClosestRowForLocation(clip.x, clip.y);
1565: int endIndex = tree.getClosestRowForLocation(clip.x + clip.width,
1566: clip.y + clip.height);
1567:
1568:
1569:
1570: if (endIndex < rows)
1571: for (int i = endIndex + 1; i < rows; i++)
1572: {
1573: TreePath path = treeState.getPathForRow(i);
1574: if (isLastChild(path))
1575: paintVerticalPartOfLeg(g, clip, insets, path);
1576: }
1577:
1578:
1579:
1580:
1581: int n = endIndex - startIndex + 1;
1582: Rectangle[] bounds = new Rectangle[n];
1583: boolean[] isLeaf = new boolean[n];
1584: boolean[] isExpanded = new boolean[n];
1585: TreePath[] path = new TreePath[n];
1586: int k;
1587:
1588: k = 0;
1589: for (int i = startIndex; i <= endIndex; i++, k++)
1590: {
1591: path[k] = treeState.getPathForRow(i);
1592: if (path[k] != null)
1593: {
1594: isLeaf[k] = treeModel.isLeaf(path[k].getLastPathComponent());
1595: isExpanded[k] = tree.isExpanded(path[k]);
1596: bounds[k] = getPathBounds(tree, path[k]);
1597:
1598: paintHorizontalPartOfLeg(g, clip, insets, bounds[k], path[k],
1599: i, isExpanded[k], false, isLeaf[k]);
1600: }
1601: if (isLastChild(path[k]))
1602: paintVerticalPartOfLeg(g, clip, insets, path[k]);
1603: }
1604:
1605: k = 0;
1606: for (int i = startIndex; i <= endIndex; i++, k++)
1607: {
1608: if (path[k] != null)
1609: paintRow(g, clip, insets, bounds[k], path[k], i, isExpanded[k],
1610: false, isLeaf[k]);
1611: }
1612: }
1613: }
1614:
1615:
1618: private boolean isLastChild(TreePath path)
1619: {
1620: if (path == null)
1621: return false;
1622: else if (path instanceof GnuPath)
1623: {
1624:
1625:
1626: return ((GnuPath) path).isLastChild;
1627: }
1628: else
1629: {
1630:
1631: TreePath parent = path.getParentPath();
1632: if (parent == null)
1633: return false;
1634: int childCount = treeState.getVisibleChildCount(parent);
1635: int p = treeModel.getIndexOfChild(parent, path.getLastPathComponent());
1636: return p == childCount - 1;
1637: }
1638: }
1639:
1640:
1646: protected void ensureRowsAreVisible(int beginRow, int endRow)
1647: {
1648: if (beginRow < endRow)
1649: {
1650: int temp = endRow;
1651: endRow = beginRow;
1652: beginRow = temp;
1653: }
1654:
1655: for (int i = beginRow; i < endRow; i++)
1656: {
1657: TreePath path = getPathForRow(tree, i);
1658: if (! tree.isVisible(path))
1659: tree.makeVisible(path);
1660: }
1661: }
1662:
1663:
1668: public void setPreferredMinSize(Dimension newSize)
1669: {
1670: preferredMinSize = newSize;
1671: }
1672:
1673:
1678: public Dimension getPreferredMinSize()
1679: {
1680: if (preferredMinSize == null)
1681: return getPreferredSize(tree);
1682: else
1683: return preferredMinSize;
1684: }
1685:
1686:
1695: public Dimension getPreferredSize(JComponent c)
1696: {
1697: return getPreferredSize(c, false);
1698: }
1699:
1700:
1708: public Dimension getPreferredSize(JComponent c, boolean checkConsistancy)
1709: {
1710: if (! validCachedPreferredSize)
1711: {
1712: Rectangle size = tree.getBounds();
1713:
1714: preferredSize = new Dimension(treeState.getPreferredWidth(size),
1715: treeState.getPreferredHeight());
1716: validCachedPreferredSize = true;
1717: }
1718: return preferredSize;
1719: }
1720:
1721:
1728: public Dimension getMinimumSize(JComponent c)
1729: {
1730: return preferredMinSize = getPreferredSize(c);
1731: }
1732:
1733:
1740: public Dimension getMaximumSize(JComponent c)
1741: {
1742: return getPreferredSize(c);
1743: }
1744:
1745:
1752: protected void completeEditing()
1753: {
1754: if (tree.getInvokesStopCellEditing() && stopEditingInCompleteEditing
1755: && editingComponent != null)
1756: cellEditor.stopCellEditing();
1757:
1758: completeEditing(false, true, false);
1759: }
1760:
1761:
1771: protected void completeEditing(boolean messageStop, boolean messageCancel,
1772: boolean messageTree)
1773: {
1774:
1775: if (stopEditingInCompleteEditing && editingComponent != null)
1776: {
1777: Component comp = editingComponent;
1778: TreePath p = editingPath;
1779: editingComponent = null;
1780: editingPath = null;
1781: if (messageStop)
1782: cellEditor.stopCellEditing();
1783: else if (messageCancel)
1784: cellEditor.cancelCellEditing();
1785:
1786: tree.remove(comp);
1787:
1788: if (editorHasDifferentSize)
1789: {
1790: treeState.invalidatePathBounds(p);
1791: updateSize();
1792: }
1793: else
1794: {
1795:
1796: Rectangle b = getPathBounds(tree, p);
1797: tree.repaint(0, b.y, tree.getWidth(), b.height);
1798: }
1799:
1800: if (messageTree)
1801: {
1802: Object value = cellEditor.getCellEditorValue();
1803: treeModel.valueForPathChanged(p, value);
1804: }
1805: }
1806: }
1807:
1808:
1816: protected boolean startEditing(TreePath path, MouseEvent event)
1817: {
1818:
1819: if (isEditing(tree) && tree.getInvokesStopCellEditing()
1820: && ! stopEditing(tree))
1821: return false;
1822:
1823: completeEditing();
1824: TreeCellEditor ed = cellEditor;
1825: if (ed != null && tree.isPathEditable(path))
1826: {
1827: if (ed.isCellEditable(event))
1828: {
1829: editingRow = getRowForPath(tree, path);
1830: Object value = path.getLastPathComponent();
1831: boolean isSelected = tree.isPathSelected(path);
1832: boolean isExpanded = tree.isExpanded(editingPath);
1833: boolean isLeaf = treeModel.isLeaf(value);
1834: editingComponent = ed.getTreeCellEditorComponent(tree, value,
1835: isSelected,
1836: isExpanded,
1837: isLeaf,
1838: editingRow);
1839:
1840: Rectangle bounds = getPathBounds(tree, path);
1841:
1842: Dimension size = editingComponent.getPreferredSize();
1843: int rowHeight = getRowHeight();
1844: if (size.height != bounds.height && rowHeight > 0)
1845: size.height = rowHeight;
1846:
1847: if (size.width != bounds.width || size.height != bounds.height)
1848: {
1849: editorHasDifferentSize = true;
1850: treeState.invalidatePathBounds(path);
1851: updateSize();
1852: }
1853: else
1854: editorHasDifferentSize = false;
1855:
1856:
1857:
1858: tree.add(editingComponent);
1859: editingComponent.setBounds(bounds.x, bounds.y, size.width,
1860: size.height);
1861: editingComponent.validate();
1862: editingPath = path;
1863:
1864: if (ed.shouldSelectCell(event))
1865: {
1866: stopEditingInCompleteEditing = false;
1867: tree.setSelectionRow(editingRow);
1868: stopEditingInCompleteEditing = true;
1869: }
1870:
1871: editorRequestFocus(editingComponent);
1872:
1873:
1874: if (event instanceof MouseEvent)
1875: {
1876: Point p = SwingUtilities.convertPoint(tree, event.getX(), event.getY(),
1877: editingComponent);
1878: Component active =
1879: SwingUtilities.getDeepestComponentAt(editingComponent, p.x, p.y);
1880: if (active != null)
1881: {
1882: MouseInputHandler ih = new MouseInputHandler(tree, active, event);
1883:
1884: }
1885: }
1886:
1887: return true;
1888: }
1889: else
1890: editingComponent = null;
1891: }
1892: return false;
1893: }
1894:
1895:
1901: private void editorRequestFocus(Component c)
1902: {
1903: if (c instanceof Container)
1904: {
1905:
1906:
1907: Container cont = (Container) c;
1908: if (cont.getComponentCount() > 0)
1909: cont.getComponent(0).requestFocus();
1910: }
1911: else if (c.isFocusable())
1912: c.requestFocus();
1913:
1914: }
1915:
1916:
1924: protected void checkForClickInExpandControl(TreePath path, int mouseX,
1925: int mouseY)
1926: {
1927: if (isLocationInExpandControl(path, mouseX, mouseY))
1928: handleExpandControlClick(path, mouseX, mouseY);
1929: }
1930:
1931:
1943: protected boolean isLocationInExpandControl(TreePath path, int mouseX,
1944: int mouseY)
1945: {
1946: boolean cntlClick = false;
1947: if (! treeModel.isLeaf(path.getLastPathComponent()))
1948: {
1949: int width;
1950: Icon expandedIcon = getExpandedIcon();
1951: if (expandedIcon != null)
1952: width = expandedIcon.getIconWidth();
1953: else
1954:
1955:
1956: width = 18;
1957:
1958: Insets i = tree.getInsets();
1959:
1960: int depth;
1961: if (isRootVisible())
1962: depth = path.getPathCount()-1;
1963: else
1964: depth = path.getPathCount()-2;
1965:
1966: int left = getRowX(tree.getRowForPath(path), depth)
1967: - width + i.left;
1968: cntlClick = mouseX >= left && mouseX <= left + width;
1969: }
1970: return cntlClick;
1971: }
1972:
1973:
1981: protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY)
1982: {
1983: toggleExpandState(path);
1984: }
1985:
1986:
1994: protected void toggleExpandState(TreePath path)
1995: {
1996:
1997: if (treeState.isExpanded(path))
1998: tree.collapsePath(path);
1999: else
2000: tree.expandPath(path);
2001: }
2002:
2003:
2014: protected boolean isToggleSelectionEvent(MouseEvent event)
2015: {
2016: return
2017: (tree.getSelectionModel().getSelectionMode() !=
2018: TreeSelectionModel.SINGLE_TREE_SELECTION) &&
2019: ((event.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0);
2020: }
2021:
2022:
2033: protected boolean isMultiSelectEvent(MouseEvent event)
2034: {
2035: return
2036: (tree.getSelectionModel().getSelectionMode() !=
2037: TreeSelectionModel.SINGLE_TREE_SELECTION) &&
2038: ((event.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0);
2039: }
2040:
2041:
2050: protected boolean isToggleEvent(MouseEvent event)
2051: {
2052: boolean toggle = false;
2053: if (SwingUtilities.isLeftMouseButton(event))
2054: {
2055: int clickCount = tree.getToggleClickCount();
2056: if (clickCount > 0 && event.getClickCount() == clickCount)
2057: toggle = true;
2058: }
2059: return toggle;
2060: }
2061:
2062:
2075: protected void selectPathForEvent(TreePath path, MouseEvent event)
2076: {
2077: if (isToggleSelectionEvent(event))
2078: {
2079:
2080: if (tree.isPathSelected(path))
2081: tree.removeSelectionPath(path);
2082: else
2083: {
2084: tree.addSelectionPath(path);
2085: tree.setAnchorSelectionPath(path);
2086: }
2087: }
2088: else if (isMultiSelectEvent(event))
2089: {
2090:
2091: TreePath anchor = tree.getAnchorSelectionPath();
2092: if (anchor != null)
2093: {
2094: int aRow = getRowForPath(tree, anchor);
2095: tree.addSelectionInterval(aRow, getRowForPath(tree, path));
2096: }
2097: else
2098: tree.addSelectionPath(path);
2099: }
2100: else
2101: {
2102:
2103: tree.setSelectionPath(path);
2104: if (isToggleEvent(event))
2105: toggleExpandState(path);
2106: }
2107: }
2108:
2109:
2115: protected boolean isLeaf(int row)
2116: {
2117: TreePath pathForRow = getPathForRow(tree, row);
2118: if (pathForRow == null)
2119: return true;
2120:
2121: Object node = pathForRow.getLastPathComponent();
2122: return treeModel.isLeaf(node);
2123: }
2124:
2125:
2128: class TreeStartEditingAction
2129: extends AbstractAction
2130: {
2131:
2136: public TreeStartEditingAction(String name)
2137: {
2138: super(name);
2139: }
2140:
2141:
2146: public void actionPerformed(ActionEvent e)
2147: {
2148: TreePath lead = tree.getLeadSelectionPath();
2149: if (!tree.isEditing())
2150: tree.startEditingAtPath(lead);
2151: }
2152: }
2153:
2154:
2157: public class ComponentHandler
2158: extends ComponentAdapter
2159: implements ActionListener
2160: {
2161:
2164: protected Timer timer;
2165:
2166:
2167: protected JScrollBar scrollBar;
2168:
2169:
2172: public ComponentHandler()
2173: {
2174:
2175: }
2176:
2177:
2182: public void componentMoved(ComponentEvent e)
2183: {
2184: if (timer == null)
2185: {
2186: JScrollPane scrollPane = getScrollPane();
2187: if (scrollPane == null)
2188: updateSize();
2189: else
2190: {
2191:
2192:
2193:
2194: scrollBar = scrollPane.getVerticalScrollBar();
2195: if (scrollBar == null || !scrollBar.getValueIsAdjusting())
2196: {
2197:
2198: scrollBar = scrollPane.getHorizontalScrollBar();
2199: if (scrollBar != null && scrollBar.getValueIsAdjusting())
2200: startTimer();
2201: else
2202: updateSize();
2203: }
2204: else
2205: {
2206: startTimer();
2207: }
2208: }
2209: }
2210: }
2211:
2212:
2216: protected void startTimer()
2217: {
2218: if (timer == null)
2219: {
2220: timer = new Timer(200, this);
2221: timer.setRepeats(true);
2222: }
2223: timer.start();
2224: }
2225:
2226:
2231: protected JScrollPane getScrollPane()
2232: {
2233: JScrollPane found = null;
2234: Component p = tree.getParent();
2235: while (p != null && !(p instanceof JScrollPane))
2236: p = p.getParent();
2237: if (p instanceof JScrollPane)
2238: found = (JScrollPane) p;
2239: return found;
2240: }
2241:
2242:
2248: public void actionPerformed(ActionEvent ae)
2249: {
2250: if (scrollBar == null || !scrollBar.getValueIsAdjusting())
2251: {
2252: if (timer != null)
2253: timer.stop();
2254: updateSize();
2255: timer = null;
2256: scrollBar = null;
2257: }
2258: }
2259: }
2260:
2261:
2265: public class CellEditorHandler
2266: implements CellEditorListener
2267: {
2268:
2271: public CellEditorHandler()
2272: {
2273:
2274: }
2275:
2276:
2282: public void editingStopped(ChangeEvent e)
2283: {
2284: completeEditing(false, false, true);
2285: }
2286:
2287:
2293: public void editingCanceled(ChangeEvent e)
2294: {
2295: completeEditing(false, false, false);
2296: }
2297: }
2298:
2299:
2302: public class FocusHandler
2303: implements FocusListener
2304: {
2305:
2308: public FocusHandler()
2309: {
2310:
2311: }
2312:
2313:
2321: public void focusGained(FocusEvent e)
2322: {
2323: repaintLeadRow();
2324: }
2325:
2326:
2334: public void focusLost(FocusEvent e)
2335: {
2336: repaintLeadRow();
2337: }
2338:
2339:
2342: void repaintLeadRow()
2343: {
2344: TreePath lead = tree.getLeadSelectionPath();
2345: if (lead != null)
2346: tree.repaint(tree.getPathBounds(lead));
2347: }
2348: }
2349:
2350:
2354: public class KeyHandler
2355: extends KeyAdapter
2356: {
2357:
2358: protected Action repeatKeyAction;
2359:
2360:
2361: protected boolean isKeyDown;
2362:
2363:
2366: public KeyHandler()
2367: {
2368:
2369: }
2370:
2371:
2379: public void keyTyped(KeyEvent e)
2380: {
2381: char typed = Character.toLowerCase(e.getKeyChar());
2382: for (int row = tree.getLeadSelectionRow() + 1;
2383: row < tree.getRowCount(); row++)
2384: {
2385: if (checkMatch(row, typed))
2386: {
2387: tree.setSelectionRow(row);
2388: tree.scrollRowToVisible(row);
2389: return;
2390: }
2391: }
2392:
2393:
2394: for (int row = 0; row < tree.getLeadSelectionRow(); row++)
2395: {
2396: if (checkMatch(row, typed))
2397: {
2398: tree.setSelectionRow(row);
2399: tree.scrollRowToVisible(row);
2400: return;
2401: }
2402: }
2403: }
2404:
2405:
2412: boolean checkMatch(int row, char typed)
2413: {
2414: TreePath path = treeState.getPathForRow(row);
2415: String node = path.getLastPathComponent().toString();
2416: if (node.length() > 0)
2417: {
2418: char x = node.charAt(0);
2419: if (typed == Character.toLowerCase(x))
2420: return true;
2421: }
2422: return false;
2423: }
2424:
2425:
2430: public void keyPressed(KeyEvent e)
2431: {
2432:
2433: }
2434:
2435:
2440: public void keyReleased(KeyEvent e)
2441: {
2442:
2443: }
2444: }
2445:
2446:
2450: public class MouseHandler
2451: extends MouseAdapter
2452: implements MouseMotionListener
2453: {
2454:
2455:
2458: private boolean selectedOnPress;
2459:
2460:
2463: public MouseHandler()
2464: {
2465:
2466: }
2467:
2468:
2473: public void mousePressed(MouseEvent e)
2474: {
2475: if (! e.isConsumed())
2476: {
2477: handleEvent(e);
2478: selectedOnPress = true;
2479: }
2480: else
2481: {
2482: selectedOnPress = false;
2483: }
2484: }
2485:
2486:
2494: public void mouseDragged(MouseEvent e)
2495: {
2496:
2497: }
2498:
2499:
2505: public void mouseMoved(MouseEvent e)
2506: {
2507:
2508: }
2509:
2510:
2515: public void mouseReleased(MouseEvent e)
2516: {
2517: if (! e.isConsumed() && ! selectedOnPress)
2518: handleEvent(e);
2519: }
2520:
2521:
2526: private void handleEvent(MouseEvent e)
2527: {
2528: if (tree != null && tree.isEnabled())
2529: {
2530:
2531: if (isEditing(tree) && tree.getInvokesStopCellEditing()
2532: && ! stopEditing(tree))
2533: return;
2534:
2535:
2536: tree.requestFocusInWindow();
2537:
2538: int x = e.getX();
2539: int y = e.getY();
2540: TreePath path = getClosestPathForLocation(tree, x, y);
2541: if (path != null)
2542: {
2543: Rectangle b = getPathBounds(tree, path);
2544: if (y <= b.y + b.height)
2545: {
2546: if (SwingUtilities.isLeftMouseButton(e))
2547: checkForClickInExpandControl(path, x, y);
2548: if (x > b.x && x <= b.x + b.width)
2549: {
2550: if (! startEditing(path, e))
2551: selectPathForEvent(path, e);
2552: }
2553: }
2554: }
2555: }
2556: }
2557: }
2558:
2559:
2564: public class MouseInputHandler
2565: implements MouseInputListener
2566: {
2567:
2568: protected Component source;
2569:
2570:
2571: protected Component destination;
2572:
2573:
2580: public MouseInputHandler(Component source, Component destination,
2581: MouseEvent e)
2582: {
2583: this.source = source;
2584: this.destination = destination;
2585: source.addMouseListener(this);
2586: source.addMouseMotionListener(this);
2587: dispatch(e);
2588: }
2589:
2590:
2596: public void mouseClicked(MouseEvent e)
2597: {
2598: dispatch(e);
2599: }
2600:
2601:
2606: public void mousePressed(MouseEvent e)
2607: {
2608:
2609: }
2610:
2611:
2616: public void mouseReleased(MouseEvent e)
2617: {
2618: dispatch(e);
2619: removeFromSource();
2620: }
2621:
2622:
2627: public void mouseEntered(MouseEvent e)
2628: {
2629: if (! SwingUtilities.isLeftMouseButton(e))
2630: removeFromSource();
2631: }
2632:
2633:
2638: public void mouseExited(MouseEvent e)
2639: {
2640: if (! SwingUtilities.isLeftMouseButton(e))
2641: removeFromSource();
2642: }
2643:
2644:
2652: public void mouseDragged(MouseEvent e)
2653: {
2654: dispatch(e);
2655: }
2656:
2657:
2663: public void mouseMoved(MouseEvent e)
2664: {
2665: removeFromSource();
2666: }
2667:
2668:
2671: protected void removeFromSource()
2672: {
2673: if (source != null)
2674: {
2675: source.removeMouseListener(this);
2676: source.removeMouseMotionListener(this);
2677: }
2678: source = null;
2679: destination = null;
2680: }
2681:
2682:
2687: private void dispatch(MouseEvent e)
2688: {
2689: if (destination != null)
2690: {
2691: MouseEvent e2 = SwingUtilities.convertMouseEvent(source, e,
2692: destination);
2693: destination.dispatchEvent(e2);
2694: }
2695: }
2696: }
2697:
2698:
2703: public class NodeDimensionsHandler
2704: extends AbstractLayoutCache.NodeDimensions
2705: {
2706:
2709: public NodeDimensionsHandler()
2710: {
2711:
2712: }
2713:
2714:
2727: public Rectangle getNodeDimensions(Object cell, int row, int depth,
2728: boolean expanded, Rectangle size)
2729: {
2730: Dimension prefSize;
2731: if (editingComponent != null && editingRow == row)
2732: {
2733:
2734: prefSize = editingComponent.getPreferredSize();
2735: int rowHeight = getRowHeight();
2736: if (rowHeight > 0 && rowHeight != prefSize.height)
2737: prefSize.height = rowHeight;
2738: }
2739: else
2740: {
2741:
2742: Component rend =
2743: currentCellRenderer.getTreeCellRendererComponent(tree, cell,
2744: tree.isRowSelected(row),
2745: expanded,
2746: treeModel.isLeaf(cell),
2747: row, false);
2748:
2749: rendererPane.add(rend);
2750: rend.validate();
2751: prefSize = rend.getPreferredSize();
2752: }
2753: if (size != null)
2754: {
2755: size.x = getRowX(row, depth);
2756:
2757: size.y = prefSize.height * row;
2758: size.width = prefSize.width;
2759: size.height = prefSize.height;
2760: }
2761: else
2762:
2763: size = new Rectangle(getRowX(row, depth), prefSize.height * row, prefSize.width,
2764: prefSize.height);
2765:
2766: return size;
2767: }
2768:
2769:
2774: protected int getRowX(int row, int depth)
2775: {
2776: return BasicTreeUI.this.getRowX(row, depth);
2777: }
2778: }
2779:
2780:
2784: public class PropertyChangeHandler
2785: implements PropertyChangeListener
2786: {
2787:
2788:
2791: public PropertyChangeHandler()
2792: {
2793:
2794: }
2795:
2796:
2802: public void propertyChange(PropertyChangeEvent event)
2803: {
2804: String property = event.getPropertyName();
2805: if (property.equals(JTree.ROOT_VISIBLE_PROPERTY))
2806: {
2807: validCachedPreferredSize = false;
2808: treeState.setRootVisible(tree.isRootVisible());
2809: tree.repaint();
2810: }
2811: else if (property.equals(JTree.SELECTION_MODEL_PROPERTY))
2812: {
2813: treeSelectionModel = tree.getSelectionModel();
2814: treeSelectionModel.setRowMapper(treeState);
2815: }
2816: else if (property.equals(JTree.TREE_MODEL_PROPERTY))
2817: {
2818: setModel(tree.getModel());
2819: }
2820: else if (property.equals(JTree.CELL_RENDERER_PROPERTY))
2821: {
2822: setCellRenderer(tree.getCellRenderer());
2823:
2824: if (treeState != null)
2825: treeState.invalidateSizes();
2826: }
2827: else if (property.equals(JTree.EDITABLE_PROPERTY))
2828: setEditable(((Boolean) event.getNewValue()).booleanValue());
2829:
2830: }
2831: }
2832:
2833:
2837: public class SelectionModelPropertyChangeHandler
2838: implements PropertyChangeListener
2839: {
2840:
2841:
2844: public SelectionModelPropertyChangeHandler()
2845: {
2846:
2847: }
2848:
2849:
2855: public void propertyChange(PropertyChangeEvent event)
2856: {
2857: treeSelectionModel.resetRowSelection();
2858: }
2859: }
2860:
2861:
2864: public class TreeCancelEditingAction
2865: extends AbstractAction
2866: {
2867:
2872: public TreeCancelEditingAction(String name)
2873: {
2874: super(name);
2875: }
2876:
2877:
2883: public void actionPerformed(ActionEvent e)
2884: {
2885: if (isEnabled() && tree.isEditing())
2886: tree.cancelEditing();
2887: }
2888: }
2889:
2890:
2893: public class TreeExpansionHandler
2894: implements TreeExpansionListener
2895: {
2896:
2897:
2900: public TreeExpansionHandler()
2901: {
2902:
2903: }
2904:
2905:
2910: public void treeExpanded(TreeExpansionEvent event)
2911: {
2912: validCachedPreferredSize = false;
2913: treeState.setExpandedState(event.getPath(), true);
2914:
2915: maxHeight = 0;
2916: tree.revalidate();
2917: tree.repaint();
2918: }
2919:
2920:
2925: public void treeCollapsed(TreeExpansionEvent event)
2926: {
2927: completeEditing();
2928: validCachedPreferredSize = false;
2929: treeState.setExpandedState(event.getPath(), false);
2930:
2931: maxHeight = 0;
2932: tree.revalidate();
2933: tree.repaint();
2934: }
2935: }
2936:
2937:
2941: public class TreeHomeAction
2942: extends AbstractAction
2943: {
2944:
2945:
2946: protected int direction;
2947:
2948:
2955: public TreeHomeAction(int dir, String name)
2956: {
2957: direction = dir;
2958: putValue(Action.NAME, name);
2959: }
2960:
2961:
2966: public void actionPerformed(ActionEvent e)
2967: {
2968: if (tree != null)
2969: {
2970: String command = (String) getValue(Action.NAME);
2971: if (command.equals("selectFirst"))
2972: {
2973: ensureRowsAreVisible(0, 0);
2974: tree.setSelectionInterval(0, 0);
2975: }
2976: if (command.equals("selectFirstChangeLead"))
2977: {
2978: ensureRowsAreVisible(0, 0);
2979: tree.setLeadSelectionPath(getPathForRow(tree, 0));
2980: }
2981: if (command.equals("selectFirstExtendSelection"))
2982: {
2983: ensureRowsAreVisible(0, 0);
2984: TreePath anchorPath = tree.getAnchorSelectionPath();
2985: if (anchorPath == null)
2986: tree.setSelectionInterval(0, 0);
2987: else
2988: {
2989: int anchorRow = getRowForPath(tree, anchorPath);
2990: tree.setSelectionInterval(0, anchorRow);
2991: tree.setAnchorSelectionPath(anchorPath);
2992: tree.setLeadSelectionPath(getPathForRow(tree, 0));
2993: }
2994: }
2995: else if (command.equals("selectLast"))
2996: {
2997: int end = getRowCount(tree) - 1;
2998: ensureRowsAreVisible(end, end);
2999: tree.setSelectionInterval(end, end);
3000: }
3001: else if (command.equals("selectLastChangeLead"))
3002: {
3003: int end = getRowCount(tree) - 1;
3004: ensureRowsAreVisible(end, end);
3005: tree.setLeadSelectionPath(getPathForRow(tree, end));
3006: }
3007: else if (command.equals("selectLastExtendSelection"))
3008: {
3009: int end = getRowCount(tree) - 1;
3010: ensureRowsAreVisible(end, end);
3011: TreePath anchorPath = tree.getAnchorSelectionPath();
3012: if (anchorPath == null)
3013: tree.setSelectionInterval(end, end);
3014: else
3015: {
3016: int anchorRow = getRowForPath(tree, anchorPath);
3017: tree.setSelectionInterval(end, anchorRow);
3018: tree.setAnchorSelectionPath(anchorPath);
3019: tree.setLeadSelectionPath(getPathForRow(tree, end));
3020: }
3021: }
3022: }
3023:
3024:
3025: tree.scrollPathToVisible(tree.getLeadSelectionPath());
3026: }
3027:
3028:
3033: public boolean isEnabled()
3034: {
3035: return (tree != null) && tree.isEnabled();
3036: }
3037: }
3038:
3039:
3043: public class TreeIncrementAction
3044: extends AbstractAction
3045: {
3046:
3047:
3050: protected int direction;
3051:
3052:
3058: public TreeIncrementAction(int dir, String name)
3059: {
3060: direction = dir;
3061: putValue(Action.NAME, name);
3062: }
3063:
3064:
3069: public void actionPerformed(ActionEvent e)
3070: {
3071: TreePath currentPath = tree.getLeadSelectionPath();
3072: int currentRow;
3073:
3074: if (currentPath != null)
3075: currentRow = treeState.getRowForPath(currentPath);
3076: else
3077: currentRow = 0;
3078:
3079: int rows = treeState.getRowCount();
3080:
3081: int nextRow = currentRow + 1;
3082: int prevRow = currentRow - 1;
3083: boolean hasNext = nextRow < rows;
3084: boolean hasPrev = prevRow >= 0 && rows > 0;
3085: TreePath newPath;
3086: String command = (String) getValue(Action.NAME);
3087:
3088: if (command.equals("selectPreviousChangeLead") && hasPrev)
3089: {
3090: newPath = treeState.getPathForRow(prevRow);
3091: tree.setSelectionPath(newPath);
3092: tree.setAnchorSelectionPath(newPath);
3093: tree.setLeadSelectionPath(newPath);
3094: }
3095: else if (command.equals("selectPreviousExtendSelection") && hasPrev)
3096: {
3097: newPath = treeState.getPathForRow(prevRow);
3098:
3099:
3100:
3101: if (tree.isPathSelected(newPath))
3102: tree.getSelectionModel().removeSelectionPath(currentPath);
3103:
3104:
3105:
3106: tree.addSelectionPath(newPath);
3107: tree.setLeadSelectionPath(newPath);
3108: }
3109: else if (command.equals("selectPrevious") && hasPrev)
3110: {
3111: newPath = treeState.getPathForRow(prevRow);
3112: tree.setSelectionPath(newPath);
3113: }
3114: else if (command.equals("selectNext") && hasNext)
3115: {
3116: newPath = treeState.getPathForRow(nextRow);
3117: tree.setSelectionPath(newPath);
3118: }
3119: else if (command.equals("selectNextExtendSelection") && hasNext)
3120: {
3121: newPath = treeState.getPathForRow(nextRow);
3122:
3123:
3124:
3125: if (tree.isPathSelected(newPath))
3126: tree.getSelectionModel().removeSelectionPath(currentPath);
3127:
3128:
3129:
3130: tree.addSelectionPath(newPath);
3131:
3132: tree.setLeadSelectionPath(newPath);
3133: }
3134: else if (command.equals("selectNextChangeLead") && hasNext)
3135: {
3136: newPath = treeState.getPathForRow(nextRow);
3137: tree.setSelectionPath(newPath);
3138: tree.setAnchorSelectionPath(newPath);
3139: tree.setLeadSelectionPath(newPath);
3140: }
3141:
3142:
3143: tree.scrollPathToVisible(tree.getLeadSelectionPath());
3144: }
3145:
3146:
3151: public boolean isEnabled()
3152: {
3153: return (tree != null) && tree.isEnabled();
3154: }
3155: }
3156:
3157:
3160: public class TreeModelHandler
3161: implements TreeModelListener
3162: {
3163:
3166: public TreeModelHandler()
3167: {
3168:
3169: }
3170:
3171:
3183: public void treeNodesChanged(TreeModelEvent e)
3184: {
3185: validCachedPreferredSize = false;
3186: treeState.treeNodesChanged(e);
3187: tree.repaint();
3188: }
3189:
3190:
3197: public void treeNodesInserted(TreeModelEvent e)
3198: {
3199: validCachedPreferredSize = false;
3200: treeState.treeNodesInserted(e);
3201: tree.repaint();
3202: }
3203:
3204:
3214: public void treeNodesRemoved(TreeModelEvent e)
3215: {
3216: validCachedPreferredSize = false;
3217: treeState.treeNodesRemoved(e);
3218: tree.repaint();
3219: }
3220:
3221:
3230: public void treeStructureChanged(TreeModelEvent e)
3231: {
3232: if (e.getPath().length == 1
3233: && ! e.getPath()[0].equals(treeModel.getRoot()))
3234: tree.expandPath(new TreePath(treeModel.getRoot()));
3235: validCachedPreferredSize = false;
3236: treeState.treeStructureChanged(e);
3237: tree.repaint();
3238: }
3239: }
3240:
3241:
3244: public class TreePageAction
3245: extends AbstractAction
3246: {
3247:
3248: protected int direction;
3249:
3250:
3256: public TreePageAction(int direction, String name)
3257: {
3258: this.direction = direction;
3259: putValue(Action.NAME, name);
3260: }
3261:
3262:
3267: public void actionPerformed(ActionEvent e)
3268: {
3269: String command = (String) getValue(Action.NAME);
3270: boolean extendSelection = command.equals("scrollUpExtendSelection")
3271: || command.equals("scrollDownExtendSelection");
3272: boolean changeSelection = command.equals("scrollUpChangeSelection")
3273: || command.equals("scrollDownChangeSelection");
3274:
3275:
3276: if (!extendSelection && !changeSelection
3277: && tree.getSelectionModel().getSelectionMode() !=
3278: TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION)
3279: {
3280: changeSelection = true;
3281: }
3282:
3283: int rowCount = getRowCount(tree);
3284: if (rowCount > 0 && treeSelectionModel != null)
3285: {
3286: Dimension maxSize = tree.getSize();
3287: TreePath lead = tree.getLeadSelectionPath();
3288: TreePath newPath = null;
3289: Rectangle visible = tree.getVisibleRect();
3290: if (direction == -1)
3291: {
3292: newPath = getClosestPathForLocation(tree, visible.x, visible.y);
3293: if (newPath.equals(lead))
3294: {
3295: visible.y = Math.max(0, visible.y - visible.height);
3296: newPath = getClosestPathForLocation(tree, visible.x,
3297: visible.y);
3298: }
3299: }
3300: else
3301: {
3302: visible.y = Math.min(maxSize.height,
3303: visible.y + visible.height - 1);
3304: newPath = getClosestPathForLocation(tree, visible.x, visible.y);
3305: if (newPath.equals(lead))
3306: {
3307: visible.y = Math.min(maxSize.height,
3308: visible.y + visible.height - 1);
3309: newPath = getClosestPathForLocation(tree, visible.x,
3310: visible.y);
3311: }
3312: }
3313:
3314:
3315: Rectangle newVisible = getPathBounds(tree, newPath);
3316: newVisible.x = visible.x;
3317: newVisible.width = visible.width;
3318: if (direction == -1)
3319: {
3320: newVisible.height = visible.height;
3321: }
3322: else
3323: {
3324: newVisible.y -= visible.height - newVisible.height;
3325: newVisible.height = visible.height;
3326: }
3327:
3328: if (extendSelection)
3329: {
3330:
3331: TreePath anchorPath = tree.getAnchorSelectionPath();
3332: if (anchorPath == null)
3333: {
3334: tree.setSelectionPath(newPath);
3335: }
3336: else
3337: {
3338: int newIndex = getRowForPath(tree, newPath);
3339: int anchorIndex = getRowForPath(tree, anchorPath);
3340: tree.setSelectionInterval(Math.min(anchorIndex, newIndex),
3341: Math.max(anchorIndex, newIndex));
3342: tree.setAnchorSelectionPath(anchorPath);
3343: tree.setLeadSelectionPath(newPath);
3344: }
3345: }
3346: else if (changeSelection)
3347: {
3348: tree.setSelectionPath(newPath);
3349: }
3350: else
3351: {
3352: tree.setLeadSelectionPath(newPath);
3353: }
3354:
3355: tree.scrollRectToVisible(newVisible);
3356: }
3357: }
3358:
3359:
3364: public boolean isEnabled()
3365: {
3366: return (tree != null) && tree.isEnabled();
3367: }
3368: }
3369:
3370:
3374: public class TreeSelectionHandler
3375: implements TreeSelectionListener
3376: {
3377:
3380: public TreeSelectionHandler()
3381: {
3382:
3383: }
3384:
3385:
3391: public void valueChanged(TreeSelectionEvent event)
3392: {
3393: completeEditing();
3394:
3395: TreePath op = event.getOldLeadSelectionPath();
3396: TreePath np = event.getNewLeadSelectionPath();
3397:
3398:
3399: if (op != np)
3400: {
3401: Rectangle o = treeState.getBounds(event.getOldLeadSelectionPath(),
3402: new Rectangle());
3403: Rectangle n = treeState.getBounds(event.getNewLeadSelectionPath(),
3404: new Rectangle());
3405:
3406: if (o != null)
3407: tree.repaint(o);
3408: if (n != null)
3409: tree.repaint(n);
3410: }
3411: }
3412: }
3413:
3414:
3417: public class TreeToggleAction
3418: extends AbstractAction
3419: {
3420:
3425: public TreeToggleAction(String name)
3426: {
3427: putValue(Action.NAME, name);
3428: }
3429:
3430:
3435: public void actionPerformed(ActionEvent e)
3436: {
3437: int selected = tree.getLeadSelectionRow();
3438: if (selected != -1 && isLeaf(selected))
3439: {
3440: TreePath anchorPath = tree.getAnchorSelectionPath();
3441: TreePath leadPath = tree.getLeadSelectionPath();
3442: toggleExpandState(getPathForRow(tree, selected));
3443:
3444:
3445: tree.setLeadSelectionPath(leadPath);
3446: tree.setAnchorSelectionPath(anchorPath);
3447:
3448:
3449: tree.scrollPathToVisible(tree.getLeadSelectionPath());
3450: }
3451: }
3452:
3453:
3458: public boolean isEnabled()
3459: {
3460: return (tree != null) && tree.isEnabled();
3461: }
3462: }
3463:
3464:
3468: public class TreeTraverseAction
3469: extends AbstractAction
3470: {
3471:
3474: protected int direction;
3475:
3476:
3482: public TreeTraverseAction(int direction, String name)
3483: {
3484: this.direction = direction;
3485: putValue(Action.NAME, name);
3486: }
3487:
3488:
3493: public void actionPerformed(ActionEvent e)
3494: {
3495: TreePath current = tree.getLeadSelectionPath();
3496: if (current == null)
3497: return;
3498:
3499: String command = (String) getValue(Action.NAME);
3500: if (command.equals("selectParent"))
3501: {
3502: if (current == null)
3503: return;
3504:
3505: if (tree.isExpanded(current))
3506: {
3507: tree.collapsePath(current);
3508: }
3509: else
3510: {
3511:
3512:
3513:
3514: TreePath parent = current.getParentPath();
3515: if (parent != null &&
3516: ! (parent.getPathCount() == 1 && ! tree.isRootVisible()))
3517: tree.setSelectionPath(parent);
3518: }
3519: }
3520: else if (command.equals("selectChild"))
3521: {
3522: Object node = current.getLastPathComponent();
3523: int nc = treeModel.getChildCount(node);
3524: if (nc == 0 || treeState.isExpanded(current))
3525: {
3526:
3527:
3528: int nextRow = tree.getLeadSelectionRow() + 1;
3529: if (nextRow <= tree.getRowCount())
3530: tree.setSelectionRow(nextRow);
3531: }
3532: else
3533: {
3534: tree.expandPath(current);
3535: }
3536: }
3537:
3538:
3539: tree.scrollPathToVisible(tree.getLeadSelectionPath());
3540: }
3541:
3542:
3547: public boolean isEnabled()
3548: {
3549: return (tree != null) && tree.isEnabled();
3550: }
3551: }
3552:
3553:
3559: boolean hasControlIcons()
3560: {
3561: if (expandedIcon != null || collapsedIcon != null)
3562: return true;
3563: return false;
3564: }
3565:
3566:
3572: Icon getCurrentControlIcon(TreePath path)
3573: {
3574: if (hasControlIcons())
3575: {
3576: if (tree.isExpanded(path))
3577: return expandedIcon;
3578: else
3579: return collapsedIcon;
3580: }
3581: else
3582: {
3583: if (nullIcon == null)
3584: nullIcon = new Icon()
3585: {
3586: public int getIconHeight()
3587: {
3588: return 0;
3589: }
3590:
3591: public int getIconWidth()
3592: {
3593: return 0;
3594: }
3595:
3596: public void paintIcon(Component c, Graphics g, int x, int y)
3597: {
3598:
3599: }
3600: };
3601: return nullIcon;
3602: }
3603: }
3604:
3605:
3612: Object getParent(Object root, Object node)
3613: {
3614: if (root == null || node == null || root.equals(node))
3615: return null;
3616:
3617: if (node instanceof TreeNode)
3618: return ((TreeNode) node).getParent();
3619: return findNode(root, node);
3620: }
3621:
3622:
3629: private Object findNode(Object root, Object node)
3630: {
3631: if (! treeModel.isLeaf(root) && ! root.equals(node))
3632: {
3633: int size = treeModel.getChildCount(root);
3634: for (int j = 0; j < size; j++)
3635: {
3636: Object child = treeModel.getChild(root, j);
3637: if (node.equals(child))
3638: return root;
3639:
3640: Object n = findNode(child, node);
3641: if (n != null)
3642: return n;
3643: }
3644: }
3645: return null;
3646: }
3647:
3648:
3655: void selectPath(JTree tree, TreePath path)
3656: {
3657: if (path != null)
3658: {
3659: tree.setSelectionPath(path);
3660: tree.setLeadSelectionPath(path);
3661: tree.makeVisible(path);
3662: tree.scrollPathToVisible(path);
3663: }
3664: }
3665:
3666:
3674: Object[] getPathToRoot(Object node, int depth)
3675: {
3676: if (node == null)
3677: {
3678: if (depth == 0)
3679: return null;
3680:
3681: return new Object[depth];
3682: }
3683:
3684: Object[] path = getPathToRoot(getParent(treeModel.getRoot(), node),
3685: depth + 1);
3686: path[path.length - depth - 1] = node;
3687: return path;
3688: }
3689:
3690:
3699: protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
3700: int bottom)
3701: {
3702:
3703: g.setColor(getHashColor());
3704: g.drawLine(x, top, x, bottom);
3705: }
3706:
3707:
3716: protected void paintHorizontalLine(Graphics g, JComponent c, int y, int left,
3717: int right)
3718: {
3719:
3720: g.setColor(getHashColor());
3721: g.drawLine(left, y, right, y);
3722: }
3723:
3724:
3733: protected void drawCentered(Component c, Graphics g, Icon icon, int x, int y)
3734: {
3735: x -= icon.getIconWidth() / 2;
3736: y -= icon.getIconHeight() / 2;
3737:
3738: if (x < 0)
3739: x = 0;
3740: if (y < 0)
3741: y = 0;
3742:
3743: icon.paintIcon(c, g, x, y);
3744: }
3745:
3746:
3754: protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2)
3755: {
3756: g.setColor(getHashColor());
3757: for (int i = x1; i < x2; i += 2)
3758: g.drawLine(i, y, i + 1, y);
3759: }
3760:
3761:
3769: protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2)
3770: {
3771: g.setColor(getHashColor());
3772: for (int i = y1; i < y2; i += 2)
3773: g.drawLine(x, i, x, i + 1);
3774: }
3775:
3776:
3790: protected void paintExpandControl(Graphics g, Rectangle clipBounds,
3791: Insets insets, Rectangle bounds,
3792: TreePath path, int row, boolean isExpanded,
3793: boolean hasBeenExpanded, boolean isLeaf)
3794: {
3795: if (shouldPaintExpandControl(path, row, isExpanded, hasBeenExpanded, isLeaf))
3796: {
3797: Icon icon = getCurrentControlIcon(path);
3798: int iconW = icon.getIconWidth();
3799: int x = bounds.x - iconW - gap;
3800: icon.paintIcon(tree, g, x, bounds.y + bounds.height / 2
3801: - icon.getIconHeight() / 2);
3802: }
3803: }
3804:
3805:
3820: protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
3821: Insets insets, Rectangle bounds,
3822: TreePath path, int row,
3823: boolean isExpanded,
3824: boolean hasBeenExpanded,
3825: boolean isLeaf)
3826: {
3827: if (row != 0)
3828: {
3829: paintHorizontalLine(g, tree, bounds.y + bounds.height / 2,
3830: bounds.x - leftChildIndent - gap, bounds.x - gap);
3831: }
3832: }
3833:
3834:
3843: protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,
3844: Insets insets, TreePath path)
3845: {
3846: Rectangle bounds = getPathBounds(tree, path);
3847: TreePath parent = path.getParentPath();
3848:
3849: boolean paintLine;
3850: if (isRootVisible())
3851: paintLine = parent != null;
3852: else
3853: paintLine = parent != null && parent.getPathCount() > 1;
3854: if (paintLine)
3855: {
3856: Rectangle parentBounds = getPathBounds(tree, parent);
3857: paintVerticalLine(g, tree, parentBounds.x + 2 * gap,
3858: parentBounds.y + parentBounds.height / 2,
3859: bounds.y + bounds.height / 2);
3860: }
3861: }
3862:
3863:
3877: protected void paintRow(Graphics g, Rectangle clipBounds, Insets insets,
3878: Rectangle bounds, TreePath path, int row,
3879: boolean isExpanded, boolean hasBeenExpanded,
3880: boolean isLeaf)
3881: {
3882: boolean selected = tree.isPathSelected(path);
3883: boolean hasIcons = false;
3884: Object node = path.getLastPathComponent();
3885:
3886: paintExpandControl(g, clipBounds, insets, bounds, path, row, isExpanded,
3887: hasBeenExpanded, isLeaf);
3888:
3889: TreeCellRenderer dtcr = currentCellRenderer;
3890:
3891: boolean focused = false;
3892: if (treeSelectionModel != null)
3893: focused = treeSelectionModel.getLeadSelectionRow() == row
3894: && tree.isFocusOwner();
3895:
3896: Component c = dtcr.getTreeCellRendererComponent(tree, node, selected,
3897: isExpanded, isLeaf, row,
3898: focused);
3899:
3900: rendererPane.paintComponent(g, c, c.getParent(), bounds);
3901: }
3902:
3903:
3906: protected void prepareForUIUninstall()
3907: {
3908:
3909: }
3910:
3911:
3921: protected boolean shouldPaintExpandControl(TreePath path, int row,
3922: boolean isExpanded,
3923: boolean hasBeenExpanded,
3924: boolean isLeaf)
3925: {
3926: Object node = path.getLastPathComponent();
3927: return ! isLeaf && hasControlIcons();
3928: }
3929:
3930:
3935: protected int getRowX(int row, int depth)
3936: {
3937: return depth * totalChildIndent;
3938: }
3939: }