001: /*
002: * Copyright (c) 2003 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: package org.columba.core.gui.base;
031:
032: import java.awt.Component;
033:
034: import javax.swing.JButton;
035: import javax.swing.JSplitPane;
036: import javax.swing.UIManager;
037: import javax.swing.border.Border;
038: import javax.swing.border.EmptyBorder;
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&feels.
046: * Some look&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: public final class UIFSplitPane extends JSplitPane {
055: /**
056: * Holds an empty border that is reused for the split pane itself
057: * and the divider.
058: */
059: private static final Border EMPTY_BORDER = new EmptyBorder(0, 0, 0,
060: 0);
061:
062: /**
063: * Determines whether the divider border shall be removed when
064: * the UI is updated.
065: *
066: * @see #isDividerBorderVisible()
067: * @see #setDividerBorderVisible(boolean)
068: */
069: private boolean dividerBorderVisible;
070:
071: // Instance Creation *****************************************************
072:
073: /**
074: * Constructs a <code>UIFSplitPane</code> configured to arrange the child
075: * components side-by-side horizontally with no continuous
076: * layout, using two buttons for the components.
077: */
078: public UIFSplitPane() {
079: this (JSplitPane.HORIZONTAL_SPLIT, false, new JButton(UIManager
080: .getString("SplitPane.leftButtonText")), new JButton(
081: UIManager.getString("SplitPane.rightButtonText")));
082: }
083:
084: /**
085: * Constructs a <code>UIFSplitPane</code> configured with the
086: * specified orientation and no continuous layout.
087: *
088: * @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
089: * <code>JSplitPane.VERTICAL_SPLIT</code>
090: * @throws IllegalArgumentException if <code>orientation</code>
091: * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT.
092: */
093: public UIFSplitPane(int newOrientation) {
094: this (newOrientation, false);
095: }
096:
097: /**
098: * Constructs a <code>UIFSplitPane</code> with the specified
099: * orientation and redrawing style.
100: *
101: * @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
102: * <code>JSplitPane.VERTICAL_SPLIT</code>
103: * @param newContinuousLayout a boolean, true for the components to
104: * redraw continuously as the divider changes position, false
105: * to wait until the divider position stops changing to redraw
106: * @throws IllegalArgumentException if <code>orientation</code>
107: * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
108: */
109: public UIFSplitPane(int newOrientation, boolean newContinuousLayout) {
110: this (newOrientation, newContinuousLayout, null, null);
111: }
112:
113: /**
114: * Constructs a <code>UIFSplitPane</code> with the specified orientation
115: * and the given componenents.
116: *
117: * @param orientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
118: * <code>JSplitPane.VERTICAL_SPLIT</code>
119: * @param leftComponent the <code>Component</code> that will
120: * appear on the left of a horizontally-split pane,
121: * or at the top of a vertically-split pane
122: * @param rightComponent the <code>Component</code> that will
123: * appear on the right of a horizontally-split pane,
124: * or at the bottom of a vertically-split pane
125: * @throws IllegalArgumentException if <code>orientation</code>
126: * is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT
127: */
128: public UIFSplitPane(int orientation, Component leftComponent,
129: Component rightComponent) {
130: this (orientation, false, leftComponent, rightComponent);
131: }
132:
133: /**
134: * Constructs a <code>UIFSplitPane</code> with the specified orientation,
135: * redrawing style, and given components.
136: *
137: * @param orientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
138: * <code>JSplitPane.VERTICAL_SPLIT</code>
139: * @param continuousLayout a boolean, true for the components to
140: * redraw continuously as the divider changes position, false
141: * to wait until the divider position stops changing to redraw
142: * @param leftComponent the <code>Component</code> that will
143: * appear on the left
144: * of a horizontally-split pane, or at the top of a
145: * vertically-split pane
146: * @param rightComponent the <code>Component</code> that will
147: * appear on the right
148: * of a horizontally-split pane, or at the bottom of a
149: * vertically-split pane
150: * @throws IllegalArgumentException if <code>orientation</code>
151: * is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
152: */
153: public UIFSplitPane(int orientation, boolean continuousLayout,
154: Component leftComponent, Component rightComponent) {
155: super (orientation, continuousLayout, leftComponent,
156: rightComponent);
157: dividerBorderVisible = false;
158: }
159:
160: /**
161: * Constructs a <code>UIFSplitPane</code>,
162: * i.e. a <code>JSplitPane</code> that has no borders.
163: * Also disabled the one touch exandable property.
164: *
165: * @param orientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or
166: * <code>JSplitPane.VERTICAL_SPLIT</code>
167: * @param leftComponent the <code>Component</code> that will
168: * appear on the left of a horizontally-split pane,
169: * or at the top of a vertically-split pane
170: * @param rightComponent the <code>Component</code> that will
171: * appear on the right of a horizontally-split pane,
172: * or at the bottom of a vertically-split pane
173: * @throws IllegalArgumentException if <code>orientation</code>
174: * is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT
175: */
176: public static UIFSplitPane createStrippedSplitPane(int orientation,
177: Component leftComponent, Component rightComponent) {
178: UIFSplitPane split = new UIFSplitPane(orientation,
179: leftComponent, rightComponent);
180: split.setBorder(EMPTY_BORDER);
181: split.setOneTouchExpandable(false);
182:
183: return split;
184: }
185:
186: // Accessing Properties **************************************************
187:
188: /**
189: * Checks and answers whether the divider border shall be visible
190: * or invisible.
191: * Note that this feature is not supported by all look&feels.
192: * Some look&feel implementation will always show a divider border,
193: * and conversely, others will never show a divider border.
194: *
195: * @return the desired (but potentially inaccurate) divider border visiblity
196: */
197: public boolean isDividerBorderVisible() {
198: return dividerBorderVisible;
199: }
200:
201: /**
202: * Makes the divider border visible or invisible.
203: * Note that this feature is not supported by all look&feels.
204: * Some look&feel implementation will always show a divider border,
205: * and conversely, others will never show a divider border.
206: *
207: * @param newVisibility true for visible, false for invisible
208: */
209: public void setDividerBorderVisible(boolean newVisibility) {
210: boolean oldVisibility = isDividerBorderVisible();
211:
212: if (oldVisibility == newVisibility) {
213: return;
214: }
215:
216: dividerBorderVisible = newVisibility;
217: firePropertyChange("dividerBorderVisible", oldVisibility,
218: newVisibility);
219: }
220:
221: // Changing the Divider Border Visibility *********************************
222:
223: /**
224: * Updates the UI and sets an empty divider border. The divider border
225: * may be restored by a L&F at UI installation time. And so, we
226: * try to reset it each time the UI is changed.
227: */
228: public void updateUI() {
229: super .updateUI();
230:
231: if (!isDividerBorderVisible()) {
232: setEmptyDividerBorder();
233: }
234: }
235:
236: /**
237: * Sets an empty divider border if and only if the UI is
238: * an instance of <code>BasicSplitPaneUI</code>.
239: */
240: private void setEmptyDividerBorder() {
241: SplitPaneUI splitPaneUI = getUI();
242:
243: if (splitPaneUI instanceof BasicSplitPaneUI) {
244: BasicSplitPaneUI basicUI = (BasicSplitPaneUI) splitPaneUI;
245: basicUI.getDivider().setBorder(EMPTY_BORDER);
246: }
247: }
248: }
|