Source for javax.swing.JScrollBar

   1: /* JScrollBar.java --
   2:    Copyright (C) 2002, 2004, 2005, 2006,  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 gnu.java.lang.CPStringBuilder;
  42: 
  43: import java.awt.Adjustable;
  44: import java.awt.Dimension;
  45: import java.awt.event.AdjustmentEvent;
  46: import java.awt.event.AdjustmentListener;
  47: import java.beans.PropertyChangeEvent;
  48: 
  49: import javax.accessibility.Accessible;
  50: import javax.accessibility.AccessibleContext;
  51: import javax.accessibility.AccessibleRole;
  52: import javax.accessibility.AccessibleState;
  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.ScrollBarUI;
  58: 
  59: /**
  60:  * The JScrollBar. Two buttons control how the values that the
  61:  * scroll bar can take. You can also drag the thumb or click the track
  62:  * to move the scroll bar. Typically, the JScrollBar is used with
  63:  * other components to translate the value of the bar to the viewable
  64:  * contents of the other components.
  65:  */
  66: public class JScrollBar extends JComponent implements Adjustable, Accessible
  67: {
  68:   /**
  69:    * Provides the accessibility features for the <code>JScrollBar</code>
  70:    * component.
  71:    */
  72:   protected class AccessibleJScrollBar extends JComponent.AccessibleJComponent
  73:     implements AccessibleValue
  74:   {
  75:     private static final long serialVersionUID = -7758162392045586663L;
  76: 
  77:     /**
  78:      * Creates a new <code>AccessibleJScrollBar</code> instance.
  79:      */
  80:     protected AccessibleJScrollBar()
  81:     {
  82:       super();
  83:     }
  84: 
  85:     /**
  86:      * Returns a set containing the current state of the {@link JScrollBar}
  87:      * component.
  88:      *
  89:      * @return The accessible state set.
  90:      */
  91:     public AccessibleStateSet getAccessibleStateSet()
  92:     {
  93:       AccessibleStateSet result = super.getAccessibleStateSet();
  94:       if (orientation == JScrollBar.HORIZONTAL)
  95:         result.add(AccessibleState.HORIZONTAL);
  96:       else if (orientation == JScrollBar.VERTICAL)
  97:         result.add(AccessibleState.VERTICAL);
  98:       return result;
  99:     }
 100: 
 101:     /**
 102:      * Returns the accessible role for the <code>JScrollBar</code> component.
 103:      *
 104:      * @return {@link AccessibleRole#SCROLL_BAR}.
 105:      */
 106:     public AccessibleRole getAccessibleRole()
 107:     {
 108:       return AccessibleRole.SCROLL_BAR;
 109:     }
 110: 
 111:     /**
 112:      * Returns an object that provides access to the current, minimum and
 113:      * maximum values.
 114:      *
 115:      * @return The accessible value.
 116:      */
 117:     public AccessibleValue getAccessibleValue()
 118:     {
 119:       return this;
 120:     }
 121: 
 122:     /**
 123:      * Returns the current value of the {@link JScrollBar} component, as an
 124:      * {@link Integer}.
 125:      *
 126:      * @return The current value of the {@link JScrollBar} component.
 127:      */
 128:     public Number getCurrentAccessibleValue()
 129:     {
 130:       return new Integer(getValue());
 131:     }
 132: 
 133:     /**
 134:      * Sets the current value of the {@link JScrollBar} component and sends a
 135:      * {@link PropertyChangeEvent} (with the property name
 136:      * {@link AccessibleContext#ACCESSIBLE_VALUE_PROPERTY}) to all registered
 137:      * listeners.  If the supplied value is <code>null</code>, this method
 138:      * does nothing and returns <code>false</code>.
 139:      *
 140:      * @param value  the new slider value (<code>null</code> permitted).
 141:      *
 142:      * @return <code>true</code> if the slider value is updated, and
 143:      *     <code>false</code> otherwise.
 144:      */
 145:     public boolean setCurrentAccessibleValue(Number value)
 146:     {
 147:       if (value == null)
 148:         return false;
 149:       Number oldValue = getCurrentAccessibleValue();
 150:       setValue(value.intValue());
 151:       firePropertyChange(AccessibleContext.ACCESSIBLE_VALUE_PROPERTY, oldValue,
 152:                          new Integer(getValue()));
 153:       return true;
 154:     }
 155: 
 156:     /**
 157:      * Returns the minimum value of the {@link JScrollBar} component, as an
 158:      * {@link Integer}.
 159:      *
 160:      * @return The minimum value of the {@link JScrollBar} component.
 161:      */
 162:     public Number getMinimumAccessibleValue()
 163:     {
 164:       return new Integer(getMinimum());
 165:     }
 166: 
 167:     /**
 168:      * Returns the maximum value of the {@link JScrollBar} component, as an
 169:      * {@link Integer}.
 170:      *
 171:      * @return The maximum value of the {@link JScrollBar} component.
 172:      */
 173:     public Number getMaximumAccessibleValue()
 174:     {
 175:       return new Integer(getMaximum() - model.getExtent());
 176:     }
 177:   }
 178: 
 179:   /**
 180:    * Listens for changes on the model and fires them to interested
 181:    * listeners on the JScrollBar, after re-sourcing them.
 182:    */
 183:   private class ScrollBarChangeListener
 184:     implements ChangeListener
 185:   {
 186: 
 187:     public void stateChanged(ChangeEvent event)
 188:     {
 189:       Object o = event.getSource();
 190:       if (o instanceof BoundedRangeModel)
 191:         {
 192:           BoundedRangeModel m = (BoundedRangeModel) o;
 193:           fireAdjustmentValueChanged(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
 194:                                      AdjustmentEvent.TRACK, m.getValue(),
 195:                                      m.getValueIsAdjusting());
 196:         }
 197:     }
 198: 
 199:   }
 200: 
 201:   private static final long serialVersionUID = -8195169869225066566L;
 202: 
 203:   /** How much the thumb moves when moving in a block. */
 204:   protected int blockIncrement = 10;
 205: 
 206:   /** The model that holds the scroll bar's data. */
 207:   protected BoundedRangeModel model;
 208: 
 209:   /** The orientation of the scroll bar. */
 210:   protected int orientation = SwingConstants.VERTICAL;
 211: 
 212:   /** How much the thumb moves when moving in a unit. */
 213:   protected int unitIncrement = 1;
 214: 
 215:   /**
 216:    * This ChangeListener forwards events fired from the model and re-sources
 217:    * them to originate from this JScrollBar.
 218:    */
 219:   private ChangeListener sbChangeListener;
 220: 
 221:   /**
 222:    * Creates a new horizontal JScrollBar object with a minimum
 223:    * of 0, a maxmium of 100, a value of 0 and an extent of 10.
 224:    */
 225:   public JScrollBar()
 226:   {
 227:     this(SwingConstants.VERTICAL, 0, 10, 0, 100);
 228:   }
 229: 
 230:   /**
 231:    * Creates a new JScrollBar object with a minimum of 0, a
 232:    * maximum of 100, a value of 0, an extent of 10 and the given
 233:    * orientation.
 234:    *
 235:    * @param orientation The orientation of the JScrollBar.
 236:    */
 237:   public JScrollBar(int orientation)
 238:   {
 239:     this(orientation, 0, 10, 0, 100);
 240:   }
 241: 
 242:   /**
 243:    * Creates a new JScrollBar object with the given orientation,
 244:    * value, min, max, and extent.
 245:    *
 246:    * @param orientation The orientation to use.
 247:    * @param value The value to use.
 248:    * @param extent The extent to use.
 249:    * @param min The minimum value of the scrollbar.
 250:    * @param max The maximum value of the scrollbar.
 251:    */
 252:   public JScrollBar(int orientation, int value, int extent, int min, int max)
 253:   {
 254:     model = new DefaultBoundedRangeModel(value, extent, min, max);
 255:     sbChangeListener = new ScrollBarChangeListener();
 256:     model.addChangeListener(sbChangeListener);
 257:     if (orientation != SwingConstants.HORIZONTAL
 258:         && orientation != SwingConstants.VERTICAL)
 259:       throw new IllegalArgumentException(orientation
 260:                                          + " is not a legal orientation");
 261:     this.orientation = orientation;
 262:     updateUI();
 263:   }
 264: 
 265:   /**
 266:    * This method sets the UI of this scrollbar to
 267:    * the given UI.
 268:    *
 269:    * @param ui The UI to use with this scrollbar.
 270:    */
 271:   public void setUI(ScrollBarUI ui)
 272:   {
 273:     super.setUI(ui);
 274:   }
 275: 
 276:   /**
 277:    * This method returns the UI that is being used
 278:    * with this scrollbar.
 279:    *
 280:    * @return The scrollbar's current UI.
 281:    */
 282:   public ScrollBarUI getUI()
 283:   {
 284:     return (ScrollBarUI) ui;
 285:   }
 286: 
 287:   /**
 288:    * This method changes the UI to be the
 289:    * default for the current look and feel.
 290:    */
 291:   public void updateUI()
 292:   {
 293:     setUI((ScrollBarUI) UIManager.getUI(this));
 294:   }
 295: 
 296:   /**
 297:    * This method returns an identifier to
 298:    * choose the correct UI delegate for the
 299:    * scrollbar.
 300:    *
 301:    * @return The identifer to choose the UI delegate; "ScrollBarUI"
 302:    */
 303:   public String getUIClassID()
 304:   {
 305:     return "ScrollBarUI";
 306:   }
 307: 
 308:   /**
 309:    * This method returns the orientation of the scrollbar.
 310:    *
 311:    * @return The orientation of the scrollbar.
 312:    */
 313:   public int getOrientation()
 314:   {
 315:     return orientation;
 316:   }
 317: 
 318:   /**
 319:    * This method sets the orientation of the scrollbar.
 320:    *
 321:    * @param orientation The orientation of the scrollbar.
 322:    */
 323:   public void setOrientation(int orientation)
 324:   {
 325:     if (orientation != SwingConstants.HORIZONTAL
 326:         && orientation != SwingConstants.VERTICAL)
 327:       throw new IllegalArgumentException("orientation must be one of HORIZONTAL or VERTICAL");
 328:     if (orientation != this.orientation)
 329:       {
 330:         int oldOrientation = this.orientation;
 331:         this.orientation = orientation;
 332:         firePropertyChange("orientation", oldOrientation,
 333:                            this.orientation);
 334:       }
 335:   }
 336: 
 337:   /**
 338:    * This method returns the model being used with
 339:    * the scrollbar.
 340:    *
 341:    * @return The scrollbar's model.
 342:    */
 343:   public BoundedRangeModel getModel()
 344:   {
 345:     return model;
 346:   }
 347: 
 348:   /**
 349:    * This method sets the model to use with
 350:    * the scrollbar.
 351:    *
 352:    * @param newModel The new model to use with the scrollbar.
 353:    */
 354:   public void setModel(BoundedRangeModel newModel)
 355:   {
 356:     BoundedRangeModel oldModel = model;
 357:     if (oldModel != null)
 358:       oldModel.removeChangeListener(sbChangeListener);
 359:     model = newModel;
 360:     if (model != null)
 361:       model.addChangeListener(sbChangeListener);
 362:     firePropertyChange("model", oldModel, model);
 363:   }
 364: 
 365:   /**
 366:    * This method returns how much the scrollbar's value
 367:    * should change for a unit increment depending on the
 368:    * given direction.
 369:    *
 370:    * @param direction The direction to scroll in.
 371:    *
 372:    * @return The amount the scrollbar's value will change given the direction.
 373:    */
 374:   public int getUnitIncrement(int direction)
 375:   {
 376:     return unitIncrement;
 377:   }
 378: 
 379:   /**
 380:    * This method sets the unitIncrement property.
 381:    *
 382:    * @param unitIncrement The new unitIncrement.
 383:    */
 384:   public void setUnitIncrement(int unitIncrement)
 385:   {
 386:     if (unitIncrement != this.unitIncrement)
 387:       {
 388:         int oldInc = this.unitIncrement;
 389:         this.unitIncrement = unitIncrement;
 390:         firePropertyChange("unitIncrement", oldInc,
 391:                            this.unitIncrement);
 392:       }
 393:   }
 394: 
 395:   /**
 396:    * The method returns how much the scrollbar's value
 397:    * should change for a block increment depending on
 398:    * the given direction.
 399:    *
 400:    * @param direction The direction to scroll in.
 401:    *
 402:    * @return The amount the scrollbar's value will change given the direction.
 403:    */
 404:   public int getBlockIncrement(int direction)
 405:   {
 406:     return blockIncrement;
 407:   }
 408: 
 409:   /**
 410:    * This method sets the blockIncrement property.
 411:    *
 412:    * @param blockIncrement The new blockIncrement.
 413:    */
 414:   public void setBlockIncrement(int blockIncrement)
 415:   {
 416:     if (blockIncrement != this.blockIncrement)
 417:       {
 418:         int oldInc = this.blockIncrement;
 419:         this.blockIncrement = blockIncrement;
 420:         firePropertyChange("blockIncrement", oldInc,
 421:                            this.blockIncrement);
 422:       }
 423:   }
 424: 
 425:   /**
 426:    * This method returns the unitIncrement.
 427:    *
 428:    * @return The unitIncrement.
 429:    */
 430:   public int getUnitIncrement()
 431:   {
 432:     return unitIncrement;
 433:   }
 434: 
 435:   /**
 436:    * This method returns the blockIncrement.
 437:    *
 438:    * @return The blockIncrement.
 439:    */
 440:   public int getBlockIncrement()
 441:   {
 442:     return blockIncrement;
 443:   }
 444: 
 445:   /**
 446:    * This method returns the value of the scrollbar.
 447:    *
 448:    * @return The value of the scrollbar.
 449:    */
 450:   public int getValue()
 451:   {
 452:     return model.getValue();
 453:   }
 454: 
 455:   /**
 456:    * This method changes the value of the scrollbar.
 457:    *
 458:    * @param value The new value of the scrollbar.
 459:    */
 460:   public void setValue(int value)
 461:   {
 462:     model.setValue(value);
 463:   }
 464: 
 465:   /**
 466:    * This method returns the visible amount (AKA extent).
 467:    * The visible amount can be used by UI delegates to
 468:    * determine the size of the thumb.
 469:    *
 470:    * @return The visible amount (AKA extent).
 471:    */
 472:   public int getVisibleAmount()
 473:   {
 474:     return model.getExtent();
 475:   }
 476: 
 477:   /**
 478:    * This method sets the visible amount (AKA extent).
 479:    *
 480:    * @param extent The visible amount (AKA extent).
 481:    */
 482:   public void setVisibleAmount(int extent)
 483:   {
 484:     model.setExtent(extent);
 485:   }
 486: 
 487:   /**
 488:    * This method returns the minimum value of the scrollbar.
 489:    *
 490:    * @return The minimum value of the scrollbar.
 491:    */
 492:   public int getMinimum()
 493:   {
 494:     return model.getMinimum();
 495:   }
 496: 
 497:   /**
 498:    * This method sets the minimum value of the scrollbar.
 499:    *
 500:    * @param minimum The minimum value of the scrollbar.
 501:    */
 502:   public void setMinimum(int minimum)
 503:   {
 504:     model.setMinimum(minimum);
 505:   }
 506: 
 507:   /**
 508:    * This method returns the maximum value of the scrollbar.
 509:    *
 510:    * @return The maximum value of the scrollbar.
 511:    */
 512:   public int getMaximum()
 513:   {
 514:     return model.getMaximum();
 515:   }
 516: 
 517:   /**
 518:    * This method sets the maximum value of the scrollbar.
 519:    *
 520:    * @param maximum The maximum value of the scrollbar.
 521:    */
 522:   public void setMaximum(int maximum)
 523:   {
 524:     model.setMaximum(maximum);
 525:   }
 526: 
 527:   /**
 528:    * This method returns the model's isAjusting value.
 529:    *
 530:    * @return The model's isAdjusting value.
 531:    */
 532:   public boolean getValueIsAdjusting()
 533:   {
 534:     return model.getValueIsAdjusting();
 535:   }
 536: 
 537:   /**
 538:    * This method sets the model's isAdjusting value.
 539:    *
 540:    * @param b The new isAdjusting value.
 541:    */
 542:   public void setValueIsAdjusting(boolean b)
 543:   {
 544:     model.setValueIsAdjusting(b);
 545:   }
 546: 
 547:   /**
 548:    * This method sets the value, extent, minimum and
 549:    * maximum.
 550:    *
 551:    * @param newValue The new value.
 552:    * @param newExtent The new extent.
 553:    * @param newMin The new minimum.
 554:    * @param newMax The new maximum.
 555:    */
 556:   public void setValues(int newValue, int newExtent, int newMin, int newMax)
 557:   {
 558:     model.setRangeProperties(newValue, newExtent, newMin, newMax,
 559:                              model.getValueIsAdjusting());
 560:   }
 561: 
 562:   /**
 563:    * This method adds an AdjustmentListener to the scroll bar.
 564:    *
 565:    * @param listener The listener to add.
 566:    */
 567:   public void addAdjustmentListener(AdjustmentListener listener)
 568:   {
 569:     listenerList.add(AdjustmentListener.class, listener);
 570:   }
 571: 
 572:   /**
 573:    * This method removes an AdjustmentListener from the scroll bar.
 574:    *
 575:    * @param listener The listener to remove.
 576:    */
 577:   public void removeAdjustmentListener(AdjustmentListener listener)
 578:   {
 579:     listenerList.remove(AdjustmentListener.class, listener);
 580:   }
 581: 
 582:   /**
 583:    * This method returns an arry of all AdjustmentListeners listening to
 584:    * this scroll bar.
 585:    *
 586:    * @return An array of AdjustmentListeners listening to this scroll bar.
 587:    */
 588:   public AdjustmentListener[] getAdjustmentListeners()
 589:   {
 590:     return (AdjustmentListener[]) listenerList.getListeners(AdjustmentListener.class);
 591:   }
 592: 
 593:   /**
 594:    * This method is called to fired AdjustmentEvents to the listeners
 595:    * of this scroll bar. All AdjustmentEvents that are fired
 596:    * will have an ID of ADJUSTMENT_VALUE_CHANGED and a type of
 597:    * TRACK.
 598:    *
 599:    * @param id The ID of the adjustment event.
 600:    * @param type The Type of change.
 601:    * @param value The new value for the property that was changed..
 602:    */
 603:   protected void fireAdjustmentValueChanged(int id, int type, int value)
 604:   {
 605:     fireAdjustmentValueChanged(id, type, value, getValueIsAdjusting());
 606:   }
 607: 
 608:   /**
 609:    * Helper method for firing adjustment events that can have their
 610:    * isAdjusting field modified.
 611:    *
 612:    * This is package private to avoid an accessor method.
 613:    *
 614:    * @param id the ID of the event
 615:    * @param type the type of the event
 616:    * @param value the value
 617:    * @param isAdjusting if the scrollbar is adjusting or not
 618:    */
 619:   void fireAdjustmentValueChanged(int id, int type, int value,
 620:                                           boolean isAdjusting)
 621:   {
 622:     Object[] adjustmentListeners = listenerList.getListenerList();
 623:     AdjustmentEvent adjustmentEvent = new AdjustmentEvent(this, id, type,
 624:                                                           value, isAdjusting);
 625:     for (int i = adjustmentListeners.length - 2; i >= 0; i -= 2)
 626:       {
 627:         if (adjustmentListeners[i] == AdjustmentListener.class)
 628:           ((AdjustmentListener) adjustmentListeners[i + 1]).adjustmentValueChanged(adjustmentEvent);
 629:       }
 630:   }
 631: 
 632:   /**
 633:    * This method returns the minimum size for this scroll bar.
 634:    *
 635:    * @return The minimum size.
 636:    */
 637:   public Dimension getMinimumSize()
 638:   {
 639:     return ui.getMinimumSize(this);
 640:   }
 641: 
 642:   /**
 643:    * This method returns the maximum size for this scroll bar.
 644:    *
 645:    * @return The maximum size.
 646:    */
 647:   public Dimension getMaximumSize()
 648:   {
 649:     return ui.getMaximumSize(this);
 650:   }
 651: 
 652:   /**
 653:    * This method overrides the setEnabled in JComponent.
 654:    * When the scroll bar is disabled, the knob cannot
 655:    * be moved.
 656:    *
 657:    * @param x Whether the scrollbar is enabled.
 658:    */
 659:   public void setEnabled(boolean x)
 660:   {
 661:     // nothing special needs to be done here since we
 662:     // just check the enabled setting before changing the value.
 663:     super.setEnabled(x);
 664:   }
 665: 
 666:   /**
 667:    * Returns a string describing the attributes for the <code>JScrollBar</code>
 668:    * component, for use in debugging.  The return value is guaranteed to be
 669:    * non-<code>null</code>, but the format of the string may vary between
 670:    * implementations.
 671:    *
 672:    * @return A string describing the attributes of the <code>JScrollBar</code>.
 673:    */
 674:   protected String paramString()
 675:   {
 676:     CPStringBuilder sb = new CPStringBuilder(super.paramString());
 677:     sb.append(",blockIncrement=").append(blockIncrement);
 678:     sb.append(",orientation=");
 679:     if (this.orientation == JScrollBar.HORIZONTAL)
 680:       sb.append("HORIZONTAL");
 681:     else
 682:       sb.append("VERTICAL");
 683:     sb.append(",unitIncrement=").append(unitIncrement);
 684:     return sb.toString();
 685:   }
 686: 
 687:   /**
 688:    * Returns the object that provides accessibility features for this
 689:    * <code>JScrollBar</code> component.
 690:    *
 691:    * @return The accessible context (an instance of
 692:    *     {@link AccessibleJScrollBar}).
 693:    */
 694:   public AccessibleContext getAccessibleContext()
 695:   {
 696:     if (accessibleContext == null)
 697:       accessibleContext = new AccessibleJScrollBar();
 698:     return accessibleContext;
 699:   }
 700: }