blob: a0bd37ffabefdc93007debe8a1f3c15aa43b243e [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.java.swing.plaf.windows;
27
28import java.awt.*;
29import java.awt.event.MouseEvent;
30
31import javax.swing.plaf.ComponentUI;
32import javax.swing.plaf.basic.BasicMenuUI;
33import javax.swing.event.MouseInputListener;
34import javax.swing.*;
35
36import com.sun.java.swing.plaf.windows.TMSchema.Part;
37import com.sun.java.swing.plaf.windows.TMSchema.State;
38
39/**
40 * Windows rendition of the component.
41 * <p>
42 * <strong>Warning:</strong>
43 * Serialized objects of this class will not be compatible with
44 * future Swing releases. The current serialization support is appropriate
45 * for short term storage or RMI between applications running the same
46 * version of Swing. A future release of Swing will provide support for
47 * long term persistence.
48 */
49public class WindowsMenuUI extends BasicMenuUI {
50 protected Integer menuBarHeight;
51 protected boolean hotTrackingOn;
52
53 final WindowsMenuItemUIAccessor accessor =
54 new WindowsMenuItemUIAccessor() {
55
56 public JMenuItem getMenuItem() {
57 return menuItem;
58 }
59
60 public State getState(JMenuItem menu) {
61 State state = menu.isEnabled() ? State.NORMAL
62 : State.DISABLED;
63 ButtonModel model = menu.getModel();
64 if (model.isArmed() || model.isSelected()) {
65 state = (menu.isEnabled()) ? State.PUSHED
66 : State.DISABLEDPUSHED;
67 } else if (model.isRollover()
68 && ((JMenu) menu).isTopLevelMenu()) {
69 /*
70 * Only paint rollover if no other menu on menubar is
71 * selected
72 */
73 State stateTmp = state;
74 state = (menu.isEnabled()) ? State.HOT
75 : State.DISABLEDHOT;
76 for (MenuElement menuElement :
77 ((JMenuBar) menu.getParent()).getSubElements()) {
78 if (((JMenuItem) menuElement).isSelected()) {
79 state = stateTmp;
80 break;
81 }
82 }
83 }
84
85 //non top level menus have HOT state instead of PUSHED
86 if (!((JMenu) menu).isTopLevelMenu()) {
87 if (state == State.PUSHED) {
88 state = State.HOT;
89 } else if (state == State.DISABLEDPUSHED) {
90 state = State.DISABLEDHOT;
91 }
92 }
93
94 /*
95 * on Vista top level menu for non active frame looks disabled
96 */
97 if (((JMenu) menu).isTopLevelMenu() && WindowsMenuItemUI.isVistaPainting()) {
98 if (! WindowsMenuBarUI.isActive(menu)) {
99 state = State.DISABLED;
100 }
101 }
102 return state;
103 }
104
105 public Part getPart(JMenuItem menuItem) {
106 return ((JMenu) menuItem).isTopLevelMenu() ? Part.MP_BARITEM
107 : Part.MP_POPUPITEM;
108 }
109 };
110 public static ComponentUI createUI(JComponent x) {
111 return new WindowsMenuUI();
112 }
113
114 protected void installDefaults() {
115 super.installDefaults();
116 if (!WindowsLookAndFeel.isClassicWindows()) {
117 menuItem.setRolloverEnabled(true);
118 }
119
120 menuBarHeight = (Integer)UIManager.getInt("MenuBar.height");
121
122 Object obj = UIManager.get("MenuBar.rolloverEnabled");
123 hotTrackingOn = (obj instanceof Boolean) ? (Boolean)obj : true;
124 }
125
126 /**
127 * Draws the background of the menu.
128 * @since 1.4
129 */
130 protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
131 if (WindowsMenuItemUI.isVistaPainting()) {
132 WindowsMenuItemUI.paintBackground(accessor, g, menuItem, bgColor);
133 return;
134 }
135
136 JMenu menu = (JMenu)menuItem;
137 ButtonModel model = menu.getModel();
138
139 // Use superclass method for the old Windows LAF,
140 // for submenus, and for XP toplevel if selected or pressed
141 if (WindowsLookAndFeel.isClassicWindows() ||
142 !menu.isTopLevelMenu() ||
143 (XPStyle.getXP() != null && (model.isArmed() || model.isSelected()))) {
144
145 super.paintBackground(g, menu, bgColor);
146 return;
147 }
148
149 Color oldColor = g.getColor();
150 int menuWidth = menu.getWidth();
151 int menuHeight = menu.getHeight();
152
153 UIDefaults table = UIManager.getLookAndFeelDefaults();
154 Color highlight = table.getColor("controlLtHighlight");
155 Color shadow = table.getColor("controlShadow");
156
157 g.setColor(menu.getBackground());
158 g.fillRect(0,0, menuWidth, menuHeight);
159
160 if (menu.isOpaque()) {
161 if (model.isArmed() || model.isSelected()) {
162 // Draw a lowered bevel border
163 g.setColor(shadow);
164 g.drawLine(0,0, menuWidth - 1,0);
165 g.drawLine(0,0, 0,menuHeight - 2);
166
167 g.setColor(highlight);
168 g.drawLine(menuWidth - 1,0, menuWidth - 1,menuHeight - 2);
169 g.drawLine(0,menuHeight - 2, menuWidth - 1,menuHeight - 2);
170 } else if (model.isRollover() && model.isEnabled()) {
171 // Only paint rollover if no other menu on menubar is selected
172 boolean otherMenuSelected = false;
173 MenuElement[] menus = ((JMenuBar)menu.getParent()).getSubElements();
174 for (int i = 0; i < menus.length; i++) {
175 if (((JMenuItem)menus[i]).isSelected()) {
176 otherMenuSelected = true;
177 break;
178 }
179 }
180 if (!otherMenuSelected) {
181 if (XPStyle.getXP() != null) {
182 g.setColor(selectionBackground); // Uses protected field.
183 g.fillRect(0, 0, menuWidth, menuHeight);
184 } else {
185 // Draw a raised bevel border
186 g.setColor(highlight);
187 g.drawLine(0,0, menuWidth - 1,0);
188 g.drawLine(0,0, 0,menuHeight - 2);
189
190 g.setColor(shadow);
191 g.drawLine(menuWidth - 1,0, menuWidth - 1,menuHeight - 2);
192 g.drawLine(0,menuHeight - 2, menuWidth - 1,menuHeight - 2);
193 }
194 }
195 }
196 }
197 g.setColor(oldColor);
198 }
199
200 /**
201 * Method which renders the text of the current menu item.
202 * <p>
203 * @param g Graphics context
204 * @param menuItem Current menu item to render
205 * @param textRect Bounding rectangle to render the text.
206 * @param text String to render
207 * @since 1.4
208 */
209 protected void paintText(Graphics g, JMenuItem menuItem,
210 Rectangle textRect, String text) {
211 if (WindowsMenuItemUI.isVistaPainting()) {
212 WindowsMenuItemUI.paintText(accessor, g, menuItem, textRect, text);
213 return;
214 }
215 JMenu menu = (JMenu)menuItem;
216 ButtonModel model = menuItem.getModel();
217 Color oldColor = g.getColor();
218
219 // Only paint rollover if no other menu on menubar is selected
220 boolean paintRollover = model.isRollover();
221 if (paintRollover && menu.isTopLevelMenu()) {
222 MenuElement[] menus = ((JMenuBar)menu.getParent()).getSubElements();
223 for (int i = 0; i < menus.length; i++) {
224 if (((JMenuItem)menus[i]).isSelected()) {
225 paintRollover = false;
226 break;
227 }
228 }
229 }
230
231 if ((model.isSelected() && (WindowsLookAndFeel.isClassicWindows() ||
232 !menu.isTopLevelMenu())) ||
233 (XPStyle.getXP() != null && (paintRollover ||
234 model.isArmed() ||
235 model.isSelected()))) {
236 g.setColor(selectionForeground); // Uses protected field.
237 }
238
239 WindowsGraphicsUtils.paintText(g, menuItem, textRect, text, 0);
240
241 g.setColor(oldColor);
242 }
243
244 protected MouseInputListener createMouseInputListener(JComponent c) {
245 return new WindowsMouseInputHandler();
246 }
247
248 /**
249 * This class implements a mouse handler that sets the rollover flag to
250 * true when the mouse enters the menu and false when it exits.
251 * @since 1.4
252 */
253 protected class WindowsMouseInputHandler extends BasicMenuUI.MouseInputHandler {
254 public void mouseEntered(MouseEvent evt) {
255 super.mouseEntered(evt);
256
257 JMenu menu = (JMenu)evt.getSource();
258 if (hotTrackingOn && menu.isTopLevelMenu() && menu.isRolloverEnabled()) {
259 menu.getModel().setRollover(true);
260 menuItem.repaint();
261 }
262 }
263
264 public void mouseExited(MouseEvent evt) {
265 super.mouseExited(evt);
266
267 JMenu menu = (JMenu)evt.getSource();
268 ButtonModel model = menu.getModel();
269 if (menu.isRolloverEnabled()) {
270 model.setRollover(false);
271 menuItem.repaint();
272 }
273 }
274 }
275
276 protected Dimension getPreferredMenuItemSize(JComponent c,
277 Icon checkIcon,
278 Icon arrowIcon,
279 int defaultTextIconGap) {
280
281 Dimension d = super.getPreferredMenuItemSize(c, checkIcon, arrowIcon,
282 defaultTextIconGap);
283
284 // Note: When toolbar containers (rebars) are implemented, only do
285 // this if the JMenuBar is not in a rebar (i.e. ignore the desktop
286 // property win.menu.height if in a rebar.)
287 if (c instanceof JMenu && ((JMenu)c).isTopLevelMenu() &&
288 menuBarHeight != null && d.height < menuBarHeight) {
289
290 d.height = menuBarHeight;
291 }
292
293 return d;
294 }
295}