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.ui;
33
import java.awt.event.MouseEvent;
34
import java.beans.PropertyChangeEvent;
35
import java.beans.PropertyChangeListener;
38
import javax.swing.plaf.ComponentUI;
39
import javax.swing.plaf.UIResource;
40
import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI;
42
import org.pushingpixels.substance.internal.animation.StateTransitionTracker;
43
import org.pushingpixels.substance.internal.animation.TransitionAwareUI;
44
import org.pushingpixels.substance.internal.utils.*;
45
import org.pushingpixels.substance.internal.utils.icon.RadioButtonMenuItemIcon;
46
import org.pushingpixels.substance.internal.utils.menu.MenuUtilities;
47
import org.pushingpixels.substance.internal.utils.menu.SubstanceMenu;
48
import org.pushingpixels.substance.internal.utils.menu.MenuUtilities.MenuPropertyListener;
51
* UI for radio button menu items in <b>Substance</b> look and feel.
53
* @author Kirill Grouchnikov
55
public class SubstanceRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI
56
implements SubstanceMenu, TransitionAwareUI {
60
protected RolloverMenuItemListener substanceRolloverListener;
62
protected StateTransitionTracker stateTransitionTracker;
65
* Property change listener. Listens on changes to
66
* {@link AbstractButton#MODEL_CHANGED_PROPERTY} property.
68
protected PropertyChangeListener substancePropertyListener;
71
* Listens on all changes to the underlying menu item.
73
protected MenuPropertyListener substanceMenuPropertyListener;
78
* @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
80
public static ComponentUI createUI(JComponent comp) {
81
SubstanceCoreUtilities.testComponentCreationThreadingViolation(comp);
82
JRadioButtonMenuItem item = (JRadioButtonMenuItem) comp;
83
item.setRolloverEnabled(true);
85
return new SubstanceRadioButtonMenuItemUI((JRadioButtonMenuItem) comp);
88
public SubstanceRadioButtonMenuItemUI(JRadioButtonMenuItem menuItem) {
89
this.stateTransitionTracker = new StateTransitionTracker(menuItem,
96
* @see javax.swing.plaf.basic.BasicMenuItemUI#installListeners()
99
protected void installListeners() {
100
super.installListeners();
102
// Improving performance on big menus.
103
this.substanceMenuPropertyListener = new MenuPropertyListener(
105
this.substanceMenuPropertyListener.install();
107
// fix for defect 109 - storing reference to rollover listener
108
this.substanceRolloverListener = new RolloverMenuItemListener(
109
this.menuItem, this.stateTransitionTracker);
110
this.menuItem.addMouseListener(this.substanceRolloverListener);
112
this.stateTransitionTracker.registerModelListeners();
114
this.substancePropertyListener = new PropertyChangeListener() {
116
public void propertyChange(PropertyChangeEvent evt) {
117
if (AbstractButton.MODEL_CHANGED_PROPERTY.equals(evt
118
.getPropertyName())) {
119
stateTransitionTracker.setModel((ButtonModel) evt
122
if ("font".equals(evt.getPropertyName())) {
123
SwingUtilities.invokeLater(new Runnable() {
126
if (menuItem != null) {
134
this.menuItem.addPropertyChangeListener(this.substancePropertyListener);
140
* @see javax.swing.plaf.basic.BasicMenuItemUI#uninstallListeners()
143
protected void uninstallListeners() {
144
super.uninstallListeners();
146
// Improving performance on big menus.
147
this.substanceMenuPropertyListener.uninstall();
148
this.substanceMenuPropertyListener = null;
150
// fix for defect 109 - unregistering rollover listener
151
this.menuItem.removeMouseListener(this.substanceRolloverListener);
152
this.substanceRolloverListener = null;
155
.removePropertyChangeListener(this.substancePropertyListener);
156
this.substancePropertyListener = null;
158
this.stateTransitionTracker.unregisterModelListeners();
164
* @see javax.swing.plaf.basic.BasicMenuItemUI#installDefaults()
167
protected void installDefaults() {
168
super.installDefaults();
169
if (this.checkIcon == null || this.checkIcon instanceof UIResource) {
170
this.checkIcon = new RadioButtonMenuItemIcon(this.menuItem,
171
SubstanceSizeUtils.getMenuCheckMarkSize(SubstanceSizeUtils
172
.getComponentFontSize(this.menuItem)));
174
this.defaultTextIconGap = SubstanceSizeUtils
175
.getTextIconGap(SubstanceSizeUtils
176
.getComponentFontSize(this.menuItem));
182
* @see org.pushingpixels.substance.SubstanceMenu#getAssociatedMenuItem()
185
public JMenuItem getAssociatedMenuItem() {
186
return this.menuItem;
192
* @see org.pushingpixels.substance.SubstanceMenu#getAcceleratorFont()
195
public Font getAcceleratorFont() {
196
return this.acceleratorFont;
202
* @see org.pushingpixels.substance.SubstanceMenu#getArrowIcon()
205
public Icon getArrowIcon() {
206
return this.arrowIcon;
212
* @see org.pushingpixels.substance.SubstanceMenu#getCheckIcon()
215
public Icon getCheckIcon() {
216
return this.checkIcon;
222
* @see org.pushingpixels.substance.SubstanceMenu#getDefaultTextIconGap()
225
public int getDefaultTextIconGap() {
226
return this.defaultTextIconGap;
233
* javax.swing.plaf.basic.BasicMenuItemUI#getPreferredMenuItemSize(javax
234
* .swing.JComponent, javax.swing.Icon, javax.swing.Icon, int)
237
protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
238
Icon arrowIcon, int defaultTextIconGap) {
239
Dimension superDim = super.getPreferredMenuItemSize(c, checkIcon,
240
arrowIcon, defaultTextIconGap);
242
return new Dimension(MenuUtilities.getPreferredWidth(menuItem),
247
public boolean isInside(MouseEvent me) {
248
return this.menuItem.getBounds().contains(me.getX(), me.getY());
252
public StateTransitionTracker getTransitionTracker() {
253
return this.stateTransitionTracker;
260
* javax.swing.plaf.basic.BasicMenuItemUI#paintMenuItem(java.awt.Graphics,
261
* javax.swing.JComponent, javax.swing.Icon, javax.swing.Icon,
262
* java.awt.Color, java.awt.Color, int)
265
protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
266
Icon arrowIcon, Color background, Color foreground,
267
int defaultTextIconGap) {
268
MenuUtilities.paintMenuItem(g, menuItem, checkIcon, arrowIcon,