| GNU Classpath (0.95) | |
| Frames | No Frames |
1: /* BasicTreeUI.java -- 2: Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing.plaf.basic; 40: 41: import gnu.javax.swing.tree.GnuPath; 42: 43: import java.awt.Color; 44: import java.awt.Component; 45: import java.awt.Container; 46: import java.awt.Dimension; 47: import java.awt.Graphics; 48: import java.awt.Insets; 49: import java.awt.Label; 50: import java.awt.Point; 51: import java.awt.Rectangle; 52: import java.awt.event.ActionEvent; 53: import java.awt.event.ActionListener; 54: import java.awt.event.ComponentAdapter; 55: import java.awt.event.ComponentEvent; 56: import java.awt.event.ComponentListener; 57: import java.awt.event.FocusEvent; 58: import java.awt.event.FocusListener; 59: import java.awt.event.InputEvent; 60: import java.awt.event.KeyAdapter; 61: import java.awt.event.KeyEvent; 62: import java.awt.event.KeyListener; 63: import java.awt.event.MouseAdapter; 64: import java.awt.event.MouseEvent; 65: import java.awt.event.MouseListener; 66: import java.awt.event.MouseMotionListener; 67: import java.beans.PropertyChangeEvent; 68: import java.beans.PropertyChangeListener; 69: import java.util.Enumeration; 70: import java.util.Hashtable; 71: 72: import javax.swing.AbstractAction; 73: import javax.swing.Action; 74: import javax.swing.ActionMap; 75: import javax.swing.CellRendererPane; 76: import javax.swing.Icon; 77: import javax.swing.InputMap; 78: import javax.swing.JComponent; 79: import javax.swing.JScrollBar; 80: import javax.swing.JScrollPane; 81: import javax.swing.JTree; 82: import javax.swing.LookAndFeel; 83: import javax.swing.SwingUtilities; 84: import javax.swing.Timer; 85: import javax.swing.UIManager; 86: import javax.swing.event.CellEditorListener; 87: import javax.swing.event.ChangeEvent; 88: import javax.swing.event.MouseInputListener; 89: import javax.swing.event.TreeExpansionEvent; 90: import javax.swing.event.TreeExpansionListener; 91: import javax.swing.event.TreeModelEvent; 92: import javax.swing.event.TreeModelListener; 93: import javax.swing.event.TreeSelectionEvent; 94: import javax.swing.event.TreeSelectionListener; 95: import javax.swing.plaf.ActionMapUIResource; 96: import javax.swing.plaf.ComponentUI; 97: import javax.swing.plaf.TreeUI; 98: import javax.swing.tree.AbstractLayoutCache; 99: import javax.swing.tree.DefaultTreeCellEditor; 100: import javax.swing.tree.DefaultTreeCellRenderer; 101: import javax.swing.tree.TreeCellEditor; 102: import javax.swing.tree.TreeCellRenderer; 103: import javax.swing.tree.TreeModel; 104: import javax.swing.tree.TreeNode; 105: import javax.swing.tree.TreePath; 106: import javax.swing.tree.TreeSelectionModel; 107: import javax.swing.tree.VariableHeightLayoutCache; 108: 109: /** 110: * A delegate providing the user interface for <code>JTree</code> according to 111: * the Basic look and feel. 112: * 113: * @see javax.swing.JTree 114: * @author Lillian Angel (langel@redhat.com) 115: * @author Sascha Brawer (brawer@dandelis.ch) 116: * @author Audrius Meskauskas (audriusa@bioinformatics.org) 117: */ 118: public class BasicTreeUI 119: extends TreeUI 120: { 121: /** 122: * The tree cell editing may be started by the single mouse click on the 123: * selected cell. To separate it from the double mouse click, the editing 124: * session starts after this time (in ms) after that single click, and only no 125: * other clicks were performed during that time. 126: */ 127: static int WAIT_TILL_EDITING = 900; 128: 129: /** Collapse Icon for the tree. */ 130: protected transient Icon collapsedIcon; 131: 132: /** Expanded Icon for the tree. */ 133: protected transient Icon expandedIcon; 134: 135: /** Distance between left margin and where vertical dashes will be drawn. */ 136: protected int leftChildIndent; 137: 138: /** 139: * Distance between leftChildIndent and where cell contents will be drawn. 140: */ 141: protected int rightChildIndent; 142: 143: /** 144: * Total fistance that will be indented. The sum of leftChildIndent and 145: * rightChildIndent . 146: */ 147: protected int totalChildIndent; 148: 149: /** Index of the row that was last selected. */ 150: protected int lastSelectedRow; 151: 152: /** Component that we're going to be drawing onto. */ 153: protected JTree tree; 154: 155: /** Renderer that is being used to do the actual cell drawing. */ 156: protected transient TreeCellRenderer currentCellRenderer; 157: 158: /** 159: * Set to true if the renderer that is currently in the tree was created by 160: * this instance. 161: */ 162: protected boolean createdRenderer; 163: 164: /** Editor for the tree. */ 165: protected transient TreeCellEditor cellEditor; 166: 167: /** 168: * Set to true if editor that is currently in the tree was created by this 169: * instance. 170: */ 171: protected boolean createdCellEditor; 172: 173: /** 174: * Set to false when editing and shouldSelectCall() returns true meaning the 175: * node should be selected before editing, used in completeEditing. 176: * GNU Classpath editing is implemented differently, so this value is not 177: * actually read anywhere. However it is always set correctly to maintain 178: * interoperability with the derived classes that read this field. 179: */ 180: protected boolean stopEditingInCompleteEditing; 181: 182: /** Used to paint the TreeCellRenderer. */ 183: protected CellRendererPane rendererPane; 184: 185: /** Size needed to completely display all the nodes. */ 186: protected Dimension preferredSize; 187: 188: /** Minimum size needed to completely display all the nodes. */ 189: protected Dimension preferredMinSize; 190: 191: /** Is the preferredSize valid? */ 192: protected boolean validCachedPreferredSize; 193: 194: /** Object responsible for handling sizing and expanded issues. */ 195: protected AbstractLayoutCache treeState; 196: 197: /** Used for minimizing the drawing of vertical lines. */ 198: protected Hashtable<TreePath, Boolean> drawingCache; 199: 200: /** 201: * True if doing optimizations for a largeModel. Subclasses that don't support 202: * this may wish to override createLayoutCache to not return a 203: * FixedHeightLayoutCache instance. 204: */ 205: protected boolean largeModel; 206: 207: /** Responsible for telling the TreeState the size needed for a node. */ 208: protected AbstractLayoutCache.NodeDimensions nodeDimensions; 209: 210: /** Used to determine what to display. */ 211: protected TreeModel treeModel; 212: 213: /** Model maintaining the selection. */ 214: protected TreeSelectionModel treeSelectionModel; 215: 216: /** 217: * How much the depth should be offset to properly calculate x locations. This 218: * is based on whether or not the root is visible, and if the root handles are 219: * visible. 220: */ 221: protected int depthOffset; 222: 223: /** 224: * When editing, this will be the Component that is doing the actual editing. 225: */ 226: protected Component editingComponent; 227: 228: /** Path that is being edited. */ 229: protected TreePath editingPath; 230: 231: /** 232: * Row that is being edited. Should only be referenced if editingComponent is 233: * null. 234: */ 235: protected int editingRow; 236: 237: /** Set to true if the editor has a different size than the renderer. */ 238: protected boolean editorHasDifferentSize; 239: 240: /** Boolean to keep track of editing. */ 241: boolean isEditing; 242: 243: /** The current path of the visible nodes in the tree. */ 244: TreePath currentVisiblePath; 245: 246: /** The gap between the icon and text. */ 247: int gap = 4; 248: 249: /** The max height of the nodes in the tree. */ 250: int maxHeight; 251: 252: /** The hash color. */ 253: Color hashColor; 254: 255: /** Listeners */ 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: /** 277: * The zero size icon, used for expand controls, if they are not visible. 278: */ 279: static Icon nullIcon; 280: 281: /** 282: * The special value of the mouse event is sent indicating that this is not 283: * just the mouse click, but the mouse click on the selected node. Sending 284: * such event forces to start the cell editing session. 285: */ 286: static final MouseEvent EDIT = new MouseEvent(new Label(), 7, 7, 7, 7, 7, 7, 287: false); 288: 289: /** 290: * Creates a new BasicTreeUI object. 291: */ 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: /** 304: * Returns an instance of the UI delegate for the specified component. 305: * 306: * @param c the <code>JComponent</code> for which we need a UI delegate for. 307: * @return the <code>ComponentUI</code> for c. 308: */ 309: public static ComponentUI createUI(JComponent c) 310: { 311: return new BasicTreeUI(); 312: } 313: 314: /** 315: * Returns the Hash color. 316: * 317: * @return the <code>Color</code> of the Hash. 318: */ 319: protected Color getHashColor() 320: { 321: return hashColor; 322: } 323: 324: /** 325: * Sets the Hash color. 326: * 327: * @param color the <code>Color</code> to set the Hash to. 328: */ 329: protected void setHashColor(Color color) 330: { 331: hashColor = color; 332: } 333: 334: /** 335: * Sets the left child's indent value. 336: * 337: * @param newAmount is the new indent value for the left child. 338: */ 339: public void setLeftChildIndent(int newAmount) 340: { 341: leftChildIndent = newAmount; 342: } 343: 344: /** 345: * Returns the indent value for the left child. 346: * 347: * @return the indent value for the left child. 348: */ 349: public int getLeftChildIndent() 350: { 351: return leftChildIndent; 352: } 353: 354: /** 355: * Sets the right child's indent value. 356: * 357: * @param newAmount is the new indent value for the right child. 358: */ 359: public void setRightChildIndent(int newAmount) 360: { 361: rightChildIndent = newAmount; 362: } 363: 364: /** 365: * Returns the indent value for the right child. 366: * 367: * @return the indent value for the right child. 368: */ 369: public int getRightChildIndent() 370: { 371: return rightChildIndent; 372: } 373: 374: /** 375: * Sets the expanded icon. 376: * 377: * @param newG is the new expanded icon. 378: */ 379: public void setExpandedIcon(Icon newG) 380: { 381: expandedIcon = newG; 382: } 383: 384: /** 385: * Returns the current expanded icon. 386: * 387: * @return the current expanded icon. 388: */ 389: public Icon getExpandedIcon() 390: { 391: return expandedIcon; 392: } 393: 394: /** 395: * Sets the collapsed icon. 396: * 397: * @param newG is the new collapsed icon. 398: */ 399: public void setCollapsedIcon(Icon newG) 400: { 401: collapsedIcon = newG; 402: } 403: 404: /** 405: * Returns the current collapsed icon. 406: * 407: * @return the current collapsed icon. 408: */ 409: public Icon getCollapsedIcon() 410: { 411: return collapsedIcon; 412: } 413: 414: /** 415: * Updates the componentListener, if necessary. 416: * 417: * @param largeModel sets this.largeModel to it. 418: */ 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: /** 431: * Returns true if largeModel is set 432: * 433: * @return true if largeModel is set, otherwise false. 434: */ 435: protected boolean isLargeModel() 436: { 437: return largeModel; 438: } 439: 440: /** 441: * Sets the row height. 442: * 443: * @param rowHeight is the height to set this.rowHeight to. 444: */ 445: protected void setRowHeight(int rowHeight) 446: { 447: completeEditing(); 448: if (rowHeight == 0) 449: rowHeight = getMaxHeight(tree); 450: treeState.setRowHeight(rowHeight); 451: } 452: 453: /** 454: * Returns the current row height. 455: * 456: * @return current row height. 457: */ 458: protected int getRowHeight() 459: { 460: return tree.getRowHeight(); 461: } 462: 463: /** 464: * Sets the TreeCellRenderer to <code>tcr</code>. This invokes 465: * <code>updateRenderer</code>. 466: * 467: * @param tcr is the new TreeCellRenderer. 468: */ 469: protected void setCellRenderer(TreeCellRenderer tcr) 470: { 471: // Finish editing before changing the renderer. 472: completeEditing(); 473: 474: // The renderer is set in updateRenderer. 475: updateRenderer(); 476: 477: // Refresh the layout if necessary. 478: if (treeState != null) 479: { 480: treeState.invalidateSizes(); 481: updateSize(); 482: } 483: } 484: 485: /** 486: * Return currentCellRenderer, which will either be the trees renderer, or 487: * defaultCellRenderer, which ever was not null. 488: * 489: * @return the current Cell Renderer 490: */ 491: protected TreeCellRenderer getCellRenderer() 492: { 493: if (currentCellRenderer != null) 494: return currentCellRenderer; 495: 496: return createDefaultCellRenderer(); 497: } 498: 499: /** 500: * Sets the tree's model. 501: * 502: * @param model to set the treeModel to. 503: */ 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: /** 525: * Returns the tree's model 526: * 527: * @return treeModel 528: */ 529: protected TreeModel getModel() 530: { 531: return treeModel; 532: } 533: 534: /** 535: * Sets the root to being visible. 536: * 537: * @param newValue sets the visibility of the root 538: */ 539: protected void setRootVisible(boolean newValue) 540: { 541: completeEditing(); 542: tree.setRootVisible(newValue); 543: } 544: 545: /** 546: * Returns true if the root is visible. 547: * 548: * @return true if the root is visible. 549: */ 550: protected boolean isRootVisible() 551: { 552: return tree.isRootVisible(); 553: } 554: 555: /** 556: * Determines whether the node handles are to be displayed. 557: * 558: * @param newValue sets whether or not node handles should be displayed. 559: */ 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: /** 572: * Returns true if the node handles are to be displayed. 573: * 574: * @return true if the node handles are to be displayed. 575: */ 576: protected boolean getShowsRootHandles() 577: { 578: return tree.getShowsRootHandles(); 579: } 580: 581: /** 582: * Sets the cell editor. 583: * 584: * @param editor to set the cellEditor to. 585: */ 586: protected void setCellEditor(TreeCellEditor editor) 587: { 588: updateCellEditor(); 589: } 590: 591: /** 592: * Returns the <code>TreeCellEditor</code> for this tree. 593: * 594: * @return the cellEditor for this tree. 595: */ 596: protected TreeCellEditor getCellEditor() 597: { 598: return cellEditor; 599: } 600: 601: /** 602: * Configures the receiver to allow, or not allow, editing. 603: * 604: * @param newValue sets the receiver to allow editing if true. 605: */ 606: protected void setEditable(boolean newValue) 607: { 608: updateCellEditor(); 609: } 610: 611: /** 612: * Returns true if the receiver allows editing. 613: * 614: * @return true if the receiver allows editing. 615: */ 616: protected boolean isEditable() 617: { 618: return tree.isEditable(); 619: } 620: 621: /** 622: * Resets the selection model. The appropriate listeners are installed on the 623: * model. 624: * 625: * @param newLSM resets the selection model. 626: */ 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: /** 638: * Returns the current selection model. 639: * 640: * @return the current selection model. 641: */ 642: protected TreeSelectionModel getSelectionModel() 643: { 644: return treeSelectionModel; 645: } 646: 647: /** 648: * Returns the Rectangle enclosing the label portion that the last item in 649: * path will be drawn to. Will return null if any component in path is 650: * currently valid. 651: * 652: * @param tree is the current tree the path will be drawn to. 653: * @param path is the current path the tree to draw to. 654: * @return the Rectangle enclosing the label portion that the last item in the 655: * path will be drawn to. 656: */ 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: /** 674: * Returns the max height of all the nodes in the tree. 675: * 676: * @param tree - the current tree 677: * @return the max height. 678: */ 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: /** 707: * Get the tree node icon. 708: */ 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: /** 721: * Returns the path for passed in row. If row is not visible null is returned. 722: * 723: * @param tree is the current tree to return path for. 724: * @param row is the row number of the row to return. 725: * @return the path for passed in row. If row is not visible null is returned. 726: */ 727: public TreePath getPathForRow(JTree tree, int row) 728: { 729: return treeState.getPathForRow(row); 730: } 731: 732: /** 733: * Returns the row that the last item identified in path is visible at. Will 734: * return -1 if any of the elments in the path are not currently visible. 735: * 736: * @param tree is the current tree to return the row for. 737: * @param path is the path used to find the row. 738: * @return the row that the last item identified in path is visible at. Will 739: * return -1 if any of the elments in the path are not currently 740: * visible. 741: */ 742: public int getRowForPath(JTree tree, TreePath path) 743: { 744: return treeState.getRowForPath(path); 745: } 746: 747: /** 748: * Returns the number of rows that are being displayed. 749: * 750: * @param tree is the current tree to return the number of rows for. 751: * @return the number of rows being displayed. 752: */ 753: public int getRowCount(JTree tree) 754: { 755: return treeState.getRowCount(); 756: } 757: 758: /** 759: * Returns the path to the node that is closest to x,y. If there is nothing 760: * currently visible this will return null, otherwise it'll always return a 761: * valid path. If you need to test if the returned object is exactly at x,y 762: * you should get the bounds for the returned path and test x,y against that. 763: * 764: * @param tree the tree to search for the closest path 765: * @param x is the x coordinate of the location to search 766: * @param y is the y coordinate of the location to search 767: * @return the tree path closes to x,y. 768: */ 769: public TreePath getClosestPathForLocation(JTree tree, int x, int y) 770: { 771: return treeState.getPathClosestTo(x, y); 772: } 773: 774: /** 775: * Returns true if the tree is being edited. The item that is being edited can 776: * be returned by getEditingPath(). 777: * 778: * @param tree is the tree to check for editing. 779: * @return true if the tree is being edited. 780: */ 781: public boolean isEditing(JTree tree) 782: { 783: return isEditing; 784: } 785: 786: /** 787: * Stops the current editing session. This has no effect if the tree is not 788: * being edited. Returns true if the editor allows the editing session to 789: * stop. 790: * 791: * @param tree is the tree to stop the editing on 792: * @return true if the editor allows the editing session to stop. 793: */ 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: /** 806: * Cancels the current editing session. 807: * 808: * @param tree is the tree to cancel the editing session on. 809: */ 810: public void cancelEditing(JTree tree) 811: { 812: // There is no need to send the cancel message to the editor, 813: // as the cancellation event itself arrives from it. This would 814: // only be necessary when cancelling the editing programatically. 815: if (editingComponent != null) 816: completeEditing(false, true, false); 817: } 818: 819: /** 820: * Selects the last item in path and tries to edit it. Editing will fail if 821: * the CellEditor won't allow it for the selected item. 822: * 823: * @param tree is the tree to edit on. 824: * @param path is the path in tree to edit on. 825: */ 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: /** 834: * Returns the path to the element that is being editted. 835: * 836: * @param tree is the tree to get the editing path from. 837: * @return the path that is being edited. 838: */ 839: public TreePath getEditingPath(JTree tree) 840: { 841: return editingPath; 842: } 843: 844: /** 845: * Invoked after the tree instance variable has been set, but before any 846: * default/listeners have been installed. 847: */ 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: /** 859: * Invoked from installUI after all the defaults/listeners have been 860: * installed. 861: */ 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: /** 875: * Invoked from uninstallUI after all the defaults/listeners have been 876: * uninstalled. 877: */ 878: protected void completeUIUninstall() 879: { 880: tree = null; 881: } 882: 883: /** 884: * Installs the subcomponents of the tree, which is the renderer pane. 885: */ 886: protected void installComponents() 887: { 888: currentCellRenderer = createDefaultCellRenderer(); 889: rendererPane = createCellRendererPane(); 890: createdRenderer = true; 891: setCellRenderer(currentCellRenderer); 892: } 893: 894: /** 895: * Creates an instance of NodeDimensions that is able to determine the size of 896: * a given node in the tree. The node dimensions must be created before 897: * configuring the layout cache. 898: * 899: * @return the NodeDimensions of a given node in the tree 900: */ 901: protected AbstractLayoutCache.NodeDimensions createNodeDimensions() 902: { 903: return new NodeDimensionsHandler(); 904: } 905: 906: /** 907: * Creates a listener that is reponsible for the updates the UI based on how 908: * the tree changes. 909: * 910: * @return the PropertyChangeListener that is reposnsible for the updates 911: */ 912: protected PropertyChangeListener createPropertyChangeListener() 913: { 914: return new PropertyChangeHandler(); 915: } 916: 917: /** 918: * Creates the listener responsible for updating the selection based on mouse 919: * events. 920: * 921: * @return the MouseListener responsible for updating. 922: */ 923: protected MouseListener createMouseListener() 924: { 925: return new MouseHandler(); 926: } 927: 928: /** 929: * Creates the listener that is responsible for updating the display when 930: * focus is lost/grained. 931: * 932: * @return the FocusListener responsible for updating. 933: */ 934: protected FocusListener createFocusListener() 935: { 936: return new FocusHandler(); 937: } 938: 939: /** 940: * Creates the listener reponsible for getting key events from the tree. 941: * 942: * @return the KeyListener responsible for getting key events. 943: */ 944: protected KeyListener createKeyListener() 945: { 946: return new KeyHandler(); 947: } 948: 949: /** 950: * Creates the listener responsible for getting property change events from 951: * the selection model. 952: * 953: * @returns the PropertyChangeListener reponsible for getting property change 954: * events from the selection model. 955: */ 956: protected PropertyChangeListener createSelectionModelPropertyChangeListener() 957: { 958: return new SelectionModelPropertyChangeHandler(); 959: } 960: 961: /** 962: * Creates the listener that updates the display based on selection change 963: * methods. 964: * 965: * @return the TreeSelectionListener responsible for updating. 966: */ 967: protected TreeSelectionListener createTreeSelectionListener() 968: { 969: return new TreeSelectionHandler(); 970: } 971: 972: /** 973: * Creates a listener to handle events from the current editor