Save This Page
Home » openjdk-7 » javax » swing » tree » [javadoc | source]
    1   /*
    2    * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.swing.tree;
   27   
   28   import javax.swing;
   29   import javax.swing.plaf.ColorUIResource;
   30   import javax.swing.plaf.FontUIResource;
   31   import javax.swing.plaf.UIResource;
   32   import javax.swing.plaf.basic.BasicGraphicsUtils;
   33   import java.awt;
   34   import java.awt.event;
   35   import java.beans;
   36   import java.io;
   37   import java.util;
   38   
   39   /**
   40    * Displays an entry in a tree.
   41    * <code>DefaultTreeCellRenderer</code> is not opaque and
   42    * unless you subclass paint you should not change this.
   43    * See <a
   44    href="http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html">How to Use Trees</a>
   45    * in <em>The Java Tutorial</em>
   46    * for examples of customizing node display using this class.
   47    * <p>
   48    * The set of icons and colors used by {@code DefaultTreeCellRenderer}
   49    * can be configured using the various setter methods. The value for
   50    * each property is initialized from the defaults table. When the
   51    * look and feel changes ({@code updateUI} is invoked), any properties
   52    * that have a value of type {@code UIResource} are refreshed from the
   53    * defaults table. The following table lists the mapping between
   54    * {@code DefaultTreeCellRenderer} property and defaults table key:
   55    * <table border="1" cellpadding="1" cellspacing="0"
   56    *         valign="top" >
   57    *   <tr valign="top"  align="left">
   58    *     <th bgcolor="#CCCCFF" align="left">Property:
   59    *     <th bgcolor="#CCCCFF" align="left">Key:
   60    *   <tr><td>"leafIcon"<td>"Tree.leafIcon"
   61    *   <tr><td>"closedIcon"<td>"Tree.closedIcon"
   62    *   <tr><td>"openIcon"<td>"Tree.openIcon"
   63    *   <tr><td>"textSelectionColor"<td>"Tree.selectionForeground"
   64    *   <tr><td>"textNonSelectionColor"<td>"Tree.textForeground"
   65    *   <tr><td>"backgroundSelectionColor"<td>"Tree.selectionBackground"
   66    *   <tr><td>"backgroundNonSelectionColor"<td>"Tree.textBackground"
   67    *   <tr><td>"borderSelectionColor"<td>"Tree.selectionBorderColor"
   68    * </table>
   69    * <p>
   70    * <strong><a name="override">Implementation Note:</a></strong>
   71    * This class overrides
   72    * <code>invalidate</code>,
   73    * <code>validate</code>,
   74    * <code>revalidate</code>,
   75    * <code>repaint</code>,
   76    * and
   77    * <code>firePropertyChange</code>
   78    * solely to improve performance.
   79    * If not overridden, these frequently called methods would execute code paths
   80    * that are unnecessary for the default tree cell renderer.
   81    * If you write your own renderer,
   82    * take care to weigh the benefits and
   83    * drawbacks of overriding these methods.
   84    *
   85    * <p>
   86    * <strong>Warning:</strong>
   87    * Serialized objects of this class will not be compatible with
   88    * future Swing releases. The current serialization support is
   89    * appropriate for short term storage or RMI between applications running
   90    * the same version of Swing.  As of 1.4, support for long term storage
   91    * of all JavaBeans<sup><font size="-2">TM</font></sup>
   92    * has been added to the <code>java.beans</code> package.
   93    * Please see {@link java.beans.XMLEncoder}.
   94    *
   95    * @author Rob Davis
   96    * @author Ray Ryan
   97    * @author Scott Violet
   98    */
   99   public class DefaultTreeCellRenderer extends JLabel implements TreeCellRenderer
  100   {
  101       /** Last tree the renderer was painted in. */
  102       private JTree tree;
  103   
  104       /** Is the value currently selected. */
  105       protected boolean selected;
  106       /** True if has focus. */
  107       protected boolean hasFocus;
  108       /** True if draws focus border around icon as well. */
  109       private boolean drawsFocusBorderAroundIcon;
  110       /** If true, a dashed line is drawn as the focus indicator. */
  111       private boolean drawDashedFocusIndicator;
  112   
  113       // If drawDashedFocusIndicator is true, the following are used.
  114       /**
  115        * Background color of the tree.
  116        */
  117       private Color treeBGColor;
  118       /**
  119        * Color to draw the focus indicator in, determined from the background.
  120        * color.
  121        */
  122       private Color focusBGColor;
  123   
  124       // Icons
  125       /** Icon used to show non-leaf nodes that aren't expanded. */
  126       transient protected Icon closedIcon;
  127   
  128       /** Icon used to show leaf nodes. */
  129       transient protected Icon leafIcon;
  130   
  131       /** Icon used to show non-leaf nodes that are expanded. */
  132       transient protected Icon openIcon;
  133   
  134       // Colors
  135       /** Color to use for the foreground for selected nodes. */
  136       protected Color textSelectionColor;
  137   
  138       /** Color to use for the foreground for non-selected nodes. */
  139       protected Color textNonSelectionColor;
  140   
  141       /** Color to use for the background when a node is selected. */
  142       protected Color backgroundSelectionColor;
  143   
  144       /** Color to use for the background when the node isn't selected. */
  145       protected Color backgroundNonSelectionColor;
  146   
  147       /** Color to use for the focus indicator when the node has focus. */
  148       protected Color borderSelectionColor;
  149   
  150       private boolean isDropCell;
  151   
  152       /**
  153        * Set to true after the constructor has run.
  154        */
  155       private boolean inited;
  156   
  157       /**
  158        * Creates a {@code DefaultTreeCellRenderer}. Icons and text color are
  159        * determined from the {@code UIManager}.
  160        */
  161       public DefaultTreeCellRenderer() {
  162           inited = true;
  163       }
  164   
  165       /**
  166        * {@inheritDoc}
  167        *
  168        * @since 1.7
  169        */
  170       public void updateUI() {
  171           super.updateUI();
  172           // To avoid invoking new methods from the constructor, the
  173           // inited field is first checked. If inited is false, the constructor
  174           // has not run and there is no point in checking the value. As
  175           // all look and feels have a non-null value for these properties,
  176           // a null value means the developer has specifically set it to
  177           // null. As such, if the value is null, this does not reset the
  178           // value.
  179           if (!inited || (getLeafIcon() instanceof UIResource)) {
  180               setLeafIcon(UIManager.getIcon("Tree.leafIcon"));
  181           }
  182           if (!inited || (getClosedIcon() instanceof UIResource)) {
  183               setClosedIcon(UIManager.getIcon("Tree.closedIcon"));
  184           }
  185           if (!inited || (getOpenIcon() instanceof UIManager)) {
  186               setOpenIcon(UIManager.getIcon("Tree.openIcon"));
  187           }
  188           if (!inited || (getTextSelectionColor() instanceof UIResource)) {
  189               setTextSelectionColor(
  190                       UIManager.getColor("Tree.selectionForeground"));
  191           }
  192           if (!inited || (getTextNonSelectionColor() instanceof UIResource)) {
  193               setTextNonSelectionColor(
  194                   UIManager.getColor("Tree.textForeground"));
  195           }
  196           if (!inited || (getBackgroundSelectionColor() instanceof UIResource)) {
  197               setBackgroundSelectionColor(
  198                   UIManager.getColor("Tree.selectionBackground"));
  199           }
  200           if (!inited ||
  201                   (getBackgroundNonSelectionColor() instanceof UIResource)) {
  202               setBackgroundNonSelectionColor(
  203                       UIManager.getColor("Tree.textBackground"));
  204           }
  205           if (!inited || (getBorderSelectionColor() instanceof UIResource)) {
  206               setBorderSelectionColor(
  207                   UIManager.getColor("Tree.selectionBorderColor"));
  208           }
  209           Object value = UIManager.get("Tree.drawsFocusBorderAroundIcon");
  210           drawsFocusBorderAroundIcon = (value != null && ((Boolean)value).
  211                                         booleanValue());
  212           value = UIManager.get("Tree.drawDashedFocusIndicator");
  213           drawDashedFocusIndicator = (value != null && ((Boolean)value).
  214                                       booleanValue());
  215       }
  216   
  217   
  218       /**
  219         * Returns the default icon, for the current laf, that is used to
  220         * represent non-leaf nodes that are expanded.
  221         */
  222       public Icon getDefaultOpenIcon() {
  223           return UIManager.getIcon("Tree.openIcon");
  224       }
  225   
  226       /**
  227         * Returns the default icon, for the current laf, that is used to
  228         * represent non-leaf nodes that are not expanded.
  229         */
  230       public Icon getDefaultClosedIcon() {
  231           return UIManager.getIcon("Tree.closedIcon");
  232       }
  233   
  234       /**
  235         * Returns the default icon, for the current laf, that is used to
  236         * represent leaf nodes.
  237         */
  238       public Icon getDefaultLeafIcon() {
  239           return UIManager.getIcon("Tree.leafIcon");
  240       }
  241   
  242       /**
  243         * Sets the icon used to represent non-leaf nodes that are expanded.
  244         */
  245       public void setOpenIcon(Icon newIcon) {
  246           openIcon = newIcon;
  247       }
  248   
  249       /**
  250         * Returns the icon used to represent non-leaf nodes that are expanded.
  251         */
  252       public Icon getOpenIcon() {
  253           return openIcon;
  254       }
  255   
  256       /**
  257         * Sets the icon used to represent non-leaf nodes that are not expanded.
  258         */
  259       public void setClosedIcon(Icon newIcon) {
  260           closedIcon = newIcon;
  261       }
  262   
  263       /**
  264         * Returns the icon used to represent non-leaf nodes that are not
  265         * expanded.
  266         */
  267       public Icon getClosedIcon() {
  268           return closedIcon;
  269       }
  270   
  271       /**
  272         * Sets the icon used to represent leaf nodes.
  273         */
  274       public void setLeafIcon(Icon newIcon) {
  275           leafIcon = newIcon;
  276       }
  277   
  278       /**
  279         * Returns the icon used to represent leaf nodes.
  280         */
  281       public Icon getLeafIcon() {
  282           return leafIcon;
  283       }
  284   
  285       /**
  286         * Sets the color the text is drawn with when the node is selected.
  287         */
  288       public void setTextSelectionColor(Color newColor) {
  289           textSelectionColor = newColor;
  290       }
  291   
  292       /**
  293         * Returns the color the text is drawn with when the node is selected.
  294         */
  295       public Color getTextSelectionColor() {
  296           return textSelectionColor;
  297       }
  298   
  299       /**
  300         * Sets the color the text is drawn with when the node isn't selected.
  301         */
  302       public void setTextNonSelectionColor(Color newColor) {
  303           textNonSelectionColor = newColor;
  304       }
  305   
  306       /**
  307         * Returns the color the text is drawn with when the node isn't selected.
  308         */
  309       public Color getTextNonSelectionColor() {
  310           return textNonSelectionColor;
  311       }
  312   
  313       /**
  314         * Sets the color to use for the background if node is selected.
  315         */
  316       public void setBackgroundSelectionColor(Color newColor) {
  317           backgroundSelectionColor = newColor;
  318       }
  319   
  320   
  321       /**
  322         * Returns the color to use for the background if node is selected.
  323         */
  324       public Color getBackgroundSelectionColor() {
  325           return backgroundSelectionColor;
  326       }
  327   
  328       /**
  329         * Sets the background color to be used for non selected nodes.
  330         */
  331       public void setBackgroundNonSelectionColor(Color newColor) {
  332           backgroundNonSelectionColor = newColor;
  333       }
  334   
  335       /**
  336         * Returns the background color to be used for non selected nodes.
  337         */
  338       public Color getBackgroundNonSelectionColor() {
  339           return backgroundNonSelectionColor;
  340       }
  341   
  342       /**
  343         * Sets the color to use for the border.
  344         */
  345       public void setBorderSelectionColor(Color newColor) {
  346           borderSelectionColor = newColor;
  347       }
  348   
  349       /**
  350         * Returns the color the border is drawn.
  351         */
  352       public Color getBorderSelectionColor() {
  353           return borderSelectionColor;
  354       }
  355   
  356       /**
  357        * Subclassed to map <code>FontUIResource</code>s to null. If
  358        * <code>font</code> is null, or a <code>FontUIResource</code>, this
  359        * has the effect of letting the font of the JTree show
  360        * through. On the other hand, if <code>font</code> is non-null, and not
  361        * a <code>FontUIResource</code>, the font becomes <code>font</code>.
  362        */
  363       public void setFont(Font font) {
  364           if(font instanceof FontUIResource)
  365               font = null;
  366           super.setFont(font);
  367       }
  368   
  369       /**
  370        * Gets the font of this component.
  371        * @return this component's font; if a font has not been set
  372        * for this component, the font of its parent is returned
  373        */
  374       public Font getFont() {
  375           Font font = super.getFont();
  376   
  377           if (font == null && tree != null) {
  378               // Strive to return a non-null value, otherwise the html support
  379               // will typically pick up the wrong font in certain situations.
  380               font = tree.getFont();
  381           }
  382           return font;
  383       }
  384   
  385       /**
  386        * Subclassed to map <code>ColorUIResource</code>s to null. If
  387        * <code>color</code> is null, or a <code>ColorUIResource</code>, this
  388        * has the effect of letting the background color of the JTree show
  389        * through. On the other hand, if <code>color</code> is non-null, and not
  390        * a <code>ColorUIResource</code>, the background becomes
  391        * <code>color</code>.
  392        */
  393       public void setBackground(Color color) {
  394           if(color instanceof ColorUIResource)
  395               color = null;
  396           super.setBackground(color);
  397       }
  398   
  399       /**
  400         * Configures the renderer based on the passed in components.
  401         * The value is set from messaging the tree with
  402         * <code>convertValueToText</code>, which ultimately invokes
  403         * <code>toString</code> on <code>value</code>.
  404         * The foreground color is set based on the selection and the icon
  405         * is set based on the <code>leaf</code> and <code>expanded</code>
  406         * parameters.
  407         */
  408       public Component getTreeCellRendererComponent(JTree tree, Object value,
  409                                                     boolean sel,
  410                                                     boolean expanded,
  411                                                     boolean leaf, int row,
  412                                                     boolean hasFocus) {
  413           String         stringValue = tree.convertValueToText(value, sel,
  414                                             expanded, leaf, row, hasFocus);
  415   
  416           this.tree = tree;
  417           this.hasFocus = hasFocus;
  418           setText(stringValue);
  419   
  420           Color fg = null;
  421           isDropCell = false;
  422   
  423           JTree.DropLocation dropLocation = tree.getDropLocation();
  424           if (dropLocation != null
  425                   && dropLocation.getChildIndex() == -1
  426                   && tree.getRowForPath(dropLocation.getPath()) == row) {
  427   
  428               Color col = UIManager.getColor("Tree.dropCellForeground");
  429               if (col != null) {
  430                   fg = col;
  431               } else {
  432                   fg = getTextSelectionColor();
  433               }
  434   
  435               isDropCell = true;
  436           } else if (sel) {
  437               fg = getTextSelectionColor();
  438           } else {
  439               fg = getTextNonSelectionColor();
  440           }
  441   
  442           setForeground(fg);
  443   
  444           // There needs to be a way to specify disabled icons.
  445           if (!tree.isEnabled()) {
  446               setEnabled(false);
  447               if (leaf) {
  448                   setDisabledIcon(getLeafIcon());
  449               } else if (expanded) {
  450                   setDisabledIcon(getOpenIcon());
  451               } else {
  452                   setDisabledIcon(getClosedIcon());
  453               }
  454           }
  455           else {
  456               setEnabled(true);
  457               if (leaf) {
  458                   setIcon(getLeafIcon());
  459               } else if (expanded) {
  460                   setIcon(getOpenIcon());
  461               } else {
  462                   setIcon(getClosedIcon());
  463               }
  464           }
  465           setComponentOrientation(tree.getComponentOrientation());
  466   
  467           selected = sel;
  468   
  469           return this;
  470       }
  471   
  472       /**
  473         * Paints the value.  The background is filled based on selected.
  474         */
  475       public void paint(Graphics g) {
  476           Color bColor;
  477   
  478           if (isDropCell) {
  479               bColor = UIManager.getColor("Tree.dropCellBackground");
  480               if (bColor == null) {
  481                   bColor = getBackgroundSelectionColor();
  482               }
  483           } else if (selected) {
  484               bColor = getBackgroundSelectionColor();
  485           } else {
  486               bColor = getBackgroundNonSelectionColor();
  487               if (bColor == null) {
  488                   bColor = getBackground();
  489               }
  490           }
  491   
  492           int imageOffset = -1;
  493           if(bColor != null) {
  494               Icon currentI = getIcon();
  495   
  496               imageOffset = getLabelStart();
  497               g.setColor(bColor);
  498               if(getComponentOrientation().isLeftToRight()) {
  499                   g.fillRect(imageOffset, 0, getWidth() - imageOffset,
  500                              getHeight());
  501               } else {
  502                   g.fillRect(0, 0, getWidth() - imageOffset,
  503                              getHeight());
  504               }
  505           }
  506   
  507           if (hasFocus) {
  508               if (drawsFocusBorderAroundIcon) {
  509                   imageOffset = 0;
  510               }
  511               else if (imageOffset == -1) {
  512                   imageOffset = getLabelStart();
  513               }
  514               if(getComponentOrientation().isLeftToRight()) {
  515                   paintFocus(g, imageOffset, 0, getWidth() - imageOffset,
  516                              getHeight(), bColor);
  517               } else {
  518                   paintFocus(g, 0, 0, getWidth() - imageOffset, getHeight(), bColor);
  519               }
  520           }
  521           super.paint(g);
  522       }
  523   
  524       private void paintFocus(Graphics g, int x, int y, int w, int h, Color notColor) {
  525           Color       bsColor = getBorderSelectionColor();
  526   
  527           if (bsColor != null && (selected || !drawDashedFocusIndicator)) {
  528               g.setColor(bsColor);
  529               g.drawRect(x, y, w - 1, h - 1);
  530           }
  531           if (drawDashedFocusIndicator && notColor != null) {
  532               if (treeBGColor != notColor) {
  533                   treeBGColor = notColor;
  534                   focusBGColor = new Color(~notColor.getRGB());
  535               }
  536               g.setColor(focusBGColor);
  537               BasicGraphicsUtils.drawDashedRect(g, x, y, w, h);
  538           }
  539       }
  540   
  541       private int getLabelStart() {
  542           Icon currentI = getIcon();
  543           if(currentI != null && getText() != null) {
  544               return currentI.getIconWidth() + Math.max(0, getIconTextGap() - 1);
  545           }
  546           return 0;
  547       }
  548   
  549       /**
  550        * Overrides <code>JComponent.getPreferredSize</code> to
  551        * return slightly wider preferred size value.
  552        */
  553       public Dimension getPreferredSize() {
  554           Dimension        retDimension = super.getPreferredSize();
  555   
  556           if(retDimension != null)
  557               retDimension = new Dimension(retDimension.width + 3,
  558                                            retDimension.height);
  559           return retDimension;
  560       }
  561   
  562      /**
  563       * Overridden for performance reasons.
  564       * See the <a href="#override">Implementation Note</a>
  565       * for more information.
  566       */
  567       public void validate() {}
  568   
  569      /**
  570       * Overridden for performance reasons.
  571       * See the <a href="#override">Implementation Note</a>
  572       * for more information.
  573       *
  574       * @since 1.5
  575       */
  576       public void invalidate() {}
  577   
  578      /**
  579       * Overridden for performance reasons.
  580       * See the <a href="#override">Implementation Note</a>
  581       * for more information.
  582       */
  583       public void revalidate() {}
  584   
  585      /**
  586       * Overridden for performance reasons.
  587       * See the <a href="#override">Implementation Note</a>
  588       * for more information.
  589       */
  590       public void repaint(long tm, int x, int y, int width, int height) {}
  591   
  592      /**
  593       * Overridden for performance reasons.
  594       * See the <a href="#override">Implementation Note</a>
  595       * for more information.
  596       */
  597       public void repaint(Rectangle r) {}
  598   
  599      /**
  600       * Overridden for performance reasons.
  601       * See the <a href="#override">Implementation Note</a>
  602       * for more information.
  603       *
  604       * @since 1.5
  605       */
  606       public void repaint() {}
  607   
  608      /**
  609       * Overridden for performance reasons.
  610       * See the <a href="#override">Implementation Note</a>
  611       * for more information.
  612       */
  613       protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
  614           // Strings get interned...
  615           if (propertyName == "text"
  616                   || ((propertyName == "font" || propertyName == "foreground")
  617                       && oldValue != newValue
  618                       && getClientProperty(javax.swing.plaf.basic.BasicHTML.propertyKey) != null)) {
  619   
  620               super.firePropertyChange(propertyName, oldValue, newValue);
  621           }
  622       }
  623   
  624      /**
  625       * Overridden for performance reasons.
  626       * See the <a href="#override">Implementation Note</a>
  627       * for more information.
  628       */
  629       public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {}
  630   
  631      /**
  632       * Overridden for performance reasons.
  633       * See the <a href="#override">Implementation Note</a>
  634       * for more information.
  635       */
  636       public void firePropertyChange(String propertyName, char oldValue, char newValue) {}
  637   
  638      /**
  639       * Overridden for performance reasons.
  640       * See the <a href="#override">Implementation Note</a>
  641       * for more information.
  642       */
  643       public void firePropertyChange(String propertyName, short oldValue, short newValue) {}
  644   
  645      /**
  646       * Overridden for performance reasons.
  647       * See the <a href="#override">Implementation Note</a>
  648       * for more information.
  649       */
  650       public void firePropertyChange(String propertyName, int oldValue, int newValue) {}
  651   
  652      /**
  653       * Overridden for performance reasons.
  654       * See the <a href="#override">Implementation Note</a>
  655       * for more information.
  656       */
  657       public void firePropertyChange(String propertyName, long oldValue, long newValue) {}
  658   
  659      /**
  660       * Overridden for performance reasons.
  661       * See the <a href="#override">Implementation Note</a>
  662       * for more information.
  663       */
  664       public void firePropertyChange(String propertyName, float oldValue, float newValue) {}
  665   
  666      /**
  667       * Overridden for performance reasons.
  668       * See the <a href="#override">Implementation Note</a>
  669       * for more information.
  670       */
  671       public void firePropertyChange(String propertyName, double oldValue, double newValue) {}
  672   
  673      /**
  674       * Overridden for performance reasons.
  675       * See the <a href="#override">Implementation Note</a>
  676       * for more information.
  677       */
  678       public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
  679   
  680   }

Save This Page
Home » openjdk-7 » javax » swing » tree » [javadoc | source]