0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package javax.swing;
0027
0028 import javax.swing.border.*;
0029 import javax.swing.event.*;
0030 import javax.swing.plaf.*;
0031 import javax.accessibility.*;
0032
0033 import java.io.Serializable;
0034 import java.io.ObjectOutputStream;
0035 import java.io.ObjectInputStream;
0036 import java.io.IOException;
0037
0038 import java.awt.Color;
0039 import java.awt.Font;
0040 import java.util.*;
0041 import java.beans.*;
0042
0043 /**
0044 * A component that lets the user graphically select a value by sliding
0045 * a knob within a bounded interval.
0046 * <p>
0047 * The slider can show both
0048 * major tick marks, and minor tick marks between the major ones. The number of
0049 * values between the tick marks is controlled with
0050 * <code>setMajorTickSpacing</code> and <code>setMinorTickSpacing</code>.
0051 * Painting of tick marks is controlled by {@code setPaintTicks}.
0052 * <p>
0053 * Sliders can also print text labels at regular intervals (or at
0054 * arbitrary locations) along the slider track. Painting of labels is
0055 * controlled by {@code setLabelTable} and {@code setPaintLabels}.
0056 * <p>
0057 * For further information and examples see
0058 * <a
0059 href="http://java.sun.com/docs/books/tutorial/uiswing/components/slider.html">How to Use Sliders</a>,
0060 * a section in <em>The Java Tutorial.</em>
0061 * <p>
0062 * <strong>Warning:</strong> Swing is not thread safe. For more
0063 * information see <a
0064 * href="package-summary.html#threading">Swing's Threading
0065 * Policy</a>.
0066 * <p>
0067 * <strong>Warning:</strong>
0068 * Serialized objects of this class will not be compatible with
0069 * future Swing releases. The current serialization support is
0070 * appropriate for short term storage or RMI between applications running
0071 * the same version of Swing. As of 1.4, support for long term storage
0072 * of all JavaBeans<sup><font size="-2">TM</font></sup>
0073 * has been added to the <code>java.beans</code> package.
0074 * Please see {@link java.beans.XMLEncoder}.
0075 *
0076 * @beaninfo
0077 * attribute: isContainer false
0078 * description: A component that supports selecting a integer value from a range.
0079 *
0080 * @version 1.116 05/05/07
0081 * @author David Kloba
0082 */
0083 public class JSlider extends JComponent implements SwingConstants,
0084 Accessible {
0085 /**
0086 * @see #getUIClassID
0087 * @see #readObject
0088 */
0089 private static final String uiClassID = "SliderUI";
0090
0091 private boolean paintTicks = false;
0092 private boolean paintTrack = true;
0093 private boolean paintLabels = false;
0094 private boolean isInverted = false;
0095
0096 /**
0097 * The data model that handles the numeric maximum value,
0098 * minimum value, and current-position value for the slider.
0099 */
0100 protected BoundedRangeModel sliderModel;
0101
0102 /**
0103 * The number of values between the major tick marks -- the
0104 * larger marks that break up the minor tick marks.
0105 */
0106 protected int majorTickSpacing;
0107
0108 /**
0109 * The number of values between the minor tick marks -- the
0110 * smaller marks that occur between the major tick marks.
0111 * @see #setMinorTickSpacing
0112 */
0113 protected int minorTickSpacing;
0114
0115 /**
0116 * If true, the knob (and the data value it represents)
0117 * resolve to the closest tick mark next to where the user
0118 * positioned the knob. The default is false.
0119 * @see #setSnapToTicks
0120 */
0121 protected boolean snapToTicks = false;
0122
0123 /**
0124 * If true, the knob (and the data value it represents)
0125 * resolve to the closest slider value next to where the user
0126 * positioned the knob.
0127 */
0128 boolean snapToValue = true;
0129
0130 /**
0131 * Whether the slider is horizontal or vertical
0132 * The default is horizontal.
0133 *
0134 * @see #setOrientation
0135 */
0136 protected int orientation;
0137
0138 /**
0139 * {@code Dictionary} of what labels to draw at which values
0140 */
0141 private Dictionary labelTable;
0142
0143 /**
0144 * The changeListener (no suffix) is the listener we add to the
0145 * slider's model. This listener is initialized to the
0146 * {@code ChangeListener} returned from {@code createChangeListener},
0147 * which by default just forwards events
0148 * to {@code ChangeListener}s (if any) added directly to the slider.
0149 *
0150 * @see #addChangeListener
0151 * @see #createChangeListener
0152 */
0153 protected ChangeListener changeListener = createChangeListener();
0154
0155 /**
0156 * Only one <code>ChangeEvent</code> is needed per slider instance since the
0157 * event's only (read-only) state is the source property. The source
0158 * of events generated here is always "this". The event is lazily
0159 * created the first time that an event notification is fired.
0160 *
0161 * @see #fireStateChanged
0162 */
0163 protected transient ChangeEvent changeEvent = null;
0164
0165 private void checkOrientation(int orientation) {
0166 switch (orientation) {
0167 case VERTICAL:
0168 case HORIZONTAL:
0169 break;
0170 default:
0171 throw new IllegalArgumentException(
0172 "orientation must be one of: VERTICAL, HORIZONTAL");
0173 }
0174 }
0175
0176 /**
0177 * Creates a horizontal slider with the range 0 to 100 and
0178 * an initial value of 50.
0179 */
0180 public JSlider() {
0181 this (HORIZONTAL, 0, 100, 50);
0182 }
0183
0184 /**
0185 * Creates a slider using the specified orientation with the
0186 * range {@code 0} to {@code 100} and an initial value of {@code 50}.
0187 * The orientation can be
0188 * either <code>SwingConstants.VERTICAL</code> or
0189 * <code>SwingConstants.HORIZONTAL</code>.
0190 *
0191 * @param orientation the orientation of the slider
0192 * @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
0193 * @see #setOrientation
0194 */
0195 public JSlider(int orientation) {
0196 this (orientation, 0, 100, 50);
0197 }
0198
0199 /**
0200 * Creates a horizontal slider using the specified min and max
0201 * with an initial value equal to the average of the min plus max.
0202 * <p>
0203 * The <code>BoundedRangeModel</code> that holds the slider's data
0204 * handles any issues that may arise from improperly setting the
0205 * minimum and maximum values on the slider. See the
0206 * {@code BoundedRangeModel} documentation for details.
0207 *
0208 * @param min the minimum value of the slider
0209 * @param max the maximum value of the slider
0210 *
0211 * @see BoundedRangeModel
0212 * @see #setMinimum
0213 * @see #setMaximum
0214 */
0215 public JSlider(int min, int max) {
0216 this (HORIZONTAL, min, max, (min + max) / 2);
0217 }
0218
0219 /**
0220 * Creates a horizontal slider using the specified min, max and value.
0221 * <p>
0222 * The <code>BoundedRangeModel</code> that holds the slider's data
0223 * handles any issues that may arise from improperly setting the
0224 * minimum, initial, and maximum values on the slider. See the
0225 * {@code BoundedRangeModel} documentation for details.
0226 *
0227 * @param min the minimum value of the slider
0228 * @param max the maximum value of the slider
0229 * @param value the initial value of the slider
0230 *
0231 * @see BoundedRangeModel
0232 * @see #setMinimum
0233 * @see #setMaximum
0234 * @see #setValue
0235 */
0236 public JSlider(int min, int max, int value) {
0237 this (HORIZONTAL, min, max, value);
0238 }
0239
0240 /**
0241 * Creates a slider with the specified orientation and the
0242 * specified minimum, maximum, and initial values.
0243 * The orientation can be
0244 * either <code>SwingConstants.VERTICAL</code> or
0245 * <code>SwingConstants.HORIZONTAL</code>.
0246 * <p>
0247 * The <code>BoundedRangeModel</code> that holds the slider's data
0248 * handles any issues that may arise from improperly setting the
0249 * minimum, initial, and maximum values on the slider. See the
0250 * {@code BoundedRangeModel} documentation for details.
0251 *
0252 * @param orientation the orientation of the slider
0253 * @param min the minimum value of the slider
0254 * @param max the maximum value of the slider
0255 * @param value the initial value of the slider
0256 *
0257 * @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
0258 *
0259 * @see BoundedRangeModel
0260 * @see #setOrientation
0261 * @see #setMinimum
0262 * @see #setMaximum
0263 * @see #setValue
0264 */
0265 public JSlider(int orientation, int min, int max, int value) {
0266 checkOrientation(orientation);
0267 this .orientation = orientation;
0268 sliderModel = new DefaultBoundedRangeModel(value, 0, min, max);
0269 sliderModel.addChangeListener(changeListener);
0270 updateUI();
0271 }
0272
0273 /**
0274 * Creates a horizontal slider using the specified
0275 * BoundedRangeModel.
0276 */
0277 public JSlider(BoundedRangeModel brm) {
0278 this .orientation = JSlider.HORIZONTAL;
0279 setModel(brm);
0280 sliderModel.addChangeListener(changeListener);
0281 updateUI();
0282 }
0283
0284 /**
0285 * Gets the UI object which implements the L&F for this component.
0286 *
0287 * @return the SliderUI object that implements the Slider L&F
0288 */
0289 public SliderUI getUI() {
0290 return (SliderUI) ui;
0291 }
0292
0293 /**
0294 * Sets the UI object which implements the L&F for this component.
0295 *
0296 * @param ui the SliderUI L&F object
0297 * @see UIDefaults#getUI
0298 * @beaninfo
0299 * bound: true
0300 * hidden: true
0301 * attribute: visualUpdate true
0302 * description: The UI object that implements the slider's LookAndFeel.
0303 */
0304 public void setUI(SliderUI ui) {
0305 super .setUI(ui);
0306 }
0307
0308 /**
0309 * Resets the UI property to a value from the current look and feel.
0310 *
0311 * @see JComponent#updateUI
0312 */
0313 public void updateUI() {
0314 setUI((SliderUI) UIManager.getUI(this ));
0315 // The labels preferred size may be derived from the font
0316 // of the slider, so we must update the UI of the slider first, then
0317 // that of labels. This way when setSize is called the right
0318 // font is used.
0319 updateLabelUIs();
0320 }
0321
0322 /**
0323 * Returns the name of the L&F class that renders this component.
0324 *
0325 * @return "SliderUI"
0326 * @see JComponent#getUIClassID
0327 * @see UIDefaults#getUI
0328 */
0329 public String getUIClassID() {
0330 return uiClassID;
0331 }
0332
0333 /**
0334 * We pass Change events along to the listeners with the
0335 * the slider (instead of the model itself) as the event source.
0336 */
0337 private class ModelListener implements ChangeListener, Serializable {
0338 public void stateChanged(ChangeEvent e) {
0339 fireStateChanged();
0340 }
0341 }
0342
0343 /**
0344 * Subclasses that want to handle {@code ChangeEvent}s
0345 * from the model differently
0346 * can override this to return
0347 * an instance of a custom <code>ChangeListener</code> implementation.
0348 * The default {@code ChangeListener} simply calls the
0349 * {@code fireStateChanged} method to forward {@code ChangeEvent}s
0350 * to the {@code ChangeListener}s that have been added directly to the
0351 * slider.
0352 * @see #changeListener
0353 * @see #fireStateChanged
0354 * @see javax.swing.event.ChangeListener
0355 * @see javax.swing.BoundedRangeModel
0356 */
0357 protected ChangeListener createChangeListener() {
0358 return new ModelListener();
0359 }
0360
0361 /**
0362 * Adds a ChangeListener to the slider.
0363 *
0364 * @param l the ChangeListener to add
0365 * @see #fireStateChanged
0366 * @see #removeChangeListener
0367 */
0368 public void addChangeListener(ChangeListener l) {
0369 listenerList.add(ChangeListener.class, l);
0370 }
0371
0372 /**
0373 * Removes a ChangeListener from the slider.
0374 *
0375 * @param l the ChangeListener to remove
0376 * @see #fireStateChanged
0377 * @see #addChangeListener
0378
0379 */
0380 public void removeChangeListener(ChangeListener l) {
0381 listenerList.remove(ChangeListener.class, l);
0382 }
0383
0384 /**
0385 * Returns an array of all the <code>ChangeListener</code>s added
0386 * to this JSlider with addChangeListener().
0387 *
0388 * @return all of the <code>ChangeListener</code>s added or an empty
0389 * array if no listeners have been added
0390 * @since 1.4
0391 */
0392 public ChangeListener[] getChangeListeners() {
0393 return (ChangeListener[]) listenerList
0394 .getListeners(ChangeListener.class);
0395 }
0396
0397 /**
0398 * Send a {@code ChangeEvent}, whose source is this {@code JSlider}, to
0399 * all {@code ChangeListener}s that have registered interest in
0400 * {@code ChangeEvent}s.
0401 * This method is called each time a {@code ChangeEvent} is received from
0402 * the model.
0403 * <p>
0404 * The event instance is created if necessary, and stored in
0405 * {@code changeEvent}.
0406 *
0407 * @see #addChangeListener
0408 * @see EventListenerList
0409 */
0410 protected void fireStateChanged() {
0411 Object[] listeners = listenerList.getListenerList();
0412 for (int i = listeners.length - 2; i >= 0; i -= 2) {
0413 if (listeners[i] == ChangeListener.class) {
0414 if (changeEvent == null) {
0415 changeEvent = new ChangeEvent(this );
0416 }
0417 ((ChangeListener) listeners[i + 1])
0418 .stateChanged(changeEvent);
0419 }
0420 }
0421 }
0422
0423 /**
0424 * Returns the {@code BoundedRangeModel} that handles the slider's three
0425 * fundamental properties: minimum, maximum, value.
0426 *
0427 * @return the data model for this component
0428 * @see #setModel
0429 * @see BoundedRangeModel
0430 */
0431 public BoundedRangeModel getModel() {
0432 return sliderModel;
0433 }
0434
0435 /**
0436 * Sets the {@code BoundedRangeModel} that handles the slider's three
0437 * fundamental properties: minimum, maximum, value.
0438 *<p>
0439 * Attempts to pass a {@code null} model to this method result in
0440 * undefined behavior, and, most likely, exceptions.
0441 *
0442 * @param newModel the new, {@code non-null} <code>BoundedRangeModel</code> to use
0443 *
0444 * @see #getModel
0445 * @see BoundedRangeModel
0446 * @beaninfo
0447 * bound: true
0448 * description: The sliders BoundedRangeModel.
0449 */
0450 public void setModel(BoundedRangeModel newModel) {
0451 BoundedRangeModel oldModel = getModel();
0452
0453 if (oldModel != null) {
0454 oldModel.removeChangeListener(changeListener);
0455 }
0456
0457 sliderModel = newModel;
0458
0459 if (newModel != null) {
0460 newModel.addChangeListener(changeListener);
0461
0462 if (accessibleContext != null) {
0463 accessibleContext.firePropertyChange(
0464 AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
0465 (oldModel == null ? null : new Integer(oldModel
0466 .getValue())), (newModel == null ? null
0467 : new Integer(newModel.getValue())));
0468 }
0469 }
0470
0471 firePropertyChange("model", oldModel, sliderModel);
0472 }
0473
0474 /**
0475 * Returns the slider's current value
0476 * from the {@code BoundedRangeModel}.
0477 *
0478 * @return the current value of the slider
0479 * @see #setValue
0480 * @see BoundedRangeModel#getValue
0481 */
0482 public int getValue() {
0483 return getModel().getValue();
0484 }
0485
0486 /**
0487 * Sets the slider's current value to {@code n}. This method
0488 * forwards the new value to the model.
0489 * <p>
0490 * The data model (an instance of {@code BoundedRangeModel})
0491 * handles any mathematical
0492 * issues arising from assigning faulty values. See the
0493 * {@code BoundedRangeModel} documentation for details.
0494 * <p>
0495 * If the new value is different from the previous value,
0496 * all change listeners are notified.
0497 *
0498 * @param n the new value
0499 * @see #getValue
0500 * @see #addChangeListener
0501 * @see BoundedRangeModel#setValue
0502 * @beaninfo
0503 * preferred: true
0504 * description: The sliders current value.
0505 */
0506 public void setValue(int n) {
0507 BoundedRangeModel m = getModel();
0508 int oldValue = m.getValue();
0509 if (oldValue == n) {
0510 return;
0511 }
0512 m.setValue(n);
0513
0514 if (accessibleContext != null) {
0515 accessibleContext.firePropertyChange(
0516 AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
0517 new Integer(oldValue), new Integer(m.getValue()));
0518 }
0519 }
0520
0521 /**
0522 * Returns the minimum value supported by the slider
0523 * from the <code>BoundedRangeModel</code>.
0524 *
0525 * @return the value of the model's minimum property
0526 * @see #setMinimum
0527 * @see BoundedRangeModel#getMinimum
0528 */
0529 public int getMinimum() {
0530 return getModel().getMinimum();
0531 }
0532
0533 /**
0534 * Sets the slider's minimum value to {@code minimum}. This method
0535 * forwards the new minimum value to the model.
0536 * <p>
0537 * The data model (an instance of {@code BoundedRangeModel})
0538 * handles any mathematical
0539 * issues arising from assigning faulty values. See the
0540 * {@code BoundedRangeModel} documentation for details.
0541 * <p>
0542 * If the new minimum value is different from the previous minimum value,
0543 * all change listeners are notified.
0544 *
0545 * @param n the new minimum
0546 * @see #getMinimum
0547 * @see #addChangeListener
0548 * @see BoundedRangeModel#setMinimum
0549 * @beaninfo
0550 * bound: true
0551 * preferred: true
0552 * description: The sliders minimum value.
0553 */
0554 public void setMinimum(int minimum) {
0555 int oldMin = getModel().getMinimum();
0556 getModel().setMinimum(minimum);
0557 firePropertyChange("minimum", new Integer(oldMin), new Integer(
0558 minimum));
0559 }
0560
0561 /**
0562 * Returns the maximum value supported by the slider
0563 * from the <code>BoundedRangeModel</code>.
0564 *
0565 * @return the value of the model's maximum property
0566 * @see #setMaximum
0567 * @see BoundedRangeModel#getMaximum
0568 */
0569 public int getMaximum() {
0570 return getModel().getMaximum();
0571 }
0572
0573 /**
0574 * Sets the slider's maximum value to {@code maximum}. This method
0575 * forwards the new maximum value to the model.
0576 * <p>
0577 * The data model (an instance of {@code BoundedRangeModel})
0578 * handles any mathematical
0579 * issues arising from assigning faulty values. See the
0580 * {@code BoundedRangeModel} documentation for details.
0581 * <p>
0582 * If the new maximum value is different from the previous maximum value,
0583 * all change listeners are notified.
0584 *
0585 * @param n the new maximum
0586 * @see #getMaximum
0587 * @see #addChangeListener
0588 * @see BoundedRangeModel#setMaximum
0589 * @beaninfo
0590 * bound: true
0591 * preferred: true
0592 * description: The sliders maximum value.
0593 */
0594 public void setMaximum(int maximum) {
0595 int oldMax = getModel().getMaximum();
0596 getModel().setMaximum(maximum);
0597 firePropertyChange("maximum", new Integer(oldMax), new Integer(
0598 maximum));
0599 }
0600
0601 /**
0602 * Returns the {@code valueIsAdjusting} property from the model. For
0603 * details on how this is used, see the {@code setValueIsAdjusting}
0604 * documentation.
0605 *
0606 * @return the value of the model's {@code valueIsAdjusting} property
0607 * @see #setValueIsAdjusting
0608 */
0609 public boolean getValueIsAdjusting() {
0610 return getModel().getValueIsAdjusting();
0611 }
0612
0613 /**
0614 * Sets the model's {@code valueIsAdjusting} property. Slider look and
0615 * feel implementations should set this property to {@code true} when
0616 * a knob drag begins, and to {@code false} when the drag ends. The
0617 * slider model will not generate {@code ChangeEvent}s while
0618 * {@code valueIsAdjusting} is {@code true}.
0619 *
0620 * @param b the new value for the {@code valueIsAdjusting} property
0621 * @see #getValueIsAdjusting
0622 * @see BoundedRangeModel#setValueIsAdjusting
0623 * @beaninfo
0624 * expert: true
0625 * description: True if the slider knob is being dragged.
0626 */
0627 public void setValueIsAdjusting(boolean b) {
0628 BoundedRangeModel m = getModel();
0629 boolean oldValue = m.getValueIsAdjusting();
0630 m.setValueIsAdjusting(b);
0631
0632 if ((oldValue != b) && (accessibleContext != null)) {
0633 accessibleContext.firePropertyChange(
0634 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
0635 ((oldValue) ? AccessibleState.BUSY : null),
0636 ((b) ? AccessibleState.BUSY : null));
0637 }
0638 }
0639
0640 /**
0641 * Returns the "extent" from the <code>BoundedRangeModel</code>.
0642 * This respresents the range of values "covered" by the knob.
0643 *
0644 * @return an int representing the extent
0645 * @see #setExtent
0646 * @see BoundedRangeModel#getExtent
0647 */
0648 public int getExtent() {
0649 return getModel().getExtent();
0650 }
0651
0652 /**
0653 * Sets the size of the range "covered" by the knob. Most look
0654 * and feel implementations will change the value by this amount
0655 * if the user clicks on either side of the knob. This method just
0656 * forwards the new extent value to the model.
0657 * <p>
0658 * The data model (an instance of {@code BoundedRangeModel})
0659 * handles any mathematical
0660 * issues arising from assigning faulty values. See the
0661 * {@code BoundedRangeModel} documentation for details.
0662 * <p>
0663 * If the new extent value is different from the previous extent value,
0664 * all change listeners are notified.
0665 *
0666 * @param extent the new extent
0667 * @see #getExtent
0668 * @see BoundedRangeModel#setExtent
0669 * @beaninfo
0670 * expert: true
0671 * description: Size of the range covered by the knob.
0672 */
0673 public void setExtent(int extent) {
0674 getModel().setExtent(extent);
0675 }
0676
0677 /**
0678 * Return this slider's vertical or horizontal orientation.
0679 * @return {@code SwingConstants.VERTICAL} or
0680 * {@code SwingConstants.HORIZONTAL}
0681 * @see #setOrientation
0682 */
0683 public int getOrientation() {
0684 return orientation;
0685 }
0686
0687 /**
0688 * Set the slider's orientation to either {@code SwingConstants.VERTICAL} or
0689 * {@code SwingConstants.HORIZONTAL}.
0690 *
0691 * @param orientation {@code HORIZONTAL} or {@code VERTICAL}
0692 * @throws IllegalArgumentException if orientation is not one of {@code VERTICAL}, {@code HORIZONTAL}
0693 * @see #getOrientation
0694 * @beaninfo
0695 * preferred: true
0696 * bound: true
0697 * attribute: visualUpdate true
0698 * description: Set the scrollbars orientation to either VERTICAL or HORIZONTAL.
0699 * enum: VERTICAL JSlider.VERTICAL
0700 * HORIZONTAL JSlider.HORIZONTAL
0701 *
0702 */
0703 public void setOrientation(int orientation) {
0704 checkOrientation(orientation);
0705 int oldValue = this .orientation;
0706 this .orientation = orientation;
0707 firePropertyChange("orientation", oldValue, orientation);
0708
0709 if ((oldValue != orientation) && (accessibleContext != null)) {
0710 accessibleContext
0711 .firePropertyChange(
0712 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
0713 ((oldValue == VERTICAL) ? AccessibleState.VERTICAL
0714 : AccessibleState.HORIZONTAL),
0715 ((orientation == VERTICAL) ? AccessibleState.VERTICAL
0716 : AccessibleState.HORIZONTAL));
0717 }
0718 if (orientation != oldValue) {
0719 revalidate();
0720 }
0721 }
0722
0723 /**
0724 * {@inheritDoc}
0725 *
0726 * @since 1.6
0727 */
0728 public void setFont(Font font) {
0729 super .setFont(font);
0730 updateLabelSizes();
0731 }
0732
0733 /**
0734 * Returns the dictionary of what labels to draw at which values.
0735 *
0736 * @return the <code>Dictionary</code> containing labels and
0737 * where to draw them
0738 */
0739 public Dictionary getLabelTable() {
0740 /*
0741 if ( labelTable == null && getMajorTickSpacing() > 0 ) {
0742 setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
0743 }
0744 */
0745 return labelTable;
0746 }
0747
0748 /**
0749 * Used to specify what label will be drawn at any given value.
0750 * The key-value pairs are of this format:
0751 * <code>{ Integer value, java.swing.JComponent label }</code>.
0752 * <p>
0753 * An easy way to generate a standard table of value labels is by using the
0754 * {@code createStandardLabels} method.
0755 * <p>
0756 * Once the labels have been set, this method calls {@link #updateLabelUIs}.
0757 * Note that the labels are only painted if the {@code paintLabels}
0758 * property is {@code true}.
0759 *
0760 * @param labels new {@code Dictionary} of labels, or {@code null} to
0761 * remove all labels
0762 * @see #createStandardLabels(int)
0763 * @see #getLabelTable
0764 * @see #setPaintLabels
0765 * @beaninfo
0766 * hidden: true
0767 * bound: true
0768 * attribute: visualUpdate true
0769 * description: Specifies what labels will be drawn for any given value.
0770 */
0771 public void setLabelTable(Dictionary labels) {
0772 Dictionary oldTable = labelTable;
0773 labelTable = labels;
0774 updateLabelUIs();
0775 firePropertyChange("labelTable", oldTable, labelTable);
0776 if (labels != oldTable) {
0777 revalidate();
0778 repaint();
0779 }
0780 }
0781
0782 /**
0783 * Updates the UIs for the labels in the label table by calling
0784 * {@code updateUI} on each label. The UIs are updated from
0785 * the current look and feel. The labels are also set to their
0786 * preferred size.
0787 *
0788 * @see #setLabelTable
0789 * @see JComponent#updateUI
0790 */
0791 protected void updateLabelUIs() {
0792 if (getLabelTable() == null) {
0793 return;
0794 }
0795 Enumeration labels = getLabelTable().keys();
0796 while (labels.hasMoreElements()) {
0797 Object value = getLabelTable().get(labels.nextElement());
0798 if (value instanceof JComponent) {
0799 JComponent component = (JComponent) value;
0800 component.updateUI();
0801 component.setSize(component.getPreferredSize());
0802 }
0803 }
0804 }
0805
0806 private void updateLabelSizes() {
0807 Dictionary labelTable = getLabelTable();
0808 if (labelTable != null) {
0809 Enumeration labels = labelTable.elements();
0810 while (labels.hasMoreElements()) {
0811 Object value = labels.nextElement();
0812 if (value instanceof JComponent) {
0813 JComponent component = (JComponent) value;
0814 component.setSize(component.getPreferredSize());
0815 }
0816 }
0817 }
0818 }
0819
0820 /**
0821 * Creates a {@code Hashtable} of numerical text labels, starting at the
0822 * slider minimum, and using the increment specified.
0823 * For example, if you call <code>createStandardLabels( 10 )</code>
0824 * and the slider minimum is zero,
0825 * then labels will be created for the values 0, 10, 20, 30, and so on.
0826 * <p>
0827 * For the labels to be drawn on the slider, the returned {@code Hashtable}
0828 * must be passed into {@code setLabelTable}, and {@code setPaintLabels}
0829 * must be set to {@code true}.
0830 * <p>
0831 * For further details on the makeup of the returned {@code Hashtable}, see
0832 * the {@code setLabelTable} documentation.
0833 *
0834 * @param increment distance between labels in the generated hashtable
0835 * @return a new {@code Hashtable} of labels
0836 * @see #setLabelTable
0837 * @see #setPaintLabels
0838 * @throws IllegalArgumentException if {@code increment} is less than or
0839 * equal to zero
0840 */
0841 public Hashtable createStandardLabels(int increment) {
0842 return createStandardLabels(increment, getMinimum());
0843 }
0844
0845 /**
0846 * Creates a {@code Hashtable} of numerical text labels, starting at the
0847 * starting point specified, and using the increment specified.
0848 * For example, if you call
0849 * <code>createStandardLabels( 10, 2 )</code>,
0850 * then labels will be created for the values 2, 12, 22, 32, and so on.
0851 * <p>
0852 * For the labels to be drawn on the slider, the returned {@code Hashtable}
0853 * must be passed into {@code setLabelTable}, and {@code setPaintLabels}
0854 * must be set to {@code true}.
0855 * <p>
0856 * For further details on the makeup of the returned {@code Hashtable}, see
0857 * the {@code setLabelTable} documentation.
0858 *
0859 * @param increment distance between labels in the generated hashtable
0860 * @param start value at which the labels will begin
0861 * @return a new {@code Hashtable} of labels
0862 * @see #setLabelTable
0863 * @see #setPaintLabels
0864 * @exception IllegalArgumentException if {@code start} is
0865 * out of range, or if {@code increment} is less than or equal
0866 * to zero
0867 */
0868 public Hashtable createStandardLabels(int increment, int start) {
0869 if (start > getMaximum() || start < getMinimum()) {
0870 throw new IllegalArgumentException(
0871 "Slider label start point out of range.");
0872 }
0873
0874 if (increment <= 0) {
0875 throw new IllegalArgumentException(
0876 "Label incremement must be > 0");
0877 }
0878
0879 class SmartHashtable extends Hashtable implements
0880 PropertyChangeListener {
0881 int increment = 0;
0882 int start = 0;
0883 boolean startAtMin = false;
0884
0885 class LabelUIResource extends JLabel implements UIResource {
0886 public LabelUIResource(String text, int alignment) {
0887 super (text, alignment);
0888 setName("Slider.label");
0889 }
0890
0891 public Font getFont() {
0892 Font font = super .getFont();
0893 if (font != null && !(font instanceof UIResource)) {
0894 return font;
0895 }
0896 return JSlider.this .getFont();
0897 }
0898
0899 public Color getForeground() {
0900 Color fg = super .getForeground();
0901 if (fg != null && !(fg instanceof UIResource)) {
0902 return fg;
0903 }
0904 if (!(JSlider.this .getForeground() instanceof UIResource)) {
0905 return JSlider.this .getForeground();
0906 }
0907 return fg;
0908 }
0909 }
0910
0911 public SmartHashtable(int increment, int start) {
0912 super ();
0913 this .increment = increment;
0914 this .start = start;
0915 startAtMin = start == getMinimum();
0916 createLabels();
0917 }
0918
0919 public void propertyChange(PropertyChangeEvent e) {
0920 if (e.getPropertyName().equals("minimum") && startAtMin) {
0921 start = getMinimum();
0922 }
0923
0924 if (e.getPropertyName().equals("minimum")
0925 || e.getPropertyName().equals("maximum")) {
0926
0927 Enumeration keys = getLabelTable().keys();
0928 Object key = null;
0929 Hashtable hashtable = new Hashtable();
0930
0931 // Save the labels that were added by the developer
0932 while (keys.hasMoreElements()) {
0933 key = keys.nextElement();
0934 Object value = getLabelTable().get(key);
0935 if (!(value instanceof LabelUIResource)) {
0936 hashtable.put(key, value);
0937 }
0938 }
0939
0940 clear();
0941 createLabels();
0942
0943 // Add the saved labels
0944 keys = hashtable.keys();
0945 while (keys.hasMoreElements()) {
0946 key = keys.nextElement();
0947 put(key, hashtable.get(key));
0948 }
0949
0950 ((JSlider) e.getSource()).setLabelTable(this );
0951 }
0952 }
0953
0954 void createLabels() {
0955 for (int labelIndex = start; labelIndex <= getMaximum(); labelIndex += increment) {
0956 put(new Integer(labelIndex), new LabelUIResource(""
0957 + labelIndex, JLabel.CENTER));
0958 }
0959 }
0960 }
0961
0962 SmartHashtable table = new SmartHashtable(increment, start);
0963
0964 if (getLabelTable() != null
0965 && (getLabelTable() instanceof PropertyChangeListener)) {
0966 removePropertyChangeListener((PropertyChangeListener) getLabelTable());
0967 }
0968
0969 addPropertyChangeListener(table);
0970
0971 return table;
0972 }
0973
0974 /**
0975 * Returns true if the value-range shown for the slider is reversed,
0976 *
0977 * @return true if the slider values are reversed from their normal order
0978 * @see #setInverted
0979 */
0980 public boolean getInverted() {
0981 return isInverted;
0982 }
0983
0984 /**
0985 * Specify true to reverse the value-range shown for the slider and false to
0986 * put the value range in the normal order. The order depends on the
0987 * slider's <code>ComponentOrientation</code> property. Normal (non-inverted)
0988 * horizontal sliders with a <code>ComponentOrientation</code> value of
0989 * <code>LEFT_TO_RIGHT</code> have their maximum on the right.
0990 * Normal horizontal sliders with a <code>ComponentOrientation</code> value of
0991 * <code>RIGHT_TO_LEFT</code> have their maximum on the left. Normal vertical
0992 * sliders have their maximum on the top. These labels are reversed when the
0993 * slider is inverted.
0994 * <p>
0995 * By default, the value of this property is {@code false}.
0996 *
0997 * @param b true to reverse the slider values from their normal order
0998 * @beaninfo
0999 * bound: true
1000 * attribute: visualUpdate true
1001 * description: If true reverses the slider values from their normal order
1002 *
1003 */
1004 public void setInverted(boolean b) {
1005 boolean oldValue = isInverted;
1006 isInverted = b;
1007 firePropertyChange("inverted", oldValue, isInverted);
1008 if (b != oldValue) {
1009 repaint();
1010 }
1011 }
1012
1013 /**
1014 * This method returns the major tick spacing. The number that is returned
1015 * represents the distance, measured in values, between each major tick mark.
1016 * If you have a slider with a range from 0 to 50 and the major tick spacing
1017 * is set to 10, you will get major ticks next to the following values:
1018 * 0, 10, 20, 30, 40, 50.
1019 *
1020 * @return the number of values between major ticks
1021 * @see #setMajorTickSpacing
1022 */
1023 public int getMajorTickSpacing() {
1024 return majorTickSpacing;
1025 }
1026
1027 /**
1028 * This method sets the major tick spacing. The number that is passed in
1029 * represents the distance, measured in values, between each major tick mark.
1030 * If you have a slider with a range from 0 to 50 and the major tick spacing
1031 * is set to 10, you will get major ticks next to the following values:
1032 * 0, 10, 20, 30, 40, 50.
1033 * <p>
1034 * In order for major ticks to be painted, {@code setPaintTicks} must be
1035 * set to {@code true}.
1036 * <p>
1037 * This method will also set up a label table for you.
1038 * If there is not already a label table, and the major tick spacing is
1039 * {@code > 0}, and {@code getPaintLabels} returns
1040 * {@code true}, a standard label table will be generated (by calling
1041 * {@code createStandardLabels}) with labels at the major tick marks.
1042 * For the example above, you would get text labels: "0",
1043 * "10", "20", "30", "40", "50".
1044 * The label table is then set on the slider by calling
1045 * {@code setLabelTable}.
1046 *
1047 * @param n new value for the {@code majorTickSpacing} property
1048 * @see #getMajorTickSpacing
1049 * @see #setPaintTicks
1050 * @see #setLabelTable
1051 * @see #createStandardLabels(int)
1052 * @beaninfo
1053 * bound: true
1054 * attribute: visualUpdate true
1055 * description: Sets the number of values between major tick marks.
1056 *
1057 */
1058 public void setMajorTickSpacing(int n) {
1059 int oldValue = majorTickSpacing;
1060 majorTickSpacing = n;
1061 if (labelTable == null && getMajorTickSpacing() > 0
1062 && getPaintLabels()) {
1063 setLabelTable(createStandardLabels(getMajorTickSpacing()));
1064 }
1065 firePropertyChange("majorTickSpacing", oldValue,
1066 majorTickSpacing);
1067 if (majorTickSpacing != oldValue && getPaintTicks()) {
1068 repaint();
1069 }
1070 }
1071
1072 /**
1073 * This method returns the minor tick spacing. The number that is returned
1074 * represents the distance, measured in values, between each minor tick mark.
1075 * If you have a slider with a range from 0 to 50 and the minor tick spacing
1076 * is set to 10, you will get minor ticks next to the following values:
1077 * 0, 10, 20, 30, 40, 50.
1078 *
1079 * @return the number of values between minor ticks
1080 * @see #getMinorTickSpacing
1081 */
1082 public int getMinorTickSpacing() {
1083 return minorTickSpacing;
1084 }
1085
1086 /**
1087 * This method sets the minor tick spacing. The number that is passed in
1088 * represents the distance, measured in values, between each minor tick mark.
1089 * If you have a slider with a range from 0 to 50 and the minor tick spacing
1090 * is set to 10, you will get minor ticks next to the following values:
1091 * 0, 10, 20, 30, 40, 50.
1092 * <p>
1093 * In order for minor ticks to be painted, {@code setPaintTicks} must be
1094 * set to {@code true}.
1095 *
1096 * @param n new value for the {@code minorTickSpacing} property
1097 * @see #getMinorTickSpacing
1098 * @see #setPaintTicks
1099 * @beaninfo
1100 * bound: true
1101 * attribute: visualUpdate true
1102 * description: Sets the number of values between minor tick marks.
1103 */
1104 public void setMinorTickSpacing(int n) {
1105 int oldValue = minorTickSpacing;
1106 minorTickSpacing = n;
1107 firePropertyChange("minorTickSpacing", oldValue,
1108 minorTickSpacing);
1109 if (minorTickSpacing != oldValue && getPaintTicks()) {
1110 repaint();
1111 }
1112 }
1113
1114 /**
1115 * Returns true if the knob (and the data value it represents)
1116 * resolve to the closest tick mark next to where the user
1117 * positioned the knob.
1118 *
1119 * @return true if the value snaps to the nearest tick mark, else false
1120 * @see #setSnapToTicks
1121 */
1122 public boolean getSnapToTicks() {
1123 return snapToTicks;
1124 }
1125
1126 /**
1127 * Returns true if the knob (and the data value it represents)
1128 * resolve to the closest slider value next to where the user
1129 * positioned the knob.
1130 *
1131 * @return true if the value snaps to the nearest slider value, else false
1132 * @see #setSnapToValue
1133 */
1134 boolean getSnapToValue() {
1135 return snapToValue;
1136 }
1137
1138 /**
1139 * Specifying true makes the knob (and the data value it represents)
1140 * resolve to the closest tick mark next to where the user
1141 * positioned the knob.
1142 * By default, this property is {@code false}.
1143 *
1144 * @param b true to snap the knob to the nearest tick mark
1145 * @see #getSnapToTicks
1146 * @beaninfo
1147 * bound: true
1148 * description: If true snap the knob to the nearest tick mark.
1149 */
1150 public void setSnapToTicks(boolean b) {
1151 boolean oldValue = snapToTicks;
1152 snapToTicks = b;
1153 firePropertyChange("snapToTicks", oldValue, snapToTicks);
1154 }
1155
1156 /**
1157 * Specifying true makes the knob (and the data value it represents)
1158 * resolve to the closest slider value next to where the user
1159 * positioned the knob. If the {@code snapToTicks} property has also been
1160 * set to {@code true}, the snap-to-ticks behavior will prevail.
1161 * By default, the snapToValue property is {@code true}.
1162 *
1163 * @param b true to snap the knob to the nearest slider value
1164 * @see #getSnapToValue
1165 * @see #setSnapToTicks
1166 * @beaninfo
1167 * bound: true
1168 * description: If true snap the knob to the nearest slider value.
1169 */
1170 void setSnapToValue(boolean b) {
1171 boolean oldValue = snapToValue;
1172 snapToValue = b;
1173 firePropertyChange("snapToValue", oldValue, snapToValue);
1174 }
1175
1176 /**
1177 * Tells if tick marks are to be painted.
1178 * @return true if tick marks are painted, else false
1179 * @see #setPaintTicks
1180 */
1181 public boolean getPaintTicks() {
1182 return paintTicks;
1183 }
1184
1185 /**
1186 * Determines whether tick marks are painted on the slider.
1187 * By default, this property is {@code false}.
1188 *
1189 * @param b whether or not tick marks should be painted
1190 * @see #getPaintTicks
1191 * @beaninfo
1192 * bound: true
1193 * attribute: visualUpdate true
1194 * description: If true tick marks are painted on the slider.
1195 */
1196 public void setPaintTicks(boolean b) {
1197 boolean oldValue = paintTicks;
1198 paintTicks = b;
1199 firePropertyChange("paintTicks", oldValue, paintTicks);
1200 if (paintTicks != oldValue) {
1201 revalidate();
1202 repaint();
1203 }
1204 }
1205
1206 /**
1207 * Tells if the track (area the slider slides in) is to be painted.
1208 * @return true if track is painted, else false
1209 * @see #setPaintTrack
1210 */
1211 public boolean getPaintTrack() {
1212 return paintTrack;
1213 }
1214
1215 /**
1216 * Determines whether the track is painted on the slider.
1217 * By default, this property is {@code true}.
1218 *
1219 * @param b whether or not to paint the slider track
1220 * @see #getPaintTrack
1221 * @beaninfo
1222 * bound: true
1223 * attribute: visualUpdate true
1224 * description: If true, the track is painted on the slider.
1225 */
1226 public void setPaintTrack(boolean b) {
1227 boolean oldValue = paintTrack;
1228 paintTrack = b;
1229 firePropertyChange("paintTrack", oldValue, paintTrack);
1230 if (paintTrack != oldValue) {
1231 repaint();
1232 }
1233 }
1234
1235 /**
1236 * Tells if labels are to be painted.
1237 * @return true if labels are painted, else false
1238 * @see #setPaintLabels
1239 */
1240 public boolean getPaintLabels() {
1241 return paintLabels;
1242 }
1243
1244 /**
1245 * Determines whether labels are painted on the slider.
1246 * <p>
1247 * This method will also set up a label table for you.
1248 * If there is not already a label table, and the major tick spacing is
1249 * {@code > 0},
1250 * a standard label table will be generated (by calling
1251 * {@code createStandardLabels}) with labels at the major tick marks.
1252 * The label table is then set on the slider by calling
1253 * {@code setLabelTable}.
1254 * <p>
1255 * By default, this property is {@code false}.
1256 *
1257 * @param b whether or not to paint labels
1258 * @see #getPaintLabels
1259 * @see #getLabelTable
1260 * @see #createStandardLabels(int)
1261 * @beaninfo
1262 * bound: true
1263 * attribute: visualUpdate true
1264 * description: If true labels are painted on the slider.
1265 */
1266 public void setPaintLabels(boolean b) {
1267 boolean oldValue = paintLabels;
1268 paintLabels = b;
1269 if (labelTable == null && getMajorTickSpacing() > 0) {
1270 setLabelTable(createStandardLabels(getMajorTickSpacing()));
1271 }
1272 firePropertyChange("paintLabels", oldValue, paintLabels);
1273 if (paintLabels != oldValue) {
1274 revalidate();
1275 repaint();
1276 }
1277 }
1278
1279 /**
1280 * See readObject() and writeObject() in JComponent for more
1281 * information about serialization in Swing.
1282 */
1283 private void writeObject(ObjectOutputStream s) throws IOException {
1284 s.defaultWriteObject();
1285 if (getUIClassID().equals(uiClassID)) {
1286 byte count = JComponent.getWriteObjCounter(this );
1287 JComponent.setWriteObjCounter(this , --count);
1288 if (count == 0 && ui != null) {
1289 ui.installUI(this );
1290 }
1291 }
1292 }
1293
1294 /**
1295 * Returns a string representation of this JSlider. This method
1296 * is intended to be used only for debugging purposes, and the
1297 * content and format of the returned string may vary between
1298 * implementations. The returned string may be empty but may not
1299 * be <code>null</code>.
1300 *
1301 * @return a string representation of this JSlider.
1302 */
1303 protected String paramString() {
1304 String paintTicksString = (paintTicks ? "true" : "false");
1305 String paintTrackString = (paintTrack ? "true" : "false");
1306 String paintLabelsString = (paintLabels ? "true" : "false");
1307 String isInvertedString = (isInverted ? "true" : "false");
1308 String snapToTicksString = (snapToTicks ? "true" : "false");
1309 String snapToValueString = (snapToValue ? "true" : "false");
1310 String orientationString = (orientation == HORIZONTAL ? "HORIZONTAL"
1311 : "VERTICAL");
1312
1313 return super .paramString() + ",isInverted=" + isInvertedString
1314 + ",majorTickSpacing=" + majorTickSpacing
1315 + ",minorTickSpacing=" + minorTickSpacing
1316 + ",orientation=" + orientationString + ",paintLabels="
1317 + paintLabelsString + ",paintTicks=" + paintTicksString
1318 + ",paintTrack=" + paintTrackString + ",snapToTicks="
1319 + snapToTicksString + ",snapToValue="
1320 + snapToValueString;
1321 }
1322
1323 /////////////////
1324 // Accessibility support
1325 ////////////////
1326
1327 /**
1328 * Gets the AccessibleContext associated with this JSlider.
1329 * For sliders, the AccessibleContext takes the form of an
1330 * AccessibleJSlider.
1331 * A new AccessibleJSlider instance is created if necessary.
1332 *
1333 * @return an AccessibleJSlider that serves as the
1334 * AccessibleContext of this JSlider
1335 */
1336 public AccessibleContext getAccessibleContext() {
1337 if (accessibleContext == null) {
1338 accessibleContext = new AccessibleJSlider();
1339 }
1340 return accessibleContext;
1341 }
1342
1343 /**
1344 * This class implements accessibility support for the
1345 * <code>JSlider</code> class. It provides an implementation of the
1346 * Java Accessibility API appropriate to slider user-interface elements.
1347 * <p>
1348 * <strong>Warning:</strong>
1349 * Serialized objects of this class will not be compatible with
1350 * future Swing releases. The current serialization support is
1351 * appropriate for short term storage or RMI between applications running
1352 * the same version of Swing. As of 1.4, support for long term storage
1353 * of all JavaBeans<sup><font size="-2">TM</font></sup>
1354 * has been added to the <code>java.beans</code> package.
1355 * Please see {@link java.beans.XMLEncoder}.
1356 */
1357 protected class AccessibleJSlider extends AccessibleJComponent
1358 implements AccessibleValue {
1359
1360 /**
1361 * Get the state set of this object.
1362 *
1363 * @return an instance of AccessibleState containing the current state
1364 * of the object
1365 * @see AccessibleState
1366 */
1367 public AccessibleStateSet getAccessibleStateSet() {
1368 AccessibleStateSet states = super .getAccessibleStateSet();
1369 if (getValueIsAdjusting()) {
1370 states.add(AccessibleState.BUSY);
1371 }
1372 if (getOrientation() == VERTICAL) {
1373 states.add(AccessibleState.VERTICAL);
1374 } else {
1375 states.add(AccessibleState.HORIZONTAL);
1376 }
1377 return states;
1378 }
1379
1380 /**
1381 * Get the role of this object.
1382 *
1383 * @return an instance of AccessibleRole describing the role of the object
1384 */
1385 public AccessibleRole getAccessibleRole() {
1386 return AccessibleRole.SLIDER;
1387 }
1388
1389 /**
1390 * Get the AccessibleValue associated with this object. In the
1391 * implementation of the Java Accessibility API for this class,
1392 * return this object, which is responsible for implementing the
1393 * AccessibleValue interface on behalf of itself.
1394 *
1395 * @return this object
1396 */
1397 public AccessibleValue getAccessibleValue() {
1398 return this ;
1399 }
1400
1401 /**
1402 * Get the accessible value of this object.
1403 *
1404 * @return The current value of this object.
1405 */
1406 public Number getCurrentAccessibleValue() {
1407 return new Integer(getValue());
1408 }
1409
1410 /**
1411 * Set the value of this object as a Number.
1412 *
1413 * @return True if the value was set.
1414 */
1415 public boolean setCurrentAccessibleValue(Number n) {
1416 // TIGER - 4422535
1417 if (n == null) {
1418 return false;
1419 }
1420 setValue(n.intValue());
1421 return true;
1422 }
1423
1424 /**
1425 * Get the minimum accessible value of this object.
1426 *
1427 * @return The minimum value of this object.
1428 */
1429 public Number getMinimumAccessibleValue() {
1430 return new Integer(getMinimum());
1431 }
1432
1433 /**
1434 * Get the maximum accessible value of this object.
1435 *
1436 * @return The maximum value of this object.
1437 */
1438 public Number getMaximumAccessibleValue() {
1439 // TIGER - 4422362
1440 BoundedRangeModel model = JSlider.this .getModel();
1441 return new Integer(model.getMaximum() - model.getExtent());
1442 }
1443 } // AccessibleJSlider
1444 }
|