KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > JSplitPane


1 /*
2  * @(#)JSplitPane.java 1.76 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8
9
10 package javax.swing;
11
12
13
14 import javax.swing.border.Border JavaDoc;
15 import javax.swing.plaf.*;
16 import javax.accessibility.*;
17
18 import java.awt.*;
19
20 import java.io.ObjectOutputStream JavaDoc;
21 import java.io.ObjectInputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23
24
25
26 /**
27  * <code>JSplitPane</code> is used to divide two (and only two)
28  * <code>Component</code>s. The two <code>Component</code>s
29  * are graphically divided based on the look and feel
30  * implementation, and the two <code>Component</code>s can then be
31  * interactively resized by the user.
32  * Information on using <code>JSplitPane</code> is in
33  * <a
34  href="http://java.sun.com/docs/books/tutorial/uiswing/components/splitpane.html">How to Use Split Panes</a> in
35  * <em>The Java Tutorial</em>.
36  * <p>
37  * The two <code>Component</code>s in a split pane can be aligned
38  * left to right using
39  * <code>JSplitPane.HORIZONTAL_SPLIT</code>, or top to bottom using
40  * <code>JSplitPane.VERTICAL_SPLIT</code>.
41  * The preferred way to change the size of the <code>Component</code>s
42  * is to invoke
43  * <code>setDividerLocation</code> where <code>location</code> is either
44  * the new x or y position, depending on the orientation of the
45  * <code>JSplitPane</code>.
46  * <p>
47  * To resize the <code>Component</code>s to their preferred sizes invoke
48  * <code>resetToPreferredSizes</code>.
49  * <p>
50  * When the user is resizing the <code>Component</code>s the minimum
51  * size of the <code>Components</code> is used to determine the
52  * maximum/minimum position the <code>Component</code>s
53  * can be set to. If the minimum size of the two
54  * components is greater than the size of the split pane the divider
55  * will not allow you to resize it. To alter the minimum size of a
56  * <code>JComponent</code>, see {@link JComponent#setMinimumSize}.
57  * <p>
58  * When the user resizes the split pane the new space is distributed between
59  * the two components based on the <code>resizeWeight</code> property.
60  * A value of 0,
61  * the default, indicates the right/bottom component gets all the space,
62  * where as a value of 1 indicates the left/top component gets all the space.
63  * <p>
64  * <strong>Warning:</strong>
65  * Serialized objects of this class will not be compatible with
66  * future Swing releases. The current serialization support is
67  * appropriate for short term storage or RMI between applications running
68  * the same version of Swing. As of 1.4, support for long term storage
69  * of all JavaBeans<sup><font size="-2">TM</font></sup>
70  * has been added to the <code>java.beans</code> package.
71  * Please see {@link java.beans.XMLEncoder}.
72  *
73  * @see #setDividerLocation
74  * @see #resetToPreferredSizes
75  *
76  * @version 1.76 12/19/03
77  * @author Scott Violet
78  */

79 public class JSplitPane extends JComponent JavaDoc implements Accessible
80 {
81     /**
82      * @see #getUIClassID
83      * @see #readObject
84      */

85     private static final String JavaDoc uiClassID = "SplitPaneUI";
86
87     /**
88      * Vertical split indicates the <code>Component</code>s are
89      * split along the y axis. For example the two
90      * <code>Component</code>s will be split one on top of the other.
91      */

92     public final static int VERTICAL_SPLIT = 0;
93
94     /**
95      * Horizontal split indicates the <code>Component</code>s are
96      * split along the x axis. For example the two
97      * <code>Component</code>s will be split one to the left of the
98      * other.
99      */

100     public final static int HORIZONTAL_SPLIT = 1;
101
102     /**
103      * Used to add a <code>Component</code> to the left of the other
104      * <code>Component</code>.
105      */

106     public final static String JavaDoc LEFT = "left";
107
108     /**
109      * Used to add a <code>Component</code> to the right of the other
110      * <code>Component</code>.
111      */

112     public final static String JavaDoc RIGHT = "right";
113
114     /**
115      * Used to add a <code>Component</code> above the other
116      * <code>Component</code>.
117      */

118     public final static String JavaDoc TOP = "top";
119
120     /**
121      * Used to add a <code>Component</code> below the other
122      * <code>Component</code>.
123      */

124     public final static String JavaDoc BOTTOM = "bottom";
125
126     /**
127      * Used to add a <code>Component</code> that will represent the divider.
128      */

129     public final static String JavaDoc DIVIDER = "divider";
130
131     /**
132      * Bound property name for orientation (horizontal or vertical).
133      */

134     public final static String JavaDoc ORIENTATION_PROPERTY = "orientation";
135
136     /**
137      * Bound property name for continuousLayout.
138      */

139     public final static String JavaDoc CONTINUOUS_LAYOUT_PROPERTY = "continuousLayout";
140
141     /**
142      * Bound property name for border.
143      */

144     public final static String JavaDoc DIVIDER_SIZE_PROPERTY = "dividerSize";
145
146     /**
147      * Bound property for oneTouchExpandable.
148      */

149     public final static String JavaDoc ONE_TOUCH_EXPANDABLE_PROPERTY =
150                                "oneTouchExpandable";
151
152     /**
153      * Bound property for lastLocation.
154      */

155     public final static String JavaDoc LAST_DIVIDER_LOCATION_PROPERTY =
156                                "lastDividerLocation";
157
158     /**
159      * Bound property for the dividerLocation.
160      * @since 1.3
161      */

162     public final static String JavaDoc DIVIDER_LOCATION_PROPERTY = "dividerLocation";
163
164     /**
165      * Bound property for weight.
166      * @since 1.3.
167      */

168     public final static String JavaDoc RESIZE_WEIGHT_PROPERTY = "resizeWeight";
169
170     /**
171      * How the views are split.
172      */

173     protected int orientation;
174
175     /**
176      * Whether or not the views are continuously redisplayed while
177      * resizing.
178      */

179     protected boolean continuousLayout;
180
181     /**
182      * The left or top component.
183      */

184     protected Component leftComponent;
185
186     /**
187      * The right or bottom component.
188      */

189     protected Component rightComponent;
190
191     /**
192      * Size of the divider.
193      */

194     protected int dividerSize;
195     private boolean dividerSizeSet = false;
196
197     /**
198      * Is a little widget provided to quickly expand/collapse the
199      * split pane?
200      */

201     protected boolean oneTouchExpandable;
202     private boolean oneTouchExpandableSet;
203
204     /**
205      * Previous location of the split pane.
206      */

207     protected int lastDividerLocation;
208
209     /**
210      * How to distribute extra space.
211      */

212     private double resizeWeight;
213
214     /**
215      * Location of the divider, at least the value that was set, the UI may
216      * have a different value.
217      */

218     private int dividerLocation;
219
220
221     /**
222      * Creates a new <code>JSplitPane</code> configured to arrange the child
223      * components side-by-side horizontally with no continuous
224      * layout, using two buttons for the components.
225      */

226     public JSplitPane() {
227         this(JSplitPane.HORIZONTAL_SPLIT, false,
228             new JButton JavaDoc(UIManager.getString("SplitPane.leftButtonText")),
229             new JButton JavaDoc(UIManager.getString("SplitPane.rightButtonText")));
230     }
231
232
233     /**
234      * Creates a new <code>JSplitPane</code> configured with the
235      * specified orientation and no continuous layout.
236      *
237      * @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
238      * <code>JSplitPane.VERTICAL_SPLIT</code>
239      * @exception IllegalArgumentException if <code>orientation</code>
240      * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT.
241      */

242     public JSplitPane(int newOrientation) {
243         this(newOrientation, false);
244     }
245
246
247     /**
248      * Creates a new <code>JSplitPane</code> with the specified
249      * orientation and redrawing style.
250      *
251      * @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
252      * <code>JSplitPane.VERTICAL_SPLIT</code>
253      * @param newContinuousLayout a boolean, true for the components to
254      * redraw continuously as the divider changes position, false
255      * to wait until the divider position stops changing to redraw
256      * @exception IllegalArgumentException if <code>orientation</code>
257      * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
258      */

259     public JSplitPane(int newOrientation,
260                       boolean newContinuousLayout) {
261         this(newOrientation, newContinuousLayout, null, null);
262     }
263
264
265     /**
266      * Creates a new <code>JSplitPane</code> with the specified
267      * orientation and
268      * with the specified components that do not do continuous
269      * redrawing.
270      *
271      * @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
272      * <code>JSplitPane.VERTICAL_SPLIT</code>
273      * @param newLeftComponent the <code>Component</code> that will
274      * appear on the left
275      * of a horizontally-split pane, or at the top of a
276      * vertically-split pane
277      * @param newRightComponent the <code>Component</code> that will
278      * appear on the right
279      * of a horizontally-split pane, or at the bottom of a
280      * vertically-split pane
281      * @exception IllegalArgumentException if <code>orientation</code>
282      * is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT
283      */

284     public JSplitPane(int newOrientation,
285                       Component newLeftComponent,
286                       Component newRightComponent){
287         this(newOrientation, false, newLeftComponent, newRightComponent);
288     }
289
290
291     /**
292      * Creates a new <code>JSplitPane</code> with the specified
293      * orientation and
294      * redrawing style, and with the specified components.
295      *
296      * @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
297      * <code>JSplitPane.VERTICAL_SPLIT</code>
298      * @param newContinuousLayout a boolean, true for the components to
299      * redraw continuously as the divider changes position, false
300      * to wait until the divider position stops changing to redraw
301      * @param newLeftComponent the <code>Component</code> that will
302      * appear on the left
303      * of a horizontally-split pane, or at the top of a
304      * vertically-split pane
305      * @param newRightComponent the <code>Component</code> that will
306      * appear on the right
307      * of a horizontally-split pane, or at the bottom of a
308      * vertically-split pane
309      * @exception IllegalArgumentException if <code>orientation</code>
310      * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
311      */

312     public JSplitPane(int newOrientation,
313                       boolean newContinuousLayout,
314                       Component newLeftComponent,
315                       Component newRightComponent){
316         super();
317
318     dividerLocation = -1;
319         setLayout(null);
320     setUIProperty("opaque", Boolean.TRUE);
321         orientation = newOrientation;
322         if (orientation != HORIZONTAL_SPLIT && orientation != VERTICAL_SPLIT)
323             throw new IllegalArgumentException JavaDoc("cannot create JSplitPane, " +
324                                                "orientation must be one of " +
325                                                "JSplitPane.HORIZONTAL_SPLIT " +
326                                                "or JSplitPane.VERTICAL_SPLIT");
327         continuousLayout = newContinuousLayout;
328         if (newLeftComponent != null)
329             setLeftComponent(newLeftComponent);
330         if (newRightComponent != null)
331             setRightComponent(newRightComponent);
332         updateUI();
333
334     }
335
336
337     /**
338      * Sets the L&F object that renders this component.
339      *
340      * @param ui the <code>SplitPaneUI</code> L&F object
341      * @see UIDefaults#getUI
342      * @beaninfo
343      * bound: true
344      * hidden: true
345      * attribute: visualUpdate true
346      * description: The UI object that implements the Component's LookAndFeel.
347      */

348     public void setUI(SplitPaneUI ui) {
349         if ((SplitPaneUI)this.ui != ui) {
350             super.setUI(ui);
351             revalidate();
352         }
353     }
354
355
356     /**
357      * Returns the <code>SplitPaneUI</code> that is providing the
358      * current look and feel.
359      *
360      * @return the <code>SplitPaneUI</code> object that renders this component
361      * @beaninfo
362      * expert: true
363      * description: The L&F object that renders this component.
364      */

365     public SplitPaneUI getUI() {
366         return (SplitPaneUI)ui;
367     }
368
369
370     /**
371      * Notification from the <code>UIManager</code> that the L&F has changed.
372      * Replaces the current UI object with the latest version from the
373      * <code>UIManager</code>.
374      *
375      * @see JComponent#updateUI
376      */

377     public void updateUI() {
378         setUI((SplitPaneUI)UIManager.getUI(this));
379         revalidate();
380     }
381
382
383     /**
384      * Returns the name of the L&F class that renders this component.
385      *
386      * @return the string "SplitPaneUI"
387      * @see JComponent#getUIClassID
388      * @see UIDefaults#getUI
389      * @beaninfo
390      * expert: true
391      * description: A string that specifies the name of the L&F class.
392      */

393     public String JavaDoc getUIClassID() {
394         return uiClassID;
395     }
396
397
398     /**
399      * Sets the size of the divider.
400      *
401      * @param newSize an integer giving the size of the divider in pixels
402      * @beaninfo
403      * bound: true
404      * description: The size of the divider.
405      */

406     public void setDividerSize(int newSize) {
407         int oldSize = dividerSize;
408
409     dividerSizeSet = true;
410         if (oldSize != newSize) {
411             dividerSize = newSize;
412             firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, newSize);
413         }
414     }
415
416
417     /**
418      * Returns the size of the divider.
419      *
420      * @return an integer giving the size of the divider in pixels
421      */

422     public int getDividerSize() {
423         return dividerSize;
424     }
425
426
427     /**
428      * Sets the component to the left (or above) the divider.
429      *
430      * @param comp the <code>Component</code> to display in that position
431      */

432     public void setLeftComponent(Component comp) {
433         if (comp == null) {
434             if (leftComponent != null) {
435                 remove(leftComponent);
436                 leftComponent = null;
437             }
438         } else {
439             add(comp, JSplitPane.LEFT);
440         }
441     }
442
443
444     /**
445      * Returns the component to the left (or above) the divider.
446      *
447      * @return the <code>Component</code> displayed in that position
448      * @beaninfo
449      * preferred: true
450      * description: The component to the left (or above) the divider.
451      */

452     public Component getLeftComponent() {
453         return leftComponent;
454     }
455
456
457     /**
458      * Sets the component above, or to the left of the divider.
459      *
460      * @param comp the <code>Component</code> to display in that position
461      * @beaninfo
462      * description: The component above, or to the left of the divider.
463      */

464     public void setTopComponent(Component comp) {
465         setLeftComponent(comp);
466     }
467
468
469     /**
470      * Returns the component above, or to the left of the divider.
471      *
472      * @return the <code>Component</code> displayed in that position
473      */

474     public Component getTopComponent() {
475         return leftComponent;
476     }
477
478
479     /**
480      * Sets the component to the right (or below) the divider.
481      *
482      * @param comp the <code>Component</code> to display in that position
483      * @beaninfo
484      * preferred: true
485      * description: The component to the right (or below) the divider.
486      */

487     public void setRightComponent(Component comp) {
488         if (comp == null) {
489             if (rightComponent != null) {
490                 remove(rightComponent);
491                 rightComponent = null;
492             }
493         } else {
494             add(comp, JSplitPane.RIGHT);
495         }
496     }
497
498
499     /**
500      * Returns the component to the right (or below) the divider.
501      *
502      * @return the <code>Component</code> displayed in that position
503      */

504     public Component getRightComponent() {
505         return rightComponent;
506     }
507
508
509     /**
510      * Sets the component below, or to the right of the divider.
511      *
512      * @param comp the <code>Component</code> to display in that position
513      * @beaninfo
514      * description: The component below, or to the right of the divider.
515      */

516     public void setBottomComponent(Component comp) {
517         setRightComponent(comp);
518     }
519
520
521     /**
522      * Returns the component below, or to the right of the divider.
523      *
524      * @return the <code>Component</code> displayed in that position
525      */

526     public Component getBottomComponent() {
527         return rightComponent;
528     }
529
530
531     /**
532      * Sets the value of the <code>oneTouchExpandable</code> property,
533      * which must be <code>true</code> for the
534      * <code>JSplitPane</code> to provide a UI widget
535      * on the divider to quickly expand/collapse the divider.
536      * The default value of this property is <code>false</code>.
537      * Some look and feels might not support one-touch expanding;
538      * they will ignore this property.
539      *
540      * @param newValue <code>true</code> to specify that the split pane should provide a
541      * collapse/expand widget
542      * @beaninfo
543      * bound: true
544      * description: UI widget on the divider to quickly
545      * expand/collapse the divider.
546      *
547      * @see #isOneTouchExpandable
548      */

549     public void setOneTouchExpandable(boolean newValue) {
550         boolean oldValue = oneTouchExpandable;
551
552         oneTouchExpandable = newValue;
553         oneTouchExpandableSet = true;
554         firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue, newValue);
555         repaint();
556     }
557
558
559     /**
560      * Gets the <code>oneTouchExpandable</code> property.
561      *
562      * @return the value of the <code>oneTouchExpandable</code> property
563      * @see #setOneTouchExpandable
564      */

565     public boolean isOneTouchExpandable() {
566         return oneTouchExpandable;
567     }
568
569
570     /**
571      * Sets the last location the divider was at to
572      * <code>newLastLocation</code>.
573      *
574      * @param newLastLocation an integer specifying the last divider location
575      * in pixels, from the left (or upper) edge of the pane to the
576      * left (or upper) edge of the divider
577      * @beaninfo
578      * bound: true
579      * description: The last location the divider was at.
580      */

581     public void setLastDividerLocation(int newLastLocation) {
582         int oldLocation = lastDividerLocation;
583
584         lastDividerLocation = newLastLocation;
585         firePropertyChange(LAST_DIVIDER_LOCATION_PROPERTY, oldLocation,
586                            newLastLocation);
587     }
588     
589
590     /**
591      * Returns the last location the divider was at.
592      *
593      * @return an integer specifying the last divider location as a count
594      * of pixels from the left (or upper) edge of the pane to the
595      * left (or upper) edge of the divider
596      */

597     public int getLastDividerLocation() {
598         return lastDividerLocation;
599     }
600
601
602     /**
603      * Sets the orientation, or how the splitter is divided. The options
604      * are:<ul>
605      * <li>JSplitPane.VERTICAL_SPLIT (above/below orientation of components)
606      * <li>JSplitPane.HORIZONTAL_SPLIT (left/right orientation of components)
607      * </ul>
608      *
609      * @param orientation an integer specifying the orientation
610      * @exception IllegalArgumentException if orientation is not one of:
611      * HORIZONTAL_SPLIT or VERTICAL_SPLIT.
612      * @beaninfo
613      * bound: true
614      * description: The orientation, or how the splitter is divided.
615      * enum: HORIZONTAL_SPLIT JSplitPane.HORIZONTAL_SPLIT
616      * VERTICAL_SPLIT JSplitPane.VERTICAL_SPLIT
617      */

618     public void setOrientation(int orientation) {
619         if ((orientation != VERTICAL_SPLIT) &&
620             (orientation != HORIZONTAL_SPLIT)) {
621            throw new IllegalArgumentException JavaDoc("JSplitPane: orientation must " +
622                                               "be one of " +
623                                               "JSplitPane.VERTICAL_SPLIT or " +
624                                               "JSplitPane.HORIZONTAL_SPLIT");
625         }
626
627         int oldOrientation = this.orientation;
628
629         this.orientation = orientation;
630         firePropertyChange(ORIENTATION_PROPERTY, oldOrientation, orientation);
631     }
632
633
634     /**
635      * Returns the orientation.
636      *
637      * @return an integer giving the orientation
638      * @see #setOrientation
639      */

640     public int getOrientation() {
641         return orientation;
642     }
643
644
645     /**
646      * Sets the value of the <code>continuousLayout</code> property,
647      * which must be <code>true</code> for the child components
648      * to be continuously
649      * redisplayed and laid out during user intervention.
650      * The default value of this property is <code>false</code>.
651      * Some look and feels might not support continuous layout;
652      * they will ignore this property.
653      *
654      * @param newContinuousLayout <code>true</code> if the components
655      * should continuously be redrawn as the divider changes position
656      * @beaninfo
657      * bound: true
658      * description: Whether the child components are
659      * continuously redisplayed and laid out during
660      * user intervention.
661      * @see #isContinuousLayout
662      */

663     public void setContinuousLayout(boolean newContinuousLayout) {
664         boolean oldCD = continuousLayout;
665
666         continuousLayout = newContinuousLayout;
667         firePropertyChange(CONTINUOUS_LAYOUT_PROPERTY, oldCD,
668                            newContinuousLayout);
669     }
670
671
672     /**
673      * Gets the <code>continuousLayout</code> property.
674      *
675      * @return the value of the <code>continuousLayout</code> property
676      * @see #setContinuousLayout
677      */

678     public boolean isContinuousLayout() {
679         return continuousLayout;
680     }
681
682     /**
683      * Specifies how to distribute extra space when the size of the split pane
684      * changes. A value of 0, the default,
685      * indicates the right/bottom component gets all the extra space (the
686      * left/top component acts fixed), where as a value of 1 specifies the
687      * left/top component gets all the extra space (the right/bottom component
688      * acts fixed). Specifically, the left/top component gets (weight * diff)
689      * extra space and the right/bottom component gets (1 - weight) * diff
690      * extra space.
691      *
692      * @param value as described above
693      * @exception IllegalArgumentException if <code>value</code> is < 0 or > 1
694      * @since 1.3
695      * @beaninfo
696      * bound: true
697      * description: Specifies how to distribute extra space when the split pane
698      * resizes.
699      */

700     public void setResizeWeight(double value) {
701     if (value < 0 || value > 1) {
702         throw new IllegalArgumentException JavaDoc("JSplitPane weight must be between 0 and 1");
703     }
704     double oldWeight = resizeWeight;
705
706     resizeWeight = value;
707     firePropertyChange(RESIZE_WEIGHT_PROPERTY, oldWeight, value);
708     }
709
710     /**
711      * Returns the number that determines how extra space is distributed.
712      * @return how extra space is to be distributed on a resize of the
713      * split pane
714      * @since 1.3
715      */

716     public double getResizeWeight() {
717     return resizeWeight;
718     }
719
720     /**
721      * Lays out the <code>JSplitPane</code> layout based on the preferred size
722      * of the children components. This will likely result in changing
723      * the divider location.
724      */

725     public void resetToPreferredSizes() {
726         SplitPaneUI ui = getUI();
727
728         if (ui != null) {
729             ui.resetToPreferredSizes(this);
730         }
731     }
732
733
734     /**
735      * Sets the divider location as a percentage of the
736      * <code>JSplitPane</code>'s size.
737      * <p>
738      * This method is implemented in terms of
739      * <code>setDividerLocation(int)</code>.
740      * This method immediately changes the size of the split pane based on
741      * its current size. If the split pane is not correctly realized and on
742      * screen, this method will have no effect (new divider location will
743      * become (current size * proportionalLocation) which is 0).
744      *
745      * @param proportionalLocation a double-precision floating point value
746      * that specifies a percentage, from zero (top/left) to 1.0
747      * (bottom/right)
748      * @exception IllegalArgumentException if the specified location is < 0
749      * or > 1.0
750      * @beaninfo
751      * description: The location of the divider.
752      */

753     public void setDividerLocation(double proportionalLocation) {
754         if (proportionalLocation < 0.0 ||
755            proportionalLocation > 1.0) {
756             throw new IllegalArgumentException JavaDoc("proportional location must " +
757                                                "be between 0.0 and 1.0.");
758         }
759         if (getOrientation() == VERTICAL_SPLIT) {
760             setDividerLocation((int)((double)(getHeight() - getDividerSize()) *
761                                      proportionalLocation));
762         } else {
763             setDividerLocation((int)((double)(getWidth() - getDividerSize()) *
764                                      proportionalLocation));
765         }
766     }
767
768
769     /**
770      * Sets the location of the divider. This is passed off to the
771      * look and feel implementation, and then listeners are notified. A value
772      * less than 0 implies the divider should be reset to a value that
773      * attempts to honor the preferred size of the left/top component.
774      * After notifying the listeners, the last divider location is updated,
775      * via <code>setLastDividerLocation</code>.
776      *
777      * @param location an int specifying a UI-specific value (typically a
778      * pixel count)
779      * @beaninfo
780      * bound: true
781      * description: The location of the divider.
782      */

783     public void setDividerLocation(int location) {
784     int oldValue = dividerLocation;
785
786     dividerLocation = location;
787
788     // Notify UI.
789
SplitPaneUI ui = getUI();
790
791         if (ui != null) {
792             ui.setDividerLocation(this, location);
793         }
794
795     // Then listeners
796
firePropertyChange(DIVIDER_LOCATION_PROPERTY, oldValue, location);
797
798     // And update the last divider location.
799
setLastDividerLocation(oldValue);
800     }
801
802
803     /**
804      * Returns the last value passed to <code>setDividerLocation</code>.
805      * The value returned from this method may differ from the actual
806      * divider location (if <code>setDividerLocation</code> was passed a
807      * value bigger than the curent size).
808      *
809      * @return an integer specifying the location of the divider
810      */

811     public int getDividerLocation() {
812     return dividerLocation;
813     }
814
815
816     /**
817      * Returns the minimum location of the divider from the look and feel
818      * implementation.
819      *
820      * @return an integer specifying a UI-specific value for the minimum
821      * location (typically a pixel count); or -1 if the UI is
822      * <code>null</code>
823      * @beaninfo
824      * description: The minimum location of the divider from the L&F.
825      */

826     public int getMinimumDividerLocation() {
827         SplitPaneUI ui = getUI();
828
829         if (ui != null) {
830             return ui.getMinimumDividerLocation(this);
831         }
832         return -1;
833     }
834
835
836     /**
837      * Returns the maximum location of the divider from the look and feel
838      * implementation.
839      *
840      * @return an integer specifying a UI-specific value for the maximum
841      * location (typically a pixel count); or -1 if the UI is
842      * <code>null</code>
843      */

844     public int getMaximumDividerLocation() {
845         SplitPaneUI ui = getUI();
846
847         if (ui != null) {
848             return ui.getMaximumDividerLocation(this);
849         }
850         return -1;
851     }
852
853
854     /**
855      * Removes the child component, <code>component</code> from the
856      * pane. Resets the <code>leftComponent</code> or
857      * <code>rightComponent</code> instance variable, as necessary.
858      *
859      * @param component the <code>Component</code> to remove
860      */

861     public void remove(Component component) {
862         if (component == leftComponent) {
863             leftComponent = null;
864         } else if (component == rightComponent) {
865             rightComponent = null;
866         }
867         super.remove(component);
868
869         // Update the JSplitPane on the screen
870
revalidate();
871         repaint();
872     }
873
874
875     /**
876      * Removes the <code>Component</code> at the specified index.
877      * Updates the <code>leftComponent</code> and <code>rightComponent</code>
878      * instance variables as necessary, and then messages super.
879      *
880      * @param index an integer specifying the component to remove, where
881      * 1 specifies the left/top component and 2 specifies the
882      * bottom/right component
883      */

884     public void remove(int index) {
885         Component comp = getComponent(index);
886
887         if (comp == leftComponent) {
888             leftComponent = null;
889         } else if (comp == rightComponent) {
890             rightComponent = null;
891         }
892         super.remove(index);
893
894         // Update the JSplitPane on the screen
895
revalidate();
896         repaint();
897     }
898
899
900     /**
901      * Removes all the child components from the split pane. Resets the
902      * <code>leftComonent</code> and <code>rightComponent</code>
903      * instance variables.
904      */

905     public void removeAll() {
906         leftComponent = rightComponent = null;
907         super.removeAll();
908
909         // Update the JSplitPane on the screen
910
revalidate();
911         repaint();
912     }
913
914
915     /**
916      * Returns true, so that calls to <code>revalidate</code>
917      * on any descendant of this <code>JSplitPane</code>
918      * will cause a request to be queued that
919      * will validate the <code>JSplitPane</code> and all its descendants.
920      *
921      * @return true
922      * @see JComponent#revalidate
923      *
924      * @beaninfo
925      * hidden: true
926      */

927     public boolean isValidateRoot() {
928         return true;
929     }
930
931
932     /**
933      * Adds the specified component to this split pane.
934      * If <code>constraints</code> identifies the left/top or
935      * right/bottom child component, and a component with that identifier
936      * was previously added, it will be removed and then <code>comp</code>
937      * will be added in its place. If <code>constraints</code> is not
938      * one of the known identifiers the layout manager may throw an
939      * <code>IllegalArgumentException</code>.
940      * <p>
941      * The possible constraints objects (Strings) are:
942      * <ul>
943      * <li>JSplitPane.TOP
944      * <li>JSplitPane.LEFT
945      * <li>JSplitPane.BOTTOM
946      * <li>JSplitPane.RIGHT
947      * </ul>
948      * If the <code>constraints</code> object is <code>null</code>,
949      * the component is added in the
950      * first available position (left/top if open, else right/bottom).
951      *
952      * @param comp the component to add
953      * @param constraints an <code>Object</code> specifying the
954      * layout constraints
955      * (position) for this component
956      * @param index an integer specifying the index in the container's
957      * list.
958      * @exception IllegalArgumentException if the <code>constraints</code>
959      * object does not match an existing component
960      * @see java.awt.Container#addImpl(Component, Object, int)
961      */

962     protected void addImpl(Component comp, Object JavaDoc constraints, int index)
963     {
964         Component toRemove;
965
966         if (constraints != null && !(constraints instanceof String JavaDoc)) {
967             throw new IllegalArgumentException JavaDoc("cannot add to layout: " +
968                                                "constraint must be a string " +
969                                                "(or null)");
970         }
971
972         /* If the constraints are null and the left/right component is
973            invalid, add it at the left/right component. */

974         if (constraints == null) {
975             if (getLeftComponent() == null) {
976                 constraints = JSplitPane.LEFT;
977             } else if (getRightComponent() == null) {
978                 constraints = JSplitPane.RIGHT;
979             }
980         }
981             
982         /* Find the Component that already exists and remove it. */
983         if (constraints != null && (constraints.equals(JSplitPane.LEFT) ||
984                                    constraints.equals(JSplitPane.TOP))) {
985             toRemove = getLeftComponent();
986             if (toRemove != null) {
987                 remove(toRemove);
988             }
989             leftComponent = comp;
990             index = -1;
991         } else if (constraints != null &&
992                    (constraints.equals(JSplitPane.RIGHT) ||
993                     constraints.equals(JSplitPane.BOTTOM))) {
994             toRemove = getRightComponent();
995             if (toRemove != null) {
996                 remove(toRemove);
997             }
998             rightComponent = comp;
999             index = -1;
1000        } else if (constraints != null &&
1001                constraints.equals(JSplitPane.DIVIDER)) {
1002            index = -1;
1003        }
1004        /* LayoutManager should raise for else condition here. */
1005
1006        super.addImpl(comp, constraints, index);
1007
1008        // Update the JSplitPane on the screen
1009
revalidate();
1010        repaint();
1011    }
1012
1013
1014    /**
1015     * Subclassed to message the UI with <code>finishedPaintingChildren</code>
1016     * after super has been messaged, as well as painting the border.
1017     *
1018     * @param g the <code>Graphics</code> context within which to paint
1019     */

1020    protected void paintChildren(Graphics g) {
1021        super.paintChildren(g);
1022
1023        SplitPaneUI ui = getUI();
1024
1025        if (ui != null) {
1026            Graphics tempG = g.create();
1027            ui.finishedPaintingChildren(this, tempG);
1028            tempG.dispose();
1029        }
1030    }
1031
1032
1033    /**
1034     * See <code>readObject</code> and <code>writeObject</code> in
1035     * <code>JComponent</code> for more
1036     * information about serialization in Swing.
1037     */

1038    private void writeObject(ObjectOutputStream JavaDoc s) throws IOException JavaDoc {
1039        s.defaultWriteObject();
1040        if (getUIClassID().equals(uiClassID)) {
1041            byte count = JComponent.getWriteObjCounter(this);
1042            JComponent.setWriteObjCounter(this, --count);
1043            if (count == 0 && ui != null) {
1044                ui.installUI(this);
1045            }
1046        }
1047    }
1048
1049    void setUIProperty(String JavaDoc propertyName, Object JavaDoc value) {
1050        if (propertyName == "dividerSize") {
1051        if (!dividerSizeSet) {
1052        setDividerSize(((Number JavaDoc)value).intValue());
1053        dividerSizeSet = false;
1054        }
1055        } else if (propertyName == "oneTouchExpandable") {
1056            if (!oneTouchExpandableSet) {
1057                setOneTouchExpandable(((Boolean JavaDoc)value).booleanValue());
1058                oneTouchExpandableSet = false;
1059            }
1060    } else {
1061        super.setUIProperty(propertyName, value);
1062    }
1063    }
1064
1065
1066    /**
1067     * Returns a string representation of this <code>JSplitPane</code>.
1068     * This method
1069     * is intended to be used only for debugging purposes, and the
1070     * content and format of the returned string may vary between
1071     * implementations. The returned string may be empty but may not
1072     * be <code>null</code>.
1073     *
1074     * @return a string representation of this <code>JSplitPane</code>.
1075     */

1076    protected String JavaDoc paramString() {
1077        String JavaDoc orientationString = (orientation == HORIZONTAL_SPLIT ?
1078                                    "HORIZONTAL_SPLIT" : "VERTICAL_SPLIT");
1079        String JavaDoc continuousLayoutString = (continuousLayout ?
1080                                         "true" : "false");
1081        String JavaDoc oneTouchExpandableString = (oneTouchExpandable ?
1082                                           "true" : "false");
1083
1084        return super.paramString() +
1085        ",continuousLayout=" + continuousLayoutString +
1086        ",dividerSize=" + dividerSize +
1087        ",lastDividerLocation=" + lastDividerLocation +
1088        ",oneTouchExpandable=" + oneTouchExpandableString +
1089        ",orientation=" + orientationString;
1090    }
1091
1092
1093
1094    ///////////////////////////
1095
// Accessibility support //
1096
///////////////////////////
1097

1098
1099    /**
1100     * Gets the AccessibleContext associated with this JSplitPane.
1101     * For split panes, the AccessibleContext takes the form of an
1102     * AccessibleJSplitPane.
1103     * A new AccessibleJSplitPane instance is created if necessary.
1104     *
1105     * @return an AccessibleJSplitPane that serves as the
1106     * AccessibleContext of this JSplitPane
1107     * @beaninfo
1108     * expert: true
1109     * description: The AccessibleContext associated with this SplitPane.
1110     */

1111    public AccessibleContext getAccessibleContext() {
1112        if (accessibleContext == null) {
1113            accessibleContext = new AccessibleJSplitPane();
1114        }
1115        return accessibleContext;
1116    }
1117
1118
1119    /**
1120     * This class implements accessibility support for the
1121     * <code>JSplitPane</code> class. It provides an implementation of the
1122     * Java Accessibility API appropriate to split pane user-interface elements.
1123     * <p>
1124     * <strong>Warning:</strong>
1125     * Serialized objects of this class will not be compatible with
1126     * future Swing releases. The current serialization support is
1127     * appropriate for short term storage or RMI between applications running
1128     * the same version of Swing. As of 1.4, support for long term storage
1129     * of all JavaBeans<sup><font size="-2">TM</font></sup>
1130     * has been added to the <code>java.beans</code> package.
1131     * Please see {@link java.beans.XMLEncoder}.
1132     */

1133    protected class AccessibleJSplitPane extends AccessibleJComponent
1134        implements AccessibleValue {
1135        /**
1136         * Gets the state set of this object.
1137         *
1138         * @return an instance of AccessibleState containing the current state
1139         * of the object
1140         * @see AccessibleState
1141         */

1142        public AccessibleStateSet getAccessibleStateSet() {
1143            AccessibleStateSet states = super.getAccessibleStateSet();
1144            // FIXME: [[[WDW - Should also add BUSY if this implements
1145
// Adjustable at some point. If this happens, we probably
1146
// should also add actions.]]]
1147
if (getOrientation() == VERTICAL_SPLIT) {
1148                states.add(AccessibleState.VERTICAL);
1149            } else {
1150                states.add(AccessibleState.HORIZONTAL);
1151            }
1152            return states;
1153        }
1154    
1155
1156        /**
1157         * Get the AccessibleValue associated with this object. In the
1158         * implementation of the Java Accessibility API for this class,
1159     * return this object, which is responsible for implementing the
1160         * AccessibleValue interface on behalf of itself.
1161     *
1162     * @return this object
1163         */

1164        public AccessibleValue getAccessibleValue() {
1165            return this;
1166        }
1167
1168
1169        /**
1170         * Gets the accessible value of this object.
1171         *
1172         * @return a localized String describing the value of this object
1173         */

1174        public Number JavaDoc getCurrentAccessibleValue() {
1175            return new Integer JavaDoc(getDividerLocation());
1176        }
1177    
1178
1179        /**
1180         * Sets the value of this object as a Number.
1181         *
1182         * @return True if the value was set.
1183         */

1184        public boolean setCurrentAccessibleValue(Number JavaDoc n) {
1185        // TIGER - 4422535
1186
if (n == null) {
1187        return false;
1188        }
1189        setDividerLocation(n.intValue());
1190        return true;
1191        }
1192    
1193
1194        /**
1195         * Gets the minimum accessible value of this object.
1196         *
1197         * @return The minimum value of this object.
1198         */

1199        public Number JavaDoc getMinimumAccessibleValue() {
1200            return new Integer JavaDoc(getUI().getMinimumDividerLocation(
1201                                                        JSplitPane.this));
1202        }
1203    
1204
1205        /**
1206         * Gets the maximum accessible value of this object.
1207         *
1208         * @return The maximum value of this object.
1209         */

1210        public Number JavaDoc getMaximumAccessibleValue() {
1211            return new Integer JavaDoc(getUI().getMaximumDividerLocation(
1212                                                        JSplitPane.this));
1213        }
1214    
1215
1216        /**
1217         * Gets the role of this object.
1218         *
1219         * @return an instance of AccessibleRole describing the role of
1220         * the object
1221         * @see AccessibleRole
1222         */

1223        public AccessibleRole getAccessibleRole() {
1224            return AccessibleRole.SPLIT_PANE;
1225        }
1226    } // inner class AccessibleJSplitPane
1227
}
1228
Popular Tags