1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing;
  27 
  28 import java.io.Serializable;
  29 import java.awt.Component;
  30 import java.awt.Adjustable;
  31 import java.awt.Dimension;
  32 import java.awt.event.AdjustmentListener;
  33 import java.awt.event.AdjustmentEvent;
  34 import java.awt.Graphics;
  35 
  36 import javax.swing.event.*;
  37 import javax.swing.plaf.*;
  38 import javax.accessibility.*;
  39 
  40 import java.io.ObjectOutputStream;
  41 import java.io.ObjectInputStream;
  42 import java.io.IOException;
  43 
  44 
  45 
  46 /**
  47  * An implementation of a scrollbar. The user positions the knob in the
  48  * scrollbar to determine the contents of the viewing area. The
  49  * program typically adjusts the display so that the end of the
  50  * scrollbar represents the end of the displayable contents, or 100%
  51  * of the contents. The start of the scrollbar is the beginning of the
  52  * displayable contents, or 0%. The position of the knob within
  53  * those bounds then translates to the corresponding percentage of
  54  * the displayable contents.
  55  * <p>
  56  * Typically, as the position of the knob in the scrollbar changes
  57  * a corresponding change is made to the position of the JViewport on
  58  * the underlying view, changing the contents of the JViewport.
  59  * <p>
  60  * <strong>Warning:</strong> Swing is not thread safe. For more
  61  * information see <a
  62  * href="package-summary.html#threading">Swing's Threading
  63  * Policy</a>.
  64  * <p>
  65  * <strong>Warning:</strong>
  66  * Serialized objects of this class will not be compatible with
  67  * future Swing releases. The current serialization support is
  68  * appropriate for short term storage or RMI between applications running
  69  * the same version of Swing.  As of 1.4, support for long term storage
  70  * of all JavaBeans&trade;
  71  * has been added to the <code>java.beans</code> package.
  72  * Please see {@link java.beans.XMLEncoder}.
  73  *
  74  * @see JScrollPane
  75  * @beaninfo
  76  *      attribute: isContainer false
  77  *    description: A component that helps determine the visible content range of an area.
  78  *
  79  * @author David Kloba
  80  */
  81 @SuppressWarnings("serial") // Same-version serialization only
  82 public class JScrollBar extends JComponent implements Adjustable, Accessible
  83 {
  84     /**
  85      * @see #getUIClassID
  86      * @see #readObject
  87      */
  88     private static final String uiClassID = "ScrollBarUI";
  89 
  90     /**
  91      * All changes from the model are treated as though the user moved
  92      * the scrollbar knob.
  93      */
  94     private ChangeListener fwdAdjustmentEvents = new ModelListener();
  95 
  96 
  97     /**
  98      * The model that represents the scrollbar's minimum, maximum, extent
  99      * (aka "visibleAmount") and current value.
 100      * @see #setModel
 101      */
 102     protected BoundedRangeModel model;
 103 
 104 
 105     /**
 106      * @see #setOrientation
 107      */
 108     protected int orientation;
 109 
 110 
 111     /**
 112      * @see #setUnitIncrement
 113      */
 114     protected int unitIncrement;
 115 
 116 
 117     /**
 118      * @see #setBlockIncrement
 119      */
 120     protected int blockIncrement;
 121 
 122 
 123     private void checkOrientation(int orientation) {
 124         switch (orientation) {
 125         case VERTICAL:
 126         case HORIZONTAL:
 127             break;
 128         default:
 129             throw new IllegalArgumentException("orientation must be one of: VERTICAL, HORIZONTAL");
 130         }
 131     }
 132 
 133 
 134     /**
 135      * Creates a scrollbar with the specified orientation,
 136      * value, extent, minimum, and maximum.
 137      * The "extent" is the size of the viewable area. It is also known
 138      * as the "visible amount".
 139      * <p>
 140      * Note: Use <code>setBlockIncrement</code> to set the block
 141      * increment to a size slightly smaller than the view's extent.
 142      * That way, when the user jumps the knob to an adjacent position,
 143      * one or two lines of the original contents remain in view.
 144      *
 145      * @exception IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL
 146      *
 147      * @see #setOrientation
 148      * @see #setValue
 149      * @see #setVisibleAmount
 150      * @see #setMinimum
 151      * @see #setMaximum
 152      */
 153     public JScrollBar(int orientation, int value, int extent, int min, int max)
 154     {
 155         checkOrientation(orientation);
 156         this.unitIncrement = 1;
 157         this.blockIncrement = (extent == 0) ? 1 : extent;
 158         this.orientation = orientation;
 159         this.model = new DefaultBoundedRangeModel(value, extent, min, max);
 160         this.model.addChangeListener(fwdAdjustmentEvents);
 161         setRequestFocusEnabled(false);
 162         updateUI();
 163     }
 164 
 165 
 166     /**
 167      * Creates a scrollbar with the specified orientation
 168      * and the following initial values:
 169      * <pre>
 170      * minimum = 0
 171      * maximum = 100
 172      * value = 0
 173      * extent = 10
 174      * </pre>
 175      */
 176     public JScrollBar(int orientation) {
 177         this(orientation, 0, 10, 0, 100);
 178     }
 179 
 180 
 181     /**
 182      * Creates a vertical scrollbar with the following initial values:
 183      * <pre>
 184      * minimum = 0
 185      * maximum = 100
 186      * value = 0
 187      * extent = 10
 188      * </pre>
 189      */
 190     public JScrollBar() {
 191         this(VERTICAL);
 192     }
 193 
 194 
 195     /**
 196      * Sets the {@literal L&F} object that renders this component.
 197      *
 198      * @param ui  the <code>ScrollBarUI</code> {@literal L&F} object
 199      * @see UIDefaults#getUI
 200      * @since 1.4
 201      * @beaninfo
 202      *        bound: true
 203      *       hidden: true
 204      *    attribute: visualUpdate true
 205      *  description: The UI object that implements the Component's LookAndFeel
 206      */
 207     public void setUI(ScrollBarUI ui) {
 208         super.setUI(ui);
 209     }
 210 
 211 
 212     /**
 213      * Returns the delegate that implements the look and feel for
 214      * this component.
 215      *
 216      * @see JComponent#setUI
 217      */
 218     public ScrollBarUI getUI() {
 219         return (ScrollBarUI)ui;
 220     }
 221 
 222 
 223     /**
 224      * Overrides <code>JComponent.updateUI</code>.
 225      * @see JComponent#updateUI
 226      */
 227     public void updateUI() {
 228         setUI((ScrollBarUI)UIManager.getUI(this));
 229     }
 230 
 231 
 232     /**
 233      * Returns the name of the LookAndFeel class for this component.
 234      *
 235      * @return "ScrollBarUI"
 236      * @see JComponent#getUIClassID
 237      * @see UIDefaults#getUI
 238      */
 239     public String getUIClassID() {
 240         return uiClassID;
 241     }
 242 
 243 
 244 
 245     /**
 246      * Returns the component's orientation (horizontal or vertical).
 247      *
 248      * @return VERTICAL or HORIZONTAL
 249      * @see #setOrientation
 250      * @see java.awt.Adjustable#getOrientation
 251      */
 252     public int getOrientation() {
 253         return orientation;
 254     }
 255 
 256 
 257     /**
 258      * Set the scrollbar's orientation to either VERTICAL or
 259      * HORIZONTAL.
 260      *
 261      * @exception IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL
 262      * @see #getOrientation
 263      * @beaninfo
 264      *    preferred: true
 265      *        bound: true
 266      *    attribute: visualUpdate true
 267      *  description: The scrollbar's orientation.
 268      *         enum: VERTICAL JScrollBar.VERTICAL
 269      *               HORIZONTAL JScrollBar.HORIZONTAL
 270      */
 271     public void setOrientation(int orientation)
 272     {
 273         checkOrientation(orientation);
 274         int oldValue = this.orientation;
 275         this.orientation = orientation;
 276         firePropertyChange("orientation", oldValue, orientation);
 277 
 278         if ((oldValue != orientation) && (accessibleContext != null)) {
 279             accessibleContext.firePropertyChange(
 280                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 281                     ((oldValue == VERTICAL)
 282                      ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL),
 283                     ((orientation == VERTICAL)
 284                      ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL));
 285         }
 286         if (orientation != oldValue) {
 287             revalidate();
 288         }
 289     }
 290 
 291 
 292     /**
 293      * Returns data model that handles the scrollbar's four
 294      * fundamental properties: minimum, maximum, value, extent.
 295      *
 296      * @see #setModel
 297      */
 298     public BoundedRangeModel getModel() {
 299         return model;
 300     }
 301 
 302 
 303     /**
 304      * Sets the model that handles the scrollbar's four
 305      * fundamental properties: minimum, maximum, value, extent.
 306      *
 307      * @see #getModel
 308      * @beaninfo
 309      *       bound: true
 310      *       expert: true
 311      * description: The scrollbar's BoundedRangeModel.
 312      */
 313     public void setModel(BoundedRangeModel newModel) {
 314         Integer oldValue = null;
 315         BoundedRangeModel oldModel = model;
 316         if (model != null) {
 317             model.removeChangeListener(fwdAdjustmentEvents);
 318             oldValue = Integer.valueOf(model.getValue());
 319         }
 320         model = newModel;
 321         if (model != null) {
 322             model.addChangeListener(fwdAdjustmentEvents);
 323         }
 324 
 325         firePropertyChange("model", oldModel, model);
 326 
 327         if (accessibleContext != null) {
 328             accessibleContext.firePropertyChange(
 329                     AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
 330                     oldValue, new Integer(model.getValue()));
 331         }
 332     }
 333 
 334 
 335     /**
 336      * Returns the amount to change the scrollbar's value by,
 337      * given a unit up/down request.  A ScrollBarUI implementation
 338      * typically calls this method when the user clicks on a scrollbar
 339      * up/down arrow and uses the result to update the scrollbar's
 340      * value.   Subclasses my override this method to compute
 341      * a value, e.g. the change required to scroll up or down one
 342      * (variable height) line text or one row in a table.
 343      * <p>
 344      * The JScrollPane component creates scrollbars (by default)
 345      * that override this method and delegate to the viewports
 346      * Scrollable view, if it has one.  The Scrollable interface
 347      * provides a more specialized version of this method.
 348      * <p>
 349      * Some look and feels implement custom scrolling behavior
 350      * and ignore this property.
 351      *
 352      * @param direction is -1 or 1 for up/down respectively
 353      * @return the value of the unitIncrement property
 354      * @see #setUnitIncrement
 355      * @see #setValue
 356      * @see Scrollable#getScrollableUnitIncrement
 357      */
 358     public int getUnitIncrement(int direction) {
 359         return unitIncrement;
 360     }
 361 
 362 
 363     /**
 364      * Sets the unitIncrement property.
 365      * <p>
 366      * Note, that if the argument is equal to the value of Integer.MIN_VALUE,
 367      * the most look and feels will not provide the scrolling to the right/down.
 368      * <p>
 369      * Some look and feels implement custom scrolling behavior
 370      * and ignore this property.
 371      *
 372      * @see #getUnitIncrement
 373      * @beaninfo
 374      *   preferred: true
 375      *       bound: true
 376      * description: The scrollbar's unit increment.
 377      */
 378     public void setUnitIncrement(int unitIncrement) {
 379         int oldValue = this.unitIncrement;
 380         this.unitIncrement = unitIncrement;
 381         firePropertyChange("unitIncrement", oldValue, unitIncrement);
 382     }
 383 
 384 
 385     /**
 386      * Returns the amount to change the scrollbar's value by,
 387      * given a block (usually "page") up/down request.  A ScrollBarUI
 388      * implementation typically calls this method when the user clicks
 389      * above or below the scrollbar "knob" to change the value
 390      * up or down by large amount.  Subclasses my override this
 391      * method to compute a value, e.g. the change required to scroll
 392      * up or down one paragraph in a text document.
 393      * <p>
 394      * The JScrollPane component creates scrollbars (by default)
 395      * that override this method and delegate to the viewports
 396      * Scrollable view, if it has one.  The Scrollable interface
 397      * provides a more specialized version of this method.
 398      * <p>
 399      * Some look and feels implement custom scrolling behavior
 400      * and ignore this property.
 401      *
 402      * @param direction is -1 or 1 for up/down respectively
 403      * @return the value of the blockIncrement property
 404      * @see #setBlockIncrement
 405      * @see #setValue
 406      * @see Scrollable#getScrollableBlockIncrement
 407      */
 408     public int getBlockIncrement(int direction) {
 409         return blockIncrement;
 410     }
 411 
 412 
 413     /**
 414      * Sets the blockIncrement property.
 415      * <p>
 416      * Note, that if the argument is equal to the value of Integer.MIN_VALUE,
 417      * the most look and feels will not provide the scrolling to the right/down.
 418      * <p>
 419      * Some look and feels implement custom scrolling behavior
 420      * and ignore this property.
 421      *
 422      * @see #getBlockIncrement()
 423      * @beaninfo
 424      *   preferred: true
 425      *       bound: true
 426      * description: The scrollbar's block increment.
 427      */
 428     public void setBlockIncrement(int blockIncrement) {
 429         int oldValue = this.blockIncrement;
 430         this.blockIncrement = blockIncrement;
 431         firePropertyChange("blockIncrement", oldValue, blockIncrement);
 432     }
 433 
 434 
 435     /**
 436      * For backwards compatibility with java.awt.Scrollbar.
 437      * @see Adjustable#getUnitIncrement
 438      * @see #getUnitIncrement(int)
 439      */
 440     public int getUnitIncrement() {
 441         return unitIncrement;
 442     }
 443 
 444 
 445     /**
 446      * For backwards compatibility with java.awt.Scrollbar.
 447      * @see Adjustable#getBlockIncrement
 448      * @see #getBlockIncrement(int)
 449      */
 450     public int getBlockIncrement() {
 451         return blockIncrement;
 452     }
 453 
 454 
 455     /**
 456      * Returns the scrollbar's value.
 457      * @return the model's value property
 458      * @see #setValue
 459      */
 460     public int getValue() {
 461         return getModel().getValue();
 462     }
 463 
 464 
 465     /**
 466      * Sets the scrollbar's value.  This method just forwards the value
 467      * to the model.
 468      *
 469      * @see #getValue
 470      * @see BoundedRangeModel#setValue
 471      * @beaninfo
 472      *   preferred: true
 473      * description: The scrollbar's current value.
 474      */
 475     public void setValue(int value) {
 476         BoundedRangeModel m = getModel();
 477         int oldValue = m.getValue();
 478         m.setValue(value);
 479 
 480         if (accessibleContext != null) {
 481             accessibleContext.firePropertyChange(
 482                     AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
 483                     Integer.valueOf(oldValue),
 484                     Integer.valueOf(m.getValue()));
 485         }
 486     }
 487 
 488 
 489     /**
 490      * Returns the scrollbar's extent, aka its "visibleAmount".  In many
 491      * scrollbar look and feel implementations the size of the
 492      * scrollbar "knob" or "thumb" is proportional to the extent.
 493      *
 494      * @return the value of the model's extent property
 495      * @see #setVisibleAmount
 496      */
 497     public int getVisibleAmount() {
 498         return getModel().getExtent();
 499     }
 500 
 501 
 502     /**
 503      * Set the model's extent property.
 504      *
 505      * @see #getVisibleAmount
 506      * @see BoundedRangeModel#setExtent
 507      * @beaninfo
 508      *   preferred: true
 509      * description: The amount of the view that is currently visible.
 510      */
 511     public void setVisibleAmount(int extent) {
 512         getModel().setExtent(extent);
 513     }
 514 
 515 
 516     /**
 517      * Returns the minimum value supported by the scrollbar
 518      * (usually zero).
 519      *
 520      * @return the value of the model's minimum property
 521      * @see #setMinimum
 522      */
 523     public int getMinimum() {
 524         return getModel().getMinimum();
 525     }
 526 
 527 
 528     /**
 529      * Sets the model's minimum property.
 530      *
 531      * @see #getMinimum
 532      * @see BoundedRangeModel#setMinimum
 533      * @beaninfo
 534      *   preferred: true
 535      * description: The scrollbar's minimum value.
 536      */
 537     public void setMinimum(int minimum) {
 538         getModel().setMinimum(minimum);
 539     }
 540 
 541 
 542     /**
 543      * The maximum value of the scrollbar is maximum - extent.
 544      *
 545      * @return the value of the model's maximum property
 546      * @see #setMaximum
 547      */
 548     public int getMaximum() {
 549         return getModel().getMaximum();
 550     }
 551 
 552 
 553     /**
 554      * Sets the model's maximum property.  Note that the scrollbar's value
 555      * can only be set to maximum - extent.
 556      *
 557      * @see #getMaximum
 558      * @see BoundedRangeModel#setMaximum
 559      * @beaninfo
 560      *   preferred: true
 561      * description: The scrollbar's maximum value.
 562      */
 563     public void setMaximum(int maximum) {
 564         getModel().setMaximum(maximum);
 565     }
 566 
 567 
 568     /**
 569      * True if the scrollbar knob is being dragged.
 570      *
 571      * @return the value of the model's valueIsAdjusting property
 572      * @see #setValueIsAdjusting
 573      */
 574     public boolean getValueIsAdjusting() {
 575         return getModel().getValueIsAdjusting();
 576     }
 577 
 578 
 579     /**
 580      * Sets the model's valueIsAdjusting property.  Scrollbar look and
 581      * feel implementations should set this property to true when
 582      * a knob drag begins, and to false when the drag ends.  The
 583      * scrollbar model will not generate ChangeEvents while
 584      * valueIsAdjusting is true.
 585      *
 586      * @see #getValueIsAdjusting
 587      * @see BoundedRangeModel#setValueIsAdjusting
 588      * @beaninfo
 589      *      expert: true
 590      * description: True if the scrollbar thumb is being dragged.
 591      */
 592     public void setValueIsAdjusting(boolean b) {
 593         BoundedRangeModel m = getModel();
 594         boolean oldValue = m.getValueIsAdjusting();
 595         m.setValueIsAdjusting(b);
 596 
 597         if ((oldValue != b) && (accessibleContext != null)) {
 598             accessibleContext.firePropertyChange(
 599                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 600                     ((oldValue) ? AccessibleState.BUSY : null),
 601                     ((b) ? AccessibleState.BUSY : null));
 602         }
 603     }
 604 
 605 
 606     /**
 607      * Sets the four BoundedRangeModel properties after forcing
 608      * the arguments to obey the usual constraints:
 609      * <pre>
 610      * minimum &le; value &le; value+extent &le; maximum
 611      * </pre>
 612      *
 613      *
 614      * @see BoundedRangeModel#setRangeProperties
 615      * @see #setValue
 616      * @see #setVisibleAmount
 617      * @see #setMinimum
 618      * @see #setMaximum
 619      */
 620     public void setValues(int newValue, int newExtent, int newMin, int newMax)
 621     {
 622         BoundedRangeModel m = getModel();
 623         int oldValue = m.getValue();
 624         m.setRangeProperties(newValue, newExtent, newMin, newMax, m.getValueIsAdjusting());
 625 
 626         if (accessibleContext != null) {
 627             accessibleContext.firePropertyChange(
 628                     AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
 629                     Integer.valueOf(oldValue),
 630                     Integer.valueOf(m.getValue()));
 631         }
 632     }
 633 
 634 
 635     /**
 636      * Adds an AdjustmentListener.  Adjustment listeners are notified
 637      * each time the scrollbar's model changes.  Adjustment events are
 638      * provided for backwards compatibility with java.awt.Scrollbar.
 639      * <p>
 640      * Note that the AdjustmentEvents type property will always have a
 641      * placeholder value of AdjustmentEvent.TRACK because all changes
 642      * to a BoundedRangeModels value are considered equivalent.  To change
 643      * the value of a BoundedRangeModel one just sets its value property,
 644      * i.e. model.setValue(123).  No information about the origin of the
 645      * change, e.g. it's a block decrement, is provided.  We don't try
 646      * fabricate the origin of the change here.
 647      *
 648      * @param l the AdjustmentLister to add
 649      * @see #removeAdjustmentListener
 650      * @see BoundedRangeModel#addChangeListener
 651      */
 652     public void addAdjustmentListener(AdjustmentListener l)   {
 653         listenerList.add(AdjustmentListener.class, l);
 654     }
 655 
 656 
 657     /**
 658      * Removes an AdjustmentEvent listener.
 659      *
 660      * @param l the AdjustmentLister to remove
 661      * @see #addAdjustmentListener
 662      */
 663     public void removeAdjustmentListener(AdjustmentListener l)  {
 664         listenerList.remove(AdjustmentListener.class, l);
 665     }
 666 
 667 
 668     /**
 669      * Returns an array of all the <code>AdjustmentListener</code>s added
 670      * to this JScrollBar with addAdjustmentListener().
 671      *
 672      * @return all of the <code>AdjustmentListener</code>s added or an empty
 673      *         array if no listeners have been added
 674      * @since 1.4
 675      */
 676     public AdjustmentListener[] getAdjustmentListeners() {
 677         return listenerList.getListeners(AdjustmentListener.class);
 678     }
 679 
 680 
 681     /**
 682      * Notify listeners that the scrollbar's model has changed.
 683      *
 684      * @see #addAdjustmentListener
 685      * @see EventListenerList
 686      */
 687     protected void fireAdjustmentValueChanged(int id, int type, int value) {
 688         fireAdjustmentValueChanged(id, type, value, getValueIsAdjusting());
 689     }
 690 
 691     /**
 692      * Notify listeners that the scrollbar's model has changed.
 693      *
 694      * @see #addAdjustmentListener
 695      * @see EventListenerList
 696      */
 697     private void fireAdjustmentValueChanged(int id, int type, int value,
 698                                             boolean isAdjusting) {
 699         Object[] listeners = listenerList.getListenerList();
 700         AdjustmentEvent e = null;
 701         for (int i = listeners.length - 2; i >= 0; i -= 2) {
 702             if (listeners[i]==AdjustmentListener.class) {
 703                 if (e == null) {
 704                     e = new AdjustmentEvent(this, id, type, value, isAdjusting);
 705                 }
 706                 ((AdjustmentListener)listeners[i+1]).adjustmentValueChanged(e);
 707             }
 708         }
 709     }
 710 
 711 
 712     /**
 713      * This class listens to ChangeEvents on the model and forwards
 714      * AdjustmentEvents for the sake of backwards compatibility.
 715      * Unfortunately there's no way to determine the proper
 716      * type of the AdjustmentEvent as all updates to the model's
 717      * value are considered equivalent.
 718      */
 719     private class ModelListener implements ChangeListener, Serializable {
 720         public void stateChanged(ChangeEvent e)   {
 721             Object obj = e.getSource();
 722             if (obj instanceof BoundedRangeModel) {
 723                 int id = AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED;
 724                 int type = AdjustmentEvent.TRACK;
 725                 BoundedRangeModel model = (BoundedRangeModel)obj;
 726                 int value = model.getValue();
 727                 boolean isAdjusting = model.getValueIsAdjusting();
 728                 fireAdjustmentValueChanged(id, type, value, isAdjusting);
 729             }
 730         }
 731     }
 732 
 733     // PENDING(hmuller) - the next three methods should be removed
 734 
 735     /**
 736      * The scrollbar is flexible along it's scrolling axis and
 737      * rigid along the other axis.
 738      */
 739     public Dimension getMinimumSize() {
 740         Dimension pref = getPreferredSize();
 741         if (orientation == VERTICAL) {
 742             return new Dimension(pref.width, 5);
 743         } else {
 744             return new Dimension(5, pref.height);
 745         }
 746     }
 747 
 748     /**
 749      * The scrollbar is flexible along it's scrolling axis and
 750      * rigid along the other axis.
 751      */
 752     public Dimension getMaximumSize() {
 753         Dimension pref = getPreferredSize();
 754         if (getOrientation() == VERTICAL) {
 755             return new Dimension(pref.width, Short.MAX_VALUE);
 756         } else {
 757             return new Dimension(Short.MAX_VALUE, pref.height);
 758         }
 759     }
 760 
 761     /**
 762      * Enables the component so that the knob position can be changed.
 763      * When the disabled, the knob position cannot be changed.
 764      *
 765      * @param x a boolean value, where true enables the component and
 766      *          false disables it
 767      */
 768     public void setEnabled(boolean x)  {
 769         super.setEnabled(x);
 770         Component[] children = getComponents();
 771         for (Component child : children) {
 772             child.setEnabled(x);
 773         }
 774     }
 775 
 776     /**
 777      * See readObject() and writeObject() in JComponent for more
 778      * information about serialization in Swing.
 779      */
 780     private void writeObject(ObjectOutputStream s) throws IOException {
 781         s.defaultWriteObject();
 782         if (getUIClassID().equals(uiClassID)) {
 783             byte count = JComponent.getWriteObjCounter(this);
 784             JComponent.setWriteObjCounter(this, --count);
 785             if (count == 0 && ui != null) {
 786                 ui.installUI(this);
 787             }
 788         }
 789     }
 790 
 791 
 792     /**
 793      * Returns a string representation of this JScrollBar. This method
 794      * is intended to be used only for debugging purposes, and the
 795      * content and format of the returned string may vary between
 796      * implementations. The returned string may be empty but may not
 797      * be <code>null</code>.
 798      *
 799      * @return  a string representation of this JScrollBar.
 800      */
 801     protected String paramString() {
 802         String orientationString = (orientation == HORIZONTAL ?
 803                                     "HORIZONTAL" : "VERTICAL");
 804 
 805         return super.paramString() +
 806         ",blockIncrement=" + blockIncrement +
 807         ",orientation=" + orientationString +
 808         ",unitIncrement=" + unitIncrement;
 809     }
 810 
 811 /////////////////
 812 // Accessibility support
 813 ////////////////
 814 
 815     /**
 816      * Gets the AccessibleContext associated with this JScrollBar.
 817      * For JScrollBar, the AccessibleContext takes the form of an
 818      * AccessibleJScrollBar.
 819      * A new AccessibleJScrollBar instance is created if necessary.
 820      *
 821      * @return an AccessibleJScrollBar that serves as the
 822      *         AccessibleContext of this JScrollBar
 823      */
 824     public AccessibleContext getAccessibleContext() {
 825         if (accessibleContext == null) {
 826             accessibleContext = new AccessibleJScrollBar();
 827         }
 828         return accessibleContext;
 829     }
 830 
 831     /**
 832      * This class implements accessibility support for the
 833      * <code>JScrollBar</code> class.  It provides an implementation of the
 834      * Java Accessibility API appropriate to scroll bar user-interface
 835      * elements.
 836      * <p>
 837      * <strong>Warning:</strong>
 838      * Serialized objects of this class will not be compatible with
 839      * future Swing releases. The current serialization support is
 840      * appropriate for short term storage or RMI between applications running
 841      * the same version of Swing.  As of 1.4, support for long term storage
 842      * of all JavaBeans&trade;
 843      * has been added to the <code>java.beans</code> package.
 844      * Please see {@link java.beans.XMLEncoder}.
 845      */
 846     @SuppressWarnings("serial") // Same-version serialization only
 847     protected class AccessibleJScrollBar extends AccessibleJComponent
 848         implements AccessibleValue {
 849 
 850         /**
 851          * Get the state set of this object.
 852          *
 853          * @return an instance of AccessibleState containing the current state
 854          * of the object
 855          * @see AccessibleState
 856          */
 857         public AccessibleStateSet getAccessibleStateSet() {
 858             AccessibleStateSet states = super.getAccessibleStateSet();
 859             if (getValueIsAdjusting()) {
 860                 states.add(AccessibleState.BUSY);
 861             }
 862             if (getOrientation() == VERTICAL) {
 863                 states.add(AccessibleState.VERTICAL);
 864             } else {
 865                 states.add(AccessibleState.HORIZONTAL);
 866             }
 867             return states;
 868         }
 869 
 870         /**
 871          * Get the role of this object.
 872          *
 873          * @return an instance of AccessibleRole describing the role of the
 874          * object
 875          */
 876         public AccessibleRole getAccessibleRole() {
 877             return AccessibleRole.SCROLL_BAR;
 878         }
 879 
 880         /**
 881          * Get the AccessibleValue associated with this object.  In the
 882          * implementation of the Java Accessibility API for this class,
 883          * return this object, which is responsible for implementing the
 884          * AccessibleValue interface on behalf of itself.
 885          *
 886          * @return this object
 887          */
 888         public AccessibleValue getAccessibleValue() {
 889             return this;
 890         }
 891 
 892         /**
 893          * Get the accessible value of this object.
 894          *
 895          * @return The current value of this object.
 896          */
 897         public Number getCurrentAccessibleValue() {
 898             return Integer.valueOf(getValue());
 899         }
 900 
 901         /**
 902          * Set the value of this object as a Number.
 903          *
 904          * @return True if the value was set.
 905          */
 906         public boolean setCurrentAccessibleValue(Number n) {
 907             // TIGER - 4422535
 908             if (n == null) {
 909                 return false;
 910             }
 911             setValue(n.intValue());
 912             return true;
 913         }
 914 
 915         /**
 916          * Get the minimum accessible value of this object.
 917          *
 918          * @return The minimum value of this object.
 919          */
 920         public Number getMinimumAccessibleValue() {
 921             return Integer.valueOf(getMinimum());
 922         }
 923 
 924         /**
 925          * Get the maximum accessible value of this object.
 926          *
 927          * @return The maximum value of this object.
 928          */
 929         public Number getMaximumAccessibleValue() {
 930             // TIGER - 4422362
 931             return new Integer(model.getMaximum() - model.getExtent());
 932         }
 933 
 934     } // AccessibleJScrollBar
 935 }