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()

Reply via email to