2
* Copyright (c) 2005-2010 Substance Kirill Grouchnikov. All Rights Reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* o Redistributions of source code must retain the above copyright notice,
8
* this list of conditions and the following disclaimer.
10
* o Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
14
* o Neither the name of Substance Kirill Grouchnikov nor the names of
15
* its contributors may be used to endorse or promote products derived
16
* from this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
package org.pushingpixels.substance.internal.utils.icon;
32
import java.awt.AlphaComposite;
33
import java.awt.Component;
34
import java.awt.Graphics;
35
import java.awt.Graphics2D;
36
import java.awt.image.BufferedImage;
39
import javax.swing.Icon;
40
import javax.swing.ImageIcon;
41
import javax.swing.JMenuItem;
42
import javax.swing.JRadioButtonMenuItem;
43
import javax.swing.plaf.UIResource;
45
import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
46
import org.pushingpixels.substance.api.ComponentState;
47
import org.pushingpixels.substance.api.ComponentStateFacet;
48
import org.pushingpixels.substance.api.SubstanceColorScheme;
49
import org.pushingpixels.substance.api.painter.border.SubstanceBorderPainter;
50
import org.pushingpixels.substance.api.painter.fill.SubstanceFillPainter;
51
import org.pushingpixels.substance.internal.animation.StateTransitionTracker;
52
import org.pushingpixels.substance.internal.animation.TransitionAwareUI;
53
import org.pushingpixels.substance.internal.utils.HashMapKey;
54
import org.pushingpixels.substance.internal.utils.LazyResettableHashMap;
55
import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities;
56
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
57
import org.pushingpixels.substance.internal.utils.SubstanceImageCreator;
58
import org.pushingpixels.substance.internal.utils.SubstanceSizeUtils;
61
* Icon for the {@link JRadioButtonMenuItem}s.
63
* @author Kirill Grouchnikov
65
public class RadioButtonMenuItemIcon implements Icon, UIResource {
67
* The size of <code>this</code> icon.
72
* The associated menu item.
74
private JMenuItem menuItem;
77
* Icon cache to speed up the painting.
79
private static LazyResettableHashMap<Icon> iconMap = new LazyResettableHashMap<Icon>(
80
"RadioButtonMenuItemIcon");
86
* The corresponding menu item.
88
* The size of <code>this</code> icon.
90
public RadioButtonMenuItemIcon(JMenuItem menuItem, int size) {
91
this.menuItem = menuItem;
96
* Returns the current icon to paint.
98
* @return Icon to paint.
100
private Icon getIconToPaint() {
101
if (this.menuItem == null)
103
TransitionAwareUI transitionAwareUI = (TransitionAwareUI) this.menuItem
105
StateTransitionTracker stateTransitionTracker = transitionAwareUI
106
.getTransitionTracker();
108
StateTransitionTracker.ModelStateInfo modelStateInfo = stateTransitionTracker
109
.getModelStateInfo();
110
Map<ComponentState, StateTransitionTracker.StateContributionInfo> activeStates = modelStateInfo
111
.getStateContributionMap();
113
int fontSize = SubstanceSizeUtils.getComponentFontSize(this.menuItem);
114
int checkMarkSize = this.size;
116
SubstanceFillPainter fillPainter = SubstanceCoreUtilities
117
.getFillPainter(this.menuItem);
118
SubstanceBorderPainter borderPainter = SubstanceCoreUtilities
119
.getBorderPainter(this.menuItem);
120
ComponentState currState = modelStateInfo.getCurrModelState();
122
SubstanceColorScheme baseFillColorScheme = SubstanceColorSchemeUtilities
123
.getColorScheme(this.menuItem, ColorSchemeAssociationKind.FILL,
125
SubstanceColorScheme baseMarkColorScheme = SubstanceColorSchemeUtilities
126
.getColorScheme(this.menuItem, ColorSchemeAssociationKind.MARK,
128
SubstanceColorScheme baseBorderColorScheme = SubstanceColorSchemeUtilities
129
.getColorScheme(this.menuItem,
130
ColorSchemeAssociationKind.BORDER, currState);
131
float visibility = stateTransitionTracker
132
.getFacetStrength(ComponentStateFacet.SELECTION);
134
HashMapKey keyBase = SubstanceCoreUtilities.getHashKey(fontSize,
135
checkMarkSize, fillPainter.getDisplayName(), borderPainter
137
baseFillColorScheme.getDisplayName(), baseMarkColorScheme
138
.getDisplayName(), baseBorderColorScheme
139
.getDisplayName(), visibility);
140
Icon iconBase = iconMap.get(keyBase);
141
if (iconBase == null) {
142
iconBase = new ImageIcon(SubstanceImageCreator.getRadioButton(
143
this.menuItem, fillPainter, borderPainter, checkMarkSize,
144
currState, 0, baseFillColorScheme, baseMarkColorScheme,
145
baseBorderColorScheme, visibility));
146
iconMap.put(keyBase, iconBase);
148
if (currState.isDisabled() || (activeStates.size() == 1)) {
152
BufferedImage result = SubstanceCoreUtilities.getBlankImage(iconBase
153
.getIconWidth(), iconBase.getIconHeight());
154
Graphics2D g2d = result.createGraphics();
155
// draw the base layer
156
iconBase.paintIcon(this.menuItem, g2d, 0, 0);
158
// draw other active layers
159
for (Map.Entry<ComponentState, StateTransitionTracker.StateContributionInfo> activeEntry : activeStates
161
ComponentState activeState = activeEntry.getKey();
162
// System.out.println("Painting state " + activeState + "[curr is "
163
// + currState + "] with " + activeEntry.getValue());
164
if (activeState == currState)
167
float stateContribution = activeEntry.getValue().getContribution();
168
if (stateContribution > 0.0f) {
169
g2d.setComposite(AlphaComposite.SrcOver
170
.derive(stateContribution));
171
SubstanceColorScheme fillColorScheme = SubstanceColorSchemeUtilities
172
.getColorScheme(this.menuItem,
173
ColorSchemeAssociationKind.FILL, activeState);
174
SubstanceColorScheme markColorScheme = SubstanceColorSchemeUtilities
175
.getColorScheme(this.menuItem,
176
ColorSchemeAssociationKind.MARK, activeState);
177
SubstanceColorScheme borderColorScheme = SubstanceColorSchemeUtilities
178
.getColorScheme(this.menuItem,
179
ColorSchemeAssociationKind.BORDER, activeState);
181
HashMapKey keyLayer = SubstanceCoreUtilities.getHashKey(
182
fontSize, checkMarkSize, fillPainter.getDisplayName(),
183
borderPainter.getDisplayName(), fillColorScheme
184
.getDisplayName(), markColorScheme
185
.getDisplayName(), borderColorScheme
186
.getDisplayName(), visibility);
187
Icon iconLayer = iconMap.get(keyLayer);
188
if (iconLayer == null) {
189
iconLayer = new ImageIcon(SubstanceImageCreator
190
.getRadioButton(this.menuItem, fillPainter,
191
borderPainter, checkMarkSize, currState, 0,
192
fillColorScheme, markColorScheme,
193
borderColorScheme, visibility));
194
iconMap.put(keyLayer, iconLayer);
197
iconLayer.paintIcon(this.menuItem, g2d, 0, 0);
202
return new ImageIcon(result);
208
* @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics,
212
public void paintIcon(Component c, Graphics g, int x, int y) {
213
Icon iconToDraw = this.getIconToPaint();
214
if (iconToDraw != null)
215
iconToDraw.paintIcon(c, g, x, y);
221
* @see javax.swing.Icon#getIconWidth()
224
public int getIconWidth() {
225
return this.size + 2;
231
* @see javax.swing.Icon#getIconHeight()
234
public int getIconHeight() {
235
return this.size + 2;