diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/classes/javax/swing/JSplitPane.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/javax/swing/JSplitPane.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,1250 @@ +/* + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + + +package javax.swing; + + + +import java.beans.ConstructorProperties; +import javax.swing.plaf.*; +import javax.accessibility.*; + +import java.awt.*; + +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; +import java.io.IOException; + + + +/** + * JSplitPane is used to divide two (and only two) + * Components. The two Components + * are graphically divided based on the look and feel + * implementation, and the two Components can then be + * interactively resized by the user. + * Information on using JSplitPane is in + * How to Use Split Panes in + * The Java Tutorial. + *

+ * The two Components in a split pane can be aligned + * left to right using + * JSplitPane.HORIZONTAL_SPLIT, or top to bottom using + * JSplitPane.VERTICAL_SPLIT. + * The preferred way to change the size of the Components + * is to invoke + * setDividerLocation where location is either + * the new x or y position, depending on the orientation of the + * JSplitPane. + *

+ * To resize the Components to their preferred sizes invoke + * resetToPreferredSizes. + *

+ * When the user is resizing the Components the minimum + * size of the Components is used to determine the + * maximum/minimum position the Components + * can be set to. If the minimum size of the two + * components is greater than the size of the split pane the divider + * will not allow you to resize it. To alter the minimum size of a + * JComponent, see {@link JComponent#setMinimumSize}. + *

+ * When the user resizes the split pane the new space is distributed between + * the two components based on the resizeWeight property. + * A value of 0, + * the default, indicates the right/bottom component gets all the space, + * where as a value of 1 indicates the left/top component gets all the space. + *

+ * Warning: Swing is not thread safe. For more + * information see Swing's Threading + * Policy. + *

+ * Warning: + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of Swing. As of 1.4, support for long term storage + * of all JavaBeansTM + * has been added to the java.beans package. + * Please see {@link java.beans.XMLEncoder}. + * + * @see #setDividerLocation + * @see #resetToPreferredSizes + * + * @author Scott Violet + */ +public class JSplitPane extends JComponent implements Accessible +{ + /** + * @see #getUIClassID + * @see #readObject + */ + private static final String uiClassID = "SplitPaneUI"; + + /** + * Vertical split indicates the Components are + * split along the y axis. For example the two + * Components will be split one on top of the other. + */ + public final static int VERTICAL_SPLIT = 0; + + /** + * Horizontal split indicates the Components are + * split along the x axis. For example the two + * Components will be split one to the left of the + * other. + */ + public final static int HORIZONTAL_SPLIT = 1; + + /** + * Used to add a Component to the left of the other + * Component. + */ + public final static String LEFT = "left"; + + /** + * Used to add a Component to the right of the other + * Component. + */ + public final static String RIGHT = "right"; + + /** + * Used to add a Component above the other + * Component. + */ + public final static String TOP = "top"; + + /** + * Used to add a Component below the other + * Component. + */ + public final static String BOTTOM = "bottom"; + + /** + * Used to add a Component that will represent the divider. + */ + public final static String DIVIDER = "divider"; + + /** + * Bound property name for orientation (horizontal or vertical). + */ + public final static String ORIENTATION_PROPERTY = "orientation"; + + /** + * Bound property name for continuousLayout. + */ + public final static String CONTINUOUS_LAYOUT_PROPERTY = "continuousLayout"; + + /** + * Bound property name for border. + */ + public final static String DIVIDER_SIZE_PROPERTY = "dividerSize"; + + /** + * Bound property for oneTouchExpandable. + */ + public final static String ONE_TOUCH_EXPANDABLE_PROPERTY = + "oneTouchExpandable"; + + /** + * Bound property for lastLocation. + */ + public final static String LAST_DIVIDER_LOCATION_PROPERTY = + "lastDividerLocation"; + + /** + * Bound property for the dividerLocation. + * @since 1.3 + */ + public final static String DIVIDER_LOCATION_PROPERTY = "dividerLocation"; + + /** + * Bound property for weight. + * @since 1.3 + */ + public final static String RESIZE_WEIGHT_PROPERTY = "resizeWeight"; + + /** + * How the views are split. + */ + protected int orientation; + + /** + * Whether or not the views are continuously redisplayed while + * resizing. + */ + protected boolean continuousLayout; + + /** + * The left or top component. + */ + protected Component leftComponent; + + /** + * The right or bottom component. + */ + protected Component rightComponent; + + /** + * Size of the divider. + */ + protected int dividerSize; + private boolean dividerSizeSet = false; + + /** + * Is a little widget provided to quickly expand/collapse the + * split pane? + */ + protected boolean oneTouchExpandable; + private boolean oneTouchExpandableSet; + + /** + * Previous location of the split pane. + */ + protected int lastDividerLocation; + + /** + * How to distribute extra space. + */ + private double resizeWeight; + + /** + * Location of the divider, at least the value that was set, the UI may + * have a different value. + */ + private int dividerLocation; + + + /** + * Creates a new JSplitPane configured to arrange the child + * components side-by-side horizontally with no continuous + * layout, using two buttons for the components. + */ + public JSplitPane() { + this(JSplitPane.HORIZONTAL_SPLIT, false, + new JButton(UIManager.getString("SplitPane.leftButtonText")), + new JButton(UIManager.getString("SplitPane.rightButtonText"))); + } + + + /** + * Creates a new JSplitPane configured with the + * specified orientation and no continuous layout. + * + * @param newOrientation JSplitPane.HORIZONTAL_SPLIT or + * JSplitPane.VERTICAL_SPLIT + * @exception IllegalArgumentException if orientation + * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT. + */ + @ConstructorProperties({"orientation"}) + public JSplitPane(int newOrientation) { + this(newOrientation, false); + } + + + /** + * Creates a new JSplitPane with the specified + * orientation and redrawing style. + * + * @param newOrientation JSplitPane.HORIZONTAL_SPLIT or + * JSplitPane.VERTICAL_SPLIT + * @param newContinuousLayout a boolean, true for the components to + * redraw continuously as the divider changes position, false + * to wait until the divider position stops changing to redraw + * @exception IllegalArgumentException if orientation + * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT + */ + public JSplitPane(int newOrientation, + boolean newContinuousLayout) { + this(newOrientation, newContinuousLayout, null, null); + } + + + /** + * Creates a new JSplitPane with the specified + * orientation and + * with the specified components that do not do continuous + * redrawing. + * + * @param newOrientation JSplitPane.HORIZONTAL_SPLIT or + * JSplitPane.VERTICAL_SPLIT + * @param newLeftComponent the Component that will + * appear on the left + * of a horizontally-split pane, or at the top of a + * vertically-split pane + * @param newRightComponent the Component that will + * appear on the right + * of a horizontally-split pane, or at the bottom of a + * vertically-split pane + * @exception IllegalArgumentException if orientation + * is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT + */ + public JSplitPane(int newOrientation, + Component newLeftComponent, + Component newRightComponent){ + this(newOrientation, false, newLeftComponent, newRightComponent); + } + + + /** + * Creates a new JSplitPane with the specified + * orientation and + * redrawing style, and with the specified components. + * + * @param newOrientation JSplitPane.HORIZONTAL_SPLIT or + * JSplitPane.VERTICAL_SPLIT + * @param newContinuousLayout a boolean, true for the components to + * redraw continuously as the divider changes position, false + * to wait until the divider position stops changing to redraw + * @param newLeftComponent the Component that will + * appear on the left + * of a horizontally-split pane, or at the top of a + * vertically-split pane + * @param newRightComponent the Component that will + * appear on the right + * of a horizontally-split pane, or at the bottom of a + * vertically-split pane + * @exception IllegalArgumentException if orientation + * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT + */ + public JSplitPane(int newOrientation, + boolean newContinuousLayout, + Component newLeftComponent, + Component newRightComponent){ + super(); + + dividerLocation = -1; + setLayout(null); + setUIProperty("opaque", Boolean.TRUE); + orientation = newOrientation; + if (orientation != HORIZONTAL_SPLIT && orientation != VERTICAL_SPLIT) + throw new IllegalArgumentException("cannot create JSplitPane, " + + "orientation must be one of " + + "JSplitPane.HORIZONTAL_SPLIT " + + "or JSplitPane.VERTICAL_SPLIT"); + continuousLayout = newContinuousLayout; + if (newLeftComponent != null) + setLeftComponent(newLeftComponent); + if (newRightComponent != null) + setRightComponent(newRightComponent); + updateUI(); + + } + + + /** + * Sets the L&F object that renders this component. + * + * @param ui the SplitPaneUI L&F object + * @see UIDefaults#getUI + * @beaninfo + * bound: true + * hidden: true + * attribute: visualUpdate true + * description: The UI object that implements the Component's LookAndFeel. + */ + public void setUI(SplitPaneUI ui) { + if ((SplitPaneUI)this.ui != ui) { + super.setUI(ui); + revalidate(); + } + } + + + /** + * Returns the SplitPaneUI that is providing the + * current look and feel. + * + * @return the SplitPaneUI object that renders this component + * @beaninfo + * expert: true + * description: The L&F object that renders this component. + */ + public SplitPaneUI getUI() { + return (SplitPaneUI)ui; + } + + + /** + * Notification from the UIManager that the L&F has changed. + * Replaces the current UI object with the latest version from the + * UIManager. + * + * @see JComponent#updateUI + */ + public void updateUI() { + setUI((SplitPaneUI)UIManager.getUI(this)); + revalidate(); + } + + + /** + * Returns the name of the L&F class that renders this component. + * + * @return the string "SplitPaneUI" + * @see JComponent#getUIClassID + * @see UIDefaults#getUI + * @beaninfo + * expert: true + * description: A string that specifies the name of the L&F class. + */ + public String getUIClassID() { + return uiClassID; + } + + + /** + * Sets the size of the divider. + * + * @param newSize an integer giving the size of the divider in pixels + * @beaninfo + * bound: true + * description: The size of the divider. + */ + public void setDividerSize(int newSize) { + int oldSize = dividerSize; + + dividerSizeSet = true; + if (oldSize != newSize) { + dividerSize = newSize; + firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, newSize); + } + } + + + /** + * Returns the size of the divider. + * + * @return an integer giving the size of the divider in pixels + */ + public int getDividerSize() { + return dividerSize; + } + + + /** + * Sets the component to the left (or above) the divider. + * + * @param comp the Component to display in that position + */ + public void setLeftComponent(Component comp) { + if (comp == null) { + if (leftComponent != null) { + remove(leftComponent); + leftComponent = null; + } + } else { + add(comp, JSplitPane.LEFT); + } + } + + + /** + * Returns the component to the left (or above) the divider. + * + * @return the Component displayed in that position + * @beaninfo + * preferred: true + * description: The component to the left (or above) the divider. + */ + public Component getLeftComponent() { + return leftComponent; + } + + + /** + * Sets the component above, or to the left of the divider. + * + * @param comp the Component to display in that position + * @beaninfo + * description: The component above, or to the left of the divider. + */ + public void setTopComponent(Component comp) { + setLeftComponent(comp); + } + + + /** + * Returns the component above, or to the left of the divider. + * + * @return the Component displayed in that position + */ + public Component getTopComponent() { + return leftComponent; + } + + + /** + * Sets the component to the right (or below) the divider. + * + * @param comp the Component to display in that position + * @beaninfo + * preferred: true + * description: The component to the right (or below) the divider. + */ + public void setRightComponent(Component comp) { + if (comp == null) { + if (rightComponent != null) { + remove(rightComponent); + rightComponent = null; + } + } else { + add(comp, JSplitPane.RIGHT); + } + } + + + /** + * Returns the component to the right (or below) the divider. + * + * @return the Component displayed in that position + */ + public Component getRightComponent() { + return rightComponent; + } + + + /** + * Sets the component below, or to the right of the divider. + * + * @param comp the Component to display in that position + * @beaninfo + * description: The component below, or to the right of the divider. + */ + public void setBottomComponent(Component comp) { + setRightComponent(comp); + } + + + /** + * Returns the component below, or to the right of the divider. + * + * @return the Component displayed in that position + */ + public Component getBottomComponent() { + return rightComponent; + } + + + /** + * Sets the value of the oneTouchExpandable property, + * which must be true for the + * JSplitPane to provide a UI widget + * on the divider to quickly expand/collapse the divider. + * The default value of this property is false. + * Some look and feels might not support one-touch expanding; + * they will ignore this property. + * + * @param newValue true to specify that the split pane should provide a + * collapse/expand widget + * @beaninfo + * bound: true + * description: UI widget on the divider to quickly + * expand/collapse the divider. + * + * @see #isOneTouchExpandable + */ + public void setOneTouchExpandable(boolean newValue) { + boolean oldValue = oneTouchExpandable; + + oneTouchExpandable = newValue; + oneTouchExpandableSet = true; + firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue, newValue); + repaint(); + } + + + /** + * Gets the oneTouchExpandable property. + * + * @return the value of the oneTouchExpandable property + * @see #setOneTouchExpandable + */ + public boolean isOneTouchExpandable() { + return oneTouchExpandable; + } + + + /** + * Sets the last location the divider was at to + * newLastLocation. + * + * @param newLastLocation an integer specifying the last divider location + * in pixels, from the left (or upper) edge of the pane to the + * left (or upper) edge of the divider + * @beaninfo + * bound: true + * description: The last location the divider was at. + */ + public void setLastDividerLocation(int newLastLocation) { + int oldLocation = lastDividerLocation; + + lastDividerLocation = newLastLocation; + firePropertyChange(LAST_DIVIDER_LOCATION_PROPERTY, oldLocation, + newLastLocation); + } + + + /** + * Returns the last location the divider was at. + * + * @return an integer specifying the last divider location as a count + * of pixels from the left (or upper) edge of the pane to the + * left (or upper) edge of the divider + */ + public int getLastDividerLocation() { + return lastDividerLocation; + } + + + /** + * Sets the orientation, or how the splitter is divided. The options + * are:

+ * + * @param orientation an integer specifying the orientation + * @exception IllegalArgumentException if orientation is not one of: + * HORIZONTAL_SPLIT or VERTICAL_SPLIT. + * @beaninfo + * bound: true + * description: The orientation, or how the splitter is divided. + * enum: HORIZONTAL_SPLIT JSplitPane.HORIZONTAL_SPLIT + * VERTICAL_SPLIT JSplitPane.VERTICAL_SPLIT + */ + public void setOrientation(int orientation) { + if ((orientation != VERTICAL_SPLIT) && + (orientation != HORIZONTAL_SPLIT)) { + throw new IllegalArgumentException("JSplitPane: orientation must " + + "be one of " + + "JSplitPane.VERTICAL_SPLIT or " + + "JSplitPane.HORIZONTAL_SPLIT"); + } + + int oldOrientation = this.orientation; + + this.orientation = orientation; + firePropertyChange(ORIENTATION_PROPERTY, oldOrientation, orientation); + } + + + /** + * Returns the orientation. + * + * @return an integer giving the orientation + * @see #setOrientation + */ + public int getOrientation() { + return orientation; + } + + + /** + * Sets the value of the continuousLayout property, + * which must be true for the child components + * to be continuously + * redisplayed and laid out during user intervention. + * The default value of this property is false. + * Some look and feels might not support continuous layout; + * they will ignore this property. + * + * @param newContinuousLayout true if the components + * should continuously be redrawn as the divider changes position + * @beaninfo + * bound: true + * description: Whether the child components are + * continuously redisplayed and laid out during + * user intervention. + * @see #isContinuousLayout + */ + public void setContinuousLayout(boolean newContinuousLayout) { + boolean oldCD = continuousLayout; + + continuousLayout = newContinuousLayout; + firePropertyChange(CONTINUOUS_LAYOUT_PROPERTY, oldCD, + newContinuousLayout); + } + + + /** + * Gets the continuousLayout property. + * + * @return the value of the continuousLayout property + * @see #setContinuousLayout + */ + public boolean isContinuousLayout() { + return continuousLayout; + } + + /** + * Specifies how to distribute extra space when the size of the split pane + * changes. A value of 0, the default, + * indicates the right/bottom component gets all the extra space (the + * left/top component acts fixed), where as a value of 1 specifies the + * left/top component gets all the extra space (the right/bottom component + * acts fixed). Specifically, the left/top component gets (weight * diff) + * extra space and the right/bottom component gets (1 - weight) * diff + * extra space. + * + * @param value as described above + * @exception IllegalArgumentException if value is < 0 or > 1 + * @since 1.3 + * @beaninfo + * bound: true + * description: Specifies how to distribute extra space when the split pane + * resizes. + */ + public void setResizeWeight(double value) { + if (value < 0 || value > 1) { + throw new IllegalArgumentException("JSplitPane weight must be between 0 and 1"); + } + double oldWeight = resizeWeight; + + resizeWeight = value; + firePropertyChange(RESIZE_WEIGHT_PROPERTY, oldWeight, value); + } + + /** + * Returns the number that determines how extra space is distributed. + * @return how extra space is to be distributed on a resize of the + * split pane + * @since 1.3 + */ + public double getResizeWeight() { + return resizeWeight; + } + + /** + * Lays out the JSplitPane layout based on the preferred size + * of the children components. This will likely result in changing + * the divider location. + */ + public void resetToPreferredSizes() { + SplitPaneUI ui = getUI(); + + if (ui != null) { + ui.resetToPreferredSizes(this); + } + } + + + /** + * Sets the divider location as a percentage of the + * JSplitPane's size. + *

+ * This method is implemented in terms of + * setDividerLocation(int). + * This method immediately changes the size of the split pane based on + * its current size. If the split pane is not correctly realized and on + * screen, this method will have no effect (new divider location will + * become (current size * proportionalLocation) which is 0). + * + * @param proportionalLocation a double-precision floating point value + * that specifies a percentage, from zero (top/left) to 1.0 + * (bottom/right) + * @exception IllegalArgumentException if the specified location is < 0 + * or > 1.0 + * @beaninfo + * description: The location of the divider. + */ + public void setDividerLocation(double proportionalLocation) { + if (proportionalLocation < 0.0 || + proportionalLocation > 1.0) { + throw new IllegalArgumentException("proportional location must " + + "be between 0.0 and 1.0."); + } + if (getOrientation() == VERTICAL_SPLIT) { + setDividerLocation((int)((double)(getHeight() - getDividerSize()) * + proportionalLocation)); + } else { + setDividerLocation((int)((double)(getWidth() - getDividerSize()) * + proportionalLocation)); + } + } + + + /** + * Sets the location of the divider. This is passed off to the + * look and feel implementation, and then listeners are notified. A value + * less than 0 implies the divider should be reset to a value that + * attempts to honor the preferred size of the left/top component. + * After notifying the listeners, the last divider location is updated, + * via setLastDividerLocation. + * + * @param location an int specifying a UI-specific value (typically a + * pixel count) + * @beaninfo + * bound: true + * description: The location of the divider. + */ + public void setDividerLocation(int location) { + int oldValue = dividerLocation; + + dividerLocation = location; + + // Notify UI. + SplitPaneUI ui = getUI(); + + if (ui != null) { + ui.setDividerLocation(this, location); + } + + // Then listeners + firePropertyChange(DIVIDER_LOCATION_PROPERTY, oldValue, location); + + // And update the last divider location. + setLastDividerLocation(oldValue); + } + + + /** + * Returns the last value passed to setDividerLocation. + * The value returned from this method may differ from the actual + * divider location (if setDividerLocation was passed a + * value bigger than the curent size). + * + * @return an integer specifying the location of the divider + */ + public int getDividerLocation() { + return dividerLocation; + } + + + /** + * Returns the minimum location of the divider from the look and feel + * implementation. + * + * @return an integer specifying a UI-specific value for the minimum + * location (typically a pixel count); or -1 if the UI is + * null + * @beaninfo + * description: The minimum location of the divider from the L&F. + */ + public int getMinimumDividerLocation() { + SplitPaneUI ui = getUI(); + + if (ui != null) { + return ui.getMinimumDividerLocation(this); + } + return -1; + } + + + /** + * Returns the maximum location of the divider from the look and feel + * implementation. + * + * @return an integer specifying a UI-specific value for the maximum + * location (typically a pixel count); or -1 if the UI is + * null + */ + public int getMaximumDividerLocation() { + SplitPaneUI ui = getUI(); + + if (ui != null) { + return ui.getMaximumDividerLocation(this); + } + return -1; + } + + + /** + * Removes the child component, component from the + * pane. Resets the leftComponent or + * rightComponent instance variable, as necessary. + * + * @param component the Component to remove + */ + public void remove(Component component) { + if (component == leftComponent) { + leftComponent = null; + } else if (component == rightComponent) { + rightComponent = null; + } + super.remove(component); + + // Update the JSplitPane on the screen + revalidate(); + repaint(); + } + + + /** + * Removes the Component at the specified index. + * Updates the leftComponent and rightComponent + * instance variables as necessary, and then messages super. + * + * @param index an integer specifying the component to remove, where + * 1 specifies the left/top component and 2 specifies the + * bottom/right component + */ + public void remove(int index) { + Component comp = getComponent(index); + + if (comp == leftComponent) { + leftComponent = null; + } else if (comp == rightComponent) { + rightComponent = null; + } + super.remove(index); + + // Update the JSplitPane on the screen + revalidate(); + repaint(); + } + + + /** + * Removes all the child components from the split pane. Resets the + * leftComonent and rightComponent + * instance variables. + */ + public void removeAll() { + leftComponent = rightComponent = null; + super.removeAll(); + + // Update the JSplitPane on the screen + revalidate(); + repaint(); + } + + + /** + * Returns true, so that calls to revalidate + * on any descendant of this JSplitPane + * will cause a request to be queued that + * will validate the JSplitPane and all its descendants. + * + * @return true + * @see JComponent#revalidate + * + * @beaninfo + * hidden: true + */ + public boolean isValidateRoot() { + return true; + } + + + /** + * Adds the specified component to this split pane. + * If constraints identifies the left/top or + * right/bottom child component, and a component with that identifier + * was previously added, it will be removed and then comp + * will be added in its place. If constraints is not + * one of the known identifiers the layout manager may throw an + * IllegalArgumentException. + *

+ * The possible constraints objects (Strings) are: + *

+ * If the constraints object is null, + * the component is added in the + * first available position (left/top if open, else right/bottom). + * + * @param comp the component to add + * @param constraints an Object specifying the + * layout constraints + * (position) for this component + * @param index an integer specifying the index in the container's + * list. + * @exception IllegalArgumentException if the constraints + * object does not match an existing component + * @see java.awt.Container#addImpl(Component, Object, int) + */ + protected void addImpl(Component comp, Object constraints, int index) + { + Component toRemove; + + if (constraints != null && !(constraints instanceof String)) { + throw new IllegalArgumentException("cannot add to layout: " + + "constraint must be a string " + + "(or null)"); + } + + /* If the constraints are null and the left/right component is + invalid, add it at the left/right component. */ + if (constraints == null) { + if (getLeftComponent() == null) { + constraints = JSplitPane.LEFT; + } else if (getRightComponent() == null) { + constraints = JSplitPane.RIGHT; + } + } + + /* Find the Component that already exists and remove it. */ + if (constraints != null && (constraints.equals(JSplitPane.LEFT) || + constraints.equals(JSplitPane.TOP))) { + toRemove = getLeftComponent(); + if (toRemove != null) { + remove(toRemove); + } + leftComponent = comp; + index = -1; + } else if (constraints != null && + (constraints.equals(JSplitPane.RIGHT) || + constraints.equals(JSplitPane.BOTTOM))) { + toRemove = getRightComponent(); + if (toRemove != null) { + remove(toRemove); + } + rightComponent = comp; + index = -1; + } else if (constraints != null && + constraints.equals(JSplitPane.DIVIDER)) { + index = -1; + } + /* LayoutManager should raise for else condition here. */ + + super.addImpl(comp, constraints, index); + + // Update the JSplitPane on the screen + revalidate(); + repaint(); + } + + + /** + * Subclassed to message the UI with finishedPaintingChildren + * after super has been messaged, as well as painting the border. + * + * @param g the Graphics context within which to paint + */ + protected void paintChildren(Graphics g) { + super.paintChildren(g); + + SplitPaneUI ui = getUI(); + + if (ui != null) { + Graphics tempG = g.create(); + ui.finishedPaintingChildren(this, tempG); + tempG.dispose(); + } + } + + + /** + * See readObject and writeObject in + * JComponent for more + * information about serialization in Swing. + */ + private void writeObject(ObjectOutputStream s) throws IOException { + s.defaultWriteObject(); + if (getUIClassID().equals(uiClassID)) { + byte count = JComponent.getWriteObjCounter(this); + JComponent.setWriteObjCounter(this, --count); + if (count == 0 && ui != null) { + ui.installUI(this); + } + } + } + + void setUIProperty(String propertyName, Object value) { + if (propertyName == "dividerSize") { + if (!dividerSizeSet) { + setDividerSize(((Number)value).intValue()); + dividerSizeSet = false; + } + } else if (propertyName == "oneTouchExpandable") { + if (!oneTouchExpandableSet) { + setOneTouchExpandable(((Boolean)value).booleanValue()); + oneTouchExpandableSet = false; + } + } else { + super.setUIProperty(propertyName, value); + } + } + + + /** + * Returns a string representation of this JSplitPane. + * This method + * is intended to be used only for debugging purposes, and the + * content and format of the returned string may vary between + * implementations. The returned string may be empty but may not + * be null. + * + * @return a string representation of this JSplitPane. + */ + protected String paramString() { + String orientationString = (orientation == HORIZONTAL_SPLIT ? + "HORIZONTAL_SPLIT" : "VERTICAL_SPLIT"); + String continuousLayoutString = (continuousLayout ? + "true" : "false"); + String oneTouchExpandableString = (oneTouchExpandable ? + "true" : "false"); + + return super.paramString() + + ",continuousLayout=" + continuousLayoutString + + ",dividerSize=" + dividerSize + + ",lastDividerLocation=" + lastDividerLocation + + ",oneTouchExpandable=" + oneTouchExpandableString + + ",orientation=" + orientationString; + } + + + + /////////////////////////// + // Accessibility support // + /////////////////////////// + + + /** + * Gets the AccessibleContext associated with this JSplitPane. + * For split panes, the AccessibleContext takes the form of an + * AccessibleJSplitPane. + * A new AccessibleJSplitPane instance is created if necessary. + * + * @return an AccessibleJSplitPane that serves as the + * AccessibleContext of this JSplitPane + * @beaninfo + * expert: true + * description: The AccessibleContext associated with this SplitPane. + */ + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleJSplitPane(); + } + return accessibleContext; + } + + + /** + * This class implements accessibility support for the + * JSplitPane class. It provides an implementation of the + * Java Accessibility API appropriate to split pane user-interface elements. + *

+ * Warning: + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of Swing. As of 1.4, support for long term storage + * of all JavaBeansTM + * has been added to the java.beans package. + * Please see {@link java.beans.XMLEncoder}. + */ + protected class AccessibleJSplitPane extends AccessibleJComponent + implements AccessibleValue { + /** + * Gets the state set of this object. + * + * @return an instance of AccessibleState containing the current state + * of the object + * @see AccessibleState + */ + public AccessibleStateSet getAccessibleStateSet() { + AccessibleStateSet states = super.getAccessibleStateSet(); + // FIXME: [[[WDW - Should also add BUSY if this implements + // Adjustable at some point. If this happens, we probably + // should also add actions.]]] + if (getOrientation() == VERTICAL_SPLIT) { + states.add(AccessibleState.VERTICAL); + } else { + states.add(AccessibleState.HORIZONTAL); + } + return states; + } + + + /** + * Get the AccessibleValue associated with this object. In the + * implementation of the Java Accessibility API for this class, + * return this object, which is responsible for implementing the + * AccessibleValue interface on behalf of itself. + * + * @return this object + */ + public AccessibleValue getAccessibleValue() { + return this; + } + + + /** + * Gets the accessible value of this object. + * + * @return a localized String describing the value of this object + */ + public Number getCurrentAccessibleValue() { + return new Integer(getDividerLocation()); + } + + + /** + * Sets the value of this object as a Number. + * + * @return True if the value was set. + */ + public boolean setCurrentAccessibleValue(Number n) { + // TIGER - 4422535 + if (n == null) { + return false; + } + setDividerLocation(n.intValue()); + return true; + } + + + /** + * Gets the minimum accessible value of this object. + * + * @return The minimum value of this object. + */ + public Number getMinimumAccessibleValue() { + return new Integer(getUI().getMinimumDividerLocation( + JSplitPane.this)); + } + + + /** + * Gets the maximum accessible value of this object. + * + * @return The maximum value of this object. + */ + public Number getMaximumAccessibleValue() { + return new Integer(getUI().getMaximumDividerLocation( + JSplitPane.this)); + } + + + /** + * Gets the role of this object. + * + * @return an instance of AccessibleRole describing the role of + * the object + * @see AccessibleRole + */ + public AccessibleRole getAccessibleRole() { + return AccessibleRole.SPLIT_PANE; + } + } // inner class AccessibleJSplitPane +}