UIFSplitPane.java
001 /*
002  * Copyright (c) 2000-2006 JGoodies Karsten Lentzsch. All Rights Reserved.
003  *
004  * Redistribution and use in source and binary forms, with or without
005  * modification, are permitted provided that the following conditions are met:
006  *
007  *  o Redistributions of source code must retain the above copyright notice,
008  *    this list of conditions and the following disclaimer.
009  *
010  *  o Redistributions in binary form must reproduce the above copyright notice,
011  *    this list of conditions and the following disclaimer in the documentation
012  *    and/or other materials provided with the distribution.
013  *
014  *  o Neither the name of JGoodies Karsten Lentzsch nor the names of
015  *    its contributors may be used to endorse or promote products derived
016  *    from this software without specific prior written permission.
017  *
018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029  */
030 
031 package com.jgoodies.uif_lite.component;
032 
033 import java.awt.Component;
034 
035 import javax.swing.BorderFactory;
036 import javax.swing.JButton;
037 import javax.swing.JSplitPane;
038 import javax.swing.UIManager;
039 import javax.swing.plaf.SplitPaneUI;
040 import javax.swing.plaf.basic.BasicSplitPaneUI;
041 
042 /**
043  * A <code>JSplitPane</code> subclass that can try to remove the divider border.
044  * Useful if the splitted components render their own borders.
045  * Note that this feature is not supported by all look&amp;feels.
046  * Some look&amp;feel implementation will always show a divider border,
047  * and conversely, others will never show a divider border.
048  *
049  @author Karsten Lentzsch
050  @version $Revision: 1.1 $
051  *
052  @see javax.swing.plaf.basic.BasicSplitPaneUI
053  */
054 
055 public final class UIFSplitPane extends JSplitPane {
056 
057     /**
058      * Holds the name of the bound property that tries to show or hide
059      * the split pane's divider border.
060      *
061      @see #isDividerBorderVisible()
062      @see #setDividerBorderVisible(boolean)
063      */
064     public static final String PROPERTYNAME_DIVIDER_BORDER_VISIBLE =
065         "dividerBorderVisible";
066 
067     /**
068      * Determines whether the divider border shall be removed when
069      * the UI is updated.
070      *
071      @see #isDividerBorderVisible()
072      @see #setDividerBorderVisible(boolean)
073      */
074     private boolean dividerBorderVisible;
075 
076 
077     // Instance Creation *****************************************************
078 
079     /**
080      * Constructs a <code>UIFSplitPane</code> configured to arrange the child
081      * components side-by-side horizontally with no continuous
082      * layout, using two buttons for the components.
083      */
084     public UIFSplitPane() {
085         this(JSplitPane.HORIZONTAL_SPLIT, false,
086                 new JButton(UIManager.getString("SplitPane.leftButtonText")),
087                 new JButton(UIManager.getString("SplitPane.rightButtonText")));
088     }
089 
090 
091     /**
092      * Constructs a <code>UIFSplitPane</code> configured with the
093      * specified orientation and no continuous layout.
094      *
095      @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
096      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
097      @throws IllegalArgumentException if <code>orientation</code>
098      *        is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT.
099      */
100     public UIFSplitPane(int newOrientation) {
101         this(newOrientation, false);
102     }
103 
104 
105     /**
106      * Constructs a <code>UIFSplitPane</code> with the specified
107      * orientation and redrawing style.
108      *
109      @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
110      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
111      @param newContinuousLayout  a boolean, true for the components to
112      *        redraw continuously as the divider changes position, false
113      *        to wait until the divider position stops changing to redraw
114      @throws IllegalArgumentException if <code>orientation</code>
115      *        is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
116      */
117     public UIFSplitPane(int newOrientation,
118                       boolean newContinuousLayout) {
119         this(newOrientation, newContinuousLayout, null, null);
120     }
121 
122 
123     /**
124      * Constructs a <code>UIFSplitPane</code> with the specified orientation
125      * and the given componenents.
126      *
127      @param orientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
128      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
129      @param leftComponent the <code>Component</code> that will
130      *    appear on the left of a horizontally-split pane,
131      *    or at the top of a vertically-split pane
132      @param rightComponent the <code>Component</code> that will
133      *    appear on the right of a horizontally-split pane,
134      *    or at the bottom of a    vertically-split pane
135      @throws IllegalArgumentException if <code>orientation</code>
136      *    is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT
137      */
138     public UIFSplitPane(int orientation,
139                          Component leftComponent,
140                          Component rightComponent) {
141         this(orientation, false, leftComponent, rightComponent);
142     }
143 
144 
145     /**
146      * Constructs a <code>UIFSplitPane</code> with the specified orientation,
147      * redrawing style, and given components.
148      *
149      @param orientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
150      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
151      @param continuousLayout  a boolean, true for the components to
152      *        redraw continuously as the divider changes position, false
153      *        to wait until the divider position stops changing to redraw
154      @param leftComponent the <code>Component</code> that will
155      *        appear on the left
156      *            of a horizontally-split pane, or at the top of a
157      *            vertically-split pane
158      @param rightComponent the <code>Component</code> that will
159      *        appear on the right
160      *            of a horizontally-split pane, or at the bottom of a
161      *            vertically-split pane
162      @throws IllegalArgumentException if <code>orientation</code>
163      *        is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
164      */
165     public UIFSplitPane(int orientation,
166                       boolean continuousLayout,
167                       Component leftComponent,
168                       Component rightComponent){
169         super(orientation, continuousLayout, leftComponent, rightComponent);
170         dividerBorderVisible = false;
171     }
172 
173 
174     /**
175      * Constructs a <code>UIFSplitPane</code>,
176      * i.e. a <code>JSplitPane</code> that has no borders.
177      * Also disabled the one touch exandable property.
178      *
179      @param orientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
180      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
181      @param leftComponent the <code>Component</code> that will
182      *    appear on the left of a horizontally-split pane,
183      *    or at the top of a vertically-split pane
184      @param rightComponent the <code>Component</code> that will
185      *    appear on the right of a horizontally-split pane,
186      *    or at the bottom of a    vertically-split pane
187      @throws IllegalArgumentException if <code>orientation</code>
188      *    is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT
189      */
190     public static UIFSplitPane createStrippedSplitPane(
191              int orientation,
192              Component leftComponent,
193              Component rightComponent) {
194         UIFSplitPane split = new UIFSplitPane(orientation, leftComponent, rightComponent);
195         split.setBorder(BorderFactory.createEmptyBorder());
196         split.setOneTouchExpandable(false);
197         return split;
198     }
199 
200 
201     // Accessing Properties **************************************************
202 
203     /**
204      * Checks and answers whether the divider border shall be visible
205      * or invisible.
206      * Note that this feature is not supported by all look&amp;feels.
207      * Some look&amp;feel implementation will always show a divider border,
208      * and conversely, others will never show a divider border.
209      *
210      @return the desired (but potentially inaccurate) divider border visiblity
211      */
212     public boolean isDividerBorderVisible() {
213         return dividerBorderVisible;
214     }
215 
216 
217     /**
218      * Makes the divider border visible or invisible.
219      * Note that this feature is not supported by all look&amp;feels.
220      * Some look&amp;feel implementation will always show a divider border,
221      * and conversely, others will never show a divider border.
222      *
223      @param newVisibility   true for visible, false for invisible
224      */
225     public void setDividerBorderVisible(boolean newVisibility) {
226         boolean oldVisibility = isDividerBorderVisible();
227         if (oldVisibility == newVisibility)
228             return;
229         dividerBorderVisible = newVisibility;
230         firePropertyChange(PROPERTYNAME_DIVIDER_BORDER_VISIBLE,
231                            oldVisibility,
232                            newVisibility);
233     }
234 
235 
236     // Changing the Divider Border Visibility *********************************
237 
238     /**
239      * Updates the UI and sets an empty divider border. The divider border
240      * may be restored by a L&F at UI installation time. And so, we
241      * try to reset it each time the UI is changed.
242      */
243     public void updateUI() {
244         super.updateUI();
245         if (!isDividerBorderVisible())
246             setEmptyDividerBorder();
247     }
248 
249 
250     /**
251      * Sets an empty divider border if and only if the UI is
252      * an instance of <code>BasicSplitPaneUI</code>.
253      */
254     private void setEmptyDividerBorder() {
255         SplitPaneUI splitPaneUI = getUI();
256         if (splitPaneUI instanceof BasicSplitPaneUI) {
257             BasicSplitPaneUI basicUI = (BasicSplitPaneUIsplitPaneUI;
258             basicUI.getDivider().setBorder(BorderFactory.createEmptyBorder());
259         }
260     }
261 
262 
263 }