/*
 * Copyright 1997-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.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;
    }
}
