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.plastic;
032:
033: import java.awt.Color;
034: import java.awt.Component;
035: import java.awt.Graphics;
036:
037: import javax.swing.JComponent;
038: import javax.swing.SwingConstants;
039: import javax.swing.UIManager;
040: import javax.swing.plaf.ComponentUI;
041: import javax.swing.plaf.metal.MetalLookAndFeel;
042:
043: import com.jgoodies.looks.common.ExtBasicArrowButtonHandler;
044:
045: /**
046: * The JGoodies PlasticXP Look&Feel implementation of <code>SpinnerUI</code>.
047: * Configures the default editor to adjust font baselines and component
048: * bounds. Also, changes the border of the buttons and the size of the arrows.
049: *
050: * @author Karsten Lentzsch
051: * @version $Revision: 1.4 $
052: */
053: public final class PlasticXPSpinnerUI extends PlasticSpinnerUI {
054:
055: public static ComponentUI createUI(JComponent b) {
056: return new PlasticXPSpinnerUI();
057: }
058:
059: /**
060: * The mouse/action listeners that are added to the spinner's
061: * arrow buttons. These listeners are shared by all
062: * spinner arrow buttons.
063: *
064: * @see #createNextButton
065: * @see #createPreviousButton
066: */
067: private static final ExtBasicArrowButtonHandler NEXT_BUTTON_HANDLER = new ExtBasicArrowButtonHandler(
068: "increment", true);
069: private static final ExtBasicArrowButtonHandler PREVIOUS_BUTTON_HANDLER = new ExtBasicArrowButtonHandler(
070: "decrement", false);
071:
072: /**
073: * Create a component that will replace the spinner models value
074: * with the object returned by <code>spinner.getPreviousValue</code>.
075: * By default the <code>previousButton</code> is a JButton
076: * who's <code>ActionListener</code> updates it's <code>JSpinner</code>
077: * ancestors model. If a previousButton isn't needed (in a subclass)
078: * then override this method to return null.
079: *
080: * @return a component that will replace the spinners model with the
081: * next value in the sequence, or null
082: * @see #installUI
083: * @see #createNextButton
084: */
085: protected Component createPreviousButton() {
086: return new SpinnerXPArrowButton(SwingConstants.SOUTH,
087: PREVIOUS_BUTTON_HANDLER);
088: }
089:
090: /**
091: * Create a component that will replace the spinner models value
092: * with the object returned by <code>spinner.getNextValue</code>.
093: * By default the <code>nextButton</code> is a JButton
094: * who's <code>ActionListener</code> updates it's <code>JSpinner</code>
095: * ancestors model. If a nextButton isn't needed (in a subclass)
096: * then override this method to return null.
097: *
098: * @return a component that will replace the spinners model with the
099: * next value in the sequence, or null
100: * @see #installUI
101: * @see #createPreviousButton
102: */
103: protected Component createNextButton() {
104: return new SpinnerXPArrowButton(SwingConstants.NORTH,
105: NEXT_BUTTON_HANDLER);
106: }
107:
108: /**
109: * It differs from its superclass in that it uses the same formula as JDK
110: * to calculate the arrow height.
111: */
112: private static final class SpinnerXPArrowButton extends
113: PlasticArrowButton {
114:
115: SpinnerXPArrowButton(int direction,
116: ExtBasicArrowButtonHandler handler) {
117: // If you change the value of the button width, don't forget
118: // to change it in PlasticXPBorders#XPSpinnerBorder too.
119: super (direction, UIManager.getInt("ScrollBar.width") - 1,
120: false);
121: addActionListener(handler);
122: addMouseListener(handler);
123: }
124:
125: protected int calculateArrowHeight(int height, int width) {
126: int arrowHeight = Math.min((height - 4) / 3,
127: (width - 4) / 3);
128: return Math.max(arrowHeight, 3);
129: }
130:
131: protected boolean isPaintingNorthBottom() {
132: return true;
133: }
134:
135: protected int calculateArrowOffset() {
136: return 1;
137: }
138:
139: protected void paintNorth(Graphics g, boolean leftToRight,
140: boolean isEnabled, Color arrowColor, boolean isPressed,
141: int width, int height, int w, int h, int arrowHeight,
142: int arrowOffset, boolean paintBottom) {
143: if (!isFreeStanding) {
144: height += 1;
145: g.translate(0, -1);
146: if (!leftToRight) {
147: width += 1;
148: g.translate(-1, 0);
149: } else {
150: width += 2;
151: }
152: }
153:
154: // Draw the arrow
155: g.setColor(arrowColor);
156: int startY = 1 + ((h + 1) - arrowHeight) / 2; // KL was (h + 1)
157: int startX = w / 2;
158: // System.out.println( "startX :" + startX + " startY :"+startY);
159: for (int line = 0; line < arrowHeight; line++) {
160: g.fillRect(startX - line - arrowOffset, startY + line,
161: 2 * (line + 1), 1);
162: }
163:
164: paintNorthBorder(g, isEnabled, width, height, paintBottom);
165:
166: if (!isFreeStanding) {
167: height -= 1;
168: g.translate(0, 1);
169: if (!leftToRight) {
170: width -= 1;
171: g.translate(1, 0);
172: } else {
173: width -= 2;
174: }
175: }
176: }
177:
178: private void paintNorthBorder(Graphics g, boolean isEnabled,
179: int w, int h, boolean paintBottom) {
180: if (isEnabled) {
181: boolean isPressed = model.isPressed()
182: && model.isArmed();
183: if (isPressed) {
184: PlasticXPUtils.drawPressedButtonBorder(g, 0, 1,
185: w - 2, h);
186: } else {
187: PlasticXPUtils.drawPlainButtonBorder(g, 0, 1,
188: w - 2, h);
189: }
190: } else {
191: PlasticXPUtils.drawDisabledButtonBorder(g, 0, 1, w - 2,
192: h + 1);
193: }
194: // Paint one pixel on the arrow button's left hand side.
195: g.setColor(isEnabled ? PlasticLookAndFeel
196: .getControlDarkShadow() : MetalLookAndFeel
197: .getControlShadow());
198: g.fillRect(0, 1, 1, 1);
199:
200: if (paintBottom) {
201: g.fillRect(0, h - 1, w - 1, 1);
202: }
203: }
204:
205: protected void paintSouth(Graphics g, boolean leftToRight,
206: boolean isEnabled, Color arrowColor, boolean isPressed,
207: int width, int height, int w, int h, int arrowHeight,
208: int arrowOffset) {
209:
210: if (!isFreeStanding) {
211: height += 1;
212: if (!leftToRight) {
213: width += 1;
214: g.translate(-1, 0);
215: } else {
216: width += 2;
217: }
218: }
219:
220: // Draw the arrow
221: g.setColor(arrowColor);
222:
223: int startY = (((h + 0) - arrowHeight) / 2) + arrowHeight
224: - 2; // KL was h + 1
225: int startX = w / 2;
226:
227: //System.out.println( "startX2 :" + startX + " startY2 :"+startY);
228:
229: for (int line = 0; line < arrowHeight; line++) {
230: g.fillRect(startX - line - arrowOffset, startY - line,
231: 2 * (line + 1), 1);
232: }
233:
234: paintSouthBorder(g, isEnabled, width, height);
235:
236: if (!isFreeStanding) {
237: height -= 1;
238: if (!leftToRight) {
239: width -= 1;
240: g.translate(1, 0);
241: } else {
242: width -= 2;
243: }
244: }
245: }
246:
247: private void paintSouthBorder(Graphics g, boolean isEnabled,
248: int w, int h) {
249: if (isEnabled) {
250: boolean isPressed = model.isPressed()
251: && model.isArmed();
252: if (isPressed) {
253: PlasticXPUtils.drawPressedButtonBorder(g, 0, -2,
254: w - 2, h + 1);
255: } else {
256: PlasticXPUtils.drawPlainButtonBorder(g, 0, -2,
257: w - 2, h + 1);
258: }
259: } else {
260: PlasticXPUtils.drawDisabledButtonBorder(g, 0, -2,
261: w - 2, h + 1);
262: }
263: // Paint one pixel on the arrow button's left hand side.
264: g.setColor(isEnabled ? PlasticLookAndFeel
265: .getControlDarkShadow() : MetalLookAndFeel
266: .getControlShadow());
267: g.fillRect(0, h - 2, 1, 1);
268: }
269:
270: }
271:
272: }
|