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