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;
031:
032: import java.awt.*;
033:
034: import javax.swing.*;
035:
036: import org.jvnet.lafwidget.animation.FadeKind;
037: import org.jvnet.lafwidget.animation.FadeState;
038: import org.jvnet.lafwidget.layout.TransitionLayout;
039: import org.jvnet.substance.color.ColorScheme;
040: import org.jvnet.substance.painter.highlight.SubstanceHighlightUtils;
041: import org.jvnet.substance.theme.SubstanceTheme;
042: import org.jvnet.substance.utils.*;
043: import org.jvnet.substance.utils.SubstanceConstants.MenuGutterFillKind;
044:
045: /**
046: * Delegate for painting background of menu items.
047: *
048: * @author Kirill Grouchnikov
049: */
050: public class SubstanceMenuBackgroundDelegate {
051: /**
052: * Delegate for painting fill background.
053: */
054: private SubstanceFillBackgroundDelegate fillBackgroundDelegate;
055:
056: /**
057: * Creates a new background delegate for menu items.
058: *
059: * @param fillAlpha
060: * Alphs attribute for the fill.
061: */
062: public SubstanceMenuBackgroundDelegate(float fillAlpha) {
063: this .fillBackgroundDelegate = new SubstanceFillBackgroundDelegate(
064: fillAlpha);
065: }
066:
067: // /**
068: // * Paints the highlight background for the specified menu item.
069: // *
070: // * @param g
071: // * Graphic context.
072: // * @param menuItem
073: // * Menu item.
074: // * @param width
075: // * Background width.
076: // * @param height
077: // * Background height.
078: // * @param theme
079: // * Theme for the background.
080: // * @param borderAlpha
081: // * Border alpha.
082: // */
083: // private void paintHighlight(Graphics g, JMenuItem menuItem,
084: // ComponentState currState, ComponentState prevState, int width,
085: // int height, float borderAlpha) {
086: // SubstanceHighlightUtils.paintHighlight(g, menuItem, currState,
087: // prevState, new Rectangle(0, 0, menuItem.getWidth(), menuItem
088: // .getHeight()), borderAlpha);
089: // }
090:
091: /**
092: * Updates the specified menu item with the background that matches the
093: * provided parameters.
094: *
095: * @param g
096: * Graphic context.
097: * @param menuItem
098: * Menu item.
099: * @param bgColor
100: * Current background color.
101: * @param borderAlpha
102: * Border alpha.
103: * @param textOffset
104: * The offset of the menu item text.
105: */
106: public void paintBackground(Graphics g, JMenuItem menuItem,
107: Color bgColor, float borderAlpha, int textOffset) {
108: if (!menuItem.isShowing())
109: return;
110: int menuWidth = menuItem.getWidth();
111: int menuHeight = menuItem.getHeight();
112:
113: Graphics2D graphics = (Graphics2D) g.create();
114:
115: if (TransitionLayout.isOpaque(menuItem)) {
116: // // menu item is opaque and selected (or armed) -
117: // // use background color of the item (with watermark)
118: // graphics.setColor(menuItem.getBackground());
119: Component comp = menuItem.getParent();
120: // graphics.fillRect(0, 0, menuWidth, menuHeight);
121: // // System.out.println(menuItem.getText());
122: this .fillBackgroundDelegate.setWatermarkAlpha(0.4f);
123: while (comp != null) {
124: // System.out.println("\t" + comp.getClass().getName());
125: if (comp instanceof JMenuItem) {
126: break;
127: }
128: if (comp instanceof JMenuBar) {
129: // top-level
130: this .fillBackgroundDelegate.setWatermarkAlpha(1.0f);
131: break;
132: }
133: comp = comp.getParent();
134: }
135:
136: // if (!(menuItem.getParent() instanceof JMenuBar))
137: if (TransitionLayout.isOpaque(menuItem)) {
138: this .fillBackgroundDelegate.update(graphics, menuItem,
139: false);
140: }
141: if (menuItem.getParent() instanceof JPopupMenu) {
142: if (menuItem.getComponentOrientation().isLeftToRight()) {
143: MenuGutterFillKind fillKind = SubstanceCoreUtilities
144: .getMenuGutterFillKind();
145: if (fillKind != MenuGutterFillKind.NONE) {
146: ColorScheme scheme = SubstanceThemeUtilities
147: .getTheme(menuItem,
148: ComponentState.DEFAULT)
149: .getColorScheme();
150: Color leftColor = ((fillKind == MenuGutterFillKind.SOFT_FILL) || (fillKind == MenuGutterFillKind.HARD)) ? scheme
151: .getUltraLightColor()
152: : scheme.getLightColor();
153: Color rightColor = ((fillKind == MenuGutterFillKind.SOFT_FILL) || (fillKind == MenuGutterFillKind.SOFT)) ? scheme
154: .getUltraLightColor()
155: : scheme.getLightColor();
156: GradientPaint gp = new GradientPaint(0, 0,
157: leftColor, textOffset, 0, rightColor);
158: graphics.setComposite(TransitionLayout
159: .getAlphaComposite(menuItem, 0.7f, g));
160:
161: // System.out.println(menuItem.getText()
162: // + "["
163: // + menuItem.isEnabled()
164: // + "] : "
165: // + ((AlphaComposite) graphics.getComposite())
166: // .getAlpha() + ", " + leftColor + "->"
167: // + rightColor);
168: //
169: graphics.setPaint(gp);
170: graphics.fillRect(0, 0, textOffset - 2,
171: menuHeight);
172: }
173: } else {
174: // fix for defect 125 - support of RTL menus
175: MenuGutterFillKind fillKind = SubstanceCoreUtilities
176: .getMenuGutterFillKind();
177: if (fillKind != MenuGutterFillKind.NONE) {
178: ColorScheme scheme = SubstanceThemeUtilities
179: .getTheme(menuItem,
180: ComponentState.DEFAULT)
181: .getColorScheme();
182: Color leftColor = ((fillKind == MenuGutterFillKind.HARD_FILL) || (fillKind == MenuGutterFillKind.HARD)) ? scheme
183: .getLightColor()
184: : scheme.getUltraLightColor();
185: Color rightColor = ((fillKind == MenuGutterFillKind.HARD_FILL) || (fillKind == MenuGutterFillKind.SOFT)) ? scheme
186: .getLightColor()
187: : scheme.getUltraLightColor();
188: GradientPaint gp = new GradientPaint(
189: textOffset, 0, leftColor, menuWidth, 0,
190: rightColor);
191: graphics.setComposite(TransitionLayout
192: .getAlphaComposite(menuItem, 0.7f, g));
193: graphics.setPaint(gp);
194: graphics.fillRect(textOffset - 2, 0, menuWidth,
195: menuHeight);
196: }
197: }
198: }
199: }
200:
201: graphics.dispose();
202: }
203:
204: public static void paintHighlights(Graphics g, JMenuItem menuItem,
205: float borderAlpha) {
206: Graphics2D graphics = (Graphics2D) g.create();
207:
208: ButtonModel model = menuItem.getModel();
209: // int menuWidth = menuItem.getWidth();
210: // int menuHeight = menuItem.getHeight();
211:
212: ComponentState prevState = SubstanceCoreUtilities
213: .getPrevComponentState(menuItem);
214: ComponentState currState = ComponentState.getState(model,
215: menuItem, !(menuItem instanceof JMenu));
216:
217: // Compute the alpha values for the animation (the highlights
218: // have separate alpha channels, so that rollover animation can start
219: // from 0.0 alpha and goes to 0.4 alpha on non-selected cells,
220: // but on selected cells can go from 0.7 to 0.9). We need to respect
221: // these border values for proper visual transitions
222: float startAlpha = SubstanceThemeUtilities.getHighlightAlpha(
223: menuItem, prevState);
224: float endAlpha = SubstanceThemeUtilities.getHighlightAlpha(
225: menuItem, currState);
226:
227: SubstanceTheme prevTheme = SubstanceThemeUtilities
228: .getHighlightTheme(menuItem, prevState);
229: SubstanceTheme currTheme = SubstanceThemeUtilities
230: .getHighlightTheme(menuItem, currState);
231:
232: FadeState state = SubstanceFadeUtilities.getFadeState(menuItem,
233: FadeKind.SELECTION, FadeKind.ARM, FadeKind.ROLLOVER);
234: float fadeCoef = 0.0f;
235: float totalAlpha = endAlpha;
236: if (state != null) {
237: fadeCoef = state.getFadePosition();
238:
239: // compute the total alpha of the overlays.
240: if (state.isFadingIn()) {
241: totalAlpha = startAlpha + (endAlpha - startAlpha)
242: * fadeCoef / 10.0f;
243: } else {
244: totalAlpha = startAlpha + (endAlpha - startAlpha)
245: * (10.0f - fadeCoef) / 10.0f;
246: }
247:
248: if (state.isFadingIn())
249: fadeCoef = 10.0f - fadeCoef;
250:
251: // System.out.println(menuItem.getText() + " from " +
252: // prevState.name()
253: // + "[" + alphaForPrevBackground + "] to " + currState.name()
254: // + "[" + alphaForCurrBackground + "] at " + fadeCoef);
255: // System.out.println("From " + prevTheme.getDisplayName() + " to :"
256: // + currTheme.getDisplayName());
257:
258: }
259:
260: // System.out.println(menuItem.getText() + "[" + currState.name() + "]:"
261: // + prevTheme.getDisplayName() + "[" + alphaForPrevBackground
262: // + "]:" + currTheme.getDisplayName() + "["
263: // + alphaForCurrBackground + "]");
264: // System.out.println("ARM:" + menuItem.getModel().isArmed() + ", ENA:"
265: // + menuItem.getModel().isEnabled() + ", PRE:"
266: // + menuItem.getModel().isPressed() + ", ROL:"
267: // + menuItem.getModel().isRollover() + ", SEL:"
268: // + menuItem.getModel().isSelected());
269:
270: // fix for defect 103 - no rollover effects on menu items
271: // that are not in the selected menu path
272: MenuElement[] selectedMenuPath = MenuSelectionManager
273: .defaultManager().getSelectedPath();
274: boolean isRollover = (selectedMenuPath.length == 0);
275: for (MenuElement elem : selectedMenuPath) {
276: if (elem == menuItem) {
277: isRollover = true;
278: break;
279: }
280: }
281: isRollover = isRollover && model.isRollover();
282:
283: boolean hasHighlight = (state != null) || model.isArmed()
284: || isRollover
285: || ((menuItem instanceof JMenu) && model.isSelected());
286:
287: if (hasHighlight && (totalAlpha > 0.0f)) {
288: graphics.setComposite(TransitionLayout.getAlphaComposite(
289: menuItem, totalAlpha, g));
290: SubstanceHighlightUtils.paintHighlight(graphics, menuItem,
291: new Rectangle(0, 0, menuItem.getWidth(), menuItem
292: .getHeight()), borderAlpha, null, currTheme
293: .getColorScheme(), prevTheme
294: .getColorScheme(), fadeCoef);
295: graphics.setComposite(TransitionLayout.getAlphaComposite(
296: menuItem, g));
297: }
298: graphics.dispose();
299: }
300: }
|