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