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

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