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
26package javax.swing.plaf.basic;
27
28import sun.swing.DefaultLookup;
29import sun.swing.UIAction;
30import java.awt.*;
31import java.awt.event.*;
32import java.beans.*;
33import javax.swing.*;
34import javax.swing.event.*;
35import javax.swing.plaf.*;
36import javax.swing.border.*;
37import java.util.Arrays;
38import 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 */
49public 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}