blob: 51cfb1ad50053803feb41776c40d91e52ed4cbfa [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.swing.plaf.metal;
27
28import java.awt.*;
29import javax.swing.*;
30import javax.swing.border.*;
31import javax.swing.plaf.basic.*;
32
33
34/**
35 * Metal's split pane divider
36 * <p>
37 * <strong>Warning:</strong>
38 * Serialized objects of this class will not be compatible with
39 * future Swing releases. The current serialization support is
40 * appropriate for short term storage or RMI between applications running
41 * the same version of Swing. As of 1.4, support for long term storage
42 * of all JavaBeans<sup><font size="-2">TM</font></sup>
43 * has been added to the <code>java.beans</code> package.
44 * Please see {@link java.beans.XMLEncoder}.
45 *
46 * @author Steve Wilson
47 * @author Ralph kar
48 */
49class MetalSplitPaneDivider extends BasicSplitPaneDivider
50{
51 private MetalBumps bumps = new MetalBumps(10, 10,
52 MetalLookAndFeel.getControlHighlight(),
53 MetalLookAndFeel.getControlDarkShadow(),
54 MetalLookAndFeel.getControl() );
55
56 private MetalBumps focusBumps = new MetalBumps(10, 10,
57 MetalLookAndFeel.getPrimaryControlHighlight(),
58 MetalLookAndFeel.getPrimaryControlDarkShadow(),
59 UIManager.getColor("SplitPane.dividerFocusColor"));
60
61 private int inset = 2;
62
63 private Color controlColor = MetalLookAndFeel.getControl();
64 private Color primaryControlColor = UIManager.getColor(
65 "SplitPane.dividerFocusColor");
66
67 public MetalSplitPaneDivider(BasicSplitPaneUI ui) {
68 super(ui);
69 }
70
71 public void paint(Graphics g) {
72 MetalBumps usedBumps;
73 if (splitPane.hasFocus()) {
74 usedBumps = focusBumps;
75 g.setColor(primaryControlColor);
76 }
77 else {
78 usedBumps = bumps;
79 g.setColor(controlColor);
80 }
81 Rectangle clip = g.getClipBounds();
82 Insets insets = getInsets();
83 g.fillRect(clip.x, clip.y, clip.width, clip.height);
84 Dimension size = getSize();
85 size.width -= inset * 2;
86 size.height -= inset * 2;
87 int drawX = inset;
88 int drawY = inset;
89 if (insets != null) {
90 size.width -= (insets.left + insets.right);
91 size.height -= (insets.top + insets.bottom);
92 drawX += insets.left;
93 drawY += insets.top;
94 }
95 usedBumps.setBumpArea(size);
96 usedBumps.paintIcon(this, g, drawX, drawY);
97 super.paint(g);
98 }
99
100 /**
101 * Creates and return an instance of JButton that can be used to
102 * collapse the left component in the metal split pane.
103 */
104 protected JButton createLeftOneTouchButton() {
105 JButton b = new JButton() {
106 // Sprite buffer for the arrow image of the left button
107 int[][] buffer = {{0, 0, 0, 2, 2, 0, 0, 0, 0},
108 {0, 0, 2, 1, 1, 1, 0, 0, 0},
109 {0, 2, 1, 1, 1, 1, 1, 0, 0},
110 {2, 1, 1, 1, 1, 1, 1, 1, 0},
111 {0, 3, 3, 3, 3, 3, 3, 3, 3}};
112
113 public void setBorder(Border b) {
114 }
115
116 public void paint(Graphics g) {
117 JSplitPane splitPane = getSplitPaneFromSuper();
118 if(splitPane != null) {
119 int oneTouchSize = getOneTouchSizeFromSuper();
120 int orientation = getOrientationFromSuper();
121 int blockSize = Math.min(getDividerSize(),
122 oneTouchSize);
123
124 // Initialize the color array
125 Color[] colors = {
126 this.getBackground(),
127 MetalLookAndFeel.getPrimaryControlDarkShadow(),
128 MetalLookAndFeel.getPrimaryControlInfo(),
129 MetalLookAndFeel.getPrimaryControlHighlight()};
130
131 // Fill the background first ...
132 g.setColor(this.getBackground());
133 if (isOpaque()) {
134 g.fillRect(0, 0, this.getWidth(),
135 this.getHeight());
136 }
137
138 // ... then draw the arrow.
139 if (getModel().isPressed()) {
140 // Adjust color mapping for pressed button state
141 colors[1] = colors[2];
142 }
143 if(orientation == JSplitPane.VERTICAL_SPLIT) {
144 // Draw the image for a vertical split
145 for (int i=1; i<=buffer[0].length; i++) {
146 for (int j=1; j<blockSize; j++) {
147 if (buffer[j-1][i-1] == 0) {
148 continue;
149 }
150 else {
151 g.setColor(
152 colors[buffer[j-1][i-1]]);
153 }
154 g.drawLine(i, j, i, j);
155 }
156 }
157 }
158 else {
159 // Draw the image for a horizontal split
160 // by simply swaping the i and j axis.
161 // Except the drawLine() call this code is
162 // identical to the code block above. This was done
163 // in order to remove the additional orientation
164 // check for each pixel.
165 for (int i=1; i<=buffer[0].length; i++) {
166 for (int j=1; j<blockSize; j++) {
167 if (buffer[j-1][i-1] == 0) {
168 // Nothing needs
169 // to be drawn
170 continue;
171 }
172 else {
173 // Set the color from the
174 // color map
175 g.setColor(
176 colors[buffer[j-1][i-1]]);
177 }
178 // Draw a pixel
179 g.drawLine(j, i, j, i);
180 }
181 }
182 }
183 }
184 }
185
186 // Don't want the button to participate in focus traversable.
187 public boolean isFocusTraversable() {
188 return false;
189 }
190 };
191 b.setRequestFocusEnabled(false);
192 b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
193 b.setFocusPainted(false);
194 b.setBorderPainted(false);
195 maybeMakeButtonOpaque(b);
196 return b;
197 }
198
199 /**
200 * If necessary <code>c</code> is made opaque.
201 */
202 private void maybeMakeButtonOpaque(JComponent c) {
203 Object opaque = UIManager.get("SplitPane.oneTouchButtonsOpaque");
204 if (opaque != null) {
205 c.setOpaque(((Boolean)opaque).booleanValue());
206 }
207 }
208
209 /**
210 * Creates and return an instance of JButton that can be used to
211 * collapse the right component in the metal split pane.
212 */
213 protected JButton createRightOneTouchButton() {
214 JButton b = new JButton() {
215 // Sprite buffer for the arrow image of the right button
216 int[][] buffer = {{2, 2, 2, 2, 2, 2, 2, 2},
217 {0, 1, 1, 1, 1, 1, 1, 3},
218 {0, 0, 1, 1, 1, 1, 3, 0},
219 {0, 0, 0, 1, 1, 3, 0, 0},
220 {0, 0, 0, 0, 3, 0, 0, 0}};
221
222 public void setBorder(Border border) {
223 }
224
225 public void paint(Graphics g) {
226 JSplitPane splitPane = getSplitPaneFromSuper();
227 if(splitPane != null) {
228 int oneTouchSize = getOneTouchSizeFromSuper();
229 int orientation = getOrientationFromSuper();
230 int blockSize = Math.min(getDividerSize(),
231 oneTouchSize);
232
233 // Initialize the color array
234 Color[] colors = {
235 this.getBackground(),
236 MetalLookAndFeel.getPrimaryControlDarkShadow(),
237 MetalLookAndFeel.getPrimaryControlInfo(),
238 MetalLookAndFeel.getPrimaryControlHighlight()};
239
240 // Fill the background first ...
241 g.setColor(this.getBackground());
242 if (isOpaque()) {
243 g.fillRect(0, 0, this.getWidth(),
244 this.getHeight());
245 }
246
247 // ... then draw the arrow.
248 if (getModel().isPressed()) {
249 // Adjust color mapping for pressed button state
250 colors[1] = colors[2];
251 }
252 if(orientation == JSplitPane.VERTICAL_SPLIT) {
253 // Draw the image for a vertical split
254 for (int i=1; i<=buffer[0].length; i++) {
255 for (int j=1; j<blockSize; j++) {
256 if (buffer[j-1][i-1] == 0) {
257 continue;
258 }
259 else {
260 g.setColor(
261 colors[buffer[j-1][i-1]]);
262 }
263 g.drawLine(i, j, i, j);
264 }
265 }
266 }
267 else {
268 // Draw the image for a horizontal split
269 // by simply swaping the i and j axis.
270 // Except the drawLine() call this code is
271 // identical to the code block above. This was done
272 // in order to remove the additional orientation
273 // check for each pixel.
274 for (int i=1; i<=buffer[0].length; i++) {
275 for (int j=1; j<blockSize; j++) {
276 if (buffer[j-1][i-1] == 0) {
277 // Nothing needs
278 // to be drawn
279 continue;
280 }
281 else {
282 // Set the color from the
283 // color map
284 g.setColor(
285 colors[buffer[j-1][i-1]]);
286 }
287 // Draw a pixel
288 g.drawLine(j, i, j, i);
289 }
290 }
291 }
292 }
293 }
294
295 // Don't want the button to participate in focus traversable.
296 public boolean isFocusTraversable() {
297 return false;
298 }
299 };
300 b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
301 b.setFocusPainted(false);
302 b.setBorderPainted(false);
303 b.setRequestFocusEnabled(false);
304 maybeMakeButtonOpaque(b);
305 return b;
306 }
307
308 /**
309 * Used to layout a MetalSplitPaneDivider. Layout for the divider
310 * involves appropriately moving the left/right buttons around.
311 * <p>
312 * This class should be treated as a &quot;protected&quot; inner class.
313 * Instantiate it only within subclasses of MetalSplitPaneDivider.
314 */
315 public class MetalDividerLayout implements LayoutManager {
316
317 // NOTE NOTE NOTE NOTE NOTE
318 // This class is no longer used, the functionality has
319 // been rolled into BasicSplitPaneDivider.DividerLayout as a
320 // defaults property
321
322 public void layoutContainer(Container c) {
323 JButton leftButton = getLeftButtonFromSuper();
324 JButton rightButton = getRightButtonFromSuper();
325 JSplitPane splitPane = getSplitPaneFromSuper();
326 int orientation = getOrientationFromSuper();
327 int oneTouchSize = getOneTouchSizeFromSuper();
328 int oneTouchOffset = getOneTouchOffsetFromSuper();
329 Insets insets = getInsets();
330
331 // This layout differs from the one used in BasicSplitPaneDivider.
332 // It does not center justify the oneTouchExpadable buttons.
333 // This was necessary in order to meet the spec of the Metal
334 // splitpane divider.
335 if (leftButton != null && rightButton != null &&
336 c == MetalSplitPaneDivider.this) {
337 if (splitPane.isOneTouchExpandable()) {
338 if (orientation == JSplitPane.VERTICAL_SPLIT) {
339 int extraY = (insets != null) ? insets.top : 0;
340 int blockSize = getDividerSize();
341
342 if (insets != null) {
343 blockSize -= (insets.top + insets.bottom);
344 }
345 blockSize = Math.min(blockSize, oneTouchSize);
346 leftButton.setBounds(oneTouchOffset, extraY,
347 blockSize * 2, blockSize);
348 rightButton.setBounds(oneTouchOffset +
349 oneTouchSize * 2, extraY,
350 blockSize * 2, blockSize);
351 }
352 else {
353 int blockSize = getDividerSize();
354 int extraX = (insets != null) ? insets.left : 0;
355
356 if (insets != null) {
357 blockSize -= (insets.left + insets.right);
358 }
359 blockSize = Math.min(blockSize, oneTouchSize);
360 leftButton.setBounds(extraX, oneTouchOffset,
361 blockSize, blockSize * 2);
362 rightButton.setBounds(extraX, oneTouchOffset +
363 oneTouchSize * 2, blockSize,
364 blockSize * 2);
365 }
366 }
367 else {
368 leftButton.setBounds(-5, -5, 1, 1);
369 rightButton.setBounds(-5, -5, 1, 1);
370 }
371 }
372 }
373
374 public Dimension minimumLayoutSize(Container c) {
375 return new Dimension(0,0);
376 }
377
378 public Dimension preferredLayoutSize(Container c) {
379 return new Dimension(0, 0);
380 }
381
382 public void removeLayoutComponent(Component c) {}
383
384 public void addLayoutComponent(String string, Component c) {}
385 }
386
387 /*
388 * The following methods only exist in order to be able to access protected
389 * members in the superclass, because these are otherwise not available
390 * in any inner class.
391 */
392
393 int getOneTouchSizeFromSuper() {
394 return super.ONE_TOUCH_SIZE;
395 }
396
397 int getOneTouchOffsetFromSuper() {
398 return super.ONE_TOUCH_OFFSET;
399 }
400
401 int getOrientationFromSuper() {
402 return super.orientation;
403 }
404
405 JSplitPane getSplitPaneFromSuper() {
406 return super.splitPane;
407 }
408
409 JButton getLeftButtonFromSuper() {
410 return super.leftButton;
411 }
412
413 JButton getRightButtonFromSuper() {
414 return super.rightButton;
415 }
416}