001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. 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 Substance Kirill Grouchnikov 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: package org.jvnet.substance.painter.highlight;
031:
032: import java.awt.*;
033: import java.awt.geom.GeneralPath;
034: import java.awt.image.BufferedImage;
035: import java.util.*;
036:
037: import org.jvnet.lafwidget.layout.TransitionLayout;
038: import org.jvnet.substance.SubstanceLookAndFeel;
039: import org.jvnet.substance.border.SubstanceBorderPainter;
040: import org.jvnet.substance.button.BaseButtonShaper;
041: import org.jvnet.substance.color.ColorScheme;
042: import org.jvnet.substance.painter.GlassGradientPainter;
043: import org.jvnet.substance.theme.SubstanceTheme;
044: import org.jvnet.substance.utils.*;
045: import org.jvnet.substance.utils.SubstanceConstants.Side;
046:
047: /**
048: * Highlight painter that paints a glass gradient. This class is part of
049: * officially supported API.
050: *
051: * @author Kirill Grouchnikov
052: * @since version 4.3
053: */
054: public class GlassHighlightPainter implements SubstanceHighlightPainter {
055: /**
056: * The display name for the highlight painters of this class.
057: */
058: public static final String DISPLAY_NAME = "Glass";
059:
060: /**
061: * Cache for small objects.
062: */
063: protected static Map<String, BufferedImage> smallImageCache = new SoftHashMap<String, BufferedImage>();
064:
065: /**
066: * Single gradient painter instance.
067: */
068: protected GlassGradientPainter painter;
069:
070: /**
071: * Creates new classic title painter.
072: */
073: public GlassHighlightPainter() {
074: this .painter = new GlassGradientPainter();
075: }
076:
077: /*
078: * (non-Javadoc)
079: *
080: * @see org.jvnet.substance.painter.SubstanceGradientPainter#getDisplayName()
081: */
082: public String getDisplayName() {
083: return DISPLAY_NAME;
084: }
085:
086: public void paintHighlight(Graphics2D graphics, Component comp,
087: int width, int height, float borderAlpha,
088: Set<Side> openSides, ColorScheme colorScheme1,
089: ColorScheme colorScheme2, float cyclePos) {
090:
091: SubstanceBorderPainter borderPainter = SubstanceCoreUtilities
092: .getBorderPainter(comp);
093:
094: int size = Math.max(width, height);
095: if (openSides == null) {
096: openSides = new HashSet<Side>();
097: }
098: if (size < 150) {
099: synchronized (this ) {
100: String openKey = "";
101: for (Side oSide : openSides) {
102: openKey += oSide.name() + "-";
103: }
104:
105: String key = width
106: + "*"
107: + height
108: + "*"
109: + SubstanceCoreUtilities
110: .getSchemeId(colorScheme1)
111: + "*"
112: + SubstanceCoreUtilities
113: .getSchemeId(colorScheme2) + "*"
114: + cyclePos + "*" + borderAlpha + "*" + openKey
115: + "*" + borderPainter.getDisplayName();
116: BufferedImage result = smallImageCache.get(key);
117: if (result == null) {
118: result = SubstanceCoreUtilities.getBlankImage(
119: width, height);
120: this .internalPaint((Graphics2D) result
121: .getGraphics(), comp, width, height,
122: colorScheme1, colorScheme2, cyclePos,
123: borderPainter, borderAlpha, openSides);
124: smallImageCache.put(key, result);
125: }
126: graphics.drawImage(result, 0, 0, null);
127: return;
128: }
129: }
130:
131: this .internalPaint(graphics, comp, width, height, colorScheme1,
132: colorScheme2, cyclePos, borderPainter, borderAlpha,
133: openSides);
134: }
135:
136: protected void internalPaint(Graphics2D graphics, Component comp,
137: int width, int height, ColorScheme colorScheme1,
138: ColorScheme colorScheme2, float cyclePos,
139: SubstanceBorderPainter borderPainter, float borderAlpha,
140: Set<SubstanceConstants.Side> openSides) {
141:
142: Graphics2D g2d = (Graphics2D) graphics.create();
143:
144: g2d.drawImage(this .painter.getContourBackground(width + 6,
145: height + 6, new Rectangle(width + 6, height + 6),
146: false, colorScheme1, colorScheme2, cyclePos, false,
147: true), -3, -3, null);
148: //
149: // SubstanceImageCreator.paintRectangularBackground(g2d, 0, 0, width,
150: // height, colorScheme2, 0.0f, false);
151: // g2d.setComposite(TransitionLayout.getAlphaComposite(comp,
152: // 1.0f - cyclePos / 10.0f, graphics));
153: // SubstanceImageCreator.paintRectangularBackground(g2d, 0, 0, width,
154: // height, colorScheme1, 0.0f, false);
155: // g2d.setComposite(TransitionLayout.getAlphaComposite(comp, 1.0f,
156: // graphics));
157:
158: if (borderAlpha > 0.0f) {
159: int openDelta = 3 + (int) (Math
160: .ceil(3.0 * SubstanceSizeUtils
161: .getBorderStrokeWidth(SubstanceSizeUtils
162: .getComponentFontSize(comp))));
163: int deltaLeft = openSides.contains(Side.LEFT) ? openDelta
164: : 0;
165: int deltaRight = openSides.contains(Side.RIGHT) ? openDelta
166: : 0;
167: int deltaTop = openSides.contains(Side.TOP) ? openDelta : 0;
168: int deltaBottom = openSides.contains(Side.BOTTOM) ? openDelta
169: : 0;
170:
171: int borderDelta = (int) Math.floor(SubstanceSizeUtils
172: .getBorderStrokeWidth(SubstanceSizeUtils
173: .getComponentFontSize(comp)) / 2.0);
174: GeneralPath contour = BaseButtonShaper.getBaseOutline(width
175: + deltaLeft + deltaRight, height + deltaTop
176: + deltaBottom, 0.0f, null, borderDelta);
177: // (null, new Insets(
178: // borderDelta, borderDelta, borderDelta, borderDelta), width
179: // + deltaLeft + deltaRight, height + deltaTop + deltaBottom);
180:
181: graphics.translate(-deltaLeft, -deltaTop);
182:
183: if (borderAlpha > 0.0f) {
184: g2d.setComposite(TransitionLayout.getAlphaComposite(
185: comp, borderAlpha, graphics));
186: int borderThickness = (int) SubstanceSizeUtils
187: .getBorderStrokeWidth(SubstanceSizeUtils
188: .getComponentFontSize(comp));
189: GeneralPath contourInner = BaseButtonShaper
190: .getBaseOutline(width + deltaLeft + deltaRight,
191: height + deltaTop + deltaBottom, 0.0f,
192: null, borderDelta + borderThickness);
193: borderPainter.paintBorder(g2d, comp, width + deltaLeft
194: + deltaRight, height + deltaTop + deltaBottom,
195: contour, contourInner, colorScheme1,
196: colorScheme2, cyclePos, true);
197: g2d.dispose();
198: }
199: }
200: }
201:
202: /**
203: * Resets image maps (used when setting new theme).
204: *
205: * @see SubstanceLookAndFeel#setCurrentTheme(String)
206: * @see SubstanceLookAndFeel#setCurrentTheme(SubstanceTheme)
207: */
208: public static synchronized void reset() {
209: smallImageCache.clear();
210: }
211: }
|