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

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

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