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.utils;
031:
032: import java.awt.*;
033: import java.awt.geom.GeneralPath;
034: import java.awt.image.BufferedImage;
035: import java.util.Map;
036: import java.util.Set;
037:
038: import javax.swing.*;
039: import javax.swing.JInternalFrame.JDesktopIcon;
040:
041: import org.jvnet.lafwidget.animation.*;
042: import org.jvnet.substance.SubstanceLookAndFeel;
043: import org.jvnet.substance.border.SubstanceBorderPainter;
044: import org.jvnet.substance.button.*;
045: import org.jvnet.substance.color.ColorScheme;
046: import org.jvnet.substance.painter.*;
047: import org.jvnet.substance.theme.SubstanceTheme;
048: import org.jvnet.substance.utils.ComponentState.ColorSchemeKind;
049: import org.jvnet.substance.utils.SubstanceConstants.Side;
050:
051: /**
052: * Delegate class for painting backgrounds of buttons in <b>Substance </b> look
053: * and feel. This class is <b>for internal use only</b>.
054: *
055: * @author Kirill Grouchnikov
056: */
057: public class ButtonBackgroundDelegate {
058: /**
059: * Cache for background images. Each time
060: * {@link #getBackground(AbstractButton, SubstanceButtonShaper, SubstanceGradientPainter, int, int)}
061: * is called, it checks <code>this</code> map to see if it already
062: * contains such background. If so, the background from the map is returned.
063: */
064: private static Map<String, BufferedImage> regularBackgrounds = new SoftHashMap<String, BufferedImage>();
065:
066: /**
067: * Contains information on a button background.
068: *
069: * @author Kirill Grouchnikov
070: */
071: public static class ButtonBackground {
072: /**
073: * Indicates whether the button is painted in active visual state.
074: */
075: public boolean isPaintedActive;
076:
077: /**
078: * The button background image.
079: */
080: public BufferedImage backgroundImage;
081:
082: /**
083: * Button background info object.
084: *
085: * @param isPaintedActive
086: * Indicates whether the button is painted in active visual
087: * state.
088: * @param backgroundImage
089: * The button background image.
090: */
091: public ButtonBackground(boolean isPaintedActive,
092: BufferedImage backgroundImage) {
093: this .isPaintedActive = isPaintedActive;
094: this .backgroundImage = backgroundImage;
095: }
096:
097: }
098:
099: /**
100: * Resets image maps (used when setting new theme).
101: *
102: * @see SubstanceLookAndFeel#setCurrentTheme(String)
103: * @see SubstanceLookAndFeel#setCurrentTheme(SubstanceTheme)
104: */
105: public static synchronized void reset() {
106: regularBackgrounds.clear();
107: PairwiseButtonBackgroundDelegate.reset();
108: }
109:
110: /**
111: * Retrieves the background for the specified button.
112: *
113: * @param button
114: * Button.
115: * @param shaper
116: * Button shaper.
117: * @param painter
118: * Button gradient painter.
119: * @param borderPainter
120: * Button border painter.
121: * @param width
122: * Button width.
123: * @param height
124: * Button height.
125: * @return Button background.
126: */
127: public static synchronized ButtonBackground getBackground(
128: AbstractButton button, SubstanceButtonShaper shaper,
129: SubstanceGradientPainter painter,
130: SubstanceBorderPainter borderPainter, int width, int height) {
131: ComponentState state = ComponentState.getState(button
132: .getModel(), button);
133: ComponentState prevState = SubstanceCoreUtilities
134: .getPrevComponentState(button);
135: // if (prevState != state)
136: // button.putClientProperty(PREV_COMPONENT_STATE, state);
137:
138: boolean isPaintedActive = (state.getColorSchemeKind() == ColorSchemeKind.CURRENT);
139: // compute cycle count (for animation)
140: float cyclePos = state.getCycleCount();
141: boolean isPulsating = false;
142: if (button instanceof JButton) {
143: JButton jb = (JButton) button;
144: if (PulseTracker.isPulsating(jb)
145: && (state != ComponentState.PRESSED_SELECTED)
146: && (state != ComponentState.PRESSED_UNSELECTED)) {
147: isPulsating = true;
148: cyclePos = (int) (PulseTracker.getCycles(jb) % 20);
149: if (cyclePos > 10) {
150: cyclePos = 19 - cyclePos;
151: }
152: isPaintedActive = true;
153: }
154: }
155:
156: // compute color scheme
157: SubstanceTheme theme = SubstanceThemeUtilities.getTheme(button,
158: state);
159: ColorScheme colorScheme = theme.getColorScheme();
160: ColorScheme colorScheme2 = colorScheme;
161: ColorScheme borderScheme = theme.getBorderTheme()
162: .getColorScheme();
163: ColorScheme borderScheme2 = borderScheme;
164:
165: // see if need to use attention-drawing animation
166: boolean isWindowModified = false;
167: if (SubstanceCoreUtilities.isTitleCloseButton(button)) {
168: // check if have windowModified property
169: Component comp = button;
170: while (comp != null) {
171: if (comp instanceof JInternalFrame) {
172: JInternalFrame jif = (JInternalFrame) comp;
173: isWindowModified = Boolean.TRUE
174: .equals(jif
175: .getClientProperty(SubstanceLookAndFeel.WINDOW_MODIFIED));
176: break;
177: }
178: if (comp instanceof JRootPane) {
179: JRootPane jrp = (JRootPane) comp;
180: isWindowModified = Boolean.TRUE
181: .equals(jrp
182: .getClientProperty(SubstanceLookAndFeel.WINDOW_MODIFIED));
183: break;
184: }
185: if (comp instanceof JDesktopIcon) {
186: JDesktopIcon jdi = (JDesktopIcon) comp;
187: JInternalFrame jif = jdi.getInternalFrame();
188: isWindowModified = Boolean.TRUE
189: .equals(jif
190: .getClientProperty(SubstanceLookAndFeel.WINDOW_MODIFIED));
191: break;
192: }
193: comp = comp.getParent();
194: }
195: if (isWindowModified) {
196: colorScheme2 = SubstanceTheme.YELLOW;
197: colorScheme = SubstanceTheme.ORANGE;
198: isPaintedActive = true;
199: }
200: }
201:
202: // see if need to use fade animation. Important - don't do it
203: // on pulsating buttons (such as default or close buttons
204: // of modified frames).
205: if (!isWindowModified && !isPulsating) {
206: // FadeTracker fadeTracker = FadeTracker.getInstance();
207:
208: FadeState fadeState = SubstanceFadeUtilities.getFadeState(
209: button, FadeKind.ROLLOVER, FadeKind.SELECTION,
210: FadeKind.PRESS);
211: if (fadeState != null) {
212: SubstanceTheme prevTheme = SubstanceThemeUtilities
213: .getTheme(button, prevState);
214: colorScheme = theme.getColorScheme();
215: colorScheme2 = prevTheme.getColorScheme();
216: borderScheme = theme.getBorderTheme().getColorScheme();
217: borderScheme2 = prevTheme.getBorderTheme()
218: .getColorScheme();
219: cyclePos = fadeState.getFadePosition();
220: if (fadeState.isFadingIn())
221: cyclePos = 10 - cyclePos;
222: isPaintedActive = true;
223: }
224: }
225:
226: // // special handling of disabled unselected buttons
227: // if (state == ComponentState.DISABLED_SELECTED) {
228: // colorScheme2 = SubstanceThemeUtilities.getTheme(button,
229: // ComponentState.SELECTED).getColorScheme();
230: // cyclePos = 3.0f;
231: // }
232: //
233: // compute a straight side
234: Set<SubstanceConstants.Side> straightSides = SubstanceCoreUtilities
235: .getSides(button,
236: SubstanceLookAndFeel.BUTTON_SIDE_PROPERTY);
237: String straightKey = "";
238: for (Side sSide : straightSides) {
239: straightKey += sSide.name() + "-";
240: }
241:
242: boolean isRoundButton = StandardButtonShaper
243: .isRoundButton(button);
244: float radius = 0.0f;
245: if (shaper instanceof RectangularButtonShaper) {
246: radius = ((RectangularButtonShaper) shaper)
247: .getCornerRadius(button, null);
248: }
249:
250: Set<Side> openSides = SubstanceCoreUtilities.getSides(button,
251: SubstanceLookAndFeel.BUTTON_OPEN_SIDE_PROPERTY);
252: String openKey = "";
253: for (Side oSide : openSides) {
254: openKey += oSide.name() + "-";
255: }
256: boolean isContentAreaFilled = button.isContentAreaFilled();
257: boolean isBorderPainted = button.isBorderPainted();
258: String key = width + ":" + height + ":" + prevState.name()
259: + ":" + state.name() + ":" + cyclePos + ":"
260: + SubstanceCoreUtilities.getSchemeId(colorScheme) + ":"
261: + SubstanceCoreUtilities.getSchemeId(colorScheme2)
262: + ":"
263: + SubstanceCoreUtilities.getSchemeId(borderScheme)
264: + ":"
265: + SubstanceCoreUtilities.getSchemeId(borderScheme2)
266: + ":" + shaper.getDisplayName() + ":"
267: + painter.getDisplayName() + ":"
268: + borderPainter.getDisplayName() + ":" + straightKey
269: + ":" + openKey + ":" + button.getClass().getName()
270: + ":" + isRoundButton + ":" + radius + ":"
271: + isContentAreaFilled + ":" + isBorderPainted + ":"
272: + SubstanceSizeUtils.getComponentFontSize(button);
273:
274: if (regularBackgrounds.get(key) == null) {
275: BufferedImage newBackground;
276:
277: int openDelta = (int) (Math.ceil(3.0 * SubstanceSizeUtils
278: .getBorderStrokeWidth(SubstanceSizeUtils
279: .getComponentFontSize(button))));
280: int deltaLeft = openSides.contains(Side.LEFT) ? openDelta
281: : 0;
282: int deltaRight = openSides.contains(Side.RIGHT) ? openDelta
283: : 0;
284: int deltaTop = openSides.contains(Side.TOP) ? openDelta : 0;
285: int deltaBottom = openSides.contains(Side.BOTTOM) ? openDelta
286: : 0;
287:
288: // System.err.println(key);
289: int borderDelta = (int) Math.floor(SubstanceSizeUtils
290: .getBorderStrokeWidth(SubstanceSizeUtils
291: .getComponentFontSize(button)) / 2.0);
292: GeneralPath contour = shaper.getButtonOutline(button,
293: new Insets(borderDelta, borderDelta, borderDelta,
294: borderDelta), width + deltaLeft
295: + deltaRight, height + deltaTop
296: + deltaBottom);
297:
298: newBackground = SubstanceCoreUtilities.getBlankImage(width,
299: height);
300: Graphics2D finalGraphics = (Graphics2D) newBackground
301: .getGraphics();
302: finalGraphics.translate(-deltaLeft, -deltaTop);
303: if (isContentAreaFilled) {
304: BufferedImage contourBackground = painter
305: .getContourBackground(width + deltaLeft
306: + deltaRight, height + deltaTop
307: + deltaBottom, contour, false,
308: colorScheme, colorScheme2, cyclePos,
309: true, colorScheme != colorScheme2);
310: finalGraphics.drawImage(contourBackground, 0, 0, null);
311: }
312:
313: if (isBorderPainted) {
314: int borderThickness = (int) SubstanceSizeUtils
315: .getBorderStrokeWidth(SubstanceSizeUtils
316: .getComponentFontSize(button));
317: GeneralPath contourInner = shaper.getButtonOutline(
318: button, new Insets(borderDelta
319: + borderThickness, borderDelta
320: + borderThickness, borderDelta
321: + borderThickness, borderDelta
322: + borderThickness), width + deltaLeft
323: + deltaRight, height + deltaTop
324: + deltaBottom);
325: borderPainter.paintBorder(finalGraphics, button, width
326: + deltaLeft + deltaRight, height + deltaTop
327: + deltaBottom, contour, contourInner,
328: borderScheme, borderScheme2, cyclePos,
329: borderScheme != borderScheme2);
330: }
331:
332: regularBackgrounds.put(key, newBackground);
333: }
334: return new ButtonBackground(isPaintedActive, regularBackgrounds
335: .get(key));
336: }
337:
338: // /**
339: // * Retrieves background image for the specified button in button pair
340: // (such
341: // * as scrollbar arrows, for example).
342: // *
343: // * @param button
344: // * Button.
345: // * @param painter
346: // * Gradient painter.
347: // * @param width
348: // * Button width.
349: // * @param height
350: // * Button height.
351: // * @param side
352: // * Button orientation.
353: // * @return Button background image.
354: // */
355: // private static synchronized ButtonBackground getPairwiseBackground(
356: // AbstractButton button, SubstanceGradientPainter painter, int width,
357: // int height, SubstanceConstants.Side side) {
358: // ComponentState state = ComponentState.getState(button.getModel(),
359: // button);
360: // ComponentState.ColorSchemeKind kind = state.getColorSchemeKind();
361: //
362: // // if ((kind == ColorSchemeKind.CURRENT)
363: // // || (kind == ColorSchemeKind.DISABLED))
364: // return getPairwiseBackground(button, kind, painter, width, height, side);
365: // //
366: // // return getPairwiseBackground(button, kind, SubstanceCoreUtilities
367: // // .getTheme(button, true).getNonActivePainter(), width, height,
368: // // side);
369: // // ButtonBackground bbRegular = getPairwiseBackground(button,
370: // // ColorSchemeKind.REGULAR, painter, width, height, side);
371: // // if (!Boolean.TRUE.equals(button
372: // // .getClientProperty(SubstanceScrollBarUI.ADJACENT_TO_TRACK)))
373: // // return bbRegular;
374: // //
375: // // ButtonBackground bbDisabled = getPairwiseBackground(button,
376: // // ColorSchemeKind.DISABLED, painter, width, height, side);
377: // //
378: // // BufferedImage result = SubstanceCoreUtilities.getBlankImage(width,
379: // // height);
380: // // Graphics2D graphics = (Graphics2D) result.createGraphics();
381: // // graphics.drawImage(bbDisabled.backgroundImage, 0, 0, null);
382: // // graphics.drawImage(bbRegular.backgroundImage, 1, 1, width - 1,
383: // // height - 1, 1, 1, width - 1, height - 1, null);
384: // // graphics.dispose();
385: // // return new ButtonBackground(bbRegular.isPaintedActive, result);
386: // }
387: //
388: // /**
389: // * Retrieves background image for the specified button in button pair
390: // (such
391: // * as scrollbar arrows, for example).
392: // *
393: // * @param button
394: // * Button.
395: // * @param kind
396: // * Color scheme kind.
397: // * @param painter
398: // * Gradient painter.
399: // * @param width
400: // * Button width.
401: // * @param height
402: // * Button height.
403: // * @param side
404: // * Button orientation.
405: // * @return Button background image.
406: // */
407: // private static synchronized ButtonBackground getPairwiseBackground(
408: // AbstractButton button, ColorSchemeKind kind,
409: // SubstanceGradientPainter painter, int width, int height,
410: // SubstanceConstants.Side side) {
411: // ComponentState state = ComponentState.getState(button.getModel(),
412: // button);
413: // // ComponentState.ColorSchemeKind kind = state.getColorSchemeKind();
414: // boolean isPaintedActive = (kind == ColorSchemeKind.CURRENT);
415: // float cyclePos = state.getCycleCount();
416: //
417: // ColorScheme colorScheme = SubstanceCoreUtilities.getComponentTheme(
418: // button, kind, true).getColorScheme();
419: // ColorScheme colorScheme2 = colorScheme;
420: // FadeTracker fadeTracker = FadeTracker.getInstance();
421: // if (fadeTracker.isTracked(button, FadeKind.ROLLOVER)) {
422: // boolean isActive = SubstanceCoreUtilities
423: // .isControlAlwaysPaintedActive(button, true);
424: // ColorScheme defaultScheme = SubstanceCoreUtilities
425: // .getDefaultScheme(button);
426: // if (state == ComponentState.DEFAULT) {
427: // // Came from rollover state
428: // colorScheme = SubstanceCoreUtilities.getActiveScheme(button);
429: // colorScheme2 = isActive ? colorScheme : defaultScheme;
430: // cyclePos = 10 - fadeTracker
431: // .getFade10(button, FadeKind.ROLLOVER);
432: // isPaintedActive = true;
433: // }
434: // if (state == ComponentState.ROLLOVER_UNSELECTED) {
435: // // Came from default state
436: // colorScheme2 = colorScheme;
437: // colorScheme = isActive ? colorScheme : defaultScheme;
438: // cyclePos = fadeTracker.getFade10(button, FadeKind.ROLLOVER);
439: // isPaintedActive = true;
440: // }
441: // }
442: //
443: // Set<Side> openSides = SubstanceCoreUtilities.getSides(button,
444: // SubstanceLookAndFeel.BUTTON_OPEN_SIDE_PROPERTY);
445: // String openKey = "";
446: // for (Side oSide : openSides) {
447: // openKey += oSide.name() + "-";
448: // }
449: // String key = width + ":" + height + ":" + side.toString() + ":"
450: // + cyclePos + ":" + openKey + ":"
451: // + SubstanceCoreUtilities.getSchemeId(colorScheme) + ":"
452: // + SubstanceCoreUtilities.getSchemeId(colorScheme2) + ":"
453: // + button.getClass().getName() + ":" + painter.getDisplayName();
454: // if (!pairwiseBackgrounds.containsKey(key)) {
455: // BufferedImage newBackground = null;
456: //
457: // // buttons will be rectangular to make two scrolls (horizontal
458: // // and vertical) touch the corners.
459: // int radius = 0;
460: //
461: // int deltaLeft = openSides.contains(Side.LEFT) ? 3 : 0;
462: // int deltaRight = openSides.contains(Side.RIGHT) ? 3 : 0;
463: // int deltaTop = openSides.contains(Side.TOP) ? 3 : 0;
464: // int deltaBottom = openSides.contains(Side.BOTTOM) ? 3 : 0;
465: //
466: // GeneralPath contour = null;
467: //
468: // // SubstanceGradientPainter painter = new StandardGradientPainter();
469: //
470: // switch (side) {
471: // case TOP:
472: // case BOTTOM:
473: // // arrow in vertical bar
474: // contour = BaseButtonShaper.getBaseOutline(height + deltaTop
475: // + deltaBottom, width + deltaLeft + deltaRight, radius,
476: // null);
477: //
478: // newBackground = painter.getContourBackground(height + deltaTop
479: // + deltaBottom, width + deltaLeft + deltaRight, contour,
480: // false, colorScheme, colorScheme2, cyclePos, true,
481: // colorScheme != colorScheme2);
482: // newBackground = SubstanceImageCreator.getRotated(newBackground,
483: // 3);
484: // break;
485: // case RIGHT:
486: // case LEFT:
487: // // arrow in horizontal bar
488: // contour = BaseButtonShaper.getBaseOutline(width + deltaLeft
489: // + deltaRight, height + deltaTop + deltaBottom, radius,
490: // null);
491: //
492: // newBackground = painter.getContourBackground(width + deltaLeft
493: // + deltaRight, height + deltaTop + deltaBottom, contour,
494: // false, colorScheme, colorScheme2, cyclePos, true,
495: // colorScheme != colorScheme2);
496: // break;
497: // }
498: //
499: // BufferedImage finalBackground = SubstanceCoreUtilities
500: // .getBlankImage(width, height);
501: // Graphics2D finalGraphics = (Graphics2D) finalBackground
502: // .getGraphics();
503: // finalGraphics.drawImage(newBackground, -deltaLeft, -deltaTop, null);
504: // pairwiseBackgrounds.put(key, finalBackground);
505: // }
506: // return new ButtonBackground(isPaintedActive, pairwiseBackgrounds
507: // .get(key));
508: // }
509: //
510: /**
511: * Simple constructor.
512: */
513: public ButtonBackgroundDelegate() {
514: super ();
515: }
516:
517: /**
518: * Updates background of the specified button.
519: *
520: * @param g
521: * Graphic context.
522: * @param button
523: * Button to update.
524: */
525: public void updateBackground(Graphics g, AbstractButton button) {
526: // failsafe for LAF change
527: if (!(UIManager.getLookAndFeel() instanceof SubstanceLookAndFeel))
528: return;
529:
530: button.setOpaque(false);
531: if (SubstanceCoreUtilities.isButtonNeverPainted(button))
532: return;
533:
534: Graphics2D graphics = (Graphics2D) g.create();
535: SubstanceGradientPainter painter = SubstanceCoreUtilities
536: .getGradientPainter(button);
537: // if (button.getModel().isPressed()) {
538: // painter = new FlatGradientPainter();
539: // }
540:
541: try {
542: int width = button.getWidth();
543: int height = button.getHeight();
544: int y = 0;
545: if (SubstanceCoreUtilities.isScrollButton(button)) {
546: Sideable sideable = (Sideable) button;
547: PairwiseButtonBackgroundDelegate.updateBackground(g,
548: button, sideable.getSide());
549: return;
550: }
551:
552: if (SubstanceCoreUtilities.isSpinnerButton(button)) {
553: Sideable sideable = (Sideable) button;
554: PairwiseButtonBackgroundDelegate.updateBackground(g,
555: button, sideable.getSide());
556: return;
557: }
558:
559: SubstanceButtonShaper shaper = SubstanceCoreUtilities
560: .getButtonShaper(button);
561: SubstanceBorderPainter borderPainter = SubstanceCoreUtilities
562: .getBorderPainter(button);
563:
564: // if (MemoryAnalyzer.isRunning())
565: // MemoryAnalyzer.enqueueUsage("For '" + button.getText()
566: // + "' using shaper '" + shaper.getClass().getName() + "'");
567: ButtonBackground bb = getBackground(button, shaper,
568: painter, borderPainter, width, height);
569: BufferedImage bgImage = bb.backgroundImage;
570: ControlBackgroundComposite composite = SubstanceCoreUtilities
571: .getControlBackgroundComposite(button);
572:
573: boolean isCustomComposite = (composite.getClass() != DefaultControlBackgroundComposite.class);
574:
575: // Here we can't set the composite directly on the graphics
576: // since then we would override the currently set composite
577: // (from TransitionLayout fades).
578: BufferedImage result = bgImage;
579:
580: if (isCustomComposite) {
581: result = SubstanceCoreUtilities.getBlankImage(bgImage
582: .getWidth(), bgImage.getHeight());
583: }
584: Graphics2D resultGr = result.createGraphics();
585: if (isCustomComposite) {
586: resultGr.setComposite(composite.getBackgroundComposite(
587: button, button.getParent(), -1,
588: bb.isPaintedActive));
589: }
590:
591: try {
592: ComponentState state = ComponentState.getState(button
593: .getModel(), button);
594:
595: // Two special cases here:
596: // 1. Button has flat appearance.
597: // 2. Button is disabled.
598: // For both cases, we need an extra temporary image with custom
599: // translucency.
600: boolean isSpecial = SubstanceCoreUtilities
601: .hasFlatAppearance(button)
602: || !state.isKindActive(FadeKind.ENABLE);
603: if (isSpecial) {
604: result = SubstanceCoreUtilities.getBlankImage(
605: bgImage.getWidth(), bgImage.getHeight());
606: resultGr = result.createGraphics();
607:
608: BufferedImage temp = SubstanceCoreUtilities
609: .getBlankImage(bgImage.getWidth(), bgImage
610: .getHeight());
611: Graphics2D tempGr = temp.createGraphics();
612: if (SubstanceCoreUtilities
613: .hasFlatAppearance(button)) {
614: // Special handling of flat buttons
615:
616: // System.out.println(button.getClass().getSimpleName()
617: // + " --> " + state.name());
618: if (FadeTracker.getInstance().isTracked(button,
619: FadeKind.ROLLOVER)
620: && !state
621: .isKindActive(FadeKind.SELECTION)
622: && state.isKindActive(FadeKind.ENABLE)) {
623: float fadeCoef = FadeTracker.getInstance()
624: .getFade10(button,
625: FadeKind.ROLLOVER);
626: tempGr.setComposite(AlphaComposite
627: .getInstance(
628: AlphaComposite.SRC_OVER,
629: fadeCoef / 10.0f));
630: } else {
631: if (state == ComponentState.DEFAULT) {
632: // System.out.println("Doing nothing");
633: return;
634: }
635: }
636: if (state != ComponentState.DISABLED_UNSELECTED)
637: tempGr.drawImage(bgImage, 0, 0, null);
638: } else {
639: if (!state.isKindActive(FadeKind.ENABLE)) {
640: tempGr.setComposite(AlphaComposite
641: .getInstance(
642: AlphaComposite.SRC_OVER,
643: SubstanceThemeUtilities
644: .getTheme(button)
645: .getThemeAlpha(
646: button,
647: state)));
648: }
649: tempGr.drawImage(bgImage, 0, 0, null);
650: }
651: // clear the image
652: resultGr.drawImage(temp, 0, 0, null);
653: tempGr.dispose();
654: } else {
655: if (isCustomComposite) {
656: resultGr.drawImage(bgImage, 0, 0, null);
657: }
658: }
659: graphics.drawImage(result, 0, y, null);
660: } finally {
661: resultGr.dispose();
662: }
663: } finally {
664: graphics.dispose();
665: }
666: }
667:
668: /**
669: * Checks whether the specified button has round corners.
670: *
671: * @param button
672: * Button to check.
673: * @return <code>true</code> if the specified button has round corners,
674: * <code>false</code> otherwise.
675: */
676: public static boolean isRoundButton(AbstractButton button) {
677: return (!SubstanceCoreUtilities.isComboBoxButton(button))
678: && (!SubstanceCoreUtilities.isScrollButton(button))
679: && SubstanceCoreUtilities.hasText(button);
680: }
681:
682: /**
683: * Returns <code>true</code> if the specified <i>x,y </i> location is
684: * contained within the look and feel's defined shape of the specified
685: * component. <code>x</code> and <code>y</code> are defined to be
686: * relative to the coordinate system of the specified component.
687: *
688: * @param button
689: * the component where the <i>x,y </i> location is being queried;
690: * @param x
691: * the <i>x </i> coordinate of the point
692: * @param y
693: * the <i>y </i> coordinate of the point
694: * @return <code>true</code> if the specified <i>x,y </i> location is
695: * contained within the look and feel's defined shape of the
696: * specified component, <code>false</code> otherwise.
697: */
698: public static boolean contains(AbstractButton button, int x, int y) {
699: // failsafe for LAF change
700: if (!(UIManager.getLookAndFeel() instanceof SubstanceLookAndFeel)) {
701: return false;
702: }
703: SubstanceButtonShaper shaper = SubstanceCoreUtilities
704: .getButtonShaper(button);
705: GeneralPath contour = shaper.getButtonOutline(button);
706: return contour.contains(x, y);
707: }
708:
709: /**
710: * Returns the memory usage string.
711: *
712: * @return Memory usage string.
713: */
714: static String getMemoryUsage() {
715: StringBuffer sb = new StringBuffer();
716: sb.append("SubstanceBackgroundDelegate: \n");
717: sb.append("\t" + regularBackgrounds.size() + " regular");
718: // + pairwiseBackgrounds.size() + " pairwise");
719: return sb.toString();
720: }
721:
722: }
|