001 /*
002 * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.swing.plaf.synth;
027
028 import java.awt.*;
029 import java.awt.event.*;
030 import java.beans.*;
031 import java.util.*;
032 import javax.swing.*;
033 import javax.swing.event.*;
034 import javax.swing.plaf.*;
035 import javax.swing.plaf.basic.*;
036 import sun.swing.plaf.synth.SynthUI;
037
038 /**
039 * Synth's SplitPaneUI.
040 *
041 * @version 1.23, 05/05/07
042 * @author Scott Violet
043 */
044 class SynthSplitPaneUI extends BasicSplitPaneUI implements
045 PropertyChangeListener, SynthUI {
046 /**
047 * Keys to use for forward focus traversal when the JComponent is
048 * managing focus.
049 */
050 private static Set managingFocusForwardTraversalKeys;
051
052 /**
053 * Keys to use for backward focus traversal when the JComponent is
054 * managing focus.
055 */
056 private static Set managingFocusBackwardTraversalKeys;
057
058 /**
059 * Style for the JSplitPane.
060 */
061 private SynthStyle style;
062 /**
063 * Style for the divider.
064 */
065 private SynthStyle dividerStyle;
066
067 /**
068 * Creates a new SynthSplitPaneUI instance
069 */
070 public static ComponentUI createUI(JComponent x) {
071 return new SynthSplitPaneUI();
072 }
073
074 /**
075 * Installs the UI defaults.
076 */
077 protected void installDefaults() {
078 updateStyle(splitPane);
079
080 setOrientation(splitPane.getOrientation());
081 setContinuousLayout(splitPane.isContinuousLayout());
082
083 resetLayoutManager();
084
085 /* Install the nonContinuousLayoutDivider here to avoid having to
086 add/remove everything later. */
087 if (nonContinuousLayoutDivider == null) {
088 setNonContinuousLayoutDivider(
089 createDefaultNonContinuousLayoutDivider(), true);
090 } else {
091 setNonContinuousLayoutDivider(nonContinuousLayoutDivider,
092 true);
093 }
094
095 // focus forward traversal key
096 if (managingFocusForwardTraversalKeys == null) {
097 managingFocusForwardTraversalKeys = new HashSet();
098 managingFocusForwardTraversalKeys.add(KeyStroke
099 .getKeyStroke(KeyEvent.VK_TAB, 0));
100 }
101 splitPane.setFocusTraversalKeys(
102 KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
103 managingFocusForwardTraversalKeys);
104 // focus backward traversal key
105 if (managingFocusBackwardTraversalKeys == null) {
106 managingFocusBackwardTraversalKeys = new HashSet();
107 managingFocusBackwardTraversalKeys.add(KeyStroke
108 .getKeyStroke(KeyEvent.VK_TAB,
109 InputEvent.SHIFT_MASK));
110 }
111 splitPane.setFocusTraversalKeys(
112 KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
113 managingFocusBackwardTraversalKeys);
114 }
115
116 private void updateStyle(JSplitPane splitPane) {
117 SynthContext context = getContext(splitPane,
118 Region.SPLIT_PANE_DIVIDER, ENABLED);
119 SynthStyle oldDividerStyle = dividerStyle;
120 dividerStyle = SynthLookAndFeel.updateStyle(context, this );
121 context.dispose();
122
123 context = getContext(splitPane, ENABLED);
124 SynthStyle oldStyle = style;
125
126 style = SynthLookAndFeel.updateStyle(context, this );
127
128 if (style != oldStyle) {
129 Object value = style.get(context, "SplitPane.size");
130 if (value == null) {
131 value = new Integer(6);
132 }
133 LookAndFeel
134 .installProperty(splitPane, "dividerSize", value);
135
136 value = style.get(context, "SplitPane.oneTouchExpandable");
137 if (value != null) {
138 LookAndFeel.installProperty(splitPane,
139 "oneTouchExpandable", value);
140 }
141
142 if (divider != null) {
143 splitPane.remove(divider);
144 divider.setDividerSize(splitPane.getDividerSize());
145 }
146 if (oldStyle != null) {
147 uninstallKeyboardActions();
148 installKeyboardActions();
149 }
150 }
151 if (style != oldStyle || dividerStyle != oldDividerStyle) {
152 // Only way to force BasicSplitPaneDivider to reread the
153 // necessary properties.
154 if (divider != null) {
155 splitPane.remove(divider);
156 }
157 divider = createDefaultDivider();
158 divider.setBasicSplitPaneUI(this );
159 splitPane.add(divider, JSplitPane.DIVIDER);
160 }
161 context.dispose();
162 }
163
164 /**
165 * Installs the event listeners for the UI.
166 */
167 protected void installListeners() {
168 super .installListeners();
169 splitPane.addPropertyChangeListener(this );
170 }
171
172 /**
173 * Uninstalls the UI defaults.
174 */
175 protected void uninstallDefaults() {
176 SynthContext context = getContext(splitPane, ENABLED);
177
178 style.uninstallDefaults(context);
179 context.dispose();
180 style = null;
181
182 context = getContext(splitPane, Region.SPLIT_PANE_DIVIDER,
183 ENABLED);
184 dividerStyle.uninstallDefaults(context);
185 context.dispose();
186 dividerStyle = null;
187
188 super .uninstallDefaults();
189 }
190
191 /**
192 * Uninstalls the event listeners for the UI.
193 */
194 protected void uninstallListeners() {
195 super .uninstallListeners();
196 splitPane.removePropertyChangeListener(this );
197 }
198
199 public SynthContext getContext(JComponent c) {
200 return getContext(c, getComponentState(c));
201 }
202
203 private SynthContext getContext(JComponent c, int state) {
204 return SynthContext.getContext(SynthContext.class, c,
205 SynthLookAndFeel.getRegion(c), style, state);
206 }
207
208 private Region getRegion(JComponent c) {
209 return SynthLookAndFeel.getRegion(c);
210 }
211
212 private int getComponentState(JComponent c) {
213 return SynthLookAndFeel.getComponentState(c);
214 }
215
216 SynthContext getContext(JComponent c, Region region) {
217 return getContext(c, region, getComponentState(c, region));
218 }
219
220 private SynthContext getContext(JComponent c, Region region,
221 int state) {
222 if (region == Region.SPLIT_PANE_DIVIDER) {
223 return SynthContext.getContext(SynthContext.class, c,
224 region, dividerStyle, state);
225 }
226 return SynthContext.getContext(SynthContext.class, c, region,
227 style, state);
228 }
229
230 private int getComponentState(JComponent c, Region subregion) {
231 int state = SynthLookAndFeel.getComponentState(c);
232
233 if (divider.isMouseOver()) {
234 state |= MOUSE_OVER;
235 }
236 return state;
237 }
238
239 public void propertyChange(PropertyChangeEvent e) {
240 if (SynthLookAndFeel.shouldUpdateStyle(e)) {
241 updateStyle((JSplitPane) e.getSource());
242 }
243 }
244
245 /**
246 * Creates the default divider.
247 */
248 public BasicSplitPaneDivider createDefaultDivider() {
249 SynthSplitPaneDivider divider = new SynthSplitPaneDivider(this );
250
251 divider.setDividerSize(splitPane.getDividerSize());
252 return divider;
253 }
254
255 protected Component createDefaultNonContinuousLayoutDivider() {
256 return new Canvas() {
257 public void paint(Graphics g) {
258 paintDragDivider(g, 0, 0, getWidth(), getHeight());
259 }
260 };
261 }
262
263 public void update(Graphics g, JComponent c) {
264 SynthContext context = getContext(c);
265
266 SynthLookAndFeel.update(context, g);
267 context.getPainter().paintSplitPaneBackground(context, g, 0, 0,
268 c.getWidth(), c.getHeight());
269 paint(context, g);
270 context.dispose();
271 }
272
273 public void paint(Graphics g, JComponent c) {
274 SynthContext context = getContext(c);
275
276 paint(context, g);
277 context.dispose();
278 }
279
280 protected void paint(SynthContext context, Graphics g) {
281 // This is done to update package private variables in
282 // BasicSplitPaneUI
283 super .paint(g, splitPane);
284 }
285
286 public void paintBorder(SynthContext context, Graphics g, int x,
287 int y, int w, int h) {
288 context.getPainter().paintSplitPaneBorder(context, g, x, y, w,
289 h);
290 }
291
292 private void paintDragDivider(Graphics g, int x, int y, int w, int h) {
293 SynthContext context = getContext(splitPane,
294 Region.SPLIT_PANE_DIVIDER);
295 context
296 .setComponentState(((context.getComponentState() | MOUSE_OVER) ^ MOUSE_OVER)
297 | PRESSED);
298 Shape oldClip = g.getClip();
299 g.clipRect(x, y, w, h);
300 context.getPainter().paintSplitPaneDragDivider(context, g, x,
301 y, w, h, splitPane.getOrientation());
302 g.setClip(oldClip);
303 context.dispose();
304 }
305
306 public void finishedPaintingChildren(JSplitPane jc, Graphics g) {
307 if (jc == splitPane && getLastDragLocation() != -1
308 && !isContinuousLayout() && !draggingHW) {
309 if (jc.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
310 paintDragDivider(g, getLastDragLocation(), 0,
311 dividerSize - 1, splitPane.getHeight() - 1);
312 } else {
313 paintDragDivider(g, 0, getLastDragLocation(), splitPane
314 .getWidth() - 1, dividerSize - 1);
315 }
316 }
317 }
318 }
|