/* * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.java.swing.plaf.windows; import java.awt.*; import java.awt.event.MouseEvent; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicMenuUI; import javax.swing.event.MouseInputListener; import javax.swing.*; import com.sun.java.swing.plaf.windows.TMSchema.Part; import com.sun.java.swing.plaf.windows.TMSchema.State; /** * Windows rendition of the component. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is appropriate * for short term storage or RMI between applications running the same * version of Swing. A future release of Swing will provide support for * long term persistence. */ public class WindowsMenuUI extends BasicMenuUI { protected Integer menuBarHeight; protected boolean hotTrackingOn; final WindowsMenuItemUIAccessor accessor = new WindowsMenuItemUIAccessor() { public JMenuItem getMenuItem() { return menuItem; } public State getState(JMenuItem menu) { State state = menu.isEnabled() ? State.NORMAL : State.DISABLED; ButtonModel model = menu.getModel(); if (model.isArmed() || model.isSelected()) { state = (menu.isEnabled()) ? State.PUSHED : State.DISABLEDPUSHED; } else if (model.isRollover() && ((JMenu) menu).isTopLevelMenu()) { /* * Only paint rollover if no other menu on menubar is * selected */ State stateTmp = state; state = (menu.isEnabled()) ? State.HOT : State.DISABLEDHOT; for (MenuElement menuElement : ((JMenuBar) menu.getParent()).getSubElements()) { if (((JMenuItem) menuElement).isSelected()) { state = stateTmp; break; } } } //non top level menus have HOT state instead of PUSHED if (!((JMenu) menu).isTopLevelMenu()) { if (state == State.PUSHED) { state = State.HOT; } else if (state == State.DISABLEDPUSHED) { state = State.DISABLEDHOT; } } /* * on Vista top level menu for non active frame looks disabled */ if (((JMenu) menu).isTopLevelMenu() && WindowsMenuItemUI.isVistaPainting()) { if (! WindowsMenuBarUI.isActive(menu)) { state = State.DISABLED; } } return state; } public Part getPart(JMenuItem menuItem) { return ((JMenu) menuItem).isTopLevelMenu() ? Part.MP_BARITEM : Part.MP_POPUPITEM; } }; public static ComponentUI createUI(JComponent x) { return new WindowsMenuUI(); } protected void installDefaults() { super.installDefaults(); if (!WindowsLookAndFeel.isClassicWindows()) { menuItem.setRolloverEnabled(true); } menuBarHeight = (Integer)UIManager.getInt("MenuBar.height"); Object obj = UIManager.get("MenuBar.rolloverEnabled"); hotTrackingOn = (obj instanceof Boolean) ? (Boolean)obj : true; } /** * Draws the background of the menu. * @since 1.4 */ protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { if (WindowsMenuItemUI.isVistaPainting()) { WindowsMenuItemUI.paintBackground(accessor, g, menuItem, bgColor); return; } JMenu menu = (JMenu)menuItem; ButtonModel model = menu.getModel(); // Use superclass method for the old Windows LAF, // for submenus, and for XP toplevel if selected or pressed if (WindowsLookAndFeel.isClassicWindows() || !menu.isTopLevelMenu() || (XPStyle.getXP() != null && (model.isArmed() || model.isSelected()))) { super.paintBackground(g, menu, bgColor); return; } Color oldColor = g.getColor(); int menuWidth = menu.getWidth(); int menuHeight = menu.getHeight(); UIDefaults table = UIManager.getLookAndFeelDefaults(); Color highlight = table.getColor("controlLtHighlight"); Color shadow = table.getColor("controlShadow"); g.setColor(menu.getBackground()); g.fillRect(0,0, menuWidth, menuHeight); if (menu.isOpaque()) { if (model.isArmed() || model.isSelected()) { // Draw a lowered bevel border g.setColor(shadow); g.drawLine(0,0, menuWidth - 1,0); g.drawLine(0,0, 0,menuHeight - 2); g.setColor(highlight); g.drawLine(menuWidth - 1,0, menuWidth - 1,menuHeight - 2); g.drawLine(0,menuHeight - 2, menuWidth - 1,menuHeight - 2); } else if (model.isRollover() && model.isEnabled()) { // Only paint rollover if no other menu on menubar is selected boolean otherMenuSelected = false; MenuElement[] menus = ((JMenuBar)menu.getParent()).getSubElements(); for (int i = 0; i < menus.length; i++) { if (((JMenuItem)menus[i]).isSelected()) { otherMenuSelected = true; break; } } if (!otherMenuSelected) { if (XPStyle.getXP() != null) { g.setColor(selectionBackground); // Uses protected field. g.fillRect(0, 0, menuWidth, menuHeight); } else { // Draw a raised bevel border g.setColor(highlight); g.drawLine(0,0, menuWidth - 1,0); g.drawLine(0,0, 0,menuHeight - 2); g.setColor(shadow); g.drawLine(menuWidth - 1,0, menuWidth - 1,menuHeight - 2); g.drawLine(0,menuHeight - 2, menuWidth - 1,menuHeight - 2); } } } } g.setColor(oldColor); } /** * Method which renders the text of the current menu item. * <p> * @param g Graphics context * @param menuItem Current menu item to render * @param textRect Bounding rectangle to render the text. * @param text String to render * @since 1.4 */ protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { if (WindowsMenuItemUI.isVistaPainting()) { WindowsMenuItemUI.paintText(accessor, g, menuItem, textRect, text); return; } JMenu menu = (JMenu)menuItem; ButtonModel model = menuItem.getModel(); Color oldColor = g.getColor(); // Only paint rollover if no other menu on menubar is selected boolean paintRollover = model.isRollover(); if (paintRollover && menu.isTopLevelMenu()) { MenuElement[] menus = ((JMenuBar)menu.getParent()).getSubElements(); for (int i = 0; i < menus.length; i++) { if (((JMenuItem)menus[i]).isSelected()) { paintRollover = false; break; } } } if ((model.isSelected() && (WindowsLookAndFeel.isClassicWindows() || !menu.isTopLevelMenu())) || (XPStyle.getXP() != null && (paintRollover || model.isArmed() || model.isSelected()))) { g.setColor(selectionForeground); // Uses protected field. } WindowsGraphicsUtils.paintText(g, menuItem, textRect, text, 0); g.setColor(oldColor); } protected MouseInputListener createMouseInputListener(JComponent c) { return new WindowsMouseInputHandler(); } /** * This class implements a mouse handler that sets the rollover flag to * true when the mouse enters the menu and false when it exits. * @since 1.4 */ protected class WindowsMouseInputHandler extends BasicMenuUI.MouseInputHandler { public void mouseEntered(MouseEvent evt) { super.mouseEntered(evt); JMenu menu = (JMenu)evt.getSource(); if (hotTrackingOn && menu.isTopLevelMenu() && menu.isRolloverEnabled()) { menu.getModel().setRollover(true); menuItem.repaint(); } } public void mouseExited(MouseEvent evt) { super.mouseExited(evt); JMenu menu = (JMenu)evt.getSource(); ButtonModel model = menu.getModel(); if (menu.isRolloverEnabled()) { model.setRollover(false); menuItem.repaint(); } } } protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap) { Dimension d = super.getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap); // Note: When toolbar containers (rebars) are implemented, only do // this if the JMenuBar is not in a rebar (i.e. ignore the desktop // property win.menu.height if in a rebar.) if (c instanceof JMenu && ((JMenu)c).isTopLevelMenu() && menuBarHeight != null && d.height < menuBarHeight) { d.height = menuBarHeight; } return d; } }