001: /*
002: * FlatSplitPaneDivider.java
003: *
004: * Copyright (C) 2002, 2003, 2004, 2005, 2006 Takis Diakoumis
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: */
021:
022: package org.underworldlabs.swing.plaf;
023:
024: import java.awt.Color;
025: import java.awt.Component;
026: import java.awt.Container;
027: import java.awt.Cursor;
028: import java.awt.Dimension;
029: import java.awt.Graphics;
030: import java.awt.Insets;
031: import java.awt.LayoutManager;
032:
033: import javax.swing.JButton;
034: import javax.swing.JSplitPane;
035:
036: import javax.swing.border.Border;
037:
038: import javax.swing.plaf.basic.BasicSplitPaneDivider;
039: import javax.swing.plaf.basic.BasicSplitPaneUI;
040:
041: import javax.swing.plaf.metal.MetalLookAndFeel;
042:
043: /*
044: * @(#)MetalSplitPaneUI.java 1.9 03/01/23
045: *
046: * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
047: * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
048: */
049:
050: /* ----------------------------------------------------------
051: * CVS NOTE: Changes to the CVS repository prior to the
052: * release of version 3.0.0beta1 has meant a
053: * resetting of CVS revision numbers.
054: * ----------------------------------------------------------
055: */
056:
057: /**
058: * Modified metal split pane divider
059: */
060: /**
061: *
062: * @author Takis Diakoumis
063: * @version $Revision: 1.4 $
064: * @date $Date: 2006/05/14 06:56:07 $
065: */
066: public class FlatSplitPaneDivider extends BasicSplitPaneDivider {
067:
068: private int inset = 2;
069:
070: public FlatSplitPaneDivider(BasicSplitPaneUI ui) {
071: super (ui);
072: setLayout(new FlapSplitPaneDividerLayout());
073: }
074:
075: // --------------------------------------------
076: // the main thing we have done here is to remove
077: // the metal bumps from the divider. all else remains
078: // the same as in MetalSplitPaneUI. the aim was to
079: // remove the bumps but retain the small buttons.
080: // --------------------------------------------
081:
082: public void paint(Graphics g) {
083: super .paint(g);
084: }
085:
086: /**
087: * Creates and return an instance of JButton that can be used to
088: * collapse the left component in the metal split pane.
089: */
090: protected JButton createLeftOneTouchButton() {
091: JButton b = new JButton() {
092: // Sprite buffer for the arrow image of the left button
093: int[][] buffer = { { 0, 0, 0, 2, 2, 0, 0, 0, 0 },
094: { 0, 0, 2, 1, 1, 1, 0, 0, 0 },
095: { 0, 2, 1, 1, 1, 1, 1, 0, 0 },
096: { 2, 1, 1, 1, 1, 1, 1, 1, 0 },
097: { 0, 3, 3, 3, 3, 3, 3, 3, 3 } };
098:
099: public void setBorder(Border b) {
100: }
101:
102: public void paint(Graphics g) {
103: JSplitPane splitPane = getSplitPaneFromSuper();
104: if (splitPane != null) {
105: int oneTouchSize = getOneTouchSizeFromSuper();
106: int orientation = getOrientationFromSuper();
107: int blockSize = Math.min(getDividerSize(),
108: oneTouchSize);
109:
110: // Initialize the color array
111: Color[] colors = {
112: this .getBackground(),
113: MetalLookAndFeel
114: .getPrimaryControlDarkShadow(),
115: MetalLookAndFeel.getPrimaryControlInfo(),
116: MetalLookAndFeel
117: .getPrimaryControlHighlight() };
118:
119: // Fill the background first ...
120: g.setColor(this .getBackground());
121: g.fillRect(0, 0, this .getWidth(), this .getHeight());
122:
123: // ... then draw the arrow.
124: if (getModel().isPressed()) {
125: // Adjust color mapping for pressed button state
126: colors[1] = colors[2];
127: }
128: if (orientation == JSplitPane.VERTICAL_SPLIT) {
129: // Draw the image for a vertical split
130: for (int i = 1; i <= buffer[0].length; i++) {
131: for (int j = 1; j < blockSize; j++) {
132: if (buffer[j - 1][i - 1] == 0) {
133: continue;
134: } else {
135: g
136: .setColor(colors[buffer[j - 1][i - 1]]);
137: }
138: g.drawLine(i, j, i, j);
139: }
140: }
141: } else {
142: // Draw the image for a horizontal split
143: // by simply swaping the i and j axis.
144: // Except the drawLine() call this code is
145: // identical to the code block above. This was done
146: // in order to remove the additional orientation
147: // check for each pixel.
148: for (int i = 1; i <= buffer[0].length; i++) {
149: for (int j = 1; j < blockSize; j++) {
150: if (buffer[j - 1][i - 1] == 0) {
151: // Nothing needs
152: // to be drawn
153: continue;
154: } else {
155: // Set the color from the
156: // color map
157: g
158: .setColor(colors[buffer[j - 1][i - 1]]);
159: }
160: // Draw a pixel
161: g.drawLine(j, i, j, i);
162: }
163: }
164: }
165: }
166: }
167:
168: // Don't want the button to participate in focus traversable.
169: public boolean isFocusTraversable() {
170: return false;
171: }
172: };
173:
174: b.setRequestFocusEnabled(false);
175: b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
176: b.setFocusPainted(false);
177: b.setBorderPainted(false);
178: return b;
179: }
180:
181: /**
182: * Creates and return an instance of JButton that can be used to
183: * collapse the right component in the metal split pane.
184: */
185: protected JButton createRightOneTouchButton() {
186: JButton b = new JButton() {
187: // Sprite buffer for the arrow image of the right button
188: int[][] buffer = { { 2, 2, 2, 2, 2, 2, 2, 2 },
189: { 0, 1, 1, 1, 1, 1, 1, 3 },
190: { 0, 0, 1, 1, 1, 1, 3, 0 },
191: { 0, 0, 0, 1, 1, 3, 0, 0 },
192: { 0, 0, 0, 0, 3, 0, 0, 0 } };
193:
194: public void setBorder(Border border) {
195: }
196:
197: public void paint(Graphics g) {
198: JSplitPane splitPane = getSplitPaneFromSuper();
199: if (splitPane != null) {
200: int oneTouchSize = getOneTouchSizeFromSuper();
201: int orientation = getOrientationFromSuper();
202: int blockSize = Math.min(getDividerSize(),
203: oneTouchSize);
204:
205: // Initialize the color array
206: Color[] colors = {
207: this .getBackground(),
208: MetalLookAndFeel
209: .getPrimaryControlDarkShadow(),
210: MetalLookAndFeel.getPrimaryControlInfo(),
211: MetalLookAndFeel
212: .getPrimaryControlHighlight() };
213:
214: // Fill the background first ...
215: g.setColor(this .getBackground());
216: g.fillRect(0, 0, this .getWidth(), this .getHeight());
217:
218: // ... then draw the arrow.
219: if (getModel().isPressed()) {
220: // Adjust color mapping for pressed button state
221: colors[1] = colors[2];
222: }
223: if (orientation == JSplitPane.VERTICAL_SPLIT) {
224: // Draw the image for a vertical split
225: for (int i = 1; i <= buffer[0].length; i++) {
226: for (int j = 1; j < blockSize; j++) {
227: if (buffer[j - 1][i - 1] == 0) {
228: continue;
229: } else {
230: g
231: .setColor(colors[buffer[j - 1][i - 1]]);
232: }
233: g.drawLine(i, j, i, j);
234: }
235: }
236: } else {
237: // Draw the image for a horizontal split
238: // by simply swaping the i and j axis.
239: // Except the drawLine() call this code is
240: // identical to the code block above. This was done
241: // in order to remove the additional orientation
242: // check for each pixel.
243: for (int i = 1; i <= buffer[0].length; i++) {
244: for (int j = 1; j < blockSize; j++) {
245: if (buffer[j - 1][i - 1] == 0) {
246: // Nothing needs
247: // to be drawn
248: continue;
249: } else {
250: // Set the color from the
251: // color map
252: g
253: .setColor(colors[buffer[j - 1][i - 1]]);
254: }
255: // Draw a pixel
256: g.drawLine(j, i, j, i);
257: }
258: }
259: }
260: }
261: }
262:
263: // Don't want the button to participate in focus traversable.
264: public boolean isFocusTraversable() {
265: return false;
266: }
267: };
268:
269: b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
270: b.setFocusPainted(false);
271: b.setBorderPainted(false);
272: b.setRequestFocusEnabled(false);
273: return b;
274: }
275:
276: /**
277: * Used to layout a MetalSplitPaneDivider. Layout for the divider
278: * involves appropriately moving the left/right buttons around.
279: * <p>
280: * This inner class is marked "public" due to a compiler bug.
281: * This class should be treated as a "protected" inner class.
282: * Instantiate it only within subclasses of MetalSplitPaneDivider.
283: */
284: public class FlapSplitPaneDividerLayout implements LayoutManager {
285:
286: public void layoutContainer(Container c) {
287:
288: JButton leftButton = getLeftButtonFromSuper();
289: JButton rightButton = getRightButtonFromSuper();
290: JSplitPane splitPane = getSplitPaneFromSuper();
291: int orientation = getOrientationFromSuper();
292: int oneTouchSize = getOneTouchSizeFromSuper();
293: int oneTouchOffset = getOneTouchOffsetFromSuper();
294: Insets insets = getInsets();
295:
296: // This layout differs from the one used in BasicSplitPaneDivider.
297: // It does not center justify the oneTouchExpadable buttons.
298: // This was necessary in order to meet the spec of the Metal
299: // splitpane divider.
300: if (leftButton != null && rightButton != null
301: && c == FlatSplitPaneDivider.this ) {
302:
303: if (splitPane.isOneTouchExpandable()) {
304:
305: if (orientation == JSplitPane.VERTICAL_SPLIT) {
306: int extraY = (insets != null) ? insets.top : 0;
307: int blockSize = getDividerSize();
308:
309: if (insets != null) {
310: blockSize -= (insets.top + insets.bottom);
311: }
312: extraY = 2;
313: blockSize = Math.min(blockSize, oneTouchSize);
314: leftButton.setBounds(oneTouchOffset, extraY,
315: blockSize * 2, blockSize);
316: rightButton.setBounds(oneTouchOffset
317: + oneTouchSize * 2, extraY,
318: blockSize * 2, blockSize);
319: }
320:
321: else {
322: int blockSize = getDividerSize();
323: int extraX = (insets != null) ? insets.left : 0;
324:
325: if (insets != null) {
326: blockSize -= (insets.left + insets.right);
327: }
328:
329: blockSize = Math.min(blockSize, oneTouchSize);
330: leftButton.setBounds(extraX, oneTouchOffset,
331: blockSize, blockSize * 2);
332: rightButton.setBounds(extraX, oneTouchOffset
333: + oneTouchSize * 2, blockSize,
334: blockSize * 2);
335: }
336:
337: }
338:
339: else {
340: leftButton.setBounds(-5, -5, 1, 1);
341: rightButton.setBounds(-5, -5, 1, 1);
342: }
343: }
344:
345: }
346:
347: public Dimension minimumLayoutSize(Container c) {
348: return new Dimension(0, 0);
349: }
350:
351: public Dimension preferredLayoutSize(Container c) {
352: return new Dimension(0, 0);
353: }
354:
355: public void removeLayoutComponent(Component c) {
356: }
357:
358: public void addLayoutComponent(String string, Component c) {
359: }
360: }
361:
362: /*
363: * The following methods only exist in order to be able to access protected
364: * members in the superclass, because these are otherwise not available
365: * in any inner class.
366: */
367:
368: int getOneTouchSizeFromSuper() {
369: return super .ONE_TOUCH_SIZE;
370: }
371:
372: int getOneTouchOffsetFromSuper() {
373: return super .ONE_TOUCH_OFFSET;
374: }
375:
376: int getOrientationFromSuper() {
377: return super .orientation;
378: }
379:
380: JSplitPane getSplitPaneFromSuper() {
381: return super .splitPane;
382: }
383:
384: JButton getLeftButtonFromSuper() {
385: return super .leftButton;
386: }
387:
388: JButton getRightButtonFromSuper() {
389: return super.rightButton;
390: }
391: }
|