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