📄 basicpopupmenuui.java
字号:
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]; } else { newPath = new MenuElement[len+2]; newPath[len+1] = item; } System.arraycopy(path, 0, newPath, 0, len); newPath[len] = popup; msm.setSelectedPath(newPath); return; } } // check if we have a toplevel menu selected. // If this is the case, we select another toplevel menu if (len > 1 && path[0] instanceof JMenuBar) { MenuElement currentMenu = path[1]; MenuElement nextMenu = findEnabledChild( path[0].getSubElements(), currentMenu, direction); if (nextMenu != null && nextMenu != currentMenu) { MenuElement newSelection[]; if (len == 2) { // menu is selected but its popup not shown newSelection = new MenuElement[2]; newSelection[0] = path[0]; newSelection[1] = nextMenu; } else { // menu is selected and its popup is shown newSelection = new MenuElement[3]; newSelection[0] = path[0]; newSelection[1] = nextMenu; newSelection[2] = ((JMenu)nextMenu).getPopupMenu(); } msm.setSelectedPath(newSelection); } } } private void selectItem(boolean direction) { MenuSelectionManager msm = MenuSelectionManager.defaultManager(); MenuElement path[] = msm.getSelectedPath(); if (path.length == 0) { return; } int len = path.length; if (len == 1 && path[0] instanceof JPopupMenu) { JPopupMenu popup = (JPopupMenu) path[0]; MenuElement[] newPath = new MenuElement[2]; newPath[0] = popup; newPath[1] = findEnabledChild(popup.getSubElements(), -1, direction); msm.setSelectedPath(newPath); } else if (len == 2 && path[0] instanceof JMenuBar && path[1] instanceof JMenu) { // a toplevel menu is selected, but its popup not shown. // Show the popup and select the first item JPopupMenu popup = ((JMenu)path[1]).getPopupMenu(); MenuElement next = findEnabledChild(popup.getSubElements(), -1, FORWARD); MenuElement[] newPath; if (next != null) { // an enabled item found -- include it in newPath newPath = new MenuElement[4]; newPath[3] = next; } else { // menu has no enabled items -- still must show the popup newPath = new MenuElement[3]; } System.arraycopy(path, 0, newPath, 0, 2); newPath[2] = popup; msm.setSelectedPath(newPath); } else if (path[len-1] instanceof JPopupMenu && path[len-2] instanceof JMenu) { // a menu (not necessarily toplevel) is open and its popup // shown. Select the appropriate menu item JMenu menu = (JMenu)path[len-2]; JPopupMenu popup = menu.getPopupMenu(); MenuElement next = findEnabledChild(popup.getSubElements(), -1, direction); if (next != null) { MenuElement[] newPath = new MenuElement[len+1]; System.arraycopy(path, 0, newPath, 0, len); newPath[len] = next; msm.setSelectedPath(newPath); } else { // all items in the popup are disabled. // We're going to find the parent popup menu and select // its next item. If there's no parent popup menu (i.e. // current menu is toplevel), do nothing if (len > 2 && path[len-3] instanceof JPopupMenu) { popup = ((JPopupMenu)path[len-3]); next = findEnabledChild(popup.getSubElements(), menu, direction); if (next != null && next != menu) { MenuElement[] newPath = new MenuElement[len-1]; System.arraycopy(path, 0, newPath, 0, len-2); newPath[len-2] = next; msm.setSelectedPath(newPath); } } } } else { // just select the next item, no path expansion needed MenuElement subs[] = path[len-2].getSubElements(); MenuElement nextChild = findEnabledChild(subs, path[len-1], direction); if (nextChild == null) { nextChild = findEnabledChild(subs, -1, direction); } if (nextChild != null) { path[len-1] = nextChild; msm.setSelectedPath(path); } } } private void cancel() { // 4234793: This action should call JPopupMenu.firePopupMenuCanceled but it's // a protected method. The real solution could be to make // firePopupMenuCanceled public and call it directly. JPopupMenu lastPopup = (JPopupMenu)getLastPopup(); if (lastPopup != null) { lastPopup.putClientProperty("JPopupMenu.firePopupMenuCanceled", Boolean.TRUE); } MenuElement path[] = MenuSelectionManager.defaultManager().getSelectedPath(); if(path.length > 4) { /* PENDING(arnaud) Change this to 2 when a mouse grabber is available for MenuBar */ MenuElement newPath[] = new MenuElement[path.length - 2]; System.arraycopy(path,0,newPath,0,path.length-2); MenuSelectionManager.defaultManager().setSelectedPath(newPath); } else MenuSelectionManager.defaultManager().clearSelectedPath(); } } private static MenuElement nextEnabledChild(MenuElement e[], int fromIndex, int toIndex) { for (int i=fromIndex; i<=toIndex; i++) { if (e[i] != null) { Component comp = e[i].getComponent(); if ( comp != null && (comp.isEnabled() || UIManager.getBoolean("MenuItem.disabledAreNavigable")) && comp.isVisible()) { return e[i]; } } } return null; } private static MenuElement previousEnabledChild(MenuElement e[], int fromIndex, int toIndex) { for (int i=fromIndex; i>=toIndex; i--) { if (e[i] != null) { Component comp = e[i].getComponent(); if ( comp != null && (comp.isEnabled() || UIManager.getBoolean("MenuItem.disabledAreNavigable")) && comp.isVisible()) { return e[i]; } } } return null; } static MenuElement findEnabledChild(MenuElement e[], int fromIndex, boolean forward) { MenuElement result = null; if (forward) { result = nextEnabledChild(e, fromIndex+1, e.length-1); if (result == null) result = nextEnabledChild(e, 0, fromIndex-1); } else { result = previousEnabledChild(e, fromIndex-1, 0); if (result == null) result = previousEnabledChild(e, e.length-1, fromIndex+1); } return result; } static MenuElement findEnabledChild(MenuElement e[], MenuElement elem, boolean forward) { for (int i=0; i<e.length; i++) { if (e[i] == elem) { return findEnabledChild(e, i, forward); } } return null; } static class MouseGrabber implements ChangeListener, AWTEventListener, ComponentListener, WindowListener { Window grabbedWindow; MenuElement[] lastPathSelected; public MouseGrabber() { MenuSelectionManager msm = MenuSelectionManager.defaultManager(); msm.addChangeListener(this); this.lastPathSelected = msm.getSelectedPath(); if(this.lastPathSelected.length != 0) { grabWindow(this.lastPathSelected); } } void uninstall() { synchronized (BasicPopupMenuUI.MOUSE_GRABBER_KEY) { MenuSelectionManager.defaultManager().removeChangeListener(this); ungrabWindow(); AppContext.getAppContext().remove(MOUSE_GRABBER_KEY); } } void grabWindow(MenuElement[] newPath) { // A grab needs to be added final Toolkit tk = Toolkit.getDefaultToolkit(); java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { tk.addAWTEventListener(MouseGrabber.this, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK | sun.awt.SunToolkit.GRAB_EVENT_MASK); return null; } } ); Component invoker = newPath[0].getComponent(); if (invoker instanceof JPopupMenu) { invoker = ((JPopupMenu)invoker).getInvoker(); } grabbedWindow = invoker instanceof Window? (Window)invoker : SwingUtilities.getWindowAncestor(invoker); if(grabbedWindow != null) { if(tk instanceof sun.awt.SunToolkit) { ((sun.awt.SunToolkit)tk).grab(grabbedWindow); } else { grabbedWindow.addComponentListener(this); grabbedWindow.addWindowListener(this); } } } void ungrabWindow() { final Toolkit tk = Toolkit.getDefaultToolkit(); // The grab should be removed java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { tk.removeAWTEventListener(MouseGrabber.this); return null; } } ); if(grabbedWindow != null) { if(tk instanceof sun.awt.SunToolkit) { ((sun.awt.SunToolkit)tk).ungrab(grabbedWindow); } else { grabbedWindow.removeComponentListener(this); grabbedWindow.removeWindowListener(this); } grabbedWindow = null; } } public void stateChanged(ChangeEvent e) { MenuSelectionManager msm = MenuSelectionManager.defaultManager(); MenuElement[] p = msm.getSelectedPath(); if (lastPathSelected.length == 0 && p.length != 0) { grabWindow(p); } if (lastPathSelected.length != 0 && p.length == 0) { ungrabWindow(); } lastPathSelected = p; } public void eventDispatched(AWTEvent ev) { if(ev instanceof sun.awt.UngrabEvent) { // Popup should be canceled in case of ungrab event cancelPopupMenu( ); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -