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