1/*
2 * Copyright (c) 1995, 2017, 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 */
25package java.awt;
26
27import java.awt.peer.ScrollbarPeer;
28import java.awt.event.*;
29import java.util.EventListener;
30import java.io.ObjectOutputStream;
31import java.io.ObjectInputStream;
32import java.io.IOException;
33import 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, side-by-side."
45 * style="float:center; 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 of 300. The slider thumb is labeled 60."
63 * style="float:center; 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 */
166public 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     */
284    private static native void initIDs();
285
286    static {
287        /* ensure that the necessary native libraries are loaded */
288        Toolkit.loadLibraries();
289        if (!GraphicsEnvironment.isHeadless()) {
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>Property</th>
304     *   <th>Description</th>
305     *   <th>Default Value</th>
306     * </tr>
307     * </thead>
308     * <tbody>
309     * <tr>
310     *   <td>orientation</td>
311     *   <td>indicates whether the scroll bar is vertical
312     *   <br>or horizontal</td>
313     *   <td>{@code Scrollbar.VERTICAL}</td>
314     * </tr>
315     * <tr>
316     *   <td>value</td>
317     *   <td>value which controls the location
318     *   <br>of the scroll bar's bubble</td>
319     *   <td>0</td>
320     * </tr>
321     * <tr>
322     *   <td>visible amount</td>
323     *   <td>visible amount of the scroll bar's range,
324     *   <br>typically represented by the size of the
325     *   <br>scroll bar's bubble</td>
326     *   <td>10</td>
327     * </tr>
328     * <tr>
329     *   <td>minimum</td>
330     *   <td>minimum value of the scroll bar</td>
331     *   <td>0</td>
332     * </tr>
333     * <tr>
334     *   <td>maximum</td>
335     *   <td>maximum value of the scroll bar</td>
336     *   <td>100</td>
337     * </tr>
338     * <tr>
339     *   <td>unit increment</td>
340     *   <td>amount the value changes when the
341     *   <br>Line Up or Line Down key is pressed,
342     *   <br>or when the end arrows of the scrollbar
343     *   <br>are clicked </td>
344     *   <td>1</td>
345     * </tr>
346     * <tr>
347     *   <td>block increment</td>
348     *   <td>amount the value changes when the
349     *   <br>Page Up or Page Down key is pressed,
350     *   <br>or when the scrollbar track is clicked
351     *   <br>on either side of the bubble </td>
352     *   <td>10</td>
353     * </tr>
354     * </tbody>
355     * </table>
356     *
357     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
358     * returns true.
359     * @see java.awt.GraphicsEnvironment#isHeadless
360     */
361    public Scrollbar() throws HeadlessException {
362        this(VERTICAL, 0, 10, 0, 100);
363    }
364
365    /**
366     * Constructs a new scroll bar with the specified orientation.
367     * <p>
368     * The {@code orientation} argument must take one of the two
369     * values {@code Scrollbar.HORIZONTAL},
370     * or {@code Scrollbar.VERTICAL},
371     * indicating a horizontal or vertical scroll bar, respectively.
372     *
373     * @param       orientation   indicates the orientation of the scroll bar
374     * @exception   IllegalArgumentException    when an illegal value for
375     *                    the {@code orientation} argument is supplied
376     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
377     * returns true.
378     * @see java.awt.GraphicsEnvironment#isHeadless
379     */
380    public Scrollbar(int orientation) throws HeadlessException {
381        this(orientation, 0, 10, 0, 100);
382    }
383
384    /**
385     * Constructs a new scroll bar with the specified orientation,
386     * initial value, visible amount, and minimum and maximum values.
387     * <p>
388     * The {@code orientation} argument must take one of the two
389     * values {@code Scrollbar.HORIZONTAL},
390     * or {@code Scrollbar.VERTICAL},
391     * indicating a horizontal or vertical scroll bar, respectively.
392     * <p>
393     * The parameters supplied to this constructor are subject to the
394     * constraints described in {@link #setValues(int, int, int, int)}.
395     *
396     * @param     orientation   indicates the orientation of the scroll bar.
397     * @param     value     the initial value of the scroll bar
398     * @param     visible   the visible amount of the scroll bar, typically
399     *                      represented by the size of the bubble
400     * @param     minimum   the minimum value of the scroll bar
401     * @param     maximum   the maximum value of the scroll bar
402     * @exception IllegalArgumentException    when an illegal value for
403     *                    the {@code orientation} argument is supplied
404     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
405     * returns true.
406     * @see #setValues
407     * @see java.awt.GraphicsEnvironment#isHeadless
408     */
409    public Scrollbar(int orientation, int value, int visible, int minimum,
410        int maximum) throws HeadlessException {
411        GraphicsEnvironment.checkHeadless();
412        switch (orientation) {
413          case HORIZONTAL:
414          case VERTICAL:
415            this.orientation = orientation;
416            break;
417          default:
418            throw new IllegalArgumentException("illegal scrollbar orientation");
419        }
420        setValues(value, visible, minimum, maximum);
421    }
422
423    /**
424     * Constructs a name for this component.  Called by {@code getName}
425     * when the name is {@code null}.
426     */
427    String constructComponentName() {
428        synchronized (Scrollbar.class) {
429            return base + nameCounter++;
430        }
431    }
432
433    /**
434     * Creates the {@code Scrollbar}'s peer.  The peer allows you to modify
435     * the appearance of the {@code Scrollbar} without changing any of its
436     * functionality.
437     */
438    public void addNotify() {
439        synchronized (getTreeLock()) {
440            if (peer == null)
441                peer = getComponentFactory().createScrollbar(this);
442            super.addNotify();
443        }
444    }
445
446    /**
447     * Returns the orientation of this scroll bar.
448     *
449     * @return    the orientation of this scroll bar, either
450     *               {@code Scrollbar.HORIZONTAL} or
451     *               {@code Scrollbar.VERTICAL}
452     * @see       java.awt.Scrollbar#setOrientation
453     */
454    public int getOrientation() {
455        return orientation;
456    }
457
458    /**
459     * Sets the orientation for this scroll bar.
460     *
461     * @param orientation  the orientation of this scroll bar, either
462     *               {@code Scrollbar.HORIZONTAL} or
463     *               {@code Scrollbar.VERTICAL}
464     * @see       java.awt.Scrollbar#getOrientation
465     * @exception   IllegalArgumentException  if the value supplied
466     *                   for {@code orientation} is not a
467     *                   legal value
468     * @since     1.1
469     */
470    public void setOrientation(int orientation) {
471        synchronized (getTreeLock()) {
472            if (orientation == this.orientation) {
473                return;
474            }
475            switch (orientation) {
476                case HORIZONTAL:
477                case VERTICAL:
478                    this.orientation = orientation;
479                    break;
480                default:
481                    throw new IllegalArgumentException("illegal scrollbar orientation");
482            }
483            /* Create a new peer with the specified orientation. */
484            if (peer != null) {
485                removeNotify();
486                addNotify();
487                invalidate();
488            }
489        }
490        if (accessibleContext != null) {
491            accessibleContext.firePropertyChange(
492                    AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
493                    ((orientation == VERTICAL)
494                     ? AccessibleState.HORIZONTAL : AccessibleState.VERTICAL),
495                    ((orientation == VERTICAL)
496                     ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL));
497        }
498    }
499
500    /**
501     * Gets the current value of this scroll bar.
502     *
503     * @return      the current value of this scroll bar
504     * @see         java.awt.Scrollbar#getMinimum
505     * @see         java.awt.Scrollbar#getMaximum
506     */
507    public int getValue() {
508        return value;
509    }
510
511    /**
512     * Sets the value of this scroll bar to the specified value.
513     * <p>
514     * If the value supplied is less than the current {@code minimum}
515     * or greater than the current {@code maximum - visibleAmount},
516     * then either {@code minimum} or {@code maximum - visibleAmount}
517     * is substituted, as appropriate.
518     * <p>
519     * Normally, a program should change a scroll bar's
520     * value only by calling {@code setValues}.
521     * The {@code setValues} method simultaneously
522     * and synchronously sets the minimum, maximum, visible amount,
523     * and value properties of a scroll bar, so that they are
524     * mutually consistent.
525     * <p>
526     * Calling this method does not fire an
527     * {@code AdjustmentEvent}.
528     *
529     * @param       newValue   the new value of the scroll bar
530     * @see         java.awt.Scrollbar#setValues
531     * @see         java.awt.Scrollbar#getValue
532     * @see         java.awt.Scrollbar#getMinimum
533     * @see         java.awt.Scrollbar#getMaximum
534     */
535    public void setValue(int newValue) {
536        // Use setValues so that a consistent policy relating
537        // minimum, maximum, visible amount, and value is enforced.
538        setValues(newValue, visibleAmount, minimum, maximum);
539    }
540
541    /**
542     * Gets the minimum value of this scroll bar.
543     *
544     * @return      the minimum value of this scroll bar
545     * @see         java.awt.Scrollbar#getValue
546     * @see         java.awt.Scrollbar#getMaximum
547     */
548    public int getMinimum() {
549        return minimum;
550    }
551
552    /**
553     * Sets the minimum value of this scroll bar.
554     * <p>
555     * When {@code setMinimum} is called, the minimum value
556     * is changed, and other values (including the maximum, the
557     * visible amount, and the current scroll bar value)
558     * are changed to be consistent with the new minimum.
559     * <p>
560     * Normally, a program should change a scroll bar's minimum
561     * value only by calling {@code setValues}.
562     * The {@code setValues} method simultaneously
563     * and synchronously sets the minimum, maximum, visible amount,
564     * and value properties of a scroll bar, so that they are
565     * mutually consistent.
566     * <p>
567     * Note that setting the minimum value to {@code Integer.MAX_VALUE}
568     * will result in the new minimum value being set to
569     * {@code Integer.MAX_VALUE - 1}.
570     *
571     * @param       newMinimum   the new minimum value for this scroll bar
572     * @see         java.awt.Scrollbar#setValues
573     * @see         java.awt.Scrollbar#setMaximum
574     * @since       1.1
575     */
576    public void setMinimum(int newMinimum) {
577        // No checks are necessary in this method since minimum is
578        // the first variable checked in the setValues function.
579
580        // Use setValues so that a consistent policy relating
581        // minimum, maximum, visible amount, and value is enforced.
582        setValues(value, visibleAmount, newMinimum, maximum);
583    }
584
585    /**
586     * Gets the maximum value of this scroll bar.
587     *
588     * @return      the maximum value of this scroll bar
589     * @see         java.awt.Scrollbar#getValue
590     * @see         java.awt.Scrollbar#getMinimum
591     */
592    public int getMaximum() {
593        return maximum;
594    }
595
596    /**
597     * Sets the maximum value of this scroll bar.
598     * <p>
599     * When {@code setMaximum} is called, the maximum value
600     * is changed, and other values (including the minimum, the
601     * visible amount, and the current scroll bar value)
602     * are changed to be consistent with the new maximum.
603     * <p>
604     * Normally, a program should change a scroll bar's maximum
605     * value only by calling {@code setValues}.
606     * The {@code setValues} method simultaneously
607     * and synchronously sets the minimum, maximum, visible amount,
608     * and value properties of a scroll bar, so that they are
609     * mutually consistent.
610     * <p>
611     * Note that setting the maximum value to {@code Integer.MIN_VALUE}
612     * will result in the new maximum value being set to
613     * {@code Integer.MIN_VALUE + 1}.
614     *
615     * @param       newMaximum   the new maximum value
616     *                     for this scroll bar
617     * @see         java.awt.Scrollbar#setValues
618     * @see         java.awt.Scrollbar#setMinimum
619     * @since       1.1
620     */
621    public void setMaximum(int newMaximum) {
622        // minimum is checked first in setValues, so we need to
623        // enforce minimum and maximum checks here.
624        if (newMaximum == Integer.MIN_VALUE) {
625            newMaximum = Integer.MIN_VALUE + 1;
626        }
627
628        if (minimum >= newMaximum) {
629            minimum = newMaximum - 1;
630        }
631
632        // Use setValues so that a consistent policy relating
633        // minimum, maximum, visible amount, and value is enforced.
634        setValues(value, visibleAmount, minimum, newMaximum);
635    }
636
637    /**
638     * Gets the visible amount of this scroll bar.
639     * <p>
640     * When a scroll bar is used to select a range of values,
641     * the visible amount is used to represent the range of values
642     * that are currently visible.  The size of the scroll bar's
643     * bubble (also called a thumb or scroll box), usually gives a
644     * visual representation of the relationship of the visible
645     * amount to the range of the scroll bar.
646     * Note that depending on platform, the value of the visible amount property
647     * may not be visually indicated by the size of the bubble.
648     * <p>
649     * The scroll bar's bubble may not be displayed when it is not
650     * moveable (e.g. when it takes up the entire length of the
651     * scroll bar's track, or when the scroll bar is disabled).
652     * Whether the bubble is displayed or not will not affect
653     * the value returned by {@code getVisibleAmount}.
654     *
655     * @return      the visible amount of this scroll bar
656     * @see         java.awt.Scrollbar#setVisibleAmount
657     * @since       1.1
658     */
659    public int getVisibleAmount() {
660        return getVisible();
661    }
662
663    /**
664     * Returns the visible amount of this scroll bar.
665     *
666     * @return the visible amount of this scroll bar
667     * @deprecated As of JDK version 1.1,
668     * replaced by {@code getVisibleAmount()}.
669     */
670    @Deprecated
671    public int getVisible() {
672        return visibleAmount;
673    }
674
675    /**
676     * Sets the visible amount of this scroll bar.
677     * <p>
678     * When a scroll bar is used to select a range of values,
679     * the visible amount is used to represent the range of values
680     * that are currently visible.  The size of the scroll bar's
681     * bubble (also called a thumb or scroll box), usually gives a
682     * visual representation of the relationship of the visible
683     * amount to the range of the scroll bar.
684     * Note that depending on platform, the value of the visible amount property
685     * may not be visually indicated by the size of the bubble.
686     * <p>
687     * The scroll bar's bubble may not be displayed when it is not
688     * moveable (e.g. when it takes up the entire length of the
689     * scroll bar's track, or when the scroll bar is disabled).
690     * Whether the bubble is displayed or not will not affect
691     * the value returned by {@code getVisibleAmount}.
692     * <p>
693     * If the visible amount supplied is less than {@code one}
694     * or greater than the current {@code maximum - minimum},
695     * then either {@code one} or {@code maximum - minimum}
696     * is substituted, as appropriate.
697     * <p>
698     * Normally, a program should change a scroll bar's
699     * value only by calling {@code setValues}.
700     * The {@code setValues} method simultaneously
701     * and synchronously sets the minimum, maximum, visible amount,
702     * and value properties of a scroll bar, so that they are
703     * mutually consistent.
704     *
705     * @param       newAmount the new visible amount
706     * @see         java.awt.Scrollbar#getVisibleAmount
707     * @see         java.awt.Scrollbar#setValues
708     * @since       1.1
709     */
710    public void setVisibleAmount(int newAmount) {
711        // Use setValues so that a consistent policy relating
712        // minimum, maximum, visible amount, and value is enforced.
713        setValues(value, newAmount, minimum, maximum);
714    }
715
716    /**
717     * Sets the unit increment for this scroll bar.
718     * <p>
719     * The unit increment is the value that is added or subtracted
720     * when the user activates the unit increment area of the
721     * scroll bar, generally through a mouse or keyboard gesture
722     * that the scroll bar receives as an adjustment event.
723     * The unit increment must be greater than zero.
724     * Attempts to set the unit increment to a value lower than 1
725     * will result in a value of 1 being set.
726     * <p>
727     * In some operating systems, this property
728     * can be ignored by the underlying controls.
729     *
730     * @param        v  the amount by which to increment or decrement
731     *                         the scroll bar's value
732     * @see          java.awt.Scrollbar#getUnitIncrement
733     * @since        1.1
734     */
735    public void setUnitIncrement(int v) {
736        setLineIncrement(v);
737    }
738
739    /**
740     * Sets the unit increment for this scroll bar.
741     *
742     * @param  v the increment value
743     *
744     * @deprecated As of JDK version 1.1,
745     * replaced by {@code setUnitIncrement(int)}.
746     */
747    @Deprecated
748    public synchronized void setLineIncrement(int v) {
749        int tmp = (v < 1) ? 1 : v;
750
751        if (lineIncrement == tmp) {
752            return;
753        }
754        lineIncrement = tmp;
755
756        ScrollbarPeer peer = (ScrollbarPeer)this.peer;
757        if (peer != null) {
758            peer.setLineIncrement(lineIncrement);
759        }
760    }
761
762    /**
763     * Gets the unit increment for this scrollbar.
764     * <p>
765     * The unit increment is the value that is added or subtracted
766     * when the user activates the unit increment area of the
767     * scroll bar, generally through a mouse or keyboard gesture
768     * that the scroll bar receives as an adjustment event.
769     * The unit increment must be greater than zero.
770     * <p>
771     * In some operating systems, this property
772     * can be ignored by the underlying controls.
773     *
774     * @return      the unit increment of this scroll bar
775     * @see         java.awt.Scrollbar#setUnitIncrement
776     * @since       1.1
777     */
778    public int getUnitIncrement() {
779        return getLineIncrement();
780    }
781
782    /**
783     * Returns the unit increment for this scrollbar.
784     *
785     * @return the unit increment for this scrollbar
786     * @deprecated As of JDK version 1.1,
787     * replaced by {@code getUnitIncrement()}.
788     */
789    @Deprecated
790    public int getLineIncrement() {
791        return lineIncrement;
792    }
793
794    /**
795     * Sets the block increment for this scroll bar.
796     * <p>
797     * The block increment is the value that is added or subtracted
798     * when the user activates the block increment area of the
799     * scroll bar, generally through a mouse or keyboard gesture
800     * that the scroll bar receives as an adjustment event.
801     * The block increment must be greater than zero.
802     * Attempts to set the block increment to a value lower than 1
803     * will result in a value of 1 being set.
804     *
805     * @param        v  the amount by which to increment or decrement
806     *                         the scroll bar's value
807     * @see          java.awt.Scrollbar#getBlockIncrement
808     * @since        1.1
809     */
810    public void setBlockIncrement(int v) {
811        setPageIncrement(v);
812    }
813
814    /**
815     * Sets the block increment for this scroll bar.
816     *
817     * @param  v the block increment
818     * @deprecated As of JDK version 1.1,
819     * replaced by {@code setBlockIncrement()}.
820     */
821    @Deprecated
822    public synchronized void setPageIncrement(int v) {
823        int tmp = (v < 1) ? 1 : v;
824
825        if (pageIncrement == tmp) {
826            return;
827        }
828        pageIncrement = tmp;
829
830        ScrollbarPeer peer = (ScrollbarPeer)this.peer;
831        if (peer != null) {
832            peer.setPageIncrement(pageIncrement);
833        }
834    }
835
836    /**
837     * Gets the block increment of this scroll bar.
838     * <p>
839     * The block increment is the value that is added or subtracted
840     * when the user activates the block increment area of the
841     * scroll bar, generally through a mouse or keyboard gesture
842     * that the scroll bar receives as an adjustment event.
843     * The block increment must be greater than zero.
844     *
845     * @return      the block increment of this scroll bar
846     * @see         java.awt.Scrollbar#setBlockIncrement
847     * @since       1.1
848     */
849    public int getBlockIncrement() {
850        return getPageIncrement();
851    }
852
853    /**
854     * Returns the block increment of this scroll bar.
855     *
856     * @return the block increment of this scroll bar
857     *
858     * @deprecated As of JDK version 1.1,
859     * replaced by {@code getBlockIncrement()}.
860     */
861    @Deprecated
862    public int getPageIncrement() {
863        return pageIncrement;
864    }
865
866    /**
867     * Sets the values of four properties for this scroll bar:
868     * {@code value}, {@code visibleAmount},
869     * {@code minimum}, and {@code maximum}.
870     * If the values supplied for these properties are inconsistent
871     * or incorrect, they will be changed to ensure consistency.
872     * <p>
873     * This method simultaneously and synchronously sets the values
874     * of four scroll bar properties, assuring that the values of
875     * these properties are mutually consistent. It enforces the
876     * following constraints:
877     * {@code maximum} must be greater than {@code minimum},
878     * {@code maximum - minimum} must not be greater
879     *     than {@code Integer.MAX_VALUE},
880     * {@code visibleAmount} must be greater than zero.
881     * {@code visibleAmount} must not be greater than
882     *     {@code maximum - minimum},
883     * {@code value} must not be less than {@code minimum},
884     * and {@code value} must not be greater than
885     *     {@code maximum - visibleAmount}
886     * <p>
887     * Calling this method does not fire an
888     * {@code AdjustmentEvent}.
889     *
890     * @param      value is the position in the current window
891     * @param      visible is the visible amount of the scroll bar
892     * @param      minimum is the minimum value of the scroll bar
893     * @param      maximum is the maximum value of the scroll bar
894     * @see        #setMinimum
895     * @see        #setMaximum
896     * @see        #setVisibleAmount
897     * @see        #setValue
898     */
899    public void setValues(int value, int visible, int minimum, int maximum) {
900        int oldValue;
901        synchronized (this) {
902            if (minimum == Integer.MAX_VALUE) {
903                minimum = Integer.MAX_VALUE - 1;
904            }
905            if (maximum <= minimum) {
906                maximum = minimum + 1;
907            }
908
909            long maxMinusMin = (long) maximum - (long) minimum;
910            if (maxMinusMin > Integer.MAX_VALUE) {
911                maxMinusMin = Integer.MAX_VALUE;
912                maximum = minimum + (int) maxMinusMin;
913            }
914            if (visible > (int) maxMinusMin) {
915                visible = (int) maxMinusMin;
916            }
917            if (visible < 1) {
918                visible = 1;
919            }
920
921            if (value < minimum) {
922                value = minimum;
923            }
924            if (value > maximum - visible) {
925                value = maximum - visible;
926            }
927
928            oldValue = this.value;
929            this.value = value;
930            this.visibleAmount = visible;
931            this.minimum = minimum;
932            this.maximum = maximum;
933            ScrollbarPeer peer = (ScrollbarPeer)this.peer;
934            if (peer != null) {
935                peer.setValues(value, visibleAmount, minimum, maximum);
936            }
937        }
938
939        if ((oldValue != value) && (accessibleContext != null))  {
940            accessibleContext.firePropertyChange(
941                    AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
942                    Integer.valueOf(oldValue),
943                    Integer.valueOf(value));
944        }
945    }
946
947    /**
948     * Returns true if the value is in the process of changing as a
949     * result of actions being taken by the user.
950     *
951     * @return the value of the {@code valueIsAdjusting} property
952     * @see #setValueIsAdjusting
953     * @since 1.4
954     */
955    public boolean getValueIsAdjusting() {
956        return isAdjusting;
957    }
958
959    /**
960     * Sets the {@code valueIsAdjusting} property.
961     *
962     * @param b new adjustment-in-progress status
963     * @see #getValueIsAdjusting
964     * @since 1.4
965     */
966    public void setValueIsAdjusting(boolean b) {
967        boolean oldValue;
968
969        synchronized (this) {
970            oldValue = isAdjusting;
971            isAdjusting = b;
972        }
973
974        if ((oldValue != b) && (accessibleContext != null)) {
975            accessibleContext.firePropertyChange(
976                    AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
977                    ((oldValue) ? AccessibleState.BUSY : null),
978                    ((b) ? AccessibleState.BUSY : null));
979        }
980    }
981
982
983
984    /**
985     * Adds the specified adjustment listener to receive instances of
986     * {@code AdjustmentEvent} from this scroll bar.
987     * If l is {@code null}, no exception is thrown and no
988     * action is performed.
989     * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
990     * >AWT Threading Issues</a> for details on AWT's threading model.
991     *
992     * @param        l the adjustment listener
993     * @see          #removeAdjustmentListener
994     * @see          #getAdjustmentListeners
995     * @see          java.awt.event.AdjustmentEvent
996     * @see          java.awt.event.AdjustmentListener
997     * @since        1.1
998     */
999    public synchronized void addAdjustmentListener(AdjustmentListener l) {
1000        if (l == null) {
1001            return;
1002        }
1003        adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l);
1004        newEventsOnly = true;
1005    }
1006
1007    /**
1008     * Removes the specified adjustment listener so that it no longer
1009     * receives instances of {@code AdjustmentEvent} from this scroll bar.
1010     * If l is {@code null}, no exception is thrown and no action
1011     * is performed.
1012     * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1013     * >AWT Threading Issues</a> for details on AWT's threading model.
1014     *
1015     * @param           l    the adjustment listener
1016     * @see             #addAdjustmentListener
1017     * @see             #getAdjustmentListeners
1018     * @see             java.awt.event.AdjustmentEvent
1019     * @see             java.awt.event.AdjustmentListener
1020     * @since           1.1
1021     */
1022    public synchronized void removeAdjustmentListener(AdjustmentListener l) {
1023        if (l == null) {
1024            return;
1025        }
1026        adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l);
1027    }
1028
1029    /**
1030     * Returns an array of all the adjustment listeners
1031     * registered on this scrollbar.
1032     *
1033     * @return all of this scrollbar's {@code AdjustmentListener}s
1034     *         or an empty array if no adjustment
1035     *         listeners are currently registered
1036     * @see             #addAdjustmentListener
1037     * @see             #removeAdjustmentListener
1038     * @see             java.awt.event.AdjustmentEvent
1039     * @see             java.awt.event.AdjustmentListener
1040     * @since 1.4
1041     */
1042    public synchronized AdjustmentListener[] getAdjustmentListeners() {
1043        return getListeners(AdjustmentListener.class);
1044    }
1045
1046    /**
1047     * Returns an array of all the objects currently registered
1048     * as <code><em>Foo</em>Listener</code>s
1049     * upon this {@code Scrollbar}.
1050     * <code><em>Foo</em>Listener</code>s are registered using the
1051     * <code>add<em>Foo</em>Listener</code> method.
1052     * <p>
1053     * You can specify the {@code listenerType} argument
1054     * with a class literal,  such as
1055     * <code><em>Foo</em>Listener.class</code>.
1056     * For example, you can query a
1057     * {@code Scrollbar c}
1058     * for its mouse listeners with the following code:
1059     *
1060     * <pre>MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));</pre>
1061     *
1062     * If no such listeners exist, this method returns an empty array.
1063     *
1064     * @param listenerType the type of listeners requested; this parameter
1065     *          should specify an interface that descends from
1066     *          {@code java.util.EventListener}
1067     * @return an array of all objects registered as
1068     *          <code><em>Foo</em>Listener</code>s on this component,
1069     *          or an empty array if no such listeners have been added
1070     * @exception ClassCastException if {@code listenerType}
1071     *          doesn't specify a class or interface that implements
1072     *          {@code java.util.EventListener}
1073     *
1074     * @since 1.3
1075     */
1076    public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
1077        EventListener l = null;
1078        if  (listenerType == AdjustmentListener.class) {
1079            l = adjustmentListener;
1080        } else {
1081            return super.getListeners(listenerType);
1082        }
1083        return AWTEventMulticaster.getListeners(l, listenerType);
1084    }
1085
1086    // REMIND: remove when filtering is done at lower level
1087    boolean eventEnabled(AWTEvent e) {
1088        if (e.id == AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED) {
1089            if ((eventMask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0 ||
1090                adjustmentListener != null) {
1091                return true;
1092            }
1093            return false;
1094        }
1095        return super.eventEnabled(e);
1096    }
1097
1098    /**
1099     * Processes events on this scroll bar. If the event is an
1100     * instance of {@code AdjustmentEvent}, it invokes the
1101     * {@code processAdjustmentEvent} method.
1102     * Otherwise, it invokes its superclass's
1103     * {@code processEvent} method.
1104     * <p>Note that if the event parameter is {@code null}
1105     * the behavior is unspecified and may result in an
1106     * exception.
1107     *
1108     * @param        e the event
1109     * @see          java.awt.event.AdjustmentEvent
1110     * @see          java.awt.Scrollbar#processAdjustmentEvent
1111     * @since        1.1
1112     */
1113    protected void processEvent(AWTEvent e) {
1114        if (e instanceof AdjustmentEvent) {
1115            processAdjustmentEvent((AdjustmentEvent)e);
1116            return;
1117        }
1118        super.processEvent(e);
1119    }
1120
1121    /**
1122     * Processes adjustment events occurring on this
1123     * scrollbar by dispatching them to any registered
1124     * {@code AdjustmentListener} objects.
1125     * <p>
1126     * This method is not called unless adjustment events are
1127     * enabled for this component. Adjustment events are enabled
1128     * when one of the following occurs:
1129     * <ul>
1130     * <li>An {@code AdjustmentListener} object is registered
1131     * via {@code addAdjustmentListener}.
1132     * <li>Adjustment events are enabled via {@code enableEvents}.
1133     * </ul>
1134     * <p>Note that if the event parameter is {@code null}
1135     * the behavior is unspecified and may result in an
1136     * exception.
1137     *
1138     * @param       e the adjustment event
1139     * @see         java.awt.event.AdjustmentEvent
1140     * @see         java.awt.event.AdjustmentListener
1141     * @see         java.awt.Scrollbar#addAdjustmentListener
1142     * @see         java.awt.Component#enableEvents
1143     * @since       1.1
1144     */
1145    protected void processAdjustmentEvent(AdjustmentEvent e) {
1146        AdjustmentListener listener = adjustmentListener;
1147        if (listener != null) {
1148            listener.adjustmentValueChanged(e);
1149        }
1150    }
1151
1152    /**
1153     * Returns a string representing the state of this {@code Scrollbar}.
1154     * This method is intended to be used only for debugging purposes, and the
1155     * content and format of the returned string may vary between
1156     * implementations. The returned string may be empty but may not be
1157     * {@code null}.
1158     *
1159     * @return      the parameter string of this scroll bar
1160     */
1161    protected String paramString() {
1162        return super.paramString() +
1163            ",val=" + value +
1164            ",vis=" + visibleAmount +
1165            ",min=" + minimum +
1166            ",max=" + maximum +
1167            ((orientation == VERTICAL) ? ",vert" : ",horz") +
1168            ",isAdjusting=" + isAdjusting;
1169    }
1170
1171
1172    /* Serialization support.
1173     */
1174
1175    /**
1176     * The scroll bar's serialized Data Version.
1177     *
1178     * @serial
1179     */
1180    private int scrollbarSerializedDataVersion = 1;
1181
1182    /**
1183     * Writes default serializable fields to stream.  Writes
1184     * a list of serializable {@code AdjustmentListeners}
1185     * as optional data. The non-serializable listeners are
1186     * detected and no attempt is made to serialize them.
1187     *
1188     * @param s the {@code ObjectOutputStream} to write
1189     * @serialData {@code null} terminated sequence of 0
1190     *   or more pairs; the pair consists of a {@code String}
1191     *   and an {@code Object}; the {@code String} indicates
1192     *   the type of object and is one of the following:
1193     *   {@code adjustmentListenerK} indicating an
1194     *     {@code AdjustmentListener} object
1195     *
1196     * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
1197     * @see java.awt.Component#adjustmentListenerK
1198     * @see #readObject(ObjectInputStream)
1199     */
1200    private void writeObject(ObjectOutputStream s)
1201      throws IOException
1202    {
1203      s.defaultWriteObject();
1204
1205      AWTEventMulticaster.save(s, adjustmentListenerK, adjustmentListener);
1206      s.writeObject(null);
1207    }
1208
1209    /**
1210     * Reads the {@code ObjectInputStream} and if
1211     * it isn't {@code null} adds a listener to
1212     * receive adjustment events fired by the
1213     * {@code Scrollbar}.
1214     * Unrecognized keys or values will be ignored.
1215     *
1216     * @param s the {@code ObjectInputStream} to read
1217     * @exception HeadlessException if
1218     *   {@code GraphicsEnvironment.isHeadless} returns
1219     *   {@code true}
1220     * @see java.awt.GraphicsEnvironment#isHeadless
1221     * @see #writeObject(ObjectOutputStream)
1222     */
1223    private void readObject(ObjectInputStream s)
1224      throws ClassNotFoundException, IOException, HeadlessException
1225    {
1226      GraphicsEnvironment.checkHeadless();
1227      s.defaultReadObject();
1228
1229      Object keyOrNull;
1230      while(null != (keyOrNull = s.readObject())) {
1231        String key = ((String)keyOrNull).intern();
1232
1233        if (adjustmentListenerK == key)
1234          addAdjustmentListener((AdjustmentListener)(s.readObject()));
1235
1236        else // skip value for unrecognized key
1237          s.readObject();
1238      }
1239    }
1240
1241
1242/////////////////
1243// Accessibility support
1244////////////////
1245
1246    /**
1247     * Gets the {@code AccessibleContext} associated with this
1248     * {@code Scrollbar}. For scrollbars, the
1249     * {@code AccessibleContext} takes the form of an
1250     * {@code AccessibleAWTScrollBar}. A new
1251     * {@code AccessibleAWTScrollBar} instance is created if necessary.
1252     *
1253     * @return an {@code AccessibleAWTScrollBar} that serves as the
1254     *         {@code AccessibleContext} of this {@code ScrollBar}
1255     * @since 1.3
1256     */
1257    public AccessibleContext getAccessibleContext() {
1258        if (accessibleContext == null) {
1259            accessibleContext = new AccessibleAWTScrollBar();
1260        }
1261        return accessibleContext;
1262    }
1263
1264    /**
1265     * This class implements accessibility support for the
1266     * {@code Scrollbar} class.  It provides an implementation of
1267     * the Java Accessibility API appropriate to scrollbar
1268     * user-interface elements.
1269     * @since 1.3
1270     */
1271    protected class AccessibleAWTScrollBar extends AccessibleAWTComponent
1272        implements AccessibleValue
1273    {
1274        /*
1275         * JDK 1.3 serialVersionUID
1276         */
1277        private static final long serialVersionUID = -344337268523697807L;
1278
1279        /**
1280         * Get the state set of this object.
1281         *
1282         * @return an instance of {@code AccessibleState}
1283         *     containing the current state of the object
1284         * @see AccessibleState
1285         */
1286        public AccessibleStateSet getAccessibleStateSet() {
1287            AccessibleStateSet states = super.getAccessibleStateSet();
1288            if (getValueIsAdjusting()) {
1289                states.add(AccessibleState.BUSY);
1290            }
1291            if (getOrientation() == VERTICAL) {
1292                states.add(AccessibleState.VERTICAL);
1293            } else {
1294                states.add(AccessibleState.HORIZONTAL);
1295            }
1296            return states;
1297        }
1298
1299        /**
1300         * Get the role of this object.
1301         *
1302         * @return an instance of {@code AccessibleRole}
1303         *     describing the role of the object
1304         */
1305        public AccessibleRole getAccessibleRole() {
1306            return AccessibleRole.SCROLL_BAR;
1307        }
1308
1309        /**
1310         * Get the {@code AccessibleValue} associated with this
1311         * object.  In the implementation of the Java Accessibility
1312         * API for this class, return this object, which is
1313         * responsible for implementing the
1314         * {@code AccessibleValue} interface on behalf of itself.
1315         *
1316         * @return this object
1317         */
1318        public AccessibleValue getAccessibleValue() {
1319            return this;
1320        }
1321
1322        /**
1323         * Get the accessible value of this object.
1324         *
1325         * @return The current value of this object.
1326         */
1327        public Number getCurrentAccessibleValue() {
1328            return Integer.valueOf(getValue());
1329        }
1330
1331        /**
1332         * Set the value of this object as a Number.
1333         *
1334         * @return True if the value was set.
1335         */
1336        public boolean setCurrentAccessibleValue(Number n) {
1337            if (n instanceof Integer) {
1338                setValue(n.intValue());
1339                return true;
1340            } else {
1341                return false;
1342            }
1343        }
1344
1345        /**
1346         * Get the minimum accessible value of this object.
1347         *
1348         * @return The minimum value of this object.
1349         */
1350        public Number getMinimumAccessibleValue() {
1351            return Integer.valueOf(getMinimum());
1352        }
1353
1354        /**
1355         * Get the maximum accessible value of this object.
1356         *
1357         * @return The maximum value of this object.
1358         */
1359        public Number getMaximumAccessibleValue() {
1360            return Integer.valueOf(getMaximum());
1361        }
1362
1363    } // AccessibleAWTScrollBar
1364
1365}
1366