/*
 * Copyright 1997-2006 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 javax.swing.plaf.basic;

import sun.swing.DefaultLookup;
import sun.swing.UIAction;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.border.*;
import java.util.Arrays;
import java.util.ArrayList;


/**
 * A default L&F implementation of MenuUI.  This implementation
 * is a "combined" view/controller.
 *
 * @author Georges Saab
 * @author David Karlton
 * @author Arnaud Weber
 */
public class BasicMenuUI extends BasicMenuItemUI
{
    protected ChangeListener         changeListener;
    protected MenuListener           menuListener;

    private int lastMnemonic = 0;

    /** Uses as the parent of the windowInputMap when selected. */
    private InputMap selectedWindowInputMap;

    /* diagnostic aids -- should be false for production builds. */
    private static final boolean TRACE =   false; // trace creates and disposes
    private static final boolean VERBOSE = false; // show reuse hits/misses
    private static final boolean DEBUG =   false;  // show bad params, misc.

    private static boolean crossMenuMnemonic = true;

    public static ComponentUI createUI(JComponent x) {
        return new BasicMenuUI();
    }

    static void loadActionMap(LazyActionMap map) {
        BasicMenuItemUI.loadActionMap(map);
        map.put(new Actions(Actions.SELECT, null, true));
    }


    protected void installDefaults() {
        super.installDefaults();
        updateDefaultBackgroundColor();
        ((JMenu)menuItem).setDelay(200);
        crossMenuMnemonic = UIManager.getBoolean("Menu.crossMenuMnemonic");
    }

    protected String getPropertyPrefix() {
        return "Menu";
    }

    protected void installListeners() {
        super.installListeners();

        if (changeListener == null)
            changeListener = createChangeListener(menuItem);

        if (changeListener != null)
            menuItem.addChangeListener(changeListener);

        if (menuListener == null)
            menuListener = createMenuListener(menuItem);

        if (menuListener != null)
            ((JMenu)menuItem).addMenuListener(menuListener);
    }

    protected void installKeyboardActions() {
        super.installKeyboardActions();
        updateMnemonicBinding();
    }

    void installLazyActionMap() {
        LazyActionMap.installLazyActionMap(menuItem, BasicMenuUI.class,
                                           getPropertyPrefix() + ".actionMap");
    }

    void updateMnemonicBinding() {
        int mnemonic = menuItem.getModel().getMnemonic();
        int[] shortcutKeys = (int[])DefaultLookup.get(menuItem, this,
                                                   "Menu.shortcutKeys");
        if (shortcutKeys == null) {
            shortcutKeys = new int[] {KeyEvent.ALT_MASK};
        }
        if (mnemonic == lastMnemonic) {
            return;
        }
        InputMap windowInputMap = SwingUtilities.getUIInputMap(
                       menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
        if (lastMnemonic != 0 && windowInputMap != null) {
            for (int i=0; i<shortcutKeys.length; i++) {
                windowInputMap.remove(KeyStroke.getKeyStroke
                                      (lastMnemonic, shortcutKeys[i], false));
            }
        }
        if (mnemonic != 0) {
            if (windowInputMap == null) {
                windowInputMap = createInputMap(JComponent.
                                              WHEN_IN_FOCUSED_WINDOW);
                SwingUtilities.replaceUIInputMap(menuItem, JComponent.
                                       WHEN_IN_FOCUSED_WINDOW, windowInputMap);
            }
            for (int i=0; i<shortcutKeys.length; i++) {
                windowInputMap.put(KeyStroke.getKeyStroke(mnemonic,
                                         shortcutKeys[i], false),
                                   "selectMenu");
            }
        }
        lastMnemonic = mnemonic;
    }

    protected void uninstallKeyboardActions() {
        super.uninstallKeyboardActions();
        lastMnemonic = 0;
    }

    protected MouseInputListener createMouseInputListener(JComponent c) {
        return getHandler();
    }

    protected MenuListener createMenuListener(JComponent c) {
        return null;
    }

    protected ChangeListener createChangeListener(JComponent c) {
        return null;
    }

    protected PropertyChangeListener createPropertyChangeListener(JComponent c) {
        return getHandler();
    }

    BasicMenuItemUI.Handler getHandler() {
        if (handler == null) {
            handler = new Handler();
        }
        return handler;
    }

    protected void uninstallDefaults() {
        menuItem.setArmed(false);
        menuItem.setSelected(false);
        menuItem.resetKeyboardActions();
        super.uninstallDefaults();
    }

    protected void uninstallListeners() {
        super.uninstallListeners();

        if (changeListener != null)
            menuItem.removeChangeListener(changeListener);

        if (menuListener != null)
            ((JMenu)menuItem).removeMenuListener(menuListener);

        changeListener = null;
        menuListener = null;
        handler = null;
    }

    protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) {
        return getHandler();
    }

    protected MenuKeyListener createMenuKeyListener(JComponent c) {
        return (MenuKeyListener)getHandler();
    }

    public Dimension getMaximumSize(JComponent c) {
        if (((JMenu)menuItem).isTopLevelMenu() == true) {
            Dimension d = c.getPreferredSize();
            return new Dimension(d.width, Short.MAX_VALUE);
        }
        return null;
    }

    protected void setupPostTimer(JMenu menu) {
        Timer timer = new Timer(menu.getDelay(), new Actions(
                                    Actions.SELECT, menu,false));
        timer.setRepeats(false);
        timer.start();
    }

    private static void appendPath(MenuElement[] path, MenuElement elem) {
        MenuElement newPath[] = new MenuElement[path.length+1];
        System.arraycopy(path, 0, newPath, 0, path.length);
        newPath[path.length] = elem;
        MenuSelectionManager.defaultManager().setSelectedPath(newPath);
    }

    private static class Actions extends UIAction {
        private static final String SELECT = "selectMenu";

        // NOTE: This will be null if the action is registered in the
        // ActionMap. For the timer use it will be non-null.
        private JMenu menu;
        private boolean force=false;

        Actions(String key, JMenu menu, boolean shouldForce) {
            super(key);
            this.menu = menu;
            this.force = shouldForce;
        }

        private JMenu getMenu(ActionEvent e) {
            if (e.getSource() instanceof JMenu) {
                return (JMenu)e.getSource();
            }
            return menu;
        }

        public void actionPerformed(ActionEvent e) {
            JMenu menu = getMenu(e);
            if (!crossMenuMnemonic) {
                JPopupMenu pm = BasicPopupMenuUI.getLastPopup();
                if (pm != null && pm != menu.getParent()) {
                    return;
                }
            }

            final MenuSelectionManager defaultManager = MenuSelectionManager.defaultManager();
            if(force) {
                Container cnt = menu.getParent();
                if(cnt != null && cnt instanceof JMenuBar) {
                    MenuElement me[];
                    MenuElement subElements[];

                    subElements = menu.getPopupMenu().getSubElements();
                    if(subElements.length > 0) {
                        me = new MenuElement[4];
                        me[0] = (MenuElement) cnt;
                        me[1] = (MenuElement) menu;
                        me[2] = (MenuElement) menu.getPopupMenu();
                        me[3] = subElements[0];
                    } else {
                        me = new MenuElement[3];
                        me[0] = (MenuElement)cnt;
                        me[1] = menu;
                        me[2] = (MenuElement) menu.getPopupMenu();
                    }
                    defaultManager.setSelectedPath(me);
                }
            } else {
                MenuElement path[] = defaultManager.getSelectedPath();
                if(path.length > 0 && path[path.length-1] == menu) {
                    appendPath(path, menu.getPopupMenu());
                }
            }
        }

        public boolean isEnabled(Object c) {
            if (c instanceof JMenu) {
                return ((JMenu)c).isEnabled();
            }
            return true;
        }
    }

    /*
     * Set the background color depending on whether this is a toplevel menu
     * in a menubar or a submenu of another menu.
     */
    private void updateDefaultBackgroundColor() {
        if (!UIManager.getBoolean("Menu.useMenuBarBackgroundForTopLevel")) {
           return;
        }
        JMenu menu = (JMenu)menuItem;
        if (menu.getBackground() instanceof UIResource) {
            if (menu.isTopLevelMenu()) {
                menu.setBackground(UIManager.getColor("MenuBar.background"));
            } else {
                menu.setBackground(UIManager.getColor(getPropertyPrefix() + ".background"));
            }
        }
    }

    /**
     * Instantiated and used by a menu item to handle the current menu selection
     * from mouse events. A MouseInputHandler processes and forwards all mouse events
     * to a shared instance of the MenuSelectionManager.
     * <p>
     * This class is protected so that it can be subclassed by other look and
     * feels to implement their own mouse handling behavior. All overridden
     * methods should call the parent methods so that the menu selection
     * is correct.
     *
     * @see javax.swing.MenuSelectionManager
     * @since 1.4
     */
    protected class MouseInputHandler implements MouseInputListener {
        // NOTE: This class exists only for backward compatability. All
        // its functionality has been moved into Handler. If you need to add
        // new functionality add it to the Handler, but make sure this
        // class calls into the Handler.

        public void mouseClicked(MouseEvent e) {
            getHandler().mouseClicked(e);
        }

        /**
         * Invoked when the mouse has been clicked on the menu. This
         * method clears or sets the selection path of the
         * MenuSelectionManager.
         *
         * @param e the mouse event
         */
        public void mousePressed(MouseEvent e) {
            getHandler().mousePressed(e);
        }

        /**
         * Invoked when the mouse has been released on the menu. Delegates the
         * mouse event to the MenuSelectionManager.
         *
         * @param e the mouse event
         */
        public void mouseReleased(MouseEvent e) {
            getHandler().mouseReleased(e);
        }

        /**
         * Invoked when the cursor enters the menu. This method sets the selected
         * path for the MenuSelectionManager and handles the case
         * in which a menu item is used to pop up an additional menu, as in a
         * hierarchical menu system.
         *
         * @param e the mouse event; not used
         */
        public void mouseEntered(MouseEvent e) {
            getHandler().mouseEntered(e);
        }
        public void mouseExited(MouseEvent e) {
            getHandler().mouseExited(e);
        }

        /**
         * Invoked when a mouse button is pressed on the menu and then dragged.
         * Delegates the mouse event to the MenuSelectionManager.
         *
         * @param e the mouse event
         * @see java.awt.event.MouseMotionListener#mouseDragged
         */
        public void mouseDragged(MouseEvent e) {
            getHandler().mouseDragged(e);
        }

        public void mouseMoved(MouseEvent e) {
            getHandler().mouseMoved(e);
        }
    }

    /**
     * As of Java 2 platform 1.4, this previously undocumented class
     * is now obsolete. KeyBindings are now managed by the popup menu.
     */
    public class ChangeHandler implements ChangeListener {
        public JMenu    menu;
        public BasicMenuUI ui;
        public boolean  isSelected = false;
        public Component wasFocused;

        public ChangeHandler(JMenu m, BasicMenuUI ui) {
            menu = m;
            this.ui = ui;
        }

        public void stateChanged(ChangeEvent e) { }
    }

    private class Handler extends BasicMenuItemUI.Handler implements
            MenuKeyListener {
        //
        // PropertyChangeListener
        //
        public void propertyChange(PropertyChangeEvent e) {
            if (e.getPropertyName() == AbstractButton.
                             MNEMONIC_CHANGED_PROPERTY) {
                updateMnemonicBinding();
            }
            else {
                if (e.getPropertyName().equals("ancestor")) {
                    updateDefaultBackgroundColor();
                }
                super.propertyChange(e);
            }
        }

        //
        // MouseInputListener
        //
        public void mouseClicked(MouseEvent e) {
        }

        /**
         * Invoked when the mouse has been clicked on the menu. This
         * method clears or sets the selection path of the
         * MenuSelectionManager.
         *
         * @param e the mouse event
         */
        public void mousePressed(MouseEvent e) {
            JMenu menu = (JMenu)menuItem;
            if (!menu.isEnabled())
                return;

            MenuSelectionManager manager =
                MenuSelectionManager.defaultManager();
            if(menu.isTopLevelMenu()) {
                if(menu.isSelected() && menu.getPopupMenu().isShowing()) {
                    manager.clearSelectedPath();
                } else {
                    Container cnt = menu.getParent();
                    if(cnt != null && cnt instanceof JMenuBar) {
                        MenuElement me[] = new MenuElement[2];
                        me[0]=(MenuElement)cnt;
                        me[1]=menu;
                        manager.setSelectedPath(me);
                    }
                }
            }

            MenuElement selectedPath[] = manager.getSelectedPath();
            if (selectedPath.length > 0 &&
                selectedPath[selectedPath.length-1] != menu.getPopupMenu()) {

                if(menu.isTopLevelMenu() ||
                   menu.getDelay() == 0) {
                    appendPath(selectedPath, menu.getPopupMenu());
                } else {
                    setupPostTimer(menu);
                }
            }
        }

        /**
         * Invoked when the mouse has been released on the menu. Delegates the
         * mouse event to the MenuSelectionManager.
         *
         * @param e the mouse event
         */
        public void mouseReleased(MouseEvent e) {
            JMenu menu = (JMenu)menuItem;
            if (!menu.isEnabled())
                return;
            MenuSelectionManager manager =
                MenuSelectionManager.defaultManager();
            manager.processMouseEvent(e);
            if (!e.isConsumed())
                manager.clearSelectedPath();
        }

        /**
         * Invoked when the cursor enters the menu. This method sets the selected
         * path for the MenuSelectionManager and handles the case
         * in which a menu item is used to pop up an additional menu, as in a
         * hierarchical menu system.
         *
         * @param e the mouse event; not used
         */
        public void mouseEntered(MouseEvent e) {
            JMenu menu = (JMenu)menuItem;
            // only disable the menu highlighting if it's disabled and the property isn't
            // true. This allows disabled rollovers to work in WinL&F
            if (!menu.isEnabled() && !UIManager.getBoolean("MenuItem.disabledAreNavigable")) {
                return;
            }

            MenuSelectionManager manager =
                MenuSelectionManager.defaultManager();
            MenuElement selectedPath[] = manager.getSelectedPath();
            if (!menu.isTopLevelMenu()) {
                if(!(selectedPath.length > 0 &&
                     selectedPath[selectedPath.length-1] ==
                     menu.getPopupMenu())) {
                    if(menu.getDelay() == 0) {
                        appendPath(getPath(), menu.getPopupMenu());
                    } else {
                        manager.setSelectedPath(getPath());
                        setupPostTimer(menu);
                    }
                }
            } else {
                if(selectedPath.length > 0 &&
                   selectedPath[0] == menu.getParent()) {
                    MenuElement newPath[] = new MenuElement[3];
                    // A top level menu's parent is by definition
                    // a JMenuBar
                    newPath[0] = (MenuElement)menu.getParent();
                    newPath[1] = menu;
                    if (BasicPopupMenuUI.getLastPopup() != null) {
                        newPath[2] = menu.getPopupMenu();
                    }
                    manager.setSelectedPath(newPath);
                }
            }
        }
        public void mouseExited(MouseEvent e) {
        }

        /**
         * Invoked when a mouse button is pressed on the menu and then dragged.
         * Delegates the mouse event to the MenuSelectionManager.
         *
         * @param e the mouse event
         * @see java.awt.event.MouseMotionListener#mouseDragged
         */
        public void mouseDragged(MouseEvent e) {
            JMenu menu = (JMenu)menuItem;
            if (!menu.isEnabled())
                return;
            MenuSelectionManager.defaultManager().processMouseEvent(e);
        }
        public void mouseMoved(MouseEvent e) {
        }


        //
        // MenuDragHandler
        //
        public void menuDragMouseEntered(MenuDragMouseEvent e) {}
        public void menuDragMouseDragged(MenuDragMouseEvent e) {
            if (menuItem.isEnabled() == false)
                return;

            MenuSelectionManager manager = e.getMenuSelectionManager();
            MenuElement path[] = e.getPath();

            Point p = e.getPoint();
            if(p.x >= 0 && p.x < menuItem.getWidth() &&
               p.y >= 0 && p.y < menuItem.getHeight()) {
                JMenu menu = (JMenu)menuItem;
                MenuElement selectedPath[] = manager.getSelectedPath();
                if(!(selectedPath.length > 0 &&
                     selectedPath[selectedPath.length-1] ==
                     menu.getPopupMenu())) {
                    if(menu.isTopLevelMenu() ||
                       menu.getDelay() == 0  ||
                       e.getID() == MouseEvent.MOUSE_DRAGGED) {
                        appendPath(path, menu.getPopupMenu());
                    } else {
                        manager.setSelectedPath(path);
                        setupPostTimer(menu);
                    }
                }
            } else if(e.getID() == MouseEvent.MOUSE_RELEASED) {
                Component comp = manager.componentForPoint(e.getComponent(), e.getPoint());
                if (comp == null)
                    manager.clearSelectedPath();
            }

        }
        public void menuDragMouseExited(MenuDragMouseEvent e) {}
        public void menuDragMouseReleased(MenuDragMouseEvent e) {}


        //
        // MenuKeyListener
        //
        /**
         * Open the Menu
         */
        public void menuKeyTyped(MenuKeyEvent e) {
            if (!crossMenuMnemonic && BasicPopupMenuUI.getLastPopup() != null) {
                // when crossMenuMnemonic is not set, we don't open a toplevel
                // menu if another toplevel menu is already open
                    return;
                }

            char key = Character.toLowerCase((char)menuItem.getMnemonic());
            MenuElement path[] = e.getPath();
            MenuSelectionManager manager = e.getMenuSelectionManager();
            if (key == Character.toLowerCase(e.getKeyChar())) {
                JPopupMenu popupMenu = ((JMenu)menuItem).getPopupMenu();
                ArrayList newList = new ArrayList(Arrays.asList(path));
                newList.add(popupMenu);
                MenuElement subs[] = popupMenu.getSubElements();
                MenuElement sub =
                        BasicPopupMenuUI.findEnabledChild(subs, -1, true);
                if(sub != null) {
                    newList.add(sub);
                }
                MenuElement newPath[] = new MenuElement[0];;
                newPath = (MenuElement[]) newList.toArray(newPath);
                manager.setSelectedPath(newPath);
                e.consume();
            } else if (((JMenu)menuItem).isTopLevelMenu()
                    && BasicPopupMenuUI.getLastPopup() == null) {
                manager.clearSelectedPath();
            }
        }

        public void menuKeyPressed(MenuKeyEvent e) {}
        public void menuKeyReleased(MenuKeyEvent e) {}
    }
}
