Save This Page
Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]
    1   /*
    2    * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.swing.plaf.basic;
   27   
   28   import java.awt.Component;
   29   import java.awt.Container;
   30   import java.awt.Adjustable;
   31   import java.awt.event;
   32   import java.awt.FontMetrics;
   33   import java.awt.Graphics;
   34   import java.awt.Dimension;
   35   import java.awt.Rectangle;
   36   import java.awt.Point;
   37   import java.awt.Insets;
   38   import java.awt.Color;
   39   import java.awt.IllegalComponentStateException;
   40   import java.awt.Polygon;
   41   import java.beans;
   42   import java.util.Dictionary;
   43   import java.util.Enumeration;
   44   
   45   import javax.swing.border.AbstractBorder;
   46   
   47   import javax.swing;
   48   import javax.swing.event;
   49   import javax.swing.plaf;
   50   import sun.swing.DefaultLookup;
   51   import sun.swing.UIAction;
   52   
   53   
   54   /**
   55    * A Basic L&F implementation of SliderUI.
   56    *
   57    * @author Tom Santos
   58    */
   59   public class BasicSliderUI extends SliderUI{
   60       // Old actions forward to an instance of this.
   61       private static final Actions SHARED_ACTION = new Actions();
   62   
   63       public static final int POSITIVE_SCROLL = +1;
   64       public static final int NEGATIVE_SCROLL = -1;
   65       public static final int MIN_SCROLL = -2;
   66       public static final int MAX_SCROLL = +2;
   67   
   68       protected Timer scrollTimer;
   69       protected JSlider slider;
   70   
   71       protected Insets focusInsets = null;
   72       protected Insets insetCache = null;
   73       protected boolean leftToRightCache = true;
   74       protected Rectangle focusRect = null;
   75       protected Rectangle contentRect = null;
   76       protected Rectangle labelRect = null;
   77       protected Rectangle tickRect = null;
   78       protected Rectangle trackRect = null;
   79       protected Rectangle thumbRect = null;
   80   
   81       protected int trackBuffer = 0;  // The distance that the track is from the side of the control
   82   
   83       private transient boolean isDragging;
   84   
   85       protected TrackListener trackListener;
   86       protected ChangeListener changeListener;
   87       protected ComponentListener componentListener;
   88       protected FocusListener focusListener;
   89       protected ScrollListener scrollListener;
   90       protected PropertyChangeListener propertyChangeListener;
   91       private Handler handler;
   92       private int lastValue;
   93   
   94       // Colors
   95       private Color shadowColor;
   96       private Color highlightColor;
   97       private Color focusColor;
   98   
   99       /**
  100        * Whther or not sameLabelBaselines is up to date.
  101        */
  102       private boolean checkedLabelBaselines;
  103       /**
  104        * Whether or not all the entries in the labeltable have the same
  105        * baseline.
  106        */
  107       private boolean sameLabelBaselines;
  108   
  109   
  110       protected Color getShadowColor() {
  111           return shadowColor;
  112       }
  113   
  114       protected Color getHighlightColor() {
  115           return highlightColor;
  116       }
  117   
  118       protected Color getFocusColor() {
  119           return focusColor;
  120       }
  121   
  122       /**
  123        * Returns true if the user is dragging the slider.
  124        *
  125        * @return true if the user is dragging the slider
  126        * @since 1.5
  127        */
  128       protected boolean isDragging() {
  129           return isDragging;
  130       }
  131   
  132       /////////////////////////////////////////////////////////////////////////////
  133       // ComponentUI Interface Implementation methods
  134       /////////////////////////////////////////////////////////////////////////////
  135       public static ComponentUI createUI(JComponent b)    {
  136           return new BasicSliderUI((JSlider)b);
  137       }
  138   
  139       public BasicSliderUI(JSlider b)   {
  140       }
  141   
  142       public void installUI(JComponent c)   {
  143           slider = (JSlider) c;
  144   
  145           checkedLabelBaselines = false;
  146   
  147           slider.setEnabled(slider.isEnabled());
  148           LookAndFeel.installProperty(slider, "opaque", Boolean.TRUE);
  149   
  150           isDragging = false;
  151           trackListener = createTrackListener( slider );
  152           changeListener = createChangeListener( slider );
  153           componentListener = createComponentListener( slider );
  154           focusListener = createFocusListener( slider );
  155           scrollListener = createScrollListener( slider );
  156           propertyChangeListener = createPropertyChangeListener( slider );
  157   
  158           installDefaults( slider );
  159           installListeners( slider );
  160           installKeyboardActions( slider );
  161   
  162           scrollTimer = new Timer( 100, scrollListener );
  163           scrollTimer.setInitialDelay( 300 );
  164   
  165           insetCache = slider.getInsets();
  166           leftToRightCache = BasicGraphicsUtils.isLeftToRight(slider);
  167           focusRect = new Rectangle();
  168           contentRect = new Rectangle();
  169           labelRect = new Rectangle();
  170           tickRect = new Rectangle();
  171           trackRect = new Rectangle();
  172           thumbRect = new Rectangle();
  173           lastValue = slider.getValue();
  174   
  175           calculateGeometry(); // This figures out where the labels, ticks, track, and thumb are.
  176       }
  177   
  178       public void uninstallUI(JComponent c) {
  179           if ( c != slider )
  180               throw new IllegalComponentStateException(
  181                                                       this + " was asked to deinstall() "
  182                                                       + c + " when it only knows about "
  183                                                       + slider + ".");
  184   
  185           LookAndFeel.uninstallBorder(slider);
  186   
  187           scrollTimer.stop();
  188           scrollTimer = null;
  189   
  190           uninstallListeners( slider );
  191           uninstallKeyboardActions(slider);
  192   
  193           focusInsets = null;
  194           insetCache = null;
  195           leftToRightCache = true;
  196           focusRect = null;
  197           contentRect = null;
  198           labelRect = null;
  199           tickRect = null;
  200           trackRect = null;
  201           thumbRect = null;
  202           trackListener = null;
  203           changeListener = null;
  204           componentListener = null;
  205           focusListener = null;
  206           scrollListener = null;
  207           propertyChangeListener = null;
  208           slider = null;
  209       }
  210   
  211       protected void installDefaults( JSlider slider ) {
  212           LookAndFeel.installBorder(slider, "Slider.border");
  213           LookAndFeel.installColorsAndFont(slider, "Slider.background",
  214                                            "Slider.foreground", "Slider.font");
  215           highlightColor = UIManager.getColor("Slider.highlight");
  216   
  217           shadowColor = UIManager.getColor("Slider.shadow");
  218           focusColor = UIManager.getColor("Slider.focus");
  219   
  220           focusInsets = (Insets)UIManager.get( "Slider.focusInsets" );
  221       }
  222   
  223       protected TrackListener createTrackListener(JSlider slider) {
  224           return new TrackListener();
  225       }
  226   
  227       protected ChangeListener createChangeListener(JSlider slider) {
  228           return getHandler();
  229       }
  230   
  231       protected ComponentListener createComponentListener(JSlider slider) {
  232           return getHandler();
  233       }
  234   
  235       protected FocusListener createFocusListener(JSlider slider) {
  236           return getHandler();
  237       }
  238   
  239       protected ScrollListener createScrollListener( JSlider slider ) {
  240           return new ScrollListener();
  241       }
  242   
  243       protected PropertyChangeListener createPropertyChangeListener(
  244               JSlider slider) {
  245           return getHandler();
  246       }
  247   
  248       private Handler getHandler() {
  249           if (handler == null) {
  250               handler = new Handler();
  251           }
  252           return handler;
  253       }
  254   
  255       protected void installListeners( JSlider slider ) {
  256           slider.addMouseListener(trackListener);
  257           slider.addMouseMotionListener(trackListener);
  258           slider.addFocusListener(focusListener);
  259           slider.addComponentListener(componentListener);
  260           slider.addPropertyChangeListener( propertyChangeListener );
  261           slider.getModel().addChangeListener(changeListener);
  262       }
  263   
  264       protected void uninstallListeners( JSlider slider ) {
  265           slider.removeMouseListener(trackListener);
  266           slider.removeMouseMotionListener(trackListener);
  267           slider.removeFocusListener(focusListener);
  268           slider.removeComponentListener(componentListener);
  269           slider.removePropertyChangeListener( propertyChangeListener );
  270           slider.getModel().removeChangeListener(changeListener);
  271           handler = null;
  272       }
  273   
  274       protected void installKeyboardActions( JSlider slider ) {
  275           InputMap km = getInputMap(JComponent.WHEN_FOCUSED, slider);
  276           SwingUtilities.replaceUIInputMap(slider, JComponent.WHEN_FOCUSED, km);
  277           LazyActionMap.installLazyActionMap(slider, BasicSliderUI.class,
  278                   "Slider.actionMap");
  279       }
  280   
  281       InputMap getInputMap(int condition, JSlider slider) {
  282           if (condition == JComponent.WHEN_FOCUSED) {
  283               InputMap keyMap = (InputMap)DefaultLookup.get(slider, this,
  284                     "Slider.focusInputMap");
  285               InputMap rtlKeyMap;
  286   
  287               if (slider.getComponentOrientation().isLeftToRight() ||
  288                   ((rtlKeyMap = (InputMap)DefaultLookup.get(slider, this,
  289                             "Slider.focusInputMap.RightToLeft")) == null)) {
  290                   return keyMap;
  291               } else {
  292                   rtlKeyMap.setParent(keyMap);
  293                   return rtlKeyMap;
  294               }
  295           }
  296           return null;
  297       }
  298   
  299       /**
  300        * Populates ComboBox's actions.
  301        */
  302       static void loadActionMap(LazyActionMap map) {
  303           map.put(new Actions(Actions.POSITIVE_UNIT_INCREMENT));
  304           map.put(new Actions(Actions.POSITIVE_BLOCK_INCREMENT));
  305           map.put(new Actions(Actions.NEGATIVE_UNIT_INCREMENT));
  306           map.put(new Actions(Actions.NEGATIVE_BLOCK_INCREMENT));
  307           map.put(new Actions(Actions.MIN_SCROLL_INCREMENT));
  308           map.put(new Actions(Actions.MAX_SCROLL_INCREMENT));
  309       }
  310   
  311       protected void uninstallKeyboardActions( JSlider slider ) {
  312           SwingUtilities.replaceUIActionMap(slider, null);
  313           SwingUtilities.replaceUIInputMap(slider, JComponent.WHEN_FOCUSED,
  314                                            null);
  315       }
  316   
  317   
  318       /**
  319        * Returns the baseline.
  320        *
  321        * @throws NullPointerException {@inheritDoc}
  322        * @throws IllegalArgumentException {@inheritDoc}
  323        * @see javax.swing.JComponent#getBaseline(int, int)
  324        * @since 1.6
  325        */
  326       public int getBaseline(JComponent c, int width, int height) {
  327           super.getBaseline(c, width, height);
  328           if (slider.getPaintLabels() && labelsHaveSameBaselines()) {
  329               FontMetrics metrics = slider.getFontMetrics(slider.getFont());
  330               Insets insets = slider.getInsets();
  331               Dimension thumbSize = getThumbSize();
  332               if (slider.getOrientation() == JSlider.HORIZONTAL) {
  333                   int tickLength = getTickLength();
  334                   int contentHeight = height - insets.top - insets.bottom -
  335                       focusInsets.top - focusInsets.bottom;
  336                   int thumbHeight = thumbSize.height;
  337                   int centerSpacing = thumbHeight;
  338                   if (slider.getPaintTicks()) {
  339                       centerSpacing += tickLength;
  340                   }
  341                   // Assume uniform labels.
  342                   centerSpacing += getHeightOfTallestLabel();
  343                   int trackY = insets.top + focusInsets.top +
  344                       (contentHeight - centerSpacing - 1) / 2;
  345                   int trackHeight = thumbHeight;
  346                   int tickY = trackY + trackHeight;
  347                   int tickHeight = tickLength;
  348                   if (!slider.getPaintTicks()) {
  349                       tickHeight = 0;
  350                   }
  351                   int labelY = tickY + tickHeight;
  352                   return labelY + metrics.getAscent();
  353               }
  354               else { // vertical
  355                   boolean inverted = slider.getInverted();
  356                   Integer value = inverted ? getLowestValue() :
  357                                              getHighestValue();
  358                   if (value != null) {
  359                       int thumbHeight = thumbSize.height;
  360                       int trackBuffer = Math.max(metrics.getHeight() / 2,
  361                                                  thumbHeight / 2);
  362                       int contentY = focusInsets.top + insets.top;
  363                       int trackY = contentY + trackBuffer;
  364                       int trackHeight = height - focusInsets.top -
  365                           focusInsets.bottom - insets.top - insets.bottom -
  366                           trackBuffer - trackBuffer;
  367                       int yPosition = yPositionForValue(value, trackY,
  368                                                         trackHeight);
  369                       return yPosition - metrics.getHeight() / 2 +
  370                           metrics.getAscent();
  371                   }
  372               }
  373           }
  374           return 0;
  375       }
  376   
  377       /**
  378        * Returns an enum indicating how the baseline of the component
  379        * changes as the size changes.
  380        *
  381        * @throws NullPointerException {@inheritDoc}
  382        * @see javax.swing.JComponent#getBaseline(int, int)
  383        * @since 1.6
  384        */
  385       public Component.BaselineResizeBehavior getBaselineResizeBehavior(
  386               JComponent c) {
  387           super.getBaselineResizeBehavior(c);
  388           // NOTE: BasicSpinner really provides for CENTER_OFFSET, but
  389           // the default min/pref size is smaller than it should be
  390           // so that getBaseline() doesn't implement the contract
  391           // for CENTER_OFFSET as defined in Component.
  392           return Component.BaselineResizeBehavior.OTHER;
  393       }
  394   
  395       /**
  396        * Returns true if all the labels from the label table have the same
  397        * baseline.
  398        *
  399        * @return true if all the labels from the label table have the
  400        *         same baseline
  401        * @since 1.6
  402        */
  403       protected boolean labelsHaveSameBaselines() {
  404           if (!checkedLabelBaselines) {
  405               checkedLabelBaselines = true;
  406               Dictionary dictionary = slider.getLabelTable();
  407               if (dictionary != null) {
  408                   sameLabelBaselines = true;
  409                   Enumeration elements = dictionary.elements();
  410                   int baseline = -1;
  411                   while (elements.hasMoreElements()) {
  412                       Component label = (Component)elements.nextElement();
  413                       Dimension pref = label.getPreferredSize();
  414                       int labelBaseline = label.getBaseline(pref.width,
  415                                                             pref.height);
  416                       if (labelBaseline >= 0) {
  417                           if (baseline == -1) {
  418                               baseline = labelBaseline;
  419                           }
  420                           else if (baseline != labelBaseline) {
  421                               sameLabelBaselines = false;
  422                               break;
  423                           }
  424                       }
  425                       else {
  426                           sameLabelBaselines = false;
  427                           break;
  428                       }
  429                   }
  430               }
  431               else {
  432                   sameLabelBaselines = false;
  433               }
  434           }
  435           return sameLabelBaselines;
  436       }
  437   
  438       public Dimension getPreferredHorizontalSize() {
  439           Dimension horizDim = (Dimension)DefaultLookup.get(slider,
  440                   this, "Slider.horizontalSize");
  441           if (horizDim == null) {
  442               horizDim = new Dimension(200, 21);
  443           }
  444           return horizDim;
  445       }
  446   
  447       public Dimension getPreferredVerticalSize() {
  448           Dimension vertDim = (Dimension)DefaultLookup.get(slider,
  449                   this, "Slider.verticalSize");
  450           if (vertDim == null) {
  451               vertDim = new Dimension(21, 200);
  452           }
  453           return vertDim;
  454       }
  455   
  456       public Dimension getMinimumHorizontalSize() {
  457           Dimension minHorizDim = (Dimension)DefaultLookup.get(slider,
  458                   this, "Slider.minimumHorizontalSize");
  459           if (minHorizDim == null) {
  460               minHorizDim = new Dimension(36, 21);
  461           }
  462           return minHorizDim;
  463       }
  464   
  465       public Dimension getMinimumVerticalSize() {
  466           Dimension minVertDim = (Dimension)DefaultLookup.get(slider,
  467                   this, "Slider.minimumVerticalSize");
  468           if (minVertDim == null) {
  469               minVertDim = new Dimension(21, 36);
  470           }
  471           return minVertDim;
  472       }
  473   
  474       public Dimension getPreferredSize(JComponent c)    {
  475           recalculateIfInsetsChanged();
  476           Dimension d;
  477           if ( slider.getOrientation() == JSlider.VERTICAL ) {
  478               d = new Dimension(getPreferredVerticalSize());
  479               d.width = insetCache.left + insetCache.right;
  480               d.width += focusInsets.left + focusInsets.right;
  481               d.width += trackRect.width + tickRect.width + labelRect.width;
  482           }
  483           else {
  484               d = new Dimension(getPreferredHorizontalSize());
  485               d.height = insetCache.top + insetCache.bottom;
  486               d.height += focusInsets.top + focusInsets.bottom;
  487               d.height += trackRect.height + tickRect.height + labelRect.height;
  488           }
  489   
  490           return d;
  491       }
  492   
  493       public Dimension getMinimumSize(JComponent c)  {
  494           recalculateIfInsetsChanged();
  495           Dimension d;
  496   
  497           if ( slider.getOrientation() == JSlider.VERTICAL ) {
  498               d = new Dimension(getMinimumVerticalSize());
  499               d.width = insetCache.left + insetCache.right;
  500               d.width += focusInsets.left + focusInsets.right;
  501               d.width += trackRect.width + tickRect.width + labelRect.width;
  502           }
  503           else {
  504               d = new Dimension(getMinimumHorizontalSize());
  505               d.height = insetCache.top + insetCache.bottom;
  506               d.height += focusInsets.top + focusInsets.bottom;
  507               d.height += trackRect.height + tickRect.height + labelRect.height;
  508           }
  509   
  510           return d;
  511       }
  512   
  513       public Dimension getMaximumSize(JComponent c) {
  514           Dimension d = getPreferredSize(c);
  515           if ( slider.getOrientation() == JSlider.VERTICAL ) {
  516               d.height = Short.MAX_VALUE;
  517           }
  518           else {
  519               d.width = Short.MAX_VALUE;
  520           }
  521   
  522           return d;
  523       }
  524   
  525       protected void calculateGeometry() {
  526           calculateFocusRect();
  527           calculateContentRect();
  528           calculateThumbSize();
  529           calculateTrackBuffer();
  530           calculateTrackRect();
  531           calculateTickRect();
  532           calculateLabelRect();
  533           calculateThumbLocation();
  534       }
  535   
  536       protected void calculateFocusRect() {
  537           focusRect.x = insetCache.left;
  538           focusRect.y = insetCache.top;
  539           focusRect.width = slider.getWidth() - (insetCache.left + insetCache.right);
  540           focusRect.height = slider.getHeight() - (insetCache.top + insetCache.bottom);
  541       }
  542   
  543       protected void calculateThumbSize() {
  544           Dimension size = getThumbSize();
  545           thumbRect.setSize( size.width, size.height );
  546       }
  547   
  548       protected void calculateContentRect() {
  549           contentRect.x = focusRect.x + focusInsets.left;
  550           contentRect.y = focusRect.y + focusInsets.top;
  551           contentRect.width = focusRect.width - (focusInsets.left + focusInsets.right);
  552           contentRect.height = focusRect.height - (focusInsets.top + focusInsets.bottom);
  553       }
  554   
  555       private int getTickSpacing() {
  556           int majorTickSpacing = slider.getMajorTickSpacing();
  557           int minorTickSpacing = slider.getMinorTickSpacing();
  558   
  559           int result;
  560   
  561           if (minorTickSpacing > 0) {
  562               result = minorTickSpacing;
  563           } else if (majorTickSpacing > 0) {
  564               result = majorTickSpacing;
  565           } else {
  566               result = 0;
  567           }
  568   
  569           return result;
  570       }
  571   
  572       protected void calculateThumbLocation() {
  573           if ( slider.getSnapToTicks() ) {
  574               int sliderValue = slider.getValue();
  575               int snappedValue = sliderValue;
  576               int tickSpacing = getTickSpacing();
  577   
  578               if ( tickSpacing != 0 ) {
  579                   // If it's not on a tick, change the value
  580                   if ( (sliderValue - slider.getMinimum()) % tickSpacing != 0 ) {
  581                       float temp = (float)(sliderValue - slider.getMinimum()) / (float)tickSpacing;
  582                       int whichTick = Math.round( temp );
  583   
  584                       // This is the fix for the bug #6401380
  585                       if (temp - (int)temp == .5 && sliderValue < lastValue) {
  586                         whichTick --;
  587                       }
  588                       snappedValue = slider.getMinimum() + (whichTick * tickSpacing);
  589                   }
  590   
  591                   if( snappedValue != sliderValue ) {
  592                       slider.setValue( snappedValue );
  593                   }
  594               }
  595           }
  596   
  597           if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  598               int valuePosition = xPositionForValue(slider.getValue());
  599   
  600               thumbRect.x = valuePosition - (thumbRect.width / 2);
  601               thumbRect.y = trackRect.y;
  602           }
  603           else {
  604               int valuePosition = yPositionForValue(slider.getValue());
  605   
  606               thumbRect.x = trackRect.x;
  607               thumbRect.y = valuePosition - (thumbRect.height / 2);
  608           }
  609       }
  610   
  611       protected void calculateTrackBuffer() {
  612           if ( slider.getPaintLabels() && slider.getLabelTable()  != null ) {
  613               Component highLabel = getHighestValueLabel();
  614               Component lowLabel = getLowestValueLabel();
  615   
  616               if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  617                   trackBuffer = Math.max( highLabel.getBounds().width, lowLabel.getBounds().width ) / 2;
  618                   trackBuffer = Math.max( trackBuffer, thumbRect.width / 2 );
  619               }
  620               else {
  621                   trackBuffer = Math.max( highLabel.getBounds().height, lowLabel.getBounds().height ) / 2;
  622                   trackBuffer = Math.max( trackBuffer, thumbRect.height / 2 );
  623               }
  624           }
  625           else {
  626               if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  627                   trackBuffer = thumbRect.width / 2;
  628               }
  629               else {
  630                   trackBuffer = thumbRect.height / 2;
  631               }
  632           }
  633       }
  634   
  635   
  636       protected void calculateTrackRect() {
  637           int centerSpacing = 0; // used to center sliders added using BorderLayout.CENTER (bug 4275631)
  638           if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  639               centerSpacing = thumbRect.height;
  640               if ( slider.getPaintTicks() ) centerSpacing += getTickLength();
  641               if ( slider.getPaintLabels() ) centerSpacing += getHeightOfTallestLabel();
  642               trackRect.x = contentRect.x + trackBuffer;
  643               trackRect.y = contentRect.y + (contentRect.height - centerSpacing - 1)/2;
  644               trackRect.width = contentRect.width - (trackBuffer * 2);
  645               trackRect.height = thumbRect.height;
  646           }
  647           else {
  648               centerSpacing = thumbRect.width;
  649               if (BasicGraphicsUtils.isLeftToRight(slider)) {
  650                   if ( slider.getPaintTicks() ) centerSpacing += getTickLength();
  651                   if ( slider.getPaintLabels() ) centerSpacing += getWidthOfWidestLabel();
  652               } else {
  653                   if ( slider.getPaintTicks() ) centerSpacing -= getTickLength();
  654                   if ( slider.getPaintLabels() ) centerSpacing -= getWidthOfWidestLabel();
  655               }
  656               trackRect.x = contentRect.x + (contentRect.width - centerSpacing - 1)/2;
  657               trackRect.y = contentRect.y + trackBuffer;
  658               trackRect.width = thumbRect.width;
  659               trackRect.height = contentRect.height - (trackBuffer * 2);
  660           }
  661   
  662       }
  663   
  664       /**
  665        * Gets the height of the tick area for horizontal sliders and the width of the
  666        * tick area for vertical sliders.  BasicSliderUI uses the returned value to
  667        * determine the tick area rectangle.  If you want to give your ticks some room,
  668        * make this larger than you need and paint your ticks away from the sides in paintTicks().
  669        */
  670       protected int getTickLength() {
  671           return 8;
  672       }
  673   
  674       protected void calculateTickRect() {
  675           if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  676               tickRect.x = trackRect.x;
  677               tickRect.y = trackRect.y + trackRect.height;
  678               tickRect.width = trackRect.width;
  679               tickRect.height = (slider.getPaintTicks()) ? getTickLength() : 0;
  680           }
  681           else {
  682               tickRect.width = (slider.getPaintTicks()) ? getTickLength() : 0;
  683               if(BasicGraphicsUtils.isLeftToRight(slider)) {
  684                   tickRect.x = trackRect.x + trackRect.width;
  685               }
  686               else {
  687                   tickRect.x = trackRect.x - tickRect.width;
  688               }
  689               tickRect.y = trackRect.y;
  690               tickRect.height = trackRect.height;
  691           }
  692       }
  693   
  694       protected void calculateLabelRect() {
  695           if ( slider.getPaintLabels() ) {
  696               if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  697                   labelRect.x = tickRect.x - trackBuffer;
  698                   labelRect.y = tickRect.y + tickRect.height;
  699                   labelRect.width = tickRect.width + (trackBuffer * 2);
  700                   labelRect.height = getHeightOfTallestLabel();
  701               }
  702               else {
  703                   if(BasicGraphicsUtils.isLeftToRight(slider)) {
  704                       labelRect.x = tickRect.x + tickRect.width;
  705                       labelRect.width = getWidthOfWidestLabel();
  706                   }
  707                   else {
  708                       labelRect.width = getWidthOfWidestLabel();
  709                       labelRect.x = tickRect.x - labelRect.width;
  710                   }
  711                   labelRect.y = tickRect.y - trackBuffer;
  712                   labelRect.height = tickRect.height + (trackBuffer * 2);
  713               }
  714           }
  715           else {
  716               if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  717                   labelRect.x = tickRect.x;
  718                   labelRect.y = tickRect.y + tickRect.height;
  719                   labelRect.width = tickRect.width;
  720                   labelRect.height = 0;
  721               }
  722               else {
  723                   if(BasicGraphicsUtils.isLeftToRight(slider)) {
  724                       labelRect.x = tickRect.x + tickRect.width;
  725                   }
  726                   else {
  727                       labelRect.x = tickRect.x;
  728                   }
  729                   labelRect.y = tickRect.y;
  730                   labelRect.width = 0;
  731                   labelRect.height = tickRect.height;
  732               }
  733           }
  734       }
  735   
  736       protected Dimension getThumbSize() {
  737           Dimension size = new Dimension();
  738   
  739           if ( slider.getOrientation() == JSlider.VERTICAL ) {
  740               size.width = 20;
  741               size.height = 11;
  742           }
  743           else {
  744               size.width = 11;
  745               size.height = 20;
  746           }
  747   
  748           return size;
  749       }
  750   
  751       public class PropertyChangeHandler implements PropertyChangeListener {
  752           // NOTE: This class exists only for backward compatability. All
  753           // its functionality has been moved into Handler. If you need to add
  754           // new functionality add it to the Handler, but make sure this
  755           // class calls into the Handler.
  756           public void propertyChange( PropertyChangeEvent e ) {
  757               getHandler().propertyChange(e);
  758           }
  759       }
  760   
  761       protected int getWidthOfWidestLabel() {
  762           Dictionary dictionary = slider.getLabelTable();
  763           int widest = 0;
  764           if ( dictionary != null ) {
  765               Enumeration keys = dictionary.keys();
  766               while ( keys.hasMoreElements() ) {
  767                   Component label = (Component)dictionary.get( keys.nextElement() );
  768                   widest = Math.max( label.getPreferredSize().width, widest );
  769               }
  770           }
  771           return widest;
  772       }
  773   
  774       protected int getHeightOfTallestLabel() {
  775           Dictionary dictionary = slider.getLabelTable();
  776           int tallest = 0;
  777           if ( dictionary != null ) {
  778               Enumeration keys = dictionary.keys();
  779               while ( keys.hasMoreElements() ) {
  780                   Component label = (Component)dictionary.get( keys.nextElement() );
  781                   tallest = Math.max( label.getPreferredSize().height, tallest );
  782               }
  783           }
  784           return tallest;
  785       }
  786   
  787       protected int getWidthOfHighValueLabel() {
  788           Component label = getHighestValueLabel();
  789           int width = 0;
  790   
  791           if ( label != null ) {
  792               width = label.getPreferredSize().width;
  793           }
  794   
  795           return width;
  796       }
  797   
  798       protected int getWidthOfLowValueLabel() {
  799           Component label = getLowestValueLabel();
  800           int width = 0;
  801   
  802           if ( label != null ) {
  803               width = label.getPreferredSize().width;
  804           }
  805   
  806           return width;
  807       }
  808   
  809       protected int getHeightOfHighValueLabel() {
  810           Component label = getHighestValueLabel();
  811           int height = 0;
  812   
  813           if ( label != null ) {
  814               height = label.getPreferredSize().height;
  815           }
  816   
  817           return height;
  818       }
  819   
  820       protected int getHeightOfLowValueLabel() {
  821           Component label = getLowestValueLabel();
  822           int height = 0;
  823   
  824           if ( label != null ) {
  825               height = label.getPreferredSize().height;
  826           }
  827   
  828           return height;
  829       }
  830   
  831       protected boolean drawInverted() {
  832           if (slider.getOrientation()==JSlider.HORIZONTAL) {
  833               if(BasicGraphicsUtils.isLeftToRight(slider)) {
  834                   return slider.getInverted();
  835               } else {
  836                   return !slider.getInverted();
  837               }
  838           } else {
  839               return slider.getInverted();
  840           }
  841       }
  842   
  843       /**
  844        * Returns the biggest value that has an entry in the label table.
  845        *
  846        * @return biggest value that has an entry in the label table, or
  847        *         null.
  848        * @since 1.6
  849        */
  850       protected Integer getHighestValue() {
  851           Dictionary dictionary = slider.getLabelTable();
  852           if (dictionary != null) {
  853               Enumeration keys = dictionary.keys();
  854               int max = slider.getMinimum() - 1;
  855               while (keys.hasMoreElements()) {
  856                   max = Math.max(max, ((Integer)keys.nextElement()).intValue());
  857               }
  858               if (max == slider.getMinimum() - 1) {
  859                   return null;
  860               }
  861               return max;
  862           }
  863           return null;
  864       }
  865   
  866       /**
  867        * Returns the smallest value that has an entry in the label table.
  868        *
  869        * @return smallest value that has an entry in the label table, or
  870        *         null.
  871        * @since 1.6
  872        */
  873       protected Integer getLowestValue() {
  874           Dictionary dictionary = slider.getLabelTable();
  875           if (dictionary != null) {
  876               Enumeration keys = dictionary.keys();
  877               int min = slider.getMaximum() + 1;
  878               while (keys.hasMoreElements()) {
  879                   min = Math.min(min, ((Integer)keys.nextElement()).intValue());
  880               }
  881               if (min == slider.getMaximum() + 1) {
  882                   return null;
  883               }
  884               return min;
  885           }
  886           return null;
  887       }
  888   
  889   
  890       /**
  891        * Returns the label that corresponds to the highest slider value in the label table.
  892        * @see JSlider#setLabelTable
  893        */
  894       protected Component getLowestValueLabel() {
  895           Integer min = getLowestValue();
  896           if (min != null) {
  897               return (Component)slider.getLabelTable().get(min);
  898           }
  899           return null;
  900       }
  901   
  902       /**
  903        * Returns the label that corresponds to the lowest slider value in the label table.
  904        * @see JSlider#setLabelTable
  905        */
  906       protected Component getHighestValueLabel() {
  907           Integer max = getHighestValue();
  908           if (max != null) {
  909               return (Component)slider.getLabelTable().get(max);
  910           }
  911           return null;
  912       }
  913   
  914       public void paint( Graphics g, JComponent c )   {
  915           recalculateIfInsetsChanged();
  916           recalculateIfOrientationChanged();
  917           Rectangle clip = g.getClipBounds();
  918   
  919           if ( !clip.intersects(trackRect) && slider.getPaintTrack())
  920               calculateGeometry();
  921   
  922           if ( slider.getPaintTrack() && clip.intersects( trackRect ) ) {
  923               paintTrack( g );
  924           }
  925           if ( slider.getPaintTicks() && clip.intersects( tickRect ) ) {
  926               paintTicks( g );
  927           }
  928           if ( slider.getPaintLabels() && clip.intersects( labelRect ) ) {
  929               paintLabels( g );
  930           }
  931           if ( slider.hasFocus() && clip.intersects( focusRect ) ) {
  932               paintFocus( g );
  933           }
  934           if ( clip.intersects( thumbRect ) ) {
  935               paintThumb( g );
  936           }
  937       }
  938   
  939       protected void recalculateIfInsetsChanged() {
  940           Insets newInsets = slider.getInsets();
  941           if ( !newInsets.equals( insetCache ) ) {
  942               insetCache = newInsets;
  943               calculateGeometry();
  944           }
  945       }
  946   
  947       protected void recalculateIfOrientationChanged() {
  948           boolean ltr = BasicGraphicsUtils.isLeftToRight(slider);
  949           if ( ltr!=leftToRightCache ) {
  950               leftToRightCache = ltr;
  951               calculateGeometry();
  952           }
  953       }
  954   
  955       public void paintFocus(Graphics g)  {
  956           g.setColor( getFocusColor() );
  957   
  958           BasicGraphicsUtils.drawDashedRect( g, focusRect.x, focusRect.y,
  959                                              focusRect.width, focusRect.height );
  960       }
  961   
  962       public void paintTrack(Graphics g)  {
  963   
  964           Rectangle trackBounds = trackRect;
  965   
  966           if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  967               int cy = (trackBounds.height / 2) - 2;
  968               int cw = trackBounds.width;
  969   
  970               g.translate(trackBounds.x, trackBounds.y + cy);
  971   
  972               g.setColor(getShadowColor());
  973               g.drawLine(0, 0, cw - 1, 0);
  974               g.drawLine(0, 1, 0, 2);
  975               g.setColor(getHighlightColor());
  976               g.drawLine(0, 3, cw, 3);
  977               g.drawLine(cw, 0, cw, 3);
  978               g.setColor(Color.black);
  979               g.drawLine(1, 1, cw-2, 1);
  980   
  981               g.translate(-trackBounds.x, -(trackBounds.y + cy));
  982           }
  983           else {
  984               int cx = (trackBounds.width / 2) - 2;
  985               int ch = trackBounds.height;
  986   
  987               g.translate(trackBounds.x + cx, trackBounds.y);
  988   
  989               g.setColor(getShadowColor());
  990               g.drawLine(0, 0, 0, ch - 1);
  991               g.drawLine(1, 0, 2, 0);
  992               g.setColor(getHighlightColor());
  993               g.drawLine(3, 0, 3, ch);
  994               g.drawLine(0, ch, 3, ch);
  995               g.setColor(Color.black);
  996               g.drawLine(1, 1, 1, ch-2);
  997   
  998               g.translate(-(trackBounds.x + cx), -trackBounds.y);
  999           }
 1000       }
 1001   
 1002       public void paintTicks(Graphics g)  {
 1003           Rectangle tickBounds = tickRect;
 1004           int i;
 1005           int maj, min, max;
 1006           int w = tickBounds.width;
 1007           int h = tickBounds.height;
 1008           int centerEffect, tickHeight;
 1009   
 1010           g.setColor(DefaultLookup.getColor(slider, this, "Slider.tickColor", Color.black));
 1011   
 1012           maj = slider.getMajorTickSpacing();
 1013           min = slider.getMinorTickSpacing();
 1014   
 1015           if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
 1016              g.translate( 0, tickBounds.y);
 1017   
 1018               int value = slider.getMinimum();
 1019               int xPos = 0;
 1020   
 1021               if ( slider.getMinorTickSpacing() > 0 ) {
 1022                   while ( value <= slider.getMaximum() ) {
 1023                       xPos = xPositionForValue( value );
 1024                       paintMinorTickForHorizSlider( g, tickBounds, xPos );
 1025                       value += slider.getMinorTickSpacing();
 1026                   }
 1027               }
 1028   
 1029               if ( slider.getMajorTickSpacing() > 0 ) {
 1030                   value = slider.getMinimum();
 1031   
 1032                   while ( value <= slider.getMaximum() ) {
 1033                       xPos = xPositionForValue( value );
 1034                       paintMajorTickForHorizSlider( g, tickBounds, xPos );
 1035                       value += slider.getMajorTickSpacing();
 1036                   }
 1037               }
 1038   
 1039               g.translate( 0, -tickBounds.y);
 1040           }
 1041           else {
 1042              g.translate(tickBounds.x, 0);
 1043   
 1044               int value = slider.getMinimum();
 1045               int yPos = 0;
 1046   
 1047               if ( slider.getMinorTickSpacing() > 0 ) {
 1048                   int offset = 0;
 1049                   if(!BasicGraphicsUtils.isLeftToRight(slider)) {
 1050                       offset = tickBounds.width - tickBounds.width / 2;
 1051                       g.translate(offset, 0);
 1052                   }
 1053   
 1054                   while ( value <= slider.getMaximum() ) {
 1055                       yPos = yPositionForValue( value );
 1056                       paintMinorTickForVertSlider( g, tickBounds, yPos );
 1057                       value += slider.getMinorTickSpacing();
 1058                   }
 1059   
 1060                   if(!BasicGraphicsUtils.isLeftToRight(slider)) {
 1061                       g.translate(-offset, 0);
 1062                   }
 1063               }
 1064   
 1065               if ( slider.getMajorTickSpacing() > 0 ) {
 1066                   value = slider.getMinimum();
 1067                   if(!BasicGraphicsUtils.isLeftToRight(slider)) {
 1068                       g.translate(2, 0);
 1069                   }
 1070   
 1071                   while ( value <= slider.getMaximum() ) {
 1072                       yPos = yPositionForValue( value );
 1073                       paintMajorTickForVertSlider( g, tickBounds, yPos );
 1074                       value += slider.getMajorTickSpacing();
 1075                   }
 1076   
 1077                   if(!BasicGraphicsUtils.isLeftToRight(slider)) {
 1078                       g.translate(-2, 0);
 1079                   }
 1080               }
 1081               g.translate(-tickBounds.x, 0);
 1082           }
 1083       }
 1084   
 1085       protected void paintMinorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
 1086           g.drawLine( x, 0, x, tickBounds.height / 2 - 1 );
 1087       }
 1088   
 1089       protected void paintMajorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
 1090           g.drawLine( x, 0, x, tickBounds.height - 2 );
 1091       }
 1092   
 1093       protected void paintMinorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
 1094           g.drawLine( 0, y, tickBounds.width / 2 - 1, y );
 1095       }
 1096   
 1097       protected void paintMajorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
 1098           g.drawLine( 0, y,  tickBounds.width - 2, y );
 1099       }
 1100   
 1101       public void paintLabels( Graphics g ) {
 1102           Rectangle labelBounds = labelRect;
 1103   
 1104           Dictionary dictionary = slider.getLabelTable();
 1105           if ( dictionary != null ) {
 1106               Enumeration keys = dictionary.keys();
 1107               int minValue = slider.getMinimum();
 1108               int maxValue = slider.getMaximum();
 1109               boolean enabled = slider.isEnabled();
 1110               while ( keys.hasMoreElements() ) {
 1111                   Integer key = (Integer)keys.nextElement();
 1112                   int value = key.intValue();
 1113                   if (value >= minValue && value <= maxValue) {
 1114                       Component label = (Component)dictionary.get( key );
 1115                       if (label instanceof JComponent) {
 1116                           ((JComponent)label).setEnabled(enabled);
 1117                       }
 1118                       if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
 1119                           g.translate( 0, labelBounds.y );
 1120                           paintHorizontalLabel( g, value, label );
 1121                           g.translate( 0, -labelBounds.y );
 1122                       }
 1123                       else {
 1124                           int offset = 0;
 1125                           if (!BasicGraphicsUtils.isLeftToRight(slider)) {
 1126                               offset = labelBounds.width -
 1127                                   label.getPreferredSize().width;
 1128                           }
 1129                           g.translate( labelBounds.x + offset, 0 );
 1130                           paintVerticalLabel( g, value, label );
 1131                           g.translate( -labelBounds.x - offset, 0 );
 1132                       }
 1133                   }
 1134               }
 1135           }
 1136   
 1137       }
 1138   
 1139       /**
 1140        * Called for every label in the label table.  Used to draw the labels for horizontal sliders.
 1141        * The graphics have been translated to labelRect.y already.
 1142        * @see JSlider#setLabelTable
 1143        */
 1144       protected void paintHorizontalLabel( Graphics g, int value, Component label ) {
 1145           int labelCenter = xPositionForValue( value );
 1146           int labelLeft = labelCenter - (label.getPreferredSize().width / 2);
 1147           g.translate( labelLeft, 0 );
 1148           label.paint( g );
 1149           g.translate( -labelLeft, 0 );
 1150       }
 1151   
 1152       /**
 1153        * Called for every label in the label table.  Used to draw the labels for vertical sliders.
 1154        * The graphics have been translated to labelRect.x already.
 1155        * @see JSlider#setLabelTable
 1156        */
 1157       protected void paintVerticalLabel( Graphics g, int value, Component label ) {
 1158           int labelCenter = yPositionForValue( value );
 1159           int labelTop = labelCenter - (label.getPreferredSize().height / 2);
 1160           g.translate( 0, labelTop );
 1161           label.paint( g );
 1162           g.translate( 0, -labelTop );
 1163       }
 1164   
 1165       public void paintThumb(Graphics g)  {
 1166           Rectangle knobBounds = thumbRect;
 1167           int w = knobBounds.width;
 1168           int h = knobBounds.height;
 1169   
 1170           g.translate(knobBounds.x, knobBounds.y);
 1171   
 1172           if ( slider.isEnabled() ) {
 1173               g.setColor(slider.getBackground());
 1174           }
 1175           else {
 1176               g.setColor(slider.getBackground().darker());
 1177           }
 1178   
 1179           Boolean paintThumbArrowShape =
 1180               (Boolean)slider.getClientProperty("Slider.paintThumbArrowShape");
 1181   
 1182           if ((!slider.getPaintTicks() && paintThumbArrowShape == null) ||
 1183               paintThumbArrowShape == Boolean.FALSE) {
 1184   
 1185               // "plain" version
 1186               g.fillRect(0, 0, w, h);
 1187   
 1188               g.setColor(Color.black);
 1189               g.drawLine(0, h-1, w-1, h-1);
 1190               g.drawLine(w-1, 0, w-1, h-1);
 1191   
 1192               g.setColor(highlightColor);
 1193               g.drawLine(0, 0, 0, h-2);
 1194               g.drawLine(1, 0, w-2, 0);
 1195   
 1196               g.setColor(shadowColor);
 1197               g.drawLine(1, h-2, w-2, h-2);
 1198               g.drawLine(w-2, 1, w-2, h-3);
 1199           }
 1200           else if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
 1201               int cw = w / 2;
 1202               g.fillRect(1, 1, w-3, h-1-cw);
 1203               Polygon p = new Polygon();
 1204               p.addPoint(1, h-cw);
 1205               p.addPoint(cw-1, h-1);
 1206               p.addPoint(w-2, h-1-cw);
 1207               g.fillPolygon(p);
 1208   
 1209               g.setColor(highlightColor);
 1210               g.drawLine(0, 0, w-2, 0);
 1211               g.drawLine(0, 1, 0, h-1-cw);
 1212               g.drawLine(0, h-cw, cw-1, h-1);
 1213   
 1214               g.setColor(Color.black);
 1215               g.drawLine(w-1, 0, w-1, h-2-cw);
 1216               g.drawLine(w-1, h-1-cw, w-1-cw, h-1);
 1217   
 1218               g.setColor(shadowColor);
 1219               g.drawLine(w-2, 1, w-2, h-2-cw);
 1220               g.drawLine(w-2, h-1-cw, w-1-cw, h-2);
 1221           }
 1222           else {  // vertical
 1223               int cw = h / 2;
 1224               if(BasicGraphicsUtils.isLeftToRight(slider)) {
 1225                     g.fillRect(1, 1, w-1-cw, h-3);
 1226                     Polygon p = new Polygon();
 1227                     p.addPoint(w-cw-1, 0);
 1228                     p.addPoint(w-1, cw);
 1229                     p.addPoint(w-1-cw, h-2);
 1230                     g.fillPolygon(p);
 1231   
 1232                     g.setColor(highlightColor);
 1233                     g.drawLine(0, 0, 0, h - 2);                  // left
 1234                     g.drawLine(1, 0, w-1-cw, 0);                 // top
 1235                     g.drawLine(w-cw-1, 0, w-1, cw);              // top slant
 1236   
 1237                     g.setColor(Color.black);
 1238                     g.drawLine(0, h-1, w-2-cw, h-1);             // bottom
 1239                     g.drawLine(w-1-cw, h-1, w-1, h-1-cw);        // bottom slant
 1240   
 1241                     g.setColor(shadowColor);
 1242                     g.drawLine(1, h-2, w-2-cw,  h-2 );         // bottom
 1243                     g.drawLine(w-1-cw, h-2, w-2, h-cw-1 );     // bottom slant
 1244               }
 1245               else {
 1246                     g.fillRect(5, 1, w-1-cw, h-3);
 1247                     Polygon p = new Polygon();
 1248                     p.addPoint(cw, 0);
 1249                     p.addPoint(0, cw);
 1250                     p.addPoint(cw, h-2);
 1251                     g.fillPolygon(p);
 1252   
 1253                     g.setColor(highlightColor);
 1254                     g.drawLine(cw-1, 0, w-2, 0);             // top
 1255                     g.drawLine(0, cw, cw, 0);                // top slant
 1256   
 1257                     g.setColor(Color.black);
 1258                     g.drawLine(0, h-1-cw, cw, h-1 );         // bottom slant
 1259                     g.drawLine(cw, h-1, w-1, h-1);           // bottom
 1260   
 1261                     g.setColor(shadowColor);
 1262                     g.drawLine(cw, h-2, w-2,  h-2 );         // bottom
 1263                     g.drawLine(w-1, 1, w-1,  h-2 );          // right
 1264               }
 1265           }
 1266   
 1267           g.translate(-knobBounds.x, -knobBounds.y);
 1268       }
 1269   
 1270       // Used exclusively by setThumbLocation()
 1271       private static Rectangle unionRect = new Rectangle();
 1272   
 1273       public void setThumbLocation(int x, int y)  {
 1274           unionRect.setBounds( thumbRect );
 1275   
 1276           thumbRect.setLocation( x, y );
 1277   
 1278           SwingUtilities.computeUnion( thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height, unionRect );
 1279           slider.repaint( unionRect.x, unionRect.y, unionRect.width, unionRect.height );
 1280       }
 1281   
 1282       public void scrollByBlock(int direction)    {
 1283           synchronized(slider)    {
 1284               int blockIncrement =
 1285                   (slider.getMaximum() - slider.getMinimum()) / 10;
 1286               if (blockIncrement == 0) {
 1287                   blockIncrement = 1;
 1288               }
 1289   
 1290               if (slider.getSnapToTicks()) {
 1291                   int tickSpacing = getTickSpacing();
 1292   
 1293                   if (blockIncrement < tickSpacing) {
 1294                       blockIncrement = tickSpacing;
 1295                   }
 1296               }
 1297   
 1298               int delta = blockIncrement * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL);
 1299               slider.setValue(slider.getValue() + delta);
 1300           }
 1301       }
 1302   
 1303       public void scrollByUnit(int direction) {
 1304           synchronized(slider)    {
 1305               int delta = ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL);
 1306   
 1307               if (slider.getSnapToTicks()) {
 1308                   delta *= getTickSpacing();
 1309               }
 1310   
 1311               slider.setValue(slider.getValue() + delta);
 1312           }
 1313       }
 1314   
 1315       /**
 1316        * This function is called when a mousePressed was detected in the track, not
 1317        * in the thumb.  The default behavior is to scroll by block.  You can
 1318        *  override this method to stop it from scrolling or to add additional behavior.
 1319        */
 1320       protected void scrollDueToClickInTrack( int dir ) {
 1321           scrollByBlock( dir );
 1322       }
 1323   
 1324       protected int xPositionForValue( int value )    {
 1325           int min = slider.getMinimum();
 1326           int max = slider.getMaximum();
 1327           int trackLength = trackRect.width;
 1328           double valueRange = (double)max - (double)min;
 1329           double pixelsPerValue = (double)trackLength / valueRange;
 1330           int trackLeft = trackRect.x;
 1331           int trackRight = trackRect.x + (trackRect.width - 1);
 1332           int xPosition;
 1333   
 1334           if ( !drawInverted() ) {
 1335               xPosition = trackLeft;
 1336               xPosition += Math.round( pixelsPerValue * ((double)value - min) );
 1337           }
 1338           else {
 1339               xPosition = trackRight;
 1340               xPosition -= Math.round( pixelsPerValue * ((double)value - min) );
 1341           }
 1342   
 1343           xPosition = Math.max( trackLeft, xPosition );
 1344           xPosition = Math.min( trackRight, xPosition );
 1345   
 1346           return xPosition;
 1347       }
 1348   
 1349       protected int yPositionForValue( int value )  {
 1350           return yPositionForValue(value, trackRect.y, trackRect.height);
 1351       }
 1352   
 1353       /**
 1354        * Returns the y location for the specified value.  No checking is
 1355        * done on the arguments.  In particular if <code>trackHeight</code> is
 1356        * negative undefined results may occur.
 1357        *
 1358        * @param value the slider value to get the location for
 1359        * @param trackY y-origin of the track
 1360        * @param trackHeight the height of the track
 1361        * @since 1.6
 1362        */
 1363       protected int yPositionForValue(int value, int trackY, int trackHeight) {
 1364           int min = slider.getMinimum();
 1365           int max = slider.getMaximum();
 1366           double valueRange = (double)max - (double)min;
 1367           double pixelsPerValue = (double)trackHeight / (double)valueRange;
 1368           int trackBottom = trackY + (trackHeight - 1);
 1369           int yPosition;
 1370   
 1371           if ( !drawInverted() ) {
 1372               yPosition = trackY;
 1373               yPosition += Math.round( pixelsPerValue * ((double)max - value ) );
 1374           }
 1375           else {
 1376               yPosition = trackY;
 1377               yPosition += Math.round( pixelsPerValue * ((double)value - min) );
 1378           }
 1379   
 1380           yPosition = Math.max( trackY, yPosition );
 1381           yPosition = Math.min( trackBottom, yPosition );
 1382   
 1383           return yPosition;
 1384       }
 1385   
 1386       /**
 1387        * Returns a value give a y position.  If yPos is past the track at the top or the
 1388        * bottom it will set the value to the min or max of the slider, depending if the
 1389        * slider is inverted or not.
 1390        */
 1391       public int valueForYPosition( int yPos ) {
 1392           int value;
 1393           final int minValue = slider.getMinimum();
 1394           final int maxValue = slider.getMaximum();
 1395           final int trackLength = trackRect.height;
 1396           final int trackTop = trackRect.y;
 1397           final int trackBottom = trackRect.y + (trackRect.height - 1);
 1398   
 1399           if ( yPos <= trackTop ) {
 1400               value = drawInverted() ? minValue : maxValue;
 1401           }
 1402           else if ( yPos >= trackBottom ) {
 1403               value = drawInverted() ? maxValue : minValue;
 1404           }
 1405           else {
 1406               int distanceFromTrackTop = yPos - trackTop;
 1407               double valueRange = (double)maxValue - (double)minValue;
 1408               double valuePerPixel = valueRange / (double)trackLength;
 1409               int valueFromTrackTop = (int)Math.round( distanceFromTrackTop * valuePerPixel );
 1410   
 1411               value = drawInverted() ? minValue + valueFromTrackTop : maxValue - valueFromTrackTop;
 1412           }
 1413   
 1414           return value;
 1415       }
 1416   
 1417       /**
 1418        * Returns a value give an x position.  If xPos is past the track at the left or the
 1419        * right it will set the value to the min or max of the slider, depending if the
 1420        * slider is inverted or not.
 1421        */
 1422       public int valueForXPosition( int xPos ) {
 1423           int value;
 1424           final int minValue = slider.getMinimum();
 1425           final int maxValue = slider.getMaximum();
 1426           final int trackLength = trackRect.width;
 1427           final int trackLeft = trackRect.x;
 1428           final int trackRight = trackRect.x + (trackRect.width - 1);
 1429   
 1430           if ( xPos <= trackLeft ) {
 1431               value = drawInverted() ? maxValue : minValue;
 1432           }
 1433           else if ( xPos >= trackRight ) {
 1434               value = drawInverted() ? minValue : maxValue;
 1435           }
 1436           else {
 1437               int distanceFromTrackLeft = xPos - trackLeft;
 1438               double valueRange = (double)maxValue - (double)minValue;
 1439               double valuePerPixel = valueRange / (double)trackLength;
 1440               int valueFromTrackLeft = (int)Math.round( distanceFromTrackLeft * valuePerPixel );
 1441   
 1442               value = drawInverted() ? maxValue - valueFromTrackLeft :
 1443                 minValue + valueFromTrackLeft;
 1444           }
 1445   
 1446           return value;
 1447       }
 1448   
 1449   
 1450       private class Handler implements ChangeListener,
 1451               ComponentListener, FocusListener, PropertyChangeListener {
 1452           // Change Handler
 1453           public void stateChanged(ChangeEvent e) {
 1454               if (!isDragging) {
 1455                   calculateThumbLocation();
 1456                   slider.repaint();
 1457               }
 1458               lastValue = slider.getValue();
 1459           }
 1460   
 1461           // Component Handler
 1462           public void componentHidden(ComponentEvent e) { }
 1463           public void componentMoved(ComponentEvent e) { }
 1464           public void componentResized(ComponentEvent e) {
 1465               calculateGeometry();
 1466               slider.repaint();
 1467           }
 1468           public void componentShown(ComponentEvent e) { }
 1469   
 1470           // Focus Handler
 1471           public void focusGained(FocusEvent e) { slider.repaint(); }
 1472           public void focusLost(FocusEvent e) { slider.repaint(); }
 1473   
 1474           // Property Change Handler
 1475           public void propertyChange(PropertyChangeEvent e) {
 1476               String propertyName = e.getPropertyName();
 1477               if (propertyName == "orientation" ||
 1478                       propertyName == "inverted" ||
 1479                       propertyName == "labelTable" ||
 1480                       propertyName == "majorTickSpacing" ||
 1481                       propertyName == "minorTickSpacing" ||
 1482                       propertyName == "paintTicks" ||
 1483                       propertyName == "paintTrack" ||
 1484                       propertyName == "font" ||
 1485                       propertyName == "paintLabels") {
 1486                   checkedLabelBaselines = false;
 1487                   calculateGeometry();
 1488                   slider.repaint();
 1489               } else if (propertyName == "componentOrientation") {
 1490                   calculateGeometry();
 1491                   slider.repaint();
 1492                   InputMap km = getInputMap(JComponent.WHEN_FOCUSED, slider);
 1493                   SwingUtilities.replaceUIInputMap(slider,
 1494                       JComponent.WHEN_FOCUSED, km);
 1495               } else if (propertyName == "model") {
 1496                   ((BoundedRangeModel)e.getOldValue()).removeChangeListener(
 1497                       changeListener);
 1498                   ((BoundedRangeModel)e.getNewValue()).addChangeListener(
 1499                       changeListener);
 1500                   calculateThumbLocation();
 1501                   slider.repaint();
 1502               }
 1503           }
 1504       }
 1505   
 1506       /////////////////////////////////////////////////////////////////////////
 1507       /// Model Listener Class
 1508       /////////////////////////////////////////////////////////////////////////
 1509       /**
 1510        * Data model listener.
 1511        *
 1512        * This class should be treated as a &quot;protected&quot; inner class.
 1513        * Instantiate it only within subclasses of <Foo>.
 1514        */
 1515       public class ChangeHandler implements ChangeListener {
 1516           // NOTE: This class exists only for backward compatability. All
 1517           // its functionality has been moved into Handler. If you need to add
 1518           // new functionality add it to the Handler, but make sure this
 1519           // class calls into the Handler.
 1520           public void stateChanged(ChangeEvent e) {
 1521               getHandler().stateChanged(e);
 1522           }
 1523       }
 1524   
 1525       /////////////////////////////////////////////////////////////////////////
 1526       /// Track Listener Class
 1527       /////////////////////////////////////////////////////////////////////////
 1528       /**
 1529        * Track mouse movements.
 1530        *
 1531        * This class should be treated as a &quot;protected&quot; inner class.
 1532        * Instantiate it only within subclasses of <Foo>.
 1533        */
 1534       public class TrackListener extends MouseInputAdapter {
 1535           protected transient int offset;
 1536           protected transient int currentMouseX, currentMouseY;
 1537   
 1538           public void mouseReleased(MouseEvent e) {
 1539               if (!slider.isEnabled()) {
 1540                   return;
 1541               }
 1542   
 1543               offset = 0;
 1544               scrollTimer.stop();
 1545   
 1546               // This is the way we have to determine snap-to-ticks.  It's
 1547               // hard to explain but since ChangeEvents don't give us any
 1548               // idea what has changed we don't have a way to stop the thumb
 1549               // bounds from being recalculated.  Recalculating the thumb
 1550               // bounds moves the thumb over the current value (i.e., snapping
 1551               // to the ticks).
 1552               if (slider.getSnapToTicks() /*|| slider.getSnapToValue()*/ ) {
 1553                   isDragging = false;
 1554                   slider.setValueIsAdjusting(false);
 1555               }
 1556               else {
 1557                   slider.setValueIsAdjusting(false);
 1558                   isDragging = false;
 1559               }
 1560               slider.repaint();
 1561           }
 1562   
 1563           /**
 1564           * If the mouse is pressed above the "thumb" component
 1565           * then reduce the scrollbars value by one page ("page up"),
 1566           * otherwise increase it by one page.  If there is no
 1567           * thumb then page up if the mouse is in the upper half
 1568           * of the track.
 1569           */
 1570           public void mousePressed(MouseEvent e) {
 1571               if (!slider.isEnabled()) {
 1572                   return;
 1573               }
 1574   
 1575               // We should recalculate geometry just before
 1576               // calculation of the thumb movement direction.
 1577               // It is important for the case, when JSlider
 1578               // is a cell editor in JTable. See 6348946.
 1579               calculateGeometry();
 1580   
 1581               currentMouseX = e.getX();
 1582               currentMouseY = e.getY();
 1583   
 1584               if (slider.isRequestFocusEnabled()) {
 1585                   slider.requestFocus();
 1586               }
 1587   
 1588               // Clicked in the Thumb area?
 1589               if (thumbRect.contains(currentMouseX, currentMouseY)) {
 1590                   if (UIManager.getBoolean("Slider.onlyLeftMouseButtonDrag")
 1591                           && !SwingUtilities.isLeftMouseButton(e)) {
 1592                       return;
 1593                   }
 1594   
 1595                   switch (slider.getOrientation()) {
 1596                   case JSlider.VERTICAL:
 1597                       offset = currentMouseY - thumbRect.y;
 1598                       break;
 1599                   case JSlider.HORIZONTAL:
 1600                       offset = currentMouseX - thumbRect.x;
 1601                       break;
 1602                   }
 1603                   isDragging = true;
 1604                   return;
 1605               }
 1606   
 1607               if (!SwingUtilities.isLeftMouseButton(e)) {
 1608                   return;
 1609               }
 1610   
 1611               isDragging = false;
 1612               slider.setValueIsAdjusting(true);
 1613   
 1614               Dimension sbSize = slider.getSize();
 1615               int direction = POSITIVE_SCROLL;
 1616   
 1617               switch (slider.getOrientation()) {
 1618               case JSlider.VERTICAL:
 1619                   if ( thumbRect.isEmpty() ) {
 1620                       int scrollbarCenter = sbSize.height / 2;
 1621                       if ( !drawInverted() ) {
 1622                           direction = (currentMouseY < scrollbarCenter) ?
 1623                               POSITIVE_SCROLL : NEGATIVE_SCROLL;
 1624                       }
 1625                       else {
 1626                           direction = (currentMouseY < scrollbarCenter) ?
 1627                               NEGATIVE_SCROLL : POSITIVE_SCROLL;
 1628                       }
 1629                   }
 1630                   else {
 1631                       int thumbY = thumbRect.y;
 1632                       if ( !drawInverted() ) {
 1633                           direction = (currentMouseY < thumbY) ?
 1634                               POSITIVE_SCROLL : NEGATIVE_SCROLL;
 1635                       }
 1636                       else {
 1637                           direction = (currentMouseY < thumbY) ?
 1638                               NEGATIVE_SCROLL : POSITIVE_SCROLL;
 1639                       }
 1640                   }
 1641                   break;
 1642               case JSlider.HORIZONTAL:
 1643                   if ( thumbRect.isEmpty() ) {
 1644                       int scrollbarCenter = sbSize.width / 2;
 1645                       if ( !drawInverted() ) {
 1646                           direction = (currentMouseX < scrollbarCenter) ?
 1647                               NEGATIVE_SCROLL : POSITIVE_SCROLL;
 1648                       }
 1649                       else {
 1650                           direction = (currentMouseX < scrollbarCenter) ?
 1651                               POSITIVE_SCROLL : NEGATIVE_SCROLL;
 1652                       }
 1653                   }
 1654                   else {
 1655                       int thumbX = thumbRect.x;
 1656                       if ( !drawInverted() ) {
 1657                           direction = (currentMouseX < thumbX) ?
 1658                               NEGATIVE_SCROLL : POSITIVE_SCROLL;
 1659                       }
 1660                       else {
 1661                           direction = (currentMouseX < thumbX) ?
 1662                               POSITIVE_SCROLL : NEGATIVE_SCROLL;
 1663                       }
 1664                   }
 1665                   break;
 1666               }
 1667   
 1668               if (shouldScroll(direction)) {
 1669                   scrollDueToClickInTrack(direction);
 1670               }
 1671               if (shouldScroll(direction)) {
 1672                   scrollTimer.stop();
 1673                   scrollListener.setDirection(direction);
 1674                   scrollTimer.start();
 1675               }
 1676           }
 1677   
 1678           public boolean shouldScroll(int direction) {
 1679               Rectangle r = thumbRect;
 1680               if (slider.getOrientation() == JSlider.VERTICAL) {
 1681                   if (drawInverted() ? direction < 0 : direction > 0) {
 1682                       if (r.y  <= currentMouseY) {
 1683                           return false;
 1684                       }
 1685                   }
 1686                   else if (r.y + r.height >= currentMouseY) {
 1687                       return false;
 1688                   }
 1689               }
 1690               else {
 1691                   if (drawInverted() ? direction < 0 : direction > 0) {
 1692                       if (r.x + r.width  >= currentMouseX) {
 1693                           return false;
 1694                       }
 1695                   }
 1696                   else if (r.x <= currentMouseX) {
 1697                       return false;
 1698                   }
 1699               }
 1700   
 1701               if (direction > 0 && slider.getValue() + slider.getExtent() >=
 1702                       slider.getMaximum()) {
 1703                   return false;
 1704               }
 1705               else if (direction < 0 && slider.getValue() <=
 1706                       slider.getMinimum()) {
 1707                   return false;
 1708               }
 1709   
 1710               return true;
 1711           }
 1712   
 1713           /**
 1714           * Set the models value to the position of the top/left
 1715           * of the thumb relative to the origin of the track.
 1716           */
 1717           public void mouseDragged(MouseEvent e) {
 1718               int thumbMiddle = 0;
 1719   
 1720               if (!slider.isEnabled()) {
 1721                   return;
 1722               }
 1723   
 1724               currentMouseX = e.getX();
 1725               currentMouseY = e.getY();
 1726   
 1727               if (!isDragging) {
 1728                   return;
 1729               }
 1730   
 1731               slider.setValueIsAdjusting(true);
 1732   
 1733               switch (slider.getOrientation()) {
 1734               case JSlider.VERTICAL:
 1735                   int halfThumbHeight = thumbRect.height / 2;
 1736                   int thumbTop = e.getY() - offset;
 1737                   int trackTop = trackRect.y;
 1738                   int trackBottom = trackRect.y + (trackRect.height - 1);
 1739                   int vMax = yPositionForValue(slider.getMaximum() -
 1740                                               slider.getExtent());
 1741   
 1742                   if (drawInverted()) {
 1743                       trackBottom = vMax;
 1744                   }
 1745                   else {
 1746                       trackTop = vMax;
 1747                   }
 1748                   thumbTop = Math.max(thumbTop, trackTop - halfThumbHeight);
 1749                   thumbTop = Math.min(thumbTop, trackBottom - halfThumbHeight);
 1750   
 1751                   setThumbLocation(thumbRect.x, thumbTop);
 1752   
 1753                   thumbMiddle = thumbTop + halfThumbHeight;
 1754                   slider.setValue( valueForYPosition( thumbMiddle ) );
 1755                   break;
 1756               case JSlider.HORIZONTAL:
 1757                   int halfThumbWidth = thumbRect.width / 2;
 1758                   int thumbLeft = e.getX() - offset;
 1759                   int trackLeft = trackRect.x;
 1760                   int trackRight = trackRect.x + (trackRect.width - 1);
 1761                   int hMax = xPositionForValue(slider.getMaximum() -
 1762                                               slider.getExtent());
 1763   
 1764                   if (drawInverted()) {
 1765                       trackLeft = hMax;
 1766                   }
 1767                   else {
 1768                       trackRight = hMax;
 1769                   }
 1770                   thumbLeft = Math.max(thumbLeft, trackLeft - halfThumbWidth);
 1771                   thumbLeft = Math.min(thumbLeft, trackRight - halfThumbWidth);
 1772   
 1773                   setThumbLocation(thumbLeft, thumbRect.y);
 1774   
 1775                   thumbMiddle = thumbLeft + halfThumbWidth;
 1776                   slider.setValue(valueForXPosition(thumbMiddle));
 1777                   break;
 1778               default:
 1779                   return;
 1780               }
 1781           }
 1782   
 1783           public void mouseMoved(MouseEvent e) { }
 1784       }
 1785   
 1786       /**
 1787        * Scroll-event listener.
 1788        *
 1789        * This class should be treated as a &quot;protected&quot; inner class.
 1790        * Instantiate it only within subclasses of <Foo>.
 1791        */
 1792       public class ScrollListener implements ActionListener {
 1793           // changed this class to public to avoid bogus IllegalAccessException
 1794           // bug in InternetExplorer browser.  It was protected.  Work around
 1795           // for 4109432
 1796           int direction = POSITIVE_SCROLL;
 1797           boolean useBlockIncrement;
 1798   
 1799           public ScrollListener() {
 1800               direction = POSITIVE_SCROLL;
 1801               useBlockIncrement = true;
 1802           }
 1803   
 1804           public ScrollListener(int dir, boolean block)   {
 1805               direction = dir;
 1806               useBlockIncrement = block;
 1807           }
 1808   
 1809           public void setDirection(int direction) {
 1810               this.direction = direction;
 1811           }
 1812   
 1813           public void setScrollByBlock(boolean block) {
 1814               this.useBlockIncrement = block;
 1815           }
 1816   
 1817           public void actionPerformed(ActionEvent e) {
 1818               if (useBlockIncrement) {
 1819                   scrollByBlock(direction);
 1820               }
 1821               else {
 1822                   scrollByUnit(direction);
 1823               }
 1824               if (!trackListener.shouldScroll(direction)) {
 1825                   ((Timer)e.getSource()).stop();
 1826               }
 1827           }
 1828       }
 1829   
 1830       /**
 1831        * Listener for resizing events.
 1832        * <p>
 1833        * This class should be treated as a &quot;protected&quot; inner class.
 1834        * Instantiate it only within subclasses of <Foo>.
 1835        */
 1836       public class ComponentHandler extends ComponentAdapter {
 1837           // NOTE: This class exists only for backward compatability. All
 1838           // its functionality has been moved into Handler. If you need to add
 1839           // new functionality add it to the Handler, but make sure this
 1840           // class calls into the Handler.
 1841           public void componentResized(ComponentEvent e)  {
 1842               getHandler().componentResized(e);
 1843           }
 1844       };
 1845   
 1846       /**
 1847        * Focus-change listener.
 1848        * <p>
 1849        * This class should be treated as a &quot;protected&quot; inner class.
 1850        * Instantiate it only within subclasses of <Foo>.
 1851        */
 1852       public class FocusHandler implements FocusListener {
 1853           // NOTE: This class exists only for backward compatability. All
 1854           // its functionality has been moved into Handler. If you need to add
 1855           // new functionality add it to the Handler, but make sure this
 1856           // class calls into the Handler.
 1857           public void focusGained(FocusEvent e) {
 1858               getHandler().focusGained(e);
 1859           }
 1860   
 1861           public void focusLost(FocusEvent e) {
 1862               getHandler().focusLost(e);
 1863           }
 1864       }
 1865   
 1866       /**
 1867        * As of Java 2 platform v1.3 this undocumented class is no longer used.
 1868        * The recommended approach to creating bindings is to use a
 1869        * combination of an <code>ActionMap</code>, to contain the action,
 1870        * and an <code>InputMap</code> to contain the mapping from KeyStroke
 1871        * to action description. The InputMap is is usually described in the
 1872        * LookAndFeel tables.
 1873        * <p>
 1874        * Please refer to the key bindings specification for further details.
 1875        * <p>
 1876        * This class should be treated as a &quot;protected&quot; inner class.
 1877        * Instantiate it only within subclasses of <Foo>.
 1878        */
 1879       public class ActionScroller extends AbstractAction {
 1880           // NOTE: This class exists only for backward compatability. All
 1881           // its functionality has been moved into Actions. If you need to add
 1882           // new functionality add it to the Actions, but make sure this
 1883           // class calls into the Actions.
 1884           int dir;
 1885           boolean block;
 1886           JSlider slider;
 1887   
 1888           public ActionScroller( JSlider slider, int dir, boolean block) {
 1889               this.dir = dir;
 1890               this.block = block;
 1891               this.slider = slider;
 1892           }
 1893   
 1894           public void actionPerformed(ActionEvent e) {
 1895               SHARED_ACTION.scroll(slider, BasicSliderUI.this, dir, block);
 1896           }
 1897   
 1898           public boolean isEnabled() {
 1899               boolean b = true;
 1900               if (slider != null) {
 1901                   b = slider.isEnabled();
 1902               }
 1903               return b;
 1904           }
 1905   
 1906       };
 1907   
 1908   
 1909       /**
 1910        * A static version of the above.
 1911        */
 1912       static class SharedActionScroller extends AbstractAction {
 1913           // NOTE: This class exists only for backward compatability. All
 1914           // its functionality has been moved into Actions. If you need to add
 1915           // new functionality add it to the Actions, but make sure this
 1916           // class calls into the Actions.
 1917           int dir;
 1918           boolean block;
 1919   
 1920           public SharedActionScroller(int dir, boolean block) {
 1921               this.dir = dir;
 1922               this.block = block;
 1923           }
 1924   
 1925           public void actionPerformed(ActionEvent evt) {
 1926               JSlider slider = (JSlider)evt.getSource();
 1927               BasicSliderUI ui = (BasicSliderUI)BasicLookAndFeel.getUIOfType(
 1928                       slider.getUI(), BasicSliderUI.class);
 1929               if (ui == null) {
 1930                   return;
 1931               }
 1932               SHARED_ACTION.scroll(slider, ui, dir, block);
 1933           }
 1934       }
 1935   
 1936       private static class Actions extends UIAction {
 1937           public static final String POSITIVE_UNIT_INCREMENT =
 1938               "positiveUnitIncrement";
 1939           public static final String POSITIVE_BLOCK_INCREMENT =
 1940               "positiveBlockIncrement";
 1941           public static final String NEGATIVE_UNIT_INCREMENT =
 1942               "negativeUnitIncrement";
 1943           public static final String NEGATIVE_BLOCK_INCREMENT =
 1944               "negativeBlockIncrement";
 1945           public static final String MIN_SCROLL_INCREMENT = "minScroll";
 1946           public static final String MAX_SCROLL_INCREMENT = "maxScroll";
 1947   
 1948   
 1949           Actions() {
 1950               super(null);
 1951           }
 1952   
 1953           public Actions(String name) {
 1954               super(name);
 1955           }
 1956   
 1957           public void actionPerformed(ActionEvent evt) {
 1958               JSlider slider = (JSlider)evt.getSource();
 1959               BasicSliderUI ui = (BasicSliderUI)BasicLookAndFeel.getUIOfType(
 1960                        slider.getUI(), BasicSliderUI.class);
 1961               String name = getName();
 1962   
 1963               if (ui == null) {
 1964                   return;
 1965               }
 1966               if (POSITIVE_UNIT_INCREMENT == name) {
 1967                   scroll(slider, ui, POSITIVE_SCROLL, false);
 1968               } else if (NEGATIVE_UNIT_INCREMENT == name) {
 1969                   scroll(slider, ui, NEGATIVE_SCROLL, false);
 1970               } else if (POSITIVE_BLOCK_INCREMENT == name) {
 1971                   scroll(slider, ui, POSITIVE_SCROLL, true);
 1972               } else if (NEGATIVE_BLOCK_INCREMENT == name) {
 1973                   scroll(slider, ui, NEGATIVE_SCROLL, true);
 1974               } else if (MIN_SCROLL_INCREMENT == name) {
 1975                   scroll(slider, ui, MIN_SCROLL, false);
 1976               } else if (MAX_SCROLL_INCREMENT == name) {
 1977                   scroll(slider, ui, MAX_SCROLL, false);
 1978               }
 1979           }
 1980   
 1981           private void scroll(JSlider slider, BasicSliderUI ui, int direction,
 1982                   boolean isBlock) {
 1983               boolean invert = slider.getInverted();
 1984   
 1985               if (direction == NEGATIVE_SCROLL || direction == POSITIVE_SCROLL) {
 1986                   if (invert) {
 1987                       direction = (direction == POSITIVE_SCROLL) ?
 1988                           NEGATIVE_SCROLL : POSITIVE_SCROLL;
 1989                   }
 1990   
 1991                   if (isBlock) {
 1992                       ui.scrollByBlock(direction);
 1993                   } else {
 1994                       ui.scrollByUnit(direction);
 1995                   }
 1996               } else {  // MIN or MAX
 1997                   if (invert) {
 1998                       direction = (direction == MIN_SCROLL) ?
 1999                           MAX_SCROLL : MIN_SCROLL;
 2000                   }
 2001   
 2002                   slider.setValue((direction == MIN_SCROLL) ?
 2003                       slider.getMinimum() : slider.getMaximum());
 2004               }
 2005           }
 2006       }
 2007   }

Save This Page
Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]