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 javax.swing.*;
033:
034: import org.jvnet.lafwidget.animation.FadeKind;
035: import org.jvnet.substance.color.*;
036:
037: /**
038: * This enum is used in order to provide uniform transition effects on mouse
039: * events. The effects include different visual appearance of the corresponding
040: * control when the mouse hovers over it (rollover), when it's pressed or
041: * selected, disabled etc.<br>
042: * Each enum value represents a single state and contains information that is
043: * used by the UI delegates in order to correctly paint the corresponding
044: * controls. <br>
045: * This class is <b>for internal use only</b>.
046: *
047: * @author Kirill Grouchnikov
048: */
049: public enum ComponentState {
050: /**
051: * Disabled active. Used for disabled buttons that have been marked as
052: * <code>default</code>.
053: */
054: DISABLED_ACTIVE(ColorSchemeKind.DISABLED, 0),
055:
056: /**
057: * Active. Used for enabled buttons that have been marked as
058: * <code>default</code>.
059: */
060: ACTIVE(ColorSchemeKind.CURRENT, 0, FadeKind.ENABLE),
061:
062: /**
063: * Disabled selected.
064: */
065: DISABLED_SELECTED(ColorSchemeKind.DISABLED, 10, FadeKind.SELECTION),
066:
067: /**
068: * Disabled and not selected.
069: */
070: DISABLED_UNSELECTED(ColorSchemeKind.DISABLED, 0),
071:
072: /**
073: * Pressed selected.
074: */
075: PRESSED_SELECTED(ColorSchemeKind.CURRENT, 5, FadeKind.ENABLE,
076: FadeKind.SELECTION, FadeKind.PRESS),
077:
078: /**
079: * Pressed and not selected.
080: */
081: PRESSED_UNSELECTED(ColorSchemeKind.CURRENT, 8, FadeKind.ENABLE,
082: FadeKind.PRESS),
083:
084: /**
085: * Selected.
086: */
087: SELECTED(ColorSchemeKind.CURRENT, 8, FadeKind.ENABLE,
088: FadeKind.SELECTION),
089:
090: /**
091: * Selected and rolled over.
092: */
093: ROLLOVER_SELECTED(ColorSchemeKind.CURRENT, 4, FadeKind.ENABLE,
094: FadeKind.ROLLOVER, FadeKind.SELECTION),
095:
096: /**
097: * Armed.
098: */
099: ARMED(ColorSchemeKind.CURRENT, 5, FadeKind.ENABLE, FadeKind.ARM),
100:
101: /**
102: * Armed and rolled over.
103: */
104: ROLLOVER_ARMED(ColorSchemeKind.CURRENT, 7, FadeKind.ENABLE,
105: FadeKind.ROLLOVER, FadeKind.ARM),
106:
107: /**
108: * Not selected and rolled over.
109: */
110: ROLLOVER_UNSELECTED(ColorSchemeKind.CURRENT, 3, FadeKind.ENABLE,
111: FadeKind.ROLLOVER),
112:
113: /**
114: * Default state.
115: */
116: DEFAULT(ColorSchemeKind.REGULAR, 0, FadeKind.ENABLE);
117:
118: /**
119: * Enum for color scheme kind. Is used in order to decouple the actual
120: * current color scheme and the decision on whether to use it.
121: *
122: * @author Kirill Grouchnikov
123: */
124: public static enum ColorSchemeKind {
125: /**
126: * Current color scheme (e.g. {@link AquaColorScheme}).
127: */
128: CURRENT,
129:
130: /**
131: * Regular color scheme (usually {@link MetallicColorScheme}).
132: */
133: REGULAR,
134:
135: /**
136: * Disabled color scheme (usually {@link LightGrayColorScheme}).
137: */
138: DISABLED
139: }
140:
141: /**
142: * The corresponding color scheme kind.
143: */
144: private ColorSchemeKind colorSchemeKind;
145:
146: /**
147: * The corresponding cycle count. Should be a number between 0 and 10. This
148: * number is used to compute the foreground color of some component. The
149: * color is interpolated between two values (0 corresponds to usual color,
150: * 10 corresponds to very light version of the usual color).
151: */
152: private int cycleCount;
153:
154: /**
155: * Active fade kinds for this state. For example, {@link #ROLLOVER_SELECTED}
156: * contains {@link FadeKind#ROLLOVER} and {@link FadeKind#SELECTION}.
157: */
158: private FadeKind[] activeKinds;
159:
160: /**
161: * Simple constructor.
162: *
163: * @param kind
164: * The corresponding color scheme kind.
165: * @param count
166: * The corresponding cycle count.
167: * @param activeKinds
168: * Indicates active fade kinds for this state. For example,
169: * {@link #ROLLOVER_SELECTED} should pass both
170: * {@link FadeKind#ROLLOVER} and {@link FadeKind#SELECTION}.
171: */
172: ComponentState(ColorSchemeKind kind, int count,
173: FadeKind... activeKinds) {
174: colorSchemeKind = kind;
175: cycleCount = count;
176: this .activeKinds = activeKinds;
177: }
178:
179: /**
180: * Returns the corresponding color scheme kind
181: *
182: * @return Corresponding color scheme kind
183: */
184: public ColorSchemeKind getColorSchemeKind() {
185: return colorSchemeKind;
186: }
187:
188: /**
189: * Returns the corresponding cycle count.
190: *
191: * @return Corresponding cycle count.
192: */
193: public int getCycleCount() {
194: return cycleCount;
195: }
196:
197: /**
198: * Returns indication whether <code>this</code> component state is
199: * "active" under the specified fade kind. For example,
200: * {@link #ROLLOVER_SELECTED} will return <code>true</code> for both
201: * {@link FadeKind#ROLLOVER} and {@link FadeKind#SELECTION}.
202: *
203: * @param fadeKind
204: * Fade kind.
205: * @return <code>true</code> if <code>this</code> component state is
206: * "active" under the specified fade kind (for example,
207: * {@link #ROLLOVER_SELECTED} will return <code>true</code> for
208: * both {@link FadeKind#ROLLOVER} and {@link FadeKind#SELECTION}),
209: * <code>false</code> otherwise.
210: */
211: public boolean isKindActive(FadeKind fadeKind) {
212: if (activeKinds == null)
213: return false;
214: for (FadeKind fk : activeKinds)
215: if (fadeKind == fk)
216: return true;
217: return false;
218: }
219:
220: /**
221: * Retrieves component state based on the button model (required parameter)
222: * and button itself (optional parameter).
223: *
224: * @param model
225: * Button model (required).
226: * @param component
227: * Button (optional).
228: * @return The matching component state.
229: */
230: public static ComponentState getState(ButtonModel model,
231: JComponent component) {
232: return getState(model, component, false);
233: }
234:
235: /**
236: * Retrieves component state based on the button model (required parameter)
237: * and button itself (optional parameter).
238: *
239: * @param model
240: * Button model (required).
241: * @param component
242: * Button (optional).
243: * @param toIgnoreSelection
244: * If <code>true</code>, the {@link ButtonModel#isSelected()}
245: * will not be checked. This can be used for tracking transitions
246: * on menu items that use <code>armed</code> state instead,
247: * when we don't want to use different rollover themes for
248: * selected and unselected checkbox and radio button menu items
249: * (to preserve consistent visual appearence of highlights).
250: * @return The matching component state.
251: */
252: public static ComponentState getState(ButtonModel model,
253: JComponent component, boolean toIgnoreSelection) {
254:
255: // if (button instanceof JToggleButton) {
256: // System.out.println(button.getWidth() + "*" + button.getHeight()
257: // + ":" + (model.isEnabled() ? "enabled:" : "")
258: // + (model.isArmed() ? "armed:" : "")
259: // + (model.isSelected() ? "selected:" : "")
260: // + (model.isRollover() ? "rollover:" : "")
261: // + (button.isRolloverEnabled() ? "rollover enabled:" : "")
262: // + (model.isPressed() ? "pressed:" : ""));
263: // }
264: //
265:
266: boolean isRollover = model.isRollover();
267: // fix for defect 103 - no rollover effects on menu items
268: // that are not in the selected menu path
269: MenuElement[] selectedMenuPath = MenuSelectionManager
270: .defaultManager().getSelectedPath();
271: for (MenuElement elem : selectedMenuPath) {
272: if (elem == component) {
273: isRollover = true;
274: break;
275: }
276: }
277:
278: if (component != null) {
279: if (component instanceof JButton) {
280: JButton jb = (JButton) component;
281: if (jb.isDefaultButton()) {
282: if (model.isEnabled()) {
283: if ((!model.isPressed()) && (!model.isArmed()))
284: return ACTIVE;
285: } else
286: return DISABLED_ACTIVE;
287: }
288: }
289: }
290:
291: boolean isRolloverEnabled = true;
292: if (component instanceof AbstractButton)
293: isRolloverEnabled = ((AbstractButton) component)
294: .isRolloverEnabled();
295: if (!model.isEnabled()) {
296: if (model.isSelected())
297: return DISABLED_SELECTED;
298: return DISABLED_UNSELECTED;
299: } else if (model.isPressed() && model.isArmed()) {
300: if (model.isSelected())
301: return PRESSED_SELECTED;
302: return PRESSED_UNSELECTED;
303: } else if (!toIgnoreSelection && model.isSelected()) {
304: if (((component == null) || isRolloverEnabled)
305: && isRollover)
306: return ROLLOVER_SELECTED;
307: return SELECTED;
308: } else if (model.isArmed()) {
309: if (((component == null) || isRolloverEnabled)
310: && isRollover)
311: return ROLLOVER_ARMED;
312: return ARMED;
313: } else if (((component == null) || isRolloverEnabled)
314: && isRollover)
315: return ROLLOVER_UNSELECTED;
316:
317: return DEFAULT;
318: }
319:
320: }
|