1223 lines · 46.2 KB · Java
RawDownload
/* * Copyright (c) 1997, 2008, 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 javax.swing.*;import javax.swing.event.*;import javax.swing.plaf.*;import javax.swing.plaf.basic.*;import javax.swing.border.*; import java.applet.Applet; import java.awt.Component;import java.awt.Container;import java.awt.Dimension;import java.awt.KeyboardFocusManager;import java.awt.Window;import java.awt.event.*;import java.awt.AWTEvent;import java.awt.Toolkit; import java.beans.PropertyChangeListener;import java.beans.PropertyChangeEvent; import java.util.*; import sun.swing.DefaultLookup;import sun.swing.UIAction; import sun.awt.AppContext; /** * A Windows L&F implementation of PopupMenuUI.  This implementation * is a "combined" view/controller. * * @author Georges Saab * @author David Karlton * @author Arnaud Weber */public class BasicPopupMenuUI extends PopupMenuUI {    static final StringBuilder MOUSE_GRABBER_KEY = new StringBuilder(                   "javax.swing.plaf.basic.BasicPopupMenuUI.MouseGrabber");    static final StringBuilder MENU_KEYBOARD_HELPER_KEY = new StringBuilder(                   "javax.swing.plaf.basic.BasicPopupMenuUI.MenuKeyboardHelper");     protected JPopupMenu popupMenu = null;    private transient PopupMenuListener popupMenuListener = null;    private MenuKeyListener menuKeyListener = null;     private static boolean checkedUnpostPopup;    private static boolean unpostPopup;     public static ComponentUI createUI(JComponent x) {        return new BasicPopupMenuUI();    }     public BasicPopupMenuUI() {        BasicLookAndFeel.needsEventHelper = true;        LookAndFeel laf = UIManager.getLookAndFeel();        if (laf instanceof BasicLookAndFeel) {            ((BasicLookAndFeel)laf).installAWTEventListener();        }    }     public void installUI(JComponent c) {        popupMenu = (JPopupMenu) c;         installDefaults();        installListeners();        installKeyboardActions();    }     public void installDefaults() {        if (popupMenu.getLayout() == null ||            popupMenu.getLayout() instanceof UIResource)            popupMenu.setLayout(new DefaultMenuLayout(popupMenu, BoxLayout.Y_AXIS));         LookAndFeel.installProperty(popupMenu, "opaque", Boolean.TRUE);        LookAndFeel.installBorder(popupMenu, "PopupMenu.border");        LookAndFeel.installColorsAndFont(popupMenu,                                         "PopupMenu.background",                                         "PopupMenu.foreground",                                         "PopupMenu.font");    }     protected void installListeners() {        if (popupMenuListener == null) {            popupMenuListener = new BasicPopupMenuListener();        }        popupMenu.addPopupMenuListener(popupMenuListener);         if (menuKeyListener == null) {            menuKeyListener = new BasicMenuKeyListener();        }        popupMenu.addMenuKeyListener(menuKeyListener);         AppContext context = AppContext.getAppContext();        synchronized (MOUSE_GRABBER_KEY) {            MouseGrabber mouseGrabber = (MouseGrabber)context.get(                                                     MOUSE_GRABBER_KEY);            if (mouseGrabber == null) {                mouseGrabber = new MouseGrabber();                context.put(MOUSE_GRABBER_KEY, mouseGrabber);            }        }        synchronized (MENU_KEYBOARD_HELPER_KEY) {            MenuKeyboardHelper helper =                    (MenuKeyboardHelper)context.get(MENU_KEYBOARD_HELPER_KEY);            if (helper == null) {                helper = new MenuKeyboardHelper();                context.put(MENU_KEYBOARD_HELPER_KEY, helper);                MenuSelectionManager msm = MenuSelectionManager.defaultManager();                msm.addChangeListener(helper);            }        }    }     protected void installKeyboardActions() {    }     static InputMap getInputMap(JPopupMenu popup, JComponent c) {        InputMap windowInputMap = null;        Object[] bindings = (Object[])UIManager.get("PopupMenu.selectedWindowInputMapBindings");        if (bindings != null) {            windowInputMap = LookAndFeel.makeComponentInputMap(c, bindings);            if (!popup.getComponentOrientation().isLeftToRight()) {                Object[] km = (Object[])UIManager.get("PopupMenu.selectedWindowInputMapBindings.RightToLeft");                if (km != null) {                    InputMap rightToLeftInputMap = LookAndFeel.makeComponentInputMap(c, km);                    rightToLeftInputMap.setParent(windowInputMap);                    windowInputMap = rightToLeftInputMap;                }            }        }        return windowInputMap;    }     static ActionMap getActionMap() {        return LazyActionMap.getActionMap(BasicPopupMenuUI.class,                                          "PopupMenu.actionMap");    }     static void loadActionMap(LazyActionMap map) {        map.put(new Actions(Actions.CANCEL));        map.put(new Actions(Actions.SELECT_NEXT));        map.put(new Actions(Actions.SELECT_PREVIOUS));        map.put(new Actions(Actions.SELECT_PARENT));        map.put(new Actions(Actions.SELECT_CHILD));        map.put(new Actions(Actions.RETURN));        BasicLookAndFeel.installAudioActionMap(map);    }     public void uninstallUI(JComponent c) {        uninstallDefaults();        uninstallListeners();        uninstallKeyboardActions();         popupMenu = null;    }     protected void uninstallDefaults() {        LookAndFeel.uninstallBorder(popupMenu);    }     protected void uninstallListeners() {        if (popupMenuListener != null) {            popupMenu.removePopupMenuListener(popupMenuListener);        }        if (menuKeyListener != null) {            popupMenu.removeMenuKeyListener(menuKeyListener);        }    }     protected void uninstallKeyboardActions() {        SwingUtilities.replaceUIActionMap(popupMenu, null);        SwingUtilities.replaceUIInputMap(popupMenu,                                  JComponent.WHEN_IN_FOCUSED_WINDOW, null);    }     static MenuElement getFirstPopup() {        MenuSelectionManager msm = MenuSelectionManager.defaultManager();        MenuElement[] p = msm.getSelectedPath();        MenuElement me = null;         for(int i = 0 ; me == null && i < p.length ; i++) {            if (p[i] instanceof JPopupMenu)                me = p[i];        }         return me;    }     static JPopupMenu getLastPopup() {        MenuSelectionManager msm = MenuSelectionManager.defaultManager();        MenuElement[] p = msm.getSelectedPath();        JPopupMenu popup = null;         for(int i = p.length - 1; popup == null && i >= 0; i--) {            if (p[i] instanceof JPopupMenu)                popup = (JPopupMenu)p[i];        }        return popup;    }     static List<JPopupMenu> getPopups() {        MenuSelectionManager msm = MenuSelectionManager.defaultManager();        MenuElement[] p = msm.getSelectedPath();         List<JPopupMenu> list = new ArrayList<JPopupMenu>(p.length);        for (MenuElement element : p) {            if (element instanceof JPopupMenu) {                list.add((JPopupMenu) element);            }        }        return list;    }     public boolean isPopupTrigger(MouseEvent e) {        return ((e.getID()==MouseEvent.MOUSE_RELEASED)                && ((e.getModifiers() & MouseEvent.BUTTON3_MASK)!=0));    }     private static boolean checkInvokerEqual(MenuElement present, MenuElement last) {        Component invokerPresent = present.getComponent();        Component invokerLast = last.getComponent();         if (invokerPresent instanceof JPopupMenu) {            invokerPresent = ((JPopupMenu)invokerPresent).getInvoker();    }        if (invokerLast instanceof JPopupMenu) {            invokerLast = ((JPopupMenu)invokerLast).getInvoker();        }        return (invokerPresent == invokerLast);    }      /**     * This Listener fires the Action that provides the correct auditory     * feedback.     *     * @since 1.4     */    private class BasicPopupMenuListener implements PopupMenuListener {        public void popupMenuCanceled(PopupMenuEvent e) {        }         public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {        }         public void popupMenuWillBecomeVisible(PopupMenuEvent e) {            BasicLookAndFeel.playSound((JPopupMenu)e.getSource(),                                       "PopupMenu.popupSound");        }    }     /**     * Handles mnemonic for children JMenuItems.     * @since 1.5     */    private class BasicMenuKeyListener implements MenuKeyListener {        MenuElement menuToOpen = null;         public void menuKeyTyped(MenuKeyEvent e) {            if (menuToOpen != null) {                // we have a submenu to open                JPopupMenu subpopup = ((JMenu)menuToOpen).getPopupMenu();                MenuElement subitem = findEnabledChild(                        subpopup.getSubElements(), -1, true);                 ArrayList<MenuElement> lst = new ArrayList<MenuElement>(Arrays.asList(e.getPath()));                lst.add(menuToOpen);                lst.add(subpopup);                if (subitem != null) {                    lst.add(subitem);                }                MenuElement newPath[] = new MenuElement[0];                newPath = lst.toArray(newPath);                MenuSelectionManager.defaultManager().setSelectedPath(newPath);                e.consume();            }            menuToOpen = null;        }         public void menuKeyPressed(MenuKeyEvent e) {            char keyChar = e.getKeyChar();             // Handle the case for Escape or Enter...            if (!Character.isLetterOrDigit(keyChar)) {                return;            }             MenuSelectionManager manager = e.getMenuSelectionManager();            MenuElement path[] = e.getPath();            MenuElement items[] = popupMenu.getSubElements();            int currentIndex = -1;            int matches = 0;            int firstMatch = -1;            int indexes[] = null;             for (int j = 0; j < items.length; j++) {                if (! (items[j] instanceof JMenuItem)) {                    continue;                }                JMenuItem item = (JMenuItem)items[j];                int mnemonic = item.getMnemonic();                if (item.isEnabled() &&                    item.isVisible() && lower(keyChar) == lower(mnemonic)) {                    if (matches == 0) {                        firstMatch = j;                        matches++;                    } else {                        if (indexes == null) {                            indexes = new int[items.length];                            indexes[0] = firstMatch;                        }                        indexes[matches++] = j;                    }                }                if (item.isArmed() || item.isSelected()) {                    currentIndex = matches - 1;                }            }             if (matches == 0) {                // no op            } else if (matches == 1) {                // Invoke the menu action                JMenuItem item = (JMenuItem)items[firstMatch];                if (item instanceof JMenu) {                    // submenus are handled in menuKeyTyped                    menuToOpen = item;                } else if (item.isEnabled()) {                    // we have a menu item                    manager.clearSelectedPath();                    item.doClick();                }                e.consume();            } else {                // Select the menu item with the matching mnemonic. If                // the same mnemonic has been invoked then select the next                // menu item in the cycle.                MenuElement newItem;                 newItem = items[indexes[(currentIndex + 1) % matches]];                 MenuElement newPath[] = new MenuElement[path.length+1];                System.arraycopy(path, 0, newPath, 0, path.length);                newPath[path.length] = newItem;                manager.setSelectedPath(newPath);                e.consume();            }        }         public void menuKeyReleased(MenuKeyEvent e) {        }         private char lower(char keyChar) {            return Character.toLowerCase(keyChar);        }         private char lower(int mnemonic) {            return Character.toLowerCase((char) mnemonic);        }    }     private static class Actions extends UIAction {        // Types of actions        private static final String CANCEL = "cancel";        private static final String SELECT_NEXT = "selectNext";        private static final String SELECT_PREVIOUS = "selectPrevious";        private static final String SELECT_PARENT = "selectParent";        private static final String SELECT_CHILD = "selectChild";        private static final String RETURN = "return";         // Used for next/previous actions        private static final boolean FORWARD = true;        private static final boolean BACKWARD = false;         // Used for parent/child actions        private static final boolean PARENT = false;        private static final boolean CHILD = true;          Actions(String key) {            super(key);        }         public void actionPerformed(ActionEvent e) {            String key = getName();            if (key == CANCEL) {                cancel();            }            else if (key == SELECT_NEXT) {                selectItem(FORWARD);            }            else if (key == SELECT_PREVIOUS) {                selectItem(BACKWARD);            }            else if (key == SELECT_PARENT) {                selectParentChild(PARENT);            }            else if (key == SELECT_CHILD) {                selectParentChild(CHILD);            }            else if (key == RETURN) {                doReturn();            }        }         private void doReturn() {            KeyboardFocusManager fmgr =                KeyboardFocusManager.getCurrentKeyboardFocusManager();            Component focusOwner = fmgr.getFocusOwner();            if(focusOwner != null && !(focusOwner instanceof JRootPane)) {                return;            }             MenuSelectionManager msm = MenuSelectionManager.defaultManager();            MenuElement path[] = msm.getSelectedPath();            MenuElement lastElement;            if(path.length > 0) {                lastElement = path[path.length-1];                if(lastElement instanceof JMenu) {                    MenuElement newPath[] = new MenuElement[path.length+1];                    System.arraycopy(path,0,newPath,0,path.length);                    newPath[path.length] = ((JMenu)lastElement).getPopupMenu();                    msm.setSelectedPath(newPath);                } else if(lastElement instanceof JMenuItem) {                    JMenuItem mi = (JMenuItem)lastElement;                     if (mi.getUI() instanceof BasicMenuItemUI) {                        ((BasicMenuItemUI)mi.getUI()).doClick(msm);                    }                    else {                        msm.clearSelectedPath();                        mi.doClick(0);                    }                }            }        }        private void selectParentChild(boolean direction) {            MenuSelectionManager msm = MenuSelectionManager.defaultManager();            MenuElement path[] = msm.getSelectedPath();            int len = path.length;             if (direction == PARENT) {                // selecting parent                int popupIndex = len-1;                 if (len > 2 &&                    // check if we have an open submenu. A submenu item may or                    // may not be selected, so submenu popup can be either the                    // last or next to the last item.                    (path[popupIndex] instanceof JPopupMenu ||                     path[--popupIndex] instanceof JPopupMenu) &&                    !((JMenu)path[popupIndex-1]).isTopLevelMenu()) {                     // we have a submenu, just close it                    MenuElement newPath[] = new MenuElement[popupIndex];                    System.arraycopy(path, 0, newPath, 0, popupIndex);                    msm.setSelectedPath(newPath);                    return;                }            } else {                // selecting child                if (len > 0 && path[len-1] instanceof JMenu &&                    !((JMenu)path[len-1]).isTopLevelMenu()) {                     // we have a submenu, open it                    JMenu menu = (JMenu)path[len-1];                    JPopupMenu popup = menu.getPopupMenu();                    MenuElement[] subs = popup.getSubElements();                    MenuElement item = findEnabledChild(subs, -1, true);                    MenuElement[] newPath;                     if (item == null) {                        newPath = new MenuElement[len+1];

Lines 1–500 of 1223.