home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / swing / JSlider.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  27.2 KB  |  913 lines

  1. /*
  2.  * @(#)JSlider.java    1.58 98/02/04
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package java.awt.swing;
  22.  
  23. import java.awt.swing.border.*;
  24. import java.awt.swing.event.*;
  25. import java.awt.swing.plaf.*;
  26. import java.awt.accessibility.*;
  27.  
  28. import java.io.Serializable;
  29. import java.util.*;
  30.  
  31.  
  32. /**
  33.  * A component that lets the user graphically select a value by slding
  34.  * a knob within a bounded interval. The slider can show both 
  35.  * major tick marks and minor tick marks between them. The number of
  36.  * pixels between the tick marks is controlled with 
  37.  * <code>setMajorTickSpacing</code> and <code>setMinorTickSpacing</code>. 
  38.  * <p>
  39.  * Warning: serialized objects of this class will not be compatible with
  40.  * future swing releases.  The current serialization support is appropriate
  41.  * for short term storage or RMI between Swing1.0 applications.  It will
  42.  * not be possible to load serialized Swing1.0 objects with future releases
  43.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  44.  * baseline for the serialized form of Swing objects.
  45.  *
  46.  * @beaninfo
  47.  *      attribute: isContainer false
  48.  *    description: A component that supports selecting a integer value from a range.
  49.  * 
  50.  * @version 1.58 02/04/98
  51.  * @author David Kloba
  52.  */
  53. public class JSlider extends JComponent implements SwingConstants, Accessible
  54. {
  55.     /**
  56.      * The data model that handles the numeric maximum value,
  57.      * minimum value, and current-position value for the slider.
  58.      */
  59.     protected BoundedRangeModel sliderModel;
  60.  
  61.     /**
  62.      * The number of pixels between the major tick marks -- the 
  63.      * larger marks that break up the minor tick marks.
  64.      */
  65.     protected int majorTickSpacing;
  66.  
  67.     /**
  68.      * The number of pixels between the minor tick marks -- the 
  69.      * smaller marks that occur between the major tick marks.
  70.      * @see #setMinorTickSpacing
  71.      */
  72.     protected int minorTickSpacing;
  73.  
  74.     /**
  75.      * If true, the knob (and the data value it represents) 
  76.      * resolve to the closest tick mark next to where the user
  77.      * positioned the knob.
  78.      * @see #setSnapToTicks
  79.      */
  80.     protected boolean snapToTicks = true;
  81.  
  82.     private boolean paintTicks = false;
  83.     private boolean paintLabels = false;
  84.     private boolean isInverted = false;
  85.  
  86.  
  87.     /**
  88.      * @see #setOrientation
  89.      */
  90.     protected int orientation;
  91.  
  92.  
  93.     /**
  94.      * Whether the component fully paints all of the pixels in its
  95.      * region. By default this component is not transparent, so the 
  96.      * value is true. Use <code>setOpaque</code> to make the sliders
  97.      * background transparent, so that pixels under the slider 
  98.      * "show through" in the area the knob moves in.
  99.      */
  100.     private Dictionary labelTable;
  101.     
  102.  
  103.     /**
  104.      * The changeListener (no suffix) is the listener we add to the
  105.      * Sliders model.  By default this listener just forwards events
  106.      * to ChangeListeners (if any) added directly to the slider.
  107.      * 
  108.      * @see #addChangeListener
  109.      * @see #createChangeListener
  110.      */
  111.     protected ChangeListener changeListener = createChangeListener();
  112.  
  113.    
  114.     /**
  115.      * Only one ChangeEvent is needed per slider instance since the
  116.      * event's only (read-only) state is the source property.  The source
  117.      * of events generated here is always "this". The event is lazily
  118.      * created the first time that an event notification is fired.
  119.      * 
  120.      * @see #fireStateChanged
  121.      */
  122.     protected transient ChangeEvent changeEvent = null;
  123.  
  124.  
  125.     private void checkOrientation(int orientation) {
  126.     switch (orientation) {
  127.     case VERTICAL:
  128.     case HORIZONTAL:
  129.         break;
  130.     default:
  131.         throw new IllegalArgumentException("orientation must be one of: VERTICAL, HORIZONTAL");
  132.     }
  133.     }
  134.  
  135.  
  136.     /**
  137.      * Creates a slider with the specified orientation and the
  138.      * specified mimimum, maximum, and initial values.
  139.      * 
  140.      * @exception IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL
  141.      *
  142.      * @see #setOrientation
  143.      * @see #setMinimum
  144.      * @see #setMaximum
  145.      * @see #setValue
  146.      */
  147.     public JSlider(int orientation, int min, int max, int value) 
  148.     {
  149.     checkOrientation(orientation);
  150.         this.orientation = orientation;
  151.         sliderModel = new DefaultBoundedRangeModel(value, 0, min, max);
  152.     sliderModel.addChangeListener(changeListener);
  153.         updateUI();
  154.     }
  155.  
  156.  
  157.     /**
  158.      * Creates a horizontal slider with the range 0 to 100 and
  159.      * an intitial value of 50.
  160.      */
  161.     public JSlider() {
  162.         this(HORIZONTAL, 0, 100, 50);
  163.     }
  164.  
  165.  
  166.     /**
  167.      * Gets the UI object which implements the L&F for this component.
  168.      *
  169.      * @return the SliderUI object that implements the Slider L&F
  170.      */
  171.     public SliderUI getUI() {
  172.         return (SliderUI)ui;
  173.     }
  174.  
  175.  
  176.     /**
  177.      * Sets the UI object which implements the L&F for this component.
  178.      *
  179.      * @param ui the SliderUI L&F object
  180.      * @see UIDefaults#getUI
  181.      * @beaninfo
  182.      *       bound: true
  183.      *      hidden: true
  184.      * description: The UI object that implements the slider's LookAndFeel. 
  185.      */
  186.     public void setUI(SliderUI ui) {
  187.         super.setUI(ui);
  188.     }
  189.  
  190.  
  191.     /**
  192.      * Notification from the UIFactory that the L&F has changed. 
  193.      * Called to replace the UI with the latest version from the 
  194.      * default UIFactory.
  195.      *
  196.      * @see JComponent#updateUI
  197.      */
  198.     public void updateUI() {
  199.         updateLabelUIs();
  200.         setUI((SliderUI)UIManager.getUI(this));
  201.     }
  202.  
  203.  
  204.     /**
  205.      * Returns the name of the L&F class that renders this component.
  206.      *
  207.      * @return "SliderUI"
  208.      * @see JComponent#getUIClassID
  209.      * @see UIDefaults#getUI
  210.      */
  211.     public String getUIClassID() {
  212.         return "SliderUI";
  213.     }
  214.  
  215.  
  216.     /**
  217.      * We pass Change events along to the listeners with the 
  218.      * the slider (instead of the model itself) as the event source.
  219.      */
  220.     private class ModelListener implements ChangeListener, Serializable {
  221.         public void stateChanged(ChangeEvent e) {
  222.             fireStateChanged();
  223.         }
  224.     }
  225.  
  226.  
  227.     /**
  228.      * Subclasses that want to handle model ChangeEvents differently
  229.      * can override this method to return their own ChangeListener 
  230.      * implementation.  The default ChangeListener just forwards 
  231.      * ChangeEvents to the ChangeListeners added directly to the slider.
  232.      * 
  233.      * @see #fireStateChanged
  234.      */
  235.     protected ChangeListener createChangeListener() {
  236.         return new ModelListener();
  237.     }
  238.  
  239.  
  240.     /**
  241.      * Adds a ChangeListener to the slider.
  242.      *
  243.      * @param l the ChangeListener to add
  244.      * @see #fireStateChanged
  245.      * @see #removeChangeListener
  246.      */
  247.     public void addChangeListener(ChangeListener l) {
  248.         listenerList.add(ChangeListener.class, l);
  249.     }
  250.     
  251.  
  252.     /**
  253.      * Removes a ChangeListener from the slider.
  254.      *
  255.      * @param l the ChangeListener to remove
  256.      * @see #fireStateChanged
  257.      * @see #addChangeListener
  258.  
  259.      */
  260.     public void removeChangeListener(ChangeListener l) {
  261.         listenerList.remove(ChangeListener.class, l);
  262.     }
  263.         
  264.  
  265.     /**
  266.      * Send a ChangeEvent, whose source is this Slider, to
  267.      * each listener.  This method method is called each time 
  268.      * a ChangeEvent is received from the model.
  269.      * 
  270.      * @see #addChangeListener
  271.      * @see EventListenerList
  272.      */
  273.     protected void fireStateChanged() {
  274.         Object[] listeners = listenerList.getListenerList();
  275.         for (int i = listeners.length - 2; i >= 0; i -= 2) {
  276.             if (listeners[i]==ChangeListener.class) {
  277.                 if (changeEvent == null) {
  278.                     changeEvent = new ChangeEvent(this);
  279.         }
  280.                 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
  281.             }          
  282.         }
  283.     }   
  284.  
  285.  
  286.     /**
  287.      * Returns data model that handles the sliders three 
  288.      * fundamental properties: minimum, maximum, value.
  289.      * 
  290.      * @see #setModel
  291.      */
  292.     public BoundedRangeModel getModel() {
  293.         return sliderModel;
  294.     }
  295.  
  296.  
  297.     /**
  298.      * Sets the model that handles the sliders three 
  299.      * fundamental properties: minimum, maximum, value.
  300.      * 
  301.      * @see #getModel
  302.      * @beaninfo
  303.      *       bound: true
  304.      * description: The sliders BoundedRangeModel.
  305.      */
  306.     public void setModel(BoundedRangeModel newModel) 
  307.     {
  308.         BoundedRangeModel oldModel = getModel();
  309.  
  310.         if (oldModel != null) {
  311.             oldModel.removeChangeListener(changeListener);
  312.         }
  313.  
  314.         sliderModel = newModel;
  315.  
  316.         if (newModel != null) {
  317.             newModel.addChangeListener(changeListener);
  318.  
  319.             if (accessibleContext != null) {
  320.                 accessibleContext.firePropertyChange(
  321.             AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
  322.                         (oldModel == null 
  323.              ? null : new Integer(oldModel.getValue())),
  324.                         (newModel == null 
  325.              ? null : new Integer(newModel.getValue())));
  326.         }
  327.         }
  328.  
  329.         firePropertyChange("model", oldModel, sliderModel);
  330.     }
  331.  
  332.  
  333.     /**
  334.      * Returns the sliders value.
  335.      * @return the models value property
  336.      * @see #setValue
  337.      */
  338.     public int getValue() { 
  339.     return getModel().getValue(); 
  340.     }
  341.  
  342.  
  343.     /**
  344.      * Sets the sliders current value.  This method just forwards
  345.      * the value to the model.
  346.      * 
  347.      * @see #getValue
  348.      * @beaninfo
  349.      *   preferred: true
  350.      * description: The sliders current value.
  351.      */
  352.     public void setValue(int n) { 
  353.         BoundedRangeModel m = getModel();
  354.         int oldValue = m.getValue();
  355.         m.setValue(n);
  356.  
  357.     if (accessibleContext != null) {
  358.             accessibleContext.firePropertyChange(
  359.             AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
  360.                     new Integer(oldValue),
  361.                     new Integer(m.getValue()));
  362.     }
  363.     }
  364.  
  365.  
  366.     /**
  367.      * Returns the minimum value supported by the slider. 
  368.      *
  369.      * @return the value of the models minimum property
  370.      * @see #setMinimum
  371.      */
  372.     public int getMinimum() { 
  373.     return getModel().getMinimum(); 
  374.     }
  375.  
  376.  
  377.     /**
  378.      * Sets the models minimum property.
  379.      *
  380.      * @see #getMinimum
  381.      * @see BoundedRangeModel#setMinimum
  382.      * @beaninfo
  383.      *   preferred: true
  384.      * description: The sliders minimum value.
  385.      */
  386.     public void setMinimum(int minimum) { 
  387.     getModel().setMinimum(minimum); 
  388.     }
  389.  
  390.  
  391.     /**
  392.      * Returns the maximum value supported by the slider.
  393.      *
  394.      * @return the value of the models maximum property
  395.      * @see #setMaximum
  396.      */
  397.     public int getMaximum() { 
  398.     return getModel().getMaximum(); 
  399.     }
  400.  
  401.  
  402.     /**
  403.      * Sets the models maximum property.  
  404.      * 
  405.      * @see #getMaximum
  406.      * @see BoundedRangeModel#setMaximum
  407.      * @beaninfo
  408.      *   preferred: true
  409.      * description: The sliders maximum value.
  410.      */
  411.     public void setMaximum(int maximum) { 
  412.     getModel().setMaximum(maximum); 
  413.     }
  414.  
  415.  
  416.     /**
  417.      * True if the slider knob is being dragged.
  418.      * 
  419.      * @return the value of the models valueIsAdjusting property
  420.      * @see #setValueIsAdjusting
  421.      */
  422.     public boolean getValueIsAdjusting() { 
  423.     return getModel().getValueIsAdjusting(); 
  424.     }
  425.  
  426.  
  427.     /**
  428.      * Sets the models valueIsAdjusting property.  Slider look and
  429.      * feel implementations should set this property to true when 
  430.      * a knob drag begins, and to false when the drag ends.  The
  431.      * slider model will not generate ChangeEvents while
  432.      * valueIsAdjusting is true.
  433.      * 
  434.      * @see #getValueIsAdjusting
  435.      * @see BoundedRangeModel#setValueIsAdjusting
  436.      * @beaninfo
  437.      *      expert: true
  438.      * description: True if the slider knob is being dragged.
  439.      */
  440.     public void setValueIsAdjusting(boolean b) { 
  441.         BoundedRangeModel m = getModel();   
  442.         boolean oldValue = m.getValueIsAdjusting();
  443.         m.setValueIsAdjusting(b);
  444.    
  445.         if ((oldValue != b) && (accessibleContext != null)) {
  446.             accessibleContext.firePropertyChange(
  447.                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  448.                     ((oldValue) ? AccessibleState.BUSY : null),
  449.                     ((b) ? AccessibleState.BUSY : null));
  450.         }
  451.     }
  452.  
  453.  
  454.     /**
  455.      * @return the range of values "covered" by the knob.
  456.      * @see #setExtent
  457.      * @see BoundedRangeModel#getExtent
  458.      */
  459.     public int getExtent() { 
  460.     return getModel().getExtent(); 
  461.     }
  462.  
  463.  
  464.     /**
  465.      * Sets the size of the range "covered" by the knob.  Most look
  466.      * and feel implementations will change the value by this amount
  467.      * if the user clicks on either side of the knob.
  468.      * 
  469.      * @see #getExtent
  470.      * @see BoundedRangeModel#setExtent
  471.      * @beaninfo
  472.      *      expert: true
  473.      * description: Size of the range covered by the knob.
  474.      */
  475.     public void setExtent(int extent) { 
  476.     getModel().setExtent(extent); 
  477.     }
  478.  
  479.  
  480.     /**
  481.      * @return VERTICAL or HORIZONTAL
  482.      * @see #setOrientation
  483.      */
  484.     public int getOrientation() { 
  485.     return orientation; 
  486.     }
  487.  
  488.  
  489.     /**
  490.      * Set the scrollbars orientation to either VERTICAL or HORIZONTAL.
  491.      * 
  492.      * @exception IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL
  493.      * @see #getOrientation
  494.      * @beaninfo
  495.      *   preferred: true
  496.      *       bound: true
  497.      * description: Set the scrollbars orientation to either VERTICAL or HORIZONTAL.
  498.      *        enum: VERTICAL JSlider.VERTICAL 
  499.      *              HORIZONTAL JSlider.HORIZONTAL
  500.      * 
  501.      */
  502.     public void setOrientation(int orientation) 
  503.     { 
  504.     checkOrientation(orientation);
  505.         int oldValue = orientation;
  506.         this.orientation = orientation;
  507.         firePropertyChange("orientation", oldValue, orientation);
  508.  
  509.         if ((oldValue != orientation) && (accessibleContext != null)) {
  510.             accessibleContext.firePropertyChange(
  511.                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  512.                     ((oldValue == VERTICAL) 
  513.                      ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL),
  514.                     ((orientation == VERTICAL) 
  515.                      ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL));
  516.         }
  517.     }
  518.  
  519.  
  520.  
  521.     /**
  522.      * Returns the dictionary of what labels to draw at which values.
  523.      *
  524.      * @return the Dictionary containing labels and where to draw them
  525.      */
  526.     public Dictionary getLabelTable() {
  527. /*
  528.         if ( labelTable == null && getMajorTickSpacing() > 0 ) {
  529.             setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
  530.         }
  531. */
  532.         return labelTable;
  533.     }
  534.  
  535.  
  536.     /**
  537.      * Used to specify what label will be drawn at any given value.
  538.      * The key-value pairs are of this format: <B>{ Integer value, java.awt.Component label }</B>
  539.      *
  540.      * @see #createStandardLabels
  541.      * @see #getLabelTable
  542.      * @beaninfo
  543.      *      hidden: true
  544.      *       bound: true
  545.      * description: Specifies what labels will be drawn for any given value.
  546.      */
  547.     public void setLabelTable( Dictionary labels ) {
  548.         Dictionary oldTable = labelTable;
  549.         labelTable = labels;
  550.         updateLabelUIs();
  551.         firePropertyChange("labelTable", oldTable, labelTable );
  552.     }
  553.  
  554.  
  555.     /**
  556.      * Called internally to replace the label UIs with the latest versions
  557.      * from the UIFactory when the UIFactory notifies us via
  558.      * <code>updateUI</code> that the L&F has changed.
  559.      *
  560.      * @see JComponent#updateUI
  561.      */
  562.     protected void updateLabelUIs() {
  563.         if ( getLabelTable() == null ) {
  564.             return;
  565.         }
  566.         Enumeration labels = getLabelTable().keys();
  567.         while ( labels.hasMoreElements() ) {
  568.             Object value = getLabelTable().get( labels.nextElement() );
  569.             if ( value instanceof JComponent ) {
  570.                 JComponent component = (JComponent)value;
  571.                 component.updateUI();
  572.                 component.setSize( component.getPreferredSize()  );
  573.             }
  574.         }
  575.     }
  576.  
  577.  
  578.     /**
  579.      * Creates a hashtable that will draw text labels starting at the slider minimum using the
  580.      * increment specified. If you call createStandardLabels( 10 ) and the slider minimum is
  581.      * zero, then it will make labels for the values 0, 10, 20, 30, and so on.
  582.      * @see #setLabelTable
  583.      */
  584.     public Hashtable createStandardLabels( int increment ) {
  585.         return createStandardLabels( increment, getMinimum() );
  586.     }
  587.  
  588.  
  589.     /**
  590.      * Creates a hashtable that will draw text labels starting at the start point
  591.      * specified using the increment specified. If you call createStandardLabels( 10, 2 ),
  592.      * then it will make labels for the values 2, 12, 22, 32, and so on.
  593.      * @see #setLabelTable
  594.      */
  595.     public Hashtable createStandardLabels( int increment, int start ) {
  596.         if ( start > getMaximum() || start < getMinimum() ) {
  597.             throw new IllegalArgumentException( "Slider label start point out of range." );
  598.         }
  599.  
  600.         Hashtable table = new Hashtable();
  601.  
  602.         for ( int labelIndex = start; labelIndex <= getMaximum(); labelIndex += increment ) {
  603.             table.put( new Integer( labelIndex ), new JLabel( ""+labelIndex, JLabel.CENTER ) );
  604.         }
  605.  
  606.         return table;
  607.     }
  608.  
  609.  
  610.     /**
  611.      * Returns true if the value-range shown for the slider is reversed,
  612.      * with the maximum value at the left end of a horizontal slider or
  613.      * at the bottom of a vertical one.
  614.      *
  615.      * @return true if the slider values are reversed from their normal order
  616.      */
  617.     public boolean getInverted() { 
  618.     return isInverted; 
  619.     }
  620.     
  621.  
  622.     /**
  623.      * Specify true to reverse the value-range shown for the slider so that
  624.      * the maximum value is at the left end of a horizontal slider or
  625.      * at the bottom of a vertical one. Specify false to put the value range
  626.      * in the normal order.
  627.      *
  628.      * @param b  true to reverse the slider values from their normal order
  629.      * @beaninfo
  630.      *       bound: true
  631.      * description: If true reverses the slider values from their normal order 
  632.      * 
  633.      */
  634.     public void setInverted( boolean b ) { 
  635.     boolean oldValue = isInverted;
  636.     isInverted = b; 
  637.         firePropertyChange("inverted", oldValue, isInverted);
  638.     }
  639.  
  640.  
  641.     /**
  642.      * @return the number of pixels between major ticks
  643.      * @see #setMajorTickSpacing
  644.      */
  645.     public int getMajorTickSpacing() { 
  646.     return majorTickSpacing; 
  647.     }
  648.  
  649.  
  650.     /**
  651.      * Sets the number of pixels between major tick marks.
  652.      * @see #getMajorTickSpacing
  653.      * @beaninfo
  654.      *       bound: true
  655.      * description: Sets the number of pixels between major tick marks.
  656.      * 
  657.      */
  658.     public void setMajorTickSpacing(int n) {
  659.     int oldValue = majorTickSpacing;
  660.         majorTickSpacing = n;
  661.         if ( labelTable == null && getMajorTickSpacing() > 0 && getPaintLabels() ) {
  662.             setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
  663.         }
  664.         firePropertyChange("majorTickSpacing", oldValue, majorTickSpacing);
  665.     }
  666.  
  667.  
  668.     
  669.     /**
  670.      * @return the number of pixels between minor ticks
  671.      * @see #getMinorTickSpacing
  672.      */
  673.     public int getMinorTickSpacing() { 
  674.     return minorTickSpacing; 
  675.     }
  676.  
  677.  
  678.     /**
  679.      * Sets the number of pixels between minor tick marks.
  680.      * @see #getMinorTickSpacing
  681.      * @beaninfo
  682.      *       bound: true
  683.      * description: Sets the number of pixels between minor tick marks.
  684.      */
  685.     public void setMinorTickSpacing(int n) { 
  686.     int oldValue = minorTickSpacing;
  687.     minorTickSpacing = n; 
  688.         firePropertyChange("minorTickSpacing", oldValue, minorTickSpacing);
  689.     }
  690.  
  691.  
  692.     /**
  693.      * Returns true if the knob (and the data value it represents) 
  694.      * resolve to the closest tick mark next to where the user
  695.      * positioned the knob.
  696.      *
  697.      * @return true if the value snaps to the nearest tick mark, else false
  698.      * @see #setSnapToTicks
  699.      */
  700.     public boolean getSnapToTicks() { 
  701.     return snapToTicks; 
  702.     }
  703.  
  704.  
  705.     /**
  706.      * Specifying true makes the knob (and the data value it represents) 
  707.      * resolve to the closest tick mark next to where the user
  708.      * positioned the knob.
  709.      *
  710.      * @param b  true to snap the knob to the nearest tick mark
  711.      * @see #getSnapToTicks
  712.      * @beaninfo
  713.      *       bound: true
  714.      * description: If true snap the knob to the nearest tick mark.
  715.      */
  716.     public void setSnapToTicks(boolean b) { 
  717.     boolean oldValue = snapToTicks;
  718.     snapToTicks = b; 
  719.         firePropertyChange("snapToTicks", oldValue, snapToTicks);
  720.     }
  721.  
  722.  
  723.     /**
  724.      * @return true if tick marks are painted, else false
  725.      * @see #setPaintTicks
  726.      */
  727.     public boolean getPaintTicks() { 
  728.     return paintTicks; 
  729.     }
  730.  
  731.  
  732.     /**
  733.      * Determines whether tick marks are painted on the slider.
  734.      * @see #getPaintTicks
  735.      * @beaninfo
  736.      *       bound: true
  737.      * description: If true tick marks are painted on the slider.
  738.      */
  739.     public void setPaintTicks(boolean b) { 
  740.     boolean oldValue = paintTicks;
  741.     paintTicks = b;
  742.         firePropertyChange("paintTicks", oldValue, paintTicks);
  743.     }
  744.  
  745.  
  746.  
  747.     /**
  748.      * @return true if labels are painted, else false
  749.      * @see #setPaintLabels
  750.      */
  751.     public boolean getPaintLabels() { 
  752.     return paintLabels; 
  753.     }
  754.  
  755.     
  756.     /**
  757.      * Determines whether labels are painted on the slider.
  758.      * @see #getPaintLabels
  759.      * @beaninfo
  760.      *       bound: true
  761.      * description: If true labels are painted on the slider.
  762.      */
  763.     public void setPaintLabels(boolean b) {
  764.     boolean oldValue = paintLabels;
  765.         paintLabels = b;
  766.         if ( labelTable == null && getMajorTickSpacing() > 0 ) {
  767.             setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
  768.         }
  769.         firePropertyChange("paintLabels", oldValue, paintLabels);
  770.     }   
  771.  
  772.  
  773.  
  774.     /**
  775.      * Returns a string containing that displays and identifies this
  776.      * object's propeties.
  777.      */
  778.     public String toString()  {
  779.         String containerString = "";
  780.  
  781.         if (!isEnabled() && !isVisible()) containerString = "(not Enabled, not Visible)";
  782.         else if (!isEnabled()) containerString = "(not Enabled)";
  783.         else if (!isVisible()) containerString = "(not Visible)";
  784.  
  785.         String sliderString =
  786.             containerString +
  787.             ((getOrientation() == 
  788.               VERTICAL) ? "vertical" : "horizontal" ) + ", " +
  789.             "value=" + getValue() + ", " +
  790.             "adj=" + getValueIsAdjusting() + ", " +
  791.             "min=" + getMinimum() + ", " +
  792.             "max=" + getMaximum() + ", " +
  793.             "majorTickSpacing=" + getMajorTickSpacing() + ", " +
  794.             "minorTickSpacing=" + getMinorTickSpacing() + ", " +
  795.             "snapToTicks=" + getSnapToTicks() + ", " +
  796.             "isInverted=" + getInverted() + ", " +
  797.             "paintLabels=" + getPaintLabels() + ", " +
  798.             "paintTicks=" + getPaintTicks();
  799.  
  800.         return getClass().getName() + "[" + sliderString + "]";
  801.     }
  802.     
  803.  
  804.  
  805. /////////////////
  806. // Accessibility support
  807. ////////////////
  808.  
  809.     /**
  810.      * Get the AccessibleContext associated with this JComponent
  811.      *
  812.      * @return the AccessibleContext of this JComponent
  813.      */
  814.     public AccessibleContext getAccessibleContext() {
  815.         if (accessibleContext == null) {
  816.             accessibleContext = new AccessibleJSlider();
  817.         }
  818.         return accessibleContext;
  819.     }
  820.  
  821.     /**
  822.      * The class used to obtain the accessible role for this object.
  823.      * <p>
  824.      * Warning: serialized objects of this class will not be compatible with
  825.      * future swing releases.  The current serialization support is appropriate
  826.      * for short term storage or RMI between Swing1.0 applications.  It will
  827.      * not be possible to load serialized Swing1.0 objects with future releases
  828.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  829.      * baseline for the serialized form of Swing objects.
  830.      */
  831.     protected class AccessibleJSlider extends AccessibleJComponent
  832.         implements AccessibleValue {
  833.  
  834.         /**
  835.          * Get the state set of this object.
  836.          *
  837.          * @return an instance of AccessibleState containing the current state 
  838.          * of the object
  839.          * @see AccessibleState
  840.          */
  841.         public AccessibleStateSet getAccessibleStateSet() {
  842.             AccessibleStateSet states = super.getAccessibleStateSet();
  843.             if (getValueIsAdjusting()) {
  844.                 states.add(AccessibleState.BUSY);
  845.             }
  846.             if (getOrientation() == VERTICAL) {
  847.                 states.add(AccessibleState.VERTICAL);
  848.             } else {
  849.                 states.add(AccessibleState.HORIZONTAL);
  850.             }
  851.             return states;
  852.         }
  853.  
  854.         /**
  855.          * Get the role of this object.
  856.          *
  857.          * @return an instance of AccessibleRole describing the role of the object
  858.          */
  859.         public AccessibleRole getAccessibleRole() {
  860.             return AccessibleRole.SLIDER;
  861.         }
  862.  
  863.         /**
  864.          * Get the AccessibleValue associated with this object if one
  865.          * exists.  Otherwise return null.
  866.          */
  867.         public AccessibleValue getAccessibleValue() {
  868.             return this;
  869.         }
  870.  
  871.         /**
  872.          * Get the accessible value of this object.
  873.          *
  874.          * @return The current value of this object.
  875.          */
  876.         public Number getCurrentAccessibleValue() {
  877.             return new Integer(getValue());
  878.         }
  879.  
  880.         /**
  881.          * Set the value of this object as a Number.
  882.          *
  883.          * @return True if the value was set.
  884.          */
  885.         public boolean setCurrentAccessibleValue(Number n) {
  886.             if (n instanceof Integer) {
  887.                 setValue(n.intValue());
  888.                 return true;
  889.             } else {
  890.                 return false;
  891.             }
  892.         }
  893.  
  894.         /**
  895.          * Get the minimum accessible value of this object.
  896.          *
  897.          * @return The minimum value of this object.
  898.          */
  899.         public Number getMinimumAccessibleValue() {
  900.             return new Integer(getMinimum());
  901.         }
  902.  
  903.         /**
  904.          * Get the maximum accessible value of this object.
  905.          *
  906.          * @return The maximum value of this object.
  907.          */
  908.         public Number getMaximumAccessibleValue() {
  909.             return new Integer(getMaximum());
  910.         }
  911.     } // AccessibleJSlider
  912. }
  913.