1 /*
2 * Copyright 1996-2008 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 */
25 package java.awt;
26
27 import java.awt.peer.LightweightPeer;
28 import java.awt.peer.ScrollPanePeer;
29 import java.awt.event;
30 import javax.accessibility;
31 import sun.awt.ScrollPaneWheelScroller;
32 import sun.awt.SunToolkit;
33
34 import java.beans.ConstructorProperties;
35 import java.beans.Transient;
36 import java.io.ObjectInputStream;
37 import java.io.ObjectOutputStream;
38 import java.io.IOException;
39
40 /**
41 * A container class which implements automatic horizontal and/or
42 * vertical scrolling for a single child component. The display
43 * policy for the scrollbars can be set to:
44 * <OL>
45 * <LI>as needed: scrollbars created and shown only when needed by scrollpane
46 * <LI>always: scrollbars created and always shown by the scrollpane
47 * <LI>never: scrollbars never created or shown by the scrollpane
48 * </OL>
49 * <P>
50 * The state of the horizontal and vertical scrollbars is represented
51 * by two <code>ScrollPaneAdjustable</code> objects (one for each
52 * dimension) which implement the <code>Adjustable</code> interface.
53 * The API provides methods to access those objects such that the
54 * attributes on the Adjustable object (such as unitIncrement, value,
55 * etc.) can be manipulated.
56 * <P>
57 * Certain adjustable properties (minimum, maximum, blockIncrement,
58 * and visibleAmount) are set internally by the scrollpane in accordance
59 * with the geometry of the scrollpane and its child and these should
60 * not be set by programs using the scrollpane.
61 * <P>
62 * If the scrollbar display policy is defined as "never", then the
63 * scrollpane can still be programmatically scrolled using the
64 * setScrollPosition() method and the scrollpane will move and clip
65 * the child's contents appropriately. This policy is useful if the
66 * program needs to create and manage its own adjustable controls.
67 * <P>
68 * The placement of the scrollbars is controlled by platform-specific
69 * properties set by the user outside of the program.
70 * <P>
71 * The initial size of this container is set to 100x100, but can
72 * be reset using setSize().
73 * <P>
74 * Scrolling with the wheel on a wheel-equipped mouse is enabled by default.
75 * This can be disabled using <code>setWheelScrollingEnabled</code>.
76 * Wheel scrolling can be customized by setting the block and
77 * unit increment of the horizontal and vertical Adjustables.
78 * For information on how mouse wheel events are dispatched, see
79 * the class description for {@link MouseWheelEvent}.
80 * <P>
81 * Insets are used to define any space used by scrollbars and any
82 * borders created by the scroll pane. getInsets() can be used
83 * to get the current value for the insets. If the value of
84 * scrollbarsAlwaysVisible is false, then the value of the insets
85 * will change dynamically depending on whether the scrollbars are
86 * currently visible or not.
87 *
88 * @author Tom Ball
89 * @author Amy Fowler
90 * @author Tim Prinzing
91 */
92 public class ScrollPane extends Container implements Accessible {
93
94
95 /**
96 * Initialize JNI field and method IDs
97 */
98 private static native void initIDs();
99
100 static {
101 /* ensure that the necessary native libraries are loaded */
102 Toolkit.loadLibraries();
103 if (!GraphicsEnvironment.isHeadless()) {
104 initIDs();
105 }
106 }
107
108 /**
109 * Specifies that horizontal/vertical scrollbar should be shown
110 * only when the size of the child exceeds the size of the scrollpane
111 * in the horizontal/vertical dimension.
112 */
113 public static final int SCROLLBARS_AS_NEEDED = 0;
114
115 /**
116 * Specifies that horizontal/vertical scrollbars should always be
117 * shown regardless of the respective sizes of the scrollpane and child.
118 */
119 public static final int SCROLLBARS_ALWAYS = 1;
120
121 /**
122 * Specifies that horizontal/vertical scrollbars should never be shown
123 * regardless of the respective sizes of the scrollpane and child.
124 */
125 public static final int SCROLLBARS_NEVER = 2;
126
127 /**
128 * There are 3 ways in which a scroll bar can be displayed.
129 * This integer will represent one of these 3 displays -
130 * (SCROLLBARS_ALWAYS, SCROLLBARS_AS_NEEDED, SCROLLBARS_NEVER)
131 *
132 * @serial
133 * @see #getScrollbarDisplayPolicy
134 */
135 private int scrollbarDisplayPolicy;
136
137 /**
138 * An adjustable vertical scrollbar.
139 * It is important to note that you must <em>NOT</em> call 3
140 * <code>Adjustable</code> methods, namely:
141 * <code>setMinimum()</code>, <code>setMaximum()</code>,
142 * <code>setVisibleAmount()</code>.
143 *
144 * @serial
145 * @see #getVAdjustable
146 */
147 private ScrollPaneAdjustable vAdjustable;
148
149 /**
150 * An adjustable horizontal scrollbar.
151 * It is important to note that you must <em>NOT</em> call 3
152 * <code>Adjustable</code> methods, namely:
153 * <code>setMinimum()</code>, <code>setMaximum()</code>,
154 * <code>setVisibleAmount()</code>.
155 *
156 * @serial
157 * @see #getHAdjustable
158 */
159 private ScrollPaneAdjustable hAdjustable;
160
161 private static final String base = "scrollpane";
162 private static int nameCounter = 0;
163
164 private static final boolean defaultWheelScroll = true;
165
166 /**
167 * Indicates whether or not scrolling should take place when a
168 * MouseWheelEvent is received.
169 *
170 * @serial
171 * @since 1.4
172 */
173 private boolean wheelScrollingEnabled = defaultWheelScroll;
174
175 /*
176 * JDK 1.1 serialVersionUID
177 */
178 private static final long serialVersionUID = 7956609840827222915L;
179
180 /**
181 * Create a new scrollpane container with a scrollbar display
182 * policy of "as needed".
183 * @throws HeadlessException if GraphicsEnvironment.isHeadless()
184 * returns true
185 * @see java.awt.GraphicsEnvironment#isHeadless
186 */
187 public ScrollPane() throws HeadlessException {
188 this(SCROLLBARS_AS_NEEDED);
189 }
190
191 /**
192 * Create a new scrollpane container.
193 * @param scrollbarDisplayPolicy policy for when scrollbars should be shown
194 * @throws IllegalArgumentException if the specified scrollbar
195 * display policy is invalid
196 * @throws HeadlessException if GraphicsEnvironment.isHeadless()
197 * returns true
198 * @see java.awt.GraphicsEnvironment#isHeadless
199 */
200 @ConstructorProperties({"scrollbarDisplayPolicy"})
201 public ScrollPane(int scrollbarDisplayPolicy) throws HeadlessException {
202 GraphicsEnvironment.checkHeadless();
203 this.layoutMgr = null;
204 this.width = 100;
205 this.height = 100;
206 switch (scrollbarDisplayPolicy) {
207 case SCROLLBARS_NEVER:
208 case SCROLLBARS_AS_NEEDED:
209 case SCROLLBARS_ALWAYS:
210 this.scrollbarDisplayPolicy = scrollbarDisplayPolicy;
211 break;
212 default:
213 throw new IllegalArgumentException("illegal scrollbar display policy");
214 }
215
216 vAdjustable = new ScrollPaneAdjustable(this, new PeerFixer(this),
217 Adjustable.VERTICAL);
218 hAdjustable = new ScrollPaneAdjustable(this, new PeerFixer(this),
219 Adjustable.HORIZONTAL);
220 setWheelScrollingEnabled(defaultWheelScroll);
221 }
222
223 /**
224 * Construct a name for this component. Called by getName() when the
225 * name is null.
226 */
227 String constructComponentName() {
228 synchronized (ScrollPane.class) {
229 return base + nameCounter++;
230 }
231 }
232
233 // The scrollpane won't work with a windowless child... it assumes
234 // it is moving a child window around so the windowless child is
235 // wrapped with a window.
236 private void addToPanel(Component comp, Object constraints, int index) {
237 Panel child = new Panel();
238 child.setLayout(new BorderLayout());
239 child.add(comp);
240 super.addImpl(child, constraints, index);
241 validate();
242 }
243
244 /**
245 * Adds the specified component to this scroll pane container.
246 * If the scroll pane has an existing child component, that
247 * component is removed and the new one is added.
248 * @param comp the component to be added
249 * @param constraints not applicable
250 * @param index position of child component (must be <= 0)
251 */
252 protected final void addImpl(Component comp, Object constraints, int index) {
253 synchronized (getTreeLock()) {
254 if (getComponentCount() > 0) {
255 remove(0);
256 }
257 if (index > 0) {
258 throw new IllegalArgumentException("position greater than 0");
259 }
260
261 if (!SunToolkit.isLightweightOrUnknown(comp)) {
262 super.addImpl(comp, constraints, index);
263 } else {
264 addToPanel(comp, constraints, index);
265 }
266 }
267 }
268
269 /**
270 * Returns the display policy for the scrollbars.
271 * @return the display policy for the scrollbars
272 */
273 public int getScrollbarDisplayPolicy() {
274 return scrollbarDisplayPolicy;
275 }
276
277 /**
278 * Returns the current size of the scroll pane's view port.
279 * @return the size of the view port in pixels
280 */
281 public Dimension getViewportSize() {
282 Insets i = getInsets();
283 return new Dimension(width - i.right - i.left,
284 height - i.top - i.bottom);
285 }
286
287 /**
288 * Returns the height that would be occupied by a horizontal
289 * scrollbar, which is independent of whether it is currently
290 * displayed by the scroll pane or not.
291 * @return the height of a horizontal scrollbar in pixels
292 */
293 public int getHScrollbarHeight() {
294 int h = 0;
295 if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) {
296 ScrollPanePeer peer = (ScrollPanePeer)this.peer;
297 if (peer != null) {
298 h = peer.getHScrollbarHeight();
299 }
300 }
301 return h;
302 }
303
304 /**
305 * Returns the width that would be occupied by a vertical
306 * scrollbar, which is independent of whether it is currently
307 * displayed by the scroll pane or not.
308 * @return the width of a vertical scrollbar in pixels
309 */
310 public int getVScrollbarWidth() {
311 int w = 0;
312 if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) {
313 ScrollPanePeer peer = (ScrollPanePeer)this.peer;
314 if (peer != null) {
315 w = peer.getVScrollbarWidth();
316 }
317 }
318 return w;
319 }
320
321 /**
322 * Returns the <code>ScrollPaneAdjustable</code> object which
323 * represents the state of the vertical scrollbar.
324 * The declared return type of this method is
325 * <code>Adjustable</code> to maintain backward compatibility.
326 * @see java.awt.ScrollPaneAdjustable
327 */
328 public Adjustable getVAdjustable() {
329 return vAdjustable;
330 }
331
332 /**
333 * Returns the <code>ScrollPaneAdjustable</code> object which
334 * represents the state of the horizontal scrollbar.
335 * The declared return type of this method is
336 * <code>Adjustable</code> to maintain backward compatibility.
337 * @see java.awt.ScrollPaneAdjustable
338 */
339 public Adjustable getHAdjustable() {
340 return hAdjustable;
341 }
342
343 /**
344 * Scrolls to the specified position within the child component.
345 * A call to this method is only valid if the scroll pane contains
346 * a child. Specifying a position outside of the legal scrolling bounds
347 * of the child will scroll to the closest legal position.
348 * Legal bounds are defined to be the rectangle:
349 * x = 0, y = 0, width = (child width - view port width),
350 * height = (child height - view port height).
351 * This is a convenience method which interfaces with the Adjustable
352 * objects which represent the state of the scrollbars.
353 * @param x the x position to scroll to
354 * @param y the y position to scroll to
355 * @throws NullPointerException if the scrollpane does not contain
356 * a child
357 */
358 public void setScrollPosition(int x, int y) {
359 synchronized (getTreeLock()) {
360 if (ncomponents <= 0) {
361 throw new NullPointerException("child is null");
362 }
363 hAdjustable.setValue(x);
364 vAdjustable.setValue(y);
365 }
366 }
367
368 /**
369 * Scrolls to the specified position within the child component.
370 * A call to this method is only valid if the scroll pane contains
371 * a child and the specified position is within legal scrolling bounds
372 * of the child. Specifying a position outside of the legal scrolling
373 * bounds of the child will scroll to the closest legal position.
374 * Legal bounds are defined to be the rectangle:
375 * x = 0, y = 0, width = (child width - view port width),
376 * height = (child height - view port height).
377 * This is a convenience method which interfaces with the Adjustable
378 * objects which represent the state of the scrollbars.
379 * @param p the Point representing the position to scroll to
380 */
381 public void setScrollPosition(Point p) {
382 setScrollPosition(p.x, p.y);
383 }
384
385 /**
386 * Returns the current x,y position within the child which is displayed
387 * at the 0,0 location of the scrolled panel's view port.
388 * This is a convenience method which interfaces with the adjustable
389 * objects which represent the state of the scrollbars.
390 * @return the coordinate position for the current scroll position
391 * @throws NullPointerException if the scrollpane does not contain
392 * a child
393 */
394 @Transient
395 public Point getScrollPosition() {
396 if (ncomponents <= 0) {
397 throw new NullPointerException("child is null");
398 }
399 return new Point(hAdjustable.getValue(), vAdjustable.getValue());
400 }
401
402 /**
403 * Sets the layout manager for this container. This method is
404 * overridden to prevent the layout mgr from being set.
405 * @param mgr the specified layout manager
406 */
407 public final void setLayout(LayoutManager mgr) {
408 throw new AWTError("ScrollPane controls layout");
409 }
410
411 /**
412 * Lays out this container by resizing its child to its preferred size.
413 * If the new preferred size of the child causes the current scroll
414 * position to be invalid, the scroll position is set to the closest
415 * valid position.
416 *
417 * @see Component#validate
418 */
419 public void doLayout() {
420 layout();
421 }
422
423 /**
424 * Determine the size to allocate the child component.
425 * If the viewport area is bigger than the childs
426 * preferred size then the child is allocated enough
427 * to fill the viewport, otherwise the child is given
428 * it's preferred size.
429 */
430 Dimension calculateChildSize() {
431 //
432 // calculate the view size, accounting for border but not scrollbars
433 // - don't use right/bottom insets since they vary depending
434 // on whether or not scrollbars were displayed on last resize
435 //
436 Dimension size = getSize();
437 Insets insets = getInsets();
438 int viewWidth = size.width - insets.left*2;
439 int viewHeight = size.height - insets.top*2;
440
441 //
442 // determine whether or not horz or vert scrollbars will be displayed
443 //
444 boolean vbarOn;
445 boolean hbarOn;
446 Component child = getComponent(0);
447 Dimension childSize = new Dimension(child.getPreferredSize());
448
449 if (scrollbarDisplayPolicy == SCROLLBARS_AS_NEEDED) {
450 vbarOn = childSize.height > viewHeight;
451 hbarOn = childSize.width > viewWidth;
452 } else if (scrollbarDisplayPolicy == SCROLLBARS_ALWAYS) {
453 vbarOn = hbarOn = true;
454 } else { // SCROLLBARS_NEVER
455 vbarOn = hbarOn = false;
456 }
457
458 //
459 // adjust predicted view size to account for scrollbars
460 //
461 int vbarWidth = getVScrollbarWidth();
462 int hbarHeight = getHScrollbarHeight();
463 if (vbarOn) {
464 viewWidth -= vbarWidth;
465 }
466 if(hbarOn) {
467 viewHeight -= hbarHeight;
468 }
469
470 //
471 // if child is smaller than view, size it up
472 //
473 if (childSize.width < viewWidth) {
474 childSize.width = viewWidth;
475 }
476 if (childSize.height < viewHeight) {
477 childSize.height = viewHeight;
478 }
479
480 return childSize;
481 }
482
483 /**
484 * @deprecated As of JDK version 1.1,
485 * replaced by <code>doLayout()</code>.
486 */
487 @Deprecated
488 public void layout() {
489 if (ncomponents > 0) {
490 Component c = getComponent(0);
491 Point p = getScrollPosition();
492 Dimension cs = calculateChildSize();
493 Dimension vs = getViewportSize();
494 Insets i = getInsets();
495
496 c.reshape(i.left - p.x, i.top - p.y, cs.width, cs.height);
497 ScrollPanePeer peer = (ScrollPanePeer)this.peer;
498 if (peer != null) {
499 peer.childResized(cs.width, cs.height);
500 }
501
502 // update adjustables... the viewport size may have changed
503 // with the scrollbars coming or going so the viewport size
504 // is updated before the adjustables.
505 vs = getViewportSize();
506 hAdjustable.setSpan(0, cs.width, vs.width);
507 vAdjustable.setSpan(0, cs.height, vs.height);
508 }
509 }
510
511 /**
512 * Prints the component in this scroll pane.
513 * @param g the specified Graphics window
514 * @see Component#print
515 * @see Component#printAll
516 */
517 public void printComponents(Graphics g) {
518 if (ncomponents > 0) {
519 Component c = component[0];
520 Point p = c.getLocation();
521 Dimension vs = getViewportSize();
522 Insets i = getInsets();
523
524 Graphics cg = g.create();
525 try {
526 cg.clipRect(i.left, i.top, vs.width, vs.height);
527 cg.translate(p.x, p.y);
528 c.printAll(cg);
529 } finally {
530 cg.dispose();
531 }
532 }
533 }
534
535 /**
536 * Creates the scroll pane's peer.
537 */
538 public void addNotify() {
539 synchronized (getTreeLock()) {
540
541 int vAdjustableValue = 0;
542 int hAdjustableValue = 0;
543
544 // Bug 4124460. Save the current adjustable values,
545 // so they can be restored after addnotify. Set the
546 // adjustables to 0, to prevent crashes for possible
547 // negative values.
548 if (getComponentCount() > 0) {
549 vAdjustableValue = vAdjustable.getValue();
550 hAdjustableValue = hAdjustable.getValue();
551 vAdjustable.setValue(0);
552 hAdjustable.setValue(0);
553 }
554
555 if (peer == null)
556 peer = getToolkit().createScrollPane(this);
557 super.addNotify();
558
559 // Bug 4124460. Restore the adjustable values.
560 if (getComponentCount() > 0) {
561 vAdjustable.setValue(vAdjustableValue);
562 hAdjustable.setValue(hAdjustableValue);
563 }
564 }
565 }
566
567 /**
568 * Returns a string representing the state of this
569 * <code>ScrollPane</code>. This
570 * method is intended to be used only for debugging purposes, and the
571 * content and format of the returned string may vary between
572 * implementations. The returned string may be empty but may not be
573 * <code>null</code>.
574 *
575 * @return the parameter string of this scroll pane
576 */
577 public String paramString() {
578 String sdpStr;
579 switch (scrollbarDisplayPolicy) {
580 case SCROLLBARS_AS_NEEDED:
581 sdpStr = "as-needed";
582 break;
583 case SCROLLBARS_ALWAYS:
584 sdpStr = "always";
585 break;
586 case SCROLLBARS_NEVER:
587 sdpStr = "never";
588 break;
589 default:
590 sdpStr = "invalid display policy";
591 }
592 Point p = ncomponents > 0? getScrollPosition() : new Point(0,0);
593 Insets i = getInsets();
594 return super.paramString()+",ScrollPosition=("+p.x+","+p.y+")"+
595 ",Insets=("+i.top+","+i.left+","+i.bottom+","+i.right+")"+
596 ",ScrollbarDisplayPolicy="+sdpStr+
597 ",wheelScrollingEnabled="+isWheelScrollingEnabled();
598 }
599
600 void autoProcessMouseWheel(MouseWheelEvent e) {
601 processMouseWheelEvent(e);
602 }
603
604 /**
605 * Process mouse wheel events that are delivered to this
606 * <code>ScrollPane</code> by scrolling an appropriate amount.
607 * <p>Note that if the event parameter is <code>null</code>
608 * the behavior is unspecified and may result in an
609 * exception.
610 *
611 * @param e the mouse wheel event
612 * @since 1.4
613 */
614 protected void processMouseWheelEvent(MouseWheelEvent e) {
615 if (isWheelScrollingEnabled()) {
616 ScrollPaneWheelScroller.handleWheelScrolling(this, e);
617 e.consume();
618 }
619 super.processMouseWheelEvent(e);
620 }
621
622 /**
623 * If wheel scrolling is enabled, we return true for MouseWheelEvents
624 * @since 1.4
625 */
626 protected boolean eventTypeEnabled(int type) {
627 if (type == MouseEvent.MOUSE_WHEEL && isWheelScrollingEnabled()) {
628 return true;
629 }
630 else {
631 return super.eventTypeEnabled(type);
632 }
633 }
634
635 /**
636 * Enables/disables scrolling in response to movement of the mouse wheel.
637 * Wheel scrolling is enabled by default.
638 *
639 * @param handleWheel <code>true</code> if scrolling should be done
640 * automatically for a MouseWheelEvent,
641 * <code>false</code> otherwise.
642 * @see #isWheelScrollingEnabled
643 * @see java.awt.event.MouseWheelEvent
644 * @see java.awt.event.MouseWheelListener
645 * @since 1.4
646 */
647 public void setWheelScrollingEnabled(boolean handleWheel) {
648 wheelScrollingEnabled = handleWheel;
649 }
650
651 /**
652 * Indicates whether or not scrolling will take place in response to
653 * the mouse wheel. Wheel scrolling is enabled by default.
654 *
655 * @see #setWheelScrollingEnabled(boolean)
656 * @since 1.4
657 */
658 public boolean isWheelScrollingEnabled() {
659 return wheelScrollingEnabled;
660 }
661
662
663 /**
664 * Writes default serializable fields to stream.
665 */
666 private void writeObject(ObjectOutputStream s) throws IOException {
667 // 4352819: We only need this degenerate writeObject to make
668 // it safe for future versions of this class to write optional
669 // data to the stream.
670 s.defaultWriteObject();
671 }
672
673 /**
674 * Reads default serializable fields to stream.
675 * @exception HeadlessException if
676 * <code>GraphicsEnvironment.isHeadless()</code> returns
677 * <code>true</code>
678 * @see java.awt.GraphicsEnvironment#isHeadless
679 */
680 private void readObject(ObjectInputStream s)
681 throws ClassNotFoundException, IOException, HeadlessException
682 {
683 GraphicsEnvironment.checkHeadless();
684 // 4352819: Gotcha! Cannot use s.defaultReadObject here and
685 // then continue with reading optional data. Use GetField instead.
686 ObjectInputStream.GetField f = s.readFields();
687
688 // Old fields
689 scrollbarDisplayPolicy = f.get("scrollbarDisplayPolicy",
690 SCROLLBARS_AS_NEEDED);
691 hAdjustable = (ScrollPaneAdjustable)f.get("hAdjustable", null);
692 vAdjustable = (ScrollPaneAdjustable)f.get("vAdjustable", null);
693
694 // Since 1.4
695 wheelScrollingEnabled = f.get("wheelScrollingEnabled",
696 defaultWheelScroll);
697
698 // // Note to future maintainers
699 // if (f.defaulted("wheelScrollingEnabled")) {
700 // // We are reading pre-1.4 stream that doesn't have
701 // // optional data, not even the TC_ENDBLOCKDATA marker.
702 // // Reading anything after this point is unsafe as we will
703 // // read unrelated objects further down the stream (4352819).
704 // }
705 // else {
706 // // Reading data from 1.4 or later, it's ok to try to read
707 // // optional data as OptionalDataException with eof == true
708 // // will be correctly reported
709 // }
710 }
711
712 class PeerFixer implements AdjustmentListener, java.io.Serializable
713 {
714 private static final long serialVersionUID = 1043664721353696630L;
715
716 PeerFixer(ScrollPane scroller) {
717 this.scroller = scroller;
718 }
719
720 /**
721 * Invoked when the value of the adjustable has changed.
722 */
723 public void adjustmentValueChanged(AdjustmentEvent e) {
724 Adjustable adj = e.getAdjustable();
725 int value = e.getValue();
726 ScrollPanePeer peer = (ScrollPanePeer) scroller.peer;
727 if (peer != null) {
728 peer.setValue(adj, value);
729 }
730
731 Component c = scroller.getComponent(0);
732 switch(adj.getOrientation()) {
733 case Adjustable.VERTICAL:
734 c.move(c.getLocation().x, -(value));
735 break;
736 case Adjustable.HORIZONTAL:
737 c.move(-(value), c.getLocation().y);
738 break;
739 default:
740 throw new IllegalArgumentException("Illegal adjustable orientation");
741 }
742 }
743
744 private ScrollPane scroller;
745 }
746
747
748 /////////////////
749 // Accessibility support
750 ////////////////
751
752 /**
753 * Gets the AccessibleContext associated with this ScrollPane.
754 * For scroll panes, the AccessibleContext takes the form of an
755 * AccessibleAWTScrollPane.
756 * A new AccessibleAWTScrollPane instance is created if necessary.
757 *
758 * @return an AccessibleAWTScrollPane that serves as the
759 * AccessibleContext of this ScrollPane
760 * @since 1.3
761 */
762 public AccessibleContext getAccessibleContext() {
763 if (accessibleContext == null) {
764 accessibleContext = new AccessibleAWTScrollPane();
765 }
766 return accessibleContext;
767 }
768
769 /**
770 * This class implements accessibility support for the
771 * <code>ScrollPane</code> class. It provides an implementation of the
772 * Java Accessibility API appropriate to scroll pane user-interface
773 * elements.
774 * @since 1.3
775 */
776 protected class AccessibleAWTScrollPane extends AccessibleAWTContainer
777 {
778 /*
779 * JDK 1.3 serialVersionUID
780 */
781 private static final long serialVersionUID = 6100703663886637L;
782
783 /**
784 * Get the role of this object.
785 *
786 * @return an instance of AccessibleRole describing the role of the
787 * object
788 * @see AccessibleRole
789 */
790 public AccessibleRole getAccessibleRole() {
791 return AccessibleRole.SCROLL_PANE;
792 }
793
794 } // class AccessibleAWTScrollPane
795
796 }
797
798 /*
799 * In JDK 1.1.1, the pkg private class java.awt.PeerFixer was moved to
800 * become an inner class of ScrollPane, which broke serialization
801 * for ScrollPane objects using JDK 1.1.
802 * Instead of moving it back out here, which would break all JDK 1.1.x
803 * releases, we keep PeerFixer in both places. Because of the scoping rules,
804 * the PeerFixer that is used in ScrollPane will be the one that is the
805 * inner class. This pkg private PeerFixer class below will only be used
806 * if the Java 2 platform is used to deserialize ScrollPane objects that were serialized
807 * using JDK1.1
808 */
809 class PeerFixer implements AdjustmentListener, java.io.Serializable {
810 /*
811 * serialVersionUID
812 */
813 private static final long serialVersionUID = 7051237413532574756L;
814
815 PeerFixer(ScrollPane scroller) {
816 this.scroller = scroller;
817 }
818
819 /**
820 * Invoked when the value of the adjustable has changed.
821 */
822 public void adjustmentValueChanged(AdjustmentEvent e) {
823 Adjustable adj = e.getAdjustable();
824 int value = e.getValue();
825 ScrollPanePeer peer = (ScrollPanePeer) scroller.peer;
826 if (peer != null) {
827 peer.setValue(adj, value);
828 }
829
830 Component c = scroller.getComponent(0);
831 switch(adj.getOrientation()) {
832 case Adjustable.VERTICAL:
833 c.move(c.getLocation().x, -(value));
834 break;
835 case Adjustable.HORIZONTAL:
836 c.move(-(value), c.getLocation().y);
837 break;
838 default:
839 throw new IllegalArgumentException("Illegal adjustable orientation");
840 }
841 }
842
843 private ScrollPane scroller;
844 }