2
* Copyright (c) 2001-2009 JGoodies Karsten Lentzsch. All Rights Reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* o Redistributions of source code must retain the above copyright notice,
8
* this list of conditions and the following disclaimer.
10
* o Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
14
* o Neither the name of JGoodies Karsten Lentzsch nor the names of
15
* its contributors may be used to endorse or promote products derived
16
* from this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
package com.jgoodies.looks.plastic;
33
import java.awt.Component;
34
import java.awt.Graphics;
35
import java.awt.Insets;
38
import javax.swing.border.AbstractBorder;
39
import javax.swing.border.Border;
40
import javax.swing.border.CompoundBorder;
41
import javax.swing.plaf.BorderUIResource;
42
import javax.swing.plaf.UIResource;
43
import javax.swing.plaf.basic.BasicBorders;
44
import javax.swing.plaf.metal.MetalBorders;
45
import javax.swing.plaf.metal.MetalLookAndFeel;
46
import javax.swing.text.JTextComponent;
50
* This class consists of a set of <code>Border</code>s used
51
* by the JGoodies Plastic XP Look and Feel UI delegates.
53
* @author Karsten Lentzsch
54
* @author Andrej Golovnin
55
* @version $Revision: 1.2 $
58
final class PlasticXPBorders {
60
private PlasticXPBorders() {
61
// Overrides default constructor; prevents instantiation.
65
// Accessing and Creating Borders ***************************************
67
private static Border comboBoxArrowButtonBorder;
68
private static Border comboBoxEditorBorder;
69
private static Border scrollPaneBorder;
70
private static Border textFieldBorder;
71
private static Border spinnerBorder;
72
private static Border rolloverButtonBorder;
76
* Returns a border instance for a <code>JButton</code>.
78
static Border getButtonBorder(Insets buttonMargin) {
79
return new BorderUIResource.CompoundBorderUIResource(
80
new XPButtonBorder(buttonMargin),
81
new BasicBorders.MarginBorder());
85
* Returns a border instance for a <code>JComboBox</code>'s arrow button.
87
static Border getComboBoxArrowButtonBorder() {
88
if (comboBoxArrowButtonBorder == null) {
89
comboBoxArrowButtonBorder = new CompoundBorder( // No UIResource
90
new XPComboBoxArrowButtonBorder(),
91
new BasicBorders.MarginBorder());
93
return comboBoxArrowButtonBorder;
97
* Returns a border instance for a <code>JComboBox</code>'s editor.
99
static Border getComboBoxEditorBorder() {
100
if (comboBoxEditorBorder == null) {
101
comboBoxEditorBorder = new CompoundBorder( // No UIResource
102
new XPComboBoxEditorBorder(),
103
new BasicBorders.MarginBorder());
105
return comboBoxEditorBorder;
109
* Returns a border instance for a <code>JScrollPane</code>.
111
static Border getScrollPaneBorder() {
112
if (scrollPaneBorder == null) {
113
scrollPaneBorder = new XPScrollPaneBorder();
115
return scrollPaneBorder;
119
* Returns a border instance for a <code>JTextField</code>.
121
static Border getTextFieldBorder() {
122
if (textFieldBorder == null) {
123
textFieldBorder = new BorderUIResource.CompoundBorderUIResource(
124
new XPTextFieldBorder(),
125
new BasicBorders.MarginBorder());
127
return textFieldBorder;
131
* Returns a border instance for a <code>JToggleButton</code>.
133
static Border getToggleButtonBorder(Insets buttonMargin) {
134
return new BorderUIResource.CompoundBorderUIResource(
135
new XPButtonBorder(buttonMargin),
136
new BasicBorders.MarginBorder());
140
* Returns a border instance for a <code>JSpinner</code>.
142
static Border getSpinnerBorder() {
143
if (spinnerBorder == null) {
144
spinnerBorder = new XPSpinnerBorder();
146
return spinnerBorder;
151
* Returns a rollover border for buttons in a <code>JToolBar</code>.
153
* @return the lazily created rollover button border
155
static Border getRolloverButtonBorder() {
156
if (rolloverButtonBorder == null) {
157
rolloverButtonBorder = new CompoundBorder(
158
new RolloverButtonBorder(),
159
new PlasticBorders.RolloverMarginBorder());
161
return rolloverButtonBorder;
165
* A border for XP style buttons.
167
private static class XPButtonBorder extends AbstractBorder implements UIResource {
169
protected final Insets insets;
171
protected XPButtonBorder(Insets insets) {
172
this.insets = insets;
175
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
176
AbstractButton button = (AbstractButton) c;
177
ButtonModel model = button.getModel();
179
if (!model.isEnabled()) {
180
PlasticXPUtils.drawDisabledButtonBorder(g, x, y, w, h);
184
boolean isPressed = model.isPressed() && model.isArmed();
185
boolean isDefault = button instanceof JButton
186
&& ((JButton) button).isDefaultButton();
187
boolean isFocused = button.isFocusPainted() && button.hasFocus();
190
PlasticXPUtils.drawPressedButtonBorder(g, x, y, w, h);
192
PlasticXPUtils.drawFocusedButtonBorder(g, x, y, w, h);
194
PlasticXPUtils.drawDefaultButtonBorder(g, x, y, w, h);
196
PlasticXPUtils.drawPlainButtonBorder(g, x, y, w, h);
199
public Insets getBorderInsets(Component c) { return insets; }
201
public Insets getBorderInsets(Component c, Insets newInsets) {
202
newInsets.top = insets.top;
203
newInsets.left = insets.left;
204
newInsets.bottom = insets.bottom;
205
newInsets.right = insets.right;
212
* A border for combo box arrow buttons.
214
private static final class XPComboBoxArrowButtonBorder extends AbstractBorder implements UIResource {
216
protected static final Insets INSETS = new Insets(1, 1, 1, 1);
218
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
219
PlasticComboBoxButton button = (PlasticComboBoxButton) c;
220
JComboBox comboBox = button.getComboBox();
221
ButtonModel model = button.getModel();
223
if (!model.isEnabled()) {
224
PlasticXPUtils.drawDisabledButtonBorder(g, x, y, w, h);
226
boolean isPressed = model.isPressed() && model.isArmed();
227
boolean isFocused = comboBox.hasFocus();
229
PlasticXPUtils.drawPressedButtonBorder(g, x, y, w, h);
231
PlasticXPUtils.drawFocusedButtonBorder(g, x, y, w, h);
233
PlasticXPUtils.drawPlainButtonBorder(g, x, y, w, h);
235
if (comboBox.isEditable()) {
236
// Paint two pixel on the arrow button's left hand side.
237
g.setColor(model.isEnabled()
238
? PlasticLookAndFeel.getControlDarkShadow()
239
: MetalLookAndFeel.getControlShadow());
240
g.fillRect(x, y, 1, 1);
241
g.fillRect(x, y + h-1, 1, 1);
245
public Insets getBorderInsets(Component c) { return INSETS; }
250
* A border for combo box editors.
252
private static final class XPComboBoxEditorBorder extends AbstractBorder {
254
private static final Insets INSETS = new Insets(1, 1, 1, 0);
256
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
257
g.setColor(c.isEnabled()
258
? PlasticLookAndFeel.getControlDarkShadow()
259
: MetalLookAndFeel.getControlShadow());
260
PlasticXPUtils.drawRect(g, x, y, w+1, h-1);
263
public Insets getBorderInsets(Component c) { return INSETS; }
268
* A border for text fields.
270
private static final class XPTextFieldBorder extends AbstractBorder {
272
private static final Insets INSETS = new Insets(1, 1, 1, 1);
274
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
276
boolean enabled = ((c instanceof JTextComponent)
277
&& (c.isEnabled() && ((JTextComponent) c).isEditable()))
282
? PlasticLookAndFeel.getControlDarkShadow()
283
: MetalLookAndFeel.getControlShadow());
284
PlasticXPUtils.drawRect(g, x, y, w-1, h-1);
287
public Insets getBorderInsets(Component c) { return INSETS; }
289
public Insets getBorderInsets(Component c, Insets newInsets) {
290
newInsets.top = INSETS.top;
291
newInsets.left = INSETS.left;
292
newInsets.bottom = INSETS.bottom;
293
newInsets.right = INSETS.right;
300
* Unlike Metal we paint a simple rectangle.
301
* Being a subclass of MetalBorders.ScrollPaneBorder ensures that
302
* the ScrollPaneUI will update the ScrollbarsFreeStanding property.
304
private static final class XPScrollPaneBorder extends MetalBorders.ScrollPaneBorder {
306
private static final Insets INSETS = new Insets(1, 1, 1, 1);
308
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
309
g.setColor(c.isEnabled()
310
? PlasticLookAndFeel.getControlDarkShadow()
311
: MetalLookAndFeel.getControlShadow());
312
PlasticXPUtils.drawRect(g, x, y, w-1, h-1);
315
public Insets getBorderInsets(Component c) { return INSETS; }
317
public Insets getBorderInsets(Component c, Insets newInsets) {
318
newInsets.top = INSETS.top;
319
newInsets.left = INSETS.left;
320
newInsets.bottom = INSETS.bottom;
321
newInsets.right = INSETS.right;
328
* A border for <code>JSpinner</code> components.
330
private static final class XPSpinnerBorder extends MetalBorders.ScrollPaneBorder {
332
private static final Insets INSETS = new Insets(1, 1, 1, 1);
334
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
335
g.setColor(c.isEnabled()
336
? PlasticLookAndFeel.getControlDarkShadow()
337
: MetalLookAndFeel.getControlShadow());
338
// If you change the value of arrowButtonWidth, don't forget
339
// to change it in PlasticXPSpinnerUI#SpinnerXPArrowButton too.
340
int arrowButtonWidth = UIManager.getInt("ScrollBar.width") - 1;
341
w -= arrowButtonWidth;
342
g.fillRect(x, y, w, 1);
343
g.fillRect(x, y+1, 1, h-1);
344
g.fillRect(x+1, y+h-1, w-1, 1);
347
public Insets getBorderInsets(Component c) { return INSETS; }
349
public Insets getBorderInsets(Component c, Insets newInsets) {
350
newInsets.top = INSETS.top;
351
newInsets.left = INSETS.left;
352
newInsets.bottom = INSETS.bottom;
353
newInsets.right = INSETS.right;
360
* A rollover border for buttons in toolbars.
362
private static final class RolloverButtonBorder extends XPButtonBorder {
364
private RolloverButtonBorder() {
365
super(new Insets(3, 3, 3, 3));
368
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
369
AbstractButton b = (AbstractButton) c;
370
ButtonModel model = b.getModel();
372
if (!model.isEnabled())
375
if (!(c instanceof JToggleButton)) {
376
if (model.isRollover() && !(model.isPressed() && !model.isArmed())) {
377
super.paintBorder( c, g, x, y, w, h );
382
if (model.isRollover()) {
383
if (model.isPressed() && model.isArmed()) {
384
PlasticXPUtils.drawPressedButtonBorder(g, x, y, w, h);
386
PlasticXPUtils.drawPlainButtonBorder(g, x, y, w, h);
388
} else if (model.isSelected()) {
389
PlasticXPUtils.drawPressedButtonBorder(g, x, y, w, h);