Logo Search packages:      
Sourcecode: classpath version File versions

BasicScrollBarUI.java

/* BasicScrollBarUI.java --
   Copyright (C) 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.plaf.basic;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.BoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JScrollBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ScrollBarUI;

/**
 * The Basic Look and Feel UI delegate for JScrollBar.
 */
00076 public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
                                                             SwingConstants
{
  /**
   * A helper class that listens to the two JButtons on each end of the
   * JScrollBar.
   */
00083   protected class ArrowButtonListener extends MouseAdapter
  {
    /**
     * Move the thumb in the direction specified by the  button's arrow. If
     * this button is held down, then it should keep moving the thumb.
     *
     * @param e The MouseEvent fired by the JButton.
     */
00091     public void mousePressed(MouseEvent e)
    {
      scrollTimer.stop();
      scrollListener.setScrollByBlock(false);
      if (e.getSource() == incrButton)
      scrollListener.setDirection(POSITIVE_SCROLL);
      else
      scrollListener.setDirection(NEGATIVE_SCROLL);
      scrollTimer.start();
    }

    /**
     * Stops the thumb when the JButton is released.
     *
     * @param e The MouseEvent fired by the JButton.
     */
00107     public void mouseReleased(MouseEvent e)
    {
      scrollTimer.stop();
    }
  }

  /**
   * A helper class that listens to the ScrollBar's model for ChangeEvents.
   */
00116   protected class ModelListener implements ChangeListener
  {
    /**
     * Called when the model changes.
     *
     * @param e The ChangeEvent fired by the model.
     */
00123     public void stateChanged(ChangeEvent e)
    {
      //       System.err.println(this + ".stateChanged()");
      calculatePreferredSize();
      layoutContainer(scrollbar);
      getThumbBounds();
      scrollbar.repaint();
    }
  }

  /**
   * A helper class that listens to the ScrollBar's properties.
   */
00136   public class PropertyChangeHandler implements PropertyChangeListener
  {
    /**
     * Called when one of the ScrollBar's properties change.
     *
     * @param e The PropertyChangeEvent fired by the ScrollBar.
     */
00143     public void propertyChange(PropertyChangeEvent e)
    {
      if (e.getPropertyName().equals(JScrollBar.MODEL_CHANGED_PROPERTY))
        {
        ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener);
        scrollbar.getModel().addChangeListener(modelListener);
        getThumbBounds();
        }
      else if (e.getPropertyName().equals(JScrollBar.ORIENTATION_CHANGED_PROPERTY))
        {
        incrButton.removeMouseListener(buttonListener);
        decrButton.removeMouseListener(buttonListener);
        incrButton = createIncreaseButton(scrollbar.getOrientation());
        decrButton = createDecreaseButton(scrollbar.getOrientation());
        incrButton.addMouseListener(buttonListener);
        decrButton.addMouseListener(buttonListener);
        calculatePreferredSize();
        layoutContainer(scrollbar);
        }
      layoutContainer(scrollbar);
      scrollbar.repaint();
    }
  }

  /**
   * A helper class that listens for events from the timer that is used to
   * move the thumb.
   */
00171   protected class ScrollListener implements ActionListener
  {
    /** The direction the thumb moves in. */
00174     private transient int direction;

    /** Whether movement will be in blocks. */
00177     private transient boolean block;

    /**
     * Creates a new ScrollListener object. The default is scrolling
     * positively with block movement.
     */
00183     public ScrollListener()
    {
      direction = POSITIVE_SCROLL;
      block = true;
    }

    /**
     * Creates a new ScrollListener object using the given direction and
     * block.
     *
     * @param dir The direction to move in.
     * @param block Whether movement will be in blocks.
     */
00196     public ScrollListener(int dir, boolean block)
    {
      direction = dir;
      this.block = block;
    }

    /**
     * Sets the direction to scroll in.
     *
     * @param direction The direction to scroll in.
     */
00207     public void setDirection(int direction)
    {
      this.direction = direction;
    }

    /**
     * Sets whether scrolling will be done in blocks.
     *
     * @param block Whether scrolling will be in blocks.
     */
00217     public void setScrollByBlock(boolean block)
    {
      this.block = block;
    }

    /**
     * Called every time the timer reaches its interval.
     *
     * @param e The ActionEvent fired by the timer.
     */
00227     public void actionPerformed(ActionEvent e)
    {
      if (block)
        {
        // Only need to check it if it's block scrolling
        // We only block scroll if the click occurs
        // in the track.
        if (! trackListener.shouldScroll(direction))
          {
            trackHighlight = NO_HIGHLIGHT;
            scrollbar.repaint();
            return;
          }
        scrollByBlock(direction);
        }
      else
      scrollByUnit(direction);
    }
  }

  /**
   * Helper class that listens for movement on the track.
   */
00250   protected class TrackListener extends MouseAdapter
    implements MouseMotionListener
  {
    /** The current X coordinate of the mouse. */
00254     protected int currentMouseX;

    /** The current Y coordinate of the mouse. */
00257     protected int currentMouseY;

    /**
     * The offset between the current mouse cursor and the  current value of
     * the scrollbar.
     */
00263     protected int offset;

    /**
     * This method is called when the mouse is being dragged.
     *
     * @param e The MouseEvent given.
     */
00270     public void mouseDragged(MouseEvent e)
    {
      currentMouseX = e.getX();
      currentMouseY = e.getY();
      if (scrollbar.getValueIsAdjusting())
        {
        int value;
        if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
          value = valueForXPosition(currentMouseX) - offset;
        else
          value = valueForYPosition(currentMouseY) - offset;

        scrollbar.setValue(value);
        }
    }

    /**
     * This method is called when the mouse is moved.
     *
     * @param e The MouseEvent given.
     */
00291     public void mouseMoved(MouseEvent e)
    {
      // Not interested in where the mouse
      // is unless it is being dragged.
    }

    /**
     * This method is called when the mouse is pressed. When it is pressed,
     * the thumb should move in blocks towards the cursor.
     *
     * @param e The MouseEvent given.
     */
00303     public void mousePressed(MouseEvent e)
    {
      currentMouseX = e.getX();
      currentMouseY = e.getY();

      int value;
      if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
      value = valueForXPosition(currentMouseX);
      else
      value = valueForYPosition(currentMouseY);

      if (value == scrollbar.getValue())
      return;

      if (! thumbRect.contains(e.getPoint()))
        {
        scrollTimer.stop();
        scrollListener.setScrollByBlock(true);
        if (value > scrollbar.getValue())
          {
            trackHighlight = INCREASE_HIGHLIGHT;
            scrollListener.setDirection(POSITIVE_SCROLL);
          }
        else
          {
            trackHighlight = DECREASE_HIGHLIGHT;
            scrollListener.setDirection(NEGATIVE_SCROLL);
          }
        scrollTimer.start();
        }
      else
        {
        // We'd like to keep track of where the cursor
        // is inside the thumb.
        // This works because the scrollbar's value represents 
        // "lower" edge of the thumb. The value at which
        // the cursor is at must be greater or equal
        // to that value.
        scrollbar.setValueIsAdjusting(true);
        offset = value - scrollbar.getValue();
        }
      scrollbar.repaint();
    }

    /**
     * This method is called when the mouse is released. It should stop
     * movement on the thumb
     *
     * @param e The MouseEvent given.
     */
00353     public void mouseReleased(MouseEvent e)
    {
      trackHighlight = NO_HIGHLIGHT;
      scrollTimer.stop();

      if (scrollbar.getValueIsAdjusting())
      scrollbar.setValueIsAdjusting(false);
      scrollbar.repaint();
    }

    /**
     * A helper method that decides whether we should keep scrolling in the
     * given direction.
     *
     * @param direction The direction to check for.
     *
     * @return Whether the thumb should keep scrolling.
     */
00371     public boolean shouldScroll(int direction)
    {
      int value;
      if (scrollbar.getOrientation() == HORIZONTAL)
      value = valueForXPosition(currentMouseX);
      else
      value = valueForYPosition(currentMouseY);

      if (direction == POSITIVE_SCROLL)
      return (value > scrollbar.getValue());
      else
      return (value < scrollbar.getValue());
    }
  }

  /** The listener that listens to the JButtons. */
00387   protected ArrowButtonListener buttonListener;

  /** The listener that listens to the model. */
00390   protected ModelListener modelListener;

  /** The listener that listens to the scrollbar for property changes. */
00393   protected PropertyChangeListener propertyChangeListener;

  /** The listener that listens to the timer. */
00396   protected ScrollListener scrollListener;

  /** The listener that listens for MouseEvents on the track. */
00399   protected TrackListener trackListener;

  /** The JButton that decrements the scrollbar's value. */
00402   protected JButton decrButton;

  /** The JButton that increments the scrollbar's value. */
00405   protected JButton incrButton;

  /** The dimensions of the maximum thumb size. */
00408   protected Dimension maximumThumbSize;

  /** The dimensions of the minimum thumb size. */
00411   protected Dimension minimumThumbSize;

  /** The color of the thumb. */
00414   protected Color thumbColor;

  /** The outer shadow of the thumb. */
00417   protected Color thumbDarkShadowColor;

  /** The top and left edge color for the thumb. */
00420   protected Color thumbHighlightColor;

  /** The outer light shadow for the thumb. */
00423   protected Color thumbLightShadowColor;

  /** The color that is used when the mouse press occurs in the track. */
00426   protected Color trackHighlightColor;

  /** The color of the track. */
00429   protected Color trackColor;

  /** The size and position of the track. */
00432   protected Rectangle trackRect;

  /** The size and position of the thumb. */
00435   protected Rectangle thumbRect;

  /** Indicates that the decrease highlight should be painted. */
00438   protected static final int DECREASE_HIGHLIGHT = 1;

  /** Indicates that the increase highlight should be painted. */
00441   protected static final int INCREASE_HIGHLIGHT = 2;

  /** Indicates that no highlight should be painted. */
00444   protected static final int NO_HIGHLIGHT = 0;

  /** Indicates that the scrolling direction is positive. */
00447   private static final int POSITIVE_SCROLL = 1;

  /** Indicates that the scrolling direction is negative. */
00450   private static final int NEGATIVE_SCROLL = -1;

  /** The cached preferred size for the scrollbar. */
00453   private transient Dimension preferredSize;

  /** The current highlight status. */
00456   protected int trackHighlight;

  /** FIXME: Use this for something (presumably mouseDragged) */
00459   protected boolean isDragging;

  /** The timer used to move the thumb when the mouse is held. */
00462   protected Timer scrollTimer;

  /** The scrollbar this UI is acting for. */
00465   protected JScrollBar scrollbar;

  /**
   * This method adds a component to the layout.
   *
   * @param name The name to associate with the component that is added.
   * @param child The Component to add.
   */
00473   public void addLayoutComponent(String name, Component child)
  {
    // You should not be adding stuff to this component.
    // The contents are fixed.
  }

  /**
   * This method configures the scrollbar's colors. This can be  done by
   * looking up the standard colors from the Look and Feel defaults.
   */
00483   protected void configureScrollBarColors()
  {
    UIDefaults defaults = UIManager.getLookAndFeelDefaults();

    trackColor = defaults.getColor("ScrollBar.track");
    trackHighlightColor = defaults.getColor("ScrollBar.trackHighlight");
    thumbColor = defaults.getColor("ScrollBar.thumb");
    thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight");
    thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow");
    thumbLightShadowColor = defaults.getColor("ScrollBar.thumbLightShadow");
  }

  /**
   * This method creates an ArrowButtonListener.
   *
   * @return A new ArrowButtonListener.
   */
00500   protected ArrowButtonListener createArrowButtonListener()
  {
    return new ArrowButtonListener();
  }

  /**
   * This method creates a new JButton with the appropriate icon for the
   * orientation.
   *
   * @param orientation The orientation this JButton uses.
   *
   * @return The increase JButton.
   */
00513   protected JButton createIncreaseButton(int orientation)
  {
    if (incrButton == null)
      incrButton = new BasicArrowButton((orientation == SwingConstants.HORIZONTAL)
                                        ? SwingConstants.EAST
                                        : SwingConstants.SOUTH);
    else
      {
      if (orientation == SwingConstants.HORIZONTAL)
        ((BasicArrowButton) incrButton).setDirection(SwingConstants.EAST);
      else
        ((BasicArrowButton) incrButton).setDirection(SwingConstants.SOUTH);
      }
    return incrButton;
  }

  /**
   * This method creates a new JButton with the appropriate icon for the
   * orientation.
   *
   * @param orientation The orientation this JButton uses.
   *
   * @return The decrease JButton.
   */
00537   protected JButton createDecreaseButton(int orientation)
  {
    if (decrButton == null)
      decrButton = new BasicArrowButton((orientation == SwingConstants.HORIZONTAL)
                                        ? SwingConstants.WEST
                                        : SwingConstants.NORTH);
    else
      {
      if (orientation == SwingConstants.HORIZONTAL)
        ((BasicArrowButton) decrButton).setDirection(SwingConstants.WEST);
      else
        ((BasicArrowButton) decrButton).setDirection(SwingConstants.NORTH);
      }
    return decrButton;
  }

  /**
   * This method creates a new ModelListener.
   *
   * @return A new ModelListener.
   */
00558   protected ModelListener createModelListener()
  {
    return new ModelListener();
  }

  /**
   * This method creates a new PropertyChangeListener.
   *
   * @return A new PropertyChangeListener.
   */
00568   protected PropertyChangeListener createPropertyChangeListener()
  {
    return new PropertyChangeHandler();
  }

  /**
   * This method creates a new ScrollListener.
   *
   * @return A new ScrollListener.
   */
00578   protected ScrollListener createScrollListener()
  {
    return new ScrollListener();
  }

  /**
   * This method creates a new TrackListener.
   *
   * @return A new TrackListener.
   */
00588   protected TrackListener createTrackListener()
  {
    return new TrackListener();
  }

  /**
   * This method returns a new BasicScrollBarUI.
   *
   * @param c The JComponent to create a UI for.
   *
   * @return A new BasicScrollBarUI.
   */
00600   public static ComponentUI createUI(JComponent c)
  {
    return new BasicScrollBarUI();
  }

  /**
   * This method returns the maximum size for this JComponent.
   *
   * @param c The JComponent to measure the maximum size for.
   *
   * @return The maximum size for the component.
   */
00612   public Dimension getMaximumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the maximum thumb size.
   *
   * @return The maximum thumb size.
   */
00622   protected Dimension getMaximumThumbSize()
  {
    return maximumThumbSize;
  }

  /**
   * This method returns the minimum size for this JComponent.
   *
   * @param c The JComponent to measure the minimum size for.
   *
   * @return The minimum size for the component.
   */
00634   public Dimension getMinimumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the minimum thumb size.
   *
   * @return The minimum thumb size.
   */
00644   protected Dimension getMinimumThumbSize()
  {
    return minimumThumbSize;
  }

  /**
   * This method calculates the preferred size since calling
   * getPreferredSize() returns a cached value.
   */
00653   private void calculatePreferredSize()
  {
    // System.err.println(this + ".calculatePreferredSize()");
    int height;
    int width;
    height = width = 0;

    if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
      {
      width += incrButton.getPreferredSize().getWidth();
      width += decrButton.getPreferredSize().getWidth();

      width += (scrollbar.getMaximum() - scrollbar.getMinimum());

      height = Math.max(incrButton.getPreferredSize().height,
                        decrButton.getPreferredSize().height);
      height = Math.max(getMinimumThumbSize().height, height);
      height = Math.max(20, height);
      height = Math.min(getMaximumThumbSize().height, height);
      }
    else
      {
      height += incrButton.getPreferredSize().getHeight();
      height += decrButton.getPreferredSize().getHeight();

      height += (scrollbar.getMaximum() - scrollbar.getMinimum());

      width = Math.max(incrButton.getPreferredSize().width,
                       decrButton.getPreferredSize().width);
      width = Math.max(getMinimumThumbSize().width, width);
      width = Math.max(20, width);
      width = Math.min(getMaximumThumbSize().width, width);
      }

    Insets insets = scrollbar.getInsets();

    height += insets.top + insets.bottom;
    width += insets.left + insets.right;

    preferredSize = new Dimension(width, height);
  }

  /**
   * This method returns a cached value of the preferredSize. The only
   * restrictions are: If the scrollbar is horizontal, the height should be
   * the maximum of the height of the JButtons and  the minimum width of the
   * thumb. For vertical scrollbars, the  calculation is similar (swap width
   * for height and vice versa).
   *
   * @param c The JComponent to measure.
   *
   * @return The preferredSize.
   */
00706   public Dimension getPreferredSize(JComponent c)
  {
    calculatePreferredSize();
    return preferredSize;
  }

  /**
   * This method returns the thumb's bounds based on the  current value of the
   * scrollbar. This method updates the cached value and returns that.
   *
   * @return The thumb bounds.
   */
00718   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 = extent * trackRect.width / (max - min);
      thumbRect.height = trackRect.height;
      }
    else
      {
      thumbRect.x = trackRect.x;
      thumbRect.y = trackRect.y + value * trackRect.height / (max - min);

      thumbRect.width = trackRect.width;
      thumbRect.height = extent * trackRect.height / (max - min);
      }
    return thumbRect;
  }

  /**
   * This method calculates the bounds of the track. This method updates the
   * cached value and returns it.
   *
   * @return The track's bounds.
   */
00769   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;
  }

  /**
   * This method installs any addition Components that  are a part of or
   * related to this scrollbar.
   */
00794   protected void installComponents()
  {
    incrButton = createIncreaseButton(scrollbar.getOrientation());
    scrollbar.add(incrButton);
    decrButton = createDecreaseButton(scrollbar.getOrientation());
    scrollbar.add(decrButton);
  }

  /**
   * This method installs the defaults for the scrollbar specified by the
   * Basic Look and Feel.
   */
00806   protected void installDefaults()
  {
    UIDefaults defaults = UIManager.getLookAndFeelDefaults();

    scrollbar.setForeground(defaults.getColor("ScrollBar.foreground"));
    scrollbar.setBackground(defaults.getColor("ScrollBar.background"));
    scrollbar.setBorder(defaults.getBorder("ScrollBar.border"));
    scrollbar.setOpaque(true);

    maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize");
    minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize");
  }

  /**
   * This method installs the keyboard actions for the scrollbar.
   */
00822   protected void installKeyboardActions()
  {
    // FIXME: implement.
  }

  /**
   * This method installs any listeners for the scrollbar. This method also
   * installs listeners for things such as the JButtons and the timer.
   */
00831   protected void installListeners()
  {
    scrollListener = createScrollListener();
    trackListener = createTrackListener();
    buttonListener = createArrowButtonListener();
    modelListener = createModelListener();
    propertyChangeListener = createPropertyChangeListener();

    scrollbar.addMouseMotionListener(trackListener);
    scrollbar.addMouseListener(trackListener);

    incrButton.addMouseListener(buttonListener);
    decrButton.addMouseListener(buttonListener);

    scrollbar.addPropertyChangeListener(propertyChangeListener);
    scrollbar.getModel().addChangeListener(modelListener);

    scrollTimer.addActionListener(scrollListener);
  }

  /**
   * This method installs the UI for the component. This can include setting
   * up listeners, defaults,  and components. This also includes initializing
   * any data objects.
   *
   * @param c The JComponent to install.
   */
00858   public void installUI(JComponent c)
  {
    super.installUI(c);
    if (c instanceof JScrollBar)
      {
      scrollbar = (JScrollBar) c;

      trackRect = new Rectangle();
      thumbRect = new Rectangle();

      scrollTimer = new Timer(200, null);
      scrollTimer.setRepeats(true);

      installComponents();
      installListeners();
      installDefaults();
      configureScrollBarColors();

      calculatePreferredSize();
      layoutContainer(scrollbar);
      }
  }

  /**
   * This method lays out the scrollbar.
   *
   * @param scrollbarContainer The Container to layout.
   */
00886   public void layoutContainer(Container scrollbarContainer)
  {
    if (scrollbarContainer instanceof JScrollBar)
      {
      if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
        layoutHScrollbar((JScrollBar) scrollbarContainer);
      else
        layoutVScrollbar((JScrollBar) scrollbarContainer);
      }
  }

  /**
   * This method lays out the scrollbar horizontally.
   *
   * @param sb The JScrollBar to layout.
   */
00902   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();

    decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height);
    incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width,
                         trackRect.height);
  }

  /**
   * This method lays out the scrollbar vertically.
   *
   * @param sb The JScrollBar to layout.
   */
00925   protected void layoutVScrollbar(JScrollBar sb)
  {
    Rectangle vr = new Rectangle();
    SwingUtilities.calculateInnerArea(scrollbar, vr);

    // Update rectangles
    getTrackBounds();
    getThumbBounds();

    Dimension incrDims = incrButton.getPreferredSize();
    Dimension decrDims = decrButton.getPreferredSize();

    decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height);
    incrButton.setBounds(vr.x, trackRect.y + trackRect.height,
                         trackRect.width, incrDims.height);
  }

  /**
   * This method returns the minimum size required for the layout.
   *
   * @param scrollbarContainer The Container that is laid out.
   *
   * @return The minimum size.
   */
00949   public Dimension minimumLayoutSize(Container scrollbarContainer)
  {
    return preferredLayoutSize(scrollbarContainer);
  }

  /**
   * This method is called when the component is painted.
   *
   * @param g The Graphics object to paint with.
   * @param c The JComponent to paint.
   */
00960   public void paint(Graphics g, JComponent c)
  {
    layoutContainer(scrollbar);
    paintTrack(g, c, getTrackBounds());
    paintThumb(g, c, getThumbBounds());

    if (trackHighlight == INCREASE_HIGHLIGHT)
      paintIncreaseHighlight(g);
    else if (trackHighlight == DECREASE_HIGHLIGHT)
      paintDecreaseHighlight(g);
  }

  /**
   * This method is called when repainting and the mouse is  pressed in the
   * track. It paints the track below the thumb with the trackHighlight
   * color.
   *
   * @param g The Graphics object to paint with.
   */
00979   protected void paintDecreaseHighlight(Graphics g)
  {
    Color saved = g.getColor();

    g.setColor(trackHighlightColor);
    if (scrollbar.getOrientation() == HORIZONTAL)
      g.fillRect(trackRect.x, trackRect.y, thumbRect.x - trackRect.x,
                 trackRect.height);
    else
      g.fillRect(trackRect.x, trackRect.y, trackRect.width,
                 thumbRect.y - trackRect.y);
    g.setColor(saved);
  }

  /**
   * This method is called when repainting and the mouse is  pressed in the
   * track. It paints the track above the thumb with the trackHighlight
   * color.
   *
   * @param g The Graphics objet to paint with.
   */
01000   protected void paintIncreaseHighlight(Graphics g)
  {
    Color saved = g.getColor();

    g.setColor(trackHighlightColor);
    if (scrollbar.getOrientation() == HORIZONTAL)
      g.fillRect(thumbRect.x + thumbRect.width, trackRect.y,
                 trackRect.x + trackRect.width - thumbRect.x - thumbRect.width,
                 trackRect.height);
    else
      g.fillRect(trackRect.x, thumbRect.y + thumbRect.height, trackRect.width,
                 trackRect.y + trackRect.height - thumbRect.y
                 - thumbRect.height);
    g.setColor(saved);
  }

  /**
   * This method paints the thumb.
   *
   * @param g The Graphics object to paint with.
   * @param c The Component that is being painted.
   * @param thumbBounds The thumb bounds.
   */
01023   protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
  {
    Color saved = g.getColor();
    Point x;
    Point y;
    Point z;
    Polygon lines;

    g.setColor(thumbHighlightColor);
    x = new Point(thumbBounds.x + 1, thumbBounds.y + 1);
    y = new Point(x);
    y.translate(thumbBounds.width - 2, 0);
    z = new Point(x);
    z.translate(0, thumbBounds.height - 2);

    lines = new Polygon(new int[] { x.x, y.x, z.x },
                        new int[] { x.y, y.y, z.y }, 3);

    g.drawPolygon(lines);

    g.setColor(thumbLightShadowColor);
    x = new Point(thumbBounds.x + thumbBounds.width - 1,
                  thumbBounds.y + thumbBounds.height - 1);
    y = new Point(x);
    y.translate(-(thumbBounds.width - 2), 0);
    z = new Point(x);
    z.translate(0, -(thumbBounds.height - 2));

    lines = new Polygon(new int[] { x.x, y.x, z.x },
                        new int[] { x.y, y.y, z.y }, 3);
    g.drawPolygon(lines);

    g.setColor(thumbDarkShadowColor);
    x = new Point(thumbBounds.x + thumbBounds.width,
                  thumbBounds.y + thumbBounds.height);
    y = new Point(x);
    y.translate(-thumbBounds.width, 0);
    z = new Point(x);
    z.translate(0, -thumbBounds.height);

    lines = new Polygon(new int[] { x.x, y.x, z.x },
                        new int[] { x.y, y.y, z.y }, 3);
    g.drawPolygon(lines);

    g.setColor(thumbColor);
    g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width,
               thumbBounds.height);

    g.setColor(saved);
  }

  /**
   * This method paints the track.
   *
   * @param g The Graphics object to paint with.
   * @param c The JComponent being painted.
   * @param trackBounds The track's bounds.
   */
01081   protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
  {
    Color saved = g.getColor();
    g.setColor(trackColor);
    g.fill3DRect(trackBounds.x, trackBounds.y, trackBounds.width,
                 trackBounds.height, false);
    g.setColor(saved);
  }

  /**
   * This method returns the preferred size for the layout.
   *
   * @param scrollbarContainer The Container to find a size for.
   *
   * @return The preferred size for the layout.
   */
01097   public Dimension preferredLayoutSize(Container scrollbarContainer)
  {
    if (scrollbarContainer instanceof JComponent)
      return getPreferredSize((JComponent) scrollbarContainer);
    else
      return null;
  }

  /**
   * This method removes a child component from the layout.
   *
   * @param child The child to remove.
   */
01110   public void removeLayoutComponent(Component child)
  {
    // You should not be removing stuff from this component.
  }

  /**
   * The method scrolls the thumb by a block in the  direction specified.
   *
   * @param direction The direction to scroll.
   */
01120   protected void scrollByBlock(int direction)
  {
    scrollbar.setValue(scrollbar.getValue()
                       + scrollbar.getBlockIncrement(direction));
  }

  /**
   * The method scrolls the thumb by a unit in the direction specified.
   *
   * @param direction The direction to scroll.
   */
01131   protected void scrollByUnit(int direction)
  {
    scrollbar.setValue(scrollbar.getValue()
                       + scrollbar.getUnitIncrement(direction));
  }

  /**
   * This method sets the thumb's bounds.
   *
   * @param x The X position of the thumb.
   * @param y The Y position of the thumb.
   * @param width The width of the thumb.
   * @param height The height of the thumb.
   */
01145   protected void setThumbBounds(int x, int y, int width, int height)
  {
    thumbRect.x = x;
    thumbRect.y = y;
    thumbRect.width = width;
    thumbRect.height = height;
  }

  /**
   * This method uninstalls any components that  are a part of or related to
   * this scrollbar.
   */
01157   protected void uninstallComponents()
  {
    scrollbar.remove(incrButton);
    scrollbar.remove(decrButton);
    incrButton = null;
    decrButton = null;
  }

  /**
   * This method uninstalls any defaults that this scrollbar acquired from the
   * Basic Look and Feel defaults.
   */
01169   protected void uninstallDefaults()
  {
    scrollbar.setForeground(null);
    scrollbar.setBackground(null);
    scrollbar.setBorder(null);
  }

  /**
   * This method uninstalls any keyboard actions this scrollbar acquired
   * during install.
   */
01180   protected void uninstallKeyboardActions()
  {
    // FIXME: implement.
  }

  /**
   * This method uninstalls any listeners that were registered during install.
   */
01188   protected void uninstallListeners()
  {
    scrollTimer.removeActionListener(scrollListener);

    scrollbar.getModel().removeChangeListener(modelListener);
    scrollbar.removePropertyChangeListener(propertyChangeListener);

    decrButton.removeMouseListener(buttonListener);
    incrButton.removeMouseListener(buttonListener);

    scrollbar.removeMouseListener(trackListener);
    scrollbar.removeMouseMotionListener(trackListener);

    propertyChangeListener = null;
    modelListener = null;
    buttonListener = null;
    trackListener = null;
    scrollListener = null;
  }

  /**
   * This method uninstalls the UI. This includes removing any defaults,
   * listeners, and components that this UI may have initialized. It also
   * nulls any instance data.
   *
   * @param c The Component to uninstall for.
   */
01215   public void uninstallUI(JComponent c)
  {
    uninstallDefaults();
    uninstallListeners();
    uninstallComponents();

    scrollTimer = null;

    thumbRect = null;
    trackRect = null;

    trackColor = null;
    trackHighlightColor = null;
    thumbColor = null;
    thumbHighlightColor = null;
    thumbDarkShadowColor = null;
    thumbLightShadowColor = null;

    scrollbar = null;
  }

  /**
   * This method returns the value in the scrollbar's range given the y
   * coordinate. If the value is out of range, it will return the closest
   * legal value.
   *
   * @param yPos The y coordinate to calculate a value for.
   *
   * @return The value for the y coordinate.
   */
01245   private int valueForYPosition(int yPos)
  {
    int min = scrollbar.getMinimum();
    int max = scrollbar.getMaximum();
    int len = trackRect.height;

    int value;

    // If the length is 0, you shouldn't be able to even see where the thumb is.
    // This really shouldn't ever happen, but just in case, we'll return the middle.
    if (len == 0)
      return ((max - min) / 2);

    value = ((yPos - trackRect.y) * (max - min) / len + min);

    // If this isn't a legal value, then we'll have to move to one now.
    if (value > max)
      value = max;
    else if (value < min)
      value = min;
    return value;
  }

  /**
   * This method returns the value in the scrollbar's range given the x
   * coordinate. If the value is out of range, it will return the closest
   * legal value.
   *
   * @param xPos The x coordinate to calculate a value for.
   *
   * @return The value for the x coordinate.
   */
01277   private int valueForXPosition(int xPos)
  {
    int min = scrollbar.getMinimum();
    int max = scrollbar.getMaximum();
    int len = trackRect.width;

    int value;

    // If the length is 0, you shouldn't be able to even see where the slider is.
    // This really shouldn't ever happen, but just in case, we'll return the middle.
    if (len == 0)
      return ((max - min) / 2);

    value = ((xPos - trackRect.x) * (max - min) / len + min);

    // If this isn't a legal value, then we'll have to move to one now.
    if (value > max)
      value = max;
    else if (value < min)
      value = min;
    return value;
  }
}

Generated by  Doxygen 1.6.0   Back to index