631 lines · 21.9 KB · Java
RawDownload
/* * Copyright (c) 1997, 2010, 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 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 shortcutKey : shortcutKeys) {                windowInputMap.remove(KeyStroke.getKeyStroke                        (lastMnemonic, shortcutKey, 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 shortcutKey : shortcutKeys) {                windowInputMap.put(KeyStroke.getKeyStroke(mnemonic,                        shortcutKey, 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] = menu;                        me[2] = menu.getPopupMenu();                        me[3] = subElements[0];                    } else {                        me = new MenuElement[3];                        me[0] = (MenuElement)cnt;                        me[1] = menu;                        me[2] = 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;            } 

Lines 1–500 of 631.