This fixes painting of selected cells in a JTree and should be slightly faster too.
2006-09-28 Roman Kennke <[EMAIL PROTECTED]> * javax/swing/tree/DefaultTreeCellRenderer.java (DefaultTreeCellRenderer): Fetch drawsFocusBorderAroundIcon property from UIManager. (paint): Rewritten to use super's implementation and only paint background and focus indicator before. (paintFocus): New helper method. (getXOffset): New helper method. /Roman
Index: javax/swing/tree/DefaultTreeCellRenderer.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/tree/DefaultTreeCellRenderer.java,v retrieving revision 1.27 diff -u -1 -5 -r1.27 DefaultTreeCellRenderer.java --- javax/swing/tree/DefaultTreeCellRenderer.java 16 Aug 2006 19:28:49 -0000 1.27 +++ javax/swing/tree/DefaultTreeCellRenderer.java 28 Sep 2006 10:28:36 -0000 @@ -65,31 +65,31 @@ extends JLabel implements TreeCellRenderer { /** * A flag indicating the current selection status. */ protected boolean selected; /** * A flag indicating the current focus status. */ protected boolean hasFocus; /** - * drawsFocusBorderAroundIcon // FIXME: is this used? + * Indicates if the focus border is also drawn around the icon. */ private boolean drawsFocusBorderAroundIcon; /** * The icon used to represent non-leaf nodes that are closed. * * @see #setClosedIcon(Icon) */ protected transient Icon closedIcon; /** * The icon used to represent leaf nodes. * * @see #setLeafIcon(Icon) */ @@ -140,30 +140,32 @@ /** * Creates a new tree cell renderer with defaults appropriate for the * current [EMAIL PROTECTED] LookAndFeel}. */ public DefaultTreeCellRenderer() { setLeafIcon(getDefaultLeafIcon()); setOpenIcon(getDefaultOpenIcon()); setClosedIcon(getDefaultClosedIcon()); setTextNonSelectionColor(UIManager.getColor("Tree.textForeground")); setTextSelectionColor(UIManager.getColor("Tree.selectionForeground")); setBackgroundNonSelectionColor(UIManager.getColor("Tree.textBackground")); setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground")); setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor")); + Object val = UIManager.get("Tree.drawsFocusBorderAroundIcon"); + drawsFocusBorderAroundIcon = val != null && ((Boolean) val).booleanValue(); } /** * Returns the default icon for non-leaf tree cells that are open (expanded). * The icon is fetched from the defaults table for the current * [EMAIL PROTECTED] LookAndFeel} using the key <code>Tree.openIcon</code>. * * @return The default icon. */ public Icon getDefaultOpenIcon() { return UIManager.getIcon("Tree.openIcon"); } /** @@ -487,72 +489,90 @@ * * @see #setFont(Font) */ public Font getFont() { return super.getFont(); } /** * Paints the value. The background is filled based on selected. * * @param g the graphics device. */ public void paint(Graphics g) { - // paint background - Rectangle vr = new Rectangle(); - Rectangle ir = new Rectangle(); - Rectangle tr = new Rectangle(); - - Insets insets = new Insets(0, 0, 0, 0); - Border border = UIManager.getBorder("Tree.selectionBorder"); - if (border != null) - insets = border.getBorderInsets(this); - - FontMetrics fm = getToolkit().getFontMetrics(getFont()); - SwingUtilities.layoutCompoundLabel((JLabel) this, fm, getText(), - getIcon(), getVerticalAlignment(), - getHorizontalAlignment(), - getVerticalTextPosition(), - getHorizontalTextPosition(), vr, ir, tr, - getIconTextGap()); - - // Reusing one rectangle. - Rectangle bounds = getBounds(ir); - - bounds.x = tr.x - insets.left; - bounds.width = tr.width + insets.left + insets.right; - - g.setColor(super.getBackground()); - g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); + // Determine background color. + Color bgColor; + if (selected) + bgColor = getBackgroundSelectionColor(); + else + { + bgColor = getBackgroundNonSelectionColor(); + if (bgColor == null) + bgColor = getBackground(); + } + // Paint background. + int xOffset = -1; + if (bgColor != null) + { + Icon i = getIcon(); + xOffset = getXOffset(); + g.setColor(bgColor); + g.fillRect(xOffset, 0, getWidth() - xOffset, getHeight()); + } - super.paint(g); - - // Paint the border of the focused element only (lead selection) if (hasFocus) { - Color b = getBorderSelectionColor(); - if (b != null) - { - g.setColor(b); - g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height - 1); - } + if (drawsFocusBorderAroundIcon) + xOffset = 0; + else if (xOffset == -1) + xOffset = getXOffset(); + paintFocus(g, xOffset, 0, getWidth() - xOffset, getHeight()); + } + super.paint(g); + } + + /** + * Paints the focus indicator. + */ + private void paintFocus(Graphics g, int x, int y, int w, int h) + { + Color col = getBorderSelectionColor(); + if (col != null) + { + g.setColor(col); + g.drawRect(x, y, w - 1, h - 1); } } /** + * Determines the X offset of the label that is caused by + * the icon. + * + * @return the X offset of the label + */ + private int getXOffset() + { + Icon i = getIcon(); + int offs = 0; + if (i != null && getText() != null) + offs = i.getIconWidth() + Math.max(0, getIconTextGap() - 1); + return offs; + } + + /** * Returns the preferred size of the cell. * * @return The preferred size of the cell. */ public Dimension getPreferredSize() { Dimension size = super.getPreferredSize(); size.width += 3; return size; } /** * For performance reasons, this method is overridden to do nothing. */ public void validate()