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

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