Home » openjdk-7 » javax » swing » [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;
   27   
   28   import javax.swing.event;
   29   import javax.swing.plaf;
   30   import javax.accessibility;
   31   
   32   import java.io.Serializable;
   33   import java.io.ObjectOutputStream;
   34   import java.io.IOException;
   35   
   36   import java.awt;
   37   import java.util;
   38   import java.beans;
   39   
   40   
   41   /**
   42    * A component that lets the user graphically select a value by sliding
   43    * a knob within a bounded interval. The knob is always positioned
   44    * at the points that match integer values within the specified interval.
   45    * <p>
   46    * The slider can show both
   47    * major tick marks, and minor tick marks between the major ones.  The number of
   48    * values between the tick marks is controlled with
   49    * <code>setMajorTickSpacing</code> and <code>setMinorTickSpacing</code>.
   50    * Painting of tick marks is controlled by {@code setPaintTicks}.
   51    * <p>
   52    * Sliders can also print text labels at regular intervals (or at
   53    * arbitrary locations) along the slider track.  Painting of labels is
   54    * controlled by {@code setLabelTable} and {@code setPaintLabels}.
   55    * <p>
   56    * For further information and examples see
   57    * <a
   58    href="http://java.sun.com/docs/books/tutorial/uiswing/components/slider.html">How to Use Sliders</a>,
   59    * a section in <em>The Java Tutorial.</em>
   60    * <p>
   61    * <strong>Warning:</strong> Swing is not thread safe. For more
   62    * information see <a
   63    * href="package-summary.html#threading">Swing's Threading
   64    * Policy</a>.
   65    * <p>
   66    * <strong>Warning:</strong>
   67    * Serialized objects of this class will not be compatible with
   68    * future Swing releases. The current serialization support is
   69    * appropriate for short term storage or RMI between applications running
   70    * the same version of Swing.  As of 1.4, support for long term storage
   71    * of all JavaBeans<sup><font size="-2">TM</font></sup>
   72    * has been added to the <code>java.beans</code> package.
   73    * Please see {@link java.beans.XMLEncoder}.
   74    *
   75    * @beaninfo
   76    *      attribute: isContainer false
   77    *    description: A component that supports selecting a integer value from a range.
   78    *
   79    * @author David Kloba
   80    */
   81   public class JSlider extends JComponent implements SwingConstants, Accessible {
   82       /**
   83        * @see #getUIClassID
   84        * @see #readObject
   85        */
   86       private static final String uiClassID = "SliderUI";
   87   
   88       private boolean paintTicks = false;
   89       private boolean paintTrack = true;
   90       private boolean paintLabels = false;
   91       private boolean isInverted = false;
   92   
   93       /**
   94        * The data model that handles the numeric maximum value,
   95        * minimum value, and current-position value for the slider.
   96        */
   97       protected BoundedRangeModel sliderModel;
   98   
   99       /**
  100        * The number of values between the major tick marks -- the
  101        * larger marks that break up the minor tick marks.
  102        */
  103       protected int majorTickSpacing;
  104   
  105       /**
  106        * The number of values between the minor tick marks -- the
  107        * smaller marks that occur between the major tick marks.
  108        * @see #setMinorTickSpacing
  109        */
  110       protected int minorTickSpacing;
  111   
  112       /**
  113        * If true, the knob (and the data value it represents)
  114        * resolve to the closest tick mark next to where the user
  115        * positioned the knob.  The default is false.
  116        * @see #setSnapToTicks
  117        */
  118       protected boolean snapToTicks = false;
  119   
  120       /**
  121        * If true, the knob (and the data value it represents)
  122        * resolve to the closest slider value next to where the user
  123        * positioned the knob.
  124        */
  125       boolean snapToValue = true;
  126   
  127       /**
  128        * Whether the slider is horizontal or vertical
  129        * The default is horizontal.
  130        *
  131        * @see #setOrientation
  132        */
  133       protected int orientation;
  134   
  135   
  136       /**
  137        * {@code Dictionary} of what labels to draw at which values
  138        */
  139       private Dictionary labelTable;
  140   
  141   
  142       /**
  143        * The changeListener (no suffix) is the listener we add to the
  144        * slider's model.  This listener is initialized to the
  145        * {@code ChangeListener} returned from {@code createChangeListener},
  146        * which by default just forwards events
  147        * to {@code ChangeListener}s (if any) added directly to the slider.
  148        *
  149        * @see #addChangeListener
  150        * @see #createChangeListener
  151        */
  152       protected ChangeListener changeListener = createChangeListener();
  153   
  154   
  155       /**
  156        * Only one <code>ChangeEvent</code> is needed per slider instance since the
  157        * event's only (read-only) state is the source property.  The source
  158        * of events generated here is always "this". The event is lazily
  159        * created the first time that an event notification is fired.
  160        *
  161        * @see #fireStateChanged
  162        */
  163       protected transient ChangeEvent changeEvent = null;
  164   
  165   
  166       private void checkOrientation(int orientation) {
  167           switch (orientation) {
  168           case VERTICAL:
  169           case HORIZONTAL:
  170               break;
  171           default:
  172               throw new IllegalArgumentException("orientation must be one of: VERTICAL, HORIZONTAL");
  173           }
  174       }
  175   
  176   
  177       /**
  178        * Creates a horizontal slider with the range 0 to 100 and
  179        * an initial value of 50.
  180        */
  181       public JSlider() {
  182           this(HORIZONTAL, 0, 100, 50);
  183       }
  184   
  185   
  186       /**
  187        * Creates a slider using the specified orientation with the
  188        * range {@code 0} to {@code 100} and an initial value of {@code 50}.
  189        * The orientation can be
  190        * either <code>SwingConstants.VERTICAL</code> or
  191        * <code>SwingConstants.HORIZONTAL</code>.
  192        *
  193        * @param  orientation  the orientation of the slider
  194        * @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
  195        * @see #setOrientation
  196        */
  197       public JSlider(int orientation) {
  198           this(orientation, 0, 100, 50);
  199       }
  200   
  201   
  202       /**
  203        * Creates a horizontal slider using the specified min and max
  204        * with an initial value equal to the average of the min plus max.
  205        * <p>
  206        * The <code>BoundedRangeModel</code> that holds the slider's data
  207        * handles any issues that may arise from improperly setting the
  208        * minimum and maximum values on the slider.  See the
  209        * {@code BoundedRangeModel} documentation for details.
  210        *
  211        * @param min  the minimum value of the slider
  212        * @param max  the maximum value of the slider
  213        *
  214        * @see BoundedRangeModel
  215        * @see #setMinimum
  216        * @see #setMaximum
  217        */
  218       public JSlider(int min, int max) {
  219           this(HORIZONTAL, min, max, (min + max) / 2);
  220       }
  221   
  222   
  223       /**
  224        * Creates a horizontal slider using the specified min, max and value.
  225        * <p>
  226        * The <code>BoundedRangeModel</code> that holds the slider's data
  227        * handles any issues that may arise from improperly setting the
  228        * minimum, initial, and maximum values on the slider.  See the
  229        * {@code BoundedRangeModel} documentation for details.
  230        *
  231        * @param min  the minimum value of the slider
  232        * @param max  the maximum value of the slider
  233        * @param value  the initial value of the slider
  234        *
  235        * @see BoundedRangeModel
  236        * @see #setMinimum
  237        * @see #setMaximum
  238        * @see #setValue
  239        */
  240       public JSlider(int min, int max, int value) {
  241           this(HORIZONTAL, min, max, value);
  242       }
  243   
  244   
  245       /**
  246        * Creates a slider with the specified orientation and the
  247        * specified minimum, maximum, and initial values.
  248        * The orientation can be
  249        * either <code>SwingConstants.VERTICAL</code> or
  250        * <code>SwingConstants.HORIZONTAL</code>.
  251        * <p>
  252        * The <code>BoundedRangeModel</code> that holds the slider's data
  253        * handles any issues that may arise from improperly setting the
  254        * minimum, initial, and maximum values on the slider.  See the
  255        * {@code BoundedRangeModel} documentation for details.
  256        *
  257        * @param orientation  the orientation of the slider
  258        * @param min  the minimum value of the slider
  259        * @param max  the maximum value of the slider
  260        * @param value  the initial value of the slider
  261        *
  262        * @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
  263        *
  264        * @see BoundedRangeModel
  265        * @see #setOrientation
  266        * @see #setMinimum
  267        * @see #setMaximum
  268        * @see #setValue
  269        */
  270       public JSlider(int orientation, int min, int max, int value)
  271       {
  272           checkOrientation(orientation);
  273           this.orientation = orientation;
  274           setModel(new DefaultBoundedRangeModel(value, 0, min, max));
  275           updateUI();
  276       }
  277   
  278   
  279       /**
  280        * Creates a horizontal slider using the specified
  281        * BoundedRangeModel.
  282        */
  283       public JSlider(BoundedRangeModel brm)
  284       {
  285           this.orientation = JSlider.HORIZONTAL;
  286           setModel(brm);
  287           updateUI();
  288       }
  289   
  290   
  291       /**
  292        * Gets the UI object which implements the L&F for this component.
  293        *
  294        * @return the SliderUI object that implements the Slider L&F
  295        */
  296       public SliderUI getUI() {
  297           return(SliderUI)ui;
  298       }
  299   
  300   
  301       /**
  302        * Sets the UI object which implements the L&F for this component.
  303        *
  304        * @param ui the SliderUI L&F object
  305        * @see UIDefaults#getUI
  306        * @beaninfo
  307        *        bound: true
  308        *       hidden: true
  309        *    attribute: visualUpdate true
  310        *  description: The UI object that implements the slider's LookAndFeel.
  311        */
  312       public void setUI(SliderUI ui) {
  313           super.setUI(ui);
  314       }
  315   
  316   
  317       /**
  318        * Resets the UI property to a value from the current look and feel.
  319        *
  320        * @see JComponent#updateUI
  321        */
  322       public void updateUI() {
  323           setUI((SliderUI)UIManager.getUI(this));
  324           // The labels preferred size may be derived from the font
  325           // of the slider, so we must update the UI of the slider first, then
  326           // that of labels.  This way when setSize is called the right
  327           // font is used.
  328           updateLabelUIs();
  329       }
  330   
  331   
  332       /**
  333        * Returns the name of the L&F class that renders this component.
  334        *
  335        * @return "SliderUI"
  336        * @see JComponent#getUIClassID
  337        * @see UIDefaults#getUI
  338        */
  339       public String getUIClassID() {
  340           return uiClassID;
  341       }
  342   
  343   
  344       /**
  345        * We pass Change events along to the listeners with the
  346        * the slider (instead of the model itself) as the event source.
  347        */
  348       private class ModelListener implements ChangeListener, Serializable {
  349           public void stateChanged(ChangeEvent e) {
  350               fireStateChanged();
  351           }
  352       }
  353   
  354   
  355       /**
  356        * Subclasses that want to handle {@code ChangeEvent}s
  357        * from the model differently
  358        * can override this to return
  359        * an instance of a custom <code>ChangeListener</code> implementation.
  360        * The default {@code ChangeListener} simply calls the
  361        * {@code fireStateChanged} method to forward {@code ChangeEvent}s
  362        * to the {@code ChangeListener}s that have been added directly to the
  363        * slider.
  364        * @see #changeListener
  365        * @see #fireStateChanged
  366        * @see javax.swing.event.ChangeListener
  367        * @see javax.swing.BoundedRangeModel
  368        */
  369       protected ChangeListener createChangeListener() {
  370           return new ModelListener();
  371       }
  372   
  373   
  374       /**
  375        * Adds a ChangeListener to the slider.
  376        *
  377        * @param l the ChangeListener to add
  378        * @see #fireStateChanged
  379        * @see #removeChangeListener
  380        */
  381       public void addChangeListener(ChangeListener l) {
  382           listenerList.add(ChangeListener.class, l);
  383       }
  384   
  385   
  386       /**
  387        * Removes a ChangeListener from the slider.
  388        *
  389        * @param l the ChangeListener to remove
  390        * @see #fireStateChanged
  391        * @see #addChangeListener
  392   
  393        */
  394       public void removeChangeListener(ChangeListener l) {
  395           listenerList.remove(ChangeListener.class, l);
  396       }
  397   
  398   
  399       /**
  400        * Returns an array of all the <code>ChangeListener</code>s added
  401        * to this JSlider with addChangeListener().
  402        *
  403        * @return all of the <code>ChangeListener</code>s added or an empty
  404        *         array if no listeners have been added
  405        * @since 1.4
  406        */
  407       public ChangeListener[] getChangeListeners() {
  408           return listenerList.getListeners(ChangeListener.class);
  409       }
  410   
  411   
  412       /**
  413        * Send a {@code ChangeEvent}, whose source is this {@code JSlider}, to
  414        * all {@code ChangeListener}s that have registered interest in
  415        * {@code ChangeEvent}s.
  416        * This method is called each time a {@code ChangeEvent} is received from
  417        * the model.
  418        * <p>
  419        * The event instance is created if necessary, and stored in
  420        * {@code changeEvent}.
  421        *
  422        * @see #addChangeListener
  423        * @see EventListenerList
  424        */
  425       protected void fireStateChanged() {
  426           Object[] listeners = listenerList.getListenerList();
  427           for (int i = listeners.length - 2; i >= 0; i -= 2) {
  428               if (listeners[i]==ChangeListener.class) {
  429                   if (changeEvent == null) {
  430                       changeEvent = new ChangeEvent(this);
  431                   }
  432                   ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
  433               }
  434           }
  435       }
  436   
  437   
  438       /**
  439        * Returns the {@code BoundedRangeModel} that handles the slider's three
  440        * fundamental properties: minimum, maximum, value.
  441        *
  442        * @return the data model for this component
  443        * @see #setModel
  444        * @see    BoundedRangeModel
  445        */
  446       public BoundedRangeModel getModel() {
  447           return sliderModel;
  448       }
  449   
  450   
  451       /**
  452        * Sets the {@code BoundedRangeModel} that handles the slider's three
  453        * fundamental properties: minimum, maximum, value.
  454        *<p>
  455        * Attempts to pass a {@code null} model to this method result in
  456        * undefined behavior, and, most likely, exceptions.
  457        *
  458        * @param  newModel the new, {@code non-null} <code>BoundedRangeModel</code> to use
  459        *
  460        * @see #getModel
  461        * @see    BoundedRangeModel
  462        * @beaninfo
  463        *       bound: true
  464        * description: The sliders BoundedRangeModel.
  465        */
  466       public void setModel(BoundedRangeModel newModel)
  467       {
  468           BoundedRangeModel oldModel = getModel();
  469   
  470           if (oldModel != null) {
  471               oldModel.removeChangeListener(changeListener);
  472           }
  473   
  474           sliderModel = newModel;
  475   
  476           if (newModel != null) {
  477               newModel.addChangeListener(changeListener);
  478           }
  479   
  480           if (accessibleContext != null) {
  481               accessibleContext.firePropertyChange(
  482                                                   AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
  483                                                   (oldModel == null
  484                                                    ? null : Integer.valueOf(oldModel.getValue())),
  485                                                   (newModel == null
  486                                                    ? null : Integer.valueOf(newModel.getValue())));
  487           }
  488   
  489           firePropertyChange("model", oldModel, sliderModel);
  490       }
  491   
  492   
  493       /**
  494        * Returns the slider's current value
  495        * from the {@code BoundedRangeModel}.
  496        *
  497        * @return  the current value of the slider
  498        * @see     #setValue
  499        * @see     BoundedRangeModel#getValue
  500        */
  501       public int getValue() {
  502           return getModel().getValue();
  503       }
  504   
  505       /**
  506        * Sets the slider's current value to {@code n}.  This method
  507        * forwards the new value to the model.
  508        * <p>
  509        * The data model (an instance of {@code BoundedRangeModel})
  510        * handles any mathematical
  511        * issues arising from assigning faulty values.  See the
  512        * {@code BoundedRangeModel} documentation for details.
  513        * <p>
  514        * If the new value is different from the previous value,
  515        * all change listeners are notified.
  516        *
  517        * @param   n       the new value
  518        * @see     #getValue
  519        * @see     #addChangeListener
  520        * @see     BoundedRangeModel#setValue
  521        * @beaninfo
  522        *   preferred: true
  523        * description: The sliders current value.
  524        */
  525       public void setValue(int n) {
  526           BoundedRangeModel m = getModel();
  527           int oldValue = m.getValue();
  528           if (oldValue == n) {
  529               return;
  530           }
  531           m.setValue(n);
  532   
  533           if (accessibleContext != null) {
  534               accessibleContext.firePropertyChange(
  535                                                   AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
  536                                                   Integer.valueOf(oldValue),
  537                                                   Integer.valueOf(m.getValue()));
  538           }
  539       }
  540   
  541   
  542       /**
  543        * Returns the minimum value supported by the slider
  544        * from the <code>BoundedRangeModel</code>.
  545        *
  546        * @return the value of the model's minimum property
  547        * @see #setMinimum
  548        * @see     BoundedRangeModel#getMinimum
  549        */
  550       public int getMinimum() {
  551           return getModel().getMinimum();
  552       }
  553   
  554   
  555       /**
  556        * Sets the slider's minimum value to {@code minimum}.  This method
  557        * forwards the new minimum value to the model.
  558        * <p>
  559        * The data model (an instance of {@code BoundedRangeModel})
  560        * handles any mathematical
  561        * issues arising from assigning faulty values.  See the
  562        * {@code BoundedRangeModel} documentation for details.
  563        * <p>
  564        * If the new minimum value is different from the previous minimum value,
  565        * all change listeners are notified.
  566        *
  567        * @param minimum  the new minimum
  568        * @see #getMinimum
  569        * @see    #addChangeListener
  570        * @see BoundedRangeModel#setMinimum
  571        * @beaninfo
  572        *       bound: true
  573        *   preferred: true
  574        * description: The sliders minimum value.
  575        */
  576       public void setMinimum(int minimum) {
  577           int oldMin = getModel().getMinimum();
  578           getModel().setMinimum(minimum);
  579           firePropertyChange( "minimum", Integer.valueOf( oldMin ), Integer.valueOf( minimum ) );
  580       }
  581   
  582   
  583       /**
  584        * Returns the maximum value supported by the slider
  585        * from the <code>BoundedRangeModel</code>.
  586        *
  587        * @return the value of the model's maximum property
  588        * @see #setMaximum
  589        * @see BoundedRangeModel#getMaximum
  590        */
  591       public int getMaximum() {
  592           return getModel().getMaximum();
  593       }
  594   
  595   
  596       /**
  597        * Sets the slider's maximum value to {@code maximum}.  This method
  598        * forwards the new maximum value to the model.
  599        * <p>
  600        * The data model (an instance of {@code BoundedRangeModel})
  601        * handles any mathematical
  602        * issues arising from assigning faulty values.  See the
  603        * {@code BoundedRangeModel} documentation for details.
  604        * <p>
  605        * If the new maximum value is different from the previous maximum value,
  606        * all change listeners are notified.
  607        *
  608        * @param maximum  the new maximum
  609        * @see #getMaximum
  610        * @see #addChangeListener
  611        * @see BoundedRangeModel#setMaximum
  612        * @beaninfo
  613        *       bound: true
  614        *   preferred: true
  615        * description: The sliders maximum value.
  616        */
  617       public void setMaximum(int maximum) {
  618           int oldMax = getModel().getMaximum();
  619           getModel().setMaximum(maximum);
  620           firePropertyChange( "maximum", Integer.valueOf( oldMax ), Integer.valueOf( maximum ) );
  621       }
  622   
  623   
  624       /**
  625        * Returns the {@code valueIsAdjusting} property from the model.  For
  626        * details on how this is used, see the {@code setValueIsAdjusting}
  627        * documentation.
  628        *
  629        * @return the value of the model's {@code valueIsAdjusting} property
  630        * @see #setValueIsAdjusting
  631        */
  632       public boolean getValueIsAdjusting() {
  633           return getModel().getValueIsAdjusting();
  634       }
  635   
  636   
  637       /**
  638        * Sets the model's {@code valueIsAdjusting} property.  Slider look and
  639        * feel implementations should set this property to {@code true} when
  640        * a knob drag begins, and to {@code false} when the drag ends.
  641        *
  642        * @param b the new value for the {@code valueIsAdjusting} property
  643        * @see   #getValueIsAdjusting
  644        * @see   BoundedRangeModel#setValueIsAdjusting
  645        * @beaninfo
  646        *      expert: true
  647        * description: True if the slider knob is being dragged.
  648        */
  649       public void setValueIsAdjusting(boolean b) {
  650           BoundedRangeModel m = getModel();
  651           boolean oldValue = m.getValueIsAdjusting();
  652           m.setValueIsAdjusting(b);
  653   
  654           if ((oldValue != b) && (accessibleContext != null)) {
  655               accessibleContext.firePropertyChange(
  656                                                   AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  657                                                   ((oldValue) ? AccessibleState.BUSY : null),
  658                                                   ((b) ? AccessibleState.BUSY : null));
  659           }
  660       }
  661   
  662   
  663       /**
  664        * Returns the "extent" from the <code>BoundedRangeModel</code>.
  665        * This respresents the range of values "covered" by the knob.
  666        *
  667        * @return an int representing the extent
  668        * @see #setExtent
  669        * @see BoundedRangeModel#getExtent
  670        */
  671       public int getExtent() {
  672           return getModel().getExtent();
  673       }
  674   
  675   
  676       /**
  677        * Sets the size of the range "covered" by the knob.  Most look
  678        * and feel implementations will change the value by this amount
  679        * if the user clicks on either side of the knob.  This method just
  680        * forwards the new extent value to the model.
  681        * <p>
  682        * The data model (an instance of {@code BoundedRangeModel})
  683        * handles any mathematical
  684        * issues arising from assigning faulty values.  See the
  685        * {@code BoundedRangeModel} documentation for details.
  686        * <p>
  687        * If the new extent value is different from the previous extent value,
  688        * all change listeners are notified.
  689        *
  690        * @param extent the new extent
  691        * @see   #getExtent
  692        * @see   BoundedRangeModel#setExtent
  693        * @beaninfo
  694        *      expert: true
  695        * description: Size of the range covered by the knob.
  696        */
  697       public void setExtent(int extent) {
  698           getModel().setExtent(extent);
  699       }
  700   
  701   
  702       /**
  703        * Return this slider's vertical or horizontal orientation.
  704        * @return {@code SwingConstants.VERTICAL} or
  705        *  {@code SwingConstants.HORIZONTAL}
  706        * @see #setOrientation
  707        */
  708       public int getOrientation() {
  709           return orientation;
  710       }
  711   
  712   
  713       /**
  714        * Set the slider's orientation to either {@code SwingConstants.VERTICAL} or
  715        * {@code SwingConstants.HORIZONTAL}.
  716        *
  717        * @param orientation {@code HORIZONTAL} or {@code VERTICAL}
  718        * @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
  719        * @see #getOrientation
  720        * @beaninfo
  721        *    preferred: true
  722        *        bound: true
  723        *    attribute: visualUpdate true
  724        *  description: Set the scrollbars orientation to either VERTICAL or HORIZONTAL.
  725        *         enum: VERTICAL JSlider.VERTICAL
  726        *               HORIZONTAL JSlider.HORIZONTAL
  727        *
  728        */
  729       public void setOrientation(int orientation)
  730       {
  731           checkOrientation(orientation);
  732           int oldValue = this.orientation;
  733           this.orientation = orientation;
  734           firePropertyChange("orientation", oldValue, orientation);
  735   
  736           if ((oldValue != orientation) && (accessibleContext != null)) {
  737               accessibleContext.firePropertyChange(
  738                                                   AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  739                                                   ((oldValue == VERTICAL)
  740                                                    ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL),
  741                                                   ((orientation == VERTICAL)
  742                                                    ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL));
  743           }
  744           if (orientation != oldValue) {
  745               revalidate();
  746           }
  747       }
  748   
  749   
  750       /**
  751        * {@inheritDoc}
  752        *
  753        * @since 1.6
  754        */
  755       public void setFont(Font font) {
  756           super.setFont(font);
  757           updateLabelSizes();
  758       }
  759   
  760       /**
  761        * {@inheritDoc}
  762        * @since 1.7
  763        */
  764       public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
  765           if (!isShowing()) {
  766               return false;
  767           }
  768   
  769           // Check that there is a label with such image
  770           Enumeration elements = labelTable.elements();
  771   
  772           while (elements.hasMoreElements()) {
  773               Component component = (Component) elements.nextElement();
  774   
  775               if (component instanceof JLabel) {
  776                   JLabel label = (JLabel) component;
  777   
  778                   if (SwingUtilities.doesIconReferenceImage(label.getIcon(), img) ||
  779                           SwingUtilities.doesIconReferenceImage(label.getDisabledIcon(), img)) {
  780                       return super.imageUpdate(img, infoflags, x, y, w, h);
  781                   }
  782               }
  783           }
  784   
  785           return false;
  786       }
  787   
  788       /**
  789        * Returns the dictionary of what labels to draw at which values.
  790        *
  791        * @return the <code>Dictionary</code> containing labels and
  792        *    where to draw them
  793        */
  794       public Dictionary getLabelTable() {
  795   /*
  796           if ( labelTable == null && getMajorTickSpacing() > 0 ) {
  797               setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
  798           }
  799   */
  800           return labelTable;
  801       }
  802   
  803   
  804       /**
  805        * Used to specify what label will be drawn at any given value.
  806        * The key-value pairs are of this format:
  807        * <code>{ Integer value, java.swing.JComponent label }</code>.
  808        * <p>
  809        * An easy way to generate a standard table of value labels is by using the
  810        * {@code createStandardLabels} method.
  811        * <p>
  812        * Once the labels have been set, this method calls {@link #updateLabelUIs}.
  813        * Note that the labels are only painted if the {@code paintLabels}
  814        * property is {@code true}.
  815        *
  816        * @param labels new {@code Dictionary} of labels, or {@code null} to
  817        *        remove all labels
  818        * @see #createStandardLabels(int)
  819        * @see #getLabelTable
  820        * @see #setPaintLabels
  821        * @beaninfo
  822        *       hidden: true
  823        *        bound: true
  824        *    attribute: visualUpdate true
  825        *  description: Specifies what labels will be drawn for any given value.
  826        */
  827       public void setLabelTable( Dictionary labels ) {
  828           Dictionary oldTable = labelTable;
  829           labelTable = labels;
  830           updateLabelUIs();
  831           firePropertyChange("labelTable", oldTable, labelTable );
  832           if (labels != oldTable) {
  833               revalidate();
  834               repaint();
  835           }
  836       }
  837   
  838   
  839       /**
  840        * Updates the UIs for the labels in the label table by calling
  841        * {@code updateUI} on each label.  The UIs are updated from
  842        * the current look and feel.  The labels are also set to their
  843        * preferred size.
  844        *
  845        * @see #setLabelTable
  846        * @see JComponent#updateUI
  847        */
  848       protected void updateLabelUIs() {
  849           Dictionary labelTable = getLabelTable();
  850   
  851           if (labelTable == null) {
  852               return;
  853           }
  854           Enumeration labels = labelTable.keys();
  855           while ( labels.hasMoreElements() ) {
  856               JComponent component = (JComponent) labelTable.get(labels.nextElement());
  857               component.updateUI();
  858               component.setSize(component.getPreferredSize());
  859           }
  860       }
  861   
  862       private void updateLabelSizes() {
  863           Dictionary labelTable = getLabelTable();
  864           if (labelTable != null) {
  865               Enumeration labels = labelTable.elements();
  866               while (labels.hasMoreElements()) {
  867                   JComponent component = (JComponent) labels.nextElement();
  868                   component.setSize(component.getPreferredSize());
  869               }
  870           }
  871       }
  872   
  873   
  874       /**
  875        * Creates a {@code Hashtable} of numerical text labels, starting at the
  876        * slider minimum, and using the increment specified.
  877        * For example, if you call <code>createStandardLabels( 10 )</code>
  878        * and the slider minimum is zero,
  879        * then labels will be created for the values 0, 10, 20, 30, and so on.
  880        * <p>
  881        * For the labels to be drawn on the slider, the returned {@code Hashtable}
  882        * must be passed into {@code setLabelTable}, and {@code setPaintLabels}
  883        * must be set to {@code true}.
  884        * <p>
  885        * For further details on the makeup of the returned {@code Hashtable}, see
  886        * the {@code setLabelTable} documentation.
  887        *
  888        * @param  increment  distance between labels in the generated hashtable
  889        * @return a new {@code Hashtable} of labels
  890        * @see #setLabelTable
  891        * @see #setPaintLabels
  892        * @throws IllegalArgumentException if {@code increment} is less than or
  893        *          equal to zero
  894        */
  895       public Hashtable createStandardLabels( int increment ) {
  896           return createStandardLabels( increment, getMinimum() );
  897       }
  898   
  899   
  900       /**
  901        * Creates a {@code Hashtable} of numerical text labels, starting at the
  902        * starting point specified, and using the increment specified.
  903        * For example, if you call
  904        * <code>createStandardLabels( 10, 2 )</code>,
  905        * then labels will be created for the values 2, 12, 22, 32, and so on.
  906        * <p>
  907        * For the labels to be drawn on the slider, the returned {@code Hashtable}
  908        * must be passed into {@code setLabelTable}, and {@code setPaintLabels}
  909        * must be set to {@code true}.
  910        * <p>
  911        * For further details on the makeup of the returned {@code Hashtable}, see
  912        * the {@code setLabelTable} documentation.
  913        *
  914        * @param  increment  distance between labels in the generated hashtable
  915        * @param  start      value at which the labels will begin
  916        * @return a new {@code Hashtable} of labels
  917        * @see #setLabelTable
  918        * @see #setPaintLabels
  919        * @exception IllegalArgumentException if {@code start} is
  920        *          out of range, or if {@code increment} is less than or equal
  921        *          to zero
  922        */
  923       public Hashtable createStandardLabels( int increment, int start ) {
  924           if ( start > getMaximum() || start < getMinimum() ) {
  925               throw new IllegalArgumentException( "Slider label start point out of range." );
  926           }
  927   
  928           if ( increment <= 0 ) {
  929               throw new IllegalArgumentException( "Label incremement must be > 0" );
  930           }
  931   
  932           class SmartHashtable extends Hashtable<Object, Object> implements PropertyChangeListener {
  933               int increment = 0;
  934               int start = 0;
  935               boolean startAtMin = false;
  936   
  937               class LabelUIResource extends JLabel implements UIResource {
  938                   public LabelUIResource( String text, int alignment ) {
  939                       super( text, alignment );
  940                       setName("Slider.label");
  941                   }
  942   
  943                   public Font getFont() {
  944                       Font font = super.getFont();
  945                       if (font != null && !(font instanceof UIResource)) {
  946                           return font;
  947                       }
  948                       return JSlider.this.getFont();
  949                   }
  950   
  951                   public Color getForeground() {
  952                       Color fg = super.getForeground();
  953                       if (fg != null && !(fg instanceof UIResource)) {
  954                           return fg;
  955                       }
  956                       if (!(JSlider.this.getForeground() instanceof UIResource)) {
  957                           return JSlider.this.getForeground();
  958                       }
  959                       return fg;
  960                   }
  961               }
  962   
  963               public SmartHashtable( int increment, int start ) {
  964                   super();
  965                   this.increment = increment;
  966                   this.start = start;
  967                   startAtMin = start == getMinimum();
  968                   createLabels();
  969               }
  970   
  971               public void propertyChange( PropertyChangeEvent e ) {
  972                   if ( e.getPropertyName().equals( "minimum" ) && startAtMin ) {
  973                       start = getMinimum();
  974                   }
  975   
  976                   if ( e.getPropertyName().equals( "minimum" ) ||
  977                        e.getPropertyName().equals( "maximum" ) ) {
  978   
  979                       Enumeration keys = getLabelTable().keys();
  980                       Hashtable<Object, Object> hashtable = new Hashtable<Object, Object>();
  981   
  982                       // Save the labels that were added by the developer
  983                       while ( keys.hasMoreElements() ) {
  984                           Object key = keys.nextElement();
  985                           Object value = labelTable.get(key);
  986                           if ( !(value instanceof LabelUIResource) ) {
  987                               hashtable.put( key, value );
  988                           }
  989                       }
  990   
  991                       clear();
  992                       createLabels();
  993   
  994                       // Add the saved labels
  995                       keys = hashtable.keys();
  996                       while ( keys.hasMoreElements() ) {
  997                           Object key = keys.nextElement();
  998                           put( key, hashtable.get( key ) );
  999                       }
 1000   
 1001                       ((JSlider)e.getSource()).setLabelTable( this );
 1002                   }
 1003               }
 1004   
 1005               void createLabels() {
 1006                   for ( int labelIndex = start; labelIndex <= getMaximum(); labelIndex += increment ) {
 1007                       put( Integer.valueOf( labelIndex ), new LabelUIResource( ""+labelIndex, JLabel.CENTER ) );
 1008                   }
 1009               }
 1010           }
 1011   
 1012           SmartHashtable table = new SmartHashtable( increment, start );
 1013   
 1014           Dictionary labelTable = getLabelTable();
 1015   
 1016           if (labelTable != null && (labelTable instanceof PropertyChangeListener)) {
 1017               removePropertyChangeListener((PropertyChangeListener) labelTable);
 1018           }
 1019   
 1020           addPropertyChangeListener( table );
 1021   
 1022           return table;
 1023       }
 1024   
 1025   
 1026       /**
 1027        * Returns true if the value-range shown for the slider is reversed,
 1028        *
 1029        * @return true if the slider values are reversed from their normal order
 1030        * @see #setInverted
 1031        */
 1032       public boolean getInverted() {
 1033           return isInverted;
 1034       }
 1035   
 1036   
 1037       /**
 1038        * Specify true to reverse the value-range shown for the slider and false to
 1039        * put the value range in the normal order.  The order depends on the
 1040        * slider's <code>ComponentOrientation</code> property.  Normal (non-inverted)
 1041        * horizontal sliders with a <code>ComponentOrientation</code> value of
 1042        * <code>LEFT_TO_RIGHT</code> have their maximum on the right.
 1043        * Normal horizontal sliders with a <code>ComponentOrientation</code> value of
 1044        * <code>RIGHT_TO_LEFT</code> have their maximum on the left.  Normal vertical
 1045        * sliders have their maximum on the top.  These labels are reversed when the
 1046        * slider is inverted.
 1047        * <p>
 1048        * By default, the value of this property is {@code false}.
 1049        *
 1050        * @param b  true to reverse the slider values from their normal order
 1051        * @beaninfo
 1052        *        bound: true
 1053        *    attribute: visualUpdate true
 1054        *  description: If true reverses the slider values from their normal order
 1055        *
 1056        */
 1057       public void setInverted( boolean b ) {
 1058           boolean oldValue = isInverted;
 1059           isInverted = b;
 1060           firePropertyChange("inverted", oldValue, isInverted);
 1061           if (b != oldValue) {
 1062               repaint();
 1063           }
 1064       }
 1065   
 1066   
 1067       /**
 1068        * This method returns the major tick spacing.  The number that is returned
 1069        * represents the distance, measured in values, between each major tick mark.
 1070        * If you have a slider with a range from 0 to 50 and the major tick spacing
 1071        * is set to 10, you will get major ticks next to the following values:
 1072        * 0, 10, 20, 30, 40, 50.
 1073        *
 1074        * @return the number of values between major ticks
 1075        * @see #setMajorTickSpacing
 1076        */
 1077       public int getMajorTickSpacing() {
 1078           return majorTickSpacing;
 1079       }
 1080   
 1081   
 1082       /**
 1083        * This method sets the major tick spacing.  The number that is passed in
 1084        * represents the distance, measured in values, between each major tick mark.
 1085        * If you have a slider with a range from 0 to 50 and the major tick spacing
 1086        * is set to 10, you will get major ticks next to the following values:
 1087        * 0, 10, 20, 30, 40, 50.
 1088        * <p>
 1089        * In order for major ticks to be painted, {@code setPaintTicks} must be
 1090        * set to {@code true}.
 1091        * <p>
 1092        * This method will also set up a label table for you.
 1093        * If there is not already a label table, and the major tick spacing is
 1094        * {@code > 0}, and {@code getPaintLabels} returns
 1095        * {@code true}, a standard label table will be generated (by calling
 1096        * {@code createStandardLabels}) with labels at the major tick marks.
 1097        * For the example above, you would get text labels: "0",
 1098        * "10", "20", "30", "40", "50".
 1099        * The label table is then set on the slider by calling
 1100        * {@code setLabelTable}.
 1101        *
 1102        * @param  n  new value for the {@code majorTickSpacing} property
 1103        * @see #getMajorTickSpacing
 1104        * @see #setPaintTicks
 1105        * @see #setLabelTable
 1106        * @see #createStandardLabels(int)
 1107        * @beaninfo
 1108        *        bound: true
 1109        *    attribute: visualUpdate true
 1110        *  description: Sets the number of values between major tick marks.
 1111        *
 1112        */
 1113       public void setMajorTickSpacing(int n) {
 1114           int oldValue = majorTickSpacing;
 1115           majorTickSpacing = n;
 1116           if ( labelTable == null && getMajorTickSpacing() > 0 && getPaintLabels() ) {
 1117               setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
 1118           }
 1119           firePropertyChange("majorTickSpacing", oldValue, majorTickSpacing);
 1120           if (majorTickSpacing != oldValue && getPaintTicks()) {
 1121               repaint();
 1122           }
 1123       }
 1124   
 1125   
 1126   
 1127       /**
 1128        * This method returns the minor tick spacing.  The number that is returned
 1129        * represents the distance, measured in values, between each minor tick mark.
 1130        * If you have a slider with a range from 0 to 50 and the minor tick spacing
 1131        * is set to 10, you will get minor ticks next to the following values:
 1132        * 0, 10, 20, 30, 40, 50.
 1133        *
 1134        * @return the number of values between minor ticks
 1135        * @see #getMinorTickSpacing
 1136        */
 1137       public int getMinorTickSpacing() {
 1138           return minorTickSpacing;
 1139       }
 1140   
 1141   
 1142       /**
 1143        * This method sets the minor tick spacing.  The number that is passed in
 1144        * represents the distance, measured in values, between each minor tick mark.
 1145        * If you have a slider with a range from 0 to 50 and the minor tick spacing
 1146        * is set to 10, you will get minor ticks next to the following values:
 1147        * 0, 10, 20, 30, 40, 50.
 1148        * <p>
 1149        * In order for minor ticks to be painted, {@code setPaintTicks} must be
 1150        * set to {@code true}.
 1151        *
 1152        * @param  n  new value for the {@code minorTickSpacing} property
 1153        * @see #getMinorTickSpacing
 1154        * @see #setPaintTicks
 1155        * @beaninfo
 1156        *        bound: true
 1157        *    attribute: visualUpdate true
 1158        *  description: Sets the number of values between minor tick marks.
 1159        */
 1160       public void setMinorTickSpacing(int n) {
 1161           int oldValue = minorTickSpacing;
 1162           minorTickSpacing = n;
 1163           firePropertyChange("minorTickSpacing", oldValue, minorTickSpacing);
 1164           if (minorTickSpacing != oldValue && getPaintTicks()) {
 1165               repaint();
 1166           }
 1167       }
 1168   
 1169   
 1170       /**
 1171        * Returns true if the knob (and the data value it represents)
 1172        * resolve to the closest tick mark next to where the user
 1173        * positioned the knob.
 1174        *
 1175        * @return true if the value snaps to the nearest tick mark, else false
 1176        * @see #setSnapToTicks
 1177        */
 1178       public boolean getSnapToTicks() {
 1179           return snapToTicks;
 1180       }
 1181   
 1182   
 1183       /**
 1184        * Returns true if the knob (and the data value it represents)
 1185        * resolve to the closest slider value next to where the user
 1186        * positioned the knob.
 1187        *
 1188        * @return true if the value snaps to the nearest slider value, else false
 1189        * @see #setSnapToValue
 1190        */
 1191       boolean getSnapToValue() {
 1192           return snapToValue;
 1193       }
 1194   
 1195   
 1196       /**
 1197        * Specifying true makes the knob (and the data value it represents)
 1198        * resolve to the closest tick mark next to where the user
 1199        * positioned the knob.
 1200        * By default, this property is {@code false}.
 1201        *
 1202        * @param b  true to snap the knob to the nearest tick mark
 1203        * @see #getSnapToTicks
 1204        * @beaninfo
 1205        *       bound: true
 1206        * description: If true snap the knob to the nearest tick mark.
 1207        */
 1208       public void setSnapToTicks(boolean b) {
 1209           boolean oldValue = snapToTicks;
 1210           snapToTicks = b;
 1211           firePropertyChange("snapToTicks", oldValue, snapToTicks);
 1212       }
 1213   
 1214   
 1215       /**
 1216        * Specifying true makes the knob (and the data value it represents)
 1217        * resolve to the closest slider value next to where the user
 1218        * positioned the knob. If the {@code snapToTicks} property has also been
 1219        * set to {@code true}, the snap-to-ticks behavior will prevail.
 1220        * By default, the snapToValue property is {@code true}.
 1221        *
 1222        * @param b  true to snap the knob to the nearest slider value
 1223        * @see #getSnapToValue
 1224        * @see #setSnapToTicks
 1225        * @beaninfo
 1226        *       bound: true
 1227        * description: If true snap the knob to the nearest slider value.
 1228        */
 1229       void setSnapToValue(boolean b) {
 1230           boolean oldValue = snapToValue;
 1231           snapToValue = b;
 1232           firePropertyChange("snapToValue", oldValue, snapToValue);
 1233       }
 1234   
 1235   
 1236       /**
 1237        * Tells if tick marks are to be painted.
 1238        * @return true if tick marks are painted, else false
 1239        * @see #setPaintTicks
 1240        */
 1241       public boolean getPaintTicks() {
 1242           return paintTicks;
 1243       }
 1244   
 1245   
 1246       /**
 1247        * Determines whether tick marks are painted on the slider.
 1248        * By default, this property is {@code false}.
 1249        *
 1250        * @param  b  whether or not tick marks should be painted
 1251        * @see #getPaintTicks
 1252        * @beaninfo
 1253        *        bound: true
 1254        *    attribute: visualUpdate true
 1255        *  description: If true tick marks are painted on the slider.
 1256        */
 1257       public void setPaintTicks(boolean b) {
 1258           boolean oldValue = paintTicks;
 1259           paintTicks = b;
 1260           firePropertyChange("paintTicks", oldValue, paintTicks);
 1261           if (paintTicks != oldValue) {
 1262               revalidate();
 1263               repaint();
 1264           }
 1265       }
 1266   
 1267       /**
 1268        * Tells if the track (area the slider slides in) is to be painted.
 1269        * @return true if track is painted, else false
 1270        * @see #setPaintTrack
 1271        */
 1272       public boolean getPaintTrack() {
 1273           return paintTrack;
 1274       }
 1275   
 1276   
 1277       /**
 1278        * Determines whether the track is painted on the slider.
 1279        * By default, this property is {@code true}.
 1280        *
 1281        * @param  b  whether or not to paint the slider track
 1282        * @see #getPaintTrack
 1283        * @beaninfo
 1284        *        bound: true
 1285        *    attribute: visualUpdate true
 1286        *  description: If true, the track is painted on the slider.
 1287        */
 1288       public void setPaintTrack(boolean b) {
 1289           boolean oldValue = paintTrack;
 1290           paintTrack = b;
 1291           firePropertyChange("paintTrack", oldValue, paintTrack);
 1292           if (paintTrack != oldValue) {
 1293               repaint();
 1294           }
 1295       }
 1296   
 1297   
 1298       /**
 1299        * Tells if labels are to be painted.
 1300        * @return true if labels are painted, else false
 1301        * @see #setPaintLabels
 1302        */
 1303       public boolean getPaintLabels() {
 1304           return paintLabels;
 1305       }
 1306   
 1307   
 1308       /**
 1309        * Determines whether labels are painted on the slider.
 1310        * <p>
 1311        * This method will also set up a label table for you.
 1312        * If there is not already a label table, and the major tick spacing is
 1313        * {@code > 0},
 1314        * a standard label table will be generated (by calling
 1315        * {@code createStandardLabels}) with labels at the major tick marks.
 1316        * The label table is then set on the slider by calling
 1317        * {@code setLabelTable}.
 1318        * <p>
 1319        * By default, this property is {@code false}.
 1320        *
 1321        * @param  b  whether or not to paint labels
 1322        * @see #getPaintLabels
 1323        * @see #getLabelTable
 1324        * @see #createStandardLabels(int)
 1325        * @beaninfo
 1326        *        bound: true
 1327        *    attribute: visualUpdate true
 1328        *  description: If true labels are painted on the slider.
 1329        */
 1330       public void setPaintLabels(boolean b) {
 1331           boolean oldValue = paintLabels;
 1332           paintLabels = b;
 1333           if ( labelTable == null && getMajorTickSpacing() > 0 ) {
 1334               setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
 1335           }
 1336           firePropertyChange("paintLabels", oldValue, paintLabels);
 1337           if (paintLabels != oldValue) {
 1338               revalidate();
 1339               repaint();
 1340           }
 1341       }
 1342   
 1343   
 1344       /**
 1345        * See readObject() and writeObject() in JComponent for more
 1346        * information about serialization in Swing.
 1347        */
 1348       private void writeObject(ObjectOutputStream s) throws IOException {
 1349           s.defaultWriteObject();
 1350           if (getUIClassID().equals(uiClassID)) {
 1351               byte count = JComponent.getWriteObjCounter(this);
 1352               JComponent.setWriteObjCounter(this, --count);
 1353               if (count == 0 && ui != null) {
 1354                   ui.installUI(this);
 1355               }
 1356           }
 1357       }
 1358   
 1359   
 1360       /**
 1361        * Returns a string representation of this JSlider. This method
 1362        * is intended to be used only for debugging purposes, and the
 1363        * content and format of the returned string may vary between
 1364        * implementations. The returned string may be empty but may not
 1365        * be <code>null</code>.
 1366        *
 1367        * @return  a string representation of this JSlider.
 1368        */
 1369       protected String paramString() {
 1370           String paintTicksString = (paintTicks ?
 1371                                      "true" : "false");
 1372           String paintTrackString = (paintTrack ?
 1373                                      "true" : "false");
 1374           String paintLabelsString = (paintLabels ?
 1375                                       "true" : "false");
 1376           String isInvertedString = (isInverted ?
 1377                                      "true" : "false");
 1378           String snapToTicksString = (snapToTicks ?
 1379                                       "true" : "false");
 1380           String snapToValueString = (snapToValue ?
 1381                                       "true" : "false");
 1382           String orientationString = (orientation == HORIZONTAL ?
 1383                                       "HORIZONTAL" : "VERTICAL");
 1384   
 1385           return super.paramString() +
 1386           ",isInverted=" + isInvertedString +
 1387           ",majorTickSpacing=" + majorTickSpacing +
 1388           ",minorTickSpacing=" + minorTickSpacing +
 1389           ",orientation=" + orientationString +
 1390           ",paintLabels=" + paintLabelsString +
 1391           ",paintTicks=" + paintTicksString +
 1392           ",paintTrack=" + paintTrackString +
 1393           ",snapToTicks=" + snapToTicksString +
 1394           ",snapToValue=" + snapToValueString;
 1395       }
 1396   
 1397   
 1398   /////////////////
 1399   // Accessibility support
 1400   ////////////////
 1401   
 1402       /**
 1403        * Gets the AccessibleContext associated with this JSlider.
 1404        * For sliders, the AccessibleContext takes the form of an
 1405        * AccessibleJSlider.
 1406        * A new AccessibleJSlider instance is created if necessary.
 1407        *
 1408        * @return an AccessibleJSlider that serves as the
 1409        *         AccessibleContext of this JSlider
 1410        */
 1411       public AccessibleContext getAccessibleContext() {
 1412           if (accessibleContext == null) {
 1413               accessibleContext = new AccessibleJSlider();
 1414           }
 1415           return accessibleContext;
 1416       }
 1417   
 1418       /**
 1419        * This class implements accessibility support for the
 1420        * <code>JSlider</code> class.  It provides an implementation of the
 1421        * Java Accessibility API appropriate to slider user-interface elements.
 1422        * <p>
 1423        * <strong>Warning:</strong>
 1424        * Serialized objects of this class will not be compatible with
 1425        * future Swing releases. The current serialization support is
 1426        * appropriate for short term storage or RMI between applications running
 1427        * the same version of Swing.  As of 1.4, support for long term storage
 1428        * of all JavaBeans<sup><font size="-2">TM</font></sup>
 1429        * has been added to the <code>java.beans</code> package.
 1430        * Please see {@link java.beans.XMLEncoder}.
 1431        */
 1432       protected class AccessibleJSlider extends AccessibleJComponent
 1433       implements AccessibleValue {
 1434   
 1435           /**
 1436            * Get the state set of this object.
 1437            *
 1438            * @return an instance of AccessibleState containing the current state
 1439            * of the object
 1440            * @see AccessibleState
 1441            */
 1442           public AccessibleStateSet getAccessibleStateSet() {
 1443               AccessibleStateSet states = super.getAccessibleStateSet();
 1444               if (getValueIsAdjusting()) {
 1445                   states.add(AccessibleState.BUSY);
 1446               }
 1447               if (getOrientation() == VERTICAL) {
 1448                   states.add(AccessibleState.VERTICAL);
 1449               }
 1450               else {
 1451                   states.add(AccessibleState.HORIZONTAL);
 1452               }
 1453               return states;
 1454           }
 1455   
 1456           /**
 1457            * Get the role of this object.
 1458            *
 1459            * @return an instance of AccessibleRole describing the role of the object
 1460            */
 1461           public AccessibleRole getAccessibleRole() {
 1462               return AccessibleRole.SLIDER;
 1463           }
 1464   
 1465           /**
 1466            * Get the AccessibleValue associated with this object.  In the
 1467            * implementation of the Java Accessibility API for this class,
 1468            * return this object, which is responsible for implementing the
 1469            * AccessibleValue interface on behalf of itself.
 1470            *
 1471            * @return this object
 1472            */
 1473           public AccessibleValue getAccessibleValue() {
 1474               return this;
 1475           }
 1476   
 1477           /**
 1478            * Get the accessible value of this object.
 1479            *
 1480            * @return The current value of this object.
 1481            */
 1482           public Number getCurrentAccessibleValue() {
 1483               return Integer.valueOf(getValue());
 1484           }
 1485   
 1486           /**
 1487            * Set the value of this object as a Number.
 1488            *
 1489            * @return True if the value was set.
 1490            */
 1491           public boolean setCurrentAccessibleValue(Number n) {
 1492               // TIGER - 4422535
 1493               if (n == null) {
 1494                   return false;
 1495               }
 1496               setValue(n.intValue());
 1497               return true;
 1498           }
 1499   
 1500           /**
 1501            * Get the minimum accessible value of this object.
 1502            *
 1503            * @return The minimum value of this object.
 1504            */
 1505           public Number getMinimumAccessibleValue() {
 1506               return Integer.valueOf(getMinimum());
 1507           }
 1508   
 1509           /**
 1510            * Get the maximum accessible value of this object.
 1511            *
 1512            * @return The maximum value of this object.
 1513            */
 1514           public Number getMaximumAccessibleValue() {
 1515               // TIGER - 4422362
 1516               BoundedRangeModel model = JSlider.this.getModel();
 1517               return Integer.valueOf(model.getMaximum() - model.getExtent());
 1518           }
 1519       } // AccessibleJSlider
 1520   }

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