/plugins/Substance/trunk/substance-6.1/substance/src/org/pushingpixels/substance/internal/utils/icon/RadioButtonMenuItemIcon.java

# · Java · 234 lines · 136 code · 22 blank · 76 comment · 15 complexity · 144005bc8ec1b127f81d624c3f33c22f MD5 · raw file

  1. /*
  2. * Copyright (c) 2005-2010 Substance Kirill Grouchnikov. All Rights Reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. *
  7. * o Redistributions of source code must retain the above copyright notice,
  8. * this list of conditions and the following disclaimer.
  9. *
  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.
  13. *
  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.
  17. *
  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.
  29. */
  30. package org.pushingpixels.substance.internal.utils.icon;
  31. import java.awt.AlphaComposite;
  32. import java.awt.Component;
  33. import java.awt.Graphics;
  34. import java.awt.Graphics2D;
  35. import java.awt.image.BufferedImage;
  36. import java.util.Map;
  37. import javax.swing.Icon;
  38. import javax.swing.ImageIcon;
  39. import javax.swing.JMenuItem;
  40. import javax.swing.JRadioButtonMenuItem;
  41. import javax.swing.plaf.UIResource;
  42. import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
  43. import org.pushingpixels.substance.api.ComponentState;
  44. import org.pushingpixels.substance.api.ComponentStateFacet;
  45. import org.pushingpixels.substance.api.SubstanceColorScheme;
  46. import org.pushingpixels.substance.api.painter.border.SubstanceBorderPainter;
  47. import org.pushingpixels.substance.api.painter.fill.SubstanceFillPainter;
  48. import org.pushingpixels.substance.internal.animation.StateTransitionTracker;
  49. import org.pushingpixels.substance.internal.animation.TransitionAwareUI;
  50. import org.pushingpixels.substance.internal.utils.HashMapKey;
  51. import org.pushingpixels.substance.internal.utils.LazyResettableHashMap;
  52. import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities;
  53. import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
  54. import org.pushingpixels.substance.internal.utils.SubstanceImageCreator;
  55. import org.pushingpixels.substance.internal.utils.SubstanceSizeUtils;
  56. /**
  57. * Icon for the {@link JRadioButtonMenuItem}s.
  58. *
  59. * @author Kirill Grouchnikov
  60. */
  61. public class RadioButtonMenuItemIcon implements Icon, UIResource {
  62. /**
  63. * The size of <code>this</code> icon.
  64. */
  65. private int size;
  66. /**
  67. * The associated menu item.
  68. */
  69. private JMenuItem menuItem;
  70. /**
  71. * Icon cache to speed up the painting.
  72. */
  73. private static LazyResettableHashMap<Icon> iconMap = new LazyResettableHashMap<Icon>(
  74. "RadioButtonMenuItemIcon");
  75. /**
  76. * Creates a new icon.
  77. *
  78. * @param menuItem
  79. * The corresponding menu item.
  80. * @param size
  81. * The size of <code>this</code> icon.
  82. */
  83. public RadioButtonMenuItemIcon(JMenuItem menuItem, int size) {
  84. this.menuItem = menuItem;
  85. this.size = size;
  86. }
  87. /**
  88. * Returns the current icon to paint.
  89. *
  90. * @return Icon to paint.
  91. */
  92. private Icon getIconToPaint() {
  93. if (this.menuItem == null)
  94. return null;
  95. TransitionAwareUI transitionAwareUI = (TransitionAwareUI) this.menuItem
  96. .getUI();
  97. StateTransitionTracker stateTransitionTracker = transitionAwareUI
  98. .getTransitionTracker();
  99. StateTransitionTracker.ModelStateInfo modelStateInfo = stateTransitionTracker
  100. .getModelStateInfo();
  101. Map<ComponentState, StateTransitionTracker.StateContributionInfo> activeStates = modelStateInfo
  102. .getStateContributionMap();
  103. int fontSize = SubstanceSizeUtils.getComponentFontSize(this.menuItem);
  104. int checkMarkSize = this.size;
  105. SubstanceFillPainter fillPainter = SubstanceCoreUtilities
  106. .getFillPainter(this.menuItem);
  107. SubstanceBorderPainter borderPainter = SubstanceCoreUtilities
  108. .getBorderPainter(this.menuItem);
  109. ComponentState currState = modelStateInfo.getCurrModelState();
  110. SubstanceColorScheme baseFillColorScheme = SubstanceColorSchemeUtilities
  111. .getColorScheme(this.menuItem, ColorSchemeAssociationKind.FILL,
  112. currState);
  113. SubstanceColorScheme baseMarkColorScheme = SubstanceColorSchemeUtilities
  114. .getColorScheme(this.menuItem, ColorSchemeAssociationKind.MARK,
  115. currState);
  116. SubstanceColorScheme baseBorderColorScheme = SubstanceColorSchemeUtilities
  117. .getColorScheme(this.menuItem,
  118. ColorSchemeAssociationKind.BORDER, currState);
  119. float visibility = stateTransitionTracker
  120. .getFacetStrength(ComponentStateFacet.SELECTION);
  121. HashMapKey keyBase = SubstanceCoreUtilities.getHashKey(fontSize,
  122. checkMarkSize, fillPainter.getDisplayName(), borderPainter
  123. .getDisplayName(),
  124. baseFillColorScheme.getDisplayName(), baseMarkColorScheme
  125. .getDisplayName(), baseBorderColorScheme
  126. .getDisplayName(), visibility);
  127. Icon iconBase = iconMap.get(keyBase);
  128. if (iconBase == null) {
  129. iconBase = new ImageIcon(SubstanceImageCreator.getRadioButton(
  130. this.menuItem, fillPainter, borderPainter, checkMarkSize,
  131. currState, 0, baseFillColorScheme, baseMarkColorScheme,
  132. baseBorderColorScheme, visibility));
  133. iconMap.put(keyBase, iconBase);
  134. }
  135. if (currState.isDisabled() || (activeStates.size() == 1)) {
  136. return iconBase;
  137. }
  138. BufferedImage result = SubstanceCoreUtilities.getBlankImage(iconBase
  139. .getIconWidth(), iconBase.getIconHeight());
  140. Graphics2D g2d = result.createGraphics();
  141. // draw the base layer
  142. iconBase.paintIcon(this.menuItem, g2d, 0, 0);
  143. // draw other active layers
  144. for (Map.Entry<ComponentState, StateTransitionTracker.StateContributionInfo> activeEntry : activeStates
  145. .entrySet()) {
  146. ComponentState activeState = activeEntry.getKey();
  147. // System.out.println("Painting state " + activeState + "[curr is "
  148. // + currState + "] with " + activeEntry.getValue());
  149. if (activeState == currState)
  150. continue;
  151. float stateContribution = activeEntry.getValue().getContribution();
  152. if (stateContribution > 0.0f) {
  153. g2d.setComposite(AlphaComposite.SrcOver
  154. .derive(stateContribution));
  155. SubstanceColorScheme fillColorScheme = SubstanceColorSchemeUtilities
  156. .getColorScheme(this.menuItem,
  157. ColorSchemeAssociationKind.FILL, activeState);
  158. SubstanceColorScheme markColorScheme = SubstanceColorSchemeUtilities
  159. .getColorScheme(this.menuItem,
  160. ColorSchemeAssociationKind.MARK, activeState);
  161. SubstanceColorScheme borderColorScheme = SubstanceColorSchemeUtilities
  162. .getColorScheme(this.menuItem,
  163. ColorSchemeAssociationKind.BORDER, activeState);
  164. HashMapKey keyLayer = SubstanceCoreUtilities.getHashKey(
  165. fontSize, checkMarkSize, fillPainter.getDisplayName(),
  166. borderPainter.getDisplayName(), fillColorScheme
  167. .getDisplayName(), markColorScheme
  168. .getDisplayName(), borderColorScheme
  169. .getDisplayName(), visibility);
  170. Icon iconLayer = iconMap.get(keyLayer);
  171. if (iconLayer == null) {
  172. iconLayer = new ImageIcon(SubstanceImageCreator
  173. .getRadioButton(this.menuItem, fillPainter,
  174. borderPainter, checkMarkSize, currState, 0,
  175. fillColorScheme, markColorScheme,
  176. borderColorScheme, visibility));
  177. iconMap.put(keyLayer, iconLayer);
  178. }
  179. iconLayer.paintIcon(this.menuItem, g2d, 0, 0);
  180. }
  181. }
  182. g2d.dispose();
  183. return new ImageIcon(result);
  184. }
  185. /*
  186. * (non-Javadoc)
  187. *
  188. * @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics,
  189. * int, int)
  190. */
  191. public void paintIcon(Component c, Graphics g, int x, int y) {
  192. Icon iconToDraw = this.getIconToPaint();
  193. if (iconToDraw != null)
  194. iconToDraw.paintIcon(c, g, x, y);
  195. }
  196. /*
  197. * (non-Javadoc)
  198. *
  199. * @see javax.swing.Icon#getIconWidth()
  200. */
  201. public int getIconWidth() {
  202. return this.size + 2;
  203. }
  204. /*
  205. * (non-Javadoc)
  206. *
  207. * @see javax.swing.Icon#getIconHeight()
  208. */
  209. public int getIconHeight() {
  210. return this.size + 2;
  211. }
  212. }