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.Component;
034: import java.awt.Graphics;
035: import java.awt.Insets;
036:
037: import javax.swing.*;
038: import javax.swing.border.AbstractBorder;
039: import javax.swing.border.Border;
040: import javax.swing.border.CompoundBorder;
041: import javax.swing.plaf.BorderUIResource;
042: import javax.swing.plaf.UIResource;
043: import javax.swing.plaf.basic.BasicBorders;
044: import javax.swing.plaf.metal.MetalBorders;
045: import javax.swing.plaf.metal.MetalLookAndFeel;
046: import javax.swing.text.JTextComponent;
047:
048: /**
049: * This class consists of a set of <code>Border</code>s used
050: * by the JGoodies Plastic XP Look and Feel UI delegates.
051: *
052: * @author Karsten Lentzsch
053: * @author Andrej Golovnin
054: * @version $Revision: 1.10 $
055: */
056:
057: final class PlasticXPBorders {
058:
059: private PlasticXPBorders() {
060: // Overrides default constructor; prevents instantiation.
061: }
062:
063: // Accessing and Creating Borders ***************************************
064:
065: private static Border comboBoxArrowButtonBorder;
066: private static Border comboBoxEditorBorder;
067: private static Border scrollPaneBorder;
068: private static Border textFieldBorder;
069: private static Border spinnerBorder;
070: private static Border rolloverButtonBorder;
071:
072: /*
073: * Returns a border instance for a <code>JButton</code>.
074: */
075: static Border getButtonBorder(Insets buttonMargin) {
076: return new BorderUIResource.CompoundBorderUIResource(
077: new XPButtonBorder(buttonMargin),
078: new BasicBorders.MarginBorder());
079: }
080:
081: /*
082: * Returns a border instance for a <code>JComboBox</code>'s arrow button.
083: */
084: static Border getComboBoxArrowButtonBorder() {
085: if (comboBoxArrowButtonBorder == null) {
086: comboBoxArrowButtonBorder = new CompoundBorder(
087: // No UIResource
088: new XPComboBoxArrowButtonBorder(),
089: new BasicBorders.MarginBorder());
090: }
091: return comboBoxArrowButtonBorder;
092: }
093:
094: /*
095: * Returns a border instance for a <code>JComboBox</code>'s editor.
096: */
097: static Border getComboBoxEditorBorder() {
098: if (comboBoxEditorBorder == null) {
099: comboBoxEditorBorder = new CompoundBorder(
100: // No UIResource
101: new XPComboBoxEditorBorder(),
102: new BasicBorders.MarginBorder());
103: }
104: return comboBoxEditorBorder;
105: }
106:
107: /*
108: * Returns a border instance for a <code>JScrollPane</code>.
109: */
110: static Border getScrollPaneBorder() {
111: if (scrollPaneBorder == null) {
112: scrollPaneBorder = new XPScrollPaneBorder();
113: }
114: return scrollPaneBorder;
115: }
116:
117: /*
118: * Returns a border instance for a <code>JTextField</code>.
119: */
120: static Border getTextFieldBorder() {
121: if (textFieldBorder == null) {
122: textFieldBorder = new BorderUIResource.CompoundBorderUIResource(
123: new XPTextFieldBorder(),
124: new BasicBorders.MarginBorder());
125: }
126: return textFieldBorder;
127: }
128:
129: /*
130: * Returns a border instance for a <code>JToggleButton</code>.
131: */
132: static Border getToggleButtonBorder(Insets buttonMargin) {
133: return new BorderUIResource.CompoundBorderUIResource(
134: new XPButtonBorder(buttonMargin),
135: new BasicBorders.MarginBorder());
136: }
137:
138: /*
139: * Returns a border instance for a <code>JSpinner</code>.
140: */
141: static Border getSpinnerBorder() {
142: if (spinnerBorder == null) {
143: spinnerBorder = new XPSpinnerBorder();
144: }
145: return spinnerBorder;
146: }
147:
148: /**
149: * Returns a rollover border for buttons in a <code>JToolBar</code>.
150: *
151: * @return the lazily created rollover button border
152: */
153: static Border getRolloverButtonBorder() {
154: if (rolloverButtonBorder == null) {
155: rolloverButtonBorder = new CompoundBorder(
156: new RolloverButtonBorder(),
157: new PlasticBorders.RolloverMarginBorder());
158: }
159: return rolloverButtonBorder;
160: }
161:
162: /**
163: * A border for XP style buttons.
164: */
165: private static class XPButtonBorder extends AbstractBorder
166: implements UIResource {
167:
168: protected final Insets insets;
169:
170: protected XPButtonBorder(Insets insets) {
171: this .insets = insets;
172: }
173:
174: public void paintBorder(Component c, Graphics g, int x, int y,
175: int w, int h) {
176: AbstractButton button = (AbstractButton) c;
177: ButtonModel model = button.getModel();
178:
179: if (!model.isEnabled()) {
180: PlasticXPUtils.drawDisabledButtonBorder(g, x, y, w, h);
181: return;
182: }
183:
184: boolean isPressed = model.isPressed() && model.isArmed();
185: boolean isDefault = button instanceof JButton
186: && ((JButton) button).isDefaultButton();
187: boolean isFocused = button.isFocusPainted()
188: && button.hasFocus();
189:
190: if (isPressed)
191: PlasticXPUtils.drawPressedButtonBorder(g, x, y, w, h);
192: else if (isFocused)
193: PlasticXPUtils.drawFocusedButtonBorder(g, x, y, w, h);
194: else if (isDefault)
195: PlasticXPUtils.drawDefaultButtonBorder(g, x, y, w, h);
196: else
197: PlasticXPUtils.drawPlainButtonBorder(g, x, y, w, h);
198: }
199:
200: public Insets getBorderInsets(Component c) {
201: return insets;
202: }
203:
204: public Insets getBorderInsets(Component c, Insets newInsets) {
205: newInsets.top = insets.top;
206: newInsets.left = insets.left;
207: newInsets.bottom = insets.bottom;
208: newInsets.right = insets.right;
209: return newInsets;
210: }
211: }
212:
213: /**
214: * A border for combo box arrow buttons.
215: */
216: private static final class XPComboBoxArrowButtonBorder extends
217: AbstractBorder implements UIResource {
218:
219: protected static final Insets INSETS = new Insets(1, 1, 1, 1);
220:
221: public void paintBorder(Component c, Graphics g, int x, int y,
222: int w, int h) {
223: PlasticComboBoxButton button = (PlasticComboBoxButton) c;
224: JComboBox comboBox = button.getComboBox();
225: ButtonModel model = button.getModel();
226:
227: if (!model.isEnabled()) {
228: PlasticXPUtils.drawDisabledButtonBorder(g, x, y, w, h);
229: } else {
230: boolean isPressed = model.isPressed()
231: && model.isArmed();
232: boolean isFocused = comboBox.hasFocus();
233: if (isPressed)
234: PlasticXPUtils.drawPressedButtonBorder(g, x, y, w,
235: h);
236: else if (isFocused)
237: PlasticXPUtils.drawFocusedButtonBorder(g, x, y, w,
238: h);
239: else
240: PlasticXPUtils.drawPlainButtonBorder(g, x, y, w, h);
241: }
242: if (comboBox.isEditable()) {
243: // Paint two pixel on the arrow button's left hand side.
244: g.setColor(model.isEnabled() ? PlasticLookAndFeel
245: .getControlDarkShadow() : MetalLookAndFeel
246: .getControlShadow());
247: g.fillRect(x, y, 1, 1);
248: g.fillRect(x, y + h - 1, 1, 1);
249: }
250: }
251:
252: public Insets getBorderInsets(Component c) {
253: return INSETS;
254: }
255: }
256:
257: /**
258: * A border for combo box editors.
259: */
260: private static final class XPComboBoxEditorBorder extends
261: AbstractBorder {
262:
263: private static final Insets INSETS = new Insets(1, 1, 1, 0);
264:
265: public void paintBorder(Component c, Graphics g, int x, int y,
266: int w, int h) {
267: g.setColor(c.isEnabled() ? PlasticLookAndFeel
268: .getControlDarkShadow() : MetalLookAndFeel
269: .getControlShadow());
270: PlasticXPUtils.drawRect(g, x, y, w + 1, h - 1);
271: }
272:
273: public Insets getBorderInsets(Component c) {
274: return INSETS;
275: }
276: }
277:
278: /**
279: * A border for text fields.
280: */
281: private static final class XPTextFieldBorder extends AbstractBorder {
282:
283: private static final Insets INSETS = new Insets(1, 1, 1, 1);
284:
285: public void paintBorder(Component c, Graphics g, int x, int y,
286: int w, int h) {
287:
288: boolean enabled = ((c instanceof JTextComponent) && (c
289: .isEnabled() && ((JTextComponent) c).isEditable()))
290: || c.isEnabled();
291:
292: g.setColor(enabled ? PlasticLookAndFeel
293: .getControlDarkShadow() : MetalLookAndFeel
294: .getControlShadow());
295: PlasticXPUtils.drawRect(g, x, y, w - 1, h - 1);
296: }
297:
298: public Insets getBorderInsets(Component c) {
299: return INSETS;
300: }
301:
302: public Insets getBorderInsets(Component c, Insets newInsets) {
303: newInsets.top = INSETS.top;
304: newInsets.left = INSETS.left;
305: newInsets.bottom = INSETS.bottom;
306: newInsets.right = INSETS.right;
307: return newInsets;
308: }
309: }
310:
311: /**
312: * Unlike Metal we paint a simple rectangle.
313: * Being a subclass of MetalBorders.ScrollPaneBorder ensures that
314: * the ScrollPaneUI will update the ScrollbarsFreeStanding property.
315: */
316: private static final class XPScrollPaneBorder extends
317: MetalBorders.ScrollPaneBorder {
318:
319: private static final Insets INSETS = new Insets(1, 1, 1, 1);
320:
321: public void paintBorder(Component c, Graphics g, int x, int y,
322: int w, int h) {
323: g.setColor(c.isEnabled() ? PlasticLookAndFeel
324: .getControlDarkShadow() : MetalLookAndFeel
325: .getControlShadow());
326: PlasticXPUtils.drawRect(g, x, y, w - 1, h - 1);
327: }
328:
329: public Insets getBorderInsets(Component c) {
330: return INSETS;
331: }
332:
333: public Insets getBorderInsets(Component c, Insets newInsets) {
334: newInsets.top = INSETS.top;
335: newInsets.left = INSETS.left;
336: newInsets.bottom = INSETS.bottom;
337: newInsets.right = INSETS.right;
338: return newInsets;
339: }
340: }
341:
342: /**
343: * A border for <code>JSpinner</code> components.
344: */
345: private static final class XPSpinnerBorder extends
346: MetalBorders.ScrollPaneBorder {
347:
348: private static final Insets INSETS = new Insets(1, 1, 1, 1);
349:
350: public void paintBorder(Component c, Graphics g, int x, int y,
351: int w, int h) {
352: g.setColor(c.isEnabled() ? PlasticLookAndFeel
353: .getControlDarkShadow() : MetalLookAndFeel
354: .getControlShadow());
355: // If you change the value of arrowButtonWidth, don't forget
356: // to change it in PlasticXPSpinnerUI#SpinnerXPArrowButton too.
357: int arrowButtonWidth = UIManager.getInt("ScrollBar.width") - 1;
358: w -= arrowButtonWidth;
359: g.fillRect(x, y, w, 1);
360: g.fillRect(x, y + 1, 1, h - 1);
361: g.fillRect(x + 1, y + h - 1, w - 1, 1);
362: }
363:
364: public Insets getBorderInsets(Component c) {
365: return INSETS;
366: }
367:
368: public Insets getBorderInsets(Component c, Insets newInsets) {
369: newInsets.top = INSETS.top;
370: newInsets.left = INSETS.left;
371: newInsets.bottom = INSETS.bottom;
372: newInsets.right = INSETS.right;
373: return newInsets;
374: }
375: }
376:
377: /**
378: * A rollover border for buttons in toolbars.
379: */
380: private static final class RolloverButtonBorder extends
381: XPButtonBorder {
382:
383: private RolloverButtonBorder() {
384: super (new Insets(3, 3, 3, 3));
385: }
386:
387: public void paintBorder(Component c, Graphics g, int x, int y,
388: int w, int h) {
389: AbstractButton b = (AbstractButton) c;
390: ButtonModel model = b.getModel();
391:
392: if (!model.isEnabled())
393: return;
394:
395: if (!(c instanceof JToggleButton)) {
396: if (model.isRollover()
397: && !(model.isPressed() && !model.isArmed())) {
398: super.paintBorder(c, g, x, y, w, h);
399: }
400: return;
401: }
402:
403: if (model.isRollover()) {
404: if (model.isPressed() && model.isArmed()) {
405: PlasticXPUtils.drawPressedButtonBorder(g, x, y, w,
406: h);
407: } else {
408: PlasticXPUtils.drawPlainButtonBorder(g, x, y, w, h);
409: }
410: } else if (model.isSelected()) {
411: PlasticXPUtils.drawPressedButtonBorder(g, x, y, w, h);
412: }
413: }
414:
415: }
416:
417: }
|