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