jdk/src/share/classes/javax/swing/JSplitPane.java
changeset 2 90ce3da70b43
child 438 2ae294e4518c
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1997-2007 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 
       
    27 
       
    28 package javax.swing;
       
    29 
       
    30 
       
    31 
       
    32 import java.beans.ConstructorProperties;
       
    33 import javax.swing.plaf.*;
       
    34 import javax.accessibility.*;
       
    35 
       
    36 import java.awt.*;
       
    37 
       
    38 import java.io.ObjectOutputStream;
       
    39 import java.io.ObjectInputStream;
       
    40 import java.io.IOException;
       
    41 
       
    42 
       
    43 
       
    44 /**
       
    45  * <code>JSplitPane</code> is used to divide two (and only two)
       
    46  * <code>Component</code>s. The two <code>Component</code>s
       
    47  * are graphically divided based on the look and feel
       
    48  * implementation, and the two <code>Component</code>s can then be
       
    49  * interactively resized by the user.
       
    50  * Information on using <code>JSplitPane</code> is in
       
    51  * <a
       
    52  href="http://java.sun.com/docs/books/tutorial/uiswing/components/splitpane.html">How to Use Split Panes</a> in
       
    53  * <em>The Java Tutorial</em>.
       
    54  * <p>
       
    55  * The two <code>Component</code>s in a split pane can be aligned
       
    56  * left to right using
       
    57  * <code>JSplitPane.HORIZONTAL_SPLIT</code>, or top to bottom using
       
    58  * <code>JSplitPane.VERTICAL_SPLIT</code>.
       
    59  * The preferred way to change the size of the <code>Component</code>s
       
    60  * is to invoke
       
    61  * <code>setDividerLocation</code> where <code>location</code> is either
       
    62  * the new x or y position, depending on the orientation of the
       
    63  * <code>JSplitPane</code>.
       
    64  * <p>
       
    65  * To resize the <code>Component</code>s to their preferred sizes invoke
       
    66  * <code>resetToPreferredSizes</code>.
       
    67  * <p>
       
    68  * When the user is resizing the <code>Component</code>s the minimum
       
    69  * size of the <code>Components</code> is used to determine the
       
    70  * maximum/minimum position the <code>Component</code>s
       
    71  * can be set to. If the minimum size of the two
       
    72  * components is greater than the size of the split pane the divider
       
    73  * will not allow you to resize it. To alter the minimum size of a
       
    74  * <code>JComponent</code>, see {@link JComponent#setMinimumSize}.
       
    75  * <p>
       
    76  * When the user resizes the split pane the new space is distributed between
       
    77  * the two components based on the <code>resizeWeight</code> property.
       
    78  * A value of 0,
       
    79  * the default, indicates the right/bottom component gets all the space,
       
    80  * where as a value of 1 indicates the left/top component gets all the space.
       
    81  * <p>
       
    82  * <strong>Warning:</strong> Swing is not thread safe. For more
       
    83  * information see <a
       
    84  * href="package-summary.html#threading">Swing's Threading
       
    85  * Policy</a>.
       
    86  * <p>
       
    87  * <strong>Warning:</strong>
       
    88  * Serialized objects of this class will not be compatible with
       
    89  * future Swing releases. The current serialization support is
       
    90  * appropriate for short term storage or RMI between applications running
       
    91  * the same version of Swing.  As of 1.4, support for long term storage
       
    92  * of all JavaBeans<sup><font size="-2">TM</font></sup>
       
    93  * has been added to the <code>java.beans</code> package.
       
    94  * Please see {@link java.beans.XMLEncoder}.
       
    95  *
       
    96  * @see #setDividerLocation
       
    97  * @see #resetToPreferredSizes
       
    98  *
       
    99  * @author Scott Violet
       
   100  */
       
   101 public class JSplitPane extends JComponent implements Accessible
       
   102 {
       
   103     /**
       
   104      * @see #getUIClassID
       
   105      * @see #readObject
       
   106      */
       
   107     private static final String uiClassID = "SplitPaneUI";
       
   108 
       
   109     /**
       
   110      * Vertical split indicates the <code>Component</code>s are
       
   111      * split along the y axis.  For example the two
       
   112      * <code>Component</code>s will be split one on top of the other.
       
   113      */
       
   114     public final static int VERTICAL_SPLIT = 0;
       
   115 
       
   116     /**
       
   117      * Horizontal split indicates the <code>Component</code>s are
       
   118      * split along the x axis.  For example the two
       
   119      * <code>Component</code>s will be split one to the left of the
       
   120      * other.
       
   121      */
       
   122     public final static int HORIZONTAL_SPLIT = 1;
       
   123 
       
   124     /**
       
   125      * Used to add a <code>Component</code> to the left of the other
       
   126      * <code>Component</code>.
       
   127      */
       
   128     public final static String LEFT = "left";
       
   129 
       
   130     /**
       
   131      * Used to add a <code>Component</code> to the right of the other
       
   132      * <code>Component</code>.
       
   133      */
       
   134     public final static String RIGHT = "right";
       
   135 
       
   136     /**
       
   137      * Used to add a <code>Component</code> above the other
       
   138      * <code>Component</code>.
       
   139      */
       
   140     public final static String TOP = "top";
       
   141 
       
   142     /**
       
   143      * Used to add a <code>Component</code> below the other
       
   144      * <code>Component</code>.
       
   145      */
       
   146     public final static String BOTTOM = "bottom";
       
   147 
       
   148     /**
       
   149      * Used to add a <code>Component</code> that will represent the divider.
       
   150      */
       
   151     public final static String DIVIDER = "divider";
       
   152 
       
   153     /**
       
   154      * Bound property name for orientation (horizontal or vertical).
       
   155      */
       
   156     public final static String ORIENTATION_PROPERTY = "orientation";
       
   157 
       
   158     /**
       
   159      * Bound property name for continuousLayout.
       
   160      */
       
   161     public final static String CONTINUOUS_LAYOUT_PROPERTY = "continuousLayout";
       
   162 
       
   163     /**
       
   164      * Bound property name for border.
       
   165      */
       
   166     public final static String DIVIDER_SIZE_PROPERTY = "dividerSize";
       
   167 
       
   168     /**
       
   169      * Bound property for oneTouchExpandable.
       
   170      */
       
   171     public final static String ONE_TOUCH_EXPANDABLE_PROPERTY =
       
   172                                "oneTouchExpandable";
       
   173 
       
   174     /**
       
   175      * Bound property for lastLocation.
       
   176      */
       
   177     public final static String LAST_DIVIDER_LOCATION_PROPERTY =
       
   178                                "lastDividerLocation";
       
   179 
       
   180     /**
       
   181      * Bound property for the dividerLocation.
       
   182      * @since 1.3
       
   183      */
       
   184     public final static String DIVIDER_LOCATION_PROPERTY = "dividerLocation";
       
   185 
       
   186     /**
       
   187      * Bound property for weight.
       
   188      * @since 1.3
       
   189      */
       
   190     public final static String RESIZE_WEIGHT_PROPERTY = "resizeWeight";
       
   191 
       
   192     /**
       
   193      * How the views are split.
       
   194      */
       
   195     protected int orientation;
       
   196 
       
   197     /**
       
   198      * Whether or not the views are continuously redisplayed while
       
   199      * resizing.
       
   200      */
       
   201     protected boolean continuousLayout;
       
   202 
       
   203     /**
       
   204      * The left or top component.
       
   205      */
       
   206     protected Component leftComponent;
       
   207 
       
   208     /**
       
   209      * The right or bottom component.
       
   210      */
       
   211     protected Component rightComponent;
       
   212 
       
   213     /**
       
   214      * Size of the divider.
       
   215      */
       
   216     protected int dividerSize;
       
   217     private boolean dividerSizeSet = false;
       
   218 
       
   219     /**
       
   220      * Is a little widget provided to quickly expand/collapse the
       
   221      * split pane?
       
   222      */
       
   223     protected boolean oneTouchExpandable;
       
   224     private boolean oneTouchExpandableSet;
       
   225 
       
   226     /**
       
   227      * Previous location of the split pane.
       
   228      */
       
   229     protected int lastDividerLocation;
       
   230 
       
   231     /**
       
   232      * How to distribute extra space.
       
   233      */
       
   234     private double resizeWeight;
       
   235 
       
   236     /**
       
   237      * Location of the divider, at least the value that was set, the UI may
       
   238      * have a different value.
       
   239      */
       
   240     private int dividerLocation;
       
   241 
       
   242 
       
   243     /**
       
   244      * Creates a new <code>JSplitPane</code> configured to arrange the child
       
   245      * components side-by-side horizontally with no continuous
       
   246      * layout, using two buttons for the components.
       
   247      */
       
   248     public JSplitPane() {
       
   249         this(JSplitPane.HORIZONTAL_SPLIT, false,
       
   250             new JButton(UIManager.getString("SplitPane.leftButtonText")),
       
   251             new JButton(UIManager.getString("SplitPane.rightButtonText")));
       
   252     }
       
   253 
       
   254 
       
   255     /**
       
   256      * Creates a new <code>JSplitPane</code> configured with the
       
   257      * specified orientation and no continuous layout.
       
   258      *
       
   259      * @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
       
   260      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
       
   261      * @exception IllegalArgumentException if <code>orientation</code>
       
   262      *          is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT.
       
   263      */
       
   264     @ConstructorProperties({"orientation"})
       
   265     public JSplitPane(int newOrientation) {
       
   266         this(newOrientation, false);
       
   267     }
       
   268 
       
   269 
       
   270     /**
       
   271      * Creates a new <code>JSplitPane</code> with the specified
       
   272      * orientation and redrawing style.
       
   273      *
       
   274      * @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
       
   275      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
       
   276      * @param newContinuousLayout  a boolean, true for the components to
       
   277      *        redraw continuously as the divider changes position, false
       
   278      *        to wait until the divider position stops changing to redraw
       
   279      * @exception IllegalArgumentException if <code>orientation</code>
       
   280      *          is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
       
   281      */
       
   282     public JSplitPane(int newOrientation,
       
   283                       boolean newContinuousLayout) {
       
   284         this(newOrientation, newContinuousLayout, null, null);
       
   285     }
       
   286 
       
   287 
       
   288     /**
       
   289      * Creates a new <code>JSplitPane</code> with the specified
       
   290      * orientation and
       
   291      * with the specified components that do not do continuous
       
   292      * redrawing.
       
   293      *
       
   294      * @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
       
   295      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
       
   296      * @param newLeftComponent the <code>Component</code> that will
       
   297      *          appear on the left
       
   298      *          of a horizontally-split pane, or at the top of a
       
   299      *          vertically-split pane
       
   300      * @param newRightComponent the <code>Component</code> that will
       
   301      *          appear on the right
       
   302      *          of a horizontally-split pane, or at the bottom of a
       
   303      *          vertically-split pane
       
   304      * @exception IllegalArgumentException if <code>orientation</code>
       
   305      *          is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT
       
   306      */
       
   307     public JSplitPane(int newOrientation,
       
   308                       Component newLeftComponent,
       
   309                       Component newRightComponent){
       
   310         this(newOrientation, false, newLeftComponent, newRightComponent);
       
   311     }
       
   312 
       
   313 
       
   314     /**
       
   315      * Creates a new <code>JSplitPane</code> with the specified
       
   316      * orientation and
       
   317      * redrawing style, and with the specified components.
       
   318      *
       
   319      * @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
       
   320      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
       
   321      * @param newContinuousLayout  a boolean, true for the components to
       
   322      *        redraw continuously as the divider changes position, false
       
   323      *        to wait until the divider position stops changing to redraw
       
   324      * @param newLeftComponent the <code>Component</code> that will
       
   325      *          appear on the left
       
   326      *          of a horizontally-split pane, or at the top of a
       
   327      *          vertically-split pane
       
   328      * @param newRightComponent the <code>Component</code> that will
       
   329      *          appear on the right
       
   330      *          of a horizontally-split pane, or at the bottom of a
       
   331      *          vertically-split pane
       
   332      * @exception IllegalArgumentException if <code>orientation</code>
       
   333      *          is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
       
   334      */
       
   335     public JSplitPane(int newOrientation,
       
   336                       boolean newContinuousLayout,
       
   337                       Component newLeftComponent,
       
   338                       Component newRightComponent){
       
   339         super();
       
   340 
       
   341         dividerLocation = -1;
       
   342         setLayout(null);
       
   343         setUIProperty("opaque", Boolean.TRUE);
       
   344         orientation = newOrientation;
       
   345         if (orientation != HORIZONTAL_SPLIT && orientation != VERTICAL_SPLIT)
       
   346             throw new IllegalArgumentException("cannot create JSplitPane, " +
       
   347                                                "orientation must be one of " +
       
   348                                                "JSplitPane.HORIZONTAL_SPLIT " +
       
   349                                                "or JSplitPane.VERTICAL_SPLIT");
       
   350         continuousLayout = newContinuousLayout;
       
   351         if (newLeftComponent != null)
       
   352             setLeftComponent(newLeftComponent);
       
   353         if (newRightComponent != null)
       
   354             setRightComponent(newRightComponent);
       
   355         updateUI();
       
   356 
       
   357     }
       
   358 
       
   359 
       
   360     /**
       
   361      * Sets the L&F object that renders this component.
       
   362      *
       
   363      * @param ui  the <code>SplitPaneUI</code> L&F object
       
   364      * @see UIDefaults#getUI
       
   365      * @beaninfo
       
   366      *        bound: true
       
   367      *       hidden: true
       
   368      *    attribute: visualUpdate true
       
   369      *  description: The UI object that implements the Component's LookAndFeel.
       
   370      */
       
   371     public void setUI(SplitPaneUI ui) {
       
   372         if ((SplitPaneUI)this.ui != ui) {
       
   373             super.setUI(ui);
       
   374             revalidate();
       
   375         }
       
   376     }
       
   377 
       
   378 
       
   379     /**
       
   380      * Returns the <code>SplitPaneUI</code> that is providing the
       
   381      * current look and feel.
       
   382      *
       
   383      * @return the <code>SplitPaneUI</code> object that renders this component
       
   384      * @beaninfo
       
   385      *       expert: true
       
   386      *  description: The L&F object that renders this component.
       
   387      */
       
   388     public SplitPaneUI getUI() {
       
   389         return (SplitPaneUI)ui;
       
   390     }
       
   391 
       
   392 
       
   393     /**
       
   394      * Notification from the <code>UIManager</code> that the L&F has changed.
       
   395      * Replaces the current UI object with the latest version from the
       
   396      * <code>UIManager</code>.
       
   397      *
       
   398      * @see JComponent#updateUI
       
   399      */
       
   400     public void updateUI() {
       
   401         setUI((SplitPaneUI)UIManager.getUI(this));
       
   402         revalidate();
       
   403     }
       
   404 
       
   405 
       
   406     /**
       
   407      * Returns the name of the L&F class that renders this component.
       
   408      *
       
   409      * @return the string "SplitPaneUI"
       
   410      * @see JComponent#getUIClassID
       
   411      * @see UIDefaults#getUI
       
   412      * @beaninfo
       
   413      *       expert: true
       
   414      *  description: A string that specifies the name of the L&F class.
       
   415      */
       
   416     public String getUIClassID() {
       
   417         return uiClassID;
       
   418     }
       
   419 
       
   420 
       
   421     /**
       
   422      * Sets the size of the divider.
       
   423      *
       
   424      * @param newSize an integer giving the size of the divider in pixels
       
   425      * @beaninfo
       
   426      *        bound: true
       
   427      *  description: The size of the divider.
       
   428      */
       
   429     public void setDividerSize(int newSize) {
       
   430         int           oldSize = dividerSize;
       
   431 
       
   432         dividerSizeSet = true;
       
   433         if (oldSize != newSize) {
       
   434             dividerSize = newSize;
       
   435             firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, newSize);
       
   436         }
       
   437     }
       
   438 
       
   439 
       
   440     /**
       
   441      * Returns the size of the divider.
       
   442      *
       
   443      * @return an integer giving the size of the divider in pixels
       
   444      */
       
   445     public int getDividerSize() {
       
   446         return dividerSize;
       
   447     }
       
   448 
       
   449 
       
   450     /**
       
   451      * Sets the component to the left (or above) the divider.
       
   452      *
       
   453      * @param comp the <code>Component</code> to display in that position
       
   454      */
       
   455     public void setLeftComponent(Component comp) {
       
   456         if (comp == null) {
       
   457             if (leftComponent != null) {
       
   458                 remove(leftComponent);
       
   459                 leftComponent = null;
       
   460             }
       
   461         } else {
       
   462             add(comp, JSplitPane.LEFT);
       
   463         }
       
   464     }
       
   465 
       
   466 
       
   467     /**
       
   468      * Returns the component to the left (or above) the divider.
       
   469      *
       
   470      * @return the <code>Component</code> displayed in that position
       
   471      * @beaninfo
       
   472      *    preferred: true
       
   473      *  description: The component to the left (or above) the divider.
       
   474      */
       
   475     public Component getLeftComponent() {
       
   476         return leftComponent;
       
   477     }
       
   478 
       
   479 
       
   480     /**
       
   481      * Sets the component above, or to the left of the divider.
       
   482      *
       
   483      * @param comp the <code>Component</code> to display in that position
       
   484      * @beaninfo
       
   485      *  description: The component above, or to the left of the divider.
       
   486      */
       
   487     public void setTopComponent(Component comp) {
       
   488         setLeftComponent(comp);
       
   489     }
       
   490 
       
   491 
       
   492     /**
       
   493      * Returns the component above, or to the left of the divider.
       
   494      *
       
   495      * @return the <code>Component</code> displayed in that position
       
   496      */
       
   497     public Component getTopComponent() {
       
   498         return leftComponent;
       
   499     }
       
   500 
       
   501 
       
   502     /**
       
   503      * Sets the component to the right (or below) the divider.
       
   504      *
       
   505      * @param comp the <code>Component</code> to display in that position
       
   506      * @beaninfo
       
   507      *    preferred: true
       
   508      *  description: The component to the right (or below) the divider.
       
   509      */
       
   510     public void setRightComponent(Component comp) {
       
   511         if (comp == null) {
       
   512             if (rightComponent != null) {
       
   513                 remove(rightComponent);
       
   514                 rightComponent = null;
       
   515             }
       
   516         } else {
       
   517             add(comp, JSplitPane.RIGHT);
       
   518         }
       
   519     }
       
   520 
       
   521 
       
   522     /**
       
   523      * Returns the component to the right (or below) the divider.
       
   524      *
       
   525      * @return the <code>Component</code> displayed in that position
       
   526      */
       
   527     public Component getRightComponent() {
       
   528         return rightComponent;
       
   529     }
       
   530 
       
   531 
       
   532     /**
       
   533      * Sets the component below, or to the right of the divider.
       
   534      *
       
   535      * @param comp the <code>Component</code> to display in that position
       
   536      * @beaninfo
       
   537      *  description: The component below, or to the right of the divider.
       
   538      */
       
   539     public void setBottomComponent(Component comp) {
       
   540         setRightComponent(comp);
       
   541     }
       
   542 
       
   543 
       
   544     /**
       
   545      * Returns the component below, or to the right of the divider.
       
   546      *
       
   547      * @return the <code>Component</code> displayed in that position
       
   548      */
       
   549     public Component getBottomComponent() {
       
   550         return rightComponent;
       
   551     }
       
   552 
       
   553 
       
   554     /**
       
   555      * Sets the value of the <code>oneTouchExpandable</code> property,
       
   556      * which must be <code>true</code> for the
       
   557      * <code>JSplitPane</code> to provide a UI widget
       
   558      * on the divider to quickly expand/collapse the divider.
       
   559      * The default value of this property is <code>false</code>.
       
   560      * Some look and feels might not support one-touch expanding;
       
   561      * they will ignore this property.
       
   562      *
       
   563      * @param newValue <code>true</code> to specify that the split pane should provide a
       
   564      *        collapse/expand widget
       
   565      * @beaninfo
       
   566      *        bound: true
       
   567      *  description: UI widget on the divider to quickly
       
   568      *               expand/collapse the divider.
       
   569      *
       
   570      * @see #isOneTouchExpandable
       
   571      */
       
   572     public void setOneTouchExpandable(boolean newValue) {
       
   573         boolean           oldValue = oneTouchExpandable;
       
   574 
       
   575         oneTouchExpandable = newValue;
       
   576         oneTouchExpandableSet = true;
       
   577         firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue, newValue);
       
   578         repaint();
       
   579     }
       
   580 
       
   581 
       
   582     /**
       
   583      * Gets the <code>oneTouchExpandable</code> property.
       
   584      *
       
   585      * @return the value of the <code>oneTouchExpandable</code> property
       
   586      * @see #setOneTouchExpandable
       
   587      */
       
   588     public boolean isOneTouchExpandable() {
       
   589         return oneTouchExpandable;
       
   590     }
       
   591 
       
   592 
       
   593     /**
       
   594      * Sets the last location the divider was at to
       
   595      * <code>newLastLocation</code>.
       
   596      *
       
   597      * @param newLastLocation an integer specifying the last divider location
       
   598      *        in pixels, from the left (or upper) edge of the pane to the
       
   599      *        left (or upper) edge of the divider
       
   600      * @beaninfo
       
   601      *        bound: true
       
   602      *  description: The last location the divider was at.
       
   603      */
       
   604     public void setLastDividerLocation(int newLastLocation) {
       
   605         int               oldLocation = lastDividerLocation;
       
   606 
       
   607         lastDividerLocation = newLastLocation;
       
   608         firePropertyChange(LAST_DIVIDER_LOCATION_PROPERTY, oldLocation,
       
   609                            newLastLocation);
       
   610     }
       
   611 
       
   612 
       
   613     /**
       
   614      * Returns the last location the divider was at.
       
   615      *
       
   616      * @return an integer specifying the last divider location as a count
       
   617      *       of pixels from the left (or upper) edge of the pane to the
       
   618      *       left (or upper) edge of the divider
       
   619      */
       
   620     public int getLastDividerLocation() {
       
   621         return lastDividerLocation;
       
   622     }
       
   623 
       
   624 
       
   625     /**
       
   626      * Sets the orientation, or how the splitter is divided. The options
       
   627      * are:<ul>
       
   628      * <li>JSplitPane.VERTICAL_SPLIT  (above/below orientation of components)
       
   629      * <li>JSplitPane.HORIZONTAL_SPLIT  (left/right orientation of components)
       
   630      * </ul>
       
   631      *
       
   632      * @param orientation an integer specifying the orientation
       
   633      * @exception IllegalArgumentException if orientation is not one of:
       
   634      *        HORIZONTAL_SPLIT or VERTICAL_SPLIT.
       
   635      * @beaninfo
       
   636      *        bound: true
       
   637      *  description: The orientation, or how the splitter is divided.
       
   638      *         enum: HORIZONTAL_SPLIT JSplitPane.HORIZONTAL_SPLIT
       
   639      *               VERTICAL_SPLIT   JSplitPane.VERTICAL_SPLIT
       
   640      */
       
   641     public void setOrientation(int orientation) {
       
   642         if ((orientation != VERTICAL_SPLIT) &&
       
   643             (orientation != HORIZONTAL_SPLIT)) {
       
   644            throw new IllegalArgumentException("JSplitPane: orientation must " +
       
   645                                               "be one of " +
       
   646                                               "JSplitPane.VERTICAL_SPLIT or " +
       
   647                                               "JSplitPane.HORIZONTAL_SPLIT");
       
   648         }
       
   649 
       
   650         int           oldOrientation = this.orientation;
       
   651 
       
   652         this.orientation = orientation;
       
   653         firePropertyChange(ORIENTATION_PROPERTY, oldOrientation, orientation);
       
   654     }
       
   655 
       
   656 
       
   657     /**
       
   658      * Returns the orientation.
       
   659      *
       
   660      * @return an integer giving the orientation
       
   661      * @see #setOrientation
       
   662      */
       
   663     public int getOrientation() {
       
   664         return orientation;
       
   665     }
       
   666 
       
   667 
       
   668     /**
       
   669      * Sets the value of the <code>continuousLayout</code> property,
       
   670      * which must be <code>true</code> for the child components
       
   671      * to be continuously
       
   672      * redisplayed and laid out during user intervention.
       
   673      * The default value of this property is <code>false</code>.
       
   674      * Some look and feels might not support continuous layout;
       
   675      * they will ignore this property.
       
   676      *
       
   677      * @param newContinuousLayout  <code>true</code> if the components
       
   678      *        should continuously be redrawn as the divider changes position
       
   679      * @beaninfo
       
   680      *        bound: true
       
   681      *  description: Whether the child components are
       
   682      *               continuously redisplayed and laid out during
       
   683      *               user intervention.
       
   684      * @see #isContinuousLayout
       
   685      */
       
   686     public void setContinuousLayout(boolean newContinuousLayout) {
       
   687         boolean           oldCD = continuousLayout;
       
   688 
       
   689         continuousLayout = newContinuousLayout;
       
   690         firePropertyChange(CONTINUOUS_LAYOUT_PROPERTY, oldCD,
       
   691                            newContinuousLayout);
       
   692     }
       
   693 
       
   694 
       
   695     /**
       
   696      * Gets the <code>continuousLayout</code> property.
       
   697      *
       
   698      * @return the value of the <code>continuousLayout</code> property
       
   699      * @see #setContinuousLayout
       
   700      */
       
   701     public boolean isContinuousLayout() {
       
   702         return continuousLayout;
       
   703     }
       
   704 
       
   705     /**
       
   706      * Specifies how to distribute extra space when the size of the split pane
       
   707      * changes. A value of 0, the default,
       
   708      * indicates the right/bottom component gets all the extra space (the
       
   709      * left/top component acts fixed), where as a value of 1 specifies the
       
   710      * left/top component gets all the extra space (the right/bottom component
       
   711      * acts fixed). Specifically, the left/top component gets (weight * diff)
       
   712      * extra space and the right/bottom component gets (1 - weight) * diff
       
   713      * extra space.
       
   714      *
       
   715      * @param value as described above
       
   716      * @exception IllegalArgumentException if <code>value</code> is < 0 or > 1
       
   717      * @since 1.3
       
   718      * @beaninfo
       
   719      *        bound: true
       
   720      *  description: Specifies how to distribute extra space when the split pane
       
   721      *               resizes.
       
   722      */
       
   723     public void setResizeWeight(double value) {
       
   724         if (value < 0 || value > 1) {
       
   725             throw new IllegalArgumentException("JSplitPane weight must be between 0 and 1");
       
   726         }
       
   727         double         oldWeight = resizeWeight;
       
   728 
       
   729         resizeWeight = value;
       
   730         firePropertyChange(RESIZE_WEIGHT_PROPERTY, oldWeight, value);
       
   731     }
       
   732 
       
   733     /**
       
   734      * Returns the number that determines how extra space is distributed.
       
   735      * @return how extra space is to be distributed on a resize of the
       
   736      *         split pane
       
   737      * @since 1.3
       
   738      */
       
   739     public double getResizeWeight() {
       
   740         return resizeWeight;
       
   741     }
       
   742 
       
   743     /**
       
   744      * Lays out the <code>JSplitPane</code> layout based on the preferred size
       
   745      * of the children components. This will likely result in changing
       
   746      * the divider location.
       
   747      */
       
   748     public void resetToPreferredSizes() {
       
   749         SplitPaneUI         ui = getUI();
       
   750 
       
   751         if (ui != null) {
       
   752             ui.resetToPreferredSizes(this);
       
   753         }
       
   754     }
       
   755 
       
   756 
       
   757     /**
       
   758      * Sets the divider location as a percentage of the
       
   759      * <code>JSplitPane</code>'s size.
       
   760      * <p>
       
   761      * This method is implemented in terms of
       
   762      * <code>setDividerLocation(int)</code>.
       
   763      * This method immediately changes the size of the split pane based on
       
   764      * its current size. If the split pane is not correctly realized and on
       
   765      * screen, this method will have no effect (new divider location will
       
   766      * become (current size * proportionalLocation) which is 0).
       
   767      *
       
   768      * @param proportionalLocation  a double-precision floating point value
       
   769      *        that specifies a percentage, from zero (top/left) to 1.0
       
   770      *        (bottom/right)
       
   771      * @exception IllegalArgumentException if the specified location is < 0
       
   772      *            or > 1.0
       
   773      * @beaninfo
       
   774      *  description: The location of the divider.
       
   775      */
       
   776     public void setDividerLocation(double proportionalLocation) {
       
   777         if (proportionalLocation < 0.0 ||
       
   778            proportionalLocation > 1.0) {
       
   779             throw new IllegalArgumentException("proportional location must " +
       
   780                                                "be between 0.0 and 1.0.");
       
   781         }
       
   782         if (getOrientation() == VERTICAL_SPLIT) {
       
   783             setDividerLocation((int)((double)(getHeight() - getDividerSize()) *
       
   784                                      proportionalLocation));
       
   785         } else {
       
   786             setDividerLocation((int)((double)(getWidth() - getDividerSize()) *
       
   787                                      proportionalLocation));
       
   788         }
       
   789     }
       
   790 
       
   791 
       
   792     /**
       
   793      * Sets the location of the divider. This is passed off to the
       
   794      * look and feel implementation, and then listeners are notified. A value
       
   795      * less than 0 implies the divider should be reset to a value that
       
   796      * attempts to honor the preferred size of the left/top component.
       
   797      * After notifying the listeners, the last divider location is updated,
       
   798      * via <code>setLastDividerLocation</code>.
       
   799      *
       
   800      * @param location an int specifying a UI-specific value (typically a
       
   801      *        pixel count)
       
   802      * @beaninfo
       
   803      *        bound: true
       
   804      *  description: The location of the divider.
       
   805      */
       
   806     public void setDividerLocation(int location) {
       
   807         int                 oldValue = dividerLocation;
       
   808 
       
   809         dividerLocation = location;
       
   810 
       
   811         // Notify UI.
       
   812         SplitPaneUI         ui = getUI();
       
   813 
       
   814         if (ui != null) {
       
   815             ui.setDividerLocation(this, location);
       
   816         }
       
   817 
       
   818         // Then listeners
       
   819         firePropertyChange(DIVIDER_LOCATION_PROPERTY, oldValue, location);
       
   820 
       
   821         // And update the last divider location.
       
   822         setLastDividerLocation(oldValue);
       
   823     }
       
   824 
       
   825 
       
   826     /**
       
   827      * Returns the last value passed to <code>setDividerLocation</code>.
       
   828      * The value returned from this method may differ from the actual
       
   829      * divider location (if <code>setDividerLocation</code> was passed a
       
   830      * value bigger than the curent size).
       
   831      *
       
   832      * @return an integer specifying the location of the divider
       
   833      */
       
   834     public int getDividerLocation() {
       
   835         return dividerLocation;
       
   836     }
       
   837 
       
   838 
       
   839     /**
       
   840      * Returns the minimum location of the divider from the look and feel
       
   841      * implementation.
       
   842      *
       
   843      * @return an integer specifying a UI-specific value for the minimum
       
   844      *          location (typically a pixel count); or -1 if the UI is
       
   845      *          <code>null</code>
       
   846      * @beaninfo
       
   847      *  description: The minimum location of the divider from the L&F.
       
   848      */
       
   849     public int getMinimumDividerLocation() {
       
   850         SplitPaneUI         ui = getUI();
       
   851 
       
   852         if (ui != null) {
       
   853             return ui.getMinimumDividerLocation(this);
       
   854         }
       
   855         return -1;
       
   856     }
       
   857 
       
   858 
       
   859     /**
       
   860      * Returns the maximum location of the divider from the look and feel
       
   861      * implementation.
       
   862      *
       
   863      * @return an integer specifying a UI-specific value for the maximum
       
   864      *          location (typically a pixel count); or -1 if the  UI is
       
   865      *          <code>null</code>
       
   866      */
       
   867     public int getMaximumDividerLocation() {
       
   868         SplitPaneUI         ui = getUI();
       
   869 
       
   870         if (ui != null) {
       
   871             return ui.getMaximumDividerLocation(this);
       
   872         }
       
   873         return -1;
       
   874     }
       
   875 
       
   876 
       
   877     /**
       
   878      * Removes the child component, <code>component</code> from the
       
   879      * pane. Resets the <code>leftComponent</code> or
       
   880      * <code>rightComponent</code> instance variable, as necessary.
       
   881      *
       
   882      * @param component the <code>Component</code> to remove
       
   883      */
       
   884     public void remove(Component component) {
       
   885         if (component == leftComponent) {
       
   886             leftComponent = null;
       
   887         } else if (component == rightComponent) {
       
   888             rightComponent = null;
       
   889         }
       
   890         super.remove(component);
       
   891 
       
   892         // Update the JSplitPane on the screen
       
   893         revalidate();
       
   894         repaint();
       
   895     }
       
   896 
       
   897 
       
   898     /**
       
   899      * Removes the <code>Component</code> at the specified index.
       
   900      * Updates the <code>leftComponent</code> and <code>rightComponent</code>
       
   901      * instance variables as necessary, and then messages super.
       
   902      *
       
   903      * @param index an integer specifying the component to remove, where
       
   904      *        1 specifies the left/top component and 2 specifies the
       
   905      *        bottom/right component
       
   906      */
       
   907     public void remove(int index) {
       
   908         Component    comp = getComponent(index);
       
   909 
       
   910         if (comp == leftComponent) {
       
   911             leftComponent = null;
       
   912         } else if (comp == rightComponent) {
       
   913             rightComponent = null;
       
   914         }
       
   915         super.remove(index);
       
   916 
       
   917         // Update the JSplitPane on the screen
       
   918         revalidate();
       
   919         repaint();
       
   920     }
       
   921 
       
   922 
       
   923     /**
       
   924      * Removes all the child components from the split pane. Resets the
       
   925      * <code>leftComonent</code> and <code>rightComponent</code>
       
   926      * instance variables.
       
   927      */
       
   928     public void removeAll() {
       
   929         leftComponent = rightComponent = null;
       
   930         super.removeAll();
       
   931 
       
   932         // Update the JSplitPane on the screen
       
   933         revalidate();
       
   934         repaint();
       
   935     }
       
   936 
       
   937 
       
   938     /**
       
   939      * Returns true, so that calls to <code>revalidate</code>
       
   940      * on any descendant of this <code>JSplitPane</code>
       
   941      * will cause a request to be queued that
       
   942      * will validate the <code>JSplitPane</code> and all its descendants.
       
   943      *
       
   944      * @return true
       
   945      * @see JComponent#revalidate
       
   946      *
       
   947      * @beaninfo
       
   948      *    hidden: true
       
   949      */
       
   950     public boolean isValidateRoot() {
       
   951         return true;
       
   952     }
       
   953 
       
   954 
       
   955     /**
       
   956      * Adds the specified component to this split pane.
       
   957      * If <code>constraints</code> identifies the left/top or
       
   958      * right/bottom child component, and a component with that identifier
       
   959      * was previously added, it will be removed and then <code>comp</code>
       
   960      * will be added in its place. If <code>constraints</code> is not
       
   961      * one of the known identifiers the layout manager may throw an
       
   962      * <code>IllegalArgumentException</code>.
       
   963      * <p>
       
   964      * The possible constraints objects (Strings) are:
       
   965      * <ul>
       
   966      * <li>JSplitPane.TOP
       
   967      * <li>JSplitPane.LEFT
       
   968      * <li>JSplitPane.BOTTOM
       
   969      * <li>JSplitPane.RIGHT
       
   970      * </ul>
       
   971      * If the <code>constraints</code> object is <code>null</code>,
       
   972      * the component is added in the
       
   973      * first available position (left/top if open, else right/bottom).
       
   974      *
       
   975      * @param comp        the component to add
       
   976      * @param constraints an <code>Object</code> specifying the
       
   977      *                    layout constraints
       
   978      *                    (position) for this component
       
   979      * @param index       an integer specifying the index in the container's
       
   980      *                    list.
       
   981      * @exception IllegalArgumentException  if the <code>constraints</code>
       
   982      *          object does not match an existing component
       
   983      * @see java.awt.Container#addImpl(Component, Object, int)
       
   984      */
       
   985     protected void addImpl(Component comp, Object constraints, int index)
       
   986     {
       
   987         Component             toRemove;
       
   988 
       
   989         if (constraints != null && !(constraints instanceof String)) {
       
   990             throw new IllegalArgumentException("cannot add to layout: " +
       
   991                                                "constraint must be a string " +
       
   992                                                "(or null)");
       
   993         }
       
   994 
       
   995         /* If the constraints are null and the left/right component is
       
   996            invalid, add it at the left/right component. */
       
   997         if (constraints == null) {
       
   998             if (getLeftComponent() == null) {
       
   999                 constraints = JSplitPane.LEFT;
       
  1000             } else if (getRightComponent() == null) {
       
  1001                 constraints = JSplitPane.RIGHT;
       
  1002             }
       
  1003         }
       
  1004 
       
  1005         /* Find the Component that already exists and remove it. */
       
  1006         if (constraints != null && (constraints.equals(JSplitPane.LEFT) ||
       
  1007                                    constraints.equals(JSplitPane.TOP))) {
       
  1008             toRemove = getLeftComponent();
       
  1009             if (toRemove != null) {
       
  1010                 remove(toRemove);
       
  1011             }
       
  1012             leftComponent = comp;
       
  1013             index = -1;
       
  1014         } else if (constraints != null &&
       
  1015                    (constraints.equals(JSplitPane.RIGHT) ||
       
  1016                     constraints.equals(JSplitPane.BOTTOM))) {
       
  1017             toRemove = getRightComponent();
       
  1018             if (toRemove != null) {
       
  1019                 remove(toRemove);
       
  1020             }
       
  1021             rightComponent = comp;
       
  1022             index = -1;
       
  1023         } else if (constraints != null &&
       
  1024                 constraints.equals(JSplitPane.DIVIDER)) {
       
  1025             index = -1;
       
  1026         }
       
  1027         /* LayoutManager should raise for else condition here. */
       
  1028 
       
  1029         super.addImpl(comp, constraints, index);
       
  1030 
       
  1031         // Update the JSplitPane on the screen
       
  1032         revalidate();
       
  1033         repaint();
       
  1034     }
       
  1035 
       
  1036 
       
  1037     /**
       
  1038      * Subclassed to message the UI with <code>finishedPaintingChildren</code>
       
  1039      * after super has been messaged, as well as painting the border.
       
  1040      *
       
  1041      * @param g the <code>Graphics</code> context within which to paint
       
  1042      */
       
  1043     protected void paintChildren(Graphics g) {
       
  1044         super.paintChildren(g);
       
  1045 
       
  1046         SplitPaneUI        ui = getUI();
       
  1047 
       
  1048         if (ui != null) {
       
  1049             Graphics           tempG = g.create();
       
  1050             ui.finishedPaintingChildren(this, tempG);
       
  1051             tempG.dispose();
       
  1052         }
       
  1053     }
       
  1054 
       
  1055 
       
  1056     /**
       
  1057      * See <code>readObject</code> and <code>writeObject</code> in
       
  1058      * <code>JComponent</code> for more
       
  1059      * information about serialization in Swing.
       
  1060      */
       
  1061     private void writeObject(ObjectOutputStream s) throws IOException {
       
  1062         s.defaultWriteObject();
       
  1063         if (getUIClassID().equals(uiClassID)) {
       
  1064             byte count = JComponent.getWriteObjCounter(this);
       
  1065             JComponent.setWriteObjCounter(this, --count);
       
  1066             if (count == 0 && ui != null) {
       
  1067                 ui.installUI(this);
       
  1068             }
       
  1069         }
       
  1070     }
       
  1071 
       
  1072     void setUIProperty(String propertyName, Object value) {
       
  1073         if (propertyName == "dividerSize") {
       
  1074             if (!dividerSizeSet) {
       
  1075                 setDividerSize(((Number)value).intValue());
       
  1076                 dividerSizeSet = false;
       
  1077             }
       
  1078         } else if (propertyName == "oneTouchExpandable") {
       
  1079             if (!oneTouchExpandableSet) {
       
  1080                 setOneTouchExpandable(((Boolean)value).booleanValue());
       
  1081                 oneTouchExpandableSet = false;
       
  1082             }
       
  1083         } else {
       
  1084             super.setUIProperty(propertyName, value);
       
  1085         }
       
  1086     }
       
  1087 
       
  1088 
       
  1089     /**
       
  1090      * Returns a string representation of this <code>JSplitPane</code>.
       
  1091      * This method
       
  1092      * is intended to be used only for debugging purposes, and the
       
  1093      * content and format of the returned string may vary between
       
  1094      * implementations. The returned string may be empty but may not
       
  1095      * be <code>null</code>.
       
  1096      *
       
  1097      * @return  a string representation of this <code>JSplitPane</code>.
       
  1098      */
       
  1099     protected String paramString() {
       
  1100         String orientationString = (orientation == HORIZONTAL_SPLIT ?
       
  1101                                     "HORIZONTAL_SPLIT" : "VERTICAL_SPLIT");
       
  1102         String continuousLayoutString = (continuousLayout ?
       
  1103                                          "true" : "false");
       
  1104         String oneTouchExpandableString = (oneTouchExpandable ?
       
  1105                                            "true" : "false");
       
  1106 
       
  1107         return super.paramString() +
       
  1108         ",continuousLayout=" + continuousLayoutString +
       
  1109         ",dividerSize=" + dividerSize +
       
  1110         ",lastDividerLocation=" + lastDividerLocation +
       
  1111         ",oneTouchExpandable=" + oneTouchExpandableString +
       
  1112         ",orientation=" + orientationString;
       
  1113     }
       
  1114 
       
  1115 
       
  1116 
       
  1117     ///////////////////////////
       
  1118     // Accessibility support //
       
  1119     ///////////////////////////
       
  1120 
       
  1121 
       
  1122     /**
       
  1123      * Gets the AccessibleContext associated with this JSplitPane.
       
  1124      * For split panes, the AccessibleContext takes the form of an
       
  1125      * AccessibleJSplitPane.
       
  1126      * A new AccessibleJSplitPane instance is created if necessary.
       
  1127      *
       
  1128      * @return an AccessibleJSplitPane that serves as the
       
  1129      *         AccessibleContext of this JSplitPane
       
  1130      * @beaninfo
       
  1131      *       expert: true
       
  1132      *  description: The AccessibleContext associated with this SplitPane.
       
  1133      */
       
  1134     public AccessibleContext getAccessibleContext() {
       
  1135         if (accessibleContext == null) {
       
  1136             accessibleContext = new AccessibleJSplitPane();
       
  1137         }
       
  1138         return accessibleContext;
       
  1139     }
       
  1140 
       
  1141 
       
  1142     /**
       
  1143      * This class implements accessibility support for the
       
  1144      * <code>JSplitPane</code> class.  It provides an implementation of the
       
  1145      * Java Accessibility API appropriate to split pane user-interface elements.
       
  1146      * <p>
       
  1147      * <strong>Warning:</strong>
       
  1148      * Serialized objects of this class will not be compatible with
       
  1149      * future Swing releases. The current serialization support is
       
  1150      * appropriate for short term storage or RMI between applications running
       
  1151      * the same version of Swing.  As of 1.4, support for long term storage
       
  1152      * of all JavaBeans<sup><font size="-2">TM</font></sup>
       
  1153      * has been added to the <code>java.beans</code> package.
       
  1154      * Please see {@link java.beans.XMLEncoder}.
       
  1155      */
       
  1156     protected class AccessibleJSplitPane extends AccessibleJComponent
       
  1157         implements AccessibleValue {
       
  1158         /**
       
  1159          * Gets the state set of this object.
       
  1160          *
       
  1161          * @return an instance of AccessibleState containing the current state
       
  1162          * of the object
       
  1163          * @see AccessibleState
       
  1164          */
       
  1165         public AccessibleStateSet getAccessibleStateSet() {
       
  1166             AccessibleStateSet states = super.getAccessibleStateSet();
       
  1167             // FIXME: [[[WDW - Should also add BUSY if this implements
       
  1168             // Adjustable at some point.  If this happens, we probably
       
  1169             // should also add actions.]]]
       
  1170             if (getOrientation() == VERTICAL_SPLIT) {
       
  1171                 states.add(AccessibleState.VERTICAL);
       
  1172             } else {
       
  1173                 states.add(AccessibleState.HORIZONTAL);
       
  1174             }
       
  1175             return states;
       
  1176         }
       
  1177 
       
  1178 
       
  1179         /**
       
  1180          * Get the AccessibleValue associated with this object.  In the
       
  1181          * implementation of the Java Accessibility API for this class,
       
  1182          * return this object, which is responsible for implementing the
       
  1183          * AccessibleValue interface on behalf of itself.
       
  1184          *
       
  1185          * @return this object
       
  1186          */
       
  1187         public AccessibleValue getAccessibleValue() {
       
  1188             return this;
       
  1189         }
       
  1190 
       
  1191 
       
  1192         /**
       
  1193          * Gets the accessible value of this object.
       
  1194          *
       
  1195          * @return a localized String describing the value of this object
       
  1196          */
       
  1197         public Number getCurrentAccessibleValue() {
       
  1198             return new Integer(getDividerLocation());
       
  1199         }
       
  1200 
       
  1201 
       
  1202         /**
       
  1203          * Sets the value of this object as a Number.
       
  1204          *
       
  1205          * @return True if the value was set.
       
  1206          */
       
  1207         public boolean setCurrentAccessibleValue(Number n) {
       
  1208             // TIGER - 4422535
       
  1209             if (n == null) {
       
  1210                 return false;
       
  1211             }
       
  1212             setDividerLocation(n.intValue());
       
  1213             return true;
       
  1214         }
       
  1215 
       
  1216 
       
  1217         /**
       
  1218          * Gets the minimum accessible value of this object.
       
  1219          *
       
  1220          * @return The minimum value of this object.
       
  1221          */
       
  1222         public Number getMinimumAccessibleValue() {
       
  1223             return new Integer(getUI().getMinimumDividerLocation(
       
  1224                                                         JSplitPane.this));
       
  1225         }
       
  1226 
       
  1227 
       
  1228         /**
       
  1229          * Gets the maximum accessible value of this object.
       
  1230          *
       
  1231          * @return The maximum value of this object.
       
  1232          */
       
  1233         public Number getMaximumAccessibleValue() {
       
  1234             return new Integer(getUI().getMaximumDividerLocation(
       
  1235                                                         JSplitPane.this));
       
  1236         }
       
  1237 
       
  1238 
       
  1239         /**
       
  1240          * Gets the role of this object.
       
  1241          *
       
  1242          * @return an instance of AccessibleRole describing the role of
       
  1243          * the object
       
  1244          * @see AccessibleRole
       
  1245          */
       
  1246         public AccessibleRole getAccessibleRole() {
       
  1247             return AccessibleRole.SPLIT_PANE;
       
  1248         }
       
  1249     } // inner class AccessibleJSplitPane
       
  1250 }