History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/plaf/basic/BasicMenuUI.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/plaf/basic/BasicMenuUI.java+631−0
@@ -0,0 +1,631 @@
1+/*
2+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package javax.swing.plaf.basic;
27+
28+import sun.swing.DefaultLookup;
29+import sun.swing.UIAction;
30+import java.awt.*;
31+import java.awt.event.*;
32+import java.beans.*;
33+import javax.swing.*;
34+import javax.swing.event.*;
35+import javax.swing.plaf.*;
36+import javax.swing.border.*;
37+import java.util.Arrays;
38+import java.util.ArrayList;
39+
40+
41+/**
42+ * A default L&F implementation of MenuUI. This implementation
43+ * is a "combined" view/controller.
44+ *
45+ * @author Georges Saab
46+ * @author David Karlton
47+ * @author Arnaud Weber
48+ */
49+public class BasicMenuUI extends BasicMenuItemUI
50+{
51+ protected ChangeListener changeListener;
52+ protected MenuListener menuListener;
53+
54+ private int lastMnemonic = 0;
55+
56+ /** Uses as the parent of the windowInputMap when selected. */
57+ private InputMap selectedWindowInputMap;
58+
59+ /* diagnostic aids -- should be false for production builds. */
60+ private static final boolean TRACE = false; // trace creates and disposes
61+ private static final boolean VERBOSE = false; // show reuse hits/misses
62+ private static final boolean DEBUG = false; // show bad params, misc.
63+
64+ private static boolean crossMenuMnemonic = true;
65+
66+ public static ComponentUI createUI(JComponent x) {
67+ return new BasicMenuUI();
68+ }
69+
70+ static void loadActionMap(LazyActionMap map) {
71+ BasicMenuItemUI.loadActionMap(map);
72+ map.put(new Actions(Actions.SELECT, null, true));
73+ }
74+
75+
76+ protected void installDefaults() {
77+ super.installDefaults();
78+ updateDefaultBackgroundColor();
79+ ((JMenu)menuItem).setDelay(200);
80+ crossMenuMnemonic = UIManager.getBoolean("Menu.crossMenuMnemonic");
81+ }
82+
83+ protected String getPropertyPrefix() {
84+ return "Menu";
85+ }
86+
87+ protected void installListeners() {
88+ super.installListeners();
89+
90+ if (changeListener == null)
91+ changeListener = createChangeListener(menuItem);
92+
93+ if (changeListener != null)
94+ menuItem.addChangeListener(changeListener);
95+
96+ if (menuListener == null)
97+ menuListener = createMenuListener(menuItem);
98+
99+ if (menuListener != null)
100+ ((JMenu)menuItem).addMenuListener(menuListener);
101+ }
102+
103+ protected void installKeyboardActions() {
104+ super.installKeyboardActions();
105+ updateMnemonicBinding();
106+ }
107+
108+ void installLazyActionMap() {
109+ LazyActionMap.installLazyActionMap(menuItem, BasicMenuUI.class,
110+ getPropertyPrefix() + ".actionMap");
111+ }
112+
113+ void updateMnemonicBinding() {
114+ int mnemonic = menuItem.getModel().getMnemonic();
115+ int[] shortcutKeys = (int[])DefaultLookup.get(menuItem, this,
116+ "Menu.shortcutKeys");
117+ if (shortcutKeys == null) {
118+ shortcutKeys = new int[] {KeyEvent.ALT_MASK};
119+ }
120+ if (mnemonic == lastMnemonic) {
121+ return;
122+ }
123+ InputMap windowInputMap = SwingUtilities.getUIInputMap(
124+ menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
125+ if (lastMnemonic != 0 && windowInputMap != null) {
126+ for (int shortcutKey : shortcutKeys) {
127+ windowInputMap.remove(KeyStroke.getKeyStroke
128+ (lastMnemonic, shortcutKey, false));
129+ }
130+ }
131+ if (mnemonic != 0) {
132+ if (windowInputMap == null) {
133+ windowInputMap = createInputMap(JComponent.
134+ WHEN_IN_FOCUSED_WINDOW);
135+ SwingUtilities.replaceUIInputMap(menuItem, JComponent.
136+ WHEN_IN_FOCUSED_WINDOW, windowInputMap);
137+ }
138+ for (int shortcutKey : shortcutKeys) {
139+ windowInputMap.put(KeyStroke.getKeyStroke(mnemonic,
140+ shortcutKey, false), "selectMenu");
141+ }
142+ }
143+ lastMnemonic = mnemonic;
144+ }
145+
146+ protected void uninstallKeyboardActions() {
147+ super.uninstallKeyboardActions();
148+ lastMnemonic = 0;
149+ }
150+
151+ protected MouseInputListener createMouseInputListener(JComponent c) {
152+ return getHandler();
153+ }
154+
155+ protected MenuListener createMenuListener(JComponent c) {
156+ return null;
157+ }
158+
159+ protected ChangeListener createChangeListener(JComponent c) {
160+ return null;
161+ }
162+
163+ protected PropertyChangeListener createPropertyChangeListener(JComponent c) {
164+ return getHandler();
165+ }
166+
167+ BasicMenuItemUI.Handler getHandler() {
168+ if (handler == null) {
169+ handler = new Handler();
170+ }
171+ return handler;
172+ }
173+
174+ protected void uninstallDefaults() {
175+ menuItem.setArmed(false);
176+ menuItem.setSelected(false);
177+ menuItem.resetKeyboardActions();
178+ super.uninstallDefaults();
179+ }
180+
181+ protected void uninstallListeners() {
182+ super.uninstallListeners();
183+
184+ if (changeListener != null)
185+ menuItem.removeChangeListener(changeListener);
186+
187+ if (menuListener != null)
188+ ((JMenu)menuItem).removeMenuListener(menuListener);
189+
190+ changeListener = null;
191+ menuListener = null;
192+ handler = null;
193+ }
194+
195+ protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) {
196+ return getHandler();
197+ }
198+
199+ protected MenuKeyListener createMenuKeyListener(JComponent c) {
200+ return (MenuKeyListener)getHandler();
201+ }
202+
203+ public Dimension getMaximumSize(JComponent c) {
204+ if (((JMenu)menuItem).isTopLevelMenu() == true) {
205+ Dimension d = c.getPreferredSize();
206+ return new Dimension(d.width, Short.MAX_VALUE);
207+ }
208+ return null;
209+ }
210+
211+ protected void setupPostTimer(JMenu menu) {
212+ Timer timer = new Timer(menu.getDelay(), new Actions(
213+ Actions.SELECT, menu,false));
214+ timer.setRepeats(false);
215+ timer.start();
216+ }
217+
218+ private static void appendPath(MenuElement[] path, MenuElement elem) {
219+ MenuElement newPath[] = new MenuElement[path.length+1];
220+ System.arraycopy(path, 0, newPath, 0, path.length);
221+ newPath[path.length] = elem;
222+ MenuSelectionManager.defaultManager().setSelectedPath(newPath);
223+ }
224+
225+ private static class Actions extends UIAction {
226+ private static final String SELECT = "selectMenu";
227+
228+ // NOTE: This will be null if the action is registered in the
229+ // ActionMap. For the timer use it will be non-null.
230+ private JMenu menu;
231+ private boolean force=false;
232+
233+ Actions(String key, JMenu menu, boolean shouldForce) {
234+ super(key);
235+ this.menu = menu;
236+ this.force = shouldForce;
237+ }
238+
239+ private JMenu getMenu(ActionEvent e) {
240+ if (e.getSource() instanceof JMenu) {
241+ return (JMenu)e.getSource();
242+ }
243+ return menu;
244+ }
245+
246+ public void actionPerformed(ActionEvent e) {
247+ JMenu menu = getMenu(e);
248+ if (!crossMenuMnemonic) {
249+ JPopupMenu pm = BasicPopupMenuUI.getLastPopup();
250+ if (pm != null && pm != menu.getParent()) {
251+ return;
252+ }
253+ }
254+
255+ final MenuSelectionManager defaultManager = MenuSelectionManager.defaultManager();
256+ if(force) {
257+ Container cnt = menu.getParent();
258+ if(cnt != null && cnt instanceof JMenuBar) {
259+ MenuElement me[];
260+ MenuElement subElements[];
261+
262+ subElements = menu.getPopupMenu().getSubElements();
263+ if(subElements.length > 0) {
264+ me = new MenuElement[4];
265+ me[0] = (MenuElement) cnt;
266+ me[1] = menu;
267+ me[2] = menu.getPopupMenu();
268+ me[3] = subElements[0];
269+ } else {
270+ me = new MenuElement[3];
271+ me[0] = (MenuElement)cnt;
272+ me[1] = menu;
273+ me[2] = menu.getPopupMenu();
274+ }
275+ defaultManager.setSelectedPath(me);
276+ }
277+ } else {
278+ MenuElement path[] = defaultManager.getSelectedPath();
279+ if(path.length > 0 && path[path.length-1] == menu) {
280+ appendPath(path, menu.getPopupMenu());
281+ }
282+ }
283+ }
284+
285+ public boolean isEnabled(Object c) {
286+ if (c instanceof JMenu) {
287+ return ((JMenu)c).isEnabled();
288+ }
289+ return true;
290+ }
291+ }
292+
293+ /*
294+ * Set the background color depending on whether this is a toplevel menu
295+ * in a menubar or a submenu of another menu.
296+ */
297+ private void updateDefaultBackgroundColor() {
298+ if (!UIManager.getBoolean("Menu.useMenuBarBackgroundForTopLevel")) {
299+ return;
300+ }
301+ JMenu menu = (JMenu)menuItem;
302+ if (menu.getBackground() instanceof UIResource) {
303+ if (menu.isTopLevelMenu()) {
304+ menu.setBackground(UIManager.getColor("MenuBar.background"));
305+ } else {
306+ menu.setBackground(UIManager.getColor(getPropertyPrefix() + ".background"));
307+ }
308+ }
309+ }
310+
311+ /**
312+ * Instantiated and used by a menu item to handle the current menu selection
313+ * from mouse events. A MouseInputHandler processes and forwards all mouse events
314+ * to a shared instance of the MenuSelectionManager.
315+ * <p>
316+ * This class is protected so that it can be subclassed by other look and
317+ * feels to implement their own mouse handling behavior. All overridden
318+ * methods should call the parent methods so that the menu selection
319+ * is correct.
320+ *
321+ * @see javax.swing.MenuSelectionManager
322+ * @since 1.4
323+ */
324+ protected class MouseInputHandler implements MouseInputListener {
325+ // NOTE: This class exists only for backward compatability. All
326+ // its functionality has been moved into Handler. If you need to add
327+ // new functionality add it to the Handler, but make sure this
328+ // class calls into the Handler.
329+
330+ public void mouseClicked(MouseEvent e) {
331+ getHandler().mouseClicked(e);
332+ }
333+
334+ /**
335+ * Invoked when the mouse has been clicked on the menu. This
336+ * method clears or sets the selection path of the
337+ * MenuSelectionManager.
338+ *
339+ * @param e the mouse event
340+ */
341+ public void mousePressed(MouseEvent e) {
342+ getHandler().mousePressed(e);
343+ }
344+
345+ /**
346+ * Invoked when the mouse has been released on the menu. Delegates the
347+ * mouse event to the MenuSelectionManager.
348+ *
349+ * @param e the mouse event
350+ */
351+ public void mouseReleased(MouseEvent e) {
352+ getHandler().mouseReleased(e);
353+ }
354+
355+ /**
356+ * Invoked when the cursor enters the menu. This method sets the selected
357+ * path for the MenuSelectionManager and handles the case
358+ * in which a menu item is used to pop up an additional menu, as in a
359+ * hierarchical menu system.
360+ *
361+ * @param e the mouse event; not used
362+ */
363+ public void mouseEntered(MouseEvent e) {
364+ getHandler().mouseEntered(e);
365+ }
366+ public void mouseExited(MouseEvent e) {
367+ getHandler().mouseExited(e);
368+ }
369+
370+ /**
371+ * Invoked when a mouse button is pressed on the menu and then dragged.
372+ * Delegates the mouse event to the MenuSelectionManager.
373+ *
374+ * @param e the mouse event
375+ * @see java.awt.event.MouseMotionListener#mouseDragged
376+ */
377+ public void mouseDragged(MouseEvent e) {
378+ getHandler().mouseDragged(e);
379+ }
380+
381+ public void mouseMoved(MouseEvent e) {
382+ getHandler().mouseMoved(e);
383+ }
384+ }
385+
386+ /**
387+ * As of Java 2 platform 1.4, this previously undocumented class
388+ * is now obsolete. KeyBindings are now managed by the popup menu.
389+ */
390+ public class ChangeHandler implements ChangeListener {
391+ public JMenu menu;
392+ public BasicMenuUI ui;
393+ public boolean isSelected = false;
394+ public Component wasFocused;
395+
396+ public ChangeHandler(JMenu m, BasicMenuUI ui) {
397+ menu = m;
398+ this.ui = ui;
399+ }
400+
401+ public void stateChanged(ChangeEvent e) { }
402+ }
403+
404+ private class Handler extends BasicMenuItemUI.Handler implements MenuKeyListener {
405+ //
406+ // PropertyChangeListener
407+ //
408+ public void propertyChange(PropertyChangeEvent e) {
409+ if (e.getPropertyName() == AbstractButton.
410+ MNEMONIC_CHANGED_PROPERTY) {
411+ updateMnemonicBinding();
412+ }
413+ else {
414+ if (e.getPropertyName().equals("ancestor")) {
415+ updateDefaultBackgroundColor();
416+ }
417+ super.propertyChange(e);
418+ }
419+ }
420+
421+ //
422+ // MouseInputListener
423+ //
424+ public void mouseClicked(MouseEvent e) {
425+ }
426+
427+ /**
428+ * Invoked when the mouse has been clicked on the menu. This
429+ * method clears or sets the selection path of the
430+ * MenuSelectionManager.
431+ *
432+ * @param e the mouse event
433+ */
434+ public void mousePressed(MouseEvent e) {
435+ JMenu menu = (JMenu)menuItem;
436+ if (!menu.isEnabled())
437+ return;
438+
439+ MenuSelectionManager manager =
440+ MenuSelectionManager.defaultManager();
441+ if(menu.isTopLevelMenu()) {
442+ if(menu.isSelected() && menu.getPopupMenu().isShowing()) {
443+ manager.clearSelectedPath();
444+ } else {
445+ Container cnt = menu.getParent();
446+ if(cnt != null && cnt instanceof JMenuBar) {
447+ MenuElement me[] = new MenuElement[2];
448+ me[0]=(MenuElement)cnt;
449+ me[1]=menu;
450+ manager.setSelectedPath(me);
451+ }
452+ }
453+ }
454+
455+ MenuElement selectedPath[] = manager.getSelectedPath();
456+ if (selectedPath.length > 0 &&
457+ selectedPath[selectedPath.length-1] != menu.getPopupMenu()) {
458+
459+ if(menu.isTopLevelMenu() ||
460+ menu.getDelay() == 0) {
461+ appendPath(selectedPath, menu.getPopupMenu());
462+ } else {
463+ setupPostTimer(menu);
464+ }
465+ }
466+ }
467+
468+ /**
469+ * Invoked when the mouse has been released on the menu. Delegates the
470+ * mouse event to the MenuSelectionManager.
471+ *
472+ * @param e the mouse event
473+ */
474+ public void mouseReleased(MouseEvent e) {
475+ JMenu menu = (JMenu)menuItem;
476+ if (!menu.isEnabled())
477+ return;
478+ MenuSelectionManager manager =
479+ MenuSelectionManager.defaultManager();
480+ manager.processMouseEvent(e);
481+ if (!e.isConsumed())
482+ manager.clearSelectedPath();
483+ }
484+
485+ /**
486+ * Invoked when the cursor enters the menu. This method sets the selected
487+ * path for the MenuSelectionManager and handles the case
488+ * in which a menu item is used to pop up an additional menu, as in a
489+ * hierarchical menu system.
490+ *
491+ * @param e the mouse event; not used
492+ */
493+ public void mouseEntered(MouseEvent e) {
494+ JMenu menu = (JMenu)menuItem;
495+ // only disable the menu highlighting if it's disabled and the property isn't
496+ // true. This allows disabled rollovers to work in WinL&F
497+ if (!menu.isEnabled() && !UIManager.getBoolean("MenuItem.disabledAreNavigable")) {
498+ return;
499+ }
500+
501+ MenuSelectionManager manager =
502+ MenuSelectionManager.defaultManager();
503+ MenuElement selectedPath[] = manager.getSelectedPath();
504+ if (!menu.isTopLevelMenu()) {
505+ if(!(selectedPath.length > 0 &&
506+ selectedPath[selectedPath.length-1] ==
507+ menu.getPopupMenu())) {
508+ if(menu.getDelay() == 0) {
509+ appendPath(getPath(), menu.getPopupMenu());
510+ } else {
511+ manager.setSelectedPath(getPath());
512+ setupPostTimer(menu);
513+ }
514+ }
515+ } else {
516+ if(selectedPath.length > 0 &&
517+ selectedPath[0] == menu.getParent()) {
518+ MenuElement newPath[] = new MenuElement[3];
519+ // A top level menu's parent is by definition
520+ // a JMenuBar
521+ newPath[0] = (MenuElement)menu.getParent();
522+ newPath[1] = menu;
523+ if (BasicPopupMenuUI.getLastPopup() != null) {
524+ newPath[2] = menu.getPopupMenu();
525+ }
526+ manager.setSelectedPath(newPath);
527+ }
528+ }
529+ }
530+ public void mouseExited(MouseEvent e) {
531+ }
532+
533+ /**
534+ * Invoked when a mouse button is pressed on the menu and then dragged.
535+ * Delegates the mouse event to the MenuSelectionManager.
536+ *
537+ * @param e the mouse event
538+ * @see java.awt.event.MouseMotionListener#mouseDragged
539+ */
540+ public void mouseDragged(MouseEvent e) {
541+ JMenu menu = (JMenu)menuItem;
542+ if (!menu.isEnabled())
543+ return;
544+ MenuSelectionManager.defaultManager().processMouseEvent(e);
545+ }
546+ public void mouseMoved(MouseEvent e) {
547+ }
548+
549+
550+ //
551+ // MenuDragHandler
552+ //
553+ public void menuDragMouseEntered(MenuDragMouseEvent e) {}
554+ public void menuDragMouseDragged(MenuDragMouseEvent e) {
555+ if (menuItem.isEnabled() == false)
556+ return;
557+
558+ MenuSelectionManager manager = e.getMenuSelectionManager();
559+ MenuElement path[] = e.getPath();
560+
561+ Point p = e.getPoint();
562+ if(p.x >= 0 && p.x < menuItem.getWidth() &&
563+ p.y >= 0 && p.y < menuItem.getHeight()) {
564+ JMenu menu = (JMenu)menuItem;
565+ MenuElement selectedPath[] = manager.getSelectedPath();
566+ if(!(selectedPath.length > 0 &&
567+ selectedPath[selectedPath.length-1] ==
568+ menu.getPopupMenu())) {
569+ if(menu.isTopLevelMenu() ||
570+ menu.getDelay() == 0 ||
571+ e.getID() == MouseEvent.MOUSE_DRAGGED) {
572+ appendPath(path, menu.getPopupMenu());
573+ } else {
574+ manager.setSelectedPath(path);
575+ setupPostTimer(menu);
576+ }
577+ }
578+ } else if(e.getID() == MouseEvent.MOUSE_RELEASED) {
579+ Component comp = manager.componentForPoint(e.getComponent(), e.getPoint());
580+ if (comp == null)
581+ manager.clearSelectedPath();
582+ }
583+
584+ }
585+ public void menuDragMouseExited(MenuDragMouseEvent e) {}
586+ public void menuDragMouseReleased(MenuDragMouseEvent e) {}
587+
588+ //
589+ // MenuKeyListener
590+ //
591+ /**
592+ * Open the Menu
593+ */
594+ public void menuKeyTyped(MenuKeyEvent e) {
595+ if (!crossMenuMnemonic && BasicPopupMenuUI.getLastPopup() != null) {
596+ // when crossMenuMnemonic is not set, we don't open a toplevel
597+ // menu if another toplevel menu is already open
598+ return;
599+ }
600+
601+ if (BasicPopupMenuUI.getPopups().size() != 0) {
602+ //Fix 6939261: to return in case not on the main menu
603+ //and has a pop-up.
604+ //after return code will be handled in BasicPopupMenuUI.java
605+ return;
606+ }
607+
608+ char key = Character.toLowerCase((char)menuItem.getMnemonic());
609+ MenuElement path[] = e.getPath();
610+ if (key == Character.toLowerCase(e.getKeyChar())) {
611+ JPopupMenu popupMenu = ((JMenu)menuItem).getPopupMenu();
612+ ArrayList newList = new ArrayList(Arrays.asList(path));
613+ newList.add(popupMenu);
614+ MenuElement subs[] = popupMenu.getSubElements();
615+ MenuElement sub =
616+ BasicPopupMenuUI.findEnabledChild(subs, -1, true);
617+ if(sub != null) {
618+ newList.add(sub);
619+ }
620+ MenuSelectionManager manager = e.getMenuSelectionManager();
621+ MenuElement newPath[] = new MenuElement[0];;
622+ newPath = (MenuElement[]) newList.toArray(newPath);
623+ manager.setSelectedPath(newPath);
624+ e.consume();
625+ }
626+ }
627+
628+ public void menuKeyPressed(MenuKeyEvent e) {}
629+ public void menuKeyReleased(MenuKeyEvent e) {}
630+ }
631+}