29 import javax.swing.border.*;
30 import javax.swing.event.*;
31 import javax.accessibility.*;
32
33 import java.awt.Component;
34 import java.awt.ComponentOrientation;
35 import java.awt.Rectangle;
36 import java.awt.Insets;
37 import java.awt.LayoutManager;
38 import java.awt.Point;
39
40 import java.io.ObjectOutputStream;
41 import java.io.IOException;
42
43 import java.beans.PropertyChangeEvent;
44 import java.beans.PropertyChangeListener;
45 import java.beans.Transient;
46
47 /**
48 * Provides a scrollable view of a lightweight component.
49 * A <code>JScrollPane</code> manages a viewport, optional
50 * vertical and horizontal scroll bars, and optional row and
51 * column heading viewports.
52 * You can find task-oriented documentation of <code>JScrollPane</code> in
53 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html">How to Use Scroll Panes</a>,
54 * a section in <em>The Java Tutorial</em>. Note that
55 * <code>JScrollPane</code> does not support heavyweight components.
56 *
57 * <TABLE STYLE="FLOAT:RIGHT" BORDER="0" SUMMARY="layout">
58 * <TR>
59 * <TD ALIGN="CENTER">
60 * <P STYLE="TEXT-ALIGN:CENTER"><IMG SRC="doc-files/JScrollPane-1.gif"
61 * alt="The following text describes this image."
62 * WIDTH="256" HEIGHT="248" STYLE="FLOAT:BOTTOM; BORDER:0px">
63 * </TD>
64 * </TR>
65 * </TABLE>
66 * The <code>JViewport</code> provides a window,
67 * or "viewport" onto a data
68 * source -- for example, a text file. That data source is the
69 * "scrollable client" (aka data model) displayed by the
70 * <code>JViewport</code> view.
71 * A <code>JScrollPane</code> basically consists of <code>JScrollBar</code>s,
72 * a <code>JViewport</code>, and the wiring between them,
73 * as shown in the diagram at right.
74 * <p>
75 * In addition to the scroll bars and viewport,
76 * a <code>JScrollPane</code> can have a
77 * column header and a row header. Each of these is a
78 * <code>JViewport</code> object that
79 * you specify with <code>setRowHeaderView</code>,
80 * and <code>setColumnHeaderView</code>.
81 * The column header viewport automatically scrolls left and right, tracking
82 * the left-right scrolling of the main viewport.
83 * (It never scrolls vertically, however.)
84 * The row header acts in a similar fashion.
85 * <p>
86 * Where two scroll bars meet, the row header meets the column header,
87 * or a scroll bar meets one of the headers, both components stop short
88 * of the corner, leaving a rectangular space which is, by default, empty.
89 * These spaces can potentially exist in any number of the four corners.
90 * In the previous diagram, the top right space is present and identified
91 * by the label "corner component".
92 * <p>
93 * Any number of these empty spaces can be replaced by using the
94 * <code>setCorner</code> method to add a component to a particular corner.
95 * (Note: The same component cannot be added to multiple corners.)
96 * This is useful if there's
97 * some extra decoration or function you'd like to add to the scroll pane.
98 * The size of each corner component is entirely determined by the size of the
99 * headers and/or scroll bars that surround it.
100 * <p>
101 * A corner component will only be visible if there is an empty space in that
102 * corner for it to exist in. For example, consider a component set into the
103 * top right corner of a scroll pane with a column header. If the scroll pane's
104 * vertical scrollbar is not present, perhaps because the view component hasn't
105 * grown large enough to require it, then the corner component will not be
106 * shown (since there is no empty space in that corner created by the meeting
107 * of the header and vertical scroll bar). Forcing the scroll bar to always be
108 * shown, using
109 * <code>setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS)</code>,
110 * will ensure that the space for the corner component always exists.
111 * <p>
112 * To add a border around the main viewport,
113 * you can use <code>setViewportBorder</code>.
114 * (Of course, you can also add a border around the whole scroll pane using
115 * <code>setBorder</code>.)
116 * <p>
117 * A common operation to want to do is to set the background color that will
118 * be used if the main viewport view is smaller than the viewport, or is
119 * not opaque. This can be accomplished by setting the background color
120 * of the viewport, via <code>scrollPane.getViewport().setBackground()</code>.
121 * The reason for setting the color of the viewport and not the scrollpane
122 * is that by default <code>JViewport</code> is opaque
123 * which, among other things, means it will completely fill
124 * in its background using its background color. Therefore when
125 * <code>JScrollPane</code> draws its background the viewport will
126 * usually draw over it.
127 * <p>
128 * By default <code>JScrollPane</code> uses <code>ScrollPaneLayout</code>
129 * to handle the layout of its child Components. <code>ScrollPaneLayout</code>
130 * determines the size to make the viewport view in one of two ways:
131 * <ol>
132 * <li>If the view implements <code>Scrollable</code>
133 * a combination of <code>getPreferredScrollableViewportSize</code>,
134 * <code>getScrollableTracksViewportWidth</code> and
135 * <code>getScrollableTracksViewportHeight</code>is used, otherwise
136 * <li><code>getPreferredSize</code> is used.
137 * </ol>
138 * <p>
139 * <strong>Warning:</strong> Swing is not thread safe. For more
140 * information see <a
141 * href="package-summary.html#threading">Swing's Threading
142 * Policy</a>.
143 * <p>
144 * <strong>Warning:</strong>
145 * Serialized objects of this class will not be compatible with
146 * future Swing releases. The current serialization support is
147 * appropriate for short term storage or RMI between applications running
148 * the same version of Swing. As of 1.4, support for long term storage
149 * of all JavaBeans™
150 * has been added to the <code>java.beans</code> package.
151 * Please see {@link java.beans.XMLEncoder}.
152 *
153 * @see JScrollBar
154 * @see JViewport
155 * @see ScrollPaneLayout
156 * @see Scrollable
157 * @see Component#getPreferredSize
158 * @see #setViewportView
159 * @see #setRowHeaderView
160 * @see #setColumnHeaderView
161 * @see #setCorner
162 * @see #setViewportBorder
163 *
164 * @beaninfo
165 * attribute: isContainer true
166 * attribute: containerDelegate getViewport
167 * description: A specialized container that manages a viewport, optional scrollbars and headers
168 *
169 * @author Hans Muller
170 * @since 1.2
171 */
172 @SuppressWarnings("serial") // Same-version serialization only
173 public class JScrollPane extends JComponent implements ScrollPaneConstants, Accessible
174 {
175 private Border viewportBorder;
176
177 /**
178 * @see #getUIClassID
179 * @see #readObject
180 */
181 private static final String uiClassID = "ScrollPaneUI";
182
183 /**
184 * The display policy for the vertical scrollbar.
185 * The default is
186 * <code>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED</code>.
187 * @see #setVerticalScrollBarPolicy
188 */
189 protected int verticalScrollBarPolicy = VERTICAL_SCROLLBAR_AS_NEEDED;
190
191
192 /**
193 * The display policy for the horizontal scrollbar.
194 * The default is
195 * <code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED</code>.
196 * @see #setHorizontalScrollBarPolicy
197 */
198 protected int horizontalScrollBarPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED;
199
200
201 /**
202 * The scrollpane's viewport child. Default is an empty
203 * <code>JViewport</code>.
204 * @see #setViewport
205 */
206 protected JViewport viewport;
207
208
209 /**
210 * The scrollpane's vertical scrollbar child.
211 * Default is a <code>JScrollBar</code>.
212 * @see #setVerticalScrollBar
213 */
214 protected JScrollBar verticalScrollBar;
215
216
217 /**
218 * The scrollpane's horizontal scrollbar child.
219 * Default is a <code>JScrollBar</code>.
220 * @see #setHorizontalScrollBar
221 */
222 protected JScrollBar horizontalScrollBar;
223
224
225 /**
226 * The row header child. Default is <code>null</code>.
227 * @see #setRowHeader
228 */
229 protected JViewport rowHeader;
230
231
232 /**
233 * The column header child. Default is <code>null</code>.
234 * @see #setColumnHeader
235 */
236 protected JViewport columnHeader;
237
238
239 /**
240 * The component to display in the lower left corner.
241 * Default is <code>null</code>.
242 * @see #setCorner
243 */
244 protected Component lowerLeft;
245
246
247 /**
248 * The component to display in the lower right corner.
249 * Default is <code>null</code>.
250 * @see #setCorner
251 */
252 protected Component lowerRight;
253
254
255 /**
256 * The component to display in the upper left corner.
257 * Default is <code>null</code>.
258 * @see #setCorner
259 */
260 protected Component upperLeft;
261
262
263 /**
264 * The component to display in the upper right corner.
265 * Default is <code>null</code>.
266 * @see #setCorner
267 */
268 protected Component upperRight;
269
270 /*
271 * State flag for mouse wheel scrolling
272 */
273 private boolean wheelScrollState = true;
274
275 /**
276 * Creates a <code>JScrollPane</code> that displays the view
277 * component in a viewport
278 * whose view position can be controlled with a pair of scrollbars.
279 * The scrollbar policies specify when the scrollbars are displayed,
280 * For example, if <code>vsbPolicy</code> is
281 * <code>VERTICAL_SCROLLBAR_AS_NEEDED</code>
282 * then the vertical scrollbar only appears if the view doesn't fit
283 * vertically. The available policy settings are listed at
284 * {@link #setVerticalScrollBarPolicy} and
285 * {@link #setHorizontalScrollBarPolicy}.
286 *
287 * @see #setViewportView
288 *
289 * @param view the component to display in the scrollpanes viewport
290 * @param vsbPolicy an integer that specifies the vertical
291 * scrollbar policy
292 * @param hsbPolicy an integer that specifies the horizontal
293 * scrollbar policy
294 */
295 public JScrollPane(Component view, int vsbPolicy, int hsbPolicy)
296 {
297 setLayout(new ScrollPaneLayout.UIResource());
298 setVerticalScrollBarPolicy(vsbPolicy);
299 setHorizontalScrollBarPolicy(hsbPolicy);
300 setViewport(createViewport());
301 setVerticalScrollBar(createVerticalScrollBar());
302 setHorizontalScrollBar(createHorizontalScrollBar());
303 if (view != null) {
304 setViewportView(view);
305 }
306 setUIProperty("opaque",true);
307 updateUI();
308
309 if (!this.getComponentOrientation().isLeftToRight()) {
310 viewport.setViewPosition(new Point(Integer.MAX_VALUE, 0));
311 }
312 }
313
314
315 /**
316 * Creates a <code>JScrollPane</code> that displays the
317 * contents of the specified
318 * component, where both horizontal and vertical scrollbars appear
319 * whenever the component's contents are larger than the view.
320 *
321 * @see #setViewportView
322 * @param view the component to display in the scrollpane's viewport
323 */
324 public JScrollPane(Component view) {
325 this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
326 }
327
328
329 /**
330 * Creates an empty (no viewport view) <code>JScrollPane</code>
331 * with specified
332 * scrollbar policies. The available policy settings are listed at
333 * {@link #setVerticalScrollBarPolicy} and
334 * {@link #setHorizontalScrollBarPolicy}.
335 *
336 * @see #setViewportView
337 *
338 * @param vsbPolicy an integer that specifies the vertical
339 * scrollbar policy
340 * @param hsbPolicy an integer that specifies the horizontal
341 * scrollbar policy
342 */
343 public JScrollPane(int vsbPolicy, int hsbPolicy) {
344 this(null, vsbPolicy, hsbPolicy);
345 }
346
347
348 /**
349 * Creates an empty (no viewport view) <code>JScrollPane</code>
350 * where both horizontal and vertical scrollbars appear when needed.
351 */
352 public JScrollPane() {
353 this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
354 }
355
356
357 /**
358 * Returns the look and feel (L&F) object that renders this component.
359 *
360 * @return the <code>ScrollPaneUI</code> object that renders this
361 * component
362 * @see #setUI
363 * @beaninfo
364 * bound: true
365 * hidden: true
366 * attribute: visualUpdate true
367 * description: The UI object that implements the Component's LookAndFeel.
368 */
369 public ScrollPaneUI getUI() {
370 return (ScrollPaneUI)ui;
371 }
372
373
374 /**
375 * Sets the <code>ScrollPaneUI</code> object that provides the
376 * look and feel (L&F) for this component.
377 *
378 * @param ui the <code>ScrollPaneUI</code> L&F object
379 * @see #getUI
380 */
381 public void setUI(ScrollPaneUI ui) {
382 super.setUI(ui);
383 }
384
385
386 /**
387 * Replaces the current <code>ScrollPaneUI</code> object with a version
388 * from the current default look and feel.
389 * To be called when the default look and feel changes.
390 *
391 * @see JComponent#updateUI
392 * @see UIManager#getUI
393 */
394 public void updateUI() {
395 setUI((ScrollPaneUI)UIManager.getUI(this));
396 }
397
398
399 /**
400 * Returns the suffix used to construct the name of the L&F class used to
401 * render this component.
402 *
403 * @return the string "ScrollPaneUI"
404 * @see JComponent#getUIClassID
405 * @see UIDefaults#getUI
406 *
407 * @beaninfo
408 * hidden: true
409 */
410 public String getUIClassID() {
411 return uiClassID;
412 }
413
414
415
416 /**
417 * Sets the layout manager for this <code>JScrollPane</code>.
418 * This method overrides <code>setLayout</code> in
419 * <code>java.awt.Container</code> to ensure that only
420 * <code>LayoutManager</code>s which
421 * are subclasses of <code>ScrollPaneLayout</code> can be used in a
422 * <code>JScrollPane</code>. If <code>layout</code> is non-null, this
423 * will invoke <code>syncWithScrollPane</code> on it.
424 *
425 * @param layout the specified layout manager
426 * @exception ClassCastException if layout is not a
427 * <code>ScrollPaneLayout</code>
428 * @see java.awt.Container#getLayout
429 * @see java.awt.Container#setLayout
430 *
431 * @beaninfo
432 * hidden: true
433 */
434 public void setLayout(LayoutManager layout) {
435 if (layout instanceof ScrollPaneLayout) {
436 super.setLayout(layout);
437 ((ScrollPaneLayout)layout).syncWithScrollPane(this);
438 }
439 else if (layout == null) {
440 super.setLayout(layout);
441 }
442 else {
443 String s = "layout of JScrollPane must be a ScrollPaneLayout";
444 throw new ClassCastException(s);
445 }
446 }
447
448 /**
449 * Overridden to return true so that any calls to <code>revalidate</code>
450 * on any descendants of this <code>JScrollPane</code> will cause the
451 * entire tree beginning with this <code>JScrollPane</code> to be
452 * validated.
453 *
454 * @return true
455 * @see java.awt.Container#validate
456 * @see JComponent#revalidate
457 * @see JComponent#isValidateRoot
458 * @see java.awt.Container#isValidateRoot
459 *
460 * @beaninfo
461 * hidden: true
462 */
463 @Override
464 public boolean isValidateRoot() {
465 return true;
466 }
467
468
469 /**
470 * Returns the vertical scroll bar policy value.
471 * @return the <code>verticalScrollBarPolicy</code> property
472 * @see #setVerticalScrollBarPolicy
473 */
474 public int getVerticalScrollBarPolicy() {
475 return verticalScrollBarPolicy;
476 }
477
478
479 /**
480 * Determines when the vertical scrollbar appears in the scrollpane.
481 * Legal values are:
482 * <ul>
483 * <li><code>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED</code>
484 * <li><code>ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER</code>
485 * <li><code>ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS</code>
486 * </ul>
487 *
488 * @param policy one of the three values listed above
489 * @exception IllegalArgumentException if <code>policy</code>
490 * is not one of the legal values shown above
491 * @see #getVerticalScrollBarPolicy
492 *
493 * @beaninfo
494 * preferred: true
495 * bound: true
496 * description: The scrollpane vertical scrollbar policy
497 * enum: VERTICAL_SCROLLBAR_AS_NEEDED ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
498 * VERTICAL_SCROLLBAR_NEVER ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER
499 * VERTICAL_SCROLLBAR_ALWAYS ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
500 */
501 public void setVerticalScrollBarPolicy(int policy) {
502 switch (policy) {
503 case VERTICAL_SCROLLBAR_AS_NEEDED:
504 case VERTICAL_SCROLLBAR_NEVER:
505 case VERTICAL_SCROLLBAR_ALWAYS:
506 break;
507 default:
508 throw new IllegalArgumentException("invalid verticalScrollBarPolicy");
509 }
510 int old = verticalScrollBarPolicy;
511 verticalScrollBarPolicy = policy;
512 firePropertyChange("verticalScrollBarPolicy", old, policy);
513 revalidate();
514 repaint();
515 }
516
517
518 /**
519 * Returns the horizontal scroll bar policy value.
520 * @return the <code>horizontalScrollBarPolicy</code> property
521 * @see #setHorizontalScrollBarPolicy
522 */
523 public int getHorizontalScrollBarPolicy() {
524 return horizontalScrollBarPolicy;
525 }
526
527
528 /**
529 * Determines when the horizontal scrollbar appears in the scrollpane.
530 * The options are:<ul>
531 * <li><code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED</code>
532 * <li><code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER</code>
533 * <li><code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS</code>
534 * </ul>
535 *
536 * @param policy one of the three values listed above
537 * @exception IllegalArgumentException if <code>policy</code>
538 * is not one of the legal values shown above
539 * @see #getHorizontalScrollBarPolicy
540 *
541 * @beaninfo
542 * preferred: true
543 * bound: true
544 * description: The scrollpane scrollbar policy
545 * enum: HORIZONTAL_SCROLLBAR_AS_NEEDED ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
546 * HORIZONTAL_SCROLLBAR_NEVER ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
547 * HORIZONTAL_SCROLLBAR_ALWAYS ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
548 */
549 public void setHorizontalScrollBarPolicy(int policy) {
550 switch (policy) {
551 case HORIZONTAL_SCROLLBAR_AS_NEEDED:
552 case HORIZONTAL_SCROLLBAR_NEVER:
553 case HORIZONTAL_SCROLLBAR_ALWAYS:
554 break;
555 default:
556 throw new IllegalArgumentException("invalid horizontalScrollBarPolicy");
557 }
558 int old = horizontalScrollBarPolicy;
559 horizontalScrollBarPolicy = policy;
560 firePropertyChange("horizontalScrollBarPolicy", old, policy);
561 revalidate();
562 repaint();
563 }
564
565
566 /**
567 * Returns the <code>Border</code> object that surrounds the viewport.
568 *
569 * @return the <code>viewportBorder</code> property
570 * @see #setViewportBorder
571 */
572 public Border getViewportBorder() {
573 return viewportBorder;
574 }
575
576
577 /**
578 * Adds a border around the viewport. Note that the border isn't
579 * set on the viewport directly, <code>JViewport</code> doesn't support
580 * the <code>JComponent</code> border property.
581 * Similarly setting the <code>JScrollPane</code>s
582 * viewport doesn't affect the <code>viewportBorder</code> property.
583 * <p>
584 * The default value of this property is computed by the look
585 * and feel implementation.
586 *
587 * @param viewportBorder the border to be added
588 * @see #getViewportBorder
589 * @see #setViewport
590 *
591 * @beaninfo
592 * preferred: true
593 * bound: true
594 * description: The border around the viewport.
595 */
596 public void setViewportBorder(Border viewportBorder) {
597 Border oldValue = this.viewportBorder;
598 this.viewportBorder = viewportBorder;
599 firePropertyChange("viewportBorder", oldValue, viewportBorder);
600 }
601
602
603 /**
604 * Returns the bounds of the viewport's border.
605 *
606 * @return a <code>Rectangle</code> object specifying the viewport border
607 */
608 public Rectangle getViewportBorderBounds()
609 {
610 Rectangle borderR = new Rectangle(getSize());
611
612 Insets insets = getInsets();
613 borderR.x = insets.left;
614 borderR.y = insets.top;
615 borderR.width -= insets.left + insets.right;
616 borderR.height -= insets.top + insets.bottom;
617
618 boolean leftToRight = SwingUtilities.isLeftToRight(this);
619
620 /* If there's a visible column header remove the space it
621 * needs from the top of borderR.
622 */
623
624 JViewport colHead = getColumnHeader();
625 if ((colHead != null) && (colHead.isVisible())) {
626 int colHeadHeight = colHead.getHeight();
649 int vsbWidth = vsb.getWidth();
650 if ( !leftToRight ) {
651 borderR.x += vsbWidth;
652 }
653 borderR.width -= vsbWidth;
654 }
655
656 /* If there's a visible horizontal scrollbar remove the space it needs
657 * from the height of borderR.
658 */
659 JScrollBar hsb = getHorizontalScrollBar();
660 if ((hsb != null) && (hsb.isVisible())) {
661 borderR.height -= hsb.getHeight();
662 }
663
664 return borderR;
665 }
666
667
668 /**
669 * By default <code>JScrollPane</code> creates scrollbars
670 * that are instances
671 * of this class. <code>Scrollbar</code> overrides the
672 * <code>getUnitIncrement</code> and <code>getBlockIncrement</code>
673 * methods so that, if the viewport's view is a <code>Scrollable</code>,
674 * the view is asked to compute these values. Unless
675 * the unit/block increment have been explicitly set.
676 * <p>
677 * <strong>Warning:</strong>
678 * Serialized objects of this class will not be compatible with
679 * future Swing releases. The current serialization support is
680 * appropriate for short term storage or RMI between applications running
681 * the same version of Swing. As of 1.4, support for long term storage
682 * of all JavaBeans™
683 * has been added to the <code>java.beans</code> package.
684 * Please see {@link java.beans.XMLEncoder}.
685 *
686 * @see Scrollable
687 * @see JScrollPane#createVerticalScrollBar
688 * @see JScrollPane#createHorizontalScrollBar
689 */
690 @SuppressWarnings("serial") // Same-version serialization only
691 protected class ScrollBar extends JScrollBar implements UIResource
692 {
693 /**
694 * Set to true when the unit increment has been explicitly set.
695 * If this is false the viewport's view is obtained and if it
696 * is an instance of <code>Scrollable</code> the unit increment
697 * from it is used.
698 */
699 private boolean unitIncrementSet;
700 /**
701 * Set to true when the block increment has been explicitly set.
702 * If this is false the viewport's view is obtained and if it
703 * is an instance of <code>Scrollable</code> the block increment
704 * from it is used.
705 */
706 private boolean blockIncrementSet;
707
708 /**
709 * Creates a scrollbar with the specified orientation.
710 * The options are:
711 * <ul>
712 * <li><code>ScrollPaneConstants.VERTICAL</code>
713 * <li><code>ScrollPaneConstants.HORIZONTAL</code>
714 * </ul>
715 *
716 * @param orientation an integer specifying one of the legal
717 * orientation values shown above
718 * @since 1.4
719 */
720 public ScrollBar(int orientation) {
721 super(orientation);
722 this.putClientProperty("JScrollBar.fastWheelScrolling",
723 Boolean.TRUE);
724 }
725
726 /**
727 * Messages super to set the value, and resets the
728 * <code>unitIncrementSet</code> instance variable to true.
729 *
730 * @param unitIncrement the new unit increment value, in pixels
731 */
732 public void setUnitIncrement(int unitIncrement) {
733 unitIncrementSet = true;
734 this.putClientProperty("JScrollBar.fastWheelScrolling", null);
735 super.setUnitIncrement(unitIncrement);
736 }
737
738 /**
739 * Computes the unit increment for scrolling if the viewport's
740 * view is a <code>Scrollable</code> object.
741 * Otherwise return <code>super.getUnitIncrement</code>.
742 *
743 * @param direction less than zero to scroll up/left,
744 * greater than zero for down/right
745 * @return an integer, in pixels, containing the unit increment
746 * @see Scrollable#getScrollableUnitIncrement
747 */
748 public int getUnitIncrement(int direction) {
749 JViewport vp = getViewport();
750 if (!unitIncrementSet && (vp != null) &&
751 (vp.getView() instanceof Scrollable)) {
752 Scrollable view = (Scrollable)(vp.getView());
753 Rectangle vr = vp.getViewRect();
754 return view.getScrollableUnitIncrement(vr, getOrientation(), direction);
755 }
756 else {
757 return super.getUnitIncrement(direction);
758 }
759 }
760
761 /**
762 * Messages super to set the value, and resets the
763 * <code>blockIncrementSet</code> instance variable to true.
764 *
765 * @param blockIncrement the new block increment value, in pixels
766 */
767 public void setBlockIncrement(int blockIncrement) {
768 blockIncrementSet = true;
769 this.putClientProperty("JScrollBar.fastWheelScrolling", null);
770 super.setBlockIncrement(blockIncrement);
771 }
772
773 /**
774 * Computes the block increment for scrolling if the viewport's
775 * view is a <code>Scrollable</code> object. Otherwise
776 * the <code>blockIncrement</code> equals the viewport's width
777 * or height. If there's no viewport return
778 * <code>super.getBlockIncrement</code>.
779 *
780 * @param direction less than zero to scroll up/left,
781 * greater than zero for down/right
782 * @return an integer, in pixels, containing the block increment
783 * @see Scrollable#getScrollableBlockIncrement
784 */
785 public int getBlockIncrement(int direction) {
786 JViewport vp = getViewport();
787 if (blockIncrementSet || vp == null) {
788 return super.getBlockIncrement(direction);
789 }
790 else if (vp.getView() instanceof Scrollable) {
791 Scrollable view = (Scrollable)(vp.getView());
792 Rectangle vr = vp.getViewRect();
793 return view.getScrollableBlockIncrement(vr, getOrientation(), direction);
794 }
795 else if (getOrientation() == VERTICAL) {
796 return vp.getExtentSize().height;
797 }
798 else {
799 return vp.getExtentSize().width;
800 }
801 }
802
803 }
804
805
806 /**
807 * Returns a <code>JScrollPane.ScrollBar</code> by default.
808 * Subclasses may override this method to force <code>ScrollPaneUI</code>
809 * implementations to use a <code>JScrollBar</code> subclass.
810 * Used by <code>ScrollPaneUI</code> implementations to
811 * create the horizontal scrollbar.
812 *
813 * @return a <code>JScrollBar</code> with a horizontal orientation
814 * @see JScrollBar
815 */
816 public JScrollBar createHorizontalScrollBar() {
817 return new ScrollBar(JScrollBar.HORIZONTAL);
818 }
819
820
821 /**
822 * Returns the horizontal scroll bar that controls the viewport's
823 * horizontal view position.
824 *
825 * @return the <code>horizontalScrollBar</code> property
826 * @see #setHorizontalScrollBar
827 */
828 @Transient
829 public JScrollBar getHorizontalScrollBar() {
830 return horizontalScrollBar;
831 }
832
833
834 /**
835 * Adds the scrollbar that controls the viewport's horizontal view
836 * position to the scrollpane.
837 * This is usually unnecessary, as <code>JScrollPane</code> creates
838 * horizontal and vertical scrollbars by default.
839 *
840 * @param horizontalScrollBar the horizontal scrollbar to be added
841 * @see #createHorizontalScrollBar
842 * @see #getHorizontalScrollBar
843 *
844 * @beaninfo
845 * expert: true
846 * bound: true
847 * description: The horizontal scrollbar.
848 */
849 public void setHorizontalScrollBar(JScrollBar horizontalScrollBar) {
850 JScrollBar old = getHorizontalScrollBar();
851 this.horizontalScrollBar = horizontalScrollBar;
852 if (horizontalScrollBar != null) {
853 add(horizontalScrollBar, HORIZONTAL_SCROLLBAR);
854 }
855 else if (old != null) {
856 remove(old);
857 }
858 firePropertyChange("horizontalScrollBar", old, horizontalScrollBar);
859
860 revalidate();
861 repaint();
862 }
863
864
865 /**
866 * Returns a <code>JScrollPane.ScrollBar</code> by default. Subclasses
867 * may override this method to force <code>ScrollPaneUI</code>
868 * implementations to use a <code>JScrollBar</code> subclass.
869 * Used by <code>ScrollPaneUI</code> implementations to create the
870 * vertical scrollbar.
871 *
872 * @return a <code>JScrollBar</code> with a vertical orientation
873 * @see JScrollBar
874 */
875 public JScrollBar createVerticalScrollBar() {
876 return new ScrollBar(JScrollBar.VERTICAL);
877 }
878
879
880 /**
881 * Returns the vertical scroll bar that controls the viewports
882 * vertical view position.
883 *
884 * @return the <code>verticalScrollBar</code> property
885 * @see #setVerticalScrollBar
886 */
887 @Transient
888 public JScrollBar getVerticalScrollBar() {
889 return verticalScrollBar;
890 }
891
892
893 /**
894 * Adds the scrollbar that controls the viewports vertical view position
895 * to the scrollpane. This is usually unnecessary,
896 * as <code>JScrollPane</code> creates vertical and
897 * horizontal scrollbars by default.
898 *
899 * @param verticalScrollBar the new vertical scrollbar to be added
900 * @see #createVerticalScrollBar
901 * @see #getVerticalScrollBar
902 *
903 * @beaninfo
904 * expert: true
905 * bound: true
906 * description: The vertical scrollbar.
907 */
908 public void setVerticalScrollBar(JScrollBar verticalScrollBar) {
909 JScrollBar old = getVerticalScrollBar();
910 this.verticalScrollBar = verticalScrollBar;
911 add(verticalScrollBar, VERTICAL_SCROLLBAR);
912 firePropertyChange("verticalScrollBar", old, verticalScrollBar);
913
914 revalidate();
915 repaint();
916 }
917
918
919 /**
920 * Returns a new <code>JViewport</code> by default.
921 * Used to create the
922 * viewport (as needed) in <code>setViewportView</code>,
923 * <code>setRowHeaderView</code>, and <code>setColumnHeaderView</code>.
924 * Subclasses may override this method to return a subclass of
925 * <code>JViewport</code>.
926 *
927 * @return a new <code>JViewport</code>
928 */
929 protected JViewport createViewport() {
930 return new JViewport();
931 }
932
933
934 /**
935 * Returns the current <code>JViewport</code>.
936 *
937 * @see #setViewport
938 * @return the <code>viewport</code> property
939 */
940 public JViewport getViewport() {
941 return viewport;
942 }
943
944
945 /**
946 * Removes the old viewport (if there is one); forces the
947 * viewPosition of the new viewport to be in the +x,+y quadrant;
948 * syncs up the row and column headers (if there are any) with the
949 * new viewport; and finally syncs the scrollbars and
950 * headers with the new viewport.
951 * <p>
952 * Most applications will find it more convenient to use
953 * <code>setViewportView</code>
954 * to add a viewport and a view to the scrollpane.
955 *
956 * @param viewport the new viewport to be used; if viewport is
957 * <code>null</code>, the old viewport is still removed
958 * and the new viewport is set to <code>null</code>
959 * @see #createViewport
960 * @see #getViewport
961 * @see #setViewportView
962 *
963 * @beaninfo
964 * expert: true
965 * bound: true
966 * attribute: visualUpdate true
967 * description: The viewport child for this scrollpane
968 *
969 */
970 public void setViewport(JViewport viewport) {
971 JViewport old = getViewport();
972 this.viewport = viewport;
973 if (viewport != null) {
974 add(viewport, VIEWPORT);
975 }
976 else if (old != null) {
977 remove(old);
978 }
979 firePropertyChange("viewport", old, viewport);
980
981 if (accessibleContext != null) {
982 ((AccessibleJScrollPane)accessibleContext).resetViewPort();
983 }
984
985 revalidate();
986 repaint();
987 }
988
989
990 /**
991 * Creates a viewport if necessary and then sets its view. Applications
992 * that don't provide the view directly to the <code>JScrollPane</code>
993 * constructor
994 * should use this method to specify the scrollable child that's going
995 * to be displayed in the scrollpane. For example:
996 * <pre>
997 * JScrollPane scrollpane = new JScrollPane();
998 * scrollpane.setViewportView(myBigComponentToScroll);
999 * </pre>
1000 * Applications should not add children directly to the scrollpane.
1001 *
1002 * @param view the component to add to the viewport
1003 * @see #setViewport
1004 * @see JViewport#setView
1005 */
1006 public void setViewportView(Component view) {
1007 if (getViewport() == null) {
1008 setViewport(createViewport());
1009 }
1010 getViewport().setView(view);
1011 }
1012
1013
1014
1015 /**
1016 * Returns the row header.
1017 * @return the <code>rowHeader</code> property
1018 * @see #setRowHeader
1019 */
1020 @Transient
1021 public JViewport getRowHeader() {
1022 return rowHeader;
1023 }
1024
1025
1026 /**
1027 * Removes the old rowHeader, if it exists; if the new rowHeader
1028 * isn't <code>null</code>, syncs the y coordinate of its
1029 * viewPosition with
1030 * the viewport (if there is one) and then adds it to the scroll pane.
1031 * <p>
1032 * Most applications will find it more convenient to use
1033 * <code>setRowHeaderView</code>
1034 * to add a row header component and its viewport to the scroll pane.
1035 *
1036 * @param rowHeader the new row header to be used; if <code>null</code>
1037 * the old row header is still removed and the new rowHeader
1038 * is set to <code>null</code>
1039 * @see #getRowHeader
1040 * @see #setRowHeaderView
1041 *
1042 * @beaninfo
1043 * bound: true
1044 * expert: true
1045 * description: The row header child for this scrollpane
1046 */
1047 public void setRowHeader(JViewport rowHeader) {
1048 JViewport old = getRowHeader();
1049 this.rowHeader = rowHeader;
1050 if (rowHeader != null) {
1051 add(rowHeader, ROW_HEADER);
1052 }
1053 else if (old != null) {
1054 remove(old);
1055 }
1056 firePropertyChange("rowHeader", old, rowHeader);
1057 revalidate();
1058 repaint();
1067 * JScrollPane scrollpane = new JScrollPane();
1068 * scrollpane.setViewportView(myBigComponentToScroll);
1069 * scrollpane.setRowHeaderView(myBigComponentsRowHeader);
1070 * </pre>
1071 *
1072 * @see #setRowHeader
1073 * @see JViewport#setView
1074 * @param view the component to display as the row header
1075 */
1076 public void setRowHeaderView(Component view) {
1077 if (getRowHeader() == null) {
1078 setRowHeader(createViewport());
1079 }
1080 getRowHeader().setView(view);
1081 }
1082
1083
1084
1085 /**
1086 * Returns the column header.
1087 * @return the <code>columnHeader</code> property
1088 * @see #setColumnHeader
1089 */
1090 @Transient
1091 public JViewport getColumnHeader() {
1092 return columnHeader;
1093 }
1094
1095
1096 /**
1097 * Removes the old columnHeader, if it exists; if the new columnHeader
1098 * isn't <code>null</code>, syncs the x coordinate of its viewPosition
1099 * with the viewport (if there is one) and then adds it to the scroll pane.
1100 * <p>
1101 * Most applications will find it more convenient to use
1102 * <code>setColumnHeaderView</code>
1103 * to add a column header component and its viewport to the scroll pane.
1104 *
1105 * @param columnHeader a {@code JViewport} which is the new column header
1106 * @see #getColumnHeader
1107 * @see #setColumnHeaderView
1108 *
1109 * @beaninfo
1110 * bound: true
1111 * description: The column header child for this scrollpane
1112 * attribute: visualUpdate true
1113 */
1114 public void setColumnHeader(JViewport columnHeader) {
1115 JViewport old = getColumnHeader();
1116 this.columnHeader = columnHeader;
1117 if (columnHeader != null) {
1118 add(columnHeader, COLUMN_HEADER);
1119 }
1120 else if (old != null) {
1121 remove(old);
1122 }
1136 * JScrollPane scrollpane = new JScrollPane();
1137 * scrollpane.setViewportView(myBigComponentToScroll);
1138 * scrollpane.setColumnHeaderView(myBigComponentsColumnHeader);
1139 * </pre>
1140 *
1141 * @see #setColumnHeader
1142 * @see JViewport#setView
1143 *
1144 * @param view the component to display as the column header
1145 */
1146 public void setColumnHeaderView(Component view) {
1147 if (getColumnHeader() == null) {
1148 setColumnHeader(createViewport());
1149 }
1150 getColumnHeader().setView(view);
1151 }
1152
1153
1154 /**
1155 * Returns the component at the specified corner. The
1156 * <code>key</code> value specifying the corner is one of:
1157 * <ul>
1158 * <li>ScrollPaneConstants.LOWER_LEFT_CORNER
1159 * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
1160 * <li>ScrollPaneConstants.UPPER_LEFT_CORNER
1161 * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
1162 * <li>ScrollPaneConstants.LOWER_LEADING_CORNER
1163 * <li>ScrollPaneConstants.LOWER_TRAILING_CORNER
1164 * <li>ScrollPaneConstants.UPPER_LEADING_CORNER
1165 * <li>ScrollPaneConstants.UPPER_TRAILING_CORNER
1166 * </ul>
1167 *
1168 * @param key one of the values as shown above
1169 * @return the corner component (which may be <code>null</code>)
1170 * identified by the given key, or <code>null</code>
1171 * if the key is invalid
1172 * @see #setCorner
1173 */
1174 public Component getCorner(String key) {
1175 boolean isLeftToRight = getComponentOrientation().isLeftToRight();
1176 if (key.equals(LOWER_LEADING_CORNER)) {
1177 key = isLeftToRight ? LOWER_LEFT_CORNER : LOWER_RIGHT_CORNER;
1178 } else if (key.equals(LOWER_TRAILING_CORNER)) {
1179 key = isLeftToRight ? LOWER_RIGHT_CORNER : LOWER_LEFT_CORNER;
1180 } else if (key.equals(UPPER_LEADING_CORNER)) {
1181 key = isLeftToRight ? UPPER_LEFT_CORNER : UPPER_RIGHT_CORNER;
1182 } else if (key.equals(UPPER_TRAILING_CORNER)) {
1183 key = isLeftToRight ? UPPER_RIGHT_CORNER : UPPER_LEFT_CORNER;
1184 }
1185 if (key.equals(LOWER_LEFT_CORNER)) {
1186 return lowerLeft;
1187 }
1188 else if (key.equals(LOWER_RIGHT_CORNER)) {
1189 return lowerRight;
1190 }
1202
1203 /**
1204 * Adds a child that will appear in one of the scroll panes
1205 * corners, if there's room. For example with both scrollbars
1206 * showing (on the right and bottom edges of the scrollpane)
1207 * the lower left corner component will be shown in the space
1208 * between ends of the two scrollbars. Legal values for
1209 * the <b>key</b> are:
1210 * <ul>
1211 * <li>ScrollPaneConstants.LOWER_LEFT_CORNER
1212 * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
1213 * <li>ScrollPaneConstants.UPPER_LEFT_CORNER
1214 * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
1215 * <li>ScrollPaneConstants.LOWER_LEADING_CORNER
1216 * <li>ScrollPaneConstants.LOWER_TRAILING_CORNER
1217 * <li>ScrollPaneConstants.UPPER_LEADING_CORNER
1218 * <li>ScrollPaneConstants.UPPER_TRAILING_CORNER
1219 * </ul>
1220 * <p>
1221 * Although "corner" doesn't match any beans property
1222 * signature, <code>PropertyChange</code> events are generated with the
1223 * property name set to the corner key.
1224 *
1225 * @param key identifies which corner the component will appear in
1226 * @param corner one of the following components:
1227 * <ul>
1228 * <li>lowerLeft
1229 * <li>lowerRight
1230 * <li>upperLeft
1231 * <li>upperRight
1232 * </ul>
1233 * @exception IllegalArgumentException if corner key is invalid
1234 */
1235 public void setCorner(String key, Component corner)
1236 {
1237 Component old;
1238 boolean isLeftToRight = getComponentOrientation().isLeftToRight();
1239 if (key.equals(LOWER_LEADING_CORNER)) {
1240 key = isLeftToRight ? LOWER_LEFT_CORNER : LOWER_RIGHT_CORNER;
1241 } else if (key.equals(LOWER_TRAILING_CORNER)) {
1242 key = isLeftToRight ? LOWER_RIGHT_CORNER : LOWER_LEFT_CORNER;
1261 old = upperRight;
1262 upperRight = corner;
1263 }
1264 else {
1265 throw new IllegalArgumentException("invalid corner key");
1266 }
1267 if (old != null) {
1268 remove(old);
1269 }
1270 if (corner != null) {
1271 add(corner, key);
1272 }
1273 firePropertyChange(key, old, corner);
1274 revalidate();
1275 repaint();
1276 }
1277
1278 /**
1279 * Sets the orientation for the vertical and horizontal
1280 * scrollbars as determined by the
1281 * <code>ComponentOrientation</code> argument.
1282 *
1283 * @param co one of the following values:
1284 * <ul>
1285 * <li>java.awt.ComponentOrientation.LEFT_TO_RIGHT
1286 * <li>java.awt.ComponentOrientation.RIGHT_TO_LEFT
1287 * <li>java.awt.ComponentOrientation.UNKNOWN
1288 * </ul>
1289 * @see java.awt.ComponentOrientation
1290 */
1291 public void setComponentOrientation( ComponentOrientation co ) {
1292 super.setComponentOrientation( co );
1293 if( verticalScrollBar != null )
1294 verticalScrollBar.setComponentOrientation( co );
1295 if( horizontalScrollBar != null )
1296 horizontalScrollBar.setComponentOrientation( co );
1297 }
1298
1299 /**
1300 * Indicates whether or not scrolling will take place in response to the
1301 * mouse wheel. Wheel scrolling is enabled by default.
1302 *
1303 * @return true if mouse wheel scrolling is enabled, false otherwise
1304 * @see #setWheelScrollingEnabled
1305 * @since 1.4
1306 * @beaninfo
1307 * bound: true
1308 * description: Flag for enabling/disabling mouse wheel scrolling
1309 */
1310 public boolean isWheelScrollingEnabled() {return wheelScrollState;}
1311
1312 /**
1313 * Enables/disables scrolling in response to movement of the mouse wheel.
1314 * Wheel scrolling is enabled by default.
1315 *
1316 * @param handleWheel <code>true</code> if scrolling should be done
1317 * automatically for a MouseWheelEvent,
1318 * <code>false</code> otherwise.
1319 * @see #isWheelScrollingEnabled
1320 * @see java.awt.event.MouseWheelEvent
1321 * @see java.awt.event.MouseWheelListener
1322 * @since 1.4
1323 * @beaninfo
1324 * bound: true
1325 * description: Flag for enabling/disabling mouse wheel scrolling
1326 */
1327 public void setWheelScrollingEnabled(boolean handleWheel) {
1328 boolean old = wheelScrollState;
1329 wheelScrollState = handleWheel;
1330 firePropertyChange("wheelScrollingEnabled", old, handleWheel);
1331 }
1332
1333 /**
1334 * See <code>readObject</code> and <code>writeObject</code> in
1335 * <code>JComponent</code> for more
1336 * information about serialization in Swing.
1337 */
1338 private void writeObject(ObjectOutputStream s) throws IOException {
1339 s.defaultWriteObject();
1340 if (getUIClassID().equals(uiClassID)) {
1341 byte count = JComponent.getWriteObjCounter(this);
1342 JComponent.setWriteObjCounter(this, --count);
1343 if (count == 0 && ui != null) {
1344 ui.installUI(this);
1345 }
1346 }
1347 }
1348
1349
1350 /**
1351 * Returns a string representation of this <code>JScrollPane</code>.
1352 * This method
1353 * is intended to be used only for debugging purposes, and the
1354 * content and format of the returned string may vary between
1355 * implementations. The returned string may be empty but may not
1356 * be <code>null</code>.
1357 *
1358 * @return a string representation of this <code>JScrollPane</code>.
1359 */
1360 protected String paramString() {
1361 String viewportBorderString = (viewportBorder != null ?
1362 viewportBorder.toString() : "");
1363 String viewportString = (viewport != null ?
1364 viewport.toString() : "");
1365 String verticalScrollBarPolicyString;
1366 if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_AS_NEEDED) {
1367 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_AS_NEEDED";
1368 } else if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_NEVER) {
1369 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_NEVER";
1370 } else if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
1371 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_ALWAYS";
1372 } else verticalScrollBarPolicyString = "";
1373 String horizontalScrollBarPolicyString;
1374 if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED) {
1375 horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_AS_NEEDED";
1376 } else if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_NEVER) {
1377 horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_NEVER";
1378 } else if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) {
1416 ////////////////
1417
1418 /**
1419 * Gets the AccessibleContext associated with this JScrollPane.
1420 * For scroll panes, the AccessibleContext takes the form of an
1421 * AccessibleJScrollPane.
1422 * A new AccessibleJScrollPane instance is created if necessary.
1423 *
1424 * @return an AccessibleJScrollPane that serves as the
1425 * AccessibleContext of this JScrollPane
1426 */
1427 public AccessibleContext getAccessibleContext() {
1428 if (accessibleContext == null) {
1429 accessibleContext = new AccessibleJScrollPane();
1430 }
1431 return accessibleContext;
1432 }
1433
1434 /**
1435 * This class implements accessibility support for the
1436 * <code>JScrollPane</code> class. It provides an implementation of the
1437 * Java Accessibility API appropriate to scroll pane user-interface
1438 * elements.
1439 * <p>
1440 * <strong>Warning:</strong>
1441 * Serialized objects of this class will not be compatible with
1442 * future Swing releases. The current serialization support is
1443 * appropriate for short term storage or RMI between applications running
1444 * the same version of Swing. As of 1.4, support for long term storage
1445 * of all JavaBeans™
1446 * has been added to the <code>java.beans</code> package.
1447 * Please see {@link java.beans.XMLEncoder}.
1448 */
1449 @SuppressWarnings("serial") // Same-version serialization only
1450 protected class AccessibleJScrollPane extends AccessibleJComponent
1451 implements ChangeListener, PropertyChangeListener {
1452
1453 /**
1454 * this {@code JScrollPane}'s current {@code JViewport}
1455 */
1456 protected JViewport viewPort = null;
1457
1458 /**
1459 * Resets the viewport ChangeListener and PropertyChangeListener
1460 */
1461 public void resetViewPort() {
1462 if (viewPort != null) {
1463 viewPort.removeChangeListener(this);
1464 viewPort.removePropertyChangeListener(this);
1465 }
1466 viewPort = JScrollPane.this.getViewport();
1487 scrollBar = getVerticalScrollBar();
1488 if (scrollBar != null) {
1489 setScrollBarRelations(scrollBar);
1490 }
1491 }
1492
1493 /**
1494 * Get the role of this object.
1495 *
1496 * @return an instance of AccessibleRole describing the role of the
1497 * object
1498 * @see AccessibleRole
1499 */
1500 public AccessibleRole getAccessibleRole() {
1501 return AccessibleRole.SCROLL_PANE;
1502 }
1503
1504 /**
1505 * Invoked when the target of the listener has changed its state.
1506 *
1507 * @param e a <code>ChangeEvent</code> object. Must not be null.
1508 *
1509 * @throws NullPointerException if the parameter is null.
1510 */
1511 public void stateChanged(ChangeEvent e) {
1512 if (e == null) {
1513 throw new NullPointerException();
1514 }
1515 firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY,
1516 Boolean.valueOf(false),
1517 Boolean.valueOf(true));
1518 }
1519
1520 /**
1521 * This method gets called when a bound property is changed.
1522 * @param e A <code>PropertyChangeEvent</code> object describing
1523 * the event source and the property that has changed. Must not be null.
1524 *
1525 * @throws NullPointerException if the parameter is null.
1526 * @since 1.5
1527 */
1528 public void propertyChange(PropertyChangeEvent e) {
1529 String propertyName = e.getPropertyName();
1530 if (propertyName == "horizontalScrollBar" ||
1531 propertyName == "verticalScrollBar") {
1532
1533 if (e.getNewValue() instanceof JScrollBar) {
1534 setScrollBarRelations((JScrollBar)e.getNewValue());
1535 }
1536 }
1537 }
1538
1539
1540 /*
1541 * Sets the CONTROLLER_FOR and CONTROLLED_BY AccessibleRelations for
1542 * the JScrollPane and JScrollBar. JScrollBar must not be null.
|
29 import javax.swing.border.*;
30 import javax.swing.event.*;
31 import javax.accessibility.*;
32
33 import java.awt.Component;
34 import java.awt.ComponentOrientation;
35 import java.awt.Rectangle;
36 import java.awt.Insets;
37 import java.awt.LayoutManager;
38 import java.awt.Point;
39
40 import java.io.ObjectOutputStream;
41 import java.io.IOException;
42
43 import java.beans.PropertyChangeEvent;
44 import java.beans.PropertyChangeListener;
45 import java.beans.Transient;
46
47 /**
48 * Provides a scrollable view of a lightweight component.
49 * A {@code JScrollPane} manages a viewport, optional
50 * vertical and horizontal scroll bars, and optional row and
51 * column heading viewports.
52 * You can find task-oriented documentation of {@code JScrollPane} in
53 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html">How to Use Scroll Panes</a>,
54 * a section in <em>The Java Tutorial</em>. Note that
55 * {@code JScrollPane} does not support heavyweight components.
56 *
57 * <TABLE STYLE="FLOAT:RIGHT" BORDER="0" SUMMARY="layout">
58 * <TR>
59 * <TD ALIGN="CENTER">
60 * <P STYLE="TEXT-ALIGN:CENTER"><IMG SRC="doc-files/JScrollPane-1.gif"
61 * alt="The following text describes this image."
62 * WIDTH="256" HEIGHT="248" STYLE="FLOAT:BOTTOM; BORDER:0px">
63 * </TD>
64 * </TR>
65 * </TABLE>
66 * The {@code JViewport} provides a window,
67 * or "viewport" onto a data
68 * source -- for example, a text file. That data source is the
69 * "scrollable client" (aka data model) displayed by the
70 * {@code JViewport} view.
71 * A {@code JScrollPane} basically consists of {@code JScrollBar}s,
72 * a {@code JViewport}, and the wiring between them,
73 * as shown in the diagram at right.
74 * <p>
75 * In addition to the scroll bars and viewport,
76 * a {@code JScrollPane} can have a
77 * column header and a row header. Each of these is a
78 * {@code JViewport} object that
79 * you specify with {@code setRowHeaderView},
80 * and {@code setColumnHeaderView}.
81 * The column header viewport automatically scrolls left and right, tracking
82 * the left-right scrolling of the main viewport.
83 * (It never scrolls vertically, however.)
84 * The row header acts in a similar fashion.
85 * <p>
86 * Where two scroll bars meet, the row header meets the column header,
87 * or a scroll bar meets one of the headers, both components stop short
88 * of the corner, leaving a rectangular space which is, by default, empty.
89 * These spaces can potentially exist in any number of the four corners.
90 * In the previous diagram, the top right space is present and identified
91 * by the label "corner component".
92 * <p>
93 * Any number of these empty spaces can be replaced by using the
94 * {@code setCorner} method to add a component to a particular corner.
95 * (Note: The same component cannot be added to multiple corners.)
96 * This is useful if there's
97 * some extra decoration or function you'd like to add to the scroll pane.
98 * The size of each corner component is entirely determined by the size of the
99 * headers and/or scroll bars that surround it.
100 * <p>
101 * A corner component will only be visible if there is an empty space in that
102 * corner for it to exist in. For example, consider a component set into the
103 * top right corner of a scroll pane with a column header. If the scroll pane's
104 * vertical scrollbar is not present, perhaps because the view component hasn't
105 * grown large enough to require it, then the corner component will not be
106 * shown (since there is no empty space in that corner created by the meeting
107 * of the header and vertical scroll bar). Forcing the scroll bar to always be
108 * shown, using
109 * {@code setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS)},
110 * will ensure that the space for the corner component always exists.
111 * <p>
112 * To add a border around the main viewport,
113 * you can use {@code setViewportBorder}.
114 * (Of course, you can also add a border around the whole scroll pane using
115 * {@code setBorder}.)
116 * <p>
117 * A common operation to want to do is to set the background color that will
118 * be used if the main viewport view is smaller than the viewport, or is
119 * not opaque. This can be accomplished by setting the background color
120 * of the viewport, via {@code scrollPane.getViewport().setBackground()}.
121 * The reason for setting the color of the viewport and not the scrollpane
122 * is that by default {@code JViewport} is opaque
123 * which, among other things, means it will completely fill
124 * in its background using its background color. Therefore when
125 * {@code JScrollPane} draws its background the viewport will
126 * usually draw over it.
127 * <p>
128 * By default {@code JScrollPane} uses {@code ScrollPaneLayout}
129 * to handle the layout of its child Components. {@code ScrollPaneLayout}
130 * determines the size to make the viewport view in one of two ways:
131 * <ol>
132 * <li>If the view implements {@code Scrollable}
133 * a combination of {@code getPreferredScrollableViewportSize},
134 * {@code getScrollableTracksViewportWidth} and
135 * {@code getScrollableTracksViewportHeight} is used, otherwise
136 * <li>{@code getPreferredSize} is used.
137 * </ol>
138 * <p>
139 * <strong>Warning:</strong> Swing is not thread safe. For more
140 * information see <a
141 * href="package-summary.html#threading">Swing's Threading
142 * Policy</a>.
143 * <p>
144 * <strong>Warning:</strong>
145 * Serialized objects of this class will not be compatible with
146 * future Swing releases. The current serialization support is
147 * appropriate for short term storage or RMI between applications running
148 * the same version of Swing. As of 1.4, support for long term storage
149 * of all JavaBeans™
150 * has been added to the {@code java.beans} package.
151 * Please see {@link java.beans.XMLEncoder}.
152 *
153 * @see JScrollBar
154 * @see JViewport
155 * @see ScrollPaneLayout
156 * @see Scrollable
157 * @see Component#getPreferredSize
158 * @see #setViewportView
159 * @see #setRowHeaderView
160 * @see #setColumnHeaderView
161 * @see #setCorner
162 * @see #setViewportBorder
163 *
164 * @beaninfo
165 * attribute: isContainer true
166 * attribute: containerDelegate getViewport
167 * description: A specialized container that manages a viewport, optional scrollbars and headers
168 *
169 * @author Hans Muller
170 * @since 1.2
171 */
172 @SuppressWarnings("serial") // Same-version serialization only
173 public class JScrollPane extends JComponent implements ScrollPaneConstants, Accessible
174 {
175 private Border viewportBorder;
176
177 /**
178 * @see #getUIClassID
179 * @see #readObject
180 */
181 private static final String uiClassID = "ScrollPaneUI";
182
183 /**
184 * The display policy for the vertical scrollbar.
185 * The default is
186 * {@code ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED}.
187 * @see #setVerticalScrollBarPolicy
188 */
189 protected int verticalScrollBarPolicy = VERTICAL_SCROLLBAR_AS_NEEDED;
190
191
192 /**
193 * The display policy for the horizontal scrollbar.
194 * The default is
195 * {@code ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED}.
196 * @see #setHorizontalScrollBarPolicy
197 */
198 protected int horizontalScrollBarPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED;
199
200
201 /**
202 * The scrollpane's viewport child. Default is an empty
203 * {@code JViewport}.
204 * @see #setViewport
205 */
206 protected JViewport viewport;
207
208
209 /**
210 * The scrollpane's vertical scrollbar child.
211 * Default is a {@code JScrollBar}.
212 * @see #setVerticalScrollBar
213 */
214 protected JScrollBar verticalScrollBar;
215
216
217 /**
218 * The scrollpane's horizontal scrollbar child.
219 * Default is a {@code JScrollBar}.
220 * @see #setHorizontalScrollBar
221 */
222 protected JScrollBar horizontalScrollBar;
223
224
225 /**
226 * The row header child. Default is {@code null}.
227 * @see #setRowHeader
228 */
229 protected JViewport rowHeader;
230
231
232 /**
233 * The column header child. Default is {@code null}.
234 * @see #setColumnHeader
235 */
236 protected JViewport columnHeader;
237
238
239 /**
240 * The component to display in the lower left corner.
241 * Default is {@code null}.
242 * @see #setCorner
243 */
244 protected Component lowerLeft;
245
246
247 /**
248 * The component to display in the lower right corner.
249 * Default is {@code null}.
250 * @see #setCorner
251 */
252 protected Component lowerRight;
253
254
255 /**
256 * The component to display in the upper left corner.
257 * Default is {@code null}.
258 * @see #setCorner
259 */
260 protected Component upperLeft;
261
262
263 /**
264 * The component to display in the upper right corner.
265 * Default is {@code null}.
266 * @see #setCorner
267 */
268 protected Component upperRight;
269
270 /*
271 * State flag for mouse wheel scrolling
272 */
273 private boolean wheelScrollState = true;
274
275 /**
276 * Creates a {@code JScrollPane} that displays the view
277 * component in a viewport
278 * whose view position can be controlled with a pair of scrollbars.
279 * The scrollbar policies specify when the scrollbars are displayed,
280 * For example, if {@code vsbPolicy} is
281 * {@code VERTICAL_SCROLLBAR_AS_NEEDED}
282 * then the vertical scrollbar only appears if the view doesn't fit
283 * vertically. The available policy settings are listed at
284 * {@link #setVerticalScrollBarPolicy} and
285 * {@link #setHorizontalScrollBarPolicy}.
286 *
287 * @see #setViewportView
288 *
289 * @param view the component to display in the scrollpanes viewport
290 * @param vsbPolicy an integer that specifies the vertical
291 * scrollbar policy
292 * @param hsbPolicy an integer that specifies the horizontal
293 * scrollbar policy
294 */
295 public JScrollPane(Component view, int vsbPolicy, int hsbPolicy)
296 {
297 setLayout(new ScrollPaneLayout.UIResource());
298 setVerticalScrollBarPolicy(vsbPolicy);
299 setHorizontalScrollBarPolicy(hsbPolicy);
300 setViewport(createViewport());
301 setVerticalScrollBar(createVerticalScrollBar());
302 setHorizontalScrollBar(createHorizontalScrollBar());
303 if (view != null) {
304 setViewportView(view);
305 }
306 setUIProperty("opaque",true);
307 updateUI();
308
309 if (!this.getComponentOrientation().isLeftToRight()) {
310 viewport.setViewPosition(new Point(Integer.MAX_VALUE, 0));
311 }
312 }
313
314
315 /**
316 * Creates a {@code JScrollPane} that displays the
317 * contents of the specified
318 * component, where both horizontal and vertical scrollbars appear
319 * whenever the component's contents are larger than the view.
320 *
321 * @see #setViewportView
322 * @param view the component to display in the scrollpane's viewport
323 */
324 public JScrollPane(Component view) {
325 this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
326 }
327
328
329 /**
330 * Creates an empty (no viewport view) {@code JScrollPane}
331 * with specified
332 * scrollbar policies. The available policy settings are listed at
333 * {@link #setVerticalScrollBarPolicy} and
334 * {@link #setHorizontalScrollBarPolicy}.
335 *
336 * @see #setViewportView
337 *
338 * @param vsbPolicy an integer that specifies the vertical
339 * scrollbar policy
340 * @param hsbPolicy an integer that specifies the horizontal
341 * scrollbar policy
342 */
343 public JScrollPane(int vsbPolicy, int hsbPolicy) {
344 this(null, vsbPolicy, hsbPolicy);
345 }
346
347
348 /**
349 * Creates an empty (no viewport view) {@code JScrollPane}
350 * where both horizontal and vertical scrollbars appear when needed.
351 */
352 public JScrollPane() {
353 this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
354 }
355
356
357 /**
358 * Returns the look and feel (L&F) object that renders this component.
359 *
360 * @return the {@code ScrollPaneUI} object that renders this
361 * component
362 * @see #setUI
363 * @beaninfo
364 * bound: true
365 * hidden: true
366 * attribute: visualUpdate true
367 * description: The UI object that implements the Component's LookAndFeel.
368 */
369 public ScrollPaneUI getUI() {
370 return (ScrollPaneUI)ui;
371 }
372
373
374 /**
375 * Sets the {@code ScrollPaneUI} object that provides the
376 * look and feel (L&F) for this component.
377 *
378 * @param ui the {@code ScrollPaneUI} L&F object
379 * @see #getUI
380 */
381 public void setUI(ScrollPaneUI ui) {
382 super.setUI(ui);
383 }
384
385
386 /**
387 * Replaces the current {@code ScrollPaneUI} object with a version
388 * from the current default look and feel.
389 * To be called when the default look and feel changes.
390 *
391 * @see JComponent#updateUI
392 * @see UIManager#getUI
393 */
394 public void updateUI() {
395 setUI((ScrollPaneUI)UIManager.getUI(this));
396 }
397
398
399 /**
400 * Returns the suffix used to construct the name of the L&F class used to
401 * render this component.
402 *
403 * @return the string "ScrollPaneUI"
404 * @see JComponent#getUIClassID
405 * @see UIDefaults#getUI
406 *
407 * @beaninfo
408 * hidden: true
409 */
410 public String getUIClassID() {
411 return uiClassID;
412 }
413
414
415
416 /**
417 * Sets the layout manager for this {@code JScrollPane}.
418 * This method overrides {@code setLayout} in
419 * {@code java.awt.Container} to ensure that only
420 * {@code LayoutManager}s which
421 * are subclasses of {@code ScrollPaneLayout} can be used in a
422 * {@code JScrollPane}. If {@code layout} is non-null, this
423 * will invoke {@code syncWithScrollPane} on it.
424 *
425 * @param layout the specified layout manager
426 * @exception ClassCastException if layout is not a
427 * {@code ScrollPaneLayout}
428 * @see java.awt.Container#getLayout
429 * @see java.awt.Container#setLayout
430 *
431 * @beaninfo
432 * hidden: true
433 */
434 public void setLayout(LayoutManager layout) {
435 if (layout instanceof ScrollPaneLayout) {
436 super.setLayout(layout);
437 ((ScrollPaneLayout)layout).syncWithScrollPane(this);
438 }
439 else if (layout == null) {
440 super.setLayout(layout);
441 }
442 else {
443 String s = "layout of JScrollPane must be a ScrollPaneLayout";
444 throw new ClassCastException(s);
445 }
446 }
447
448 /**
449 * Overridden to return true so that any calls to {@code revalidate}
450 * on any descendants of this {@code JScrollPane} will cause the
451 * entire tree beginning with this {@code JScrollPane} to be
452 * validated.
453 *
454 * @return true
455 * @see java.awt.Container#validate
456 * @see JComponent#revalidate
457 * @see JComponent#isValidateRoot
458 * @see java.awt.Container#isValidateRoot
459 *
460 * @beaninfo
461 * hidden: true
462 */
463 @Override
464 public boolean isValidateRoot() {
465 return true;
466 }
467
468
469 /**
470 * Returns the vertical scroll bar policy value.
471 * @return the {@code verticalScrollBarPolicy} property
472 * @see #setVerticalScrollBarPolicy
473 */
474 public int getVerticalScrollBarPolicy() {
475 return verticalScrollBarPolicy;
476 }
477
478
479 /**
480 * Determines when the vertical scrollbar appears in the scrollpane.
481 * Legal values are:
482 * <ul>
483 * <li>{@code ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED}
484 * <li>{@code ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER}
485 * <li>{@code ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS}
486 * </ul>
487 *
488 * @param policy one of the three values listed above
489 * @exception IllegalArgumentException if {@code policy}
490 * is not one of the legal values shown above
491 * @see #getVerticalScrollBarPolicy
492 *
493 * @beaninfo
494 * preferred: true
495 * bound: true
496 * description: The scrollpane vertical scrollbar policy
497 * enum: VERTICAL_SCROLLBAR_AS_NEEDED ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
498 * VERTICAL_SCROLLBAR_NEVER ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER
499 * VERTICAL_SCROLLBAR_ALWAYS ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
500 */
501 public void setVerticalScrollBarPolicy(int policy) {
502 switch (policy) {
503 case VERTICAL_SCROLLBAR_AS_NEEDED:
504 case VERTICAL_SCROLLBAR_NEVER:
505 case VERTICAL_SCROLLBAR_ALWAYS:
506 break;
507 default:
508 throw new IllegalArgumentException("invalid verticalScrollBarPolicy");
509 }
510 int old = verticalScrollBarPolicy;
511 verticalScrollBarPolicy = policy;
512 firePropertyChange("verticalScrollBarPolicy", old, policy);
513 revalidate();
514 repaint();
515 }
516
517
518 /**
519 * Returns the horizontal scroll bar policy value.
520 * @return the {@code horizontalScrollBarPolicy} property
521 * @see #setHorizontalScrollBarPolicy
522 */
523 public int getHorizontalScrollBarPolicy() {
524 return horizontalScrollBarPolicy;
525 }
526
527
528 /**
529 * Determines when the horizontal scrollbar appears in the scrollpane.
530 * The options are:<ul>
531 * <li>{@code ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED}
532 * <li>{@code ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER}
533 * <li>{@code ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS}
534 * </ul>
535 *
536 * @param policy one of the three values listed above
537 * @exception IllegalArgumentException if {@code policy}
538 * is not one of the legal values shown above
539 * @see #getHorizontalScrollBarPolicy
540 *
541 * @beaninfo
542 * preferred: true
543 * bound: true
544 * description: The scrollpane scrollbar policy
545 * enum: HORIZONTAL_SCROLLBAR_AS_NEEDED ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
546 * HORIZONTAL_SCROLLBAR_NEVER ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
547 * HORIZONTAL_SCROLLBAR_ALWAYS ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
548 */
549 public void setHorizontalScrollBarPolicy(int policy) {
550 switch (policy) {
551 case HORIZONTAL_SCROLLBAR_AS_NEEDED:
552 case HORIZONTAL_SCROLLBAR_NEVER:
553 case HORIZONTAL_SCROLLBAR_ALWAYS:
554 break;
555 default:
556 throw new IllegalArgumentException("invalid horizontalScrollBarPolicy");
557 }
558 int old = horizontalScrollBarPolicy;
559 horizontalScrollBarPolicy = policy;
560 firePropertyChange("horizontalScrollBarPolicy", old, policy);
561 revalidate();
562 repaint();
563 }
564
565
566 /**
567 * Returns the {@code Border} object that surrounds the viewport.
568 *
569 * @return the {@code viewportBorder} property
570 * @see #setViewportBorder
571 */
572 public Border getViewportBorder() {
573 return viewportBorder;
574 }
575
576
577 /**
578 * Adds a border around the viewport. Note that the border isn't
579 * set on the viewport directly, {@code JViewport} doesn't support
580 * the {@code JComponent} border property.
581 * Similarly setting the {@code JScrollPane}s
582 * viewport doesn't affect the {@code viewportBorder} property.
583 * <p>
584 * The default value of this property is computed by the look
585 * and feel implementation.
586 *
587 * @param viewportBorder the border to be added
588 * @see #getViewportBorder
589 * @see #setViewport
590 *
591 * @beaninfo
592 * preferred: true
593 * bound: true
594 * description: The border around the viewport.
595 */
596 public void setViewportBorder(Border viewportBorder) {
597 Border oldValue = this.viewportBorder;
598 this.viewportBorder = viewportBorder;
599 firePropertyChange("viewportBorder", oldValue, viewportBorder);
600 }
601
602
603 /**
604 * Returns the bounds of the viewport's border.
605 *
606 * @return a {@code Rectangle} object specifying the viewport border
607 */
608 public Rectangle getViewportBorderBounds()
609 {
610 Rectangle borderR = new Rectangle(getSize());
611
612 Insets insets = getInsets();
613 borderR.x = insets.left;
614 borderR.y = insets.top;
615 borderR.width -= insets.left + insets.right;
616 borderR.height -= insets.top + insets.bottom;
617
618 boolean leftToRight = SwingUtilities.isLeftToRight(this);
619
620 /* If there's a visible column header remove the space it
621 * needs from the top of borderR.
622 */
623
624 JViewport colHead = getColumnHeader();
625 if ((colHead != null) && (colHead.isVisible())) {
626 int colHeadHeight = colHead.getHeight();
649 int vsbWidth = vsb.getWidth();
650 if ( !leftToRight ) {
651 borderR.x += vsbWidth;
652 }
653 borderR.width -= vsbWidth;
654 }
655
656 /* If there's a visible horizontal scrollbar remove the space it needs
657 * from the height of borderR.
658 */
659 JScrollBar hsb = getHorizontalScrollBar();
660 if ((hsb != null) && (hsb.isVisible())) {
661 borderR.height -= hsb.getHeight();
662 }
663
664 return borderR;
665 }
666
667
668 /**
669 * By default {@code JScrollPane} creates scrollbars
670 * that are instances
671 * of this class. {@code Scrollbar} overrides the
672 * {@code getUnitIncrement} and {@code getBlockIncrement}
673 * methods so that, if the viewport's view is a {@code Scrollable},
674 * the view is asked to compute these values. Unless
675 * the unit/block increment have been explicitly set.
676 * <p>
677 * <strong>Warning:</strong>
678 * Serialized objects of this class will not be compatible with
679 * future Swing releases. The current serialization support is
680 * appropriate for short term storage or RMI between applications running
681 * the same version of Swing. As of 1.4, support for long term storage
682 * of all JavaBeans™
683 * has been added to the {@code java.beans} package.
684 * Please see {@link java.beans.XMLEncoder}.
685 *
686 * @see Scrollable
687 * @see JScrollPane#createVerticalScrollBar
688 * @see JScrollPane#createHorizontalScrollBar
689 */
690 @SuppressWarnings("serial") // Same-version serialization only
691 protected class ScrollBar extends JScrollBar implements UIResource
692 {
693 /**
694 * Set to true when the unit increment has been explicitly set.
695 * If this is false the viewport's view is obtained and if it
696 * is an instance of {@code Scrollable} the unit increment
697 * from it is used.
698 */
699 private boolean unitIncrementSet;
700 /**
701 * Set to true when the block increment has been explicitly set.
702 * If this is false the viewport's view is obtained and if it
703 * is an instance of {@code Scrollable} the block increment
704 * from it is used.
705 */
706 private boolean blockIncrementSet;
707
708 /**
709 * Creates a scrollbar with the specified orientation.
710 * The options are:
711 * <ul>
712 * <li>{@code ScrollPaneConstants.VERTICAL}
713 * <li>{@code ScrollPaneConstants.HORIZONTAL}
714 * </ul>
715 *
716 * @param orientation an integer specifying one of the legal
717 * orientation values shown above
718 * @since 1.4
719 */
720 public ScrollBar(int orientation) {
721 super(orientation);
722 this.putClientProperty("JScrollBar.fastWheelScrolling",
723 Boolean.TRUE);
724 }
725
726 /**
727 * Messages super to set the value, and resets the
728 * {@code unitIncrementSet} instance variable to true.
729 *
730 * @param unitIncrement the new unit increment value, in pixels
731 */
732 public void setUnitIncrement(int unitIncrement) {
733 unitIncrementSet = true;
734 this.putClientProperty("JScrollBar.fastWheelScrolling", null);
735 super.setUnitIncrement(unitIncrement);
736 }
737
738 /**
739 * Computes the unit increment for scrolling if the viewport's
740 * view is a {@code Scrollable} object.
741 * Otherwise return {@code super.getUnitIncrement}.
742 *
743 * @param direction less than zero to scroll up/left,
744 * greater than zero for down/right
745 * @return an integer, in pixels, containing the unit increment
746 * @see Scrollable#getScrollableUnitIncrement
747 */
748 public int getUnitIncrement(int direction) {
749 JViewport vp = getViewport();
750 if (!unitIncrementSet && (vp != null) &&
751 (vp.getView() instanceof Scrollable)) {
752 Scrollable view = (Scrollable)(vp.getView());
753 Rectangle vr = vp.getViewRect();
754 return view.getScrollableUnitIncrement(vr, getOrientation(), direction);
755 }
756 else {
757 return super.getUnitIncrement(direction);
758 }
759 }
760
761 /**
762 * Messages super to set the value, and resets the
763 * {@code blockIncrementSet} instance variable to true.
764 *
765 * @param blockIncrement the new block increment value, in pixels
766 */
767 public void setBlockIncrement(int blockIncrement) {
768 blockIncrementSet = true;
769 this.putClientProperty("JScrollBar.fastWheelScrolling", null);
770 super.setBlockIncrement(blockIncrement);
771 }
772
773 /**
774 * Computes the block increment for scrolling if the viewport's
775 * view is a {@code Scrollable} object. Otherwise
776 * the {@code blockIncrement} equals the viewport's width
777 * or height. If there's no viewport return
778 * {@code super.getBlockIncrement}.
779 *
780 * @param direction less than zero to scroll up/left,
781 * greater than zero for down/right
782 * @return an integer, in pixels, containing the block increment
783 * @see Scrollable#getScrollableBlockIncrement
784 */
785 public int getBlockIncrement(int direction) {
786 JViewport vp = getViewport();
787 if (blockIncrementSet || vp == null) {
788 return super.getBlockIncrement(direction);
789 }
790 else if (vp.getView() instanceof Scrollable) {
791 Scrollable view = (Scrollable)(vp.getView());
792 Rectangle vr = vp.getViewRect();
793 return view.getScrollableBlockIncrement(vr, getOrientation(), direction);
794 }
795 else if (getOrientation() == VERTICAL) {
796 return vp.getExtentSize().height;
797 }
798 else {
799 return vp.getExtentSize().width;
800 }
801 }
802
803 }
804
805
806 /**
807 * Returns a {@code JScrollPane.ScrollBar} by default.
808 * Subclasses may override this method to force {@code ScrollPaneUI}
809 * implementations to use a {@code JScrollBar} subclass.
810 * Used by {@code ScrollPaneUI} implementations to
811 * create the horizontal scrollbar.
812 *
813 * @return a {@code JScrollBar} with a horizontal orientation
814 * @see JScrollBar
815 */
816 public JScrollBar createHorizontalScrollBar() {
817 return new ScrollBar(JScrollBar.HORIZONTAL);
818 }
819
820
821 /**
822 * Returns the horizontal scroll bar that controls the viewport's
823 * horizontal view position.
824 *
825 * @return the {@code horizontalScrollBar} property
826 * @see #setHorizontalScrollBar
827 */
828 @Transient
829 public JScrollBar getHorizontalScrollBar() {
830 return horizontalScrollBar;
831 }
832
833
834 /**
835 * Adds the scrollbar that controls the viewport's horizontal view
836 * position to the scrollpane.
837 * This is usually unnecessary, as {@code JScrollPane} creates
838 * horizontal and vertical scrollbars by default.
839 *
840 * @param horizontalScrollBar the horizontal scrollbar to be added
841 * @see #createHorizontalScrollBar
842 * @see #getHorizontalScrollBar
843 *
844 * @beaninfo
845 * expert: true
846 * bound: true
847 * description: The horizontal scrollbar.
848 */
849 public void setHorizontalScrollBar(JScrollBar horizontalScrollBar) {
850 JScrollBar old = getHorizontalScrollBar();
851 this.horizontalScrollBar = horizontalScrollBar;
852 if (horizontalScrollBar != null) {
853 add(horizontalScrollBar, HORIZONTAL_SCROLLBAR);
854 }
855 else if (old != null) {
856 remove(old);
857 }
858 firePropertyChange("horizontalScrollBar", old, horizontalScrollBar);
859
860 revalidate();
861 repaint();
862 }
863
864
865 /**
866 * Returns a {@code JScrollPane.ScrollBar} by default. Subclasses
867 * may override this method to force {@code ScrollPaneUI}
868 * implementations to use a {@code JScrollBar} subclass.
869 * Used by {@code ScrollPaneUI} implementations to create the
870 * vertical scrollbar.
871 *
872 * @return a {@code JScrollBar} with a vertical orientation
873 * @see JScrollBar
874 */
875 public JScrollBar createVerticalScrollBar() {
876 return new ScrollBar(JScrollBar.VERTICAL);
877 }
878
879
880 /**
881 * Returns the vertical scroll bar that controls the viewports
882 * vertical view position.
883 *
884 * @return the {@code verticalScrollBar} property
885 * @see #setVerticalScrollBar
886 */
887 @Transient
888 public JScrollBar getVerticalScrollBar() {
889 return verticalScrollBar;
890 }
891
892
893 /**
894 * Adds the scrollbar that controls the viewports vertical view position
895 * to the scrollpane. This is usually unnecessary,
896 * as {@code JScrollPane} creates vertical and
897 * horizontal scrollbars by default.
898 *
899 * @param verticalScrollBar the new vertical scrollbar to be added
900 * @see #createVerticalScrollBar
901 * @see #getVerticalScrollBar
902 *
903 * @beaninfo
904 * expert: true
905 * bound: true
906 * description: The vertical scrollbar.
907 */
908 public void setVerticalScrollBar(JScrollBar verticalScrollBar) {
909 JScrollBar old = getVerticalScrollBar();
910 this.verticalScrollBar = verticalScrollBar;
911 add(verticalScrollBar, VERTICAL_SCROLLBAR);
912 firePropertyChange("verticalScrollBar", old, verticalScrollBar);
913
914 revalidate();
915 repaint();
916 }
917
918
919 /**
920 * Returns a new {@code JViewport} by default.
921 * Used to create the
922 * viewport (as needed) in {@code setViewportView},
923 * {@code setRowHeaderView}, and {@code setColumnHeaderView}.
924 * Subclasses may override this method to return a subclass of
925 * {@code JViewport}.
926 *
927 * @return a new {@code JViewport}
928 */
929 protected JViewport createViewport() {
930 return new JViewport();
931 }
932
933
934 /**
935 * Returns the current {@code JViewport}.
936 *
937 * @see #setViewport
938 * @return the {@code viewport} property
939 */
940 public JViewport getViewport() {
941 return viewport;
942 }
943
944
945 /**
946 * Removes the old viewport (if there is one); forces the
947 * viewPosition of the new viewport to be in the +x,+y quadrant;
948 * syncs up the row and column headers (if there are any) with the
949 * new viewport; and finally syncs the scrollbars and
950 * headers with the new viewport.
951 * <p>
952 * Most applications will find it more convenient to use
953 * {@code setViewportView}
954 * to add a viewport and a view to the scrollpane.
955 *
956 * @param viewport the new viewport to be used; if viewport is
957 * {@code null}, the old viewport is still removed
958 * and the new viewport is set to {@code null}
959 * @see #createViewport
960 * @see #getViewport
961 * @see #setViewportView
962 *
963 * @beaninfo
964 * expert: true
965 * bound: true
966 * attribute: visualUpdate true
967 * description: The viewport child for this scrollpane
968 *
969 */
970 public void setViewport(JViewport viewport) {
971 JViewport old = getViewport();
972 this.viewport = viewport;
973 if (viewport != null) {
974 add(viewport, VIEWPORT);
975 }
976 else if (old != null) {
977 remove(old);
978 }
979 firePropertyChange("viewport", old, viewport);
980
981 if (accessibleContext != null) {
982 ((AccessibleJScrollPane)accessibleContext).resetViewPort();
983 }
984
985 revalidate();
986 repaint();
987 }
988
989
990 /**
991 * Creates a viewport if necessary and then sets its view. Applications
992 * that don't provide the view directly to the {@code JScrollPane}
993 * constructor
994 * should use this method to specify the scrollable child that's going
995 * to be displayed in the scrollpane. For example:
996 * <pre>
997 * JScrollPane scrollpane = new JScrollPane();
998 * scrollpane.setViewportView(myBigComponentToScroll);
999 * </pre>
1000 * Applications should not add children directly to the scrollpane.
1001 *
1002 * @param view the component to add to the viewport
1003 * @see #setViewport
1004 * @see JViewport#setView
1005 */
1006 public void setViewportView(Component view) {
1007 if (getViewport() == null) {
1008 setViewport(createViewport());
1009 }
1010 getViewport().setView(view);
1011 }
1012
1013
1014
1015 /**
1016 * Returns the row header.
1017 * @return the {@code rowHeader} property
1018 * @see #setRowHeader
1019 */
1020 @Transient
1021 public JViewport getRowHeader() {
1022 return rowHeader;
1023 }
1024
1025
1026 /**
1027 * Removes the old rowHeader, if it exists; if the new rowHeader
1028 * isn't {@code null}, syncs the y coordinate of its
1029 * viewPosition with
1030 * the viewport (if there is one) and then adds it to the scroll pane.
1031 * <p>
1032 * Most applications will find it more convenient to use
1033 * {@code setRowHeaderView}
1034 * to add a row header component and its viewport to the scroll pane.
1035 *
1036 * @param rowHeader the new row header to be used; if {@code null}
1037 * the old row header is still removed and the new rowHeader
1038 * is set to {@code null}
1039 * @see #getRowHeader
1040 * @see #setRowHeaderView
1041 *
1042 * @beaninfo
1043 * bound: true
1044 * expert: true
1045 * description: The row header child for this scrollpane
1046 */
1047 public void setRowHeader(JViewport rowHeader) {
1048 JViewport old = getRowHeader();
1049 this.rowHeader = rowHeader;
1050 if (rowHeader != null) {
1051 add(rowHeader, ROW_HEADER);
1052 }
1053 else if (old != null) {
1054 remove(old);
1055 }
1056 firePropertyChange("rowHeader", old, rowHeader);
1057 revalidate();
1058 repaint();
1067 * JScrollPane scrollpane = new JScrollPane();
1068 * scrollpane.setViewportView(myBigComponentToScroll);
1069 * scrollpane.setRowHeaderView(myBigComponentsRowHeader);
1070 * </pre>
1071 *
1072 * @see #setRowHeader
1073 * @see JViewport#setView
1074 * @param view the component to display as the row header
1075 */
1076 public void setRowHeaderView(Component view) {
1077 if (getRowHeader() == null) {
1078 setRowHeader(createViewport());
1079 }
1080 getRowHeader().setView(view);
1081 }
1082
1083
1084
1085 /**
1086 * Returns the column header.
1087 * @return the {@code columnHeader} property
1088 * @see #setColumnHeader
1089 */
1090 @Transient
1091 public JViewport getColumnHeader() {
1092 return columnHeader;
1093 }
1094
1095
1096 /**
1097 * Removes the old columnHeader, if it exists; if the new columnHeader
1098 * isn't {@code null}, syncs the x coordinate of its viewPosition
1099 * with the viewport (if there is one) and then adds it to the scroll pane.
1100 * <p>
1101 * Most applications will find it more convenient to use
1102 * {@code setColumnHeaderView}
1103 * to add a column header component and its viewport to the scroll pane.
1104 *
1105 * @param columnHeader a {@code JViewport} which is the new column header
1106 * @see #getColumnHeader
1107 * @see #setColumnHeaderView
1108 *
1109 * @beaninfo
1110 * bound: true
1111 * description: The column header child for this scrollpane
1112 * attribute: visualUpdate true
1113 */
1114 public void setColumnHeader(JViewport columnHeader) {
1115 JViewport old = getColumnHeader();
1116 this.columnHeader = columnHeader;
1117 if (columnHeader != null) {
1118 add(columnHeader, COLUMN_HEADER);
1119 }
1120 else if (old != null) {
1121 remove(old);
1122 }
1136 * JScrollPane scrollpane = new JScrollPane();
1137 * scrollpane.setViewportView(myBigComponentToScroll);
1138 * scrollpane.setColumnHeaderView(myBigComponentsColumnHeader);
1139 * </pre>
1140 *
1141 * @see #setColumnHeader
1142 * @see JViewport#setView
1143 *
1144 * @param view the component to display as the column header
1145 */
1146 public void setColumnHeaderView(Component view) {
1147 if (getColumnHeader() == null) {
1148 setColumnHeader(createViewport());
1149 }
1150 getColumnHeader().setView(view);
1151 }
1152
1153
1154 /**
1155 * Returns the component at the specified corner. The
1156 * {@code key} value specifying the corner is one of:
1157 * <ul>
1158 * <li>ScrollPaneConstants.LOWER_LEFT_CORNER
1159 * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
1160 * <li>ScrollPaneConstants.UPPER_LEFT_CORNER
1161 * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
1162 * <li>ScrollPaneConstants.LOWER_LEADING_CORNER
1163 * <li>ScrollPaneConstants.LOWER_TRAILING_CORNER
1164 * <li>ScrollPaneConstants.UPPER_LEADING_CORNER
1165 * <li>ScrollPaneConstants.UPPER_TRAILING_CORNER
1166 * </ul>
1167 *
1168 * @param key one of the values as shown above
1169 * @return the corner component (which may be {@code null})
1170 * identified by the given key, or {@code null}
1171 * if the key is invalid
1172 * @see #setCorner
1173 */
1174 public Component getCorner(String key) {
1175 boolean isLeftToRight = getComponentOrientation().isLeftToRight();
1176 if (key.equals(LOWER_LEADING_CORNER)) {
1177 key = isLeftToRight ? LOWER_LEFT_CORNER : LOWER_RIGHT_CORNER;
1178 } else if (key.equals(LOWER_TRAILING_CORNER)) {
1179 key = isLeftToRight ? LOWER_RIGHT_CORNER : LOWER_LEFT_CORNER;
1180 } else if (key.equals(UPPER_LEADING_CORNER)) {
1181 key = isLeftToRight ? UPPER_LEFT_CORNER : UPPER_RIGHT_CORNER;
1182 } else if (key.equals(UPPER_TRAILING_CORNER)) {
1183 key = isLeftToRight ? UPPER_RIGHT_CORNER : UPPER_LEFT_CORNER;
1184 }
1185 if (key.equals(LOWER_LEFT_CORNER)) {
1186 return lowerLeft;
1187 }
1188 else if (key.equals(LOWER_RIGHT_CORNER)) {
1189 return lowerRight;
1190 }
1202
1203 /**
1204 * Adds a child that will appear in one of the scroll panes
1205 * corners, if there's room. For example with both scrollbars
1206 * showing (on the right and bottom edges of the scrollpane)
1207 * the lower left corner component will be shown in the space
1208 * between ends of the two scrollbars. Legal values for
1209 * the <b>key</b> are:
1210 * <ul>
1211 * <li>ScrollPaneConstants.LOWER_LEFT_CORNER
1212 * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
1213 * <li>ScrollPaneConstants.UPPER_LEFT_CORNER
1214 * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
1215 * <li>ScrollPaneConstants.LOWER_LEADING_CORNER
1216 * <li>ScrollPaneConstants.LOWER_TRAILING_CORNER
1217 * <li>ScrollPaneConstants.UPPER_LEADING_CORNER
1218 * <li>ScrollPaneConstants.UPPER_TRAILING_CORNER
1219 * </ul>
1220 * <p>
1221 * Although "corner" doesn't match any beans property
1222 * signature, {@code PropertyChange} events are generated with the
1223 * property name set to the corner key.
1224 *
1225 * @param key identifies which corner the component will appear in
1226 * @param corner one of the following components:
1227 * <ul>
1228 * <li>lowerLeft
1229 * <li>lowerRight
1230 * <li>upperLeft
1231 * <li>upperRight
1232 * </ul>
1233 * @exception IllegalArgumentException if corner key is invalid
1234 */
1235 public void setCorner(String key, Component corner)
1236 {
1237 Component old;
1238 boolean isLeftToRight = getComponentOrientation().isLeftToRight();
1239 if (key.equals(LOWER_LEADING_CORNER)) {
1240 key = isLeftToRight ? LOWER_LEFT_CORNER : LOWER_RIGHT_CORNER;
1241 } else if (key.equals(LOWER_TRAILING_CORNER)) {
1242 key = isLeftToRight ? LOWER_RIGHT_CORNER : LOWER_LEFT_CORNER;
1261 old = upperRight;
1262 upperRight = corner;
1263 }
1264 else {
1265 throw new IllegalArgumentException("invalid corner key");
1266 }
1267 if (old != null) {
1268 remove(old);
1269 }
1270 if (corner != null) {
1271 add(corner, key);
1272 }
1273 firePropertyChange(key, old, corner);
1274 revalidate();
1275 repaint();
1276 }
1277
1278 /**
1279 * Sets the orientation for the vertical and horizontal
1280 * scrollbars as determined by the
1281 * {@code ComponentOrientation} argument.
1282 *
1283 * @param co one of the following values:
1284 * <ul>
1285 * <li>java.awt.ComponentOrientation.LEFT_TO_RIGHT
1286 * <li>java.awt.ComponentOrientation.RIGHT_TO_LEFT
1287 * <li>java.awt.ComponentOrientation.UNKNOWN
1288 * </ul>
1289 * @see java.awt.ComponentOrientation
1290 */
1291 public void setComponentOrientation( ComponentOrientation co ) {
1292 super.setComponentOrientation( co );
1293 if( verticalScrollBar != null )
1294 verticalScrollBar.setComponentOrientation( co );
1295 if( horizontalScrollBar != null )
1296 horizontalScrollBar.setComponentOrientation( co );
1297 }
1298
1299 /**
1300 * Indicates whether or not scrolling will take place in response to the
1301 * mouse wheel. Wheel scrolling is enabled by default.
1302 *
1303 * @return true if mouse wheel scrolling is enabled, false otherwise
1304 * @see #setWheelScrollingEnabled
1305 * @since 1.4
1306 * @beaninfo
1307 * bound: true
1308 * description: Flag for enabling/disabling mouse wheel scrolling
1309 */
1310 public boolean isWheelScrollingEnabled() {return wheelScrollState;}
1311
1312 /**
1313 * Enables/disables scrolling in response to movement of the mouse wheel.
1314 * Wheel scrolling is enabled by default.
1315 *
1316 * @param handleWheel {@code true} if scrolling should be done
1317 * automatically for a MouseWheelEvent,
1318 * {@code false} otherwise.
1319 * @see #isWheelScrollingEnabled
1320 * @see java.awt.event.MouseWheelEvent
1321 * @see java.awt.event.MouseWheelListener
1322 * @since 1.4
1323 * @beaninfo
1324 * bound: true
1325 * description: Flag for enabling/disabling mouse wheel scrolling
1326 */
1327 public void setWheelScrollingEnabled(boolean handleWheel) {
1328 boolean old = wheelScrollState;
1329 wheelScrollState = handleWheel;
1330 firePropertyChange("wheelScrollingEnabled", old, handleWheel);
1331 }
1332
1333 /**
1334 * See {@code readObject} and {@code writeObject} in
1335 * {@code JComponent} for more
1336 * information about serialization in Swing.
1337 */
1338 private void writeObject(ObjectOutputStream s) throws IOException {
1339 s.defaultWriteObject();
1340 if (getUIClassID().equals(uiClassID)) {
1341 byte count = JComponent.getWriteObjCounter(this);
1342 JComponent.setWriteObjCounter(this, --count);
1343 if (count == 0 && ui != null) {
1344 ui.installUI(this);
1345 }
1346 }
1347 }
1348
1349
1350 /**
1351 * Returns a string representation of this {@code JScrollPane}.
1352 * This method
1353 * is intended to be used only for debugging purposes, and the
1354 * content and format of the returned string may vary between
1355 * implementations. The returned string may be empty but may not
1356 * be {@code null}.
1357 *
1358 * @return a string representation of this {@code JScrollPane}.
1359 */
1360 protected String paramString() {
1361 String viewportBorderString = (viewportBorder != null ?
1362 viewportBorder.toString() : "");
1363 String viewportString = (viewport != null ?
1364 viewport.toString() : "");
1365 String verticalScrollBarPolicyString;
1366 if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_AS_NEEDED) {
1367 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_AS_NEEDED";
1368 } else if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_NEVER) {
1369 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_NEVER";
1370 } else if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
1371 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_ALWAYS";
1372 } else verticalScrollBarPolicyString = "";
1373 String horizontalScrollBarPolicyString;
1374 if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED) {
1375 horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_AS_NEEDED";
1376 } else if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_NEVER) {
1377 horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_NEVER";
1378 } else if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) {
1416 ////////////////
1417
1418 /**
1419 * Gets the AccessibleContext associated with this JScrollPane.
1420 * For scroll panes, the AccessibleContext takes the form of an
1421 * AccessibleJScrollPane.
1422 * A new AccessibleJScrollPane instance is created if necessary.
1423 *
1424 * @return an AccessibleJScrollPane that serves as the
1425 * AccessibleContext of this JScrollPane
1426 */
1427 public AccessibleContext getAccessibleContext() {
1428 if (accessibleContext == null) {
1429 accessibleContext = new AccessibleJScrollPane();
1430 }
1431 return accessibleContext;
1432 }
1433
1434 /**
1435 * This class implements accessibility support for the
1436 * {@code JScrollPane} class. It provides an implementation of the
1437 * Java Accessibility API appropriate to scroll pane user-interface
1438 * elements.
1439 * <p>
1440 * <strong>Warning:</strong>
1441 * Serialized objects of this class will not be compatible with
1442 * future Swing releases. The current serialization support is
1443 * appropriate for short term storage or RMI between applications running
1444 * the same version of Swing. As of 1.4, support for long term storage
1445 * of all JavaBeans™
1446 * has been added to the {@code java.beans} package.
1447 * Please see {@link java.beans.XMLEncoder}.
1448 */
1449 @SuppressWarnings("serial") // Same-version serialization only
1450 protected class AccessibleJScrollPane extends AccessibleJComponent
1451 implements ChangeListener, PropertyChangeListener {
1452
1453 /**
1454 * this {@code JScrollPane}'s current {@code JViewport}
1455 */
1456 protected JViewport viewPort = null;
1457
1458 /**
1459 * Resets the viewport ChangeListener and PropertyChangeListener
1460 */
1461 public void resetViewPort() {
1462 if (viewPort != null) {
1463 viewPort.removeChangeListener(this);
1464 viewPort.removePropertyChangeListener(this);
1465 }
1466 viewPort = JScrollPane.this.getViewport();
1487 scrollBar = getVerticalScrollBar();
1488 if (scrollBar != null) {
1489 setScrollBarRelations(scrollBar);
1490 }
1491 }
1492
1493 /**
1494 * Get the role of this object.
1495 *
1496 * @return an instance of AccessibleRole describing the role of the
1497 * object
1498 * @see AccessibleRole
1499 */
1500 public AccessibleRole getAccessibleRole() {
1501 return AccessibleRole.SCROLL_PANE;
1502 }
1503
1504 /**
1505 * Invoked when the target of the listener has changed its state.
1506 *
1507 * @param e a {@code ChangeEvent} object. Must not be null.
1508 *
1509 * @throws NullPointerException if the parameter is null.
1510 */
1511 public void stateChanged(ChangeEvent e) {
1512 if (e == null) {
1513 throw new NullPointerException();
1514 }
1515 firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY,
1516 Boolean.valueOf(false),
1517 Boolean.valueOf(true));
1518 }
1519
1520 /**
1521 * This method gets called when a bound property is changed.
1522 * @param e A {@code PropertyChangeEvent} object describing
1523 * the event source and the property that has changed. Must not be null.
1524 *
1525 * @throws NullPointerException if the parameter is null.
1526 * @since 1.5
1527 */
1528 public void propertyChange(PropertyChangeEvent e) {
1529 String propertyName = e.getPropertyName();
1530 if (propertyName == "horizontalScrollBar" ||
1531 propertyName == "verticalScrollBar") {
1532
1533 if (e.getNewValue() instanceof JScrollBar) {
1534 setScrollBarRelations((JScrollBar)e.getNewValue());
1535 }
1536 }
1537 }
1538
1539
1540 /*
1541 * Sets the CONTROLLER_FOR and CONTROLLED_BY AccessibleRelations for
1542 * the JScrollPane and JScrollBar. JScrollBar must not be null.
|