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