0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package javax.swing;
0027
0028 import javax.swing.plaf.*;
0029 import javax.swing.border.*;
0030 import javax.swing.event.*;
0031 import javax.accessibility.*;
0032
0033 import java.awt.Component;
0034 import java.awt.ComponentOrientation;
0035 import java.awt.Graphics;
0036 import java.awt.Rectangle;
0037 import java.awt.Insets;
0038 import java.awt.Color;
0039 import java.awt.LayoutManager;
0040 import java.awt.Point;
0041
0042 import java.io.ObjectOutputStream;
0043 import java.io.ObjectInputStream;
0044 import java.io.IOException;
0045
0046 import java.beans.*;
0047
0048 /**
0049 * Provides a scrollable view of a lightweight component.
0050 * A <code>JScrollPane</code> manages a viewport, optional
0051 * vertical and horizontal scroll bars, and optional row and
0052 * column heading viewports.
0053 * You can find task-oriented documentation of <code>JScrollPane</code> in
0054 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/scrollpane.html">How to Use Scroll Panes</a>,
0055 * a section in <em>The Java Tutorial</em>. Note that
0056 * <code>JScrollPane</code> does not support heavyweight components.
0057 * <p>
0058 * <TABLE ALIGN="RIGHT" BORDER="0" SUMMARY="layout">
0059 * <TR>
0060 * <TD ALIGN="CENTER">
0061 * <P ALIGN="CENTER"><IMG SRC="doc-files/JScrollPane-1.gif"
0062 * alt="The following text describes this image."
0063 * WIDTH="256" HEIGHT="248" ALIGN="BOTTOM" BORDER="0">
0064 * </TD>
0065 * </TR>
0066 * </TABLE>
0067 * The <code>JViewport</code> provides a window,
0068 * or "viewport" onto a data
0069 * source -- for example, a text file. That data source is the
0070 * "scrollable client" (aka data model) displayed by the
0071 * <code>JViewport</code> view.
0072 * A <code>JScrollPane</code> basically consists of <code>JScrollBar</code>s,
0073 * a <code>JViewport</code>, and the wiring between them,
0074 * as shown in the diagram at right.
0075 * <p>
0076 * In addition to the scroll bars and viewport,
0077 * a <code>JScrollPane</code> can have a
0078 * column header and a row header. Each of these is a
0079 * <code>JViewport</code> object that
0080 * you specify with <code>setRowHeaderView</code>,
0081 * and <code>setColumnHeaderView</code>.
0082 * The column header viewport automatically scrolls left and right, tracking
0083 * the left-right scrolling of the main viewport.
0084 * (It never scrolls vertically, however.)
0085 * The row header acts in a similar fashion.
0086 * <p>
0087 * Where two scroll bars meet, the row header meets the column header,
0088 * or a scroll bar meets one of the headers, both components stop short
0089 * of the corner, leaving a rectangular space which is, by default, empty.
0090 * These spaces can potentially exist in any number of the four corners.
0091 * In the previous diagram, the top right space is present and identified
0092 * by the label "corner component".
0093 * <p>
0094 * Any number of these empty spaces can be replaced by using the
0095 * <code>setCorner</code> method to add a component to a particular corner.
0096 * (Note: The same component cannot be added to multiple corners.)
0097 * This is useful if there's
0098 * some extra decoration or function you'd like to add to the scroll pane.
0099 * The size of each corner component is entirely determined by the size of the
0100 * headers and/or scroll bars that surround it.
0101 * <p>
0102 * A corner component will only be visible if there is an empty space in that
0103 * corner for it to exist in. For example, consider a component set into the
0104 * top right corner of a scroll pane with a column header. If the scroll pane's
0105 * vertical scrollbar is not present, perhaps because the view component hasn't
0106 * grown large enough to require it, then the corner component will not be
0107 * shown (since there is no empty space in that corner created by the meeting
0108 * of the header and vertical scroll bar). Forcing the scroll bar to always be
0109 * shown, using
0110 * <code>setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS)</code>,
0111 * will ensure that the space for the corner component always exists.
0112 * <p>
0113 * To add a border around the main viewport,
0114 * you can use <code>setViewportBorder</code>.
0115 * (Of course, you can also add a border around the whole scroll pane using
0116 * <code>setBorder</code>.)
0117 * <p>
0118 * A common operation to want to do is to set the background color that will
0119 * be used if the main viewport view is smaller than the viewport, or is
0120 * not opaque. This can be accomplished by setting the background color
0121 * of the viewport, via <code>scrollPane.getViewport().setBackground()</code>.
0122 * The reason for setting the color of the viewport and not the scrollpane
0123 * is that by default <code>JViewport</code> is opaque
0124 * which, among other things, means it will completely fill
0125 * in its background using its background color. Therefore when
0126 * <code>JScrollPane</code> draws its background the viewport will
0127 * usually draw over it.
0128 * <p>
0129 * By default <code>JScrollPane</code> uses <code>ScrollPaneLayout</code>
0130 * to handle the layout of its child Components. <code>ScrollPaneLayout</code>
0131 * determines the size to make the viewport view in one of two ways:
0132 * <ol>
0133 * <li>If the view implements <code>Scrollable</code>
0134 * a combination of <code>getPreferredScrollableViewportSize</code>,
0135 * <code>getScrollableTracksViewportWidth</code> and
0136 * <code>getScrollableTracksViewportHeight</code>is used, otherwise
0137 * <li><code>getPreferredSize</code> is used.
0138 * </ol>
0139 * <p>
0140 * <strong>Warning:</strong> Swing is not thread safe. For more
0141 * information see <a
0142 * href="package-summary.html#threading">Swing's Threading
0143 * Policy</a>.
0144 * <p>
0145 * <strong>Warning:</strong>
0146 * Serialized objects of this class will not be compatible with
0147 * future Swing releases. The current serialization support is
0148 * appropriate for short term storage or RMI between applications running
0149 * the same version of Swing. As of 1.4, support for long term storage
0150 * of all JavaBeans<sup><font size="-2">TM</font></sup>
0151 * has been added to the <code>java.beans</code> package.
0152 * Please see {@link java.beans.XMLEncoder}.
0153 *
0154 * @see JScrollBar
0155 * @see JViewport
0156 * @see ScrollPaneLayout
0157 * @see Scrollable
0158 * @see Component#getPreferredSize
0159 * @see #setViewportView
0160 * @see #setRowHeaderView
0161 * @see #setColumnHeaderView
0162 * @see #setCorner
0163 * @see #setViewportBorder
0164 *
0165 * @beaninfo
0166 * attribute: isContainer true
0167 * attribute: containerDelegate getViewport
0168 * description: A specialized container that manages a viewport, optional scrollbars and headers
0169 *
0170 * @version 1.116 @(#)JScrollPane.java 1.116
0171 * @author Hans Muller
0172 */
0173 public class JScrollPane extends JComponent implements
0174 ScrollPaneConstants, Accessible {
0175 private Border viewportBorder;
0176
0177 /**
0178 * @see #getUIClassID
0179 * @see #readObject
0180 */
0181 private static final String uiClassID = "ScrollPaneUI";
0182
0183 /**
0184 * The display policy for the vertical scrollbar.
0185 * The default is
0186 * <code>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED</code>.
0187 * @see #setVerticalScrollBarPolicy
0188 */
0189 protected int verticalScrollBarPolicy = VERTICAL_SCROLLBAR_AS_NEEDED;
0190
0191 /**
0192 * The display policy for the horizontal scrollbar.
0193 * The default is
0194 * <code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED</code>.
0195 * @see #setHorizontalScrollBarPolicy
0196 */
0197 protected int horizontalScrollBarPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED;
0198
0199 /**
0200 * The scrollpane's viewport child. Default is an empty
0201 * <code>JViewport</code>.
0202 * @see #setViewport
0203 */
0204 protected JViewport viewport;
0205
0206 /**
0207 * The scrollpane's vertical scrollbar child.
0208 * Default is a <code>JScrollBar</code>.
0209 * @see #setVerticalScrollBar
0210 */
0211 protected JScrollBar verticalScrollBar;
0212
0213 /**
0214 * The scrollpane's horizontal scrollbar child.
0215 * Default is a <code>JScrollBar</code>.
0216 * @see #setHorizontalScrollBar
0217 */
0218 protected JScrollBar horizontalScrollBar;
0219
0220 /**
0221 * The row header child. Default is <code>null</code>.
0222 * @see #setRowHeader
0223 */
0224 protected JViewport rowHeader;
0225
0226 /**
0227 * The column header child. Default is <code>null</code>.
0228 * @see #setColumnHeader
0229 */
0230 protected JViewport columnHeader;
0231
0232 /**
0233 * The component to display in the lower left corner.
0234 * Default is <code>null</code>.
0235 * @see #setCorner
0236 */
0237 protected Component lowerLeft;
0238
0239 /**
0240 * The component to display in the lower right corner.
0241 * Default is <code>null</code>.
0242 * @see #setCorner
0243 */
0244 protected Component lowerRight;
0245
0246 /**
0247 * The component to display in the upper left corner.
0248 * Default is <code>null</code>.
0249 * @see #setCorner
0250 */
0251 protected Component upperLeft;
0252
0253 /**
0254 * The component to display in the upper right corner.
0255 * Default is <code>null</code>.
0256 * @see #setCorner
0257 */
0258 protected Component upperRight;
0259
0260 /*
0261 * State flag for mouse wheel scrolling
0262 */
0263 private boolean wheelScrollState = true;
0264
0265 /**
0266 * Creates a <code>JScrollPane</code> that displays the view
0267 * component in a viewport
0268 * whose view position can be controlled with a pair of scrollbars.
0269 * The scrollbar policies specify when the scrollbars are displayed,
0270 * For example, if <code>vsbPolicy</code> is
0271 * <code>VERTICAL_SCROLLBAR_AS_NEEDED</code>
0272 * then the vertical scrollbar only appears if the view doesn't fit
0273 * vertically. The available policy settings are listed at
0274 * {@link #setVerticalScrollBarPolicy} and
0275 * {@link #setHorizontalScrollBarPolicy}.
0276 *
0277 * @see #setViewportView
0278 *
0279 * @param view the component to display in the scrollpanes viewport
0280 * @param vsbPolicy an integer that specifies the vertical
0281 * scrollbar policy
0282 * @param hsbPolicy an integer that specifies the horizontal
0283 * scrollbar policy
0284 */
0285 public JScrollPane(Component view, int vsbPolicy, int hsbPolicy) {
0286 setLayout(new ScrollPaneLayout.UIResource());
0287 setVerticalScrollBarPolicy(vsbPolicy);
0288 setHorizontalScrollBarPolicy(hsbPolicy);
0289 setViewport(createViewport());
0290 setVerticalScrollBar(createVerticalScrollBar());
0291 setHorizontalScrollBar(createHorizontalScrollBar());
0292 if (view != null) {
0293 setViewportView(view);
0294 }
0295 setOpaque(true);
0296 updateUI();
0297
0298 if (!this .getComponentOrientation().isLeftToRight()) {
0299 viewport.setViewPosition(new Point(Integer.MAX_VALUE, 0));
0300 }
0301 }
0302
0303 /**
0304 * Creates a <code>JScrollPane</code> that displays the
0305 * contents of the specified
0306 * component, where both horizontal and vertical scrollbars appear
0307 * whenever the component's contents are larger than the view.
0308 *
0309 * @see #setViewportView
0310 * @param view the component to display in the scrollpane's viewport
0311 */
0312 public JScrollPane(Component view) {
0313 this (view, VERTICAL_SCROLLBAR_AS_NEEDED,
0314 HORIZONTAL_SCROLLBAR_AS_NEEDED);
0315 }
0316
0317 /**
0318 * Creates an empty (no viewport view) <code>JScrollPane</code>
0319 * with specified
0320 * scrollbar policies. The available policy settings are listed at
0321 * {@link #setVerticalScrollBarPolicy} and
0322 * {@link #setHorizontalScrollBarPolicy}.
0323 *
0324 * @see #setViewportView
0325 *
0326 * @param vsbPolicy an integer that specifies the vertical
0327 * scrollbar policy
0328 * @param hsbPolicy an integer that specifies the horizontal
0329 * scrollbar policy
0330 */
0331 public JScrollPane(int vsbPolicy, int hsbPolicy) {
0332 this (null, vsbPolicy, hsbPolicy);
0333 }
0334
0335 /**
0336 * Creates an empty (no viewport view) <code>JScrollPane</code>
0337 * where both horizontal and vertical scrollbars appear when needed.
0338 */
0339 public JScrollPane() {
0340 this (null, VERTICAL_SCROLLBAR_AS_NEEDED,
0341 HORIZONTAL_SCROLLBAR_AS_NEEDED);
0342 }
0343
0344 /**
0345 * Returns the look and feel (L&F) object that renders this component.
0346 *
0347 * @return the <code>ScrollPaneUI</code> object that renders this
0348 * component
0349 * @see #setUI
0350 * @beaninfo
0351 * bound: true
0352 * hidden: true
0353 * attribute: visualUpdate true
0354 * description: The UI object that implements the Component's LookAndFeel.
0355 */
0356 public ScrollPaneUI getUI() {
0357 return (ScrollPaneUI) ui;
0358 }
0359
0360 /**
0361 * Sets the <code>ScrollPaneUI</code> object that provides the
0362 * look and feel (L&F) for this component.
0363 *
0364 * @param ui the <code>ScrollPaneUI</code> L&F object
0365 * @see #getUI
0366 */
0367 public void setUI(ScrollPaneUI ui) {
0368 super .setUI(ui);
0369 }
0370
0371 /**
0372 * Replaces the current <code>ScrollPaneUI</code> object with a version
0373 * from the current default look and feel.
0374 * To be called when the default look and feel changes.
0375 *
0376 * @see JComponent#updateUI
0377 * @see UIManager#getUI
0378 */
0379 public void updateUI() {
0380 setUI((ScrollPaneUI) UIManager.getUI(this ));
0381 }
0382
0383 /**
0384 * Returns the suffix used to construct the name of the L&F class used to
0385 * render this component.
0386 *
0387 * @return the string "ScrollPaneUI"
0388 * @see JComponent#getUIClassID
0389 * @see UIDefaults#getUI
0390 *
0391 * @beaninfo
0392 * hidden: true
0393 */
0394 public String getUIClassID() {
0395 return uiClassID;
0396 }
0397
0398 /**
0399 * Sets the layout manager for this <code>JScrollPane</code>.
0400 * This method overrides <code>setLayout</code> in
0401 * <code>java.awt.Container</code> to ensure that only
0402 * <code>LayoutManager</code>s which
0403 * are subclasses of <code>ScrollPaneLayout</code> can be used in a
0404 * <code>JScrollPane</code>. If <code>layout</code> is non-null, this
0405 * will invoke <code>syncWithScrollPane</code> on it.
0406 *
0407 * @param layout the specified layout manager
0408 * @exception ClassCastException if layout is not a
0409 * <code>ScrollPaneLayout</code>
0410 * @see java.awt.Container#getLayout
0411 * @see java.awt.Container#setLayout
0412 *
0413 * @beaninfo
0414 * hidden: true
0415 */
0416 public void setLayout(LayoutManager layout) {
0417 if (layout instanceof ScrollPaneLayout) {
0418 super .setLayout(layout);
0419 ((ScrollPaneLayout) layout).syncWithScrollPane(this );
0420 } else if (layout == null) {
0421 super .setLayout(layout);
0422 } else {
0423 String s = "layout of JScrollPane must be a ScrollPaneLayout";
0424 throw new ClassCastException(s);
0425 }
0426 }
0427
0428 /**
0429 * Overridden to return true so that any calls to <code>revalidate</code>
0430 * on any descendants of this <code>JScrollPane</code> will cause the
0431 * entire tree beginning with this <code>JScrollPane</code> to be
0432 * validated.
0433 *
0434 * @return true
0435 * @see java.awt.Container#validate
0436 * @see JComponent#revalidate
0437 * @see JComponent#isValidateRoot
0438 *
0439 * @beaninfo
0440 * hidden: true
0441 */
0442 public boolean isValidateRoot() {
0443 return true;
0444 }
0445
0446 /**
0447 * Returns the vertical scroll bar policy value.
0448 * @return the <code>verticalScrollBarPolicy</code> property
0449 * @see #setVerticalScrollBarPolicy
0450 */
0451 public int getVerticalScrollBarPolicy() {
0452 return verticalScrollBarPolicy;
0453 }
0454
0455 /**
0456 * Determines when the vertical scrollbar appears in the scrollpane.
0457 * Legal values are:
0458 * <ul>
0459 * <li><code>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED</code>
0460 * <li><code>ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER</code>
0461 * <li><code>ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS</code>
0462 * </ul>
0463 *
0464 * @param policy one of the three values listed above
0465 * @exception IllegalArgumentException if <code>policy</code>
0466 * is not one of the legal values shown above
0467 * @see #getVerticalScrollBarPolicy
0468 *
0469 * @beaninfo
0470 * preferred: true
0471 * bound: true
0472 * description: The scrollpane vertical scrollbar policy
0473 * enum: VERTICAL_SCROLLBAR_AS_NEEDED ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
0474 * VERTICAL_SCROLLBAR_NEVER ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER
0475 * VERTICAL_SCROLLBAR_ALWAYS ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
0476 */
0477 public void setVerticalScrollBarPolicy(int policy) {
0478 switch (policy) {
0479 case VERTICAL_SCROLLBAR_AS_NEEDED:
0480 case VERTICAL_SCROLLBAR_NEVER:
0481 case VERTICAL_SCROLLBAR_ALWAYS:
0482 break;
0483 default:
0484 throw new IllegalArgumentException(
0485 "invalid verticalScrollBarPolicy");
0486 }
0487 int old = verticalScrollBarPolicy;
0488 verticalScrollBarPolicy = policy;
0489 firePropertyChange("verticalScrollBarPolicy", old, policy);
0490 revalidate();
0491 repaint();
0492 }
0493
0494 /**
0495 * Returns the horizontal scroll bar policy value.
0496 * @return the <code>horizontalScrollBarPolicy</code> property
0497 * @see #setHorizontalScrollBarPolicy
0498 */
0499 public int getHorizontalScrollBarPolicy() {
0500 return horizontalScrollBarPolicy;
0501 }
0502
0503 /**
0504 * Determines when the horizontal scrollbar appears in the scrollpane.
0505 * The options are:<ul>
0506 * <li><code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED</code>
0507 * <li><code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER</code>
0508 * <li><code>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS</code>
0509 * </ul>
0510 *
0511 * @param policy one of the three values listed above
0512 * @exception IllegalArgumentException if <code>policy</code>
0513 * is not one of the legal values shown above
0514 * @see #getHorizontalScrollBarPolicy
0515 *
0516 * @beaninfo
0517 * preferred: true
0518 * bound: true
0519 * description: The scrollpane scrollbar policy
0520 * enum: HORIZONTAL_SCROLLBAR_AS_NEEDED ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
0521 * HORIZONTAL_SCROLLBAR_NEVER ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
0522 * HORIZONTAL_SCROLLBAR_ALWAYS ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
0523 */
0524 public void setHorizontalScrollBarPolicy(int policy) {
0525 switch (policy) {
0526 case HORIZONTAL_SCROLLBAR_AS_NEEDED:
0527 case HORIZONTAL_SCROLLBAR_NEVER:
0528 case HORIZONTAL_SCROLLBAR_ALWAYS:
0529 break;
0530 default:
0531 throw new IllegalArgumentException(
0532 "invalid horizontalScrollBarPolicy");
0533 }
0534 int old = horizontalScrollBarPolicy;
0535 horizontalScrollBarPolicy = policy;
0536 firePropertyChange("horizontalScrollBarPolicy", old, policy);
0537 revalidate();
0538 repaint();
0539 }
0540
0541 /**
0542 * Returns the <code>Border</code> object that surrounds the viewport.
0543 *
0544 * @return the <code>viewportBorder</code> property
0545 * @see #setViewportBorder
0546 */
0547 public Border getViewportBorder() {
0548 return viewportBorder;
0549 }
0550
0551 /**
0552 * Adds a border around the viewport. Note that the border isn't
0553 * set on the viewport directly, <code>JViewport</code> doesn't support
0554 * the <code>JComponent</code> border property.
0555 * Similarly setting the <code>JScrollPane</code>s
0556 * viewport doesn't affect the <code>viewportBorder</code> property.
0557 * <p>
0558 * The default value of this property is computed by the look
0559 * and feel implementation.
0560 *
0561 * @param viewportBorder the border to be added
0562 * @see #getViewportBorder
0563 * @see #setViewport
0564 *
0565 * @beaninfo
0566 * preferred: true
0567 * bound: true
0568 * description: The border around the viewport.
0569 */
0570 public void setViewportBorder(Border viewportBorder) {
0571 Border oldValue = this .viewportBorder;
0572 this .viewportBorder = viewportBorder;
0573 firePropertyChange("viewportBorder", oldValue, viewportBorder);
0574 }
0575
0576 /**
0577 * Returns the bounds of the viewport's border.
0578 *
0579 * @return a <code>Rectangle</code> object specifying the viewport border
0580 */
0581 public Rectangle getViewportBorderBounds() {
0582 Rectangle borderR = new Rectangle(getSize());
0583
0584 Insets insets = getInsets();
0585 borderR.x = insets.left;
0586 borderR.y = insets.top;
0587 borderR.width -= insets.left + insets.right;
0588 borderR.height -= insets.top + insets.bottom;
0589
0590 boolean leftToRight = SwingUtilities.isLeftToRight(this );
0591
0592 /* If there's a visible column header remove the space it
0593 * needs from the top of borderR.
0594 */
0595
0596 JViewport colHead = getColumnHeader();
0597 if ((colHead != null) && (colHead.isVisible())) {
0598 int colHeadHeight = colHead.getHeight();
0599 borderR.y += colHeadHeight;
0600 borderR.height -= colHeadHeight;
0601 }
0602
0603 /* If there's a visible row header remove the space it needs
0604 * from the left of borderR.
0605 */
0606
0607 JViewport rowHead = getRowHeader();
0608 if ((rowHead != null) && (rowHead.isVisible())) {
0609 int rowHeadWidth = rowHead.getWidth();
0610 if (leftToRight) {
0611 borderR.x += rowHeadWidth;
0612 }
0613 borderR.width -= rowHeadWidth;
0614 }
0615
0616 /* If there's a visible vertical scrollbar remove the space it needs
0617 * from the width of borderR.
0618 */
0619 JScrollBar vsb = getVerticalScrollBar();
0620 if ((vsb != null) && (vsb.isVisible())) {
0621 int vsbWidth = vsb.getWidth();
0622 if (!leftToRight) {
0623 borderR.x += vsbWidth;
0624 }
0625 borderR.width -= vsbWidth;
0626 }
0627
0628 /* If there's a visible horizontal scrollbar remove the space it needs
0629 * from the height of borderR.
0630 */
0631 JScrollBar hsb = getHorizontalScrollBar();
0632 if ((hsb != null) && (hsb.isVisible())) {
0633 borderR.height -= hsb.getHeight();
0634 }
0635
0636 return borderR;
0637 }
0638
0639 /**
0640 * By default <code>JScrollPane</code> creates scrollbars
0641 * that are instances
0642 * of this class. <code>Scrollbar</code> overrides the
0643 * <code>getUnitIncrement</code> and <code>getBlockIncrement</code>
0644 * methods so that, if the viewport's view is a <code>Scrollable</code>,
0645 * the view is asked to compute these values. Unless
0646 * the unit/block increment have been explicitly set.
0647 * <p>
0648 * <strong>Warning:</strong>
0649 * Serialized objects of this class will not be compatible with
0650 * future Swing releases. The current serialization support is
0651 * appropriate for short term storage or RMI between applications running
0652 * the same version of Swing. As of 1.4, support for long term storage
0653 * of all JavaBeans<sup><font size="-2">TM</font></sup>
0654 * has been added to the <code>java.beans</code> package.
0655 * Please see {@link java.beans.XMLEncoder}.
0656 *
0657 * @see Scrollable
0658 * @see JScrollPane#createVerticalScrollBar
0659 * @see JScrollPane#createHorizontalScrollBar
0660 */
0661 protected class ScrollBar extends JScrollBar implements UIResource {
0662 /**
0663 * Set to true when the unit increment has been explicitly set.
0664 * If this is false the viewport's view is obtained and if it
0665 * is an instance of <code>Scrollable</code> the unit increment
0666 * from it is used.
0667 */
0668 private boolean unitIncrementSet;
0669 /**
0670 * Set to true when the block increment has been explicitly set.
0671 * If this is false the viewport's view is obtained and if it
0672 * is an instance of <code>Scrollable</code> the block increment
0673 * from it is used.
0674 */
0675 private boolean blockIncrementSet;
0676
0677 /**
0678 * Creates a scrollbar with the specified orientation.
0679 * The options are:
0680 * <ul>
0681 * <li><code>ScrollPaneConstants.VERTICAL</code>
0682 * <li><code>ScrollPaneConstants.HORIZONTAL</code>
0683 * </ul>
0684 *
0685 * @param orientation an integer specifying one of the legal
0686 * orientation values shown above
0687 * @since 1.4
0688 */
0689 public ScrollBar(int orientation) {
0690 super (orientation);
0691 this .putClientProperty("JScrollBar.fastWheelScrolling",
0692 Boolean.TRUE);
0693 }
0694
0695 /**
0696 * Messages super to set the value, and resets the
0697 * <code>unitIncrementSet</code> instance variable to true.
0698 *
0699 * @param unitIncrement the new unit increment value, in pixels
0700 */
0701 public void setUnitIncrement(int unitIncrement) {
0702 unitIncrementSet = true;
0703 this .putClientProperty("JScrollBar.fastWheelScrolling",
0704 null);
0705 super .setUnitIncrement(unitIncrement);
0706 }
0707
0708 /**
0709 * Computes the unit increment for scrolling if the viewport's
0710 * view is a <code>Scrollable</code> object.
0711 * Otherwise return <code>super.getUnitIncrement</code>.
0712 *
0713 * @param direction less than zero to scroll up/left,
0714 * greater than zero for down/right
0715 * @return an integer, in pixels, containing the unit increment
0716 * @see Scrollable#getScrollableUnitIncrement
0717 */
0718 public int getUnitIncrement(int direction) {
0719 JViewport vp = getViewport();
0720 if (!unitIncrementSet && (vp != null)
0721 && (vp.getView() instanceof Scrollable)) {
0722 Scrollable view = (Scrollable) (vp.getView());
0723 Rectangle vr = vp.getViewRect();
0724 return view.getScrollableUnitIncrement(vr,
0725 getOrientation(), direction);
0726 } else {
0727 return super .getUnitIncrement(direction);
0728 }
0729 }
0730
0731 /**
0732 * Messages super to set the value, and resets the
0733 * <code>blockIncrementSet</code> instance variable to true.
0734 *
0735 * @param blockIncrement the new block increment value, in pixels
0736 */
0737 public void setBlockIncrement(int blockIncrement) {
0738 blockIncrementSet = true;
0739 this .putClientProperty("JScrollBar.fastWheelScrolling",
0740 null);
0741 super .setBlockIncrement(blockIncrement);
0742 }
0743
0744 /**
0745 * Computes the block increment for scrolling if the viewport's
0746 * view is a <code>Scrollable</code> object. Otherwise
0747 * the <code>blockIncrement</code> equals the viewport's width
0748 * or height. If there's no viewport return
0749 * <code>super.getBlockIncrement</code>.
0750 *
0751 * @param direction less than zero to scroll up/left,
0752 * greater than zero for down/right
0753 * @return an integer, in pixels, containing the block increment
0754 * @see Scrollable#getScrollableBlockIncrement
0755 */
0756 public int getBlockIncrement(int direction) {
0757 JViewport vp = getViewport();
0758 if (blockIncrementSet || vp == null) {
0759 return super .getBlockIncrement(direction);
0760 } else if (vp.getView() instanceof Scrollable) {
0761 Scrollable view = (Scrollable) (vp.getView());
0762 Rectangle vr = vp.getViewRect();
0763 return view.getScrollableBlockIncrement(vr,
0764 getOrientation(), direction);
0765 } else if (getOrientation() == VERTICAL) {
0766 return vp.getExtentSize().height;
0767 } else {
0768 return vp.getExtentSize().width;
0769 }
0770 }
0771
0772 }
0773
0774 /**
0775 * Returns a <code>JScrollPane.ScrollBar</code> by default.
0776 * Subclasses may override this method to force <code>ScrollPaneUI</code>
0777 * implementations to use a <code>JScrollBar</code> subclass.
0778 * Used by <code>ScrollPaneUI</code> implementations to
0779 * create the horizontal scrollbar.
0780 *
0781 * @return a <code>JScrollBar</code> with a horizontal orientation
0782 * @see JScrollBar
0783 */
0784 public JScrollBar createHorizontalScrollBar() {
0785 return new ScrollBar(JScrollBar.HORIZONTAL);
0786 }
0787
0788 /**
0789 * Returns the horizontal scroll bar that controls the viewport's
0790 * horizontal view position.
0791 *
0792 * @return the <code>horizontalScrollBar</code> property
0793 * @see #setHorizontalScrollBar
0794 */
0795 public JScrollBar getHorizontalScrollBar() {
0796 return horizontalScrollBar;
0797 }
0798
0799 /**
0800 * Adds the scrollbar that controls the viewport's horizontal view
0801 * position to the scrollpane.
0802 * This is usually unnecessary, as <code>JScrollPane</code> creates
0803 * horizontal and vertical scrollbars by default.
0804 *
0805 * @param horizontalScrollBar the horizontal scrollbar to be added
0806 * @see #createHorizontalScrollBar
0807 * @see #getHorizontalScrollBar
0808 *
0809 * @beaninfo
0810 * expert: true
0811 * bound: true
0812 * description: The horizontal scrollbar.
0813 */
0814 public void setHorizontalScrollBar(JScrollBar horizontalScrollBar) {
0815 JScrollBar old = getHorizontalScrollBar();
0816 this .horizontalScrollBar = horizontalScrollBar;
0817 if (horizontalScrollBar != null) {
0818 add(horizontalScrollBar, HORIZONTAL_SCROLLBAR);
0819 } else if (old != null) {
0820 remove(old);
0821 }
0822 firePropertyChange("horizontalScrollBar", old,
0823 horizontalScrollBar);
0824
0825 revalidate();
0826 repaint();
0827 }
0828
0829 /**
0830 * Returns a <code>JScrollPane.ScrollBar</code> by default. Subclasses
0831 * may override this method to force <code>ScrollPaneUI</code>
0832 * implementations to use a <code>JScrollBar</code> subclass.
0833 * Used by <code>ScrollPaneUI</code> implementations to create the
0834 * vertical scrollbar.
0835 *
0836 * @return a <code>JScrollBar</code> with a vertical orientation
0837 * @see JScrollBar
0838 */
0839 public JScrollBar createVerticalScrollBar() {
0840 return new ScrollBar(JScrollBar.VERTICAL);
0841 }
0842
0843 /**
0844 * Returns the vertical scroll bar that controls the viewports
0845 * vertical view position.
0846 *
0847 * @return the <code>verticalScrollBar</code> property
0848 * @see #setVerticalScrollBar
0849 */
0850 public JScrollBar getVerticalScrollBar() {
0851 return verticalScrollBar;
0852 }
0853
0854 /**
0855 * Adds the scrollbar that controls the viewports vertical view position
0856 * to the scrollpane. This is usually unnecessary,
0857 * as <code>JScrollPane</code> creates vertical and
0858 * horizontal scrollbars by default.
0859 *
0860 * @param verticalScrollBar the new vertical scrollbar to be added
0861 * @see #createVerticalScrollBar
0862 * @see #getVerticalScrollBar
0863 *
0864 * @beaninfo
0865 * expert: true
0866 * bound: true
0867 * description: The vertical scrollbar.
0868 */
0869 public void setVerticalScrollBar(JScrollBar verticalScrollBar) {
0870 JScrollBar old = getVerticalScrollBar();
0871 this .verticalScrollBar = verticalScrollBar;
0872 add(verticalScrollBar, VERTICAL_SCROLLBAR);
0873 firePropertyChange("verticalScrollBar", old, verticalScrollBar);
0874
0875 revalidate();
0876 repaint();
0877 }
0878
0879 /**
0880 * Returns a new <code>JViewport</code> by default.
0881 * Used to create the
0882 * viewport (as needed) in <code>setViewportView</code>,
0883 * <code>setRowHeaderView</code>, and <code>setColumnHeaderView</code>.
0884 * Subclasses may override this method to return a subclass of
0885 * <code>JViewport</code>.
0886 *
0887 * @return a new <code>JViewport</code>
0888 */
0889 protected JViewport createViewport() {
0890 return new JViewport();
0891 }
0892
0893 /**
0894 * Returns the current <code>JViewport</code>.
0895 *
0896 * @see #setViewport
0897 * @return the <code>viewport</code> property
0898 */
0899 public JViewport getViewport() {
0900 return viewport;
0901 }
0902
0903 /**
0904 * Removes the old viewport (if there is one); forces the
0905 * viewPosition of the new viewport to be in the +x,+y quadrant;
0906 * syncs up the row and column headers (if there are any) with the
0907 * new viewport; and finally syncs the scrollbars and
0908 * headers with the new viewport.
0909 * <p>
0910 * Most applications will find it more convenient to use
0911 * <code>setViewportView</code>
0912 * to add a viewport and a view to the scrollpane.
0913 *
0914 * @param viewport the new viewport to be used; if viewport is
0915 * <code>null</code>, the old viewport is still removed
0916 * and the new viewport is set to <code>null</code>
0917 * @see #createViewport
0918 * @see #getViewport
0919 * @see #setViewportView
0920 *
0921 * @beaninfo
0922 * expert: true
0923 * bound: true
0924 * attribute: visualUpdate true
0925 * description: The viewport child for this scrollpane
0926 *
0927 */
0928 public void setViewport(JViewport viewport) {
0929 JViewport old = getViewport();
0930 this .viewport = viewport;
0931 if (viewport != null) {
0932 add(viewport, VIEWPORT);
0933 } else if (old != null) {
0934 remove(old);
0935 }
0936 firePropertyChange("viewport", old, viewport);
0937
0938 if (accessibleContext != null) {
0939 ((AccessibleJScrollPane) accessibleContext).resetViewPort();
0940 }
0941
0942 revalidate();
0943 repaint();
0944 }
0945
0946 /**
0947 * Creates a viewport if necessary and then sets its view. Applications
0948 * that don't provide the view directly to the <code>JScrollPane</code>
0949 * constructor
0950 * should use this method to specify the scrollable child that's going
0951 * to be displayed in the scrollpane. For example:
0952 * <pre>
0953 * JScrollPane scrollpane = new JScrollPane();
0954 * scrollpane.setViewportView(myBigComponentToScroll);
0955 * </pre>
0956 * Applications should not add children directly to the scrollpane.
0957 *
0958 * @param view the component to add to the viewport
0959 * @see #setViewport
0960 * @see JViewport#setView
0961 */
0962 public void setViewportView(Component view) {
0963 if (getViewport() == null) {
0964 setViewport(createViewport());
0965 }
0966 getViewport().setView(view);
0967 }
0968
0969 /**
0970 * Returns the row header.
0971 * @return the <code>rowHeader</code> property
0972 * @see #setRowHeader
0973 */
0974 public JViewport getRowHeader() {
0975 return rowHeader;
0976 }
0977
0978 /**
0979 * Removes the old rowHeader, if it exists; if the new rowHeader
0980 * isn't <code>null</code>, syncs the y coordinate of its
0981 * viewPosition with
0982 * the viewport (if there is one) and then adds it to the scroll pane.
0983 * <p>
0984 * Most applications will find it more convenient to use
0985 * <code>setRowHeaderView</code>
0986 * to add a row header component and its viewport to the scroll pane.
0987 *
0988 * @param rowHeader the new row header to be used; if <code>null</code>
0989 * the old row header is still removed and the new rowHeader
0990 * is set to <code>null</code>
0991 * @see #getRowHeader
0992 * @see #setRowHeaderView
0993 *
0994 * @beaninfo
0995 * bound: true
0996 * expert: true
0997 * description: The row header child for this scrollpane
0998 */
0999 public void setRowHeader(JViewport rowHeader) {
1000 JViewport old = getRowHeader();
1001 this .rowHeader = rowHeader;
1002 if (rowHeader != null) {
1003 add(rowHeader, ROW_HEADER);
1004 } else if (old != null) {
1005 remove(old);
1006 }
1007 firePropertyChange("rowHeader", old, rowHeader);
1008 revalidate();
1009 repaint();
1010 }
1011
1012 /**
1013 * Creates a row-header viewport if necessary, sets
1014 * its view and then adds the row-header viewport
1015 * to the scrollpane. For example:
1016 * <pre>
1017 * JScrollPane scrollpane = new JScrollPane();
1018 * scrollpane.setViewportView(myBigComponentToScroll);
1019 * scrollpane.setRowHeaderView(myBigComponentsRowHeader);
1020 * </pre>
1021 *
1022 * @see #setRowHeader
1023 * @see JViewport#setView
1024 * @param view the component to display as the row header
1025 */
1026 public void setRowHeaderView(Component view) {
1027 if (getRowHeader() == null) {
1028 setRowHeader(createViewport());
1029 }
1030 getRowHeader().setView(view);
1031 }
1032
1033 /**
1034 * Returns the column header.
1035 * @return the <code>columnHeader</code> property
1036 * @see #setColumnHeader
1037 */
1038 public JViewport getColumnHeader() {
1039 return columnHeader;
1040 }
1041
1042 /**
1043 * Removes the old columnHeader, if it exists; if the new columnHeader
1044 * isn't <code>null</code>, syncs the x coordinate of its viewPosition
1045 * with the viewport (if there is one) and then adds it to the scroll pane.
1046 * <p>
1047 * Most applications will find it more convenient to use
1048 * <code>setColumnHeaderView</code>
1049 * to add a column header component and its viewport to the scroll pane.
1050 *
1051 * @see #getColumnHeader
1052 * @see #setColumnHeaderView
1053 *
1054 * @beaninfo
1055 * bound: true
1056 * description: The column header child for this scrollpane
1057 * attribute: visualUpdate true
1058 */
1059 public void setColumnHeader(JViewport columnHeader) {
1060 JViewport old = getColumnHeader();
1061 this .columnHeader = columnHeader;
1062 if (columnHeader != null) {
1063 add(columnHeader, COLUMN_HEADER);
1064 } else if (old != null) {
1065 remove(old);
1066 }
1067 firePropertyChange("columnHeader", old, columnHeader);
1068
1069 revalidate();
1070 repaint();
1071 }
1072
1073 /**
1074 * Creates a column-header viewport if necessary, sets
1075 * its view, and then adds the column-header viewport
1076 * to the scrollpane. For example:
1077 * <pre>
1078 * JScrollPane scrollpane = new JScrollPane();
1079 * scrollpane.setViewportView(myBigComponentToScroll);
1080 * scrollpane.setColumnHeaderView(myBigComponentsColumnHeader);
1081 * </pre>
1082 *
1083 * @see #setColumnHeader
1084 * @see JViewport#setView
1085 *
1086 * @param view the component to display as the column header
1087 */
1088 public void setColumnHeaderView(Component view) {
1089 if (getColumnHeader() == null) {
1090 setColumnHeader(createViewport());
1091 }
1092 getColumnHeader().setView(view);
1093 }
1094
1095 /**
1096 * Returns the component at the specified corner. The
1097 * <code>key</code> value specifying the corner is one of:
1098 * <ul>
1099 * <li>ScrollPaneConstants.LOWER_LEFT_CORNER
1100 * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
1101 * <li>ScrollPaneConstants.UPPER_LEFT_CORNER
1102 * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
1103 * <li>ScrollPaneConstants.LOWER_LEADING_CORNER
1104 * <li>ScrollPaneConstants.LOWER_TRAILING_CORNER
1105 * <li>ScrollPaneConstants.UPPER_LEADING_CORNER
1106 * <li>ScrollPaneConstants.UPPER_TRAILING_CORNER
1107 * </ul>
1108 *
1109 * @param key one of the values as shown above
1110 * @return the corner component (which may be <code>null</code>)
1111 * identified by the given key, or <code>null</code>
1112 * if the key is invalid
1113 * @see #setCorner
1114 */
1115 public Component getCorner(String key) {
1116 boolean isLeftToRight = getComponentOrientation()
1117 .isLeftToRight();
1118 if (key.equals(LOWER_LEADING_CORNER)) {
1119 key = isLeftToRight ? LOWER_LEFT_CORNER
1120 : LOWER_RIGHT_CORNER;
1121 } else if (key.equals(LOWER_TRAILING_CORNER)) {
1122 key = isLeftToRight ? LOWER_RIGHT_CORNER
1123 : LOWER_LEFT_CORNER;
1124 } else if (key.equals(UPPER_LEADING_CORNER)) {
1125 key = isLeftToRight ? UPPER_LEFT_CORNER
1126 : UPPER_RIGHT_CORNER;
1127 } else if (key.equals(UPPER_TRAILING_CORNER)) {
1128 key = isLeftToRight ? UPPER_RIGHT_CORNER
1129 : UPPER_LEFT_CORNER;
1130 }
1131 if (key.equals(LOWER_LEFT_CORNER)) {
1132 return lowerLeft;
1133 } else if (key.equals(LOWER_RIGHT_CORNER)) {
1134 return lowerRight;
1135 } else if (key.equals(UPPER_LEFT_CORNER)) {
1136 return upperLeft;
1137 } else if (key.equals(UPPER_RIGHT_CORNER)) {
1138 return upperRight;
1139 } else {
1140 return null;
1141 }
1142 }
1143
1144 /**
1145 * Adds a child that will appear in one of the scroll panes
1146 * corners, if there's room. For example with both scrollbars
1147 * showing (on the right and bottom edges of the scrollpane)
1148 * the lower left corner component will be shown in the space
1149 * between ends of the two scrollbars. Legal values for
1150 * the <b>key</b> are:
1151 * <ul>
1152 * <li>ScrollPaneConstants.LOWER_LEFT_CORNER
1153 * <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
1154 * <li>ScrollPaneConstants.UPPER_LEFT_CORNER
1155 * <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
1156 * <li>ScrollPaneConstants.LOWER_LEADING_CORNER
1157 * <li>ScrollPaneConstants.LOWER_TRAILING_CORNER
1158 * <li>ScrollPaneConstants.UPPER_LEADING_CORNER
1159 * <li>ScrollPaneConstants.UPPER_TRAILING_CORNER
1160 * </ul>
1161 * <p>
1162 * Although "corner" doesn't match any beans property
1163 * signature, <code>PropertyChange</code> events are generated with the
1164 * property name set to the corner key.
1165 *
1166 * @param key identifies which corner the component will appear in
1167 * @param corner one of the following components:
1168 * <ul>
1169 * <li>lowerLeft
1170 * <li>lowerRight
1171 * <li>upperLeft
1172 * <li>upperRight
1173 * </ul>
1174 * @exception IllegalArgumentException if corner key is invalid
1175 */
1176 public void setCorner(String key, Component corner) {
1177 Component old;
1178 boolean isLeftToRight = getComponentOrientation()
1179 .isLeftToRight();
1180 if (key.equals(LOWER_LEADING_CORNER)) {
1181 key = isLeftToRight ? LOWER_LEFT_CORNER
1182 : LOWER_RIGHT_CORNER;
1183 } else if (key.equals(LOWER_TRAILING_CORNER)) {
1184 key = isLeftToRight ? LOWER_RIGHT_CORNER
1185 : LOWER_LEFT_CORNER;
1186 } else if (key.equals(UPPER_LEADING_CORNER)) {
1187 key = isLeftToRight ? UPPER_LEFT_CORNER
1188 : UPPER_RIGHT_CORNER;
1189 } else if (key.equals(UPPER_TRAILING_CORNER)) {
1190 key = isLeftToRight ? UPPER_RIGHT_CORNER
1191 : UPPER_LEFT_CORNER;
1192 }
1193 if (key.equals(LOWER_LEFT_CORNER)) {
1194 old = lowerLeft;
1195 lowerLeft = corner;
1196 } else if (key.equals(LOWER_RIGHT_CORNER)) {
1197 old = lowerRight;
1198 lowerRight = corner;
1199 } else if (key.equals(UPPER_LEFT_CORNER)) {
1200 old = upperLeft;
1201 upperLeft = corner;
1202 } else if (key.equals(UPPER_RIGHT_CORNER)) {
1203 old = upperRight;
1204 upperRight = corner;
1205 } else {
1206 throw new IllegalArgumentException("invalid corner key");
1207 }
1208 if (old != null) {
1209 remove(old);
1210 }
1211 if (corner != null) {
1212 add(corner, key);
1213 }
1214 firePropertyChange(key, old, corner);
1215 revalidate();
1216 repaint();
1217 }
1218
1219 /**
1220 * Sets the orientation for the vertical and horizontal
1221 * scrollbars as determined by the
1222 * <code>ComponentOrientation</code> argument.
1223 *
1224 * @param co one of the following values:
1225 * <ul>
1226 * <li>java.awt.ComponentOrientation.LEFT_TO_RIGHT
1227 * <li>java.awt.ComponentOrientation.RIGHT_TO_LEFT
1228 * <li>java.awt.ComponentOrientation.UNKNOWN
1229 * </ul>
1230 * @see java.awt.ComponentOrientation
1231 */
1232 public void setComponentOrientation(ComponentOrientation co) {
1233 super .setComponentOrientation(co);
1234 if (verticalScrollBar != null)
1235 verticalScrollBar.setComponentOrientation(co);
1236 if (horizontalScrollBar != null)
1237 horizontalScrollBar.setComponentOrientation(co);
1238 }
1239
1240 /**
1241 * Indicates whether or not scrolling will take place in response to the
1242 * mouse wheel. Wheel scrolling is enabled by default.
1243 *
1244 * @see #setWheelScrollingEnabled
1245 * @since 1.4
1246 * @beaninfo
1247 * bound: true
1248 * description: Flag for enabling/disabling mouse wheel scrolling
1249 */
1250 public boolean isWheelScrollingEnabled() {
1251 return wheelScrollState;
1252 }
1253
1254 /**
1255 * Enables/disables scrolling in response to movement of the mouse wheel.
1256 * Wheel scrolling is enabled by default.
1257 *
1258 * @param handleWheel <code>true</code> if scrolling should be done
1259 * automatically for a MouseWheelEvent,
1260 * <code>false</code> otherwise.
1261 * @see #isWheelScrollingEnabled
1262 * @see java.awt.event.MouseWheelEvent
1263 * @see java.awt.event.MouseWheelListener
1264 * @since 1.4
1265 * @beaninfo
1266 * bound: true
1267 * description: Flag for enabling/disabling mouse wheel scrolling
1268 */
1269 public void setWheelScrollingEnabled(boolean handleWheel) {
1270 boolean old = wheelScrollState;
1271 wheelScrollState = handleWheel;
1272 firePropertyChange("wheelScrollingEnabled", old, handleWheel);
1273 }
1274
1275 /**
1276 * See <code>readObject</code> and <code>writeObject</code> in
1277 * <code>JComponent</code> for more
1278 * information about serialization in Swing.
1279 */
1280 private void writeObject(ObjectOutputStream s) throws IOException {
1281 s.defaultWriteObject();
1282 if (getUIClassID().equals(uiClassID)) {
1283 byte count = JComponent.getWriteObjCounter(this );
1284 JComponent.setWriteObjCounter(this , --count);
1285 if (count == 0 && ui != null) {
1286 ui.installUI(this );
1287 }
1288 }
1289 }
1290
1291 /**
1292 * Returns a string representation of this <code>JScrollPane</code>.
1293 * This method
1294 * is intended to be used only for debugging purposes, and the
1295 * content and format of the returned string may vary between
1296 * implementations. The returned string may be empty but may not
1297 * be <code>null</code>.
1298 *
1299 * @return a string representation of this <code>JScrollPane</code>.
1300 */
1301 protected String paramString() {
1302 String viewportBorderString = (viewportBorder != null ? viewportBorder
1303 .toString()
1304 : "");
1305 String viewportString = (viewport != null ? viewport.toString()
1306 : "");
1307 String verticalScrollBarPolicyString;
1308 if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_AS_NEEDED) {
1309 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_AS_NEEDED";
1310 } else if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_NEVER) {
1311 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_NEVER";
1312 } else if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
1313 verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_ALWAYS";
1314 } else
1315 verticalScrollBarPolicyString = "";
1316 String horizontalScrollBarPolicyString;
1317 if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED) {
1318 horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_AS_NEEDED";
1319 } else if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_NEVER) {
1320 horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_NEVER";
1321 } else if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) {
1322 horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_ALWAYS";
1323 } else
1324 horizontalScrollBarPolicyString = "";
1325 String horizontalScrollBarString = (horizontalScrollBar != null ? horizontalScrollBar
1326 .toString()
1327 : "");
1328 String verticalScrollBarString = (verticalScrollBar != null ? verticalScrollBar
1329 .toString()
1330 : "");
1331 String columnHeaderString = (columnHeader != null ? columnHeader
1332 .toString()
1333 : "");
1334 String rowHeaderString = (rowHeader != null ? rowHeader
1335 .toString() : "");
1336 String lowerLeftString = (lowerLeft != null ? lowerLeft
1337 .toString() : "");
1338 String lowerRightString = (lowerRight != null ? lowerRight
1339 .toString() : "");
1340 String upperLeftString = (upperLeft != null ? upperLeft
1341 .toString() : "");
1342 String upperRightString = (upperRight != null ? upperRight
1343 .toString() : "");
1344
1345 return super .paramString() + ",columnHeader="
1346 + columnHeaderString + ",horizontalScrollBar="
1347 + horizontalScrollBarString
1348 + ",horizontalScrollBarPolicy="
1349 + horizontalScrollBarPolicyString + ",lowerLeft="
1350 + lowerLeftString + ",lowerRight=" + lowerRightString
1351 + ",rowHeader=" + rowHeaderString + ",upperLeft="
1352 + upperLeftString + ",upperRight=" + upperRightString
1353 + ",verticalScrollBar=" + verticalScrollBarString
1354 + ",verticalScrollBarPolicy="
1355 + verticalScrollBarPolicyString + ",viewport="
1356 + viewportString + ",viewportBorder="
1357 + viewportBorderString;
1358 }
1359
1360 /////////////////
1361 // Accessibility support
1362 ////////////////
1363
1364 /**
1365 * Gets the AccessibleContext associated with this JScrollPane.
1366 * For scroll panes, the AccessibleContext takes the form of an
1367 * AccessibleJScrollPane.
1368 * A new AccessibleJScrollPane instance is created if necessary.
1369 *
1370 * @return an AccessibleJScrollPane that serves as the
1371 * AccessibleContext of this JScrollPane
1372 */
1373 public AccessibleContext getAccessibleContext() {
1374 if (accessibleContext == null) {
1375 accessibleContext = new AccessibleJScrollPane();
1376 }
1377 return accessibleContext;
1378 }
1379
1380 /**
1381 * This class implements accessibility support for the
1382 * <code>JScrollPane</code> class. It provides an implementation of the
1383 * Java Accessibility API appropriate to scroll pane user-interface
1384 * elements.
1385 * <p>
1386 * <strong>Warning:</strong>
1387 * Serialized objects of this class will not be compatible with
1388 * future Swing releases. The current serialization support is
1389 * appropriate for short term storage or RMI between applications running
1390 * the same version of Swing. As of 1.4, support for long term storage
1391 * of all JavaBeans<sup><font size="-2">TM</font></sup>
1392 * has been added to the <code>java.beans</code> package.
1393 * Please see {@link java.beans.XMLEncoder}.
1394 */
1395 protected class AccessibleJScrollPane extends AccessibleJComponent
1396 implements ChangeListener, PropertyChangeListener {
1397
1398 protected JViewport viewPort = null;
1399
1400 /*
1401 * Resets the viewport ChangeListener and PropertyChangeListener
1402 */
1403 public void resetViewPort() {
1404 if (viewPort != null) {
1405 viewPort.removeChangeListener(this );
1406 viewPort.removePropertyChangeListener(this );
1407 }
1408 viewPort = JScrollPane.this .getViewport();
1409 if (viewPort != null) {
1410 viewPort.addChangeListener(this );
1411 viewPort.addPropertyChangeListener(this );
1412 }
1413 }
1414
1415 /**
1416 * AccessibleJScrollPane constructor
1417 */
1418 public AccessibleJScrollPane() {
1419 super ();
1420
1421 resetViewPort();
1422
1423 // initialize the AccessibleRelationSets for the JScrollPane
1424 // and JScrollBar(s)
1425 JScrollBar scrollBar = getHorizontalScrollBar();
1426 if (scrollBar != null) {
1427 setScrollBarRelations(scrollBar);
1428 }
1429 scrollBar = getVerticalScrollBar();
1430 if (scrollBar != null) {
1431 setScrollBarRelations(scrollBar);
1432 }
1433 }
1434
1435 /**
1436 * Get the role of this object.
1437 *
1438 * @return an instance of AccessibleRole describing the role of the
1439 * object
1440 * @see AccessibleRole
1441 */
1442 public AccessibleRole getAccessibleRole() {
1443 return AccessibleRole.SCROLL_PANE;
1444 }
1445
1446 /**
1447 * Invoked when the target of the listener has changed its state.
1448 *
1449 * @param e a <code>ChangeEvent</code> object. Must not be null.
1450 *
1451 * @throws NullPointerException if the parameter is null.
1452 */
1453 public void stateChanged(ChangeEvent e) {
1454 if (e == null) {
1455 throw new NullPointerException();
1456 }
1457 firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY,
1458 Boolean.valueOf(false), Boolean.valueOf(true));
1459 }
1460
1461 /**
1462 * This method gets called when a bound property is changed.
1463 * @param e A <code>PropertyChangeEvent</code> object describing
1464 * the event source and the property that has changed. Must not be null.
1465 *
1466 * @throws NullPointerException if the parameter is null.
1467 * @since 1.5
1468 */
1469 public void propertyChange(PropertyChangeEvent e) {
1470 String propertyName = e.getPropertyName();
1471 if (propertyName == "horizontalScrollBar"
1472 || propertyName == "verticalScrollBar") {
1473
1474 if (e.getNewValue() instanceof JScrollBar) {
1475 setScrollBarRelations((JScrollBar) e.getNewValue());
1476 }
1477 }
1478 }
1479
1480 /*
1481 * Sets the CONTROLLER_FOR and CONTROLLED_BY AccessibleRelations for
1482 * the JScrollPane and JScrollBar. JScrollBar must not be null.
1483 */
1484 void setScrollBarRelations(JScrollBar scrollBar) {
1485 /*
1486 * The JScrollBar is a CONTROLLER_FOR the JScrollPane.
1487 * The JScrollPane is CONTROLLED_BY the JScrollBar.
1488 */
1489 AccessibleRelation controlledBy = new AccessibleRelation(
1490 AccessibleRelation.CONTROLLED_BY, scrollBar);
1491 AccessibleRelation controllerFor = new AccessibleRelation(
1492 AccessibleRelation.CONTROLLER_FOR, JScrollPane.this );
1493
1494 // set the relation set for the scroll bar
1495 AccessibleContext ac = scrollBar.getAccessibleContext();
1496 ac.getAccessibleRelationSet().add(controllerFor);
1497
1498 // set the relation set for the scroll pane
1499 getAccessibleRelationSet().add(controlledBy);
1500 }
1501 }
1502 }
|