1. /*
  2. * @(#)JScrollPane.java 1.62 01/11/29
  3. *
  4. * Copyright 2002 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.Graphics;
  14. import java.awt.Rectangle;
  15. import java.awt.Insets;
  16. import java.awt.Color;
  17. import java.awt.LayoutManager;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21. /**
  22. * A specialized container that manages a viewport, optional
  23. * vertical and horizontal scrollbars, and optional row and
  24. * column heading viewports.
  25. * <p>
  26. * <TABLE ALIGN="RIGHT" BORDER="0">
  27. * <TR>
  28. * <TD ALIGN="CENTER">
  29. * <P ALIGN="CENTER"><IMG SRC="doc-files/JScrollPane-1.gif" WIDTH="256" HEIGHT="248" ALIGN="BOTTOM" BORDER="0">
  30. * </TD>
  31. * </TR>
  32. * </TABLE>
  33. * The JViewport provides a window, or "viewport" onto a data
  34. * source -- for example, a text file. That data source is the
  35. * "scrollable client" (aka data model) displayed by the
  36. * JViewport view. A JScrollPane basically consists of JScrollBars, a JViewport,
  37. * and the wiring between them, as shown in the diagram at right.
  38. * <p>
  39. * In addition to the scroll bars and viewport, a JScrollPane can have a
  40. * column header and a row header. Each of these is a JViewport object that
  41. * you specify with <code>setRowHeaderView</code>, and <code>setColumnHeaderView</code>.
  42. * The column header viewport automatically scrolls left and right, tracking
  43. * the left-right scrolling of the main viewport. (It never scrolls vertically,
  44. * however.) The row header acts in a similar fashion.
  45. * <p>
  46. * By default, the corners are empty. You can put a component into a corner using
  47. * <code>setCorner</code>, in case you there is some function or decoration you
  48. * would like to add to the scroll pane. The size of corner components is
  49. * entirely determined by the size of the headers and scroll bars that surround them.
  50. * <p>
  51. * To add a border around the main viewport, you can use <code>setViewportBorder</code>.
  52. * (Of course, you can also add a border around the whole scroll pane using
  53. * <code>setBorder</code>.)
  54. * <p>
  55. * For the keyboard keys used by this component in the standard Look and
  56. * Feel (L&F) renditions, see the
  57. * <a href="doc-files/Key-Index.html#JScrollPane">JScrollPane</a>
  58. * key assignments.
  59. * <p>
  60. * <strong>Warning:</strong>
  61. * Serialized objects of this class will not be compatible with
  62. * future Swing releases. The current serialization support is appropriate
  63. * for short term storage or RMI between applications running the same
  64. * version of Swing. A future release of Swing will provide support for
  65. * long term persistence.
  66. *
  67. * @see JScrollBar
  68. * @see JViewport
  69. * @see #setViewportView
  70. * @see #setRowHeaderView
  71. * @see #setColumnHeaderView
  72. * @see #setCorner
  73. * @see #setViewportBorder
  74. *
  75. * @beaninfo
  76. * attribute: isContainer true
  77. * attribute: containerDelegate getViewport
  78. * description: A specialized container that manages a viewport, optional scrollbars and headers
  79. *
  80. * @version 1.62 11/29/01
  81. * @author Hans Muller
  82. */
  83. public class JScrollPane extends JComponent implements ScrollPaneConstants, Accessible
  84. {
  85. private Border viewportBorder;
  86. /**
  87. * @see #getUIClassID
  88. * @see #readObject
  89. */
  90. private static final String uiClassID = "ScrollPaneUI";
  91. /**
  92. * The display policy for the vertical scrollbar.
  93. * The default is JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED.
  94. * @see #setVerticalScrollBarPolicy
  95. */
  96. protected int verticalScrollBarPolicy = VERTICAL_SCROLLBAR_AS_NEEDED;
  97. /**
  98. * The display policy for the horizontal scrollbar.
  99. * The default is JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED.
  100. * @see #setHorizontalScrollBarPolicy
  101. */
  102. protected int horizontalScrollBarPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED;
  103. /**
  104. * The scrollpanes viewport child. Default is an empty JViewport.
  105. * @see #setViewport
  106. */
  107. protected JViewport viewport;
  108. /**
  109. * The scrollpane's vertical scrollbar child. Default is a JScrollBar.
  110. * @see #setVerticalScrollBar
  111. */
  112. protected JScrollBar verticalScrollBar;
  113. /**
  114. * The scrollpane's horizontal scrollbar child. Default is a JScrollBar.
  115. * @see #setHorizontalScrollBar
  116. */
  117. protected JScrollBar horizontalScrollBar;
  118. /**
  119. * The row header child. Default is null.
  120. * @see #setRowHeader
  121. */
  122. protected JViewport rowHeader;
  123. /**
  124. * The column header child. Default is null.
  125. * @see #setColumnHeader
  126. */
  127. protected JViewport columnHeader;
  128. /**
  129. * The component to display in the lower left corner. Default is null.
  130. * @see #setCorner
  131. */
  132. protected Component lowerLeft;
  133. /**
  134. * The component to display in the lower right corner. Default is null.
  135. * @see #setCorner
  136. */
  137. protected Component lowerRight;
  138. /**
  139. * The component to display in the upper left corner. Default is null.
  140. * @see #setCorner
  141. */
  142. protected Component upperLeft;
  143. /**
  144. * The component to display in the upper right corner. Default is null.
  145. * @see #setCorner
  146. */
  147. protected Component upperRight;
  148. /**
  149. * Create a JScrollPane that displays the view component in a viewport
  150. * whose view position can be controlled with a pair of scrollbars.
  151. * The scrollbar policies specify when the scrollbars are displayed,
  152. * e.g. if <code>vsbPolicy</code> is VERTICAL_SCROLLBAR_AS_NEEDED</code>
  153. * then the vertical scrollbar only appears if the view doesn't fit
  154. * vertically. The available policies settings are listed at
  155. * {@link #setVerticalScrollBarPolicy} and {@link #setHorizontalScrollBarPolicy}.
  156. *
  157. * @see #setViewportView
  158. *
  159. * @param view the Component to display in the scrollpanes viewport
  160. * @param vsbPolicy an int that specifies the vertical scrollbar policy
  161. * @param hsbPolicy an int that specifies the horizontal scrollbar policy
  162. */
  163. public JScrollPane(Component view, int vsbPolicy, int hsbPolicy)
  164. {
  165. setLayout(new ScrollPaneLayout.UIResource());
  166. setVerticalScrollBarPolicy(vsbPolicy);
  167. setHorizontalScrollBarPolicy(hsbPolicy);
  168. setViewport(createViewport());
  169. setVerticalScrollBar(createVerticalScrollBar());
  170. setHorizontalScrollBar(createHorizontalScrollBar());
  171. if (view != null) {
  172. setViewportView(view);
  173. }
  174. updateUI();
  175. }
  176. /**
  177. * Create a JScrollPane that displays the contents of the specified
  178. * component, where both horizontal and vertical scrollbars appear
  179. * whenever the component's contents are larger than the view.
  180. *
  181. * @see #setViewportView
  182. * @param view the Component to display in the scrollpanes viewport
  183. */
  184. public JScrollPane(Component view) {
  185. this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
  186. }
  187. /**
  188. * Create an empty (no viewport view) JScrollPane with specified
  189. * scrollbar policies. The available policies settings are listed at
  190. * {@link #setVerticalScrollBarPolicy} and {@link #setHorizontalScrollBarPolicy}.
  191. *
  192. * @see #setViewportView
  193. *
  194. * @param vsbPolicy an int that specifies the vertical scrollbar policy
  195. * @param hsbPolicy an int that specifies the horizontal scrollbar policy
  196. */
  197. public JScrollPane(int vsbPolicy, int hsbPolicy) {
  198. this(null, vsbPolicy, hsbPolicy);
  199. }
  200. /**
  201. * Create an empty (no viewport view) JScrollPane where both horizontal and vertical
  202. * scrollbars appear when needed.
  203. */
  204. public JScrollPane() {
  205. this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
  206. }
  207. /**
  208. * Returns the L&F object that renders this component.
  209. *
  210. * @return the ScrollPaneUI object that renders this component
  211. * @see #setUI
  212. */
  213. public ScrollPaneUI getUI() {
  214. return (ScrollPaneUI)ui;
  215. }
  216. /**
  217. * Sets the ScrollPaneUI object that provides the look and feel for
  218. * this component.
  219. *
  220. * @param ui the ScrollPaneUI L&F object
  221. * @see #getUI
  222. */
  223. public void setUI(ScrollPaneUI ui) {
  224. super.setUI(ui);
  225. }
  226. /**
  227. * To be called when the default look and feel changes.
  228. * Replaces the current ScrollPaneUI object with a version
  229. * from the current default LookAndFeel.
  230. *
  231. * @see JComponent#updateUI
  232. * @see UIManager#getUI
  233. */
  234. public void updateUI() {
  235. setUI((ScrollPaneUI)UIManager.getUI(this));
  236. }
  237. /**
  238. * Returns the key used to look up the ScrollPaneUI class that provides
  239. * the look and feel for JScrollPane.
  240. *
  241. * @return "ScrollPaneUI"
  242. * @see JComponent#getUIClassID
  243. * @see UIDefaults#getUI
  244. *
  245. * @beaninfo
  246. * hidden: true
  247. */
  248. public String getUIClassID() {
  249. return uiClassID;
  250. }
  251. /**
  252. * Sets the layout manager for this JScrollPane. This method overrides
  253. * setLayout in java.awt.Container to ensure that only LayoutManagers which
  254. * are subclasses of ScrollPaneLayout can be used in a JScrollPane.
  255. *
  256. * @param layout the specified layout manager
  257. * @exception ClassCastException if layout is not a ScrollPaneLayout
  258. * @see java.awt.Container#getLayout
  259. * @see java.awt.Container#setLayout
  260. *
  261. * @beaninfo
  262. * hidden: true
  263. */
  264. public void setLayout(LayoutManager layout) {
  265. if ((layout == null) || (layout instanceof ScrollPaneLayout)) {
  266. super.setLayout(layout);
  267. }
  268. else {
  269. String s = "layout of JScrollPane must be a ScrollPaneLayout";
  270. throw new ClassCastException(s);
  271. }
  272. }
  273. /**
  274. * Returns true if this component paints every pixel
  275. * in its range. (In other words, it does not have a transparent
  276. * background or foreground.)
  277. *
  278. * @return The value of the opaque property
  279. * @see JComponent#isOpaque
  280. */
  281. public boolean isOpaque() {
  282. JViewport viewport;
  283. Component view;
  284. if( (viewport = getViewport()) != null &&
  285. ((view = viewport.getView()) != null) &&
  286. ((view instanceof JComponent) && ((JComponent)view).isOpaque())) {
  287. if(((JComponent)view).getWidth() >= viewport.getWidth() &&
  288. ((JComponent)view).getHeight() >= viewport.getHeight())
  289. return true;
  290. }
  291. return false;
  292. }
  293. /**
  294. * Calls to revalidate() on any descendant of this JScrollPane, e.g.
  295. * the viewports view, will cause a request to be queued that
  296. * will validate the JScrollPane and all its descendants.
  297. *
  298. * @return true
  299. * @see JComponent#revalidate
  300. *
  301. * @beaninfo
  302. * hidden: true
  303. */
  304. public boolean isValidateRoot() {
  305. return true;
  306. }
  307. /**
  308. * Returns the vertical scroll bar policy value.
  309. * @return the vertical scrollbar policy
  310. * @see #setVerticalScrollBarPolicy
  311. */
  312. public int getVerticalScrollBarPolicy() {
  313. return verticalScrollBarPolicy;
  314. }
  315. /**
  316. * Determines when the vertical scrollbar appears in the scrollpane.
  317. * Legal values are:
  318. * <ul>
  319. * <li>JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
  320. * <li>JScrollPane.VERTICAL_SCROLLBAR_NEVER
  321. * <li>JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
  322. * </ul>
  323. *
  324. * @see #getVerticalScrollBarPolicy
  325. *
  326. * @beaninfo
  327. * preferred: true
  328. * bound: true
  329. * description: The scrollpane vertical scrollbar policy
  330. * enum: VERTICAL_SCROLLBAR_AS_NEEDED JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
  331. * VERTICAL_SCROLLBAR_NEVER JScrollPane.VERTICAL_SCROLLBAR_NEVER
  332. * VERTICAL_SCROLLBAR_ALWAYS JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
  333. */
  334. public void setVerticalScrollBarPolicy(int policy) {
  335. switch (policy) {
  336. case VERTICAL_SCROLLBAR_AS_NEEDED:
  337. case VERTICAL_SCROLLBAR_NEVER:
  338. case VERTICAL_SCROLLBAR_ALWAYS:
  339. break;
  340. default:
  341. throw new IllegalArgumentException("invalid verticalScrollBarPolicy");
  342. }
  343. int old = verticalScrollBarPolicy;
  344. verticalScrollBarPolicy = policy;
  345. firePropertyChange("verticalScrollBarPolicy", old, policy);
  346. }
  347. /**
  348. * Returns the horizontal scroll bar policy value.
  349. * @return the horizontal scrollbar policy.
  350. * @see #setHorizontalScrollBarPolicy
  351. */
  352. public int getHorizontalScrollBarPolicy() {
  353. return horizontalScrollBarPolicy;
  354. }
  355. /**
  356. * Determines when the horizontal scrollbar appears in the scrollpane.
  357. * The options are:<ul>
  358. * <li>JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
  359. * <li>JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
  360. * <li>JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS
  361. * </ul>
  362. *
  363. * @see #getHorizontalScrollBarPolicy
  364. *
  365. * @beaninfo
  366. * preferred: true
  367. * bound: true
  368. * description: The scrollpane scrollbar policy
  369. * enum: HORIZONTAL_SCROLLBAR_AS_NEEDED JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
  370. * HORIZONTAL_SCROLLBAR_NEVER JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
  371. * HORIZONTAL_SCROLLBAR_ALWAYS JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS
  372. */
  373. public void setHorizontalScrollBarPolicy(int policy) {
  374. switch (policy) {
  375. case HORIZONTAL_SCROLLBAR_AS_NEEDED:
  376. case HORIZONTAL_SCROLLBAR_NEVER:
  377. case HORIZONTAL_SCROLLBAR_ALWAYS:
  378. break;
  379. default:
  380. throw new IllegalArgumentException("invalid horizontalScrollBarPolicy");
  381. }
  382. int old = horizontalScrollBarPolicy;
  383. horizontalScrollBarPolicy = policy;
  384. firePropertyChange("horizontalScrollBarPolicy", old, policy);
  385. }
  386. /**
  387. * Returns the value of the viewportBorder property.
  388. *
  389. * @return the Border object that surrounds the viewport
  390. * @see #setViewportBorder
  391. */
  392. public Border getViewportBorder() {
  393. return viewportBorder;
  394. }
  395. /**
  396. * Add a border around the viewport. Note that the border isn't
  397. * set on the viewport directly, JViewport doesn't support the
  398. * JComponent border property. Similarly setting the JScrollPanes
  399. * viewport doesn't effect the viewportBorder property.
  400. * <p>
  401. * The default value of this property is computed by the look
  402. * and feel implementation.
  403. *
  404. * @see #getViewportBorder
  405. * @see #setViewport
  406. *
  407. * @beaninfo
  408. * preferred: true
  409. * bound: true
  410. * description: The border around the viewport.
  411. */
  412. public void setViewportBorder(Border viewportBorder) {
  413. Border oldValue = this.viewportBorder;
  414. this.viewportBorder = viewportBorder;
  415. firePropertyChange("viewportBorder", oldValue, viewportBorder);
  416. }
  417. /**
  418. * Returns the bounds of the viewport border.
  419. *
  420. * @return a Rectangle object specifying the viewport border
  421. */
  422. public Rectangle getViewportBorderBounds()
  423. {
  424. Rectangle borderR = new Rectangle(getSize());
  425. Insets insets = getInsets();
  426. borderR.x = insets.left;
  427. borderR.y = insets.top;
  428. borderR.width -= insets.left + insets.right;
  429. borderR.height -= insets.top + insets.bottom;
  430. /* If there's a visible column header remove the space it
  431. * needs from the top of borderR.
  432. */
  433. JViewport colHead = getColumnHeader();
  434. if ((colHead != null) && (colHead.isVisible())) {
  435. int colHeadHeight = colHead.getHeight();
  436. borderR.y += colHeadHeight;
  437. borderR.height -= colHeadHeight;
  438. }
  439. /* If there's a visible row header remove the space it needs
  440. * from the left of borderR.
  441. */
  442. JViewport rowHead = getRowHeader();
  443. if ((rowHead != null) && (rowHead.isVisible())) {
  444. int rowHeadWidth = rowHead.getWidth();
  445. borderR.x += rowHeadWidth;
  446. borderR.width -= rowHeadWidth;
  447. }
  448. /* If there's a visible vertical scrollbar remove the space it needs
  449. * from the width of borderR.
  450. */
  451. JScrollBar vsb = getVerticalScrollBar();
  452. if ((vsb != null) && (vsb.isVisible())) {
  453. borderR.width -= vsb.getWidth();
  454. }
  455. /* If there's a visible horizontal scrollbar remove the space it needs
  456. * from the height of borderR.
  457. */
  458. JScrollBar hsb = getHorizontalScrollBar();
  459. if ((hsb != null) && (hsb.isVisible())) {
  460. borderR.height -= hsb.getHeight();
  461. }
  462. return borderR;
  463. }
  464. /**
  465. * By default JScrollPane creates scrollbars that are instances
  466. * of this class. Scrollbar overrides the getUnitIncrement
  467. * and getBlockIncrement methods so that, if the viewports view is
  468. * a Scrollable, the view is asked to compute these values. Unless
  469. * the unit/block increment have been explicitly set.
  470. * <p>
  471. * <strong>Warning:</strong>
  472. * Serialized objects of this class will not be compatible with
  473. * future Swing releases. The current serialization support is appropriate
  474. * for short term storage or RMI between applications running the same
  475. * version of Swing. A future release of Swing will provide support for
  476. * long term persistence.
  477. *
  478. * @see Scrollable
  479. * @see JScrollPane#createVerticalScrollBar
  480. * @see JScrollPane#createHorizontalScrollBar
  481. */
  482. protected class ScrollBar extends JScrollBar implements UIResource
  483. {
  484. /**
  485. * Set to true when the unit increment has been explicitly set.
  486. * If this is false the viewports view is obtained and if it
  487. * is an instance of Scrollable the unit increment from it is used.
  488. */
  489. private boolean unitIncrementSet;
  490. /**
  491. * Set to true when the block increment has been explicitly set.
  492. * If this is false the viewports view is obtained and if it
  493. * is an instance of Scrollable the block increment from it is used.
  494. */
  495. private boolean blockIncrementSet;
  496. /**
  497. * Create a scrollbar with the specified orientation, where the options
  498. * are:<ul>
  499. * <li>JScrollPane.VERTICAL_SCROLLBAR
  500. * <li>JScrollPane.HORIZONTAL_SCROLLBAR
  501. * </ul>
  502. *
  503. * @param orientation an int specifying the orientation
  504. */
  505. public ScrollBar(int orientation) {
  506. super(orientation);
  507. }
  508. /**
  509. * Messages super to set the value, and resets the
  510. * <code>unitIncrementSet</code> instance variable to true.
  511. */
  512. public void setUnitIncrement(int unitIncrement) {
  513. unitIncrementSet = true;
  514. super.setUnitIncrement(unitIncrement);
  515. }
  516. /**
  517. * If the viewports view is a Scrollable then ask the view
  518. * to compute the unit increment. Otherwise return
  519. * super.getUnitIncrement().
  520. *
  521. * @see Scrollable#getScrollableUnitIncrement
  522. */
  523. public int getUnitIncrement(int direction) {
  524. JViewport vp = getViewport();
  525. if (!unitIncrementSet && (vp != null) &&
  526. (vp.getView() instanceof Scrollable)) {
  527. Scrollable view = (Scrollable)(vp.getView());
  528. Rectangle vr = vp.getViewRect();
  529. return view.getScrollableUnitIncrement(vr, getOrientation(), direction);
  530. }
  531. else {
  532. return super.getUnitIncrement(direction);
  533. }
  534. }
  535. /**
  536. * Messages super to set the value, and resets the
  537. * <code>blockIncrementSet</code> instance variable to true.
  538. */
  539. public void setBlockIncrement(int blockIncrement) {
  540. blockIncrementSet = true;
  541. super.setBlockIncrement(blockIncrement);
  542. }
  543. /**
  544. * If the viewports view is a Scrollable then ask the
  545. * view to compute the block increment. Otherwise
  546. * the blockIncrement equals the viewports width
  547. * or height. If there's no viewport reuurn
  548. * super.getBlockIncrement().
  549. *
  550. * @see Scrollable#getScrollableBlockIncrement
  551. */
  552. public int getBlockIncrement(int direction) {
  553. JViewport vp = getViewport();
  554. if (blockIncrementSet || vp == null) {
  555. return super.getBlockIncrement(direction);
  556. }
  557. else if (vp.getView() instanceof Scrollable) {
  558. Scrollable view = (Scrollable)(vp.getView());
  559. Rectangle vr = vp.getViewRect();
  560. return view.getScrollableBlockIncrement(vr, getOrientation(), direction);
  561. }
  562. else if (getOrientation() == VERTICAL) {
  563. return vp.getExtentSize().height;
  564. }
  565. else {
  566. return vp.getExtentSize().width;
  567. }
  568. }
  569. }
  570. /**
  571. * Used by ScrollPaneUI implementations to create the horizontal
  572. * scrollbar. Returns a JScrollPane.ScrollBar by default. Subclasses
  573. * may override this method to force ScrollPaneUI implementations to
  574. * use a JScrollBar subclass.
  575. *
  576. * @return a JScrollBar with a horizontal orientation
  577. * @see JScrollBar
  578. */
  579. public JScrollBar createHorizontalScrollBar() {
  580. return new ScrollBar(JScrollBar.HORIZONTAL);
  581. }
  582. /**
  583. * Returns the horizontal scroll bar.
  584. * @return the scrollbar that controls the viewports horizontal view position
  585. * @see #setHorizontalScrollBar
  586. */
  587. public JScrollBar getHorizontalScrollBar() {
  588. return horizontalScrollBar;
  589. }
  590. /**
  591. * Add the scrollbar that controls the viewports horizontal view position
  592. * to the scrollpane. This is usually unneccessary, JScrollPane creates
  593. * horizontal and vertical scrollbars by default.
  594. *
  595. * @see #createHorizontalScrollBar
  596. * @see #getHorizontalScrollBar
  597. *
  598. * @beaninfo
  599. * expert: true
  600. * bound: true
  601. * description: The horizontal scrollbar.
  602. */
  603. public void setHorizontalScrollBar(JScrollBar horizontalScrollBar) {
  604. JScrollBar old = getHorizontalScrollBar();
  605. this.horizontalScrollBar = horizontalScrollBar;
  606. add(horizontalScrollBar, HORIZONTAL_SCROLLBAR);
  607. firePropertyChange("horizontalScrollBar", old, horizontalScrollBar);
  608. }
  609. /**
  610. * Used by ScrollPaneUI implementations to create the vertical
  611. * scrollbar. Returns a JScrollPane.ScrollBar by default. Subclasses
  612. * may override this method to force ScrollPaneUI implementations to
  613. * use a JScrollBar subclass.
  614. *
  615. * @return a JScrollBar with a vertical orientation
  616. * @see JScrollBar
  617. */
  618. public JScrollBar createVerticalScrollBar() {
  619. return new ScrollBar(JScrollBar.VERTICAL);
  620. }
  621. /**
  622. * Returns the vertical scroll bar.
  623. * @return the scrollbar that controls the viewports vertical view position
  624. * @see #setVerticalScrollBar
  625. */
  626. public JScrollBar getVerticalScrollBar() {
  627. return verticalScrollBar;
  628. }
  629. /**
  630. * Add the scrollbar that controls the viewports vertical view position
  631. * to the scrollpane. This is usually unneccessary, JScrollPane creates
  632. * vertical and vertical scrollbars by default.
  633. *
  634. * @see #createVerticalScrollBar
  635. * @see #getVerticalScrollBar
  636. *
  637. * @beaninfo
  638. * expert: true
  639. * bound: true
  640. * description: The vertical scrollbar.
  641. */
  642. public void setVerticalScrollBar(JScrollBar verticalScrollBar) {
  643. JScrollBar old = getVerticalScrollBar();
  644. this.verticalScrollBar = verticalScrollBar;
  645. add(verticalScrollBar, VERTICAL_SCROLLBAR);
  646. firePropertyChange("verticalScrollBar", old, verticalScrollBar);
  647. }
  648. /**
  649. * Returns a new JViewport by default. Used to create the
  650. * viewport (as needed) in <code>setViewportView</code>,
  651. * <code>setRowHeaderView</code>, and <code>setColumnHeaderView</code>.
  652. * Subclasses may override this method to return a subclass of JViewport.
  653. *
  654. * @return a JViewport
  655. */
  656. protected JViewport createViewport() {
  657. return new JViewport();
  658. }
  659. /**
  660. * Returns the current JViewport.
  661. *
  662. * @see #setViewport
  663. * @return the JViewport currently in use
  664. */
  665. public JViewport getViewport() {
  666. return viewport;
  667. }
  668. /**
  669. * Remove the old viewport (if there is one), force the
  670. * viewPosition of the new viewport to be in the +x,+y quadrant,
  671. * sync up the row and column headers (if there are any) with the
  672. * new viewport, and finally sync the scrollbars and
  673. * headers with the new viewport.
  674. * <p>
  675. * Most applications will find it more convenient to use setViewportView
  676. * to add a viewport and a view to the scrollpane.
  677. *
  678. * @see #createViewport
  679. * @see #getViewport
  680. * @see #setViewportView
  681. *
  682. * @beaninfo
  683. * expert: true
  684. * bound: true
  685. * attribute: visualUpdate true
  686. * description: The viewport child for this scrollpane
  687. *
  688. */
  689. public void setViewport(JViewport viewport) {
  690. JViewport old = getViewport();
  691. this.viewport = viewport;
  692. if (viewport != null) {
  693. add(viewport, VIEWPORT);
  694. }
  695. else if (old != null) {
  696. remove(old);
  697. }
  698. firePropertyChange("viewport", old, viewport);
  699. if (accessibleContext != null) {
  700. ((AccessibleJScrollPane)accessibleContext).resetViewPort();
  701. }
  702. revalidate();
  703. repaint();
  704. }
  705. /**
  706. * Creates a viewport if neccessary and then sets its view. Applications
  707. * that don't provide the view directly to the JScrollPane constructor
  708. * should use this method to specify the scrollable child that's going
  709. * to be displayed in the scrollpane, e.g.:
  710. * <pre>
  711. * JScrollPane scrollpane = new JScrollPane();
  712. * scrollpane.setViewportView(myBigComponentToScroll);
  713. * </pre>
  714. * Applications should not add children directly to the scrollpane.
  715. *
  716. * @param view the Component to add to the viewport
  717. * @see #setViewport
  718. * @see JViewport#setView
  719. */
  720. public void setViewportView(Component view) {
  721. if (getViewport() == null) {
  722. setViewport(createViewport());
  723. }
  724. getViewport().setView(view);
  725. }
  726. /**
  727. * Returns the row header.
  728. * @return the JViewport for the row header
  729. * @see #setRowHeader
  730. */
  731. public JViewport getRowHeader() {
  732. return rowHeader;
  733. }
  734. /**
  735. * If an old rowHeader exists, remove it. If the new rowHeader
  736. * isn't null, sync the y coordinate of the its viewPosition with
  737. * the viewport (if there is one) and then add it to the ScrollPane.
  738. * <p>
  739. * Most applications will find it more convenient to use setRowHeaderView
  740. * to add a row header component and its viewport to the scrollpane.
  741. *
  742. * @see #getRowHeader
  743. * @see #setRowHeaderView
  744. *
  745. * @beaninfo
  746. * bound: true
  747. * expert: true
  748. * description: The row header child for this scrollpane
  749. */
  750. public void setRowHeader(JViewport rowHeader) {
  751. JViewport old = getRowHeader();
  752. this.rowHeader = rowHeader;
  753. if (rowHeader != null) {
  754. add(rowHeader, ROW_HEADER);
  755. }
  756. else if (old != null) {
  757. remove(old);
  758. }
  759. firePropertyChange("rowHeader", old, rowHeader);
  760. }
  761. /**
  762. * Creates a row-header viewport if neccessary, sets
  763. * its view and then adds the row-header viewport
  764. * to the scrollpane. For example:
  765. * <pre>
  766. * JScrollPane scrollpane = new JScrollPane();
  767. * scrollpane.setViewportView(myBigComponentToScroll);
  768. * scrollpane.setRowHeaderView(myBigComponentsRowHeader);
  769. * </pre>
  770. *
  771. * @see #setRowHeader
  772. * @see JViewport#setView
  773. * @param view the Component to display as the row header
  774. */
  775. public void setRowHeaderView(Component view) {
  776. if (getRowHeader() == null) {
  777. setRowHeader(createViewport());
  778. }
  779. getRowHeader().setView(view);
  780. }
  781. /**
  782. * Returns the column header.
  783. * @return a JViewport object for the column header
  784. * @see #setColumnHeader
  785. */
  786. public JViewport getColumnHeader() {
  787. return columnHeader;
  788. }
  789. /**
  790. * If an old columnHeader exists, remove it. If the new columnHeader
  791. * isn't null, sync the x coordinate of the its viewPosition with
  792. * the viewport (if there is one) and then add it to the ScrollPane.
  793. * <p>
  794. * Most applications will find it more convenient to use setRowHeaderView
  795. * to add a row header component and its viewport to the scrollpane.
  796. *
  797. * @see #getColumnHeader
  798. * @see #setColumnHeaderView
  799. *
  800. * @beaninfo
  801. * bound: true
  802. * description: The column header child for this scrollpane
  803. * attribute: visualUpdate true
  804. */
  805. public void setColumnHeader(JViewport columnHeader) {
  806. JViewport old = getColumnHeader();
  807. this.columnHeader = columnHeader;
  808. if (columnHeader != null) {
  809. add(columnHeader, COLUMN_HEADER);
  810. }
  811. else if (old != null) {
  812. remove(columnHeader);
  813. }
  814. firePropertyChange("columnHeader", old, columnHeader);
  815. revalidate();
  816. repaint();
  817. }
  818. /**
  819. * Creates a column-header viewport if neccessary, sets
  820. * its view and then adds the column-header viewport
  821. * to the scrollpane. For example:
  822. * <pre>
  823. * JScrollPane scrollpane = new JScrollPane();
  824. * scrollpane.setViewportView(myBigComponentToScroll);
  825. * scrollpane.setColumnHeaderView(myBigComponentsColumnHeader);
  826. * </pre>
  827. *
  828. * @see #setColumnHeader
  829. * @see JViewport#setView
  830. *
  831. * @param view the Component to display as the column header
  832. */
  833. public void setColumnHeaderView(Component view) {
  834. if (getColumnHeader() == null) {
  835. setColumnHeader(createViewport());
  836. }
  837. getColumnHeader().setView(view);
  838. }
  839. /**
  840. * Returns the component at the specified corner. The
  841. * <code>key</code> value specifying the corner is one of:
  842. * <ul>
  843. * <li>JScrollPane.LOWER_LEFT_CORNER
  844. * <li>JScrollPane.LOWER_RIGHT_CORNER
  845. * <li>JScrollPane.UPPER_LEFT_CORNER
  846. * <li>JScrollPane.UPPER_RIGHT_CORNER
  847. * </ul>
  848. *
  849. * @see #setCorner
  850. * @return the Component at the specified corner
  851. */
  852. public Component getCorner(String key) {
  853. if (key.equals(LOWER_LEFT_CORNER)) {
  854. return lowerLeft;
  855. }
  856. else if (key.equals(LOWER_RIGHT_CORNER)) {
  857. return lowerRight;
  858. }
  859. else if (key.equals(UPPER_LEFT_CORNER)) {
  860. return upperLeft;
  861. }
  862. else if (key.equals(UPPER_RIGHT_CORNER)) {
  863. return upperRight;
  864. }
  865. else {
  866. return null;
  867. }
  868. }
  869. /**
  870. * Adds a child that will appear in one of the scroll panes
  871. * corners, if there's room. For example with both scrollbars
  872. * showing (on the right and bottom edges of the scrollpane)
  873. * the lower left corner component will be shown in the space
  874. * between ends of the two scrollbars. Legal values for
  875. * the <b>key</b> are:
  876. * <ul>
  877. * <li>JScrollPane.LOWER_LEFT_CORNER
  878. * <li>JScrollPane.LOWER_RIGHT_CORNER
  879. * <li>JScrollPane.UPPER_LEFT_CORNER
  880. * <li>JScrollPane.UPPER_RIGHT_CORNER
  881. * </ul>
  882. * <p>
  883. * Although "corner" isn't doesn't match any beans property
  884. * signature, PropertyChange events are generated with the
  885. * property name set to the corner key.
  886. *
  887. * @param key identifies which corner the component will appear in
  888. * @param corner any component
  889. */
  890. public void setCorner(String key, Component corner)
  891. {
  892. Component old;
  893. if (key.equals(LOWER_LEFT_CORNER)) {
  894. old = lowerLeft;
  895. lowerLeft = corner;
  896. }
  897. else if (key.equals(LOWER_RIGHT_CORNER)) {
  898. old = lowerRight;
  899. lowerRight = corner;
  900. }
  901. else if (key.equals(UPPER_LEFT_CORNER)) {
  902. old = upperLeft;
  903. upperLeft = corner;
  904. }
  905. else if (key.equals(UPPER_RIGHT_CORNER)) {
  906. old = upperRight;
  907. upperRight = corner;
  908. }
  909. else {
  910. throw new IllegalArgumentException("invalid corner key");
  911. }
  912. add(corner, key);
  913. firePropertyChange(key, old, corner);
  914. }
  915. /**
  916. * See readObject() and writeObject() in JComponent for more
  917. * information about serialization in Swing.
  918. */
  919. private void writeObject(ObjectOutputStream s) throws IOException {
  920. s.defaultWriteObject();
  921. if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  922. ui.installUI(this);
  923. }
  924. }
  925. /**
  926. * Returns a string representation of this JScrollPane. This method
  927. * is intended to be used only for debugging purposes, and the
  928. * content and format of the returned string may vary between
  929. * implementations. The returned string may be empty but may not
  930. * be <code>null</code>.
  931. *
  932. * @return a string representation of this JScrollPane.
  933. */
  934. protected String paramString() {
  935. String viewportBorderString = (viewportBorder != null ?
  936. viewportBorder.toString() : "");
  937. String viewportString = (viewport != null ?
  938. viewport.toString() : "");
  939. String verticalScrollBarPolicyString;
  940. if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_AS_NEEDED) {
  941. verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_AS_NEEDED";
  942. } else if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_NEVER) {
  943. verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_NEVER";
  944. } else if (verticalScrollBarPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
  945. verticalScrollBarPolicyString = "VERTICAL_SCROLLBAR_ALWAYS";
  946. } else verticalScrollBarPolicyString = "";
  947. String horizontalScrollBarPolicyString;
  948. if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED) {
  949. horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_AS_NEEDED";
  950. } else if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_NEVER) {
  951. horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_NEVER";
  952. } else if (horizontalScrollBarPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) {
  953. horizontalScrollBarPolicyString = "HORIZONTAL_SCROLLBAR_ALWAYS";
  954. } else horizontalScrollBarPolicyString = "";
  955. String horizontalScrollBarString = (horizontalScrollBar != null ?
  956. horizontalScrollBar.toString()
  957. : "");
  958. String verticalScrollBarString = (verticalScrollBar != null ?
  959. verticalScrollBar.toString() : "");
  960. String columnHeaderString = (columnHeader != null ?
  961. columnHeader.toString() : "");
  962. String rowHeaderString = (rowHeader != null ?
  963. rowHeader.toString() : "");
  964. String lowerLeftString = (lowerLeft != null ?
  965. lowerLeft.toString() : "");
  966. String lowerRightString = (lowerRight != null ?
  967. lowerRight.toString() : "");
  968. String upperLeftString = (upperLeft != null ?
  969. upperLeft.toString() : "");
  970. String upperRightString = (upperRight != null ?
  971. upperRight.toString() : "");
  972. return super.paramString() +
  973. ",columnHeader=" + columnHeaderString +
  974. ",horizontalScrollBar=" + horizontalScrollBarString +
  975. ",horizontalScrollBarPolicy=" + horizontalScrollBarPolicyString +
  976. ",lowerLeft=" + lowerLeftString +
  977. ",lowerRight=" + lowerRightString +
  978. ",rowHeader=" + rowHeaderString +
  979. ",upperLeft=" + upperLeftString +
  980. ",upperRight=" + upperRightString +
  981. ",verticalScrollBar=" + verticalScrollBarString +
  982. ",verticalScrollBarPolicy=" + verticalScrollBarPolicyString +
  983. ",viewport=" + viewportString +
  984. ",viewportBorder=" + viewportBorderString;
  985. }
  986. /////////////////
  987. // Accessibility support
  988. ////////////////
  989. /**
  990. * Get the AccessibleContext associated with this JComponent
  991. *
  992. * @return the AccessibleContext of this JComponent
  993. */
  994. public AccessibleContext getAccessibleContext() {
  995. if (accessibleContext == null) {
  996. accessibleContext = new AccessibleJScrollPane();
  997. }
  998. return accessibleContext;
  999. }
  1000. /**
  1001. * The class used to obtain the accessible role for this object.
  1002. * <p>
  1003. * <strong>Warning:</strong>
  1004. * Serialized objects of this class will not be compatible with
  1005. * future Swing releases. The current serialization support is appropriate
  1006. * for short term storage or RMI between applications running the same
  1007. * version of Swing. A future release of Swing will provide support for
  1008. * long term persistence.
  1009. */
  1010. protected class AccessibleJScrollPane extends AccessibleJComponent
  1011. implements ChangeListener {
  1012. protected JViewport viewPort = null;
  1013. public void resetViewPort() {
  1014. viewPort.removeChangeListener(this);
  1015. viewPort = JScrollPane.this.getViewport();
  1016. viewPort.addChangeListener(this);
  1017. }
  1018. /**
  1019. * Constructor to set up listener on viewport.
  1020. */
  1021. public AccessibleJScrollPane() {
  1022. super();
  1023. if (viewPort == null) {
  1024. viewPort = JScrollPane.this.getViewport();
  1025. }
  1026. viewPort.addChangeListener(this);
  1027. }
  1028. /**
  1029. * Get the role of this object.
  1030. *
  1031. * @return an instance of AccessibleRole describing the role of the
  1032. * object
  1033. * @see AccessibleRole
  1034. */
  1035. public AccessibleRole getAccessibleRole() {
  1036. return AccessibleRole.SCROLL_PANE;
  1037. }
  1038. /**
  1039. * Supports the change listener interface and fires property change
  1040. */
  1041. public void stateChanged(ChangeEvent e) {
  1042. AccessibleContext ac = ((Accessible)JScrollPane.this).getAccessibleContext();
  1043. if (ac != null) {
  1044. ac.firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, new Boolean(false), new Boolean(true));
  1045. }
  1046. }
  1047. }
  1048. }