/* BasicSliderUI.java --
   Copyright (C) 2004, 2005, 2006,  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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
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.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Dictionary;
import java.util.Enumeration;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.BoundedRangeModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.MouseInputAdapter;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SliderUI;

/**
 * <p>
 * BasicSliderUI.java This is the UI delegate in the Basic look and feel that
 * paints JSliders.
 * </p>
 * 
 * <p>
 * The UI delegate keeps track of 6 rectangles that place the various parts of
 * the JSlider inside the component.
 * </p>
 * 
 * <p>
 * The rectangles are organized as follows:
 * </p>
 * <pre>
 *     +-------------------------------------------------------+ <-- focusRect
 *     |                                                       |
 *     |  +==+-------------------+==+--------------------+==+<------ contentRect
 *     |  |  |                   |  |<---thumbRect       |  |  |
 *     |  |  |    TRACK          |  |                    |<--------- trackRect
 *     |  |  +-------------------+==+--------------------+  |  |
 *     |  |  |                                           |  |  |
 *     |  |  |          TICKS GO HERE                    |<-------- tickRect
 *     |  |  |                                           |  |  |
 *     |  +==+-------------------------------------------+==+  |
 *     |  |  |                                           |  |  |
 *     |  |  |                                           |  |<----- labelRect
 *     |  |  |                 LABELS GO HERE            |  |  |
 *     |  |  |                                           |  |  |
 *     |  |  |                                           |  |  |
 *     |  |  |                                           |  |  |
 *     |  |  |                                           |  |  |
 *     |  |                                              |  |  |
 * </pre>
 * 
 * <p>
 * The space between the contentRect and the focusRect are the FocusInsets.
 * </p>
 * 
 * <p>
 * The space between the focusRect and the component bounds is the insetCache
 * which are the component's insets.
 * </p>
 * 
 * <p>
 * The top of the thumb is the top of the contentRect. The trackRect has to be
 * as tall as the thumb.
 * </p>
 * 
 * <p>
 * The trackRect and tickRect do not start from the left edge of the
 * focusRect. They are trackBuffer away from each side of the focusRect. This
 * is so that the thumb has room to move.
 * </p>
 * 
 * <p>
 * The labelRect does start right against the contentRect's left and right
 * edges and it gets all remaining space.
 * </p>
 */
public class BasicSliderUI extends SliderUI
{
  /**
   * Helper class that listens to the {@link JSlider}'s model for changes.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public class ChangeHandler implements ChangeListener
  {
    /**
     * Called when the slider's model has been altered. The UI delegate should
     * recalculate any rectangles that are dependent on the model for their
     * positions and repaint.
     *
     * @param e A static {@link ChangeEvent} passed from the model.
     */
    public void stateChanged(ChangeEvent e)
    {
      // Maximum, minimum, and extent values will be taken
      // care of automatically when the slider is repainted.
      // Only thing that needs recalculation is the thumb.
      calculateThumbLocation();
      slider.repaint();
    }
  }

  /**
   * Helper class that listens for resize events.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public class ComponentHandler extends ComponentAdapter
  {
    /**
     * Called when the size of the component changes. The UI delegate should
     * recalculate any rectangles that are dependent on the model for their
     * positions and repaint.
     *
     * @param e A {@link ComponentEvent}.
     */
    public void componentResized(ComponentEvent e)
    {
      calculateGeometry();

      slider.revalidate();
      slider.repaint();
    }
  }

  /**
   * Helper class that listens for focus events.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public class FocusHandler implements FocusListener
  {
    /**
     * Called when the {@link JSlider} has gained focus.  It should repaint
     * the slider with the focus drawn.
     *
     * @param e A {@link FocusEvent}.
     */
    public void focusGained(FocusEvent e)
    {
      slider.repaint();
      hasFocus = true;
    }

    /**
     * Called when the {@link JSlider} has lost focus. It  should repaint the
     * slider without the focus drawn.
     *
     * @param e A {@link FocusEvent}.
     */
    public void focusLost(FocusEvent e)
    {
      slider.repaint();
      hasFocus = false;
    }
  }

  /**
   * Helper class that listens for changes to the properties of the {@link
   * JSlider}.
   */
  public class PropertyChangeHandler implements PropertyChangeListener
  {
    /**
     * Called when one of the properties change. The UI should recalculate any
     * rectangles if necessary and repaint.
     *
     * @param e A {@link PropertyChangeEvent}.
     */
    public void propertyChange(PropertyChangeEvent e)
    {
      // Check for orientation changes.
      if (e.getPropertyName().equals("orientation"))
        recalculateIfOrientationChanged();
      else if (e.getPropertyName().equals("model"))
        {
          BoundedRangeModel oldModel = (BoundedRangeModel) e.getOldValue();
          oldModel.removeChangeListener(changeListener);
          slider.getModel().addChangeListener(changeListener);
          calculateThumbLocation();
        }
      else if (e.getPropertyName().equals("paintTicks"))
        calculateGeometry();

      // elif the componentOrientation changes (this is a bound property,
      // just undocumented) we change leftToRightCache. In Sun's 
      // implementation, the LTR cache changes on a repaint. This is strange
      // since there is no need to do so. We could events here and 
      // update the cache. 
      // elif the border/insets change, we recalculateInsets.
      slider.repaint();
    }
  }

  /**
   * Helper class that listens to our swing timer. This class is responsible
   * for listening to the timer and moving the thumb in the proper direction
   * every interval.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public class ScrollListener implements ActionListener
  {
    /** Indicates which direction the thumb should scroll. */
    private transient int direction;

    /** Indicates whether we should scroll in blocks or in units. */
    private transient boolean block;

    /**
     * Creates a new ScrollListener object.
     */
    public ScrollListener()
    {
      direction = POSITIVE_SCROLL;
      block = false;
    }

    /**
     * Creates a new ScrollListener object.
     *
     * @param dir The direction to scroll in.
     * @param block If movement will be in blocks.
     */
    public ScrollListener(int dir, boolean block)
    {
      direction = dir;
      this.block = block;
    }

    /**
     * Called every time the swing timer reaches its interval. If the thumb
     * needs to move, then this method will move the thumb one block or  unit
     * in the direction desired. Otherwise, the timer can be stopped.
     *
     * @param e An {@link ActionEvent}.
     */
    public void actionPerformed(ActionEvent e)
    {
      if (! trackListener.shouldScroll(direction))
        {
          scrollTimer.stop();
          return;
        }

      if (block)
        scrollByBlock(direction);
      else
        scrollByUnit(direction);
    }

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

    /**
     * Sets whether movement will be in blocks.
     *
     * @param block If movement will be in blocks.
     */
    public void setScrollByBlock(boolean block)
    {
      this.block = block;
    }
  }

  /**
   * Helper class that listens for mouse events.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public class TrackListener extends MouseInputAdapter
  {
    /** The current X position of the mouse. */
    protected int currentMouseX;

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

    /**
     * The offset between the current slider value and the cursor's position.
     */
    protected int offset;

    /**
     * Called when the mouse has been dragged. This should find the mouse's
     * current position and adjust the value of the {@link JSlider}
     * accordingly.
     *
     * @param e A {@link MouseEvent}
     */
    public void mouseDragged(MouseEvent e)
    {
      dragging = true;
      if (slider.isEnabled())
        {
          currentMouseX = e.getX();
          currentMouseY = e.getY();
          if (slider.getValueIsAdjusting())
            {
              int value;
              if (slider.getOrientation() == JSlider.HORIZONTAL)
                value = valueForXPosition(currentMouseX) - offset;
              else
                value = valueForYPosition(currentMouseY) - offset;

              slider.setValue(value);
            }
        }
    }

    /**
     * Called when the mouse has moved over a component but no buttons have
     * been pressed yet.
     *
     * @param e A {@link MouseEvent}
     */
    public void mouseMoved(MouseEvent e)
    {
      // Don't care that we're moved unless we're dragging.
    }

    /**
     * Called when the mouse is pressed. When the press occurs on the thumb
     * itself, the {@link JSlider} should have its value set to where the
     * mouse was pressed. If the press occurs on the track, then the thumb
     * should move one block towards the direction of the mouse.
     *
     * @param e A {@link MouseEvent}
     */
    public void mousePressed(MouseEvent e)
    {
      if (slider.isEnabled())
        {
          currentMouseX = e.getX();
          currentMouseY = e.getY();

          int value;
          if (slider.getOrientation() == JSlider.HORIZONTAL)
            value = valueForXPosition(currentMouseX);
          else
            value = valueForYPosition(currentMouseY);

          if (slider.getSnapToTicks())
            value = findClosestTick(value);

          // If the thumb is hit, then we don't need to set the timers to 
          // move it. 
          if (! thumbRect.contains(e.getPoint()))
            {
              // The mouse has hit some other part of the slider.
              // The value moves no matter where in the slider you hit.
              if (value > slider.getValue())
                scrollDueToClickInTrack(POSITIVE_SCROLL);
              else
                scrollDueToClickInTrack(NEGATIVE_SCROLL);
            }
          else
            {
              slider.setValueIsAdjusting(true);
              offset = value - slider.getValue();
            }
        }
    }

    /**
     * Called when the mouse is released.  This should stop the timer that
     * scrolls the thumb.
     *
     * @param e A {@link MouseEvent}
     */
    public void mouseReleased(MouseEvent e)
    {
      dragging = false;
      if (slider.isEnabled())
        {
          currentMouseX = e.getX();
          currentMouseY = e.getY();

          if (slider.getValueIsAdjusting())
            {
              slider.setValueIsAdjusting(false);
              if (slider.getSnapToTicks())
                slider.setValue(findClosestTick(slider.getValue()));
            }
          if (scrollTimer != null)
            scrollTimer.stop();
        }
    }

    /**
     * Indicates whether the thumb should scroll in the given direction.
     *
     * @param direction The direction to check.
     *
     * @return True if the thumb should move in that direction.
     */
    public boolean shouldScroll(int direction)
    {
      int value;
      if (slider.getOrientation() == JSlider.HORIZONTAL)
        value = valueForXPosition(currentMouseX);
      else
        value = valueForYPosition(currentMouseY);

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

  /**
   * This class is no longer used as of JDK1.3.
   */
  public class ActionScroller extends AbstractAction
  {
    /**
     * Not used.
     *
     * @param slider not used
     * @param dir not used
     * @param block not used
     */
    public ActionScroller(JSlider slider, int dir, boolean block)
    {
      // Not used.
    }

    /**
     * Not used.
     *
     * @param event not used
     */
    public void actionPerformed(ActionEvent event)
    {
      // Not used.
    }
  }

  /** Listener for changes from the model. */
  protected ChangeListener changeListener;

  /** Listener for changes to the {@link JSlider}. */
  protected PropertyChangeListener propertyChangeListener;

  /** Listener for the scrollTimer. */
  protected ScrollListener scrollListener;

  /** Listener for component resizing. */
  protected ComponentListener componentListener;

  /** Listener for focus handling. */
  protected FocusListener focusListener;

  /** Listener for mouse events. */
  protected TrackListener trackListener;

  /** The insets between the FocusRectangle and the ContentRectangle. */
  protected Insets focusInsets;

  /** The {@link JSlider}'s insets. */
  protected Insets insetCache;

  /** Rectangle describing content bounds. See diagram above. */
  protected Rectangle contentRect;

  /** Rectangle describing focus bounds. See diagram above. */
  protected Rectangle focusRect;

  /** Rectangle describing the thumb's bounds. See diagram above. */
  protected Rectangle thumbRect;

  /** Rectangle describing the tick bounds. See diagram above. */
  protected Rectangle tickRect;

  /** Rectangle describing the label bounds. See diagram above. */
  protected Rectangle labelRect;

  /** Rectangle describing the track bounds. See diagram above. */
  protected Rectangle trackRect;

  /** FIXME: use this somewhere. */
  public static final int MAX_SCROLL = 2;

  /** FIXME: use this somewhere. */
  public static final int MIN_SCROLL = -2;

  /** A constant describing scrolling towards the minimum. */
  public static final int NEGATIVE_SCROLL = -1;

  /** A constant describing scrolling towards the maximum. */
  public static final int POSITIVE_SCROLL = 1;

  /** The gap between the edges of the contentRect and trackRect. */
  protected int trackBuffer;

  /** Whether this slider is actually drawn left to right. */
  protected boolean leftToRightCache;

  /** A timer that periodically moves the thumb. */
  protected Timer scrollTimer;

  /** A reference to the {@link JSlider} that this UI was created for. */
  protected JSlider slider;

  /** The shadow color. */
  private transient Color shadowColor;

  /** The highlight color. */
  private transient Color highlightColor;

  /** The focus color. */
  private transient Color focusColor;
  
  /** True if the slider has focus. */
  private transient boolean hasFocus;
  
  /** True if the user is dragging the slider. */
  boolean dragging;

  /**
   * Creates a new Basic look and feel Slider UI.
   *
   * @param b The {@link JSlider} that this UI was created for.
   */
  public BasicSliderUI(JSlider b)
  {
    super();
  }

  /**
   * Returns true if the user is dragging the slider.
   * 
   * @return true if the slider is being dragged.
   * 
   * @since 1.5
   */
  protected boolean isDragging()
  {
    return dragging;
  }
  
  /**
   * Gets the shadow color to be used for this slider. The shadow color is the
   * color used for drawing the top and left edges of the track.
   *
   * @return The shadow color.
   */
  protected Color getShadowColor()
  {
    return shadowColor;
  }

  /**
   * Gets the highlight color to be used for this slider. The highlight color
   * is the color used for drawing the bottom and right edges of the track.
   *
   * @return The highlight color.
   */
  protected Color getHighlightColor()
  {
    return highlightColor;
  }

  /**
   * Gets the focus color to be used for this slider. The focus color is the
   * color used for drawing the focus rectangle when the component gains
   * focus.
   *
   * @return The focus color.
   */
  protected Color getFocusColor()
  {
    return focusColor;
  }

  /**
   * Factory method to create a BasicSliderUI for the given {@link
   * JComponent}, which should be a {@link JSlider}.
   *
   * @param b The {@link JComponent} a UI is being created for.
   *
   * @return A BasicSliderUI for the {@link JComponent}.
   */
  public static ComponentUI createUI(JComponent b)
  {
    return new BasicSliderUI((JSlider) b);
  }

  /**
   * Installs and initializes all fields for this UI delegate. Any properties
   * of the UI that need to be initialized and/or set to defaults will be
   * done now. It will also install any listeners necessary.
   *
   * @param c The {@link JComponent} that is having this UI installed.
   */
  public void installUI(JComponent c)
  {
    super.installUI(c);
    if (c instanceof JSlider)
      {
        slider = (JSlider) c;

        focusRect = new Rectangle();
        contentRect = new Rectangle();
        thumbRect = new Rectangle();
        trackRect = new Rectangle();
        tickRect = new Rectangle();
        labelRect = new Rectangle();

        insetCache = slider.getInsets();
        leftToRightCache = ! slider.getInverted();

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

        installDefaults(slider);
        installListeners(slider);
        installKeyboardActions(slider);

        calculateFocusRect();

        calculateContentRect();
        calculateThumbSize();
        calculateTrackBuffer();
        calculateTrackRect();
        calculateThumbLocation();

        calculateTickRect();
        calculateLabelRect();
      }
  }

  /**
   * Performs the opposite of installUI. Any properties or resources that need
   * to be cleaned up will be done now. It will also uninstall any listeners
   * it has. In addition, any properties of this UI will be nulled.
   *
   * @param c The {@link JComponent} that is having this UI uninstalled.
   */
  public void uninstallUI(JComponent c)
  {
    super.uninstallUI(c);

    uninstallKeyboardActions(slider);
    uninstallListeners(slider);

    scrollTimer = null;

    focusRect = null;
    contentRect = null;
    thumbRect = null;
    trackRect = null;
    tickRect = null;
    labelRect = null;

    focusInsets = null;
  }

  /**
   * Initializes any default properties that this UI has from the defaults for
   * the Basic look and feel.
   *
   * @param slider The {@link JSlider} that is having this UI installed.
   */
  protected void installDefaults(JSlider slider)
  {
    LookAndFeel.installColors(slider, "Slider.background",
                              "Slider.foreground");
    LookAndFeel.installBorder(slider, "Slider.border");
    shadowColor = UIManager.getColor("Slider.shadow");
    highlightColor = UIManager.getColor("Slider.highlight");
    focusColor = UIManager.getColor("Slider.focus");
    focusInsets = UIManager.getInsets("Slider.focusInsets");
    slider.setOpaque(true);
  }

  /**
   * Creates a new {@link TrackListener}.
   *
   * @param slider The {@link JSlider} that this {@link TrackListener} is
   *        created for.
   *
   * @return A new {@link TrackListener}.
   */
  protected TrackListener createTrackListener(JSlider slider)
  {
    return new TrackListener();
  }

  /**
   * Creates a new {@link ChangeListener}.
   *
   * @param slider The {@link JSlider} that this {@link ChangeListener} is
   *        created for.
   *
   * @return A new {@link ChangeListener}.
   */
  protected ChangeListener createChangeListener(JSlider slider)
  {
    return new ChangeHandler();
  }

  /**
   * Creates a new {@link ComponentListener}.
   *
   * @param slider The {@link JSlider} that this {@link ComponentListener} is
   *        created for.
   *
   * @return A new {@link ComponentListener}.
   */
  protected ComponentListener createComponentListener(JSlider slider)
  {
    return new ComponentHandler();
  }

  /**
   * Creates a new {@link FocusListener}.
   *
   * @param slider The {@link JSlider} that this {@link FocusListener} is
   *        created for.
   *
   * @return A new {@link FocusListener}.
   */
  protected FocusListener createFocusListener(JSlider slider)
  {
    return new FocusHandler();
  }

  /**
   * Creates a new {@link ScrollListener}.
   *
   * @param slider The {@link JSlider} that this {@link ScrollListener} is
   *        created for.
   *
   * @return A new {@link ScrollListener}.
   */
  protected ScrollListener createScrollListener(JSlider slider)
  {
    return new ScrollListener();
  }

  /**
   * Creates a new {@link PropertyChangeListener}.
   *
   * @param slider The {@link JSlider} that this {@link
   *        PropertyChangeListener} is created for.
   *
   * @return A new {@link PropertyChangeListener}.
   */
  protected PropertyChangeListener createPropertyChangeListener(JSlider slider)
  {
    return new PropertyChangeHandler();
  }

  /**
   * Creates and registers all the listeners for this UI delegate. This
   * includes creating the ScrollListener and registering it to the timer.
   *
   * @param slider The {@link JSlider} is having listeners installed.
   */
  protected void installListeners(JSlider slider)
  {
    propertyChangeListener = createPropertyChangeListener(slider);
    componentListener = createComponentListener(slider);
    trackListener = createTrackListener(slider);
    focusListener = createFocusListener(slider);
    changeListener = createChangeListener(slider);
    scrollListener = createScrollListener(slider);

    slider.addPropertyChangeListener(propertyChangeListener);
    slider.addComponentListener(componentListener);
    slider.addMouseListener(trackListener);
    slider.addMouseMotionListener(trackListener);
    slider.addFocusListener(focusListener);
    slider.getModel().addChangeListener(changeListener);

    scrollTimer.addActionListener(scrollListener);
  }

  /**
   * Unregisters all the listeners that this UI delegate was using. In
   * addition, it will also null any listeners that it was using.
   *
   * @param slider The {@link JSlider} that is having listeners removed.
   */
  protected void uninstallListeners(JSlider slider)
  {
    slider.removePropertyChangeListener(propertyChangeListener);
    slider.removeComponentListener(componentListener);
    slider.removeMouseListener(trackListener);
    slider.removeMouseMotionListener(trackListener);
    slider.removeFocusListener(focusListener);
    slider.getModel().removeChangeListener(changeListener);

    scrollTimer.removeActionListener(scrollListener);

    propertyChangeListener = null;
    componentListener = null;
    trackListener = null;
    focusListener = null;
    changeListener = null;
    scrollListener = null;
  }

  /**
   * Installs any keyboard actions. The list of keys that need to be bound are
   * listed in Basic look and feel's defaults.
   *
   * @param slider The {@link JSlider} that is having keyboard actions
   *        installed.
   */
  protected void installKeyboardActions(JSlider slider)
  {
    InputMap keyMap = getInputMap(JComponent.WHEN_FOCUSED);
    SwingUtilities.replaceUIInputMap(slider, JComponent.WHEN_FOCUSED, keyMap);
    ActionMap map = getActionMap();
    SwingUtilities.replaceUIActionMap(slider, map);
  }

  /**
   * Uninstalls any keyboard actions. The list of keys used  are listed in
   * Basic look and feel's defaults.
   *
   * @param slider The {@link JSlider} that is having keyboard actions
   *        uninstalled.
   */
  protected void uninstallKeyboardActions(JSlider slider)
  {
    SwingUtilities.replaceUIActionMap(slider, null);
    SwingUtilities.replaceUIInputMap(slider, JComponent.WHEN_FOCUSED, null);
  }

  /* XXX: This is all after experimentation with SUN's implementation.

     PreferredHorizontalSize seems to be 200x21.
     PreferredVerticalSize seems to be 21x200.

     MinimumHorizontalSize seems to be 36x21.
     MinimumVerticalSize seems to be 21x36.

     PreferredSize seems to be 200x63. Or Components.getBounds?

     MinimumSize seems to be 36x63.

     MaximumSize seems to be 32767x63.
   */

  /**
   * This method returns the preferred size when the slider is horizontally
   * oriented.
   *
   * @return The dimensions of the preferred horizontal size.
   */
  public Dimension getPreferredHorizontalSize()
  {
    Insets insets = slider.getInsets();

    // The width should cover all the labels (which are usually the
    // deciding factor of the width)
    int width = getWidthOfWidestLabel() * (slider.getLabelTable() == null ? 0
        : slider.getLabelTable().size());

    // If there are not enough labels.
    // This number is pretty much arbitrary, but it looks nice.
    if (width < 200)
      width = 200;

    // We can only draw inside of the focusRectangle, so we have to
    // pad it with insets.
    width += insets.left + insets.right + focusInsets.left + focusInsets.right;

    // Height is determined by the thumb, the ticks and the labels.
    int height = getThumbSize().height;

    if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0
        || slider.getMinorTickSpacing() > 0)
      height += getTickLength();

    if (slider.getPaintLabels())
      height += getHeightOfTallestLabel();

    height += insets.top + insets.bottom + focusInsets.top
    + focusInsets.bottom;

    return new Dimension(width, height);
  }

  /**
   * This method returns the preferred size when the slider is vertically
   * oriented.
   *
   * @return The dimensions of the preferred vertical size.
   */
  public Dimension getPreferredVerticalSize()
  {
    Insets insets = slider.getInsets();

    int height = getHeightOfTallestLabel() * (slider.getLabelTable() == null
                                              ? 0 : slider.getLabelTable()
                                                          .size());

    if (height < 200)
      height = 200;

    height += insets.top + insets.bottom + focusInsets.top
    + focusInsets.bottom;

    int width = getThumbSize().width;

    if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0
        || slider.getMinorTickSpacing() > 0)
      width += getTickLength();

    if (slider.getPaintLabels())
      width += getWidthOfWidestLabel();

    width += insets.left + insets.right + focusInsets.left + focusInsets.right;

    return new Dimension(width, height);
  }

  /**
   * This method returns the minimum size when the slider is horizontally
   * oriented.
   *
   * @return The dimensions of the minimum horizontal size.
   */
  public Dimension getMinimumHorizontalSize()
  {
    Insets insets = slider.getInsets();
    // Height is determined by the thumb, the ticks and the labels.
    int height = getThumbSize().height; 

    if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0
        || slider.getMinorTickSpacing() > 0)
      height += getTickLength();

    if (slider.getPaintLabels())
      height += getHeightOfTallestLabel();

    height += insets.top + insets.bottom + focusInsets.top
        + focusInsets.bottom;

    return new Dimension(36, height);
  }

  /**
   * This method returns the minimum size of the slider when it  is vertically
   * oriented.
   *
   * @return The dimensions of the minimum vertical size.
   */
  public Dimension getMinimumVerticalSize()
  {
    Insets insets = slider.getInsets();
    int width = getThumbSize().width;

    if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0
        || slider.getMinorTickSpacing() > 0)
      width += getTickLength();

    if (slider.getPaintLabels())
      width += getWidthOfWidestLabel();

    width += insets.left + insets.right + focusInsets.left + focusInsets.right;

    return new Dimension(width, 36);
  }

  /**
   * This method returns the preferred size of the component. If it returns
   * null, then it is up to the Layout Manager to give the {@link JComponent}
   * a size.
   *
   * @param c The {@link JComponent} to find the preferred size for.
   *
   * @return The dimensions of the preferred size.
   */
  public Dimension getPreferredSize(JComponent c)
  {
    if (slider.getOrientation() == JSlider.HORIZONTAL)
      return getPreferredHorizontalSize();
    else
      return getPreferredVerticalSize();
  }

  /**
   * This method returns the minimum size for this {@link JSlider}  for this
   * look and feel. If it returns null, then it is up to the Layout Manager
   * to give the {@link JComponent} a size.
   *
   * @param c The {@link JComponent} to find the minimum size for.
   *
   * @return The dimensions of the minimum size.
   */
  public Dimension getMinimumSize(JComponent c)
  {
    if (slider.getOrientation() == JSlider.HORIZONTAL)
      return getMinimumHorizontalSize();
    else
      return getMinimumVerticalSize();
  }

  /**
   * This method returns the maximum size for this {@link JSlider} for this
   * look and feel.
   *
   * @param c The {@link JComponent} to find a maximum size for.
   *
   * @return The dimensions of the maximum size.
   */
  public Dimension getMaximumSize(JComponent c)
  {
    Insets insets = slider.getInsets();
    if (slider.getOrientation() == JSlider.HORIZONTAL)
      {
        // Height is determined by the thumb, the ticks and the labels.
        int height = getThumbSize().height; 

        if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0
            || slider.getMinorTickSpacing() > 0)
          height += getTickLength();

        if (slider.getPaintLabels())
          height += getHeightOfTallestLabel();

        height += insets.top + insets.bottom + focusInsets.top
            + focusInsets.bottom;

        return new Dimension(32767, height);
      }
    else
      {
        int width = getThumbSize().width;

        if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0
            || slider.getMinorTickSpacing() > 0)
          width += getTickLength();

        if (slider.getPaintLabels())
          width += getWidthOfWidestLabel();

        width += insets.left + insets.right + focusInsets.left 
            + focusInsets.right;

        return new Dimension(width, 32767);
      }
  }

  /**
   * This method calculates all the sizes of the rectangles by delegating to
   * the helper methods calculateXXXRect.
   */
  protected void calculateGeometry()
  {
    calculateFocusRect();
    calculateContentRect();
    calculateThumbSize();
    calculateTrackBuffer();
    calculateTrackRect();
    calculateTickRect();
    calculateLabelRect();
    calculateThumbLocation();
  }

  /**
   * This method calculates the size and position of the focusRect. This
   * method does not need to be called if the orientation changes.
   */
  protected void calculateFocusRect()
  {
    insetCache = slider.getInsets();
    focusRect = SwingUtilities.calculateInnerArea(slider, focusRect);
    if (focusRect.width < 0)
      focusRect.width = 0;
    if (focusRect.height < 0)
      focusRect.height = 0;
  }

  /**
   * Sets the width and height of the <code>thumbRect</code> field, using the
   * dimensions returned by {@link #getThumbSize()}.
   */
  protected void calculateThumbSize()
  {
    Dimension d = getThumbSize();
    thumbRect.width = d.width;
    thumbRect.height = d.height;
  }

  /**
   * Updates the <code>contentRect</code> field to an area inside the 
   * <code>focusRect</code>. This method does not need to be called if the 
   * orientation changes.
   */
  protected void calculateContentRect()
  {
    contentRect.x = focusRect.x + focusInsets.left;
    contentRect.y = focusRect.y + focusInsets.top;
    
    contentRect.width = focusRect.width - focusInsets.left - focusInsets.right;
    contentRect.height = focusRect.height - focusInsets.top 
        - focusInsets.bottom;

    if (contentRect.width < 0)
      contentRect.width = 0;
    if (contentRect.height < 0)
      contentRect.height = 0;
  }

  /**
   * Calculates the position of the thumbRect based on the current value of
   * the slider. It must take into  account the orientation of the slider.
   */
  protected void calculateThumbLocation()
  {
    int value = slider.getValue();

    if (slider.getOrientation() == JSlider.HORIZONTAL)
      {
        thumbRect.x = xPositionForValue(value) - thumbRect.width / 2;
        thumbRect.y = trackRect.y + 1;
      }
    else
      {
        thumbRect.x = trackRect.x + 1;
        thumbRect.y = yPositionForValue(value) - thumbRect.height / 2;
      }
  }

  /**
   * Calculates the gap size between the edge of the <code>contentRect</code> 
   * and the edge of the <code>trackRect</code>, storing the result in the
   * <code>trackBuffer</code> field.  Sufficient space needs to be reserved 
   * for the slider thumb and/or the labels at each end of the slider track.
   */
  protected void calculateTrackBuffer()
  {
    if (slider.getOrientation() == JSlider.HORIZONTAL)
      {
        int w = Math.max(getWidthOfLowValueLabel(), getWidthOfHighValueLabel());
        trackBuffer = Math.max(thumbRect.width / 2, w / 2);
        
      }
    else
      {
        int h = Math.max(getHeightOfLowValueLabel(), 
                         getHeightOfHighValueLabel());
        trackBuffer = Math.max(thumbRect.height / 2, h / 2);
      }
  }

  /**
   * Returns the size of the slider's thumb.  The size is hard coded to
   * <code>11 x 20</code> for horizontal sliders, and <code>20 x 11</code> for 
   * vertical sliders. Note that a new instance of {@link Dimension} is 
   * returned for every call to this method (this seems wasteful, but 
   * {@link Dimension} instances are not immutable, so this is probably 
   * unavoidable).
   *
   * @return The size of the slider's thumb.
   */
  protected Dimension getThumbSize()
  {
    if (slider.getOrientation() == JSlider.HORIZONTAL)
      return new Dimension(11, 20);
    else
      return new Dimension(20, 11);
  }

  /**
   * Calculates the size and position of the trackRect. It must take into
   * account the orientation of the slider.
   */
  protected void calculateTrackRect()
  {
    if (slider.getOrientation() == JSlider.HORIZONTAL)
      {
        trackRect.x = contentRect.x + trackBuffer;
        int h = getThumbSize().height;
        if (slider.getPaintTicks() && (slider.getMajorTickSpacing() > 0 
            || slider.getMinorTickSpacing() > 0))
          h += getTickLength();
        if (slider.getPaintLabels())
          h += getHeightOfTallestLabel();
        trackRect.y = contentRect.y + (contentRect.height - h) / 2 - 1;
        trackRect.width = contentRect.width - 2 * trackBuffer;
        trackRect.height = thumbRect.height;
      }
    else
      {
        int w = getThumbSize().width;
        if (slider.getPaintTicks() && (slider.getMajorTickSpacing() > 0
            || slider.getMinorTickSpacing() > 0))
          w += getTickLength();  
        if (slider.getPaintLabels())
          w += getWidthOfWidestLabel();
        trackRect.x = contentRect.x + (contentRect.width - w) / 2 - 1;
        trackRect.y = contentRect.y + trackBuffer;
        trackRect.width = thumbRect.width;
        trackRect.height = contentRect.height - 2 * trackBuffer;
      }
  }

  /**
   * This method returns the height of the tick area box if the slider  is
   * horizontal and the width of the tick area box is the slider is vertical.
   * It not necessarily how long the ticks will be. If a gap between the edge
   * of tick box and the actual tick is desired, then that will need to be
   * handled in the tick painting methods.
   *
   * @return The height (or width if the slider is vertical) of the tick
   *         rectangle.
   */
  protected int getTickLength()
  {
    return 8;
  }

  /**
   * This method calculates the size and position of the tickRect. It must
   * take into account the orientation of the slider.
   */
  protected void calculateTickRect()
  {
    if (slider.getOrientation() == JSlider.HORIZONTAL)
      {
        tickRect.x = trackRect.x;
        tickRect.y = trackRect.y + trackRect.height;
        tickRect.width = trackRect.width;
        tickRect.height = slider.getPaintTicks() ? getTickLength() : 0;
        
        // this makes our Mauve tests pass...can't explain it!
        if (!slider.getPaintTicks())
          tickRect.y--;

        if (tickRect.y + tickRect.height > contentRect.y + contentRect.height)
          tickRect.height = contentRect.y + contentRect.height - tickRect.y;
      }
    else
      {
        tickRect.x = trackRect.x + trackRect.width;
        tickRect.y = trackRect.y;
        tickRect.width = slider.getPaintTicks() ? getTickLength() : 0;
        tickRect.height = trackRect.height;

        // this makes our Mauve tests pass...can't explain it!
        if (!slider.getPaintTicks())
          tickRect.x--;

        if (tickRect.x + tickRect.width > contentRect.x + contentRect.width)
          tickRect.width = contentRect.x + contentRect.width - tickRect.x;
      }
  }

  /**
   * Calculates the <code>labelRect</code> field, taking into account the 
   * orientation of the slider.
   */
  protected void calculateLabelRect()
  {
    if (slider.getOrientation() == JSlider.HORIZONTAL)
      {
        if (slider.getPaintLabels())
          {
            labelRect.x = contentRect.x;
            labelRect.y = tickRect.y + tickRect.height - 1;
            labelRect.width = contentRect.width;
          }
        else
          {
            labelRect.x = trackRect.x;
            labelRect.y = tickRect.y + tickRect.height;
            labelRect.width = trackRect.width;
          }
        labelRect.height = getHeightOfTallestLabel();
      }
    else
      {
        if (slider.getPaintLabels())
          {
            labelRect.x = tickRect.x + tickRect.width - 1;
            labelRect.y = contentRect.y;
            labelRect.height = contentRect.height;
          }
        else
          {
            labelRect.x = tickRect.x + tickRect.width;
            labelRect.y = trackRect.y;
            labelRect.height = trackRect.height;
          }
        labelRect.width = getWidthOfWidestLabel();
      }
  }

  /**
   * This method returns the width of the widest label  in the slider's label
   * table.
   *
   * @return The width of the widest label or 0 if no label table exists.
   */
  protected int getWidthOfWidestLabel()
  {
    int widest = 0;
    Component label;

    if (slider.getLabelTable() == null)
      return 0;

    Dimension pref;
    for (Enumeration list = slider.getLabelTable().elements();
         list.hasMoreElements();)
      {
        Object comp = list.nextElement();
        if (! (comp instanceof Component))
          continue;
        label = (Component) comp;
        pref = label.getPreferredSize();
        if (pref != null && pref.width > widest)
          widest = pref.width;
      }
    return widest;
  }

  /**
   * This method returns the height of the tallest label in the slider's label
   * table.
   *
   * @return The height of the tallest label or 0 if no label table exists.
   */
  protected int getHeightOfTallestLabel()
  {
    int tallest = 0;
    Component label;

    if (slider.getLabelTable() == null)
      return 0;
    Dimension pref;
    for (Enumeration list = slider.getLabelTable().elements();
         list.hasMoreElements();)
      {
        Object comp = list.nextElement();
        if (! (comp instanceof Component))
          continue;
        label = (Component) comp;
        pref = label.getPreferredSize();
        if (pref != null && pref.height > tallest)
          tallest = pref.height;
      }
    return tallest;
  }

  /**
   * Returns the width of the label whose key has the highest value, or 0 if
   * there are no labels.
   *
   * @return The width of the label whose key has the highest value.
   * 
   * @see #getHighestValueLabel()
   */
  protected int getWidthOfHighValueLabel()
  {
    Component highValueLabel = getHighestValueLabel();
    if (highValueLabel != null)
      return highValueLabel.getPreferredSize().width;
    else
      return 0;
  }

  /**
   * Returns the width of the label whose key has the lowest value, or 0 if
   * there are no labels.
   *
   * @return The width of the label whose key has the lowest value.
   * 
   * @see #getLowestValueLabel()
   */
  protected int getWidthOfLowValueLabel()
  {
    Component lowValueLabel = getLowestValueLabel();
    if (lowValueLabel != null)
      return lowValueLabel.getPreferredSize().width;
    else
      return 0;
  }

  /**
   * Returns the height of the label whose key has the highest value, or 0 if
   * there are no labels.
   *
   * @return The height of the high value label or 0 if no label table exists.
   */
  protected int getHeightOfHighValueLabel()
  {
    Component highValueLabel = getHighestValueLabel();
    if (highValueLabel != null)
      return highValueLabel.getPreferredSize().height;
    else
      return 0;
  }

  /**
   * Returns the height of the label whose key has the lowest value, or 0 if
   * there are no labels.
   *
   * @return The height of the low value label or 0 if no label table exists.
   */
  protected int getHeightOfLowValueLabel()
  {
    Component lowValueLabel = getLowestValueLabel();
    if (lowValueLabel != null)
      return lowValueLabel.getPreferredSize().height;
    else
      return 0;
  }

  /**
   * Returns <code>true</code> if the slider scale is to be drawn inverted,
   * and <code>false</code> if not.
   *
   * @return <code>true</code> if the slider is to be drawn inverted.
   */
  protected boolean drawInverted()
  {
    return slider.getInverted();
  }

  /**
   * This method returns the label whose key has the lowest value.
   *
   * @return The low value label or null if no label table exists.
   */
  protected Component getLowestValueLabel()
  {
    Integer key = new Integer(Integer.MAX_VALUE);
    Integer tmpKey;
    Dictionary labelTable = slider.getLabelTable();

    if (labelTable == null)
      return null;

    for (Enumeration list = labelTable.keys(); list.hasMoreElements();)
      {
        Object value = list.nextElement();
        if (! (value instanceof Integer))
          continue;
        tmpKey = (Integer) value;
        if (tmpKey.intValue() < key.intValue())
          key = tmpKey;
      }
    Object comp = labelTable.get(key);
    if (! (comp instanceof Component))
      return null;
    return (Component) comp;
  }

  /**
   * Returns the label whose key has the highest value.
   *
   * @return The label whose key has the highest value or <code>null</code> if 
   *     no label table exists.
   */
  protected Component getHighestValueLabel()
  {
    Integer key = new Integer(Integer.MIN_VALUE);
    Integer tmpKey;
    Dictionary labelTable = slider.getLabelTable();

    if (labelTable == null)
      return null;

    for (Enumeration list = labelTable.keys(); list.hasMoreElements();)
      {
        Object value = list.nextElement();
        if (! (value instanceof Integer))
          continue;
        tmpKey = (Integer) value;
        if (tmpKey.intValue() > key.intValue())
          key = tmpKey;
      }
    Object comp = labelTable.get(key);
    if (! (comp instanceof Component))
      return null;
    return (Component) comp;
  }

  /**
   * This method is used to paint the {@link JSlider}. It delegates all its
   * duties to the various paint methods like paintTicks(),  paintTrack(),
   * paintThumb(), etc.
   *
   * @param g The {@link Graphics} object to paint with.
   * @param c The {@link JComponent} that is being painted.
   */
  public void paint(Graphics g, JComponent c)
  {
    // FIXME: Move this to propertyChangeEvent handler, when we get those.
    leftToRightCache = slider.getComponentOrientation() 
        != ComponentOrientation.RIGHT_TO_LEFT;
    // FIXME: This next line is only here because the above line is here.
    calculateGeometry();

    if (slider.getPaintTrack())
      paintTrack(g);
    if (slider.getPaintTicks())
      paintTicks(g);
    if (slider.getPaintLabels())
      paintLabels(g);
    
    paintThumb(g);
    
    if (hasFocus)
      paintFocus(g);
  }

  /**
   * This method recalculates any rectangles that need to be recalculated
   * after the insets of the component have changed.
   */
  protected void recalculateIfInsetsChanged()
  {
    // Examining a test program shows that either Sun calls private
    // methods that we don't know about, or these don't do anything.
    calculateFocusRect();

    calculateContentRect();
    calculateThumbSize();
    calculateTrackBuffer();
    calculateTrackRect();
    calculateThumbLocation();

    calculateTickRect();
    calculateLabelRect();
  }

  /**
   * This method recalculates any rectangles that need to be recalculated
   * after the orientation of the slider changes.
   */
  protected void recalculateIfOrientationChanged()
  {
    // Examining a test program shows that either Sun calls private
    // methods that we don't know about, or these don't do anything.  
    calculateThumbSize();
    calculateTrackBuffer();
    calculateTrackRect();
    calculateThumbLocation();

    calculateTickRect();
    calculateLabelRect();
  }

  /**
   * This method is called during a repaint if the slider has focus. It draws
   * an outline of the  focusRect using the color returned by
   * getFocusColor().
   *
   * @param g The {@link Graphics} object to draw with.
   */
  public void paintFocus(Graphics g)
  {
    Color saved_color = g.getColor();

    g.setColor(getFocusColor());
    
    g.drawRect(focusRect.x, focusRect.y, focusRect.width, focusRect.height);

    g.setColor(saved_color);
  }

  /**
   * <p>
   * This method is called during a repaint if the  track is to be drawn. It
   * draws a 3D rectangle to  represent the track. The track is not the size
   * of the trackRect. The top and left edges of the track should be outlined
   * with the shadow color. The bottom and right edges should be outlined
   * with the highlight color.
   * </p>
   * <pre>
   *    a---d   
   *    |   |   
   *    |   |   a------------------------d
   *    |   |   |                        |
   *    |   |   b------------------------c
   *    |   |
   *    |   |   
   *    b---c
   * </pre>
   * 
   * <p>
   * The b-a-d path needs to be drawn with the shadow color and the b-c-d path
   * needs to be drawn with the highlight color.
   * </p>
   *
   * @param g The {@link Graphics} object to draw with.
   */
  public void paintTrack(Graphics g)
  {
    Color saved_color = g.getColor();
    int width;
    int height;

    Point a = new Point(trackRect.x, trackRect.y + 1);
    Point b = new Point(a);
    Point c = new Point(a);
    Point d = new Point(a);

    if (slider.getOrientation() == JSlider.HORIZONTAL)
      {
        width = trackRect.width;
        height = (thumbRect.height / 4 == 0) ? 1 : thumbRect.height / 4;

        a.translate(0, (trackRect.height / 2) - (height / 2));
        b.translate(0, (trackRect.height / 2) + (height / 2));
        c.translate(trackRect.width, (trackRect.height / 2) + (height / 2));
        d.translate(trackRect.width, (trackRect.height / 2) - (height / 2));
      }
    else
      {
        width = (thumbRect.width / 4 == 0) ? 1 : thumbRect.width / 4;
        height = trackRect.height;

        a.translate((trackRect.width / 2) - (width / 2), 0);
        b.translate((trackRect.width / 2) - (width / 2), trackRect.height);
        c.translate((trackRect.width / 2) + (width / 2), trackRect.height);
        d.translate((trackRect.width / 2) + (width / 2), 0);
      }
    g.setColor(Color.GRAY);
    g.fillRect(a.x, a.y, width, height);

    g.setColor(getHighlightColor());
    g.drawLine(b.x, b.y, c.x, c.y);
    g.drawLine(c.x, c.y, d.x, d.y);

    g.setColor(getShadowColor());
    g.drawLine(b.x, b.y, a.x, a.y);
    g.drawLine(a.x, a.y, d.x, d.y);

    g.setColor(saved_color);
  }

  /**
   * This method is called during a repaint if the ticks are to be drawn. This
   * method must still verify that the majorTickSpacing and minorTickSpacing
   * are greater than zero before drawing the ticks.
   *
   * @param g The {@link Graphics} object to draw with.
   */
  public void paintTicks(Graphics g)
  {
    int max = slider.getMaximum();
    int min = slider.getMinimum();
    int majorSpace = slider.getMajorTickSpacing();
    int minorSpace = slider.getMinorTickSpacing();

    if (majorSpace > 0)
      {
        if (slider.getOrientation() == JSlider.HORIZONTAL)
          {
            g.translate(0, tickRect.y);
            for (int i = min; i <= max; i += majorSpace)
              paintMajorTickForHorizSlider(g, tickRect, xPositionForValue(i));
            g.translate(0, -tickRect.y);
          }
        else // JSlider.VERTICAL
          {
            g.translate(tickRect.x, 0);
            for (int i = min; i <= max; i += majorSpace)
              paintMajorTickForVertSlider(g, tickRect, yPositionForValue(i));
            g.translate(-tickRect.x, 0);
          }
      }
    if (minorSpace > 0)
      {
        if (slider.getOrientation() == JSlider.HORIZONTAL)
          {
            g.translate(0, tickRect.y);
            for (int i = min; i <= max; i += minorSpace)
              paintMinorTickForHorizSlider(g, tickRect, xPositionForValue(i));
            g.translate(0, -tickRect.y);
          }
        else
          {
            g.translate(tickRect.x, 0);
            for (int i = min; i <= max; i += minorSpace)
              paintMinorTickForVertSlider(g, tickRect, yPositionForValue(i));
            g.translate(-tickRect.x, 0);
          }
      }
  }

  /* Minor ticks start at 1/4 of the height (or width) of the tickRect and 
     extend to 1/2 of the tickRect.

     Major ticks start at 1/4 of the height and extend to 3/4.
   */

  /**
   * This method paints a minor tick for a horizontal slider at the given x
   * value. x represents the x coordinate to paint at.
   *
   * @param g The {@link Graphics} object to draw with.
   * @param tickBounds The tickRect rectangle.
   * @param x The x coordinate to draw the tick at.
   */
  protected void paintMinorTickForHorizSlider(Graphics g,
                                              Rectangle tickBounds, int x)
  {
    int y = tickRect.height / 4;
    Color saved = g.getColor();
    g.setColor(Color.BLACK);

    g.drawLine(x, y, x, y + tickRect.height / 4);
    g.setColor(saved);
  }

  /**
   * This method paints a major tick for a horizontal slider at the given x
   * value. x represents the x coordinate to paint at.
   *
   * @param g The {@link Graphics} object to draw with.
   * @param tickBounds The tickRect rectangle.
   * @param x The x coordinate to draw the tick at.
   */
  protected void paintMajorTickForHorizSlider(Graphics g,
                                              Rectangle tickBounds, int x)
  {
    int y = tickRect.height / 4;
    Color saved = g.getColor();
    g.setColor(Color.BLACK);

    g.drawLine(x, y, x, y + tickRect.height / 2);
    g.setColor(saved);
  }

  /**
   * This method paints a minor tick for a vertical slider at the given y
   * value. y represents the y coordinate to paint at.
   *
   * @param g The {@link Graphics} object to draw with.
   * @param tickBounds The tickRect rectangle.
   * @param y The y coordinate to draw the tick at.
   */
  protected void paintMinorTickForVertSlider(Graphics g, Rectangle tickBounds,
                                             int y)
  {
    int x = tickRect.width / 4;
    Color saved = g.getColor();
    g.setColor(Color.BLACK);

    g.drawLine(x, y, x + tickRect.width / 4, y);
    g.setColor(saved);
  }

  /**
   * This method paints a major tick for a vertical slider at the given y
   * value. y represents the y coordinate to paint at.
   *
   * @param g The {@link Graphics} object to draw with.
   * @param tickBounds The tickRect rectangle.
   * @param y The y coordinate to draw the tick at.
   */
  protected void paintMajorTickForVertSlider(Graphics g, Rectangle tickBounds,
                                             int y)
  {
    int x = tickRect.width / 4;
    Color saved = g.getColor();
    g.setColor(Color.BLACK);

    g.drawLine(x, y, x + tickRect.width / 2, y);
    g.setColor(saved);
  }

  /**
   * This method paints all the labels from the slider's label table. This
   * method must make sure that the label table is not null before painting
   * the labels. Each entry in the label table is a (integer, component)
   * pair. Every label is painted at the value of the integer.
   *
   * @param g The {@link Graphics} object to draw with.
   */
  public void paintLabels(Graphics g)
  {
    if (slider.getLabelTable() != null)
      {
        Dictionary table = slider.getLabelTable();
        Integer tmpKey;
        Object key;
        Object element;
        Component label;
        if (slider.getOrientation() == JSlider.HORIZONTAL)
          {
            for (Enumeration list = table.keys(); list.hasMoreElements();)
              {
                key = list.nextElement();
                if (! (key instanceof Integer))
                  continue;
                tmpKey = (Integer) key;
                element = table.get(tmpKey);
                // We won't paint them if they're not
                // JLabels so continue anyway
                if (! (element instanceof JLabel))
                  continue;
                label = (Component) element;
                paintHorizontalLabel(g, tmpKey.intValue(), label);
              }
          }
        else
          {
            for (Enumeration list = table.keys(); list.hasMoreElements();)
              {
                key = list.nextElement();
                if (! (key instanceof Integer))
                  continue;
                tmpKey = (Integer) key;
                element = table.get(tmpKey);
                // We won't paint them if they're not
                // JLabels so continue anyway
                if (! (element instanceof JLabel))
                  continue;
                label = (Component) element;
                paintVerticalLabel(g, tmpKey.intValue(), label);
              }
          }
      }
  }

  /**
   * This method paints the label on the horizontal slider at the value
   * specified. The value is not a coordinate. It is a value within the range
   * of the  slider. If the value is not within the range of the slider, this
   * method will do nothing. This method should not paint outside the
   * boundaries of the labelRect.
   *
   * @param g The {@link Graphics} object to draw with.
   * @param value The value to paint at.
   * @param label The label to paint.
   */
  protected void paintHorizontalLabel(Graphics g, int value, Component label)
  {
    // This relies on clipping working properly or we'll end up
    // painting all over the place. If our preferred size is ignored, then
    // the labels may not fit inside the slider's bounds. Rather than mucking 
    // with font sizes and possible icon sizes, we'll set the bounds for
    // the label and let it get clipped.
    Dimension dim = label.getPreferredSize();
    int w = (int) dim.getWidth();
    int h = (int) dim.getHeight();

    int max = slider.getMaximum();
    int min = slider.getMinimum();

    if (value > max || value < min)
      return;

    //           value
    //             |
    //        ------------
    //        |          |
    //        |          |
    //        |          |
    //  The label must move w/2 to the right to fit directly under the value.
    int xpos = xPositionForValue(value) - w / 2;
    int ypos = labelRect.y;

    // We want to center the label around the xPositionForValue
    // So we use xpos - w / 2. However, if value is min and the label 
    // is large, we run the risk of going out of bounds. So we bring it back
    // to 0 if it becomes negative.
    if (xpos < 0)
      xpos = 0;

    // If the label + starting x position is greater than
    // the x space in the label rectangle, we reset it to the largest
    // amount possible in the rectangle. This means ugliness.
    if (xpos + w > labelRect.x + labelRect.width)
      w = labelRect.x + labelRect.width - xpos;

    // If the label is too tall. We reset it to the height of the label
    // rectangle.
    if (h > labelRect.height)
      h = labelRect.height;

    label.setBounds(xpos, ypos, w, h);
    SwingUtilities.paintComponent(g, label, null, label.getBounds());
  }

  /**
   * This method paints the label on the vertical slider at the value
   * specified. The value is not a coordinate. It is a value within the range
   * of the  slider. If the value is not within the range of the slider, this
   * method will do nothing. This method should not paint outside the
   * boundaries of the labelRect.
   *
   * @param g The {@link Graphics} object to draw with.
   * @param value The value to paint at.
   * @param label The label to paint.
   */
  protected void paintVerticalLabel(Graphics g, int value, Component label)
  {
    Dimension dim = label.getPreferredSize();
    int w = (int) dim.getWidth();
    int h = (int) dim.getHeight();

    int max = slider.getMaximum();
    int min = slider.getMinimum();

    if (value > max || value < min)
      return;

    int xpos = labelRect.x;
    int ypos = yPositionForValue(value) - h / 2;

    if (ypos < 0)
      ypos = 0;

    if (ypos + h > labelRect.y + labelRect.height)
      h = labelRect.y + labelRect.height - ypos;

    if (w > labelRect.width)
      w = labelRect.width;

    label.setBounds(xpos, ypos, w, h);
    SwingUtilities.paintComponent(g, label, null, label.getBounds());
  }

  /**
   * <p>
   * This method paints a thumb. There are two types of thumb:
   * </p>
   * <pre>
   *   Vertical         Horizontal
   *    a---b            a-----b
   *    |   |            |      \
   *    e   c            |       c
   *     \ /             |      /
   *      d              e-----d
   *  </pre>
   * 
   * <p>
   * In the case of vertical thumbs, we highlight the path b-a-e-d and shadow
   * the path b-c-d. In the case of horizontal thumbs, we highlight the path
   * c-b-a-e and shadow the path c-d-e. In both cases we fill the path
   * a-b-c-d-e before shadows and highlights are drawn.
   * </p>
   *
   * @param g The graphics object to paint with
   */
  public void paintThumb(Graphics g)
  {
    Color saved_color = g.getColor();

    Point a = new Point(thumbRect.x, thumbRect.y);
    Point b = new Point(a);
    Point c = new Point(a);
    Point d = new Point(a);
    Point e = new Point(a);

    Polygon bright;
    Polygon light; // light shadow
    Polygon dark; // dark shadow
    Polygon all;

    // This will be in X-dimension if the slider is inverted and y if it isn't.
    int turnPoint;

    if (slider.getOrientation() == JSlider.HORIZONTAL)
      {
        turnPoint = thumbRect.height * 3 / 4;

        b.translate(thumbRect.width - 1, 0);
        c.translate(thumbRect.width - 1, turnPoint);
        d.translate(thumbRect.width / 2 - 1, thumbRect.height - 1);
        e.translate(0, turnPoint);

        bright = new Polygon(new int[] { b.x - 1, a.x, e.x, d.x },
                             new int[] { b.y, a.y, e.y, d.y }, 4);

        dark = new Polygon(new int[] { b.x, c.x, d.x + 1 }, new int[] { b.y,
                                                                       c.y - 1,
                                                                       d.y }, 3);

        light = new Polygon(new int[] { b.x - 1, c.x - 1, d.x + 1 },
                            new int[] { b.y + 1, c.y - 1, d.y - 1 }, 3);

        all = new Polygon(
                          new int[] { a.x + 1, b.x - 2, c.x - 2, d.x, e.x + 1 },
                          new int[] { a.y + 1, b.y + 1, c.y - 1, d.y - 1, e.y },
                          5);
      }
    else
      {
        turnPoint = thumbRect.width * 3 / 4 - 1;

        b.translate(turnPoint, 0);
        c.translate(thumbRect.width - 1, thumbRect.height / 2);
        d.translate(turnPoint, thumbRect.height - 1);
        e.translate(0, thumbRect.height - 1);

        bright = new Polygon(new int[] { c.x - 1, b.x, a.x, e.x },
                             new int[] { c.y - 1, b.y, a.y, e.y - 1 }, 4);

        dark = new Polygon(new int[] { c.x, d.x, e.x }, new int[] { c.y, d.y,
                                                                   e.y }, 3);

        light = new Polygon(new int[] { c.x - 1, d.x, e.x + 1 },
                            new int[] { c.y, d.y - 1, e.y - 1 }, 3);
        all = new Polygon(new int[] { a.x + 1, b.x, c.x - 2, c.x - 2, d.x,
                                     e.x + 1 }, new int[] { a.y + 1, b.y + 1,
                                                           c.y - 1, c.y,
                                                           d.y - 2, e.y - 2 },
                          6);
      }

    g.setColor(Color.WHITE);
    g.drawPolyline(bright.xpoints, bright.ypoints, bright.npoints);

    g.setColor(Color.BLACK);
    g.drawPolyline(dark.xpoints, dark.ypoints, dark.npoints);

    g.setColor(Color.GRAY);
    g.drawPolyline(light.xpoints, light.ypoints, light.npoints);

    g.setColor(Color.LIGHT_GRAY);
    g.drawPolyline(all.xpoints, all.ypoints, all.npoints);
    g.fillPolygon(all);

    g.setColor(saved_color);
  }

  /**
   * This method sets the position of the thumbRect.
   *
   * @param x The new x position.
   * @param y The new y position.
   */
  public void setThumbLocation(int x, int y)
  {
    thumbRect.x = x;
    thumbRect.y = y;
  }

  /**
   * Moves the thumb one block in the direction specified (a block is 1/10th
   * of the slider range).   If the slider snaps to ticks, this method is 
   * responsible for snapping it to a tick after the thumb has been moved.
   *
   * @param direction  the direction (positive values increment the thumb 
   *   position by one block, zero/negative values decrement the thumb position
   *   by one block).
   */
  public void scrollByBlock(int direction)
  {
    int unit = (slider.getMaximum() - slider.getMinimum()) / 10;
    int moveTo = slider.getValue();
    if (direction > 0)
      moveTo += unit;
    else
      moveTo -= unit;

    if (slider.getSnapToTicks())
      moveTo = findClosestTick(moveTo);

    slider.setValue(moveTo);
  }

  /**
   * Moves the thumb one unit in the specified direction. If the slider snaps 
   * to ticks, this method is responsible for snapping it to a tick after the 
   * thumb has been moved.
   *
   * @param direction  the direction (positive values increment the thumb 
   *   position by one, zero/negative values decrement the thumb position by
   *   one).
   */
  public void scrollByUnit(int direction)
  {
    int moveTo = slider.getValue();
    if (direction > 0)
      moveTo++;
    else
      moveTo--;

    if (slider.getSnapToTicks())
      moveTo = findClosestTick(moveTo);

    slider.setValue(moveTo);
  }

  /**
   * This method is called when there has been a click in the track and the
   * thumb needs to be scrolled  on regular intervals. This method is only
   * responsible  for starting the timer and not for stopping it.
   *
   * @param dir The direction to move in.
   */
  protected void scrollDueToClickInTrack(int dir)
  {
    scrollTimer.stop();

    scrollListener.setDirection(dir);
    scrollListener.setScrollByBlock(true);

    scrollTimer.start();
  }

  /**
   * Returns the x-coordinate (relative to the component) for the given slider 
   * value.  This method assumes that the <code>trackRect</code> field is
   * set up.
   *
   * @param value  the slider value.
   *
   * @return The x-coordinate.
   */
  protected int xPositionForValue(int value)
  {
    double min = slider.getMinimum();
    if (value < min)
      value = (int) min;
    double max = slider.getMaximum();
    if (value > max)
      value = (int) max;
    double len = trackRect.width;
    if ((max - min) <= 0.0)
      return 0;
    int xPos = (int) ((value - min) / (max - min) * len + 0.5);

    if (drawInverted())
      return trackRect.x + Math.max(trackRect.width - xPos - 1, 0);
    else
      return trackRect.x + Math.min(xPos, trackRect.width - 1);
  }

  /**
   * Returns the y-coordinate (relative to the component) for the given slider 
   * value.  This method assumes that the <code>trackRect</code> field is 
   * set up.
   *
   * @param value  the slider value.
   *
   * @return The y-coordinate.
   */
  protected int yPositionForValue(int value)
  {
    double min = slider.getMinimum();
    if (value < min)
      value = (int) min;
    double max = slider.getMaximum();
    if (value > max)
      value = (int) max;
    int len = trackRect.height;
    if ((max - min) <= 0.0)
      return 0;

    int yPos = (int) ((value - min) / (max - min) * len + 0.5);

    if (! drawInverted())
      return trackRect.y + trackRect.height - Math.max(yPos, 1);
    else
      return trackRect.y + Math.min(yPos, trackRect.height - 1);
  }

  /**
   * This method returns the value in the slider'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.
   */
  public int valueForYPosition(int yPos)
  {
    int min = slider.getMinimum();
    int max = slider.getMaximum();
    int len = trackRect.height;

    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;

    if (! drawInverted())
      value = (len - (yPos - trackRect.y)) * (max - min) / len + min;
    else
      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 slider'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.
   */
  public int valueForXPosition(int xPos)
  {
    int min = slider.getMinimum();
    int max = slider.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;

    if (! drawInverted())
      value = (xPos - trackRect.x) * (max - min) / len + min;
    else
      value = (len - (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;
  }

  /**
   * This method finds the closest value that has a tick associated with it.
   * This is package-private to avoid an accessor method.
   *
   * @param value The value to search from.
   *
   * @return The closest value that has a tick associated with it.
   */
  int findClosestTick(int value)
  {
    int min = slider.getMinimum();
    int max = slider.getMaximum();
    int majorSpace = slider.getMajorTickSpacing();
    int minorSpace = slider.getMinorTickSpacing();

    // The default value to return is value + minor or
    // value + major. 
    // Initializing at min - value leaves us with a default
    // return value of min, which always has tick marks
    // (if ticks are painted).
    int minor = min - value;
    int major = min - value;

    // If there are no major tick marks or minor tick marks 
    // e.g. snap is set to true but no ticks are set, then
    // we can just return the value.
    if (majorSpace <= 0 && minorSpace <= 0)
      return value;

    // First check the major ticks.
    if (majorSpace > 0)
      {
        int lowerBound = (value - min) / majorSpace;
        int majLower = majorSpace * lowerBound + min;
        int majHigher = majorSpace * (lowerBound + 1) + min;

        if (majHigher <= max && majHigher - value <= value - majLower)
          major = majHigher - value;
        else
          major = majLower - value;
      }

    if (minorSpace > 0)
      {
        int lowerBound = value / minorSpace;
        int minLower = minorSpace * lowerBound;
        int minHigher = minorSpace * (lowerBound + 1);

        if (minHigher <= max && minHigher - value <= value - minLower)
          minor = minHigher - value;
        else
          minor = minLower - value;
      }

    // Give preference to minor ticks
    if (Math.abs(minor) > Math.abs(major))
      return value + major;
    else
      return value + minor;
  }
  
  InputMap getInputMap(int condition) 
  {
    if (condition == JComponent.WHEN_FOCUSED)
      return (InputMap) UIManager.get("Slider.focusInputMap");
    return null;
  }

  /**
   * Returns the action map for the {@link JSlider}.  All sliders share
   * a single action map which is created the first time this method is 
   * called, then stored in the UIDefaults table for subsequent access.
   * 
   * @return The shared action map.
   */
  ActionMap getActionMap() 
  {
    ActionMap map = (ActionMap) UIManager.get("Slider.actionMap");

    if (map == null) // first time here
      {
        map = createActionMap();
        if (map != null)
          UIManager.put("Slider.actionMap", map);
      }
    return map;
  }

  /**
   * Creates the action map shared by all {@link JSlider} instances.
   * This method is called once by {@link #getActionMap()} when it 
   * finds no action map in the UIDefaults table...after the map is 
   * created, it gets added to the defaults table so that subsequent 
   * calls to {@link #getActionMap()} will return the same shared 
   * instance.
   * 
   * @return The action map.
   */
  ActionMap createActionMap()
  {
    ActionMap map = new ActionMapUIResource();
    map.put("positiveUnitIncrement", 
            new AbstractAction("positiveUnitIncrement") {
              public void actionPerformed(ActionEvent event)
              {
                JSlider slider = (JSlider) event.getSource();
                BasicSliderUI ui = (BasicSliderUI) slider.getUI();
                if (slider.getInverted())
                  ui.scrollByUnit(BasicSliderUI.NEGATIVE_SCROLL);
                else
                  ui.scrollByUnit(BasicSliderUI.POSITIVE_SCROLL);
              }
            }
    );
    map.put("negativeUnitIncrement", 
            new AbstractAction("negativeUnitIncrement") {
              public void actionPerformed(ActionEvent event)
              {
                JSlider slider = (JSlider) event.getSource();
                BasicSliderUI ui = (BasicSliderUI) slider.getUI();
                if (slider.getInverted())
                  ui.scrollByUnit(BasicSliderUI.POSITIVE_SCROLL);
                else
                  ui.scrollByUnit(BasicSliderUI.NEGATIVE_SCROLL);
              }
            }
    );
    map.put("positiveBlockIncrement", 
            new AbstractAction("positiveBlockIncrement") {
              public void actionPerformed(ActionEvent event)
              {
                JSlider slider = (JSlider) event.getSource();
                BasicSliderUI ui = (BasicSliderUI) slider.getUI();
                if (slider.getInverted())
                  ui.scrollByBlock(BasicSliderUI.NEGATIVE_SCROLL);
                else
                  ui.scrollByBlock(BasicSliderUI.POSITIVE_SCROLL);
              }
            }
    );
    map.put("negativeBlockIncrement", 
            new AbstractAction("negativeBlockIncrement") {
              public void actionPerformed(ActionEvent event)
              {
                JSlider slider = (JSlider) event.getSource();
                BasicSliderUI ui = (BasicSliderUI) slider.getUI();
                if (slider.getInverted())
                  ui.scrollByBlock(BasicSliderUI.POSITIVE_SCROLL);
                else
                  ui.scrollByBlock(BasicSliderUI.NEGATIVE_SCROLL);
              }
            }
    );
    map.put("minScroll", 
            new AbstractAction("minScroll") {
              public void actionPerformed(ActionEvent event)
              {
                JSlider slider = (JSlider) event.getSource();
                if (slider.getInverted())
                  slider.setValue(slider.getMaximum());
                else
                  slider.setValue(slider.getMinimum());   
              }
            }
    );
    map.put("maxScroll", 
            new AbstractAction("maxScroll") {
              public void actionPerformed(ActionEvent event)
              {
                JSlider slider = (JSlider) event.getSource();
                if (slider.getInverted())
                  slider.setValue(slider.getMinimum());
                else
                  slider.setValue(slider.getMaximum());                  
              }
            }
    );
    return map;
  }
}
