Frames | No Frames |
1: /* DefaultTreeCellRenderer.java 2: Copyright (C) 2002, 2004, 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.tree; 40: 41: import java.awt.Color; 42: import java.awt.Component; 43: import java.awt.Dimension; 44: import java.awt.Font; 45: import java.awt.FontMetrics; 46: import java.awt.Graphics; 47: import java.awt.Insets; 48: import java.awt.Rectangle; 49: 50: import javax.swing.Icon; 51: import javax.swing.JLabel; 52: import javax.swing.JTree; 53: import javax.swing.LookAndFeel; 54: import javax.swing.SwingUtilities; 55: import javax.swing.UIManager; 56: import javax.swing.border.Border; 57: import javax.swing.plaf.UIResource; 58: 59: /** 60: * A default implementation of the {@link TreeCellRenderer} interface. 61: * 62: * @author Andrew Selkirk 63: */ 64: public class DefaultTreeCellRenderer 65: extends JLabel 66: implements TreeCellRenderer 67: { 68: 69: /** 70: * A flag indicating the current selection status. 71: */ 72: protected boolean selected; 73: 74: /** 75: * A flag indicating the current focus status. 76: */ 77: protected boolean hasFocus; 78: 79: /** 80: * drawsFocusBorderAroundIcon // FIXME: is this used? 81: */ 82: private boolean drawsFocusBorderAroundIcon; 83: 84: /** 85: * The icon used to represent non-leaf nodes that are closed. 86: * 87: * @see #setClosedIcon(Icon) 88: */ 89: protected transient Icon closedIcon; 90: 91: /** 92: * The icon used to represent leaf nodes. 93: * 94: * @see #setLeafIcon(Icon) 95: */ 96: protected transient Icon leafIcon; 97: 98: /** 99: * The icon used to represent non-leaf nodes that are open. 100: * 101: * @see #setOpenIcon(Icon) 102: */ 103: protected transient Icon openIcon; 104: 105: /** 106: * The color used for text in selected cells. 107: * 108: * @see #setTextSelectionColor(Color) 109: */ 110: protected Color textSelectionColor; 111: 112: /** 113: * The color used for text in non-selected cells. 114: * 115: * @see #setTextNonSelectionColor(Color) 116: */ 117: protected Color textNonSelectionColor; 118: 119: /** 120: * The background color for selected cells. 121: * 122: * @see #setBackgroundSelectionColor(Color) 123: */ 124: protected Color backgroundSelectionColor; 125: 126: /** 127: * The background color for non-selected cells. 128: * 129: * @see #setBackgroundNonSelectionColor(Color) 130: */ 131: protected Color backgroundNonSelectionColor; 132: 133: /** 134: * The border color for selected tree cells. 135: * 136: * @see #setBorderSelectionColor(Color) 137: */ 138: protected Color borderSelectionColor; 139: 140: /** 141: * Creates a new tree cell renderer with defaults appropriate for the 142: * current {@link LookAndFeel}. 143: */ 144: public DefaultTreeCellRenderer() 145: { 146: setLeafIcon(getDefaultLeafIcon()); 147: setOpenIcon(getDefaultOpenIcon()); 148: setClosedIcon(getDefaultClosedIcon()); 149: 150: setTextNonSelectionColor(UIManager.getColor("Tree.textForeground")); 151: setTextSelectionColor(UIManager.getColor("Tree.selectionForeground")); 152: setBackgroundNonSelectionColor(UIManager.getColor("Tree.textBackground")); 153: setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground")); 154: setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor")); 155: } 156: 157: /** 158: * Returns the default icon for non-leaf tree cells that are open (expanded). 159: * The icon is fetched from the defaults table for the current 160: * {@link LookAndFeel} using the key <code>Tree.openIcon</code>. 161: * 162: * @return The default icon. 163: */ 164: public Icon getDefaultOpenIcon() 165: { 166: return UIManager.getIcon("Tree.openIcon"); 167: } 168: 169: /** 170: * Returns the default icon for non-leaf tree cells that are closed (not 171: * expanded). The icon is fetched from the defaults table for the current 172: * {@link LookAndFeel} using the key <code>Tree.closedIcon</code>. 173: * 174: * @return The default icon. 175: */ 176: public Icon getDefaultClosedIcon() 177: { 178: return UIManager.getIcon("Tree.closedIcon"); 179: } 180: 181: /** 182: * Returns the default icon for leaf tree cells. The icon is fetched from 183: * the defaults table for the current {@link LookAndFeel} using the key 184: * <code>Tree.leafIcon</code>. 185: * 186: * @return The default icon. 187: */ 188: public Icon getDefaultLeafIcon() 189: { 190: return UIManager.getIcon("Tree.leafIcon"); 191: } 192: 193: /** 194: * Sets the icon to be displayed for non-leaf nodes that are open (expanded). 195: * Set this to <code>null</code> if no icon is required. 196: * 197: * @param icon the icon (<code>null</code> permitted). 198: * 199: * @see #getOpenIcon() 200: */ 201: public void setOpenIcon(Icon icon) 202: { 203: openIcon = icon; 204: } 205: 206: /** 207: * Returns the icon displayed for non-leaf nodes that are open (expanded). 208: * The default value is initialised from the {@link LookAndFeel}. 209: * 210: * @return The open icon (possibly <code>null</code>). 211: * 212: * @see #setOpenIcon(Icon) 213: */ 214: public Icon getOpenIcon() 215: { 216: return openIcon; 217: } 218: 219: /** 220: * Sets the icon to be displayed for non-leaf nodes that are closed. Set 221: * this to <code>null</code> if no icon is required. 222: * 223: * @param icon the icon (<code>null</code> permitted). 224: * 225: * @see #getClosedIcon() 226: */ 227: public void setClosedIcon(Icon icon) 228: { 229: closedIcon = icon; 230: } 231: 232: /** 233: * Returns the icon displayed for non-leaf nodes that are closed. The 234: * default value is initialised from the {@link LookAndFeel}. 235: * 236: * @return The closed icon (possibly <code>null</code>). 237: * 238: * @see #setClosedIcon(Icon) 239: */ 240: public Icon getClosedIcon() 241: { 242: return closedIcon; 243: } 244: 245: /** 246: * Sets the icon to be displayed for leaf nodes. Set this to 247: * <code>null</code> if no icon is required. 248: * 249: * @param icon the icon (<code>null</code> permitted). 250: * 251: * @see #getLeafIcon() 252: */ 253: public void setLeafIcon(Icon icon) 254: { 255: leafIcon = icon; 256: } 257: 258: /** 259: * Returns the icon displayed for leaf nodes. The default value is 260: * initialised from the {@link LookAndFeel}. 261: * 262: * @return The leaf icon (possibly <code>null</code>). 263: * 264: * @see #setLeafIcon(Icon) 265: */ 266: public Icon getLeafIcon() 267: { 268: return leafIcon; 269: } 270: 271: /** 272: * Sets the text color for tree cells that are selected. 273: * 274: * @param c the color (<code>null</code> permitted). 275: * 276: * @see #getTextSelectionColor() 277: */ 278: public void setTextSelectionColor(Color c) 279: { 280: textSelectionColor = c; 281: } 282: 283: /** 284: * Returns the text color for tree cells that are selected. 285: * The default value is obtained from the {@link LookAndFeel} defaults 286: * table using the key <code>Tree.selectionForeground</code>. 287: * 288: * @return The text color for tree cells that are selected. 289: * 290: * @see #setTextSelectionColor(Color) 291: */ 292: public Color getTextSelectionColor() 293: { 294: return textSelectionColor; 295: } 296: 297: /** 298: * Sets the text color for tree cells that are not selected. 299: * 300: * @param c the color (<code>null</code> permitted). 301: * 302: * @see #getTextNonSelectionColor() 303: */ 304: public void setTextNonSelectionColor(Color c) 305: { 306: textNonSelectionColor = c; 307: } 308: 309: /** 310: * Returns the text color for tree cells that are not selected. 311: * The default value is obtained from the {@link LookAndFeel} defaults 312: * table using the key <code>Tree.selectionForeground</code>. 313: * 314: * @return The background color for tree cells that are not selected. 315: * 316: * @see #setTextgroundNonSelectionColor(Color) 317: */ 318: public Color getTextNonSelectionColor() 319: { 320: return textNonSelectionColor; 321: } 322: 323: /** 324: * Sets the background color for tree cells that are selected. 325: * 326: * @param c the color (<code>null</code> permitted). 327: * 328: * @see #getBackgroundSelectionColor() 329: */ 330: public void setBackgroundSelectionColor(Color c) 331: { 332: backgroundSelectionColor = c; 333: } 334: 335: /** 336: * Returns the background color for tree cells that are selected. 337: * The default value is obtained from the {@link LookAndFeel} defaults 338: * table using the key <code>Tree.selectionBackground</code>. 339: * 340: * @return The background color for tree cells that are selected. 341: * 342: * @see #setBackgroundSelectionColor(Color) 343: */ 344: public Color getBackgroundSelectionColor() 345: { 346: return backgroundSelectionColor; 347: } 348: 349: /** 350: * Sets the background color for tree cells that are not selected. 351: * 352: * @param c the color (<code>null</code> permitted). 353: * 354: * @see #getBackgroundNonSelectionColor() 355: */ 356: public void setBackgroundNonSelectionColor(Color c) 357: { 358: backgroundNonSelectionColor = c; 359: } 360: 361: /** 362: * Returns the background color for tree cells that are not selected. 363: * The default value is obtained from the {@link LookAndFeel} defaults 364: * table using the key <code>Tree.textBackground</code>. 365: * 366: * @return The background color for tree cells that are not selected. 367: * 368: * @see #setBackgroundNonSelectionColor(Color) 369: */ 370: public Color getBackgroundNonSelectionColor() 371: { 372: return backgroundNonSelectionColor; 373: } 374: 375: /** 376: * Sets the border color for tree cells that are selected. 377: * 378: * @param c the color (<code>null</code> permitted). 379: * 380: * @see #getBorderSelectionColor() 381: */ 382: public void setBorderSelectionColor(Color c) 383: { 384: borderSelectionColor = c; 385: } 386: 387: /** 388: * Returns the border color for tree cells that are selected. 389: * The default value is obtained from the {@link LookAndFeel} defaults 390: * table using the key <code>Tree.selectionBorderColor</code>. 391: * 392: * @return The border color for tree cells that are selected. 393: * 394: * @see #setBorderSelectionColor(Color) 395: */ 396: public Color getBorderSelectionColor() 397: { 398: return borderSelectionColor; 399: } 400: 401: /** 402: * Sets the font. 403: * 404: * @param f the font. 405: * 406: * @see #getFont() 407: */ 408: public void setFont(Font f) 409: { 410: if (f != null && f instanceof UIResource) 411: f = null; 412: super.setFont(f); 413: } 414: 415: /** 416: * Sets the background color. 417: * 418: * @param c the color. 419: */ 420: public void setBackground(Color c) 421: { 422: if (c != null && c instanceof UIResource) 423: c = null; 424: super.setBackground(c); 425: } 426: 427: /** 428: * Returns a component (in fact <code>this</code>) that can be used to 429: * render a tree cell with the specified state. 430: * 431: * @param tree the tree that the cell belongs to. 432: * @param val the cell value. 433: * @param selected indicates whether or not the cell is selected. 434: * @param expanded indicates whether or not the cell is expanded. 435: * @param leaf indicates whether or not the cell is a leaf in the tree. 436: * @param row the row index. 437: * @param hasFocus indicates whether or not the cell has the focus. 438: * 439: * @return <code>this</code>. 440: */ 441: public Component getTreeCellRendererComponent(JTree tree, Object val, 442: boolean selected, 443: boolean expanded, boolean leaf, 444: int row, boolean hasFocus) 445: { 446: if (leaf) 447: setIcon(getLeafIcon()); 448: else if (expanded) 449: setIcon(getOpenIcon()); 450: else 451: setIcon(getClosedIcon()); 452: 453: setText(val.toString()); 454: this.selected = selected; 455: this.hasFocus = hasFocus; 456: setHorizontalAlignment(LEFT); 457: setOpaque(false); 458: setVerticalAlignment(CENTER); 459: setEnabled(true); 460: super.setFont(UIManager.getFont("Tree.font")); 461: 462: if (selected) 463: { 464: super.setBackground(getBackgroundSelectionColor()); 465: setForeground(getTextSelectionColor()); 466: 467: if (hasFocus) 468: setBorderSelectionColor(UIManager.getLookAndFeelDefaults(). 469: getColor("Tree.selectionBorderColor")); 470: else 471: setBorderSelectionColor(null); 472: } 473: else 474: { 475: super.setBackground(getBackgroundNonSelectionColor()); 476: setForeground(getTextNonSelectionColor()); 477: setBorderSelectionColor(null); 478: } 479: 480: return this; 481: } 482: 483: /** 484: * Returns the current font. 485: * 486: * @return The current font. 487: * 488: * @see #setFont(Font) 489: */ 490: public Font getFont() 491: { 492: return super.getFont(); 493: } 494: 495: /** 496: * Paints the value. The background is filled based on selected. 497: * 498: * @param g the graphics device. 499: */ 500: public void paint(Graphics g) 501: { 502: // paint background 503: Rectangle vr = new Rectangle(); 504: Rectangle ir = new Rectangle(); 505: Rectangle tr = new Rectangle(); 506: 507: Insets insets = new Insets(0, 0, 0, 0); 508: Border border = UIManager.getBorder("Tree.selectionBorder"); 509: if (border != null) 510: insets = border.getBorderInsets(this); 511: 512: FontMetrics fm = getToolkit().getFontMetrics(getFont()); 513: SwingUtilities.layoutCompoundLabel((JLabel) this, fm, getText(), 514: getIcon(), getVerticalAlignment(), 515: getHorizontalAlignment(), 516: getVerticalTextPosition(), 517: getHorizontalTextPosition(), vr, ir, tr, 518: getIconTextGap()); 519: 520: // Reusing one rectangle. 521: Rectangle bounds = getBounds(ir); 522: 523: bounds.x = tr.x - insets.left; 524: bounds.width = tr.width + insets.left + insets.right; 525: 526: g.setColor(super.getBackground()); 527: g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); 528: 529: super.paint(g); 530: 531: // Paint the border of the focused element only (lead selection) 532: if (hasFocus) 533: { 534: Color b = getBorderSelectionColor(); 535: if (b != null) 536: { 537: g.setColor(b); 538: g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height - 1); 539: } 540: } 541: } 542: 543: /** 544: * Returns the preferred size of the cell. 545: * 546: * @return The preferred size of the cell. 547: */ 548: public Dimension getPreferredSize() 549: { 550: Rectangle vr = new Rectangle(); 551: Rectangle ir = new Rectangle(); 552: Rectangle tr = new Rectangle(); 553: 554: FontMetrics fm = getToolkit().getFontMetrics(getFont()); 555: SwingUtilities.layoutCompoundLabel((JLabel) this, fm, getText(), 556: getIcon(), getVerticalAlignment(), 557: getHorizontalAlignment(), 558: getVerticalTextPosition(), 559: getHorizontalTextPosition(), vr, ir, tr, 560: getIconTextGap()); 561: Rectangle cr = ir.union(tr); 562: return new Dimension(cr.width, cr.height); 563: } 564: 565: /** 566: * For performance reasons, this method is overridden to do nothing. 567: */ 568: public void validate() 569: { 570: // Overridden for performance reasons. 571: } 572: 573: /** 574: * For performance reasons, this method is overridden to do nothing. 575: */ 576: public void revalidate() 577: { 578: // Overridden for performance reasons. 579: } 580: 581: /** 582: * For performance reasons, this method is overridden to do nothing. 583: * 584: * @param tm ignored 585: * @param x coordinate of the region to mark as dirty 586: * @param y coordinate of the region to mark as dirty 587: * @param width dimension of the region to mark as dirty 588: * @param height dimension of the region to mark as dirty 589: */ 590: public void repaint(long tm, int x, int y, int width, int height) 591: { 592: // Overridden for performance reasons. 593: } 594: 595: /** 596: * For performance reasons, this method is overridden to do nothing. 597: * 598: * @param area the area to repaint. 599: */ 600: public void repaint(Rectangle area) 601: { 602: // Overridden for performance reasons. 603: } 604: 605: /** 606: * For performance reasons, this method is overridden to do nothing. 607: * 608: * @param name the property name. 609: * @param oldValue the old value. 610: * @param newValue the new value. 611: */ 612: protected void firePropertyChange(String name, Object oldValue, 613: Object newValue) 614: { 615: // Overridden for performance reasons. 616: } 617: 618: /** 619: * For performance reasons, this method is overridden to do nothing. 620: * 621: * @param name the property name. 622: * @param oldValue the old value. 623: * @param newValue the new value. 624: */ 625: public void firePropertyChange(String name, byte oldValue, byte newValue) 626: { 627: // Overridden for performance reasons. 628: } 629: 630: /** 631: * For performance reasons, this method is overridden to do nothing. 632: * 633: * @param name the property name. 634: * @param oldValue the old value. 635: * @param newValue the new value. 636: */ 637: public void firePropertyChange(String name, char oldValue, char newValue) 638: { 639: // Overridden for performance reasons. 640: } 641: 642: /** 643: * For performance reasons, this method is overridden to do nothing. 644: * 645: * @param name the property name. 646: * @param oldValue the old value. 647: * @param newValue the new value. 648: */ 649: public void firePropertyChange(String name, short oldValue, short newValue) 650: { 651: // Overridden for performance reasons. 652: } 653: 654: /** 655: * For performance reasons, this method is overridden to do nothing. 656: * 657: * @param name the property name. 658: * @param oldValue the old value. 659: * @param newValue the new value. 660: */ 661: public void firePropertyChange(String name, int oldValue, int newValue) 662: { 663: // Overridden for performance reasons. 664: } 665: 666: /** 667: * For performance reasons, this method is overridden to do nothing. 668: * 669: * @param name the property name. 670: * @param oldValue the old value. 671: * @param newValue the new value. 672: */ 673: public void firePropertyChange(String name, long oldValue, long newValue) 674: { 675: // Overridden for performance reasons. 676: } 677: 678: /** 679: * For performance reasons, this method is overridden to do nothing. 680: * 681: * @param name the property name. 682: * @param oldValue the old value. 683: * @param newValue the new value. 684: */ 685: public void firePropertyChange(String name, float oldValue, float newValue) 686: { 687: // Overridden for performance reasons. 688: } 689: 690: /** 691: * For performance reasons, this method is overridden to do nothing. 692: * 693: * @param name the property name. 694: * @param oldValue the old value. 695: * @param newValue the new value. 696: */ 697: public void firePropertyChange(String name, double oldValue, double newValue) 698: { 699: // Overridden for performance reasons. 700: } 701: 702: /** 703: * For performance reasons, this method is overridden to do nothing. 704: * 705: * @param name the property name. 706: * @param oldValue the old value. 707: * @param newValue the new value. 708: */ 709: public void firePropertyChange(String name, boolean oldValue, 710: boolean newValue) 711: { 712: // Overridden for performance reasons. 713: } 714: 715: }