001: /*
002: * Copyright (c) 2001-2007 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.looks.windows;
032:
033: import java.awt.Color;
034: import java.awt.Component;
035: import java.awt.Container;
036: import java.awt.Dimension;
037: import java.awt.Graphics;
038: import java.awt.LayoutManager;
039:
040: import javax.swing.JButton;
041: import javax.swing.JSplitPane;
042: import javax.swing.UIManager;
043: import javax.swing.border.Border;
044: import javax.swing.plaf.basic.BasicSplitPaneDivider;
045: import javax.swing.plaf.basic.BasicSplitPaneUI;
046:
047: /**
048: * Paints nicely rendered one touch triangles.
049: *
050: * @author Karsten Lentzsch
051: * @version $Revision: 1.4 $
052: *
053: * @see WindowsSplitPaneUI
054: */
055: final class WindowsSplitPaneDivider extends BasicSplitPaneDivider {
056:
057: private static final int EXT_ONE_TOUCH_SIZE = 5;
058: private static final int EXT_ONE_TOUCH_OFFSET = 2;
059: private static final int EXT_BLOCKSIZE = 6;
060:
061: /**
062: * Used to lay out a WindowsSplitPaneDivider. Layout for the divider
063: * involves appropriately moving the left/right buttons around.
064: * <p>
065: * This inner class is marked "public" due to a compiler bug.
066: * This class should be treated as a "protected" inner class.
067: * Instantiate it only within subclasses of MetalSplitPaneDivider.
068: */
069: public final class ExtWindowsDividerLayout implements LayoutManager {
070: public void layoutContainer(Container c) {
071: JButton theLeftButton = getLeftButtonFromSuper();
072: JButton theRightButton = getRightButtonFromSuper();
073: JSplitPane theSplitPane = getSplitPaneFromSuper();
074: int theOrientation = getOrientationFromSuper();
075: int oneTouchSize = getOneTouchSize();
076: int oneTouchOffset = getOneTouchOffset();
077: int blockSize = 5;
078: //getBlockSize(); //Math.min(getDividerSize(), oneTouchSize);
079:
080: // This layout differs from the one used in BasicSplitPaneDivider.
081: // It does not center justify the oneTouchExpadable buttons.
082: // This was necessary in order to meet the spec of the Metal
083: // splitpane divider.
084: if (theLeftButton != null && theRightButton != null
085: && c == WindowsSplitPaneDivider.this ) {
086: if (theSplitPane.isOneTouchExpandable()) {
087: if (theOrientation == JSplitPane.VERTICAL_SPLIT) {
088: theLeftButton.setBounds(oneTouchOffset, 0,
089: blockSize * 2, blockSize);
090: theRightButton.setBounds(oneTouchOffset
091: + oneTouchSize * 2, 0, blockSize * 2,
092: blockSize);
093: } else {
094: theLeftButton.setBounds(0, oneTouchOffset,
095: blockSize, blockSize * 2);
096: theRightButton.setBounds(0, oneTouchOffset
097: + oneTouchSize * 2, blockSize,
098: blockSize * 2);
099: }
100: } else {
101: theLeftButton.setBounds(-5, -5, 1, 1);
102: theRightButton.setBounds(-5, -5, 1, 1);
103: }
104: }
105: }
106:
107: public Dimension minimumLayoutSize(Container c) {
108: return new Dimension(0, 0);
109: }
110:
111: public Dimension preferredLayoutSize(Container c) {
112: return new Dimension(0, 0);
113: }
114:
115: public void removeLayoutComponent(Component c) {
116: // Unused method; implements LayoutManager.
117: }
118:
119: public void addLayoutComponent(String string, Component c) {
120: // Unused method; implements LayoutManager.
121: }
122: }
123:
124: public WindowsSplitPaneDivider(BasicSplitPaneUI ui) {
125: super (ui);
126: setLayout(new ExtWindowsDividerLayout());
127: }
128:
129: /**
130: * Creates and return an instance of JButton that can be used to
131: * collapse the left component in the metal split pane.
132: */
133: protected JButton createLeftOneTouchButton() {
134: JButton b = new JButton() {
135: // Sprite buffer for the arrow image of the left button
136: int[][] buffer = { { 0, 0, 0, 2, 2, 0, 0, 0, 0 },
137: { 0, 0, 2, 1, 1, 1, 0, 0, 0 },
138: { 0, 2, 1, 1, 1, 1, 1, 0, 0 },
139: { 2, 1, 1, 1, 1, 1, 1, 1, 0 },
140: { 0, 3, 3, 3, 3, 3, 3, 3, 3 } };
141:
142: public void setBorder(Border border) {
143: // Ignore borders
144: }
145:
146: public void paint(Graphics g) {
147: JSplitPane theSplitPane = getSplitPaneFromSuper();
148: if (theSplitPane != null) {
149: int theOrientation = getOrientationFromSuper();
150: int blockSize = buffer.length + 1;
151: //Math.min(getDividerSize(), oneTouchSize);
152:
153: // Initialize the color array
154: Color[] colors = { this .getBackground(),
155: UIManager.getColor("controlDkShadow"),
156: Color.black,
157: //UIManager.getColor(),
158: UIManager.getColor("controlLtHighlight") };
159:
160: // Fill the background first ...
161: g.setColor(this .getBackground());
162: g.fillRect(0, 0, this .getWidth(), this .getHeight());
163:
164: // ... then draw the arrow.
165: if (getModel().isPressed()) {
166: // Adjust color mapping for pressed button state
167: colors[1] = colors[2];
168: }
169: if (theOrientation == JSplitPane.VERTICAL_SPLIT) {
170: // Draw the image for a vertical split
171: for (int i = 1; i <= buffer[0].length; i++) {
172: for (int j = 1; j < blockSize; j++) {
173: if (buffer[j - 1][i - 1] == 0) {
174: continue;
175: }
176: g
177: .setColor(colors[buffer[j - 1][i - 1]]);
178: g.drawLine(i - 1, j, i - 1, j);
179: }
180: }
181: } else {
182: // Draw the image for a horizontal split
183: // by simply swaping the i and j axis.
184: // Except the drawLine() call this code is
185: // identical to the code block above. This was done
186: // in order to remove the additional orientation
187: // check for each pixel.
188: for (int i = 1; i <= buffer[0].length; i++) {
189: for (int j = 1; j < blockSize; j++) {
190: if (buffer[j - 1][i - 1] == 0) {
191: // Nothing needs
192: // to be drawn
193: continue;
194: }
195: // Set the color from the
196: // color map
197: g
198: .setColor(colors[buffer[j - 1][i - 1]]);
199: // Draw a pixel
200: g.drawLine(j - 1, i, j - 1, i);
201: }
202: }
203: }
204: }
205: }
206:
207: };
208: b.setFocusPainted(false);
209: b.setBorderPainted(false);
210: b.setFocusable(false);
211: b.setOpaque(false);
212: return b;
213: }
214:
215: /**
216: * Creates and return an instance of JButton that can be used to
217: * collapse the right component in the metal split pane.
218: */
219: protected JButton createRightOneTouchButton() {
220: JButton b = new JButton() {
221: // Sprite buffer for the arrow image of the right button
222: int[][] buffer = { { 2, 2, 2, 2, 2, 2, 2, 2 },
223: { 0, 1, 1, 1, 1, 1, 1, 3 },
224: { 0, 0, 1, 1, 1, 1, 3, 0 },
225: { 0, 0, 0, 1, 1, 3, 0, 0 },
226: { 0, 0, 0, 0, 3, 0, 0, 0 } };
227:
228: public void setBorder(Border border) {
229: // Ignore borders
230: }
231:
232: public void paint(Graphics g) {
233: JSplitPane theSplitPane = getSplitPaneFromSuper();
234: if (theSplitPane != null) {
235: int theOrientation = getOrientationFromSuper();
236: int blockSize = buffer.length + 1;
237: //Math.min(getDividerSize(), oneTouchSize);
238:
239: // Initialize the color array
240: Color[] colors = { this .getBackground(),
241: UIManager.getColor("controlDkShadow"),
242: Color.black,
243: //UIManager.getColor("controlDkShadow"),
244: UIManager.getColor("controlLtHighlight") };
245:
246: // Fill the background first ...
247: g.setColor(this .getBackground());
248: g.fillRect(0, 0, this .getWidth(), this .getHeight());
249:
250: // ... then draw the arrow.
251: if (getModel().isPressed()) {
252: // Adjust color mapping for pressed button state
253: colors[1] = colors[2];
254: }
255: if (theOrientation == JSplitPane.VERTICAL_SPLIT) {
256: // Draw the image for a vertical split
257: for (int i = 1; i <= buffer[0].length; i++) {
258: for (int j = 1; j < blockSize; j++) {
259: if (buffer[j - 1][i - 1] == 0) {
260: continue;
261: }
262: g
263: .setColor(colors[buffer[j - 1][i - 1]]);
264: g.drawLine(i, j, i, j);
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: // Set the color from the
282: // color map
283: g
284: .setColor(colors[buffer[j - 1][i - 1]]);
285: // Draw a pixel
286: g.drawLine(j - 1, i, j - 1, i);
287: }
288: }
289: }
290: }
291: }
292: };
293: b.setFocusPainted(false);
294: b.setBorderPainted(false);
295: b.setFocusable(false);
296: b.setOpaque(false);
297: return b;
298: }
299:
300: int getBlockSize() {
301: return EXT_BLOCKSIZE;
302: }
303:
304: int getOneTouchOffset() {
305: return EXT_ONE_TOUCH_OFFSET;
306: }
307:
308: int getOneTouchSize() {
309: return EXT_ONE_TOUCH_SIZE;
310: }
311:
312: int getOrientationFromSuper() {
313: return super .orientation;
314: }
315:
316: JButton getLeftButtonFromSuper() {
317: return super .leftButton;
318: }
319:
320: JButton getRightButtonFromSuper() {
321: return super .rightButton;
322: }
323:
324: JSplitPane getSplitPaneFromSuper() {
325: return super .splitPane;
326: }
327:
328: public void paint(Graphics g) {
329: if (splitPane.isOpaque()) {
330: Color bgColor = splitPane.hasFocus() ? UIManager
331: .getColor("SplitPane.shadow") : getBackground();
332:
333: if (bgColor != null) {
334: g.setColor(bgColor);
335: g.fillRect(0, 0, getWidth(), getHeight());
336: }
337: }
338: super.paint(g);
339: }
340:
341: }
|