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: import java.awt.event.MouseEvent;
034: import java.beans.PropertyChangeEvent;
035: import java.beans.PropertyChangeListener;
036:
037: import javax.swing.*;
038: import javax.swing.plaf.ComponentUI;
039: import javax.swing.plaf.UIResource;
040: import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI;
041:
042: import org.jvnet.lafwidget.animation.FadeStateListener;
043: import org.jvnet.substance.utils.*;
044: import org.jvnet.substance.utils.icon.RadioButtonMenuItemIcon;
045: import org.jvnet.substance.utils.menu.MenuUtilities;
046: import org.jvnet.substance.utils.menu.MenuUtilities.MenuPropertyListener;
047:
048: /**
049: * UI for radio button menu items in <b>Substance</b> look and feel.
050: *
051: * @author Kirill Grouchnikov
052: */
053: public class SubstanceRadioButtonMenuItemUI extends
054: BasicRadioButtonMenuItemUI implements SubstanceMenu, Trackable {
055: /**
056: * Rollover listener.
057: */
058: protected RolloverMenuItemListener substanceRolloverListener;
059:
060: /**
061: * Listener for fade animations.
062: */
063: protected FadeStateListener substanceFadeStateListener;
064:
065: /**
066: * Property change listener. Listens on changes to
067: * {@link AbstractButton#MODEL_CHANGED_PROPERTY} property.
068: */
069: protected PropertyChangeListener substancePropertyListener;
070:
071: /**
072: * Listens on all changes to the underlying menu item.
073: */
074: protected MenuPropertyListener substanceMenuPropertyListener;
075:
076: /*
077: * (non-Javadoc)
078: *
079: * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
080: */
081: public static ComponentUI createUI(JComponent b) {
082: JRadioButtonMenuItem item = (JRadioButtonMenuItem) b;
083: item.setRolloverEnabled(true);
084:
085: return new SubstanceRadioButtonMenuItemUI();
086: }
087:
088: /*
089: * (non-Javadoc)
090: *
091: * @see javax.swing.plaf.basic.BasicMenuItemUI#installListeners()
092: */
093: @Override
094: protected void installListeners() {
095: super .installListeners();
096:
097: // Improving performance on big menus.
098: this .substanceMenuPropertyListener = new MenuPropertyListener(
099: this .menuItem);
100: this .substanceMenuPropertyListener.install();
101:
102: // fix for defect 109 - storing reference to rollover listener
103: this .substanceRolloverListener = new RolloverMenuItemListener(
104: this .menuItem);
105: this .menuItem.addMouseListener(this .substanceRolloverListener);
106:
107: this .substanceFadeStateListener = new FadeStateListener(
108: this .menuItem, this .menuItem.getModel(),
109: SubstanceCoreUtilities.getFadeCallback(this .menuItem,
110: this .menuItem.getModel(), true, false,
111: this .menuItem));
112: this .substanceFadeStateListener.registerListeners();
113:
114: this .substancePropertyListener = new PropertyChangeListener() {
115: public void propertyChange(PropertyChangeEvent evt) {
116: if (AbstractButton.MODEL_CHANGED_PROPERTY.equals(evt
117: .getPropertyName())) {
118: if (substanceFadeStateListener != null)
119: substanceFadeStateListener
120: .unregisterListeners();
121: substanceFadeStateListener = new FadeStateListener(
122: menuItem, menuItem.getModel(),
123: SubstanceCoreUtilities.getFadeCallback(
124: menuItem, menuItem.getModel(),
125: true, false, menuItem));
126: substanceFadeStateListener.registerListeners();
127: }
128: if ("font".equals(evt.getPropertyName())) {
129: SwingUtilities.invokeLater(new Runnable() {
130: public void run() {
131: menuItem.updateUI();
132: }
133: });
134: }
135: }
136: };
137: this .menuItem
138: .addPropertyChangeListener(this .substancePropertyListener);
139: }
140:
141: /*
142: * (non-Javadoc)
143: *
144: * @see javax.swing.plaf.basic.BasicMenuItemUI#uninstallListeners()
145: */
146: @Override
147: protected void uninstallListeners() {
148: super .uninstallListeners();
149:
150: // Improving performance on big menus.
151: this .substanceMenuPropertyListener.uninstall();
152: this .substanceMenuPropertyListener = null;
153:
154: // fix for defect 109 - unregistering rollover listener
155: this .menuItem
156: .removeMouseListener(this .substanceRolloverListener);
157: this .substanceRolloverListener = null;
158:
159: this .menuItem
160: .removePropertyChangeListener(this .substancePropertyListener);
161: this .substancePropertyListener = null;
162:
163: this .substanceFadeStateListener.unregisterListeners();
164: this .substanceFadeStateListener = null;
165: }
166:
167: /*
168: * (non-Javadoc)
169: *
170: * @see javax.swing.plaf.basic.BasicMenuItemUI#installDefaults()
171: */
172: @Override
173: protected void installDefaults() {
174: super .installDefaults();
175: if (this .checkIcon == null
176: || this .checkIcon instanceof UIResource) {
177: this .checkIcon = new RadioButtonMenuItemIcon(
178: this .menuItem,
179: SubstanceSizeUtils
180: .getMenuCheckMarkSize(SubstanceSizeUtils
181: .getComponentFontSize(this .menuItem)));
182: }
183: this .defaultTextIconGap = SubstanceSizeUtils
184: .getMenuTextIconGap(SubstanceSizeUtils
185: .getComponentFontSize(this .menuItem));
186: }
187:
188: /*
189: * (non-Javadoc)
190: *
191: * @see org.jvnet.substance.SubstanceMenu#getAssociatedMenuItem()
192: */
193: public JMenuItem getAssociatedMenuItem() {
194: return this .menuItem;
195: }
196:
197: /*
198: * (non-Javadoc)
199: *
200: * @see org.jvnet.substance.SubstanceMenu#getAcceleratorFont()
201: */
202: public Font getAcceleratorFont() {
203: return this .acceleratorFont;
204: }
205:
206: /*
207: * (non-Javadoc)
208: *
209: * @see org.jvnet.substance.SubstanceMenu#getArrowIcon()
210: */
211: public Icon getArrowIcon() {
212: return this .arrowIcon;
213: }
214:
215: /*
216: * (non-Javadoc)
217: *
218: * @see org.jvnet.substance.SubstanceMenu#getCheckIcon()
219: */
220: public Icon getCheckIcon() {
221: return this .checkIcon;
222: }
223:
224: /*
225: * (non-Javadoc)
226: *
227: * @see org.jvnet.substance.SubstanceMenu#getDefaultTextIconGap()
228: */
229: public int getDefaultTextIconGap() {
230: return this .defaultTextIconGap;
231: }
232:
233: /*
234: * (non-Javadoc)
235: *
236: * @see javax.swing.plaf.basic.BasicMenuItemUI#getPreferredMenuItemSize(javax.swing.JComponent,
237: * javax.swing.Icon, javax.swing.Icon, int)
238: */
239: @Override
240: protected Dimension getPreferredMenuItemSize(JComponent c,
241: Icon checkIcon, Icon arrowIcon, int defaultTextIconGap) {
242: Dimension super Dim = super .getPreferredMenuItemSize(c,
243: checkIcon, arrowIcon, defaultTextIconGap);
244:
245: return new Dimension(MenuUtilities.getPreferredWidth(menuItem),
246: super Dim.height);
247: }
248:
249: /*
250: * (non-Javadoc)
251: *
252: * @see org.jvnet.substance.utils.Trackable#isInside(java.awt.event.MouseEvent)
253: */
254: public boolean isInside(MouseEvent me) {
255: return this .menuItem.getBounds().contains(me.getX(), me.getY());
256: }
257:
258: /*
259: * (non-Javadoc)
260: *
261: * @see javax.swing.plaf.basic.BasicMenuItemUI#paintMenuItem(java.awt.Graphics,
262: * javax.swing.JComponent, javax.swing.Icon, javax.swing.Icon,
263: * java.awt.Color, java.awt.Color, int)
264: */
265: @Override
266: protected void paintMenuItem(Graphics g, JComponent c,
267: Icon checkIcon, Icon arrowIcon, Color background,
268: Color foreground, int defaultTextIconGap) {
269: MenuUtilities.paintMenuItem(g, menuItem, checkIcon, arrowIcon,
270: defaultTextIconGap);
271: }
272: }
|