Home » openjdk-7 » javax » swing » [javadoc | source]

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

Home » openjdk-7 » javax » swing » [javadoc | source]