summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java')
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java430
1 files changed, 382 insertions, 48 deletions
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
index 526dfb50ae2..9602ade9947 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
@@ -38,30 +38,106 @@ exception statement from your version. */
package javax.swing.plaf.metal;
+import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
-import java.util.HashMap;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.swing.JButton;
import javax.swing.JComponent;
+import javax.swing.JScrollBar;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicScrollBarUI;
-public class MetalScrollBarUI
- extends BasicScrollBarUI
+/**
+ * A UI delegate for the {@link JScrollBar} component.
+ */
+public class MetalScrollBarUI extends BasicScrollBarUI
{
+
+ /**
+ * A property change handler for the UI delegate that monitors for
+ * changes to the "JScrollBar.isFreeStanding" property, and updates
+ * the buttons and track rendering as appropriate.
+ */
+ class MetalScrollBarPropertyChangeHandler
+ extends BasicScrollBarUI.PropertyChangeHandler
+ {
+ /**
+ * Creates a new handler.
+ *
+ * @see #createPropertyChangeListener()
+ */
+ public MetalScrollBarPropertyChangeHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles a property change event. If the event name is
+ * <code>JSlider.isFreeStanding</code>, this method updates the
+ * delegate, otherwise the event is passed up to the super class.
+ *
+ * @param e the property change event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(FREE_STANDING_PROP))
+ {
+ Boolean prop = (Boolean) e.getNewValue();
+ isFreeStanding = (prop == null ? true : prop.booleanValue());
+ if (increaseButton != null)
+ increaseButton.setFreeStanding(isFreeStanding);
+ if (decreaseButton != null)
+ decreaseButton.setFreeStanding(isFreeStanding);
+ }
+ else
+ super.propertyChange(e);
+ }
+ }
+
+ /** 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(18, 18);
-
- // FIXME: maybe replace by a Map of instances when this becomes stateful
- /** The shared UI instance for JScrollBars. */
- private static HashMap instances = null;
+ /** 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;
+
+ /** The button that decreases the value in the scroll bar. */
+ protected MetalScrollButton decreaseButton;
+
+ /**
+ * The scroll bar width.
+ */
+ protected int scrollBarWidth;
+
+ /**
+ * A flag that indicates whether the scroll bar is "free standing", which
+ * means it has complete borders and can be used anywhere in the UI. A
+ * 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 = true;
+
+ /**
+ * The color for the scroll bar shadow (this is read from the UIDefaults in
+ * the installDefaults() method).
+ */
+ Color scrollBarShadowColor;
+
/**
- * Constructs a new instance of MetalScrollBarUI.
+ * Constructs a new instance of <code>MetalScrollBarUI</code>, with no
+ * specific initialisation.
*/
public MetalScrollBarUI()
{
@@ -69,28 +145,192 @@ public class MetalScrollBarUI
}
/**
- * Returns an instance of MetalScrollBarUI.
+ * Returns a new instance of <code>MetalScrollBarUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalScrollBarUI
+ * @return An instance of MetalScrollBarUI
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
+ return new MetalScrollBarUI();
+ }
+
+ /**
+ * Installs the defaults.
+ */
+ protected void installDefaults()
+ {
+ // need to initialise isFreeStanding before calling the super class,
+ // so that the value is set when createIncreaseButton() and
+ // createDecreaseButton() are called (unless there is somewhere earlier
+ // 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();
+ }
+
+ /**
+ * Creates a property change listener for the delegate to use. This
+ * overrides the method to provide a custom listener for the
+ * {@link MetalLookAndFeel} that can handle the
+ * <code>JScrollBar.isFreeStanding</code> property.
+ *
+ * @return A property change listener.
+ */
+ protected PropertyChangeListener createPropertyChangeListener()
+ {
+ return new MetalScrollBarPropertyChangeHandler();
+ }
+
+ /**
+ * Creates a new button to use as the control at the lower end of the
+ * {@link JScrollBar}.
+ *
+ * @param orientation the orientation of the button ({@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} or {@link #WEST}).
+ *
+ * @return The button.
+ */
+ protected JButton createDecreaseButton(int orientation)
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ scrollBarWidth = defaults.getInt("ScrollBar.width");
+ decreaseButton = new MetalScrollButton(orientation, scrollBarWidth,
+ isFreeStanding);
+ return decreaseButton;
+ }
- Object o = instances.get(component);
- MetalScrollBarUI instance;
- if (o == null)
+ /**
+ * Creates a new button to use as the control at the upper end of the
+ * {@link JScrollBar}.
+ *
+ * @param orientation the orientation of the button ({@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} or {@link #WEST}).
+ *
+ * @return The button.
+ */
+ protected JButton createIncreaseButton(int orientation)
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ scrollBarWidth = defaults.getInt("ScrollBar.width");
+ increaseButton = new MetalScrollButton(orientation, scrollBarWidth,
+ isFreeStanding);
+ return increaseButton;
+ }
+
+ /**
+ * Paints the track for the scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param trackBounds the track bounds.
+ */
+ protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
+ {
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width,
+ trackBounds.height);
+ if (scrollbar.getOrientation() == HORIZONTAL)
+ paintTrackHorizontal(g, c, trackBounds.x, trackBounds.y,
+ trackBounds.width, trackBounds.height);
+ else
+ paintTrackVertical(g, c, trackBounds.x, trackBounds.y,
+ trackBounds.width, trackBounds.height);
+
+ }
+
+ /**
+ * Paints the track for a horizontal scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param x the x-coordinate for the track bounds.
+ * @param y the y-coordinate for the track bounds.
+ * @param w the width for the track bounds.
+ * @param h the height for the track bounds.
+ */
+ private void paintTrackHorizontal(Graphics g, JComponent c,
+ int x, int y, int w, int h)
+ {
+ if (c.isEnabled())
{
- instance = new MetalScrollBarUI();
- instances.put(component, instance);
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+
+ 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);
+
+ if (isFreeStanding)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y + h - 2, x + w - 1, y + h - 2);
+ g.setColor(scrollBarShadowColor);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
}
else
- instance = (MetalScrollBarUI) o;
-
- return instance;
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ 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);
+ }
+ }
+ }
+
+ /**
+ * Paints the track for a vertical scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param x the x-coordinate for the track bounds.
+ * @param y the y-coordinate for the track bounds.
+ * @param w the width for the track bounds.
+ * @param h the height for the track bounds.
+ */
+ private void paintTrackVertical(Graphics g, JComponent c,
+ int x, int y, int w, int h)
+ {
+ if (c.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+
+ 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);
+
+ if (isFreeStanding)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x + w - 2, y, x + w - 2, y + h - 1);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ }
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ 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);
+ }
+ }
}
/**
@@ -102,45 +342,139 @@ public class MetalScrollBarUI
*/
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
{
- // first we fill the background
- g.setColor(thumbColor);
- g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width,
- thumbBounds.height);
+ // 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 outer dark line
- g.setColor(thumbDarkShadowColor);
- g.drawRect(thumbBounds.x, thumbBounds.y, thumbBounds.width - 1,
- thumbBounds.height - 1);
+ // draw the pattern
+ MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3,
+ thumbBounds.width - 6, thumbBounds.height - 6,
+ thumbHighlightColor, thumbLightShadowColor);
+ }
- // draw the inner light line
+ /**
+ * Paints the thumb for a horizontal scroll bar.
+ *
+ * @param g the graphics device.
+ * @param c the scroll bar component.
+ * @param thumbBounds the thumb bounds.
+ */
+ 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);
+ if (isFreeStanding)
+ g.fillRect(x, y, w, h - 1);
+ else
+ g.fillRect(x, y, w, h);
+
+ // 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(g, thumbBounds.x + 3, thumbBounds.y + 3,
- thumbBounds.width - 6, thumbBounds.height - 6,
- thumbHighlightColor, thumbDarkShadowColor);
}
-
+
/**
- * This method returns the minimum thumb size.
+ * Paints the thumb for a vertical scroll bar.
+ *
+ * @param g the graphics device.
+ * @param c the scroll bar component.
+ * @param thumbBounds the thumb bounds.
+ */
+ 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);
+ }
+
+ /**
+ * Returns the minimum thumb size. For a free standing scroll bar the
+ * minimum size is <code>17 x 17</code> pixels, whereas for a non free
+ * standing scroll bar the minimum size is <code>15 x 15</code> pixels.
*
* @return The minimum thumb size.
*/
protected Dimension getMinimumThumbSize()
{
- return MIN_THUMB_SIZE;
+ if (isFreeStanding)
+ return MIN_THUMB_SIZE_FREE_STANDING;
+ else
+ return MIN_THUMB_SIZE;
}
+
}
+
OpenPOWER on IntegriCloud