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