2
* Copyright (c) 2005-2010 Substance Kirill Grouchnikov. 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 Substance Kirill Grouchnikov 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.
30
package org.pushingpixels.substance.internal.utils.border;
33
import java.awt.image.BufferedImage;
35
import javax.swing.border.Border;
36
import javax.swing.plaf.UIResource;
38
import org.pushingpixels.lafwidget.LafWidgetUtilities;
39
import org.pushingpixels.substance.api.*;
40
import org.pushingpixels.substance.internal.utils.*;
43
* Gradient border for the <b>Substance</b> look and feel. This class is <b>for
44
* internal use only</b>.
46
* @author Kirill Grouchnikov
48
public class SubstanceBorder implements Border, UIResource {
50
* Insets of <code>this</code> border.
52
protected Insets myInsets;
57
protected float alpha;
60
* When the border is painted, the default radius is multiplied by this
63
protected float radiusScaleFactor;
66
* Cache of small border images.
68
private static LazyResettableHashMap<BufferedImage> smallImageCache = new LazyResettableHashMap<BufferedImage>(
72
* Creates a new border with dynamic insets (computed at the invocation time
73
* of {@link #getBorderInsets(Component)} call).
75
public SubstanceBorder() {
78
this.radiusScaleFactor = 0.5f;
82
* Creates a new border with dynamic insets (computed at the invocation time
83
* of {@link #getBorderInsets(Component)} call).
85
* @param radiusScaleFactor
86
* Radius scale factor.
88
public SubstanceBorder(float radiusScaleFactor) {
90
this.radiusScaleFactor = radiusScaleFactor;
94
* Creates a new border with the specified insets.
99
public SubstanceBorder(Insets insets) {
101
this.myInsets = new Insets(insets.top, insets.left, insets.bottom,
106
* Sets the alpha for this border.
111
public void setAlpha(float alpha) {
116
* Paints border instance for the specified component.
123
* Component left X (in graphics context).
125
* Component top Y (in graphics context).
131
* Component enabled status.
133
* Component focus ownership status.
137
private void paintBorder(Component c, Graphics g, int x, int y, int width,
138
int height, boolean isEnabled, boolean hasFocus, float alpha) {
139
// failsafe for LAF change
140
if (!SubstanceLookAndFeel.isCurrentLookAndFeel()) {
144
if ((width <= 0) || (height <= 0))
151
Graphics2D graphics = (Graphics2D) g.create();
153
float radius = this.radiusScaleFactor
155
.getClassicButtonCornerRadius(SubstanceSizeUtils
156
.getComponentFontSize(c));
158
ComponentState state = isEnabled ? ComponentState.ENABLED
159
: ComponentState.DISABLED_UNSELECTED;
160
SubstanceColorScheme borderColorScheme = SubstanceColorSchemeUtilities
161
.getColorScheme(c, ColorSchemeAssociationKind.BORDER, state);
162
float finalAlpha = alpha
163
* SubstanceColorSchemeUtilities.getAlpha(c, state);
165
graphics.setComposite(LafWidgetUtilities.getAlphaComposite(c,
168
if (width * height < 100000) {
169
HashMapKey hashKey = SubstanceCoreUtilities
170
.getHashKey(SubstanceCoreUtilities.getBorderPainter(c)
171
.getDisplayName(), SubstanceSizeUtils
172
.getComponentFontSize(c), width, height, radius,
173
borderColorScheme.getDisplayName());
174
BufferedImage result = smallImageCache.get(hashKey);
175
if (result == null) {
176
result = SubstanceCoreUtilities.getBlankImage(width, height);
177
Graphics2D g2d = result.createGraphics();
178
SubstanceImageCreator.paintBorder(c, g2d, 0, 0, width, height,
179
radius, borderColorScheme);
181
smallImageCache.put(hashKey, result);
183
graphics.drawImage(result, x, y, null);
185
// for borders larger than 100000 pixels, use simple
187
graphics.translate(x, y);
188
SubstanceImageCreator.paintSimpleBorder(c, graphics, width, height,
198
* @see javax.swing.border.Border#paintBorder(java.awt.Component,
199
* java.awt.Graphics, int, int, int, int)
202
public void paintBorder(Component c, Graphics g, int x, int y, int width,
204
paintBorder(c, g, x, y, width, height, c.isEnabled(), c.hasFocus(),
211
* @see javax.swing.border.Border#getBorderInsets(java.awt.Component)
214
public Insets getBorderInsets(Component c) {
215
if (this.myInsets == null) {
216
return SubstanceSizeUtils.getDefaultBorderInsets(SubstanceSizeUtils
217
.getComponentFontSize(c));
219
return this.myInsets;
225
* @see javax.swing.border.Border#isBorderOpaque()
228
public boolean isBorderOpaque() {
233
* Returns the radius scale factor of this border.
235
* @return The radius scale factor of this border.
237
public float getRadiusScaleFactor() {
238
return this.radiusScaleFactor;