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 */ DefaultTreeCellRenderer()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 */ getDefaultOpenIcon()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 */ getDefaultClosedIcon()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 */ getDefaultLeafIcon()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 */ setOpenIcon(Icon icon)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 */ getOpenIcon()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 */ setClosedIcon(Icon icon)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 */ getClosedIcon()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 */ setLeafIcon(Icon icon)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 */ getLeafIcon()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 */ setTextSelectionColor(Color c)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 */ getTextSelectionColor()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 */ setTextNonSelectionColor(Color c)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 */ getTextNonSelectionColor()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 */ setBackgroundSelectionColor(Color c)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 */ getBackgroundSelectionColor()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 */ setBackgroundNonSelectionColor(Color c)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 */ getBackgroundNonSelectionColor()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 */ setBorderSelectionColor(Color c)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 */ getBorderSelectionColor()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 */ setFont(Font f)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 */ setBackground(Color c)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 */ getTreeCellRendererComponent(JTree tree, Object val, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus)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 */ getFont()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 */ paint(Graphics g)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 */ paintFocus(Graphics g, int x, int y, int w, int h)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 */ getXOffset()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 */ getPreferredSize()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 */ validate()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 */ revalidate()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 */ repaint(long tm, int x, int y, int width, int height)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 */ repaint(Rectangle area)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 */ firePropertyChange(String name, Object oldValue, Object newValue)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 */ firePropertyChange(String name, byte oldValue, byte newValue)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 */ firePropertyChange(String name, char oldValue, char newValue)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 */ firePropertyChange(String name, short oldValue, short newValue)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 */ firePropertyChange(String name, int oldValue, int newValue)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 */ firePropertyChange(String name, long oldValue, long newValue)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 */ firePropertyChange(String name, float oldValue, float newValue)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 */ firePropertyChange(String name, double oldValue, double newValue)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 */ firePropertyChange(String name, boolean oldValue, boolean newValue)714 public void firePropertyChange(String name, boolean oldValue, 715 boolean newValue) 716 { 717 // Overridden for performance reasons. 718 } 719 720 } 721