Source for javax.swing.JSlider

   1: /* JSlider.java --
   2:    Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing;
  40: 
  41: import java.awt.Dimension;
  42: import java.awt.MenuContainer;
  43: import java.awt.image.ImageObserver;
  44: import java.beans.PropertyChangeEvent;
  45: import java.io.Serializable;
  46: import java.util.Dictionary;
  47: import java.util.Enumeration;
  48: import java.util.Hashtable;
  49: 
  50: import javax.accessibility.Accessible;
  51: import javax.accessibility.AccessibleContext;
  52: import javax.accessibility.AccessibleRole;
  53: import javax.accessibility.AccessibleStateSet;
  54: import javax.accessibility.AccessibleValue;
  55: import javax.swing.event.ChangeEvent;
  56: import javax.swing.event.ChangeListener;
  57: import javax.swing.plaf.SliderUI;
  58: 
  59: /**
  60:  * The JSlider is a Swing component that allows selection of a value within a
  61:  * range by adjusting a thumb in a track. The values for the minimum,
  62:  * maximum, extent and value are stored in a {@link
  63:  * DefaultBoundedRangeModel}.
  64:  * 
  65:  * <p>
  66:  * JSliders have the following properties:
  67:  * </p>
  68:  * 
  69:  * <table>
  70:  * <tr><th> Property         </th><th> Stored in </th><th> Bound? </th></tr>
  71:  * <tr><td> extent           </td><td> model     </td><td> no     </td></tr>
  72:  * <tr><td> inverted         </td><td> slider    </td><td> yes    </td></tr>
  73:  * <tr><td> labelTable       </td><td> slider    </td><td> yes    </td></tr>
  74:  * <tr><td> majorTickSpacing </td><td> slider    </td><td> yes    </td></tr> 
  75:  * <tr><td> maximum          </td><td> model     </td><td> no     </td></tr>
  76:  * <tr><td> minimum          </td><td> model     </td><td> no     </td></tr>
  77:  * <tr><td> minorTickSpacing </td><td> slider    </td><td> yes    </td></tr>
  78:  * <tr><td> model            </td><td> slider    </td><td> yes    </td></tr> 
  79:  * <tr><td> orientation      </td><td> slider    </td><td> yes    </td></tr>
  80:  * <tr><td> paintLabels      </td><td> slider    </td><td> yes    </td></tr>
  81:  * <tr><td> paintTicks       </td><td> slider    </td><td> yes    </td></tr>
  82:  * <tr><td> snapToTicks      </td><td> slider    </td><td> no     </td></tr>
  83:  * <tr><td> value            </td><td> model     </td><td> no     </td></tr>
  84:  * <tr><td> valueIsAdjusting </td><td> model     </td><td> no     </td></tr>
  85:  * </table>
  86:  * 
  87:  * <p>
  88:  * The various behavioral aspects of these properties follows:
  89:  * </p>
  90:  * 
  91:  * <ul>
  92:  * <li>
  93:  * When non-bound properties stored in the slider change, the slider fires
  94:  * ChangeEvents to its ChangeListeners.
  95:  * </li>
  96:  * <li>
  97:  * When bound properties stored in the slider change, the slider fires
  98:  * PropertyChangeEvents to its PropertyChangeListeners
  99:  * </li>
 100:  * <li>
 101:  * If any of the model's properties change, it fires a ChangeEvent to its
 102:  * ChangeListeners, which include the slider.
 103:  * </li>
 104:  * <li>
 105:  * If the slider receives a ChangeEvent from its model, it will propagate the
 106:  * ChangeEvent to its ChangeListeners, with the ChangeEvent's "source"
 107:  * property set to refer to the slider, rather than the model.
 108:  * </li>
 109:  * </ul>
 110:  */
 111: public class JSlider extends JComponent implements SwingConstants, Accessible,
 112:                                                    ImageObserver,
 113:                                                    MenuContainer, Serializable
 114: {
 115:   /** DOCUMENT ME! */
 116:   private static final long serialVersionUID = -1441275936141218479L;
 117: 
 118:   /**
 119:    * DOCUMENT ME!
 120:    */
 121:   // FIXME: This inner class is a complete stub and needs to be implemented
 122:   // properly.
 123:   protected class AccessibleJSlider extends JComponent.AccessibleJComponent
 124:     implements AccessibleValue
 125:   {
 126:     private static final long serialVersionUID = -6301740148041106789L;
 127:   
 128:     /**
 129:      * Creates a new AccessibleJSlider object.
 130:      */
 131:     protected AccessibleJSlider()
 132:     {
 133:       // Nothing to do here.
 134:     }
 135: 
 136:     /**
 137:      * DOCUMENT ME!
 138:      *
 139:      * @return DOCUMENT ME!
 140:      */
 141:     public AccessibleStateSet getAccessibleStateSet()
 142:     {
 143:       return null;
 144:     }
 145: 
 146:     /**
 147:      * DOCUMENT ME!
 148:      *
 149:      * @return DOCUMENT ME!
 150:      */
 151:     public AccessibleRole getAccessibleRole()
 152:     {
 153:       return null;
 154:     }
 155: 
 156:     /**
 157:      * DOCUMENT ME!
 158:      *
 159:      * @return DOCUMENT ME!
 160:      */
 161:     public AccessibleValue getAccessibleValue()
 162:     {
 163:       return null;
 164:     }
 165: 
 166:     /**
 167:      * DOCUMENT ME!
 168:      *
 169:      * @return DOCUMENT ME!
 170:      */
 171:     public Number getCurrentAccessibleValue()
 172:     {
 173:       return null;
 174:     }
 175: 
 176:     /**
 177:      * setCurrentAccessibleValue
 178:      *
 179:      * @param value0 TODO
 180:      *
 181:      * @return boolean
 182:      */
 183:     public boolean setCurrentAccessibleValue(Number value0)
 184:     {
 185:       return false;
 186:     }
 187: 
 188:     /**
 189:      * getMinimumAccessibleValue
 190:      *
 191:      * @return Number
 192:      */
 193:     public Number getMinimumAccessibleValue()
 194:     {
 195:       return null;
 196:     }
 197: 
 198:     /**
 199:      * getMaximumAccessibleValue
 200:      *
 201:      * @return Number
 202:      */
 203:     public Number getMaximumAccessibleValue()
 204:     {
 205:       return null;
 206:     }
 207:   }
 208: 
 209:   /** Whether or not this slider paints its ticks. */
 210:   private transient boolean paintTicks = false;
 211: 
 212:   /** Whether or not this slider paints its track. */
 213:   private transient boolean paintTrack = true;
 214: 
 215:   /** Whether or not this slider paints its labels. */
 216:   private transient boolean paintLabels = false;
 217: 
 218:   /**
 219:    * A dictionary of (Integer, Component) pairs where each Component is a
 220:    * JLabel and the Integer determines where the label will be painted.
 221:    */
 222:   private transient Dictionary labelTable;
 223: 
 224:   /** The model used to describe the slider. */
 225:   protected BoundedRangeModel sliderModel;
 226: 
 227:   /** The space between major ticks. */
 228:   protected int majorTickSpacing;
 229: 
 230:   /** The space between minor ticks. */
 231:   protected int minorTickSpacing;
 232: 
 233:   /** Whether the slider snaps its values to ticks. */
 234:   protected boolean snapToTicks = false;
 235: 
 236:   /** The orientation of the slider. */
 237:   protected int orientation = HORIZONTAL;
 238: 
 239:   /** Whether the slider is inverted. */
 240:   private transient boolean isInverted;
 241: 
 242:   /** The ChangeListener that listens to the model. */
 243:   protected ChangeListener changeListener;
 244: 
 245:   /** The ChangeEvent that is passed to all listeners of this slider. */
 246:   protected transient ChangeEvent changeEvent;
 247: 
 248:   /**
 249:    * Creates a new horizontal JSlider object with a minimum of 0, a maximum of
 250:    * 100, and a value of 50.
 251:    */
 252:   public JSlider()
 253:   {
 254:     this(HORIZONTAL, 0, 100, 50);
 255:   }
 256: 
 257:   /**
 258:    * Creates a new JSlider object with the given orientation and a minimum of
 259:    * 0, a maximum of 100, and a value of 50.
 260:    *
 261:    * @param orientation The orientation of the slider ({@link #HORIZONTAL} or
 262:    *                    {@link #VERTICAL}).
 263:    * 
 264:    * @throws IllegalArgumentException if <code>orientation</code> is not one of
 265:    *         the specified values.
 266:    */
 267:   public JSlider(int orientation)
 268:   {
 269:     this(orientation, 0, 100, 50);
 270:   }
 271: 
 272:   /**
 273:    * Creates a new horizontal JSlider object with the given maximum and
 274:    * minimum and a value that is  halfway between the minimum and the
 275:    * maximum.
 276:    *
 277:    * @param minimum The minimum value of the JSlider.
 278:    * @param maximum The maximum value of the JSlider.
 279:    */
 280:   public JSlider(int minimum, int maximum)
 281:   {
 282:     this(HORIZONTAL, minimum, maximum, (maximum + minimum) / 2);
 283:   }
 284: 
 285:   /**
 286:    * Creates a new horizontal JSlider object with the given minimum, maximum,
 287:    * and value.
 288:    *
 289:    * @param minimum The minimum value of the JSlider.
 290:    * @param maximum The maximum value of the JSlider.
 291:    * @param value The initial value of the JSlider.
 292:    */
 293:   public JSlider(int minimum, int maximum, int value)
 294:   {
 295:     this(HORIZONTAL, minimum, maximum, value);
 296:   }
 297: 
 298:   /**
 299:    * Creates a new JSlider object with the given orientation, minimum,
 300:    * maximum, and value.
 301:    *
 302:    * @param orientation The orientation of the slider ({@link #HORIZONTAL} or
 303:    *                    {@link #VERTICAL}).
 304:    * @param minimum The minimum value of the JSlider.
 305:    * @param maximum The maximum value of the JSlider.
 306:    * @param value The initial value of the JSlider.
 307:    * 
 308:    * @throws IllegalArgumentException if <code>orientation</code> is not one of
 309:    *         the specified values.
 310:    */
 311:   public JSlider(int orientation, int minimum, int maximum, int value)
 312:   {
 313:     sliderModel = new DefaultBoundedRangeModel(value, 0, minimum, maximum);
 314:     if (orientation != HORIZONTAL && orientation != VERTICAL)
 315:       throw new IllegalArgumentException(orientation + " is not a legal orientation");
 316:     this.orientation = orientation;
 317:     changeListener = createChangeListener();
 318:     sliderModel.addChangeListener(changeListener);
 319:     updateUI();
 320:   }
 321: 
 322:   /**
 323:    * Creates a new horizontal JSlider object with the given model.
 324:    *
 325:    * @param model The model (<code>null</code> not permitted).
 326:    * 
 327:    * @throws NullPointerException if <code>model</code> is <code>null</code>.
 328:    */
 329:   public JSlider(BoundedRangeModel model)
 330:   {
 331:     sliderModel = model;
 332:     changeListener = createChangeListener();
 333:     sliderModel.addChangeListener(changeListener);
 334:     updateUI();
 335:   }
 336: 
 337:   /**
 338:    * This method returns the current value of the slider.
 339:    *
 340:    * @return The value of the slider stored in the model.
 341:    */
 342:   public int getValue()
 343:   {
 344:     return sliderModel.getValue();
 345:   }
 346: 
 347:   /**
 348:    * This method sets the value of the slider.
 349:    *
 350:    * @param value The slider's new value.
 351:    */
 352:   public void setValue(int value)
 353:   {
 354:     sliderModel.setValue(value);
 355:   }
 356: 
 357:   /**
 358:    * This method returns the slider's UI delegate.
 359:    *
 360:    * @return The slider's UI delegate.
 361:    */
 362:   public SliderUI getUI()
 363:   {
 364:     return (SliderUI) ui;
 365:   }
 366: 
 367:   /**
 368:    * This method sets the slider's UI delegate.
 369:    *
 370:    * @param ui A SliderUI object to use with this slider.
 371:    */
 372:   public void setUI(SliderUI ui)
 373:   {
 374:     super.setUI(ui);
 375:   }
 376: 
 377:   /**
 378:    * This method sets this slider's UI to the UIManager's default for the
 379:    * current look and feel.
 380:    */
 381:   public void updateUI()
 382:   {
 383:     setUI((SliderUI) UIManager.getUI(this));
 384:     invalidate();
 385:     repaint();
 386:   }
 387: 
 388:   /**
 389:    * This method returns a name to identify which look and feel class will be
 390:    * the UI delegate for the slider.
 391:    *
 392:    * @return The Look and Feel classID. "SliderUI"
 393:    */
 394:   public String getUIClassID()
 395:   {
 396:     return "SliderUI";
 397:   }
 398: 
 399:   /**
 400:    * Creates a ChangeListener for this Slider.
 401:    *
 402:    * @return A new ChangeListener.
 403:    */
 404:   protected ChangeListener createChangeListener()
 405:   {
 406:     return new ChangeListener()
 407:       {
 408:     public void stateChanged(ChangeEvent ce)
 409:     {
 410:       // No need to trigger a repaint since the UI listens to the model
 411:       // as well. All we need to do is pass on the stateChanged event 
 412:       // to our listeners.
 413:       fireStateChanged();
 414:     }
 415:       };
 416:   }
 417: 
 418:   /**
 419:    * This method registers a listener to this slider. The listener will be
 420:    * informed of new ChangeEvents.
 421:    *
 422:    * @param listener The listener to register.
 423:    */
 424:   public void addChangeListener(ChangeListener listener)
 425:   {
 426:     listenerList.add(ChangeListener.class, listener);
 427:   }
 428: 
 429:   /**
 430:    * This method removes a listener from this slider.
 431:    *
 432:    * @param listener The listener to remove.
 433:    */
 434:   public void removeChangeListener(ChangeListener listener)
 435:   {
 436:     listenerList.remove(ChangeListener.class, listener);
 437:   }
 438: 
 439:   /**
 440:    * This method is called whenever the model fires a ChangeEvent. It should
 441:    * propagate the ChangeEvent to its listeners with a new ChangeEvent that
 442:    * identifies the slider as the source.
 443:    */
 444:   protected void fireStateChanged()
 445:   {
 446:     Object[] changeListeners = listenerList.getListenerList();
 447:     if (changeEvent == null)
 448:       changeEvent = new ChangeEvent(this);
 449:     for (int i = changeListeners.length - 2; i >= 0; i -= 2)
 450:       {
 451:     if (changeListeners[i] == ChangeListener.class)
 452:       ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent);
 453:       }
 454:   }
 455: 
 456:   /**
 457:    * This method returns an array of all ChangeListeners listening to this
 458:    * slider.
 459:    *
 460:    * @return An array of ChangeListeners listening to this slider.
 461:    */
 462:   public ChangeListener[] getChangeListeners()
 463:   {
 464:     return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
 465:   }
 466: 
 467:   /**
 468:    * This method returns the model of the slider.
 469:    *
 470:    * @return The slider's model.
 471:    */
 472:   public BoundedRangeModel getModel()
 473:   {
 474:     return sliderModel;
 475:   }
 476: 
 477:   /**
 478:    * This method changes the "model" property. It also needs  to unregister
 479:    * any listeners to the old model and register any listeners to the new
 480:    * model.
 481:    *
 482:    * @param model The model to use with the slider.
 483:    */
 484:   public void setModel(BoundedRangeModel model)
 485:   {
 486:     // I didn't do the null pointer check on purpose.
 487:     // If you try it with Sun's, it'll go ahead and set it to null
 488:     // and bork the next time it tries to access the model.
 489:     if (model != sliderModel)
 490:       {
 491:     BoundedRangeModel oldModel = sliderModel;
 492:     sliderModel = model;
 493:     oldModel.removeChangeListener(changeListener);
 494:     sliderModel.addChangeListener(changeListener);
 495:     firePropertyChange("model", oldModel, sliderModel);
 496:       }
 497:   }
 498: 
 499:   /**
 500:    * This method returns the minimum value of the slider.
 501:    *
 502:    * @return The minimum value of the slider.
 503:    */
 504:   public int getMinimum()
 505:   {
 506:     return sliderModel.getMinimum();
 507:   }
 508: 
 509:   /**
 510:    * This method sets the minimum value of the slider.
 511:    *
 512:    * @param minimum The minimum value of the slider.
 513:    */
 514:   public void setMinimum(int minimum)
 515:   {
 516:     int old = sliderModel.getMinimum();
 517:     sliderModel.setMinimum(minimum);
 518:     if (minimum != old)
 519:       firePropertyChange("minimum", old, minimum);
 520:   }
 521: 
 522:   /**
 523:    * This method returns the maximum value of the slider.
 524:    *
 525:    * @return The maximum value of the slider.
 526:    */
 527:   public int getMaximum()
 528:   {
 529:     return sliderModel.getMaximum();
 530:   }
 531: 
 532:   /**
 533:    * This method sets the maximum value of the slider.
 534:    *
 535:    * @param maximum The maximum value of the slider.
 536:    */
 537:   public void setMaximum(int maximum)
 538:   {
 539:     int old = sliderModel.getMaximum();
 540:     sliderModel.setMaximum(maximum);
 541:     if (maximum != old)
 542:       firePropertyChange("maximum", old, maximum);
 543:   }
 544: 
 545:   /**
 546:    * This method returns this slider's isAdjusting value which is true if the
 547:    * thumb is being dragged.
 548:    *
 549:    * @return The slider's isAdjusting value.
 550:    */
 551:   public boolean getValueIsAdjusting()
 552:   {
 553:     return sliderModel.getValueIsAdjusting();
 554:   }
 555: 
 556:   /**
 557:    * This method sets the isAdjusting value for the slider.
 558:    *
 559:    * @param adjusting The slider's isAdjusting value.
 560:    */
 561:   public void setValueIsAdjusting(boolean adjusting)
 562:   {
 563:     sliderModel.setValueIsAdjusting(adjusting);
 564:   }
 565: 
 566:   /**
 567:    * This method returns the extent value for this slider.
 568:    *
 569:    * @return The extent value for this slider.
 570:    */
 571:   public int getExtent()
 572:   {
 573:     return sliderModel.getExtent();
 574:   }
 575: 
 576:   /**
 577:    * This method sets the extent value for this slider.
 578:    *
 579:    * @param extent The extent value for this slider.
 580:    */
 581:   public void setExtent(int extent)
 582:   {
 583:     sliderModel.setExtent(extent);
 584:   }
 585: 
 586:   /**
 587:    * This method returns the slider orientation.
 588:    *
 589:    * @return The orientation of the slider.
 590:    */
 591:   public int getOrientation()
 592:   {
 593:     return orientation;
 594:   }
 595: 
 596:   /**
 597:    * This method changes the "orientation" property of this slider. If the
 598:    * orientation is not VERTICAL or HORIZONTAL, this method does nothing.
 599:    *
 600:    * @param orientation The orientation of this slider.
 601:    */
 602:   public void setOrientation(int orientation)
 603:   {
 604:     if (orientation != VERTICAL && orientation != HORIZONTAL)
 605:       throw new IllegalArgumentException("orientation must be one of: VERTICAL, HORIZONTAL");
 606:     if (orientation != this.orientation)
 607:       {
 608:     int oldOrientation = this.orientation;
 609:     this.orientation = orientation;
 610:     firePropertyChange("orientation", oldOrientation,
 611:                        this.orientation);
 612:       }
 613:   }
 614: 
 615:   /**
 616:    * This method returns the label table for this slider.
 617:    *
 618:    * @return The label table for this slider.
 619:    */
 620:   public Dictionary getLabelTable()
 621:   {
 622:     return labelTable;
 623:   }
 624: 
 625:   /**
 626:    * This method changes the "labelTable" property of this slider.
 627:    *
 628:    * @param table The label table for this slider.
 629:    */
 630:   public void setLabelTable(Dictionary table)
 631:   {
 632:     if (table != labelTable)
 633:       {
 634:     Dictionary oldTable = labelTable;
 635:     labelTable = table;
 636:     firePropertyChange("labelTable", oldTable, labelTable);
 637:       }
 638:   }
 639: 
 640:   /**
 641:    * This method is called to reset UI delegates for the labels in the
 642:    * labelTable to a default for the current look and feel.
 643:    */
 644:   protected void updateLabelUIs()
 645:   {
 646:     if (labelTable == null)
 647:       return;
 648:     for (Enumeration list = labelTable.elements(); list.hasMoreElements();)
 649:       {
 650:     JLabel label = (JLabel) list.nextElement();
 651:     label.updateUI();
 652:       }
 653:   }
 654: 
 655:   /**
 656:    * Creates a hashtable of (Integer, JLabel) pairs that can be used as a
 657:    * label table for this slider. The labels will start from the sliders
 658:    * minimum and increase by the increment. Each  label will have a text
 659:    * string indicating their integer value.
 660:    *
 661:    * @param increment The increment between labels (must be > 0).
 662:    *
 663:    * @return A hashtable with the labels and their keys.
 664:    *
 665:    * @throws IllegalArgumentException if <code>increment</code> is not greater
 666:    *         than zero.
 667:    */
 668:   public Hashtable createStandardLabels(int increment)
 669:   {
 670:     return createStandardLabels(increment, sliderModel.getMinimum());
 671:   }
 672: 
 673:   /**
 674:    * Creates a hashtable of (Integer, JLabel) pairs that can be used as a
 675:    * label table for this slider. The labels will start from the given start
 676:    * value and increase by the increment. Each  label will have a text string
 677:    * indicating its integer value.
 678:    *
 679:    * @param increment The increment between labels (must be > 0).
 680:    * @param start The value to start from.
 681:    *
 682:    * @return A hashtable with the labels and their keys.
 683:    *
 684:    * @throws IllegalArgumentException if <code>increment</code> is not greater
 685:    *         than zero, or <code>start</code> is not within the range of the
 686:    *         model.
 687:    */
 688:   public Hashtable createStandardLabels(int increment, int start)
 689:   {
 690:     if (increment <= 0) 
 691:       throw new IllegalArgumentException("Requires 'increment' > 0.");
 692:     if (start < getMinimum() || start > getMaximum())
 693:       throw new IllegalArgumentException("The 'start' value is out of range.");
 694:     Hashtable table = new Hashtable();
 695:     JLabel label;
 696:     Dimension dim;
 697: 
 698:     int max = sliderModel.getMaximum();
 699: 
 700:     for (int i = start; i <= max; i += increment)
 701:       {
 702:     label = new JLabel(String.valueOf(i));
 703:     label.setVerticalAlignment(CENTER);
 704:     label.setHorizontalAlignment(CENTER);
 705:     
 706:     // Make sure these labels have the width and height
 707:     // they want.
 708:     dim = label.getPreferredSize();
 709:     label.setBounds(label.getX(), label.getY(),
 710:                     (int) dim.getWidth(),
 711:             (int) dim.getHeight()); 
 712:     table.put(new Integer(i), label);
 713:       }
 714:     return table;
 715:   }
 716: 
 717:   /**
 718:    * This method returns whether the slider is inverted. Horizontal sliders
 719:    * that are not inverted will have the minimums on the left. If they are
 720:    * inverted, the minimums will be  on the right. Vertical sliders that are
 721:    * not inverted will have the minimums at the bottom. If they are inverted,
 722:    * the minimums will be at the top.
 723:    *
 724:    * @return Whether this slider is inverted.
 725:    */
 726:   public boolean getInverted()
 727:   {
 728:     return isInverted;
 729:   }
 730: 
 731:   /**
 732:    * This method changes the "inverted" property for this slider.Horizontal
 733:    * sliders  that are not inverted will have the minimums on the left. If
 734:    * they are inverted, the minimums will be  on the right. Vertical sliders
 735:    * that are not inverted will have the minimums at the bottom. If they are
 736:    * inverted, the minimums will be at the top. However, if the slider's
 737:    * componentOrientation is set to RIGHT_TO_LEFT, then everything gets
 738:    * reversed again.
 739:    *
 740:    * @param inverted Whether the slider should be inverted.
 741:    */
 742:   public void setInverted(boolean inverted)
 743:   {
 744:     if (isInverted != inverted)
 745:       {
 746:     boolean oldInverted = isInverted;
 747:     isInverted = inverted;
 748:     firePropertyChange("inverted", oldInverted, isInverted);
 749:       }
 750:   }
 751: 
 752:   /**
 753:    * This method returns the amount of units between each major tick mark.
 754:    *
 755:    * @return The amount of units between each major tick mark.
 756:    */
 757:   public int getMajorTickSpacing()
 758:   {
 759:     return majorTickSpacing;
 760:   }
 761: 
 762:   /**
 763:    * This method changes the "majorTickSpacing" property for this slider. The
 764:    * major tick spacing is the amount of units between each major tick mark.
 765:    *
 766:    * @param spacing The amount of units between each major tick mark.
 767:    */
 768:   public void setMajorTickSpacing(int spacing)
 769:   {
 770:     if (majorTickSpacing != spacing)
 771:       {
 772:     int oldSpacing = majorTickSpacing;
 773:     majorTickSpacing = spacing;
 774:     firePropertyChange("majorTickSpacing", oldSpacing,
 775:                        majorTickSpacing);
 776:       }
 777:   }
 778: 
 779:   /**
 780:    * This method returns the amount of units between each minor tick mark.
 781:    *
 782:    * @return The amount of units between each minor tick mark.
 783:    */
 784:   public int getMinorTickSpacing()
 785:   {
 786:     return minorTickSpacing;
 787:   }
 788: 
 789:   /**
 790:    * This method changes the "minorTickSpacing" property for this slider. The
 791:    * minor tick spacing is the amount of units between each minor tick mark.
 792:    *
 793:    * @param spacing The amount of units between each minor tick mark.
 794:    */
 795:   public void setMinorTickSpacing(int spacing)
 796:   {
 797:     if (minorTickSpacing != spacing)
 798:       {
 799:     int oldSpacing = minorTickSpacing;
 800:     minorTickSpacing = spacing;
 801:     firePropertyChange("minorTickSpacing", oldSpacing,
 802:                        minorTickSpacing);
 803:       }
 804:   }
 805: 
 806:   /**
 807:    * This method returns whether this slider is snapping to ticks.  Sliders
 808:    * that snap to ticks will automatically move the thumb to the nearest tick
 809:    * mark.
 810:    *
 811:    * @return Whether this slider snaps to ticks.
 812:    */
 813:   public boolean getSnapToTicks()
 814:   {
 815:     return snapToTicks;
 816:   }
 817: 
 818:   /**
 819:    * This method sets whether this slider will snap to ticks. Sliders that
 820:    * snap to ticks will automatically move the thumb to the nearest tick
 821:    * mark.
 822:    *
 823:    * @param snap Whether this slider snaps to ticks.
 824:    */
 825:   public void setSnapToTicks(boolean snap)
 826:   {
 827:     if (snap != snapToTicks)
 828:       {
 829:     snapToTicks = snap;
 830:     firePropertyChange("snapToTicks", !snap, snap);
 831:       }
 832:   }
 833: 
 834:   /**
 835:    * This method returns whether the slider will paint its tick marks. In
 836:    * addition to setting this property to true, one of minor tick spacing  or
 837:    * major tick spacing must be set to a value greater than 0 in order for
 838:    * ticks to be painted.
 839:    *
 840:    * @return Whether ticks will be painted.
 841:    */
 842:   public boolean getPaintTicks()
 843:   {
 844:     return paintTicks;
 845:   }
 846: 
 847:   /**
 848:    * This method changes the "paintTicks" property for this slider. In
 849:    * addition to setting this property to true, one of minor tick spacing  or
 850:    * major tick spacing must be set to a value greater than 0 in order for
 851:    * ticks to be painted.
 852:    *
 853:    * @param paint Whether ticks will be painted.
 854:    */
 855:   public void setPaintTicks(boolean paint)
 856:   {
 857:     if (paint != paintTicks)
 858:       {
 859:     boolean oldPaintTicks = paintTicks;
 860:     paintTicks = paint;
 861:     firePropertyChange("paintTicks", oldPaintTicks, paintTicks);
 862:       }
 863:   }
 864: 
 865:   /**
 866:    * This method returns whether the track will be painted.
 867:    *
 868:    * @return Whether the track will be painted.
 869:    */
 870:   public boolean getPaintTrack()
 871:   {
 872:     return paintTrack;
 873:   }
 874: 
 875:   /**
 876:    * Sets the flag that controls whether or not the track is painted, and
 877:    * sends a {@link PropertyChangeEvent} (for the "paintTrack" property) to all
 878:    * registered listeners.
 879:    *
 880:    * @param paint Whether the track will be painted.
 881:    */
 882:   public void setPaintTrack(boolean paint)
 883:   {
 884:     if (paintTrack != paint)
 885:     {
 886:       paintTrack = paint;
 887:       firePropertyChange("paintTrack", !paint, paint);
 888:     }
 889:   }
 890: 
 891:   /**
 892:    * This method returns whether labels will be painted.
 893:    *
 894:    * @return Whether labels will be painted.
 895:    */
 896:   public boolean getPaintLabels()
 897:   {
 898:     return paintLabels;
 899:   }
 900: 
 901:   /**
 902:    * This method changes the "paintLabels" property.
 903:    *
 904:    * @param paint Whether labels will be painted.
 905:    */
 906:   public void setPaintLabels(boolean paint)
 907:   {
 908:     if (paint != paintLabels)
 909:       {
 910:     paintLabels = paint;
 911:         if (paint && majorTickSpacing > 0)
 912:           labelTable = createStandardLabels(majorTickSpacing);
 913:     firePropertyChange("paintLabels", !paint, paint);
 914:       }
 915:   }
 916: 
 917:   /**
 918:    * This method is used primarily for debugging purposes and returns a string
 919:    * that can be used to represent this slider.
 920:    *
 921:    * @return A string representing this slider.
 922:    */
 923:   protected String paramString()
 924:   {
 925:     return "JSlider";
 926:   }
 927: 
 928:   /**
 929:    * DOCUMENT ME!
 930:    *
 931:    * @return DOCUMENT ME!
 932:    */
 933:   public AccessibleContext getAccessibleContext()
 934:   {
 935:     if (accessibleContext == null)
 936:       accessibleContext = new AccessibleJSlider();
 937:     
 938:     return accessibleContext;
 939:   }
 940: }