1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26
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://docs.oracle.com/javase/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>.
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™
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 * @since 1.2
101 */
102 @SuppressWarnings("serial") // Same-version serialization only
103 public class JSplitPane extends JComponent implements Accessible
104 {
105 /**
106 * @see #getUIClassID
107 * @see #readObject
108 */
109 private static final String uiClassID = "SplitPaneUI";
110
111 /**
112 * Vertical split indicates the <code>Component</code>s are
113 * split along the y axis. For example the two
114 * <code>Component</code>s will be split one on top of the other.
115 */
116 public final static int VERTICAL_SPLIT = 0;
117
118 /**
119 * Horizontal split indicates the <code>Component</code>s are
120 * split along the x axis. For example the two
121 * <code>Component</code>s will be split one to the left of the
348 if (orientation != HORIZONTAL_SPLIT && orientation != VERTICAL_SPLIT)
349 throw new IllegalArgumentException("cannot create JSplitPane, " +
350 "orientation must be one of " +
351 "JSplitPane.HORIZONTAL_SPLIT " +
352 "or JSplitPane.VERTICAL_SPLIT");
353 continuousLayout = newContinuousLayout;
354 if (newLeftComponent != null)
355 setLeftComponent(newLeftComponent);
356 if (newRightComponent != null)
357 setRightComponent(newRightComponent);
358 updateUI();
359
360 }
361
362
363 /**
364 * Sets the L&F object that renders this component.
365 *
366 * @param ui the <code>SplitPaneUI</code> L&F object
367 * @see UIDefaults#getUI
368 * @beaninfo
369 * bound: true
370 * hidden: true
371 * attribute: visualUpdate true
372 * description: The UI object that implements the Component's LookAndFeel.
373 */
374 public void setUI(SplitPaneUI ui) {
375 if ((SplitPaneUI)this.ui != ui) {
376 super.setUI(ui);
377 revalidate();
378 }
379 }
380
381
382 /**
383 * Returns the <code>SplitPaneUI</code> that is providing the
384 * current look and feel.
385 *
386 * @return the <code>SplitPaneUI</code> object that renders this component
387 * @beaninfo
388 * expert: true
389 * description: The L&F object that renders this component.
390 */
391 public SplitPaneUI getUI() {
392 return (SplitPaneUI)ui;
393 }
394
395
396 /**
397 * Notification from the <code>UIManager</code> that the L&F has changed.
398 * Replaces the current UI object with the latest version from the
399 * <code>UIManager</code>.
400 *
401 * @see JComponent#updateUI
402 */
403 public void updateUI() {
404 setUI((SplitPaneUI)UIManager.getUI(this));
405 revalidate();
406 }
407
408
409 /**
410 * Returns the name of the L&F class that renders this component.
411 *
412 * @return the string "SplitPaneUI"
413 * @see JComponent#getUIClassID
414 * @see UIDefaults#getUI
415 * @beaninfo
416 * expert: true
417 * description: A string that specifies the name of the L&F class.
418 */
419 public String getUIClassID() {
420 return uiClassID;
421 }
422
423
424 /**
425 * Sets the size of the divider.
426 *
427 * @param newSize an integer giving the size of the divider in pixels
428 * @beaninfo
429 * bound: true
430 * description: The size of the divider.
431 */
432 public void setDividerSize(int newSize) {
433 int oldSize = dividerSize;
434
435 dividerSizeSet = true;
436 if (oldSize != newSize) {
437 dividerSize = newSize;
438 firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, newSize);
439 }
440 }
441
442
443 /**
444 * Returns the size of the divider.
445 *
446 * @return an integer giving the size of the divider in pixels
447 */
448 public int getDividerSize() {
449 return dividerSize;
450 }
451
454 * Sets the component to the left (or above) the divider.
455 *
456 * @param comp the <code>Component</code> to display in that position
457 */
458 public void setLeftComponent(Component comp) {
459 if (comp == null) {
460 if (leftComponent != null) {
461 remove(leftComponent);
462 leftComponent = null;
463 }
464 } else {
465 add(comp, JSplitPane.LEFT);
466 }
467 }
468
469
470 /**
471 * Returns the component to the left (or above) the divider.
472 *
473 * @return the <code>Component</code> displayed in that position
474 * @beaninfo
475 * preferred: true
476 * description: The component to the left (or above) the divider.
477 */
478 public Component getLeftComponent() {
479 return leftComponent;
480 }
481
482
483 /**
484 * Sets the component above, or to the left of the divider.
485 *
486 * @param comp the <code>Component</code> to display in that position
487 * @beaninfo
488 * description: The component above, or to the left of the divider.
489 */
490 public void setTopComponent(Component comp) {
491 setLeftComponent(comp);
492 }
493
494
495 /**
496 * Returns the component above, or to the left of the divider.
497 *
498 * @return the <code>Component</code> displayed in that position
499 */
500 public Component getTopComponent() {
501 return leftComponent;
502 }
503
504
505 /**
506 * Sets the component to the right (or below) the divider.
507 *
508 * @param comp the <code>Component</code> to display in that position
509 * @beaninfo
510 * preferred: true
511 * description: The component to the right (or below) the divider.
512 */
513 public void setRightComponent(Component comp) {
514 if (comp == null) {
515 if (rightComponent != null) {
516 remove(rightComponent);
517 rightComponent = null;
518 }
519 } else {
520 add(comp, JSplitPane.RIGHT);
521 }
522 }
523
524
525 /**
526 * Returns the component to the right (or below) the divider.
527 *
528 * @return the <code>Component</code> displayed in that position
529 */
530 public Component getRightComponent() {
531 return rightComponent;
532 }
533
534
535 /**
536 * Sets the component below, or to the right of the divider.
537 *
538 * @param comp the <code>Component</code> to display in that position
539 * @beaninfo
540 * description: The component below, or to the right of the divider.
541 */
542 public void setBottomComponent(Component comp) {
543 setRightComponent(comp);
544 }
545
546
547 /**
548 * Returns the component below, or to the right of the divider.
549 *
550 * @return the <code>Component</code> displayed in that position
551 */
552 public Component getBottomComponent() {
553 return rightComponent;
554 }
555
556
557 /**
558 * Sets the value of the <code>oneTouchExpandable</code> property,
559 * which must be <code>true</code> for the
560 * <code>JSplitPane</code> to provide a UI widget
561 * on the divider to quickly expand/collapse the divider.
562 * The default value of this property is <code>false</code>.
563 * Some look and feels might not support one-touch expanding;
564 * they will ignore this property.
565 *
566 * @param newValue <code>true</code> to specify that the split pane should provide a
567 * collapse/expand widget
568 * @beaninfo
569 * bound: true
570 * description: UI widget on the divider to quickly
571 * expand/collapse the divider.
572 *
573 * @see #isOneTouchExpandable
574 */
575 public void setOneTouchExpandable(boolean newValue) {
576 boolean oldValue = oneTouchExpandable;
577
578 oneTouchExpandable = newValue;
579 oneTouchExpandableSet = true;
580 firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue, newValue);
581 repaint();
582 }
583
584
585 /**
586 * Gets the <code>oneTouchExpandable</code> property.
587 *
588 * @return the value of the <code>oneTouchExpandable</code> property
589 * @see #setOneTouchExpandable
590 */
591 public boolean isOneTouchExpandable() {
592 return oneTouchExpandable;
593 }
594
595
596 /**
597 * Sets the last location the divider was at to
598 * <code>newLastLocation</code>.
599 *
600 * @param newLastLocation an integer specifying the last divider location
601 * in pixels, from the left (or upper) edge of the pane to the
602 * left (or upper) edge of the divider
603 * @beaninfo
604 * bound: true
605 * description: The last location the divider was at.
606 */
607 public void setLastDividerLocation(int newLastLocation) {
608 int oldLocation = lastDividerLocation;
609
610 lastDividerLocation = newLastLocation;
611 firePropertyChange(LAST_DIVIDER_LOCATION_PROPERTY, oldLocation,
612 newLastLocation);
613 }
614
615
616 /**
617 * Returns the last location the divider was at.
618 *
619 * @return an integer specifying the last divider location as a count
620 * of pixels from the left (or upper) edge of the pane to the
621 * left (or upper) edge of the divider
622 */
623 public int getLastDividerLocation() {
624 return lastDividerLocation;
625 }
626
627
628 /**
629 * Sets the orientation, or how the splitter is divided. The options
630 * are:<ul>
631 * <li>JSplitPane.VERTICAL_SPLIT (above/below orientation of components)
632 * <li>JSplitPane.HORIZONTAL_SPLIT (left/right orientation of components)
633 * </ul>
634 *
635 * @param orientation an integer specifying the orientation
636 * @exception IllegalArgumentException if orientation is not one of:
637 * HORIZONTAL_SPLIT or VERTICAL_SPLIT.
638 * @beaninfo
639 * bound: true
640 * description: The orientation, or how the splitter is divided.
641 * enum: HORIZONTAL_SPLIT JSplitPane.HORIZONTAL_SPLIT
642 * VERTICAL_SPLIT JSplitPane.VERTICAL_SPLIT
643 */
644 public void setOrientation(int orientation) {
645 if ((orientation != VERTICAL_SPLIT) &&
646 (orientation != HORIZONTAL_SPLIT)) {
647 throw new IllegalArgumentException("JSplitPane: orientation must " +
648 "be one of " +
649 "JSplitPane.VERTICAL_SPLIT or " +
650 "JSplitPane.HORIZONTAL_SPLIT");
651 }
652
653 int oldOrientation = this.orientation;
654
655 this.orientation = orientation;
656 firePropertyChange(ORIENTATION_PROPERTY, oldOrientation, orientation);
657 }
658
659
660 /**
661 * Returns the orientation.
662 *
663 * @return an integer giving the orientation
664 * @see #setOrientation
665 */
666 public int getOrientation() {
667 return orientation;
668 }
669
670
671 /**
672 * Sets the value of the <code>continuousLayout</code> property,
673 * which must be <code>true</code> for the child components
674 * to be continuously
675 * redisplayed and laid out during user intervention.
676 * The default value of this property is look and feel dependent.
677 * Some look and feels might not support continuous layout;
678 * they will ignore this property.
679 *
680 * @param newContinuousLayout <code>true</code> if the components
681 * should continuously be redrawn as the divider changes position
682 * @beaninfo
683 * bound: true
684 * description: Whether the child components are
685 * continuously redisplayed and laid out during
686 * user intervention.
687 * @see #isContinuousLayout
688 */
689 public void setContinuousLayout(boolean newContinuousLayout) {
690 boolean oldCD = continuousLayout;
691
692 continuousLayout = newContinuousLayout;
693 firePropertyChange(CONTINUOUS_LAYOUT_PROPERTY, oldCD,
694 newContinuousLayout);
695 }
696
697
698 /**
699 * Gets the <code>continuousLayout</code> property.
700 *
701 * @return the value of the <code>continuousLayout</code> property
702 * @see #setContinuousLayout
703 */
704 public boolean isContinuousLayout() {
705 return continuousLayout;
706 }
707
708 /**
709 * Specifies how to distribute extra space when the size of the split pane
710 * changes. A value of 0, the default,
711 * indicates the right/bottom component gets all the extra space (the
712 * left/top component acts fixed), where as a value of 1 specifies the
713 * left/top component gets all the extra space (the right/bottom component
714 * acts fixed). Specifically, the left/top component gets (weight * diff)
715 * extra space and the right/bottom component gets (1 - weight) * diff
716 * extra space.
717 *
718 * @param value as described above
719 * @exception IllegalArgumentException if <code>value</code> is < 0 or > 1
720 * @since 1.3
721 * @beaninfo
722 * bound: true
723 * description: Specifies how to distribute extra space when the split pane
724 * resizes.
725 */
726 public void setResizeWeight(double value) {
727 if (value < 0 || value > 1) {
728 throw new IllegalArgumentException("JSplitPane weight must be between 0 and 1");
729 }
730 double oldWeight = resizeWeight;
731
732 resizeWeight = value;
733 firePropertyChange(RESIZE_WEIGHT_PROPERTY, oldWeight, value);
734 }
735
736 /**
737 * Returns the number that determines how extra space is distributed.
738 * @return how extra space is to be distributed on a resize of the
739 * split pane
740 * @since 1.3
741 */
742 public double getResizeWeight() {
743 return resizeWeight;
744 }
745
756 }
757 }
758
759
760 /**
761 * Sets the divider location as a percentage of the
762 * <code>JSplitPane</code>'s size.
763 * <p>
764 * This method is implemented in terms of
765 * <code>setDividerLocation(int)</code>.
766 * This method immediately changes the size of the split pane based on
767 * its current size. If the split pane is not correctly realized and on
768 * screen, this method will have no effect (new divider location will
769 * become (current size * proportionalLocation) which is 0).
770 *
771 * @param proportionalLocation a double-precision floating point value
772 * that specifies a percentage, from zero (top/left) to 1.0
773 * (bottom/right)
774 * @exception IllegalArgumentException if the specified location is < 0
775 * or > 1.0
776 * @beaninfo
777 * description: The location of the divider.
778 */
779 public void setDividerLocation(double proportionalLocation) {
780 if (proportionalLocation < 0.0 ||
781 proportionalLocation > 1.0) {
782 throw new IllegalArgumentException("proportional location must " +
783 "be between 0.0 and 1.0.");
784 }
785 if (getOrientation() == VERTICAL_SPLIT) {
786 setDividerLocation((int)((double)(getHeight() - getDividerSize()) *
787 proportionalLocation));
788 } else {
789 setDividerLocation((int)((double)(getWidth() - getDividerSize()) *
790 proportionalLocation));
791 }
792 }
793
794
795 /**
796 * Sets the location of the divider. This is passed off to the
797 * look and feel implementation, and then listeners are notified. A value
798 * less than 0 implies the divider should be reset to a value that
799 * attempts to honor the preferred size of the left/top component.
800 * After notifying the listeners, the last divider location is updated,
801 * via <code>setLastDividerLocation</code>.
802 *
803 * @param location an int specifying a UI-specific value (typically a
804 * pixel count)
805 * @beaninfo
806 * bound: true
807 * description: The location of the divider.
808 */
809 public void setDividerLocation(int location) {
810 int oldValue = dividerLocation;
811
812 dividerLocation = location;
813
814 // Notify UI.
815 SplitPaneUI ui = getUI();
816
817 if (ui != null) {
818 ui.setDividerLocation(this, location);
819 }
820
821 // Then listeners
822 firePropertyChange(DIVIDER_LOCATION_PROPERTY, oldValue, location);
823
824 // And update the last divider location.
825 setLastDividerLocation(oldValue);
826 }
827
828
829 /**
830 * Returns the last value passed to <code>setDividerLocation</code>.
831 * The value returned from this method may differ from the actual
832 * divider location (if <code>setDividerLocation</code> was passed a
833 * value bigger than the current size).
834 *
835 * @return an integer specifying the location of the divider
836 */
837 public int getDividerLocation() {
838 return dividerLocation;
839 }
840
841
842 /**
843 * Returns the minimum location of the divider from the look and feel
844 * implementation.
845 *
846 * @return an integer specifying a UI-specific value for the minimum
847 * location (typically a pixel count); or -1 if the UI is
848 * <code>null</code>
849 * @beaninfo
850 * description: The minimum location of the divider from the L&F.
851 */
852 public int getMinimumDividerLocation() {
853 SplitPaneUI ui = getUI();
854
855 if (ui != null) {
856 return ui.getMinimumDividerLocation(this);
857 }
858 return -1;
859 }
860
861
862 /**
863 * Returns the maximum location of the divider from the look and feel
864 * implementation.
865 *
866 * @return an integer specifying a UI-specific value for the maximum
867 * location (typically a pixel count); or -1 if the UI is
868 * <code>null</code>
869 */
870 public int getMaximumDividerLocation() {
871 SplitPaneUI ui = getUI();
872
873 if (ui != null) {
874 return ui.getMaximumDividerLocation(this);
875 }
876 return -1;
877 }
878
879
880 /**
881 * Removes the child component, <code>component</code> from the
882 * pane. Resets the <code>leftComponent</code> or
883 * <code>rightComponent</code> instance variable, as necessary.
884 *
885 * @param component the <code>Component</code> to remove
886 */
887 public void remove(Component component) {
888 if (component == leftComponent) {
889 leftComponent = null;
930 */
931 public void removeAll() {
932 leftComponent = rightComponent = null;
933 super.removeAll();
934
935 // Update the JSplitPane on the screen
936 revalidate();
937 repaint();
938 }
939
940
941 /**
942 * Returns true, so that calls to <code>revalidate</code>
943 * on any descendant of this <code>JSplitPane</code>
944 * will cause a request to be queued that
945 * will validate the <code>JSplitPane</code> and all its descendants.
946 *
947 * @return true
948 * @see JComponent#revalidate
949 * @see java.awt.Container#isValidateRoot
950 *
951 * @beaninfo
952 * hidden: true
953 */
954 @Override
955 public boolean isValidateRoot() {
956 return true;
957 }
958
959
960 /**
961 * Adds the specified component to this split pane.
962 * If <code>constraints</code> identifies the left/top or
963 * right/bottom child component, and a component with that identifier
964 * was previously added, it will be removed and then <code>comp</code>
965 * will be added in its place. If <code>constraints</code> is not
966 * one of the known identifiers the layout manager may throw an
967 * <code>IllegalArgumentException</code>.
968 * <p>
969 * The possible constraints objects (Strings) are:
970 * <ul>
971 * <li>JSplitPane.TOP
972 * <li>JSplitPane.LEFT
973 * <li>JSplitPane.BOTTOM
974 * <li>JSplitPane.RIGHT
1115 ",lastDividerLocation=" + lastDividerLocation +
1116 ",oneTouchExpandable=" + oneTouchExpandableString +
1117 ",orientation=" + orientationString;
1118 }
1119
1120
1121
1122 ///////////////////////////
1123 // Accessibility support //
1124 ///////////////////////////
1125
1126
1127 /**
1128 * Gets the AccessibleContext associated with this JSplitPane.
1129 * For split panes, the AccessibleContext takes the form of an
1130 * AccessibleJSplitPane.
1131 * A new AccessibleJSplitPane instance is created if necessary.
1132 *
1133 * @return an AccessibleJSplitPane that serves as the
1134 * AccessibleContext of this JSplitPane
1135 * @beaninfo
1136 * expert: true
1137 * description: The AccessibleContext associated with this SplitPane.
1138 */
1139 public AccessibleContext getAccessibleContext() {
1140 if (accessibleContext == null) {
1141 accessibleContext = new AccessibleJSplitPane();
1142 }
1143 return accessibleContext;
1144 }
1145
1146
1147 /**
1148 * This class implements accessibility support for the
1149 * <code>JSplitPane</code> class. It provides an implementation of the
1150 * Java Accessibility API appropriate to split pane user-interface elements.
1151 * <p>
1152 * <strong>Warning:</strong>
1153 * Serialized objects of this class will not be compatible with
1154 * future Swing releases. The current serialization support is
1155 * appropriate for short term storage or RMI between applications running
1156 * the same version of Swing. As of 1.4, support for long term storage
1157 * of all JavaBeans™
1158 * has been added to the <code>java.beans</code> package.
|
1 /*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javax.swing;
27
28 import java.beans.JavaBean;
29 import java.beans.BeanProperty;
30 import java.beans.ConstructorProperties;
31 import javax.swing.plaf.*;
32 import javax.accessibility.*;
33
34 import java.awt.*;
35
36 import java.io.ObjectOutputStream;
37 import java.io.IOException;
38
39 /**
40 * <code>JSplitPane</code> is used to divide two (and only two)
41 * <code>Component</code>s. The two <code>Component</code>s
42 * are graphically divided based on the look and feel
43 * implementation, and the two <code>Component</code>s can then be
44 * interactively resized by the user.
45 * Information on using <code>JSplitPane</code> is in
46 * <a
47 href="http://docs.oracle.com/javase/tutorial/uiswing/components/splitpane.html">How to Use Split Panes</a> in
48 * <em>The Java Tutorial</em>.
49 * <p>
50 * The two <code>Component</code>s in a split pane can be aligned
51 * left to right using
52 * <code>JSplitPane.HORIZONTAL_SPLIT</code>, or top to bottom using
53 * <code>JSplitPane.VERTICAL_SPLIT</code>.
54 * The preferred way to change the size of the <code>Component</code>s
55 * is to invoke
56 * <code>setDividerLocation</code> where <code>location</code> is either
57 * the new x or y position, depending on the orientation of the
58 * <code>JSplitPane</code>.
77 * <strong>Warning:</strong> Swing is not thread safe. For more
78 * information see <a
79 * href="package-summary.html#threading">Swing's Threading
80 * Policy</a>.
81 * <p>
82 * <strong>Warning:</strong>
83 * Serialized objects of this class will not be compatible with
84 * future Swing releases. The current serialization support is
85 * appropriate for short term storage or RMI between applications running
86 * the same version of Swing. As of 1.4, support for long term storage
87 * of all JavaBeans™
88 * has been added to the <code>java.beans</code> package.
89 * Please see {@link java.beans.XMLEncoder}.
90 *
91 * @see #setDividerLocation
92 * @see #resetToPreferredSizes
93 *
94 * @author Scott Violet
95 * @since 1.2
96 */
97 @JavaBean(defaultProperty = "UI")
98 @SuppressWarnings("serial") // Same-version serialization only
99 public class JSplitPane extends JComponent implements Accessible
100 {
101 /**
102 * @see #getUIClassID
103 * @see #readObject
104 */
105 private static final String uiClassID = "SplitPaneUI";
106
107 /**
108 * Vertical split indicates the <code>Component</code>s are
109 * split along the y axis. For example the two
110 * <code>Component</code>s will be split one on top of the other.
111 */
112 public final static int VERTICAL_SPLIT = 0;
113
114 /**
115 * Horizontal split indicates the <code>Component</code>s are
116 * split along the x axis. For example the two
117 * <code>Component</code>s will be split one to the left of the
344 if (orientation != HORIZONTAL_SPLIT && orientation != VERTICAL_SPLIT)
345 throw new IllegalArgumentException("cannot create JSplitPane, " +
346 "orientation must be one of " +
347 "JSplitPane.HORIZONTAL_SPLIT " +
348 "or JSplitPane.VERTICAL_SPLIT");
349 continuousLayout = newContinuousLayout;
350 if (newLeftComponent != null)
351 setLeftComponent(newLeftComponent);
352 if (newRightComponent != null)
353 setRightComponent(newRightComponent);
354 updateUI();
355
356 }
357
358
359 /**
360 * Sets the L&F object that renders this component.
361 *
362 * @param ui the <code>SplitPaneUI</code> L&F object
363 * @see UIDefaults#getUI
364 */
365 public void setUI(SplitPaneUI ui) {
366 if ((SplitPaneUI)this.ui != ui) {
367 super.setUI(ui);
368 revalidate();
369 }
370 }
371
372
373 /**
374 * Returns the <code>SplitPaneUI</code> that is providing the
375 * current look and feel.
376 *
377 * @return the <code>SplitPaneUI</code> object that renders this component
378 */
379 @BeanProperty(bound = false, expert = true, description
380 = "The L&F object that renders this component.")
381 public SplitPaneUI getUI() {
382 return (SplitPaneUI)ui;
383 }
384
385
386 /**
387 * Notification from the <code>UIManager</code> that the L&F has changed.
388 * Replaces the current UI object with the latest version from the
389 * <code>UIManager</code>.
390 *
391 * @see JComponent#updateUI
392 */
393 public void updateUI() {
394 setUI((SplitPaneUI)UIManager.getUI(this));
395 revalidate();
396 }
397
398
399 /**
400 * Returns the name of the L&F class that renders this component.
401 *
402 * @return the string "SplitPaneUI"
403 * @see JComponent#getUIClassID
404 * @see UIDefaults#getUI
405 */
406 @BeanProperty(bound = false, expert = true, description
407 = "A string that specifies the name of the L&F class.")
408 public String getUIClassID() {
409 return uiClassID;
410 }
411
412
413 /**
414 * Sets the size of the divider.
415 *
416 * @param newSize an integer giving the size of the divider in pixels
417 */
418 @BeanProperty(description
419 = "The size of the divider.")
420 public void setDividerSize(int newSize) {
421 int oldSize = dividerSize;
422
423 dividerSizeSet = true;
424 if (oldSize != newSize) {
425 dividerSize = newSize;
426 firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, newSize);
427 }
428 }
429
430
431 /**
432 * Returns the size of the divider.
433 *
434 * @return an integer giving the size of the divider in pixels
435 */
436 public int getDividerSize() {
437 return dividerSize;
438 }
439
442 * Sets the component to the left (or above) the divider.
443 *
444 * @param comp the <code>Component</code> to display in that position
445 */
446 public void setLeftComponent(Component comp) {
447 if (comp == null) {
448 if (leftComponent != null) {
449 remove(leftComponent);
450 leftComponent = null;
451 }
452 } else {
453 add(comp, JSplitPane.LEFT);
454 }
455 }
456
457
458 /**
459 * Returns the component to the left (or above) the divider.
460 *
461 * @return the <code>Component</code> displayed in that position
462 */
463 @BeanProperty(bound = false, preferred = true, description
464 = "The component to the left (or above) the divider.")
465 public Component getLeftComponent() {
466 return leftComponent;
467 }
468
469
470 /**
471 * Sets the component above, or to the left of the divider.
472 *
473 * @param comp the <code>Component</code> to display in that position
474 */
475 @BeanProperty(bound = false, description
476 = "The component above, or to the left of the divider.")
477 public void setTopComponent(Component comp) {
478 setLeftComponent(comp);
479 }
480
481
482 /**
483 * Returns the component above, or to the left of the divider.
484 *
485 * @return the <code>Component</code> displayed in that position
486 */
487 public Component getTopComponent() {
488 return leftComponent;
489 }
490
491
492 /**
493 * Sets the component to the right (or below) the divider.
494 *
495 * @param comp the <code>Component</code> to display in that position
496 */
497 @BeanProperty(bound = false, preferred = true, description
498 = "The component to the right (or below) the divider.")
499 public void setRightComponent(Component comp) {
500 if (comp == null) {
501 if (rightComponent != null) {
502 remove(rightComponent);
503 rightComponent = null;
504 }
505 } else {
506 add(comp, JSplitPane.RIGHT);
507 }
508 }
509
510
511 /**
512 * Returns the component to the right (or below) the divider.
513 *
514 * @return the <code>Component</code> displayed in that position
515 */
516 public Component getRightComponent() {
517 return rightComponent;
518 }
519
520
521 /**
522 * Sets the component below, or to the right of the divider.
523 *
524 * @param comp the <code>Component</code> to display in that position
525 */
526 @BeanProperty(bound = false, description
527 = "The component below, or to the right of the divider.")
528 public void setBottomComponent(Component comp) {
529 setRightComponent(comp);
530 }
531
532
533 /**
534 * Returns the component below, or to the right of the divider.
535 *
536 * @return the <code>Component</code> displayed in that position
537 */
538 public Component getBottomComponent() {
539 return rightComponent;
540 }
541
542
543 /**
544 * Sets the value of the <code>oneTouchExpandable</code> property,
545 * which must be <code>true</code> for the
546 * <code>JSplitPane</code> to provide a UI widget
547 * on the divider to quickly expand/collapse the divider.
548 * The default value of this property is <code>false</code>.
549 * Some look and feels might not support one-touch expanding;
550 * they will ignore this property.
551 *
552 * @param newValue <code>true</code> to specify that the split pane should provide a
553 * collapse/expand widget
554 *
555 * @see #isOneTouchExpandable
556 */
557 @BeanProperty(description
558 = "UI widget on the divider to quickly expand/collapse the divider.")
559 public void setOneTouchExpandable(boolean newValue) {
560 boolean oldValue = oneTouchExpandable;
561
562 oneTouchExpandable = newValue;
563 oneTouchExpandableSet = true;
564 firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue, newValue);
565 repaint();
566 }
567
568
569 /**
570 * Gets the <code>oneTouchExpandable</code> property.
571 *
572 * @return the value of the <code>oneTouchExpandable</code> property
573 * @see #setOneTouchExpandable
574 */
575 public boolean isOneTouchExpandable() {
576 return oneTouchExpandable;
577 }
578
579
580 /**
581 * Sets the last location the divider was at to
582 * <code>newLastLocation</code>.
583 *
584 * @param newLastLocation an integer specifying the last divider location
585 * in pixels, from the left (or upper) edge of the pane to the
586 * left (or upper) edge of the divider
587 */
588 @BeanProperty(description
589 = "The last location the divider was at.")
590 public void setLastDividerLocation(int newLastLocation) {
591 int oldLocation = lastDividerLocation;
592
593 lastDividerLocation = newLastLocation;
594 firePropertyChange(LAST_DIVIDER_LOCATION_PROPERTY, oldLocation,
595 newLastLocation);
596 }
597
598
599 /**
600 * Returns the last location the divider was at.
601 *
602 * @return an integer specifying the last divider location as a count
603 * of pixels from the left (or upper) edge of the pane to the
604 * left (or upper) edge of the divider
605 */
606 public int getLastDividerLocation() {
607 return lastDividerLocation;
608 }
609
610
611 /**
612 * Sets the orientation, or how the splitter is divided. The options
613 * are:<ul>
614 * <li>JSplitPane.VERTICAL_SPLIT (above/below orientation of components)
615 * <li>JSplitPane.HORIZONTAL_SPLIT (left/right orientation of components)
616 * </ul>
617 *
618 * @param orientation an integer specifying the orientation
619 * @exception IllegalArgumentException if orientation is not one of:
620 * HORIZONTAL_SPLIT or VERTICAL_SPLIT.
621 */
622 @BeanProperty(enumerationValues = {
623 "JSplitPane.HORIZONTAL_SPLIT",
624 "JSplitPane.VERTICAL_SPLIT"}, description
625 = "The orientation, or how the splitter is divided.")
626 public void setOrientation(int orientation) {
627 if ((orientation != VERTICAL_SPLIT) &&
628 (orientation != HORIZONTAL_SPLIT)) {
629 throw new IllegalArgumentException("JSplitPane: orientation must " +
630 "be one of " +
631 "JSplitPane.VERTICAL_SPLIT or " +
632 "JSplitPane.HORIZONTAL_SPLIT");
633 }
634
635 int oldOrientation = this.orientation;
636
637 this.orientation = orientation;
638 firePropertyChange(ORIENTATION_PROPERTY, oldOrientation, orientation);
639 }
640
641
642 /**
643 * Returns the orientation.
644 *
645 * @return an integer giving the orientation
646 * @see #setOrientation
647 */
648 public int getOrientation() {
649 return orientation;
650 }
651
652
653 /**
654 * Sets the value of the <code>continuousLayout</code> property,
655 * which must be <code>true</code> for the child components
656 * to be continuously
657 * redisplayed and laid out during user intervention.
658 * The default value of this property is look and feel dependent.
659 * Some look and feels might not support continuous layout;
660 * they will ignore this property.
661 *
662 * @param newContinuousLayout <code>true</code> if the components
663 * should continuously be redrawn as the divider changes position
664 * @see #isContinuousLayout
665 */
666 @BeanProperty(description
667 = "Whether the child components are continuously redisplayed and laid out during user intervention.")
668 public void setContinuousLayout(boolean newContinuousLayout) {
669 boolean oldCD = continuousLayout;
670
671 continuousLayout = newContinuousLayout;
672 firePropertyChange(CONTINUOUS_LAYOUT_PROPERTY, oldCD,
673 newContinuousLayout);
674 }
675
676
677 /**
678 * Gets the <code>continuousLayout</code> property.
679 *
680 * @return the value of the <code>continuousLayout</code> property
681 * @see #setContinuousLayout
682 */
683 public boolean isContinuousLayout() {
684 return continuousLayout;
685 }
686
687 /**
688 * Specifies how to distribute extra space when the size of the split pane
689 * changes. A value of 0, the default,
690 * indicates the right/bottom component gets all the extra space (the
691 * left/top component acts fixed), where as a value of 1 specifies the
692 * left/top component gets all the extra space (the right/bottom component
693 * acts fixed). Specifically, the left/top component gets (weight * diff)
694 * extra space and the right/bottom component gets (1 - weight) * diff
695 * extra space.
696 *
697 * @param value as described above
698 * @exception IllegalArgumentException if <code>value</code> is < 0 or > 1
699 * @since 1.3
700 */
701 @BeanProperty(description
702 = "Specifies how to distribute extra space when the split pane resizes.")
703 public void setResizeWeight(double value) {
704 if (value < 0 || value > 1) {
705 throw new IllegalArgumentException("JSplitPane weight must be between 0 and 1");
706 }
707 double oldWeight = resizeWeight;
708
709 resizeWeight = value;
710 firePropertyChange(RESIZE_WEIGHT_PROPERTY, oldWeight, value);
711 }
712
713 /**
714 * Returns the number that determines how extra space is distributed.
715 * @return how extra space is to be distributed on a resize of the
716 * split pane
717 * @since 1.3
718 */
719 public double getResizeWeight() {
720 return resizeWeight;
721 }
722
733 }
734 }
735
736
737 /**
738 * Sets the divider location as a percentage of the
739 * <code>JSplitPane</code>'s size.
740 * <p>
741 * This method is implemented in terms of
742 * <code>setDividerLocation(int)</code>.
743 * This method immediately changes the size of the split pane based on
744 * its current size. If the split pane is not correctly realized and on
745 * screen, this method will have no effect (new divider location will
746 * become (current size * proportionalLocation) which is 0).
747 *
748 * @param proportionalLocation a double-precision floating point value
749 * that specifies a percentage, from zero (top/left) to 1.0
750 * (bottom/right)
751 * @exception IllegalArgumentException if the specified location is < 0
752 * or > 1.0
753 */
754 @BeanProperty(description
755 = "The location of the divider.")
756 public void setDividerLocation(double proportionalLocation) {
757 if (proportionalLocation < 0.0 ||
758 proportionalLocation > 1.0) {
759 throw new IllegalArgumentException("proportional location must " +
760 "be between 0.0 and 1.0.");
761 }
762 if (getOrientation() == VERTICAL_SPLIT) {
763 setDividerLocation((int)((double)(getHeight() - getDividerSize()) *
764 proportionalLocation));
765 } else {
766 setDividerLocation((int)((double)(getWidth() - getDividerSize()) *
767 proportionalLocation));
768 }
769 }
770
771
772 /**
773 * Sets the location of the divider. This is passed off to the
774 * look and feel implementation, and then listeners are notified. A value
775 * less than 0 implies the divider should be reset to a value that
776 * attempts to honor the preferred size of the left/top component.
777 * After notifying the listeners, the last divider location is updated,
778 * via <code>setLastDividerLocation</code>.
779 *
780 * @param location an int specifying a UI-specific value (typically a
781 * pixel count)
782 */
783 @BeanProperty(description
784 = "The location of the divider.")
785 public void setDividerLocation(int location) {
786 int oldValue = dividerLocation;
787
788 dividerLocation = location;
789
790 // Notify UI.
791 SplitPaneUI ui = getUI();
792
793 if (ui != null) {
794 ui.setDividerLocation(this, location);
795 }
796
797 // Then listeners
798 firePropertyChange(DIVIDER_LOCATION_PROPERTY, oldValue, location);
799
800 // And update the last divider location.
801 setLastDividerLocation(oldValue);
802 }
803
804
805 /**
806 * Returns the last value passed to <code>setDividerLocation</code>.
807 * The value returned from this method may differ from the actual
808 * divider location (if <code>setDividerLocation</code> was passed a
809 * value bigger than the current size).
810 *
811 * @return an integer specifying the location of the divider
812 */
813 public int getDividerLocation() {
814 return dividerLocation;
815 }
816
817
818 /**
819 * Returns the minimum location of the divider from the look and feel
820 * implementation.
821 *
822 * @return an integer specifying a UI-specific value for the minimum
823 * location (typically a pixel count); or -1 if the UI is
824 * <code>null</code>
825 */
826 @BeanProperty(bound = false, description
827 = "The minimum location of the divider from the L&F.")
828 public int getMinimumDividerLocation() {
829 SplitPaneUI ui = getUI();
830
831 if (ui != null) {
832 return ui.getMinimumDividerLocation(this);
833 }
834 return -1;
835 }
836
837
838 /**
839 * Returns the maximum location of the divider from the look and feel
840 * implementation.
841 *
842 * @return an integer specifying a UI-specific value for the maximum
843 * location (typically a pixel count); or -1 if the UI is
844 * <code>null</code>
845 */
846 @BeanProperty(bound = false)
847 public int getMaximumDividerLocation() {
848 SplitPaneUI ui = getUI();
849
850 if (ui != null) {
851 return ui.getMaximumDividerLocation(this);
852 }
853 return -1;
854 }
855
856
857 /**
858 * Removes the child component, <code>component</code> from the
859 * pane. Resets the <code>leftComponent</code> or
860 * <code>rightComponent</code> instance variable, as necessary.
861 *
862 * @param component the <code>Component</code> to remove
863 */
864 public void remove(Component component) {
865 if (component == leftComponent) {
866 leftComponent = null;
907 */
908 public void removeAll() {
909 leftComponent = rightComponent = null;
910 super.removeAll();
911
912 // Update the JSplitPane on the screen
913 revalidate();
914 repaint();
915 }
916
917
918 /**
919 * Returns true, so that calls to <code>revalidate</code>
920 * on any descendant of this <code>JSplitPane</code>
921 * will cause a request to be queued that
922 * will validate the <code>JSplitPane</code> and all its descendants.
923 *
924 * @return true
925 * @see JComponent#revalidate
926 * @see java.awt.Container#isValidateRoot
927 */
928 @Override
929 @BeanProperty(hidden = true)
930 public boolean isValidateRoot() {
931 return true;
932 }
933
934
935 /**
936 * Adds the specified component to this split pane.
937 * If <code>constraints</code> identifies the left/top or
938 * right/bottom child component, and a component with that identifier
939 * was previously added, it will be removed and then <code>comp</code>
940 * will be added in its place. If <code>constraints</code> is not
941 * one of the known identifiers the layout manager may throw an
942 * <code>IllegalArgumentException</code>.
943 * <p>
944 * The possible constraints objects (Strings) are:
945 * <ul>
946 * <li>JSplitPane.TOP
947 * <li>JSplitPane.LEFT
948 * <li>JSplitPane.BOTTOM
949 * <li>JSplitPane.RIGHT
1090 ",lastDividerLocation=" + lastDividerLocation +
1091 ",oneTouchExpandable=" + oneTouchExpandableString +
1092 ",orientation=" + orientationString;
1093 }
1094
1095
1096
1097 ///////////////////////////
1098 // Accessibility support //
1099 ///////////////////////////
1100
1101
1102 /**
1103 * Gets the AccessibleContext associated with this JSplitPane.
1104 * For split panes, the AccessibleContext takes the form of an
1105 * AccessibleJSplitPane.
1106 * A new AccessibleJSplitPane instance is created if necessary.
1107 *
1108 * @return an AccessibleJSplitPane that serves as the
1109 * AccessibleContext of this JSplitPane
1110 */
1111 @BeanProperty(bound = false, expert = true, description
1112 = "The AccessibleContext associated with this SplitPane.")
1113 public AccessibleContext getAccessibleContext() {
1114 if (accessibleContext == null) {
1115 accessibleContext = new AccessibleJSplitPane();
1116 }
1117 return accessibleContext;
1118 }
1119
1120
1121 /**
1122 * This class implements accessibility support for the
1123 * <code>JSplitPane</code> class. It provides an implementation of the
1124 * Java Accessibility API appropriate to split pane user-interface elements.
1125 * <p>
1126 * <strong>Warning:</strong>
1127 * Serialized objects of this class will not be compatible with
1128 * future Swing releases. The current serialization support is
1129 * appropriate for short term storage or RMI between applications running
1130 * the same version of Swing. As of 1.4, support for long term storage
1131 * of all JavaBeans™
1132 * has been added to the <code>java.beans</code> package.
|