classpath-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cp-patches] FYI: BasicScrollBarUI/MetalScrollBarUI


From: David Gilbert
Subject: [cp-patches] FYI: BasicScrollBarUI/MetalScrollBarUI
Date: Mon, 24 Oct 2005 21:27:48 +0100
User-agent: Mozilla Thunderbird 1.0.6 (X11/20050728)

This patch (committed) fixes some of the visual problems with the JScrollBar component under the MetalLookAndFeel. I've also written some Mauve tests to back up some of the changes, and will commit these shortly:

2005-10-24  David Gilbert  <address@hidden>

        * javax/swing/plaf/basic/BasicScrollBarUI.java
        (ModelListener.stateChanged): changed call to getThumbBounds() to
        updateThumbRect(),
        (PropertyChangeHandler.propertyChange): likewise, plus added handling
        for 'enabled' property,
        (getMaximumSize): return maximum dimension,
        (getThumbBounds): just return field value,
        (getTrackBounds): just return field value,
        (installUI): switch order of calls to installDefaults() and
        installComponents(),
        (layoutHScrollBar): reimplemented using new updateThumbRect() method,
        (layoutVScrollBar): likewise,
        (updateThumbRect): new method,
        * javax/swing/plaf/metal/MetalLookAndFeel.java
        (initComponentDefaults): added 'ScrollBar.width' default,
        * javax/swing/plaf/metal/MetalScrollBarUI.java
        (MIN_THUMB_SIZE): changed value,
        (MIN_THUMB_SIZE_FREE_STANDING): new field,
        (isFreeStanding): set default to true,
        (scrollBarShadowColor): new field,
        (installDefaults): initialise scrollBarShadowColor,
        (createDecreaseButton): retain reference in decreaseButton field,
        (createIncreaseButton): retain reference in increaseButton field,
        (paintTrackHorizontal): use scrollBarShadowColor, add special handling
        for free standing scroll bar in disabled state,
        (paintTrackVertical): likewise,
        (paintThumb): separate horizontal and vertical cases,
        (paintThumbHorizontal): new method,
        (paintThumbVertical): new method,
        (getMinimumThumbSize): return different size depending on whether or
        not the scroll bar is free standing,
        * javax/swing/plaf/metal/MetalScrollButton.java
        (paintNorthBorderFreeStanding): modified drawing.

Regards,

Dave
Index: javax/swing/plaf/basic/BasicScrollBarUI.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java,v
retrieving revision 1.27
diff -u -r1.27 BasicScrollBarUI.java
--- javax/swing/plaf/basic/BasicScrollBarUI.java        18 Oct 2005 14:02:16 
-0000      1.27
+++ javax/swing/plaf/basic/BasicScrollBarUI.java        24 Oct 2005 20:24:20 
-0000
@@ -128,9 +128,8 @@
      */
     public void stateChanged(ChangeEvent e)
     {
-      //       System.err.println(this + ".stateChanged()");
       calculatePreferredSize();
-      getThumbBounds();
+      updateThumbRect();
       scrollbar.repaint();
     }
   }
@@ -151,7 +150,7 @@
         {
           ((BoundedRangeModel) 
e.getOldValue()).removeChangeListener(modelListener);
           scrollbar.getModel().addChangeListener(modelListener);
-          getThumbBounds();
+          updateThumbRect();
         }
       else if (e.getPropertyName().equals("orientation"))
         {
@@ -173,6 +172,14 @@
           decrButton.addMouseListener(buttonListener);
           calculatePreferredSize();
         }
+      else if (e.getPropertyName().equals("enabled"))
+        {
+          Boolean b = (Boolean) e.getNewValue();
+          if (incrButton != null)
+            incrButton.setEnabled(b.booleanValue());
+          if (decrButton != null)
+            decrButton.setEnabled(b.booleanValue());
+        }
     }
   }
 
@@ -625,7 +632,7 @@
    */
   public Dimension getMaximumSize(JComponent c)
   {
-    return getPreferredSize(c);
+    return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
   }
 
   /**
@@ -667,7 +674,6 @@
    */
   void calculatePreferredSize()
   {
-    // System.err.println(this + ".calculatePreferredSize()");
     int height;
     int width;
     height = width = 0;
@@ -730,48 +736,6 @@
    */
   protected Rectangle getThumbBounds()
   {
-    int max = scrollbar.getMaximum();
-    int min = scrollbar.getMinimum();
-    int value = scrollbar.getValue();
-    int extent = scrollbar.getVisibleAmount();
-
-    // System.err.println(this + ".getThumbBounds()");
-    if (max == min)
-      {
-       thumbRect.x = trackRect.x;
-       thumbRect.y = trackRect.y;
-       if (scrollbar.getOrientation() == HORIZONTAL)
-         {
-           thumbRect.width = getMinimumThumbSize().width;
-           thumbRect.height = trackRect.height;
-         }
-       else
-         {
-           thumbRect.width = trackRect.width;
-           thumbRect.height = getMinimumThumbSize().height;
-         }
-       return thumbRect;
-      }
-
-    if (scrollbar.getOrientation() == HORIZONTAL)
-      {
-       thumbRect.x = trackRect.x;
-       thumbRect.x += (value - min) * trackRect.width / (max - min);
-       thumbRect.y = trackRect.y;
-
-       thumbRect.width = Math.max(extent * trackRect.width / (max - min),
-                                   getMinimumThumbSize().width);
-       thumbRect.height = trackRect.height;
-      }
-    else
-      {
-       thumbRect.x = trackRect.x;
-       thumbRect.y = trackRect.y + value * trackRect.height / (max - min);
-
-       thumbRect.width = trackRect.width;
-       thumbRect.height = Math.max(extent * trackRect.height / (max - min),
-                                    getMinimumThumbSize().height);
-      }
     return thumbRect;
   }
 
@@ -783,22 +747,6 @@
    */
   protected Rectangle getTrackBounds()
   {
-    SwingUtilities.calculateInnerArea(scrollbar, trackRect);
-
-    if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
-      {
-       trackRect.width -= incrButton.getPreferredSize().getWidth();
-       trackRect.width -= decrButton.getPreferredSize().getWidth();
-
-       trackRect.x += decrButton.getPreferredSize().getWidth();
-      }
-    else
-      {
-       trackRect.height -= incrButton.getPreferredSize().getHeight();
-       trackRect.height -= decrButton.getPreferredSize().getHeight();
-
-       trackRect.y += incrButton.getPreferredSize().getHeight();
-      }
     return trackRect;
   }
 
@@ -896,8 +844,8 @@
 
        scrollTimer = new Timer(300, null);
 
+        installDefaults();
        installComponents();
-       installDefaults();
        configureScrollBarColors();
        installListeners();
 
@@ -928,17 +876,20 @@
    */
   protected void layoutHScrollbar(JScrollBar sb)
   {
-    // All we have to do is layout the 2 buttons?
     Rectangle vr = new Rectangle();
     SwingUtilities.calculateInnerArea(scrollbar, vr);
 
-    // Update the rectangles.
-    getTrackBounds();
-    getThumbBounds();
-
     Dimension incrDims = incrButton.getPreferredSize();
     Dimension decrDims = decrButton.getPreferredSize();
+    
+    // calculate and update the track bounds
+    SwingUtilities.calculateInnerArea(scrollbar, trackRect);
+    trackRect.width -= incrDims.getWidth();
+    trackRect.width -= decrDims.getWidth();
+    trackRect.x += decrDims.getWidth();
 
+    updateThumbRect();
+    
     decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height);
     incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width,
                          trackRect.height);
@@ -954,18 +905,74 @@
     Rectangle vr = new Rectangle();
     SwingUtilities.calculateInnerArea(scrollbar, vr);
 
-    // Update rectangles
-    getTrackBounds();
-    getThumbBounds();
-
     Dimension incrDims = incrButton.getPreferredSize();
     Dimension decrDims = decrButton.getPreferredSize();
+    
+    // Update rectangles
+    SwingUtilities.calculateInnerArea(scrollbar, trackRect);
+    trackRect.height -= incrDims.getHeight();
+    trackRect.height -= decrDims.getHeight();
+    trackRect.y += decrDims.getHeight();
+    
+    updateThumbRect();
 
     decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height);
     incrButton.setBounds(vr.x, trackRect.y + trackRect.height,
                          trackRect.width, incrDims.height);
   }
 
+  /**
+   * Updates the thumb rect.
+   */
+  void updateThumbRect()
+  {
+    int max = scrollbar.getMaximum();
+    int min = scrollbar.getMinimum();
+    int value = scrollbar.getValue();
+    int extent = scrollbar.getVisibleAmount();
+    if (max - extent <= min)
+      {
+        if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL)
+          {
+            thumbRect.x = trackRect.x;
+            thumbRect.y = trackRect.y;
+            thumbRect.width = getMinimumThumbSize().width;
+            thumbRect.height = trackRect.height;
+          }
+        else
+          {
+            thumbRect.x = trackRect.x;
+            thumbRect.y = trackRect.y;
+            thumbRect.width = trackRect.width;
+            thumbRect.height = getMinimumThumbSize().height;
+          }
+      }
+    else
+      {
+        if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL)
+          {
+            thumbRect.x = trackRect.x;
+            thumbRect.width = Math.max(extent * trackRect.width / (max - min),
+                getMinimumThumbSize().width);
+            int availableWidth = trackRect.width - thumbRect.width;
+            thumbRect.x += (value - min) * availableWidth / (max - min - 
extent);
+            thumbRect.y = trackRect.y;
+            thumbRect.height = trackRect.height;
+          }
+        else
+          {
+            thumbRect.x = trackRect.x;
+            thumbRect.height = Math.max(extent * trackRect.height / (max - 
min),
+                    getMinimumThumbSize().height);
+            int availableHeight = trackRect.height - thumbRect.height;
+            thumbRect.y = trackRect.y 
+              + (value - min) * availableHeight / (max - min - extent);
+            thumbRect.width = trackRect.width;
+          }
+      }
+
+  }
+  
   /**
    * This method returns the minimum size required for the layout.
    *
Index: javax/swing/plaf/metal/MetalLookAndFeel.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java,v
retrieving revision 1.67
diff -u -r1.67 MetalLookAndFeel.java
--- javax/swing/plaf/metal/MetalLookAndFeel.java        19 Oct 2005 14:54:55 
-0000      1.67
+++ javax/swing/plaf/metal/MetalLookAndFeel.java        24 Oct 2005 20:24:22 
-0000
@@ -1016,6 +1016,7 @@
       "ScrollBar.thumbShadow", getPrimaryControlDarkShadow(),
       "ScrollBar.track", getControl(),
       "ScrollBar.trackHighlight", getControlDarkShadow(),
+      "ScrollBar.width", new Integer(17),
 
       "ScrollPane.background", getControl(),
       "ScrollPane.border", new MetalBorders.ScrollPaneBorder(),
Index: javax/swing/plaf/metal/MetalScrollBarUI.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java,v
retrieving revision 1.9
diff -u -r1.9 MetalScrollBarUI.java
--- javax/swing/plaf/metal/MetalScrollBarUI.java        19 Oct 2005 13:46:02 
-0000      1.9
+++ javax/swing/plaf/metal/MetalScrollBarUI.java        24 Oct 2005 20:24:23 
-0000
@@ -103,9 +103,13 @@
   /** The name for the 'free standing' property. */
   public static final String FREE_STANDING_PROP = "JScrollBar.isFreeStanding";
 
-  /** The minimum thumb size */
-  private static final Dimension MIN_THUMB_SIZE = new Dimension(17, 17);
+  /** The minimum thumb size for a scroll bar that is not free standing. */
+  private static final Dimension MIN_THUMB_SIZE = new Dimension(15, 15);
 
+  /** The minimum thumb size for a scroll bar that is free standing. */
+  private static final Dimension MIN_THUMB_SIZE_FREE_STANDING 
+    = new Dimension(17, 17);
+  
   /** The button that increases the value in the scroll bar. */
   protected MetalScrollButton increaseButton;
   
@@ -121,7 +125,10 @@
    * scroll bar which is not free standing has borders missing from one
    * side, and relies on being part of another container with its own borders
    * to look right visually. */
-  protected boolean isFreeStanding;
+  protected boolean isFreeStanding = true;
+  
+  /** The color for the scroll bar shadow. */
+  Color scrollBarShadowColor;
   
   /**
    * Constructs a new instance of MetalScrollBarUI.
@@ -154,6 +161,7 @@
     // that we can do this).
     Boolean prop = (Boolean) scrollbar.getClientProperty(FREE_STANDING_PROP);
     isFreeStanding = (prop == null ? true : prop.booleanValue());
+    scrollBarShadowColor = UIManager.getColor("ScrollBar.shadow");
     super.installDefaults();
   }
     
@@ -183,7 +191,9 @@
   {
     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
     scrollBarWidth = defaults.getInt("ScrollBar.width");
-    return new MetalScrollButton(orientation, scrollBarWidth, isFreeStanding);
+    decreaseButton = new MetalScrollButton(orientation, scrollBarWidth, 
+            isFreeStanding);
+    return decreaseButton;
   }
 
   /**
@@ -199,7 +209,9 @@
   {
     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
     scrollBarWidth = defaults.getInt("ScrollBar.width");
-    return new MetalScrollButton(orientation, scrollBarWidth, isFreeStanding);
+    increaseButton = new MetalScrollButton(orientation, scrollBarWidth, 
+            isFreeStanding);
+    return increaseButton;
   }
   
   /**
@@ -243,7 +255,7 @@
         g.drawLine(x, y, x + w - 1, y);
         g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
         
-        g.setColor(MetalLookAndFeel.getControlShadow());
+        g.setColor(scrollBarShadowColor);
         g.drawLine(x + 1, y + 1, x + 1, y + h - 1);
         g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
         
@@ -251,14 +263,21 @@
           {
             g.setColor(MetalLookAndFeel.getControlDarkShadow());
             g.drawLine(x, y + h - 2, x + w - 1, y + h - 2);
-            g.setColor(MetalLookAndFeel.getControlShadow());
+            g.setColor(scrollBarShadowColor);
             g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
           }
       }
     else
       {
         g.setColor(MetalLookAndFeel.getControlDisabled());
-        g.drawRect(x, y, w - 1, h - 1);
+        if (isFreeStanding)
+          g.drawRect(x, y, w - 1, h - 1);
+        else
+          {
+            g.drawLine(x, y, x + w - 1, y);
+            g.drawLine(x, y, x, y + h - 1);
+            g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+          }
       }
   }
     
@@ -272,7 +291,7 @@
    * @param w  the width for the track bounds.
    * @param h  the height for the track bounds.
    */
-  protected void paintTrackVertical(Graphics g, JComponent c, 
+  private void paintTrackVertical(Graphics g, JComponent c, 
       int x, int y, int w, int h)
   {
     if (c.isEnabled())
@@ -282,10 +301,9 @@
         g.drawLine(x, y, x + w - 1, y);
         g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
         
-        g.setColor(MetalLookAndFeel.getControlShadow());
+        g.setColor(scrollBarShadowColor);
         g.drawLine(x + 1, y + 1, x + w - 1, y + 1);
         g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
-        g.drawLine(x + 1, y + h - 2, x + w - 1, y + h - 2);
         
         if (isFreeStanding) 
           {
@@ -298,7 +316,14 @@
     else
       {
         g.setColor(MetalLookAndFeel.getControlDisabled());
-        g.drawRect(x, y, w - 1, h - 1);
+        if (isFreeStanding)
+          g.drawRect(x, y, w - 1, h - 1);
+        else
+          {
+            g.drawLine(x, y, x + w - 1, y);
+            g.drawLine(x, y, x, y + h - 1);
+            g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+          }
       }
   }
 
@@ -314,46 +339,108 @@
     // a disabled scrollbar has no thumb in the metal look and feel
     if (!c.isEnabled())
       return;
+    if (scrollbar.getOrientation() == HORIZONTAL)
+      paintThumbHorizontal(g, c, thumbBounds);
+    else 
+      paintThumbVertical(g, c, thumbBounds);
+
+    // draw the pattern
+    MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3,
+            thumbBounds.width - 6, thumbBounds.height - 6,
+            thumbHighlightColor, thumbLightShadowColor);
+  }
+
+  private void paintThumbHorizontal(Graphics g, JComponent c, 
+          Rectangle thumbBounds) 
+  {
+    int x = thumbBounds.x;
+    int y = thumbBounds.y;
+    int w = thumbBounds.width;
+    int h = thumbBounds.height;
     
     // first we fill the background
     g.setColor(thumbColor);
-    g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width,
-               thumbBounds.height);
-
-    // draw the outer dark line
-    int hAdj = 1;
-    int wAdj = 1;
-    if (scrollbar.getOrientation() == HORIZONTAL)
-      hAdj++;
+    if (isFreeStanding)
+      g.fillRect(x, y, w, h - 1);
     else
-      wAdj++;
+      g.fillRect(x, y, w, h);
     
-    g.setColor(new Color(102, 102, 153));
-    g.drawRect(thumbBounds.x, thumbBounds.y, thumbBounds.width - wAdj,
-               thumbBounds.height - hAdj);
-
-    // draw the inner light line
+    // then draw the dark box
+    g.setColor(thumbLightShadowColor);
+    if (isFreeStanding)
+      g.drawRect(x, y, w - 1, h - 2);
+    else
+      {
+        g.drawLine(x, y, x + w - 1, y);
+        g.drawLine(x, y, x, y + h - 1);
+        g.drawLine(x + w - 1, y, x + w - 1, y + h -1);
+      }
+    
+    // then the highlight
     g.setColor(thumbHighlightColor);
-    g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1,
-               thumbBounds.x + thumbBounds.width - 2,
-               thumbBounds.y + 1);
-    g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1,
-               thumbBounds.x + 1,
-               thumbBounds.y + thumbBounds.height - 2);
-
+    if (isFreeStanding)
+      {
+        g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+        g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+      }
+    else
+      {
+        g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+        g.drawLine(x + 1, y + 1, x + 1, y + h - 1);
+      }
+    
     // draw the shadow line
     UIDefaults def = UIManager.getLookAndFeelDefaults();
     g.setColor(def.getColor("ScrollBar.shadow"));
-    g.drawLine(thumbBounds.x + 1, thumbBounds.y + thumbBounds.height,
-               thumbBounds.x + thumbBounds.width,
-               thumbBounds.y + thumbBounds.height);
+    g.drawLine(x + w, y + 1, x + w, y + h - 1);
 
-    // draw the pattern
-    MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3,
-                                thumbBounds.width - 6, thumbBounds.height - 6,
-                                thumbHighlightColor, new Color(102, 102, 153));
   }
-
+  
+  private void paintThumbVertical(Graphics g, JComponent c, 
+          Rectangle thumbBounds)
+  {
+    int x = thumbBounds.x;
+    int y = thumbBounds.y;
+    int w = thumbBounds.width;
+    int h = thumbBounds.height;
+    
+    // first we fill the background
+    g.setColor(thumbColor);
+    if (isFreeStanding)
+      g.fillRect(x, y, w - 1, h);
+    else
+      g.fillRect(x, y, w, h);
+     
+    // then draw the dark box
+    g.setColor(thumbLightShadowColor);
+    if (isFreeStanding)
+      g.drawRect(x, y, w - 2, h - 1);
+    else
+      {
+        g.drawLine(x, y, x + w - 1, y);
+        g.drawLine(x, y, x, y + h - 1);
+        g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+      }
+    
+    // then the highlight
+    g.setColor(thumbHighlightColor);
+    if (isFreeStanding)
+      {
+        g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+        g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+      }
+    else
+      {
+        g.drawLine(x + 1, y + 1, x + w - 1, y + 1);
+        g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+      }
+    
+    // draw the shadow line
+    UIDefaults def = UIManager.getLookAndFeelDefaults();
+    g.setColor(def.getColor("ScrollBar.shadow"));
+    g.drawLine(x + 1, y + h, x + w - 2, y + h);
+  }
+  
   /**
    * This method returns the minimum thumb size.
    *
@@ -361,7 +448,10 @@
    */
   protected Dimension getMinimumThumbSize()
   {
-    return MIN_THUMB_SIZE;
+    if (isFreeStanding)
+      return MIN_THUMB_SIZE_FREE_STANDING;
+    else
+      return MIN_THUMB_SIZE;
   }
   
 }
Index: javax/swing/plaf/metal/MetalScrollButton.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/javax/swing/plaf/metal/MetalScrollButton.java,v
retrieving revision 1.1
diff -u -r1.1 MetalScrollButton.java
--- javax/swing/plaf/metal/MetalScrollButton.java       8 Sep 2005 08:58:48 
-0000       1.1
+++ javax/swing/plaf/metal/MetalScrollButton.java       24 Oct 2005 20:24:23 
-0000
@@ -38,6 +38,7 @@
 
 package javax.swing.plaf.metal;
 
+import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.Graphics;
 import java.awt.Rectangle;
@@ -206,13 +207,13 @@
         g.drawLine(w - 2, 2, w - 2, h - 1);
         
         g.setColor(MetalLookAndFeel.getControlHighlight());
-        g.drawLine(1, 1, 1, h - 1);
-        g.drawLine(1, 1, w - 1, 1);
+        g.drawLine(1, 1, 1, h - 2);
+        g.drawLine(1, 1, w - 3, 1);
         g.drawLine(w - 1, 1, w - 1, h - 1);
       
         g.setColor(MetalLookAndFeel.getControl());
         g.drawLine(1, h - 1, 1, h - 1);
-        g.drawLine(w - 1, 1, w - 1, 1);
+        g.drawLine(w - 2, 1, w - 2, 1);
       }
     else
       {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]