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.Color;
033: import java.awt.Component;
034:
035: import javax.swing.JComponent;
036: import javax.swing.JTabbedPane;
037: import javax.swing.plaf.UIResource;
038:
039: import org.jvnet.lafwidget.animation.FadeKind;
040: import org.jvnet.substance.SubstanceLookAndFeel;
041: import org.jvnet.substance.combo.SubstanceComboBoxButton;
042: import org.jvnet.substance.painter.decoration.DecorationAreaType;
043: import org.jvnet.substance.painter.decoration.SubstanceDecorationUtilities;
044: import org.jvnet.substance.scroll.SubstanceScrollButton;
045: import org.jvnet.substance.theme.*;
046:
047: public class SubstanceThemeUtilities {
048: public static SubstanceTheme getDecorationTheme(Component component) {
049: Component c = component;
050: SubstanceTheme globalTheme = SubstanceLookAndFeel.getTheme();
051: while (c != null) {
052: DecorationAreaType decorationType = SubstanceDecorationUtilities
053: .getImmediateDecorationType(c);
054: if (decorationType != null) {
055: if (globalTheme.toUseDecorationPainter(decorationType)) {
056: return globalTheme
057: .getDecorationTheme(decorationType);
058: }
059: }
060: // if (c instanceof JPopupMenu) {
061: // Component invoker = ((JPopupMenu) c).getInvoker();
062: // if (c != invoker)
063: // return getDecorationTheme(invoker);
064: // }
065: c = c.getParent();
066: }
067: return null;
068: }
069:
070: public static SubstanceTheme getNonColorizedTheme(
071: Component component, boolean toReturnCurrent) {
072: SubstanceTheme notColorized = null;
073: if (component != null) {
074: Component comp = component;
075: // while (comp != null) {
076: if (comp instanceof JComponent) {
077: JComponent jcomp = (JComponent) comp;
078: Object controlThemeObj = jcomp
079: .getClientProperty(SubstanceLookAndFeel.THEME_PROPERTY);
080: if (controlThemeObj != null) {
081: if (controlThemeObj instanceof String) {
082: notColorized = SubstanceTheme
083: .getTheme((String) controlThemeObj);
084: }
085: if (controlThemeObj instanceof ThemeInfo) {
086: notColorized = SubstanceTheme
087: .createInstance((ThemeInfo) controlThemeObj);
088: }
089: if (controlThemeObj instanceof SubstanceTheme) {
090: notColorized = ((SubstanceTheme) controlThemeObj);
091: }
092: }
093: // Object decorationAreaObj = jcomp.getClientProperty(key)
094: }
095: }
096:
097: if (notColorized == null)
098: if (toReturnCurrent)
099: return SubstanceLookAndFeel.getTheme();
100:
101: return notColorized;
102: }
103:
104: public static SubstanceTheme getTheme(Component component) {
105: SubstanceTheme theme = getDecorationTheme(component);
106: if (theme == null) {
107: theme = getNonColorizedTheme(component, true);
108: }
109: if (theme == null) {
110: theme = SubstanceLookAndFeel.getTheme();
111: }
112:
113: return getColorizedTheme(component, theme);
114: }
115:
116: public static SubstanceTheme getColorizedTheme(Component component,
117: SubstanceTheme theme, ColorizationSupport support) {
118: if (component != null) {
119: // Support for enhancement 256 - colorizing
120: // controls.
121: Color bk = support.getBackground(component);
122: Color fg = support.getForeground(component);
123: if (component instanceof SubstanceTitleButton) {
124: if ((fg != null) && (bk != null)) {
125: // guard for issue 322 - these are null when JavaHelp
126: // window is printed.
127: fg = SubstanceColorUtilities.getInterpolatedColor(
128: fg, bk, 0.5);
129: }
130: }
131: if (bk instanceof UIResource)
132: bk = null;
133: if (fg instanceof UIResource) {
134: fg = null;
135: }
136: if ((bk != null) || (fg != null)) {
137: double colorization = SubstanceCoreUtilities
138: .getColorizationFactor(component);
139: if (colorization > 0.0) {
140: return SubstanceShiftTheme.getShiftedTheme(theme,
141: bk, colorization, fg, colorization);
142: }
143: }
144: }
145: return theme;
146: }
147:
148: public static interface ColorizationSupport {
149: public Color getBackground(Component component);
150:
151: public Color getForeground(Component component);
152: }
153:
154: public static SubstanceTheme getColorizedTheme(Component component,
155: SubstanceTheme theme) {
156: ColorizationSupport support = new ColorizationSupport() {
157: private boolean toTakeFromParent(Component component) {
158: return (component.getParent() != null)
159: && ((component instanceof SubstanceScrollButton)
160: || (component instanceof SubstanceSpinnerButton)
161: || (component instanceof SubstanceComboBoxButton) || (component instanceof SubstanceTitleButton));
162: }
163:
164: public Color getBackground(Component component) {
165: return toTakeFromParent(component) ? component
166: .getParent().getBackground() : component
167: .getBackground();
168: }
169:
170: public Color getForeground(Component component) {
171: return toTakeFromParent(component) ? component
172: .getParent().getBackground() : component
173: .getBackground();
174: }
175: };
176:
177: if (component != null) {
178: // Support for enhancement 256 - colorizing
179: // controls. Special case - scroll, combo and spinner buttons
180: // that should take the background from parent.
181: boolean takeFromParent = (component instanceof SubstanceScrollButton)
182: || (component instanceof SubstanceSpinnerButton)
183: || (component instanceof SubstanceComboBoxButton)
184: || (component instanceof SubstanceTitleButton);
185: takeFromParent = takeFromParent
186: && (component.getParent() != null);
187: Color bk = takeFromParent ? component.getParent()
188: .getBackground() : component.getBackground();
189: Color fg = takeFromParent ? component.getParent()
190: .getForeground() : component.getForeground();
191: if (component instanceof SubstanceTitleButton) {
192: if ((fg != null) && (bk != null)) {
193: // guard for issue 322 - these are null when JavaHelp
194: // window is printed.
195: fg = SubstanceColorUtilities.getInterpolatedColor(
196: fg, bk, 0.5);
197: }
198: }
199: if (bk instanceof UIResource)
200: bk = null;
201: if (fg instanceof UIResource) {
202: fg = null;
203: }
204: if ((bk != null) || (fg != null)) {
205: double colorization = SubstanceCoreUtilities
206: .getColorizationFactor(component);
207: if (colorization > 0.0) {
208: return SubstanceShiftTheme.getShiftedTheme(theme,
209: bk, colorization, fg, colorization);
210: }
211: }
212: }
213: return theme;
214: }
215:
216: public static SubstanceTheme getNonColorizedTheme(JTabbedPane jtp,
217: int tabIndex) {
218: SubstanceTheme compTheme = getNonColorizedTheme(jtp
219: .getComponentAt(tabIndex), false);
220: if (compTheme != null)
221: return compTheme;
222: SubstanceTheme paneTheme = getNonColorizedTheme(jtp, true);
223: return paneTheme;
224: }
225:
226: public static SubstanceTheme getTheme(final JTabbedPane jtp,
227: final int tabIndex, ComponentState componentState) {
228: Component component = jtp.getComponent(tabIndex);
229:
230: SubstanceTheme nonColorized = getNonColorizedTheme(jtp,
231: tabIndex);
232: if (SubstanceCoreUtilities.isControlAlwaysPaintedActive(
233: component, true)) {
234: if (componentState.isKindActive(FadeKind.ENABLE))
235: componentState = ComponentState.SELECTED;
236: else
237: componentState = ComponentState.DISABLED_SELECTED;
238: }
239: SubstanceTheme colorized = getColorizedTheme(component,
240: nonColorized, new ColorizationSupport() {
241: public Color getBackground(Component component) {
242: return jtp.getBackgroundAt(tabIndex);
243: }
244:
245: public Color getForeground(Component component) {
246: return component.getForeground();
247: }
248: });
249: return colorized.getTheme(component, componentState);
250: }
251:
252: /**
253: * Returns the theme of the component.
254: *
255: * @param component
256: * Component.
257: * @param componentState
258: * Component state.
259: * @return Component theme.
260: */
261: public static SubstanceTheme getTheme(Component component,
262: ComponentState componentState) {
263: return getTheme(component, componentState, false);
264: }
265:
266: /**
267: * Returns the theme of the component.
268: *
269: * @param component
270: * Component.
271: * @param componentState
272: * Component state.
273: * @return Component theme.
274: */
275: public static SubstanceTheme getTheme(Component component,
276: ComponentState componentState, boolean toIgnoreHighlights) {
277: if ((component != null)
278: && SubstanceCoreUtilities.isControlAlwaysPaintedActive(
279: component, true)
280: && !componentState.isKindActive(FadeKind.PRESS)
281: && componentState.isKindActive(FadeKind.ENABLE)) {
282: componentState = ComponentState.ACTIVE;
283: }
284: SubstanceTheme theme = null;
285:
286: boolean isControlActive = componentState
287: .isKindActive(FadeKind.ENABLE)
288: && (componentState != ComponentState.DEFAULT);
289: boolean toUseDecorationTheme = false;
290: DecorationAreaType decorationType = SubstanceDecorationUtilities
291: .getDecorationType(component);
292: if (decorationType != null) {
293: toUseDecorationTheme = SubstanceLookAndFeel.getTheme()
294: .toUseDecorationThemeOnActiveControls(
295: decorationType);
296: }
297:
298: if (!isControlActive || toUseDecorationTheme) {
299: theme = getTheme(component);
300: } else {
301: // if the component is in active state and participates in
302: // rollover, selection, press or arm transition, we need to
303: // ignore the decoration theme.
304: theme = getNonColorizedTheme(component, true);
305: if (theme != null) {
306: theme = getColorizedTheme(component, theme);
307: }
308: }
309: if (theme != null) {
310: return theme.getTheme(component, componentState,
311: toIgnoreHighlights);
312: }
313: return SubstanceLookAndFeel.getTheme();
314: }
315:
316: /**
317: * Returns the highlight theme of the component.
318: *
319: * @param component
320: * Component.
321: * @param componentState
322: * Component state.
323: * @return Component highlight theme.
324: */
325: public static SubstanceTheme getHighlightTheme(Component component,
326: ComponentState componentState) {
327: SubstanceTheme nonColorized = getNonColorizedTheme(component,
328: true);
329: SubstanceTheme theme = getColorizedTheme(component,
330: nonColorized);
331: if (theme != null)
332: return theme.getHighlightTheme(component, componentState);
333: return null;
334: }
335:
336: /**
337: * Returns the alpha channel of the highlight theme of the component.
338: *
339: * @param component
340: * Component.
341: * @param componentState
342: * Component state.
343: * @return Highlight theme alpha channel.
344: */
345: public static float getHighlightAlpha(Component component,
346: ComponentState componentState) {
347: SubstanceTheme nonColorized = getNonColorizedTheme(component,
348: true);
349: SubstanceTheme theme = getColorizedTheme(component,
350: nonColorized);
351: if (theme != null)
352: return theme.getHighlightThemeAlpha(component,
353: componentState);
354: return 0.0f;
355: }
356:
357: private static class ConstantThemeWrapper extends SubstanceTheme {
358: private SubstanceTheme delegate;
359:
360: public ConstantThemeWrapper(SubstanceTheme delegate) {
361: super (delegate.getColorScheme(), "Wrapper "
362: + delegate.getDisplayName(), delegate.getKind());
363: this .delegate = delegate;
364: }
365:
366: @Override
367: public SubstanceTheme getActiveTheme() {
368: return this .delegate;
369: }
370:
371: @Override
372: public SubstanceTheme getActiveTitlePaneTheme() {
373: return this .delegate;
374: }
375:
376: @Override
377: public SubstanceTheme getBorderTheme() {
378: return this .delegate;
379: }
380:
381: @Override
382: public SubstanceTheme getDecorationTheme(
383: DecorationAreaType decorationType) {
384: return this .delegate;
385: }
386:
387: @Override
388: public SubstanceTheme getDefaultTheme() {
389: return this .delegate;
390: }
391:
392: @Override
393: public SubstanceTheme getDefaultTitlePaneTheme() {
394: return this .delegate;
395: }
396:
397: @Override
398: public SubstanceTheme getDisabledTheme() {
399: return this .delegate.getDisabledTheme();
400: }
401:
402: @Override
403: public SubstanceTheme getFirstTheme() {
404: return this .delegate;
405: }
406:
407: @Override
408: public SubstanceTheme getHighlightTheme(Component comp,
409: ComponentState componentState) {
410: return this .delegate;
411: }
412:
413: @Override
414: public SubstanceTheme getSecondTheme() {
415: return this .delegate;
416: }
417:
418: @Override
419: public SubstanceTheme getTheme(Component comp,
420: ComponentState componentState) {
421: if (!componentState.isKindActive(FadeKind.ENABLE))
422: return this .delegate.getDisabledTheme();
423: return this .delegate;
424: }
425:
426: @Override
427: public SubstanceTheme getTheme(Component comp,
428: ComponentState componentState,
429: boolean toIgnoreHighlights) {
430: if (!componentState.isKindActive(FadeKind.ENABLE))
431: return this .delegate.getDisabledTheme();
432: return this .delegate;
433: }
434:
435: @Override
436: public SubstanceTheme getWatermarkTheme() {
437: return this .delegate;
438: }
439: }
440:
441: public static SubstanceTheme getConstantTheme(SubstanceTheme theme) {
442: return new ConstantThemeWrapper(theme);
443: }
444: }
|