1 /*
2  * Copyright (c) 1995, 2019, 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 java.awt;
26 
27 import java.awt.peer.ScrollbarPeer;
28 import java.awt.event.*;
29 import java.util.EventListener;
30 import java.io.ObjectOutputStream;
31 import java.io.ObjectInputStream;
32 import java.io.IOException;
33 import javax.accessibility.*;
34 
35 
36 /**
37  * The {@code Scrollbar} class embodies a scroll bar, a
38  * familiar user-interface object. A scroll bar provides a
39  * convenient means for allowing a user to select from a
40  * range of values. The following three vertical
41  * scroll bars could be used as slider controls to pick
42  * the red, green, and blue components of a color:
43  * <p>
44  * <img src="doc-files/Scrollbar-1.gif" alt="Image shows 3 vertical sliders,
45  * side-by-side." style="margin: 7px 10px;">
46  * <p>
47  * Each scroll bar in this example could be created with
48  * code similar to the following:
49  *
50  * <hr><blockquote><pre>
51  * redSlider=new Scrollbar(Scrollbar.VERTICAL, 0, 1, 0, 255);
52  * add(redSlider);
53  * </pre></blockquote><hr>
54  * <p>
55  * Alternatively, a scroll bar can represent a range of values. For
56  * example, if a scroll bar is used for scrolling through text, the
57  * width of the "bubble" (also called the "thumb" or "scroll box")
58  * can be used to represent the amount of text that is visible.
59  * Here is an example of a scroll bar that represents a range:
60  * <p>
61  * <img src="doc-files/Scrollbar-2.gif"
62  * alt="Image shows horizontal slider with starting range of 0 and ending range
63  * of 300. The slider thumb is labeled 60." style="margin: 7px 10px;">
64  * <p>
65  * The value range represented by the bubble in this example
66  * is the <em>visible amount</em>. The horizontal scroll bar
67  * in this example could be created with code like the following:
68  *
69  * <hr><blockquote><pre>
70  * ranger = new Scrollbar(Scrollbar.HORIZONTAL, 0, 60, 0, 300);
71  * add(ranger);
72  * </pre></blockquote><hr>
73  * <p>
74  * Note that the actual maximum value of the scroll bar is the
75  * {@code maximum} minus the {@code visible amount}.
76  * In the previous example, because the {@code maximum} is
77  * 300 and the {@code visible amount} is 60, the actual maximum
78  * value is 240.  The range of the scrollbar track is 0 - 300.
79  * The left side of the bubble indicates the value of the
80  * scroll bar.
81  * <p>
82  * Normally, the user changes the value of the scroll bar by
83  * making a gesture with the mouse. For example, the user can
84  * drag the scroll bar's bubble up and down, or click in the
85  * scroll bar's unit increment or block increment areas. Keyboard
86  * gestures can also be mapped to the scroll bar. By convention,
87  * the <b>Page&nbsp;Up</b> and <b>Page&nbsp;Down</b>
88  * keys are equivalent to clicking in the scroll bar's block
89  * increment and block decrement areas.
90  * <p>
91  * When the user changes the value of the scroll bar, the scroll bar
92  * receives an instance of {@code AdjustmentEvent}.
93  * The scroll bar processes this event, passing it along to
94  * any registered listeners.
95  * <p>
96  * Any object that wishes to be notified of changes to the
97  * scroll bar's value should implement
98  * {@code AdjustmentListener}, an interface defined in
99  * the package {@code java.awt.event}.
100  * Listeners can be added and removed dynamically by calling
101  * the methods {@code addAdjustmentListener} and
102  * {@code removeAdjustmentListener}.
103  * <p>
104  * The {@code AdjustmentEvent} class defines five types
105  * of adjustment event, listed here:
106  *
107  * <ul>
108  * <li>{@code AdjustmentEvent.TRACK} is sent out when the
109  * user drags the scroll bar's bubble.
110  * <li>{@code AdjustmentEvent.UNIT_INCREMENT} is sent out
111  * when the user clicks in the left arrow of a horizontal scroll
112  * bar, or the top arrow of a vertical scroll bar, or makes the
113  * equivalent gesture from the keyboard.
114  * <li>{@code AdjustmentEvent.UNIT_DECREMENT} is sent out
115  * when the user clicks in the right arrow of a horizontal scroll
116  * bar, or the bottom arrow of a vertical scroll bar, or makes the
117  * equivalent gesture from the keyboard.
118  * <li>{@code AdjustmentEvent.BLOCK_INCREMENT} is sent out
119  * when the user clicks in the track, to the left of the bubble
120  * on a horizontal scroll bar, or above the bubble on a vertical
121  * scroll bar. By convention, the <b>Page&nbsp;Up</b>
122  * key is equivalent, if the user is using a keyboard that
123  * defines a <b>Page&nbsp;Up</b> key.
124  * <li>{@code AdjustmentEvent.BLOCK_DECREMENT} is sent out
125  * when the user clicks in the track, to the right of the bubble
126  * on a horizontal scroll bar, or below the bubble on a vertical
127  * scroll bar. By convention, the <b>Page&nbsp;Down</b>
128  * key is equivalent, if the user is using a keyboard that
129  * defines a <b>Page&nbsp;Down</b> key.
130  * </ul>
131  * <p>
132  * The JDK&nbsp;1.0 event system is supported for backwards
133  * compatibility, but its use with newer versions of the platform is
134  * discouraged. The five types of adjustment events introduced
135  * with JDK&nbsp;1.1 correspond to the five event types
136  * that are associated with scroll bars in previous platform versions.
137  * The following list gives the adjustment event type,
138  * and the corresponding JDK&nbsp;1.0 event type it replaces.
139  *
140  * <ul>
141  * <li>{@code AdjustmentEvent.TRACK} replaces
142  * {@code Event.SCROLL_ABSOLUTE}
143  * <li>{@code AdjustmentEvent.UNIT_INCREMENT} replaces
144  * {@code Event.SCROLL_LINE_UP}
145  * <li>{@code AdjustmentEvent.UNIT_DECREMENT} replaces
146  * {@code Event.SCROLL_LINE_DOWN}
147  * <li>{@code AdjustmentEvent.BLOCK_INCREMENT} replaces
148  * {@code Event.SCROLL_PAGE_UP}
149  * <li>{@code AdjustmentEvent.BLOCK_DECREMENT} replaces
150  * {@code Event.SCROLL_PAGE_DOWN}
151  * </ul>
152  * <p>
153  * <b>Note</b>: We recommend using a {@code Scrollbar}
154  * for value selection only.  If you want to implement
155  * a scrollable component inside a container, we recommend you use
156  * a {@link ScrollPane ScrollPane}. If you use a
157  * {@code Scrollbar} for this purpose, you are likely to
158  * encounter issues with painting, key handling, sizing and
159  * positioning.
160  *
161  * @author      Sami Shaio
162  * @see         java.awt.event.AdjustmentEvent
163  * @see         java.awt.event.AdjustmentListener
164  * @since       1.0
165  */
166 public class Scrollbar extends Component implements Adjustable, Accessible {
167 
168     /**
169      * A constant that indicates a horizontal scroll bar.
170      */
171     public static final int     HORIZONTAL = 0;
172 
173     /**
174      * A constant that indicates a vertical scroll bar.
175      */
176     public static final int     VERTICAL   = 1;
177 
178     /**
179      * The value of the {@code Scrollbar}.
180      * This property must be greater than or equal to {@code minimum}
181      * and less than or equal to
182      * {@code maximum - visibleAmount}
183      *
184      * @serial
185      * @see #getValue
186      * @see #setValue
187      */
188     int value;
189 
190     /**
191      * The maximum value of the {@code Scrollbar}.
192      * This value must be greater than the {@code minimum}
193      * value.<br>
194      *
195      * @serial
196      * @see #getMaximum
197      * @see #setMaximum
198      */
199     int maximum;
200 
201     /**
202      * The minimum value of the {@code Scrollbar}.
203      * This value must be less than the {@code maximum}
204      * value.<br>
205      *
206      * @serial
207      * @see #getMinimum
208      * @see #setMinimum
209      */
210     int minimum;
211 
212     /**
213      * The size of the {@code Scrollbar}'s bubble.
214      * When a scroll bar is used to select a range of values,
215      * the visibleAmount represents the size of this range.
216      * Depending on platform, this may be visually indicated
217      * by the size of the bubble.
218      *
219      * @serial
220      * @see #getVisibleAmount
221      * @see #setVisibleAmount
222      */
223     int visibleAmount;
224 
225     /**
226      * The {@code Scrollbar}'s orientation--being either horizontal
227      * or vertical.
228      * This value should be specified when the scrollbar is created.<BR>
229      * orientation can be either : {@code VERTICAL} or
230      * {@code HORIZONTAL} only.
231      *
232      * @serial
233      * @see #getOrientation
234      * @see #setOrientation
235      */
236     int orientation;
237 
238     /**
239      * The amount by which the scrollbar value will change when going
240      * up or down by a line.
241      * This value must be greater than zero.
242      *
243      * @serial
244      * @see #getLineIncrement
245      * @see #setLineIncrement
246      */
247     int lineIncrement = 1;
248 
249     /**
250      * The amount by which the scrollbar value will change when going
251      * up or down by a page.
252      * This value must be greater than zero.
253      *
254      * @serial
255      * @see #getPageIncrement
256      * @see #setPageIncrement
257      */
258     int pageIncrement = 10;
259 
260     /**
261      * The adjusting status of the {@code Scrollbar}.
262      * True if the value is in the process of changing as a result of
263      * actions being taken by the user.
264      *
265      * @see #getValueIsAdjusting
266      * @see #setValueIsAdjusting
267      * @since 1.4
268      */
269     transient boolean isAdjusting;
270 
271     transient AdjustmentListener adjustmentListener;
272 
273     private static final String base = "scrollbar";
274     private static int nameCounter = 0;
275 
276     /*
277      * JDK 1.1 serialVersionUID
278      */
279     private static final long serialVersionUID = 8451667562882310543L;
280 
281     /**
282      * Initialize JNI field and method IDs.
283      */
initIDs()284     private static native void initIDs();
285 
286     static {
287         /* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries()288         Toolkit.loadLibraries();
289         if (!GraphicsEnvironment.isHeadless()) {
initIDs()290             initIDs();
291         }
292     }
293 
294     /**
295      * Constructs a new vertical scroll bar.
296      * The default properties of the scroll bar are listed in
297      * the following table:
298      *
299      * <table class="striped">
300      * <caption>Scrollbar default properties</caption>
301      * <thead>
302      *   <tr>
303      *     <th scope="col">Property
304      *     <th scope="col">Description
305      *     <th scope="col">Default Value
306      * </thead>
307      * <tbody>
308      *   <tr>
309      *     <th scope="row">orientation
310      *     <td>indicates whether the scroll bar is vertical or horizontal
311      *     <td>{@code Scrollbar.VERTICAL}
312      *   <tr>
313      *     <th scope="row">value
314      *     <td>value which controls the location of the scroll bar's bubble
315      *     <td>0
316      *   <tr>
317      *     <th scope="row">visible amount
318      *     <td>visible amount of the scroll bar's range, typically represented
319      *     by the size of the scroll bar's bubble
320      *     <td>10
321      *   <tr>
322      *     <th scope="row">minimum
323      *     <td>minimum value of the scroll bar
324      *     <td>0
325      *   <tr>
326      *     <th scope="row">maximum
327      *     <td>maximum value of the scroll bar
328      *     <td>100
329      *   <tr>
330      *     <th scope="row">unit increment
331      *     <td>amount the value changes when the Line Up or Line Down key is
332      *     pressed, or when the end arrows of the scrollbar are clicked
333      *     <td>1
334      *   <tr>
335      *     <th scope="row">block increment
336      *     <td>amount the value changes when the Page Up or Page Down key is
337      *     pressed, or when the scrollbar track is clicked<br>on either side of
338      *     the bubble
339      *     <td>10
340      * </tbody>
341      * </table>
342      *
343      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
344      * returns true.
345      * @see java.awt.GraphicsEnvironment#isHeadless
346      */
Scrollbar()347     public Scrollbar() throws HeadlessException {
348         this(VERTICAL, 0, 10, 0, 100);
349     }
350 
351     /**
352      * Constructs a new scroll bar with the specified orientation.
353      * <p>
354      * The {@code orientation} argument must take one of the two
355      * values {@code Scrollbar.HORIZONTAL},
356      * or {@code Scrollbar.VERTICAL},
357      * indicating a horizontal or vertical scroll bar, respectively.
358      *
359      * @param       orientation   indicates the orientation of the scroll bar
360      * @exception   IllegalArgumentException    when an illegal value for
361      *                    the {@code orientation} argument is supplied
362      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
363      * returns true.
364      * @see java.awt.GraphicsEnvironment#isHeadless
365      */
Scrollbar(int orientation)366     public Scrollbar(int orientation) throws HeadlessException {
367         this(orientation, 0, 10, 0, 100);
368     }
369 
370     /**
371      * Constructs a new scroll bar with the specified orientation,
372      * initial value, visible amount, and minimum and maximum values.
373      * <p>
374      * The {@code orientation} argument must take one of the two
375      * values {@code Scrollbar.HORIZONTAL},
376      * or {@code Scrollbar.VERTICAL},
377      * indicating a horizontal or vertical scroll bar, respectively.
378      * <p>
379      * The parameters supplied to this constructor are subject to the
380      * constraints described in {@link #setValues(int, int, int, int)}.
381      *
382      * @param     orientation   indicates the orientation of the scroll bar.
383      * @param     value     the initial value of the scroll bar
384      * @param     visible   the visible amount of the scroll bar, typically
385      *                      represented by the size of the bubble
386      * @param     minimum   the minimum value of the scroll bar
387      * @param     maximum   the maximum value of the scroll bar
388      * @exception IllegalArgumentException    when an illegal value for
389      *                    the {@code orientation} argument is supplied
390      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
391      * returns true.
392      * @see #setValues
393      * @see java.awt.GraphicsEnvironment#isHeadless
394      */
Scrollbar(int orientation, int value, int visible, int minimum, int maximum)395     public Scrollbar(int orientation, int value, int visible, int minimum,
396         int maximum) throws HeadlessException {
397         GraphicsEnvironment.checkHeadless();
398         switch (orientation) {
399           case HORIZONTAL:
400           case VERTICAL:
401             this.orientation = orientation;
402             break;
403           default:
404             throw new IllegalArgumentException("illegal scrollbar orientation");
405         }
406         setValues(value, visible, minimum, maximum);
407     }
408 
409     /**
410      * Constructs a name for this component.  Called by {@code getName}
411      * when the name is {@code null}.
412      */
constructComponentName()413     String constructComponentName() {
414         synchronized (Scrollbar.class) {
415             return base + nameCounter++;
416         }
417     }
418 
419     /**
420      * Creates the {@code Scrollbar}'s peer.  The peer allows you to modify
421      * the appearance of the {@code Scrollbar} without changing any of its
422      * functionality.
423      */
addNotify()424     public void addNotify() {
425         synchronized (getTreeLock()) {
426             if (peer == null)
427                 peer = getComponentFactory().createScrollbar(this);
428             super.addNotify();
429         }
430     }
431 
432     /**
433      * Returns the orientation of this scroll bar.
434      *
435      * @return    the orientation of this scroll bar, either
436      *               {@code Scrollbar.HORIZONTAL} or
437      *               {@code Scrollbar.VERTICAL}
438      * @see       java.awt.Scrollbar#setOrientation
439      */
getOrientation()440     public int getOrientation() {
441         return orientation;
442     }
443 
444     /**
445      * Sets the orientation for this scroll bar.
446      *
447      * @param orientation  the orientation of this scroll bar, either
448      *               {@code Scrollbar.HORIZONTAL} or
449      *               {@code Scrollbar.VERTICAL}
450      * @see       java.awt.Scrollbar#getOrientation
451      * @exception   IllegalArgumentException  if the value supplied
452      *                   for {@code orientation} is not a
453      *                   legal value
454      * @since     1.1
455      */
setOrientation(int orientation)456     public void setOrientation(int orientation) {
457         synchronized (getTreeLock()) {
458             if (orientation == this.orientation) {
459                 return;
460             }
461             switch (orientation) {
462                 case HORIZONTAL:
463                 case VERTICAL:
464                     this.orientation = orientation;
465                     break;
466                 default:
467                     throw new IllegalArgumentException("illegal scrollbar orientation");
468             }
469             /* Create a new peer with the specified orientation. */
470             if (peer != null) {
471                 removeNotify();
472                 addNotify();
473                 invalidate();
474             }
475         }
476         if (accessibleContext != null) {
477             accessibleContext.firePropertyChange(
478                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
479                     ((orientation == VERTICAL)
480                      ? AccessibleState.HORIZONTAL : AccessibleState.VERTICAL),
481                     ((orientation == VERTICAL)
482                      ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL));
483         }
484     }
485 
486     /**
487      * Gets the current value of this scroll bar.
488      *
489      * @return      the current value of this scroll bar
490      * @see         java.awt.Scrollbar#getMinimum
491      * @see         java.awt.Scrollbar#getMaximum
492      */
getValue()493     public int getValue() {
494         return value;
495     }
496 
497     /**
498      * Sets the value of this scroll bar to the specified value.
499      * <p>
500      * If the value supplied is less than the current {@code minimum}
501      * or greater than the current {@code maximum - visibleAmount},
502      * then either {@code minimum} or {@code maximum - visibleAmount}
503      * is substituted, as appropriate.
504      * <p>
505      * Normally, a program should change a scroll bar's
506      * value only by calling {@code setValues}.
507      * The {@code setValues} method simultaneously
508      * and synchronously sets the minimum, maximum, visible amount,
509      * and value properties of a scroll bar, so that they are
510      * mutually consistent.
511      * <p>
512      * Calling this method does not fire an
513      * {@code AdjustmentEvent}.
514      *
515      * @param       newValue   the new value of the scroll bar
516      * @see         java.awt.Scrollbar#setValues
517      * @see         java.awt.Scrollbar#getValue
518      * @see         java.awt.Scrollbar#getMinimum
519      * @see         java.awt.Scrollbar#getMaximum
520      */
setValue(int newValue)521     public void setValue(int newValue) {
522         // Use setValues so that a consistent policy relating
523         // minimum, maximum, visible amount, and value is enforced.
524         setValues(newValue, visibleAmount, minimum, maximum);
525     }
526 
527     /**
528      * Gets the minimum value of this scroll bar.
529      *
530      * @return      the minimum value of this scroll bar
531      * @see         java.awt.Scrollbar#getValue
532      * @see         java.awt.Scrollbar#getMaximum
533      */
getMinimum()534     public int getMinimum() {
535         return minimum;
536     }
537 
538     /**
539      * Sets the minimum value of this scroll bar.
540      * <p>
541      * When {@code setMinimum} is called, the minimum value
542      * is changed, and other values (including the maximum, the
543      * visible amount, and the current scroll bar value)
544      * are changed to be consistent with the new minimum.
545      * <p>
546      * Normally, a program should change a scroll bar's minimum
547      * value only by calling {@code setValues}.
548      * The {@code setValues} method simultaneously
549      * and synchronously sets the minimum, maximum, visible amount,
550      * and value properties of a scroll bar, so that they are
551      * mutually consistent.
552      * <p>
553      * Note that setting the minimum value to {@code Integer.MAX_VALUE}
554      * will result in the new minimum value being set to
555      * {@code Integer.MAX_VALUE - 1}.
556      *
557      * @param       newMinimum   the new minimum value for this scroll bar
558      * @see         java.awt.Scrollbar#setValues
559      * @see         java.awt.Scrollbar#setMaximum
560      * @since       1.1
561      */
setMinimum(int newMinimum)562     public void setMinimum(int newMinimum) {
563         // No checks are necessary in this method since minimum is
564         // the first variable checked in the setValues function.
565 
566         // Use setValues so that a consistent policy relating
567         // minimum, maximum, visible amount, and value is enforced.
568         setValues(value, visibleAmount, newMinimum, maximum);
569     }
570 
571     /**
572      * Gets the maximum value of this scroll bar.
573      *
574      * @return      the maximum value of this scroll bar
575      * @see         java.awt.Scrollbar#getValue
576      * @see         java.awt.Scrollbar#getMinimum
577      */
getMaximum()578     public int getMaximum() {
579         return maximum;
580     }
581 
582     /**
583      * Sets the maximum value of this scroll bar.
584      * <p>
585      * When {@code setMaximum} is called, the maximum value
586      * is changed, and other values (including the minimum, the
587      * visible amount, and the current scroll bar value)
588      * are changed to be consistent with the new maximum.
589      * <p>
590      * Normally, a program should change a scroll bar's maximum
591      * value only by calling {@code setValues}.
592      * The {@code setValues} method simultaneously
593      * and synchronously sets the minimum, maximum, visible amount,
594      * and value properties of a scroll bar, so that they are
595      * mutually consistent.
596      * <p>
597      * Note that setting the maximum value to {@code Integer.MIN_VALUE}
598      * will result in the new maximum value being set to
599      * {@code Integer.MIN_VALUE + 1}.
600      *
601      * @param       newMaximum   the new maximum value
602      *                     for this scroll bar
603      * @see         java.awt.Scrollbar#setValues
604      * @see         java.awt.Scrollbar#setMinimum
605      * @since       1.1
606      */
setMaximum(int newMaximum)607     public void setMaximum(int newMaximum) {
608         // minimum is checked first in setValues, so we need to
609         // enforce minimum and maximum checks here.
610         if (newMaximum == Integer.MIN_VALUE) {
611             newMaximum = Integer.MIN_VALUE + 1;
612         }
613 
614         if (minimum >= newMaximum) {
615             minimum = newMaximum - 1;
616         }
617 
618         // Use setValues so that a consistent policy relating
619         // minimum, maximum, visible amount, and value is enforced.
620         setValues(value, visibleAmount, minimum, newMaximum);
621     }
622 
623     /**
624      * Gets the visible amount of this scroll bar.
625      * <p>
626      * When a scroll bar is used to select a range of values,
627      * the visible amount is used to represent the range of values
628      * that are currently visible.  The size of the scroll bar's
629      * bubble (also called a thumb or scroll box), usually gives a
630      * visual representation of the relationship of the visible
631      * amount to the range of the scroll bar.
632      * Note that depending on platform, the value of the visible amount property
633      * may not be visually indicated by the size of the bubble.
634      * <p>
635      * The scroll bar's bubble may not be displayed when it is not
636      * moveable (e.g. when it takes up the entire length of the
637      * scroll bar's track, or when the scroll bar is disabled).
638      * Whether the bubble is displayed or not will not affect
639      * the value returned by {@code getVisibleAmount}.
640      *
641      * @return      the visible amount of this scroll bar
642      * @see         java.awt.Scrollbar#setVisibleAmount
643      * @since       1.1
644      */
getVisibleAmount()645     public int getVisibleAmount() {
646         return getVisible();
647     }
648 
649     /**
650      * Returns the visible amount of this scroll bar.
651      *
652      * @return the visible amount of this scroll bar
653      * @deprecated As of JDK version 1.1,
654      * replaced by {@code getVisibleAmount()}.
655      */
656     @Deprecated
getVisible()657     public int getVisible() {
658         return visibleAmount;
659     }
660 
661     /**
662      * Sets the visible amount of this scroll bar.
663      * <p>
664      * When a scroll bar is used to select a range of values,
665      * the visible amount is used to represent the range of values
666      * that are currently visible.  The size of the scroll bar's
667      * bubble (also called a thumb or scroll box), usually gives a
668      * visual representation of the relationship of the visible
669      * amount to the range of the scroll bar.
670      * Note that depending on platform, the value of the visible amount property
671      * may not be visually indicated by the size of the bubble.
672      * <p>
673      * The scroll bar's bubble may not be displayed when it is not
674      * moveable (e.g. when it takes up the entire length of the
675      * scroll bar's track, or when the scroll bar is disabled).
676      * Whether the bubble is displayed or not will not affect
677      * the value returned by {@code getVisibleAmount}.
678      * <p>
679      * If the visible amount supplied is less than {@code one}
680      * or greater than the current {@code maximum - minimum},
681      * then either {@code one} or {@code maximum - minimum}
682      * is substituted, as appropriate.
683      * <p>
684      * Normally, a program should change a scroll bar's
685      * value only by calling {@code setValues}.
686      * The {@code setValues} method simultaneously
687      * and synchronously sets the minimum, maximum, visible amount,
688      * and value properties of a scroll bar, so that they are
689      * mutually consistent.
690      *
691      * @param       newAmount the new visible amount
692      * @see         java.awt.Scrollbar#getVisibleAmount
693      * @see         java.awt.Scrollbar#setValues
694      * @since       1.1
695      */
setVisibleAmount(int newAmount)696     public void setVisibleAmount(int newAmount) {
697         // Use setValues so that a consistent policy relating
698         // minimum, maximum, visible amount, and value is enforced.
699         setValues(value, newAmount, minimum, maximum);
700     }
701 
702     /**
703      * Sets the unit increment for this scroll bar.
704      * <p>
705      * The unit increment is the value that is added or subtracted
706      * when the user activates the unit increment area of the
707      * scroll bar, generally through a mouse or keyboard gesture
708      * that the scroll bar receives as an adjustment event.
709      * The unit increment must be greater than zero.
710      * Attempts to set the unit increment to a value lower than 1
711      * will result in a value of 1 being set.
712      * <p>
713      * In some operating systems, this property
714      * can be ignored by the underlying controls.
715      *
716      * @param        v  the amount by which to increment or decrement
717      *                         the scroll bar's value
718      * @see          java.awt.Scrollbar#getUnitIncrement
719      * @since        1.1
720      */
setUnitIncrement(int v)721     public void setUnitIncrement(int v) {
722         setLineIncrement(v);
723     }
724 
725     /**
726      * Sets the unit increment for this scroll bar.
727      *
728      * @param  v the increment value
729      *
730      * @deprecated As of JDK version 1.1,
731      * replaced by {@code setUnitIncrement(int)}.
732      */
733     @Deprecated
setLineIncrement(int v)734     public synchronized void setLineIncrement(int v) {
735         int tmp = (v < 1) ? 1 : v;
736 
737         if (lineIncrement == tmp) {
738             return;
739         }
740         lineIncrement = tmp;
741 
742         ScrollbarPeer peer = (ScrollbarPeer)this.peer;
743         if (peer != null) {
744             peer.setLineIncrement(lineIncrement);
745         }
746     }
747 
748     /**
749      * Gets the unit increment for this scrollbar.
750      * <p>
751      * The unit increment is the value that is added or subtracted
752      * when the user activates the unit increment area of the
753      * scroll bar, generally through a mouse or keyboard gesture
754      * that the scroll bar receives as an adjustment event.
755      * The unit increment must be greater than zero.
756      * <p>
757      * In some operating systems, this property
758      * can be ignored by the underlying controls.
759      *
760      * @return      the unit increment of this scroll bar
761      * @see         java.awt.Scrollbar#setUnitIncrement
762      * @since       1.1
763      */
getUnitIncrement()764     public int getUnitIncrement() {
765         return getLineIncrement();
766     }
767 
768     /**
769      * Returns the unit increment for this scrollbar.
770      *
771      * @return the unit increment for this scrollbar
772      * @deprecated As of JDK version 1.1,
773      * replaced by {@code getUnitIncrement()}.
774      */
775     @Deprecated
getLineIncrement()776     public int getLineIncrement() {
777         return lineIncrement;
778     }
779 
780     /**
781      * Sets the block increment for this scroll bar.
782      * <p>
783      * The block increment is the value that is added or subtracted
784      * when the user activates the block increment area of the
785      * scroll bar, generally through a mouse or keyboard gesture
786      * that the scroll bar receives as an adjustment event.
787      * The block increment must be greater than zero.
788      * Attempts to set the block increment to a value lower than 1
789      * will result in a value of 1 being set.
790      *
791      * @param        v  the amount by which to increment or decrement
792      *                         the scroll bar's value
793      * @see          java.awt.Scrollbar#getBlockIncrement
794      * @since        1.1
795      */
setBlockIncrement(int v)796     public void setBlockIncrement(int v) {
797         setPageIncrement(v);
798     }
799 
800     /**
801      * Sets the block increment for this scroll bar.
802      *
803      * @param  v the block increment
804      * @deprecated As of JDK version 1.1,
805      * replaced by {@code setBlockIncrement()}.
806      */
807     @Deprecated
setPageIncrement(int v)808     public synchronized void setPageIncrement(int v) {
809         int tmp = (v < 1) ? 1 : v;
810 
811         if (pageIncrement == tmp) {
812             return;
813         }
814         pageIncrement = tmp;
815 
816         ScrollbarPeer peer = (ScrollbarPeer)this.peer;
817         if (peer != null) {
818             peer.setPageIncrement(pageIncrement);
819         }
820     }
821 
822     /**
823      * Gets the block increment of this scroll bar.
824      * <p>
825      * The block increment is the value that is added or subtracted
826      * when the user activates the block increment area of the
827      * scroll bar, generally through a mouse or keyboard gesture
828      * that the scroll bar receives as an adjustment event.
829      * The block increment must be greater than zero.
830      *
831      * @return      the block increment of this scroll bar
832      * @see         java.awt.Scrollbar#setBlockIncrement
833      * @since       1.1
834      */
getBlockIncrement()835     public int getBlockIncrement() {
836         return getPageIncrement();
837     }
838 
839     /**
840      * Returns the block increment of this scroll bar.
841      *
842      * @return the block increment of this scroll bar
843      *
844      * @deprecated As of JDK version 1.1,
845      * replaced by {@code getBlockIncrement()}.
846      */
847     @Deprecated
getPageIncrement()848     public int getPageIncrement() {
849         return pageIncrement;
850     }
851 
852     /**
853      * Sets the values of four properties for this scroll bar:
854      * {@code value}, {@code visibleAmount},
855      * {@code minimum}, and {@code maximum}.
856      * If the values supplied for these properties are inconsistent
857      * or incorrect, they will be changed to ensure consistency.
858      * <p>
859      * This method simultaneously and synchronously sets the values
860      * of four scroll bar properties, assuring that the values of
861      * these properties are mutually consistent. It enforces the
862      * following constraints:
863      * {@code maximum} must be greater than {@code minimum},
864      * {@code maximum - minimum} must not be greater
865      *     than {@code Integer.MAX_VALUE},
866      * {@code visibleAmount} must be greater than zero.
867      * {@code visibleAmount} must not be greater than
868      *     {@code maximum - minimum},
869      * {@code value} must not be less than {@code minimum},
870      * and {@code value} must not be greater than
871      *     {@code maximum - visibleAmount}
872      * <p>
873      * Calling this method does not fire an
874      * {@code AdjustmentEvent}.
875      *
876      * @param      value is the position in the current window
877      * @param      visible is the visible amount of the scroll bar
878      * @param      minimum is the minimum value of the scroll bar
879      * @param      maximum is the maximum value of the scroll bar
880      * @see        #setMinimum
881      * @see        #setMaximum
882      * @see        #setVisibleAmount
883      * @see        #setValue
884      */
setValues(int value, int visible, int minimum, int maximum)885     public void setValues(int value, int visible, int minimum, int maximum) {
886         int oldValue;
887         synchronized (this) {
888             if (minimum == Integer.MAX_VALUE) {
889                 minimum = Integer.MAX_VALUE - 1;
890             }
891             if (maximum <= minimum) {
892                 maximum = minimum + 1;
893             }
894 
895             long maxMinusMin = (long) maximum - (long) minimum;
896             if (maxMinusMin > Integer.MAX_VALUE) {
897                 maxMinusMin = Integer.MAX_VALUE;
898                 maximum = minimum + (int) maxMinusMin;
899             }
900             if (visible > (int) maxMinusMin) {
901                 visible = (int) maxMinusMin;
902             }
903             if (visible < 1) {
904                 visible = 1;
905             }
906 
907             if (value < minimum) {
908                 value = minimum;
909             }
910             if (value > maximum - visible) {
911                 value = maximum - visible;
912             }
913 
914             oldValue = this.value;
915             this.value = value;
916             this.visibleAmount = visible;
917             this.minimum = minimum;
918             this.maximum = maximum;
919             ScrollbarPeer peer = (ScrollbarPeer)this.peer;
920             if (peer != null) {
921                 peer.setValues(value, visibleAmount, minimum, maximum);
922             }
923         }
924 
925         if ((oldValue != value) && (accessibleContext != null))  {
926             accessibleContext.firePropertyChange(
927                     AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
928                     Integer.valueOf(oldValue),
929                     Integer.valueOf(value));
930         }
931     }
932 
933     /**
934      * Returns true if the value is in the process of changing as a
935      * result of actions being taken by the user.
936      *
937      * @return the value of the {@code valueIsAdjusting} property
938      * @see #setValueIsAdjusting
939      * @since 1.4
940      */
getValueIsAdjusting()941     public boolean getValueIsAdjusting() {
942         return isAdjusting;
943     }
944 
945     /**
946      * Sets the {@code valueIsAdjusting} property.
947      *
948      * @param b new adjustment-in-progress status
949      * @see #getValueIsAdjusting
950      * @since 1.4
951      */
setValueIsAdjusting(boolean b)952     public void setValueIsAdjusting(boolean b) {
953         boolean oldValue;
954 
955         synchronized (this) {
956             oldValue = isAdjusting;
957             isAdjusting = b;
958         }
959 
960         if ((oldValue != b) && (accessibleContext != null)) {
961             accessibleContext.firePropertyChange(
962                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
963                     ((oldValue) ? AccessibleState.BUSY : null),
964                     ((b) ? AccessibleState.BUSY : null));
965         }
966     }
967 
968 
969 
970     /**
971      * Adds the specified adjustment listener to receive instances of
972      * {@code AdjustmentEvent} from this scroll bar.
973      * If l is {@code null}, no exception is thrown and no
974      * action is performed.
975      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
976      * >AWT Threading Issues</a> for details on AWT's threading model.
977      *
978      * @param        l the adjustment listener
979      * @see          #removeAdjustmentListener
980      * @see          #getAdjustmentListeners
981      * @see          java.awt.event.AdjustmentEvent
982      * @see          java.awt.event.AdjustmentListener
983      * @since        1.1
984      */
addAdjustmentListener(AdjustmentListener l)985     public synchronized void addAdjustmentListener(AdjustmentListener l) {
986         if (l == null) {
987             return;
988         }
989         adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l);
990         newEventsOnly = true;
991     }
992 
993     /**
994      * Removes the specified adjustment listener so that it no longer
995      * receives instances of {@code AdjustmentEvent} from this scroll bar.
996      * If l is {@code null}, no exception is thrown and no action
997      * is performed.
998      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
999      * >AWT Threading Issues</a> for details on AWT's threading model.
1000      *
1001      * @param           l    the adjustment listener
1002      * @see             #addAdjustmentListener
1003      * @see             #getAdjustmentListeners
1004      * @see             java.awt.event.AdjustmentEvent
1005      * @see             java.awt.event.AdjustmentListener
1006      * @since           1.1
1007      */
removeAdjustmentListener(AdjustmentListener l)1008     public synchronized void removeAdjustmentListener(AdjustmentListener l) {
1009         if (l == null) {
1010             return;
1011         }
1012         adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l);
1013     }
1014 
1015     /**
1016      * Returns an array of all the adjustment listeners
1017      * registered on this scrollbar.
1018      *
1019      * @return all of this scrollbar's {@code AdjustmentListener}s
1020      *         or an empty array if no adjustment
1021      *         listeners are currently registered
1022      * @see             #addAdjustmentListener
1023      * @see             #removeAdjustmentListener
1024      * @see             java.awt.event.AdjustmentEvent
1025      * @see             java.awt.event.AdjustmentListener
1026      * @since 1.4
1027      */
getAdjustmentListeners()1028     public synchronized AdjustmentListener[] getAdjustmentListeners() {
1029         return getListeners(AdjustmentListener.class);
1030     }
1031 
1032     /**
1033      * Returns an array of all the objects currently registered
1034      * as <code><em>Foo</em>Listener</code>s
1035      * upon this {@code Scrollbar}.
1036      * <code><em>Foo</em>Listener</code>s are registered using the
1037      * <code>add<em>Foo</em>Listener</code> method.
1038      * <p>
1039      * You can specify the {@code listenerType} argument
1040      * with a class literal,  such as
1041      * <code><em>Foo</em>Listener.class</code>.
1042      * For example, you can query a
1043      * {@code Scrollbar c}
1044      * for its mouse listeners with the following code:
1045      *
1046      * <pre>MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));</pre>
1047      *
1048      * If no such listeners exist, this method returns an empty array.
1049      *
1050      * @param listenerType the type of listeners requested; this parameter
1051      *          should specify an interface that descends from
1052      *          {@code java.util.EventListener}
1053      * @return an array of all objects registered as
1054      *          <code><em>Foo</em>Listener</code>s on this component,
1055      *          or an empty array if no such listeners have been added
1056      * @exception ClassCastException if {@code listenerType}
1057      *          doesn't specify a class or interface that implements
1058      *          {@code java.util.EventListener}
1059      *
1060      * @since 1.3
1061      */
getListeners(Class<T> listenerType)1062     public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
1063         EventListener l = null;
1064         if  (listenerType == AdjustmentListener.class) {
1065             l = adjustmentListener;
1066         } else {
1067             return super.getListeners(listenerType);
1068         }
1069         return AWTEventMulticaster.getListeners(l, listenerType);
1070     }
1071 
1072     // REMIND: remove when filtering is done at lower level
eventEnabled(AWTEvent e)1073     boolean eventEnabled(AWTEvent e) {
1074         if (e.id == AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED) {
1075             if ((eventMask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0 ||
1076                 adjustmentListener != null) {
1077                 return true;
1078             }
1079             return false;
1080         }
1081         return super.eventEnabled(e);
1082     }
1083 
1084     /**
1085      * Processes events on this scroll bar. If the event is an
1086      * instance of {@code AdjustmentEvent}, it invokes the
1087      * {@code processAdjustmentEvent} method.
1088      * Otherwise, it invokes its superclass's
1089      * {@code processEvent} method.
1090      * <p>Note that if the event parameter is {@code null}
1091      * the behavior is unspecified and may result in an
1092      * exception.
1093      *
1094      * @param        e the event
1095      * @see          java.awt.event.AdjustmentEvent
1096      * @see          java.awt.Scrollbar#processAdjustmentEvent
1097      * @since        1.1
1098      */
processEvent(AWTEvent e)1099     protected void processEvent(AWTEvent e) {
1100         if (e instanceof AdjustmentEvent) {
1101             processAdjustmentEvent((AdjustmentEvent)e);
1102             return;
1103         }
1104         super.processEvent(e);
1105     }
1106 
1107     /**
1108      * Processes adjustment events occurring on this
1109      * scrollbar by dispatching them to any registered
1110      * {@code AdjustmentListener} objects.
1111      * <p>
1112      * This method is not called unless adjustment events are
1113      * enabled for this component. Adjustment events are enabled
1114      * when one of the following occurs:
1115      * <ul>
1116      * <li>An {@code AdjustmentListener} object is registered
1117      * via {@code addAdjustmentListener}.
1118      * <li>Adjustment events are enabled via {@code enableEvents}.
1119      * </ul>
1120      * <p>Note that if the event parameter is {@code null}
1121      * the behavior is unspecified and may result in an
1122      * exception.
1123      *
1124      * @param       e the adjustment event
1125      * @see         java.awt.event.AdjustmentEvent
1126      * @see         java.awt.event.AdjustmentListener
1127      * @see         java.awt.Scrollbar#addAdjustmentListener
1128      * @see         java.awt.Component#enableEvents
1129      * @since       1.1
1130      */
processAdjustmentEvent(AdjustmentEvent e)1131     protected void processAdjustmentEvent(AdjustmentEvent e) {
1132         AdjustmentListener listener = adjustmentListener;
1133         if (listener != null) {
1134             listener.adjustmentValueChanged(e);
1135         }
1136     }
1137 
1138     /**
1139      * Returns a string representing the state of this {@code Scrollbar}.
1140      * This method is intended to be used only for debugging purposes, and the
1141      * content and format of the returned string may vary between
1142      * implementations. The returned string may be empty but may not be
1143      * {@code null}.
1144      *
1145      * @return      the parameter string of this scroll bar
1146      */
paramString()1147     protected String paramString() {
1148         return super.paramString() +
1149             ",val=" + value +
1150             ",vis=" + visibleAmount +
1151             ",min=" + minimum +
1152             ",max=" + maximum +
1153             ((orientation == VERTICAL) ? ",vert" : ",horz") +
1154             ",isAdjusting=" + isAdjusting;
1155     }
1156 
1157 
1158     /* Serialization support.
1159      */
1160 
1161     /**
1162      * The scroll bar's serialized Data Version.
1163      *
1164      * @serial
1165      */
1166     private int scrollbarSerializedDataVersion = 1;
1167 
1168     /**
1169      * Writes default serializable fields to stream.  Writes
1170      * a list of serializable {@code AdjustmentListeners}
1171      * as optional data. The non-serializable listeners are
1172      * detected and no attempt is made to serialize them.
1173      *
1174      * @param s the {@code ObjectOutputStream} to write
1175      * @serialData {@code null} terminated sequence of 0
1176      *   or more pairs; the pair consists of a {@code String}
1177      *   and an {@code Object}; the {@code String} indicates
1178      *   the type of object and is one of the following:
1179      *   {@code adjustmentListenerK} indicating an
1180      *     {@code AdjustmentListener} object
1181      *
1182      * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
1183      * @see java.awt.Component#adjustmentListenerK
1184      * @see #readObject(ObjectInputStream)
1185      */
writeObject(ObjectOutputStream s)1186     private void writeObject(ObjectOutputStream s)
1187       throws IOException
1188     {
1189       s.defaultWriteObject();
1190 
1191       AWTEventMulticaster.save(s, adjustmentListenerK, adjustmentListener);
1192       s.writeObject(null);
1193     }
1194 
1195     /**
1196      * Reads the {@code ObjectInputStream} and if
1197      * it isn't {@code null} adds a listener to
1198      * receive adjustment events fired by the
1199      * {@code Scrollbar}.
1200      * Unrecognized keys or values will be ignored.
1201      *
1202      * @param s the {@code ObjectInputStream} to read
1203      * @exception HeadlessException if
1204      *   {@code GraphicsEnvironment.isHeadless} returns
1205      *   {@code true}
1206      * @see java.awt.GraphicsEnvironment#isHeadless
1207      * @see #writeObject(ObjectOutputStream)
1208      */
readObject(ObjectInputStream s)1209     private void readObject(ObjectInputStream s)
1210       throws ClassNotFoundException, IOException, HeadlessException
1211     {
1212       GraphicsEnvironment.checkHeadless();
1213       s.defaultReadObject();
1214 
1215       Object keyOrNull;
1216       while(null != (keyOrNull = s.readObject())) {
1217         String key = ((String)keyOrNull).intern();
1218 
1219         if (adjustmentListenerK == key)
1220           addAdjustmentListener((AdjustmentListener)(s.readObject()));
1221 
1222         else // skip value for unrecognized key
1223           s.readObject();
1224       }
1225     }
1226 
1227 
1228 /////////////////
1229 // Accessibility support
1230 ////////////////
1231 
1232     /**
1233      * Gets the {@code AccessibleContext} associated with this
1234      * {@code Scrollbar}. For scrollbars, the
1235      * {@code AccessibleContext} takes the form of an
1236      * {@code AccessibleAWTScrollBar}. A new
1237      * {@code AccessibleAWTScrollBar} instance is created if necessary.
1238      *
1239      * @return an {@code AccessibleAWTScrollBar} that serves as the
1240      *         {@code AccessibleContext} of this {@code ScrollBar}
1241      * @since 1.3
1242      */
getAccessibleContext()1243     public AccessibleContext getAccessibleContext() {
1244         if (accessibleContext == null) {
1245             accessibleContext = new AccessibleAWTScrollBar();
1246         }
1247         return accessibleContext;
1248     }
1249 
1250     /**
1251      * This class implements accessibility support for the
1252      * {@code Scrollbar} class.  It provides an implementation of
1253      * the Java Accessibility API appropriate to scrollbar
1254      * user-interface elements.
1255      * @since 1.3
1256      */
1257     protected class AccessibleAWTScrollBar extends AccessibleAWTComponent
1258         implements AccessibleValue
1259     {
1260         /*
1261          * JDK 1.3 serialVersionUID
1262          */
1263         private static final long serialVersionUID = -344337268523697807L;
1264 
1265         /**
1266          * Get the state set of this object.
1267          *
1268          * @return an instance of {@code AccessibleState}
1269          *     containing the current state of the object
1270          * @see AccessibleState
1271          */
getAccessibleStateSet()1272         public AccessibleStateSet getAccessibleStateSet() {
1273             AccessibleStateSet states = super.getAccessibleStateSet();
1274             if (getValueIsAdjusting()) {
1275                 states.add(AccessibleState.BUSY);
1276             }
1277             if (getOrientation() == VERTICAL) {
1278                 states.add(AccessibleState.VERTICAL);
1279             } else {
1280                 states.add(AccessibleState.HORIZONTAL);
1281             }
1282             return states;
1283         }
1284 
1285         /**
1286          * Get the role of this object.
1287          *
1288          * @return an instance of {@code AccessibleRole}
1289          *     describing the role of the object
1290          */
getAccessibleRole()1291         public AccessibleRole getAccessibleRole() {
1292             return AccessibleRole.SCROLL_BAR;
1293         }
1294 
1295         /**
1296          * Get the {@code AccessibleValue} associated with this
1297          * object.  In the implementation of the Java Accessibility
1298          * API for this class, return this object, which is
1299          * responsible for implementing the
1300          * {@code AccessibleValue} interface on behalf of itself.
1301          *
1302          * @return this object
1303          */
getAccessibleValue()1304         public AccessibleValue getAccessibleValue() {
1305             return this;
1306         }
1307 
1308         /**
1309          * Get the accessible value of this object.
1310          *
1311          * @return The current value of this object.
1312          */
getCurrentAccessibleValue()1313         public Number getCurrentAccessibleValue() {
1314             return Integer.valueOf(getValue());
1315         }
1316 
1317         /**
1318          * Set the value of this object as a Number.
1319          *
1320          * @return True if the value was set.
1321          */
setCurrentAccessibleValue(Number n)1322         public boolean setCurrentAccessibleValue(Number n) {
1323             if (n instanceof Integer) {
1324                 setValue(n.intValue());
1325                 return true;
1326             } else {
1327                 return false;
1328             }
1329         }
1330 
1331         /**
1332          * Get the minimum accessible value of this object.
1333          *
1334          * @return The minimum value of this object.
1335          */
getMinimumAccessibleValue()1336         public Number getMinimumAccessibleValue() {
1337             return Integer.valueOf(getMinimum());
1338         }
1339 
1340         /**
1341          * Get the maximum accessible value of this object.
1342          *
1343          * @return The maximum value of this object.
1344          */
getMaximumAccessibleValue()1345         public Number getMaximumAccessibleValue() {
1346             return Integer.valueOf(getMaximum());
1347         }
1348 
1349     } // AccessibleAWTScrollBar
1350 
1351 }
1352