1 7 8 package javax.swing.plaf.basic; 9 10 import javax.swing.*; 11 import javax.swing.event.*; 12 import javax.swing.plaf.*; 13 import javax.swing.plaf.basic.*; 14 import javax.swing.border.*; 15 16 import java.applet.Applet ; 17 18 import java.awt.Component ; 19 import java.awt.Container ; 20 import java.awt.Dimension ; 21 import java.awt.KeyboardFocusManager ; 22 import java.awt.Window ; 23 import java.awt.event.*; 24 import java.awt.AWTEvent ; 25 import java.awt.Toolkit ; 26 27 import java.beans.PropertyChangeListener ; 28 import java.beans.PropertyChangeEvent ; 29 30 import java.util.*; 31 32 import sun.swing.DefaultLookup; 33 import sun.swing.UIAction; 34 35 44 public class BasicPopupMenuUI extends PopupMenuUI { 45 protected JPopupMenu popupMenu = null; 46 private transient PopupMenuListener popupMenuListener = null; 47 private MenuKeyListener menuKeyListener = null; 48 static boolean menuKeyboardHelperInstalled = false; 49 static MenuKeyboardHelper menuKeyboardHelper = null; 50 51 private static boolean checkedUnpostPopup; 52 private static boolean unpostPopup; 53 54 public static ComponentUI createUI(JComponent x) { 55 return new BasicPopupMenuUI (); 56 } 57 58 public BasicPopupMenuUI() { 59 BasicLookAndFeel.hasPopups = true; 60 LookAndFeel laf = UIManager.getLookAndFeel(); 61 if (laf instanceof BasicLookAndFeel ) { 62 ((BasicLookAndFeel )laf).createdPopup(); 63 } 64 } 65 66 public void installUI(JComponent c) { 67 popupMenu = (JPopupMenu) c; 68 69 installDefaults(); 70 installListeners(); 71 installKeyboardActions(); 72 } 73 74 public void installDefaults() { 75 if (popupMenu.getLayout() == null || 76 popupMenu.getLayout() instanceof UIResource) 77 popupMenu.setLayout(new DefaultMenuLayout (popupMenu, BoxLayout.Y_AXIS)); 78 79 LookAndFeel.installProperty(popupMenu, "opaque", Boolean.TRUE); 80 LookAndFeel.installBorder(popupMenu, "PopupMenu.border"); 81 LookAndFeel.installColorsAndFont(popupMenu, 82 "PopupMenu.background", 83 "PopupMenu.foreground", 84 "PopupMenu.font"); 85 } 86 87 protected void installListeners() { 88 if (popupMenuListener == null) { 89 popupMenuListener = new BasicPopupMenuListener(); 90 } 91 popupMenu.addPopupMenuListener(popupMenuListener); 92 93 if (menuKeyListener == null) { 94 menuKeyListener = new BasicMenuKeyListener(); 95 } 96 popupMenu.addMenuKeyListener(menuKeyListener); 97 98 if (mouseGrabber == null) { 99 mouseGrabber = new MouseGrabber(); 100 } 101 102 if (!menuKeyboardHelperInstalled) { 103 if (menuKeyboardHelper == null) { 104 menuKeyboardHelper = new MenuKeyboardHelper(); 105 } 106 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 107 msm.addChangeListener(menuKeyboardHelper); 108 menuKeyboardHelperInstalled = true; 109 } 110 } 111 112 protected void installKeyboardActions() { 113 } 114 115 static InputMap getInputMap(JPopupMenu popup, JComponent c) { 116 InputMap windowInputMap = null; 117 Object [] bindings = (Object [])UIManager.get("PopupMenu.selectedWindowInputMapBindings"); 118 if (bindings != null) { 119 windowInputMap = LookAndFeel.makeComponentInputMap(c, bindings); 120 if (!popup.getComponentOrientation().isLeftToRight()) { 121 Object [] km = (Object [])UIManager.get("PopupMenu.selectedWindowInputMapBindings.RightToLeft"); 122 if (km != null) { 123 InputMap rightToLeftInputMap = LookAndFeel.makeComponentInputMap(c, km); 124 rightToLeftInputMap.setParent(windowInputMap); 125 windowInputMap = rightToLeftInputMap; 126 } 127 } 128 } 129 return windowInputMap; 130 } 131 132 static ActionMap getActionMap() { 133 return LazyActionMap.getActionMap(BasicPopupMenuUI .class, 134 "PopupMenu.actionMap"); 135 } 136 137 static void loadActionMap(LazyActionMap map) { 138 map.put(new Actions(Actions.CANCEL)); 139 map.put(new Actions(Actions.SELECT_NEXT)); 140 map.put(new Actions(Actions.SELECT_PREVIOUS)); 141 map.put(new Actions(Actions.SELECT_PARENT)); 142 map.put(new Actions(Actions.SELECT_CHILD)); 143 map.put(new Actions(Actions.RETURN)); 144 BasicLookAndFeel.installAudioActionMap(map); 145 } 146 147 public void uninstallUI(JComponent c) { 148 uninstallDefaults(); 149 uninstallListeners(); 150 uninstallKeyboardActions(); 151 152 popupMenu = null; 153 } 154 155 protected void uninstallDefaults() { 156 LookAndFeel.uninstallBorder(popupMenu); 157 } 158 159 protected void uninstallListeners() { 160 if (popupMenuListener != null) { 161 popupMenu.removePopupMenuListener(popupMenuListener); 162 } 163 if (menuKeyListener != null) { 164 popupMenu.removeMenuKeyListener(menuKeyListener); 165 } 166 if(mouseGrabber != null) { 167 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 168 msm.removeChangeListener(mouseGrabber); 169 mouseGrabber.ungrabWindow(); 170 mouseGrabber = null; 171 } 172 } 173 174 protected void uninstallKeyboardActions() { 175 SwingUtilities.replaceUIActionMap(popupMenu, null); 176 SwingUtilities.replaceUIInputMap(popupMenu, 177 JComponent.WHEN_IN_FOCUSED_WINDOW, null); 178 } 179 180 static MenuElement getFirstPopup() { 181 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 182 MenuElement[] p = msm.getSelectedPath(); 183 MenuElement me = null; 184 185 for(int i = 0 ; me == null && i < p.length ; i++) { 186 if (p[i] instanceof JPopupMenu) 187 me = p[i]; 188 } 189 190 return me; 191 } 192 193 private static boolean doUnpostPopupOnDeactivation() { 194 if (!checkedUnpostPopup) { 195 Boolean b = java.security.AccessController.doPrivileged( 196 new java.security.PrivilegedAction <Boolean > () { 197 public Boolean run() { 198 String pKey = 199 "sun.swing.unpostPopupsOnWindowDeactivation"; 200 String value = System.getProperty(pKey, "true"); 201 return Boolean.valueOf(value); 202 } 203 } 204 ); 205 unpostPopup = b.booleanValue(); 206 checkedUnpostPopup = true; 207 } 208 return unpostPopup; 209 } 210 211 static JPopupMenu getLastPopup() { 212 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 213 MenuElement[] p = msm.getSelectedPath(); 214 JPopupMenu popup = null; 215 216 for(int i = p.length - 1; popup == null && i >= 0; i--) { 217 if (p[i] instanceof JPopupMenu) 218 popup = (JPopupMenu)p[i]; 219 } 220 return popup; 221 } 222 223 static List getPopups() { 224 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 225 MenuElement[] p = msm.getSelectedPath(); 226 227 List list = new ArrayList(p.length); 228 for(int i = 0; i < p.length; i++) { 229 if (p[i] instanceof JPopupMenu) { 230 list.add((JPopupMenu)p[i]); 231 } 232 } 233 return list; 234 } 235 236 public boolean isPopupTrigger(MouseEvent e) { 237 return ((e.getID()==MouseEvent.MOUSE_RELEASED) 238 && ((e.getModifiers() & MouseEvent.BUTTON3_MASK)!=0)); 239 } 240 241 private static boolean checkInvokerEqual(MenuElement present, MenuElement last) { 242 Component invokerPresent = present.getComponent(); 243 Component invokerLast = last.getComponent(); 244 245 if (invokerPresent instanceof JPopupMenu) { 246 invokerPresent = ((JPopupMenu)invokerPresent).getInvoker(); 247 } 248 if (invokerLast instanceof JPopupMenu) { 249 invokerLast = ((JPopupMenu)invokerLast).getInvoker(); 250 } 251 return (invokerPresent == invokerLast); 252 } 253 254 255 261 private class BasicPopupMenuListener implements PopupMenuListener { 262 public void popupMenuCanceled(PopupMenuEvent e) { 263 } 264 265 public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 266 } 267 268 public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 269 BasicLookAndFeel.playSound((JPopupMenu)e.getSource(), 270 "PopupMenu.popupSound"); 271 } 272 } 273 274 278 private class BasicMenuKeyListener implements MenuKeyListener { 279 MenuElement menuToOpen = null; 280 281 public void menuKeyTyped(MenuKeyEvent e) { 282 if (menuToOpen != null) { 283 JPopupMenu subpopup = ((JMenu)menuToOpen).getPopupMenu(); 285 MenuElement subitem = findEnabledChild( 286 subpopup.getSubElements(), -1, true); 287 288 ArrayList lst = new ArrayList(Arrays.asList(e.getPath())); 289 lst.add(menuToOpen); 290 lst.add(subpopup); 291 if (subitem != null) { 292 lst.add(subitem); 293 } 294 MenuElement newPath[] = new MenuElement[0];; 295 newPath = (MenuElement[])lst.toArray(newPath); 296 MenuSelectionManager.defaultManager().setSelectedPath(newPath); 297 e.consume(); 298 } 299 menuToOpen = null; 300 } 301 302 public void menuKeyPressed(MenuKeyEvent e) { 303 if (!Character.isLetterOrDigit(e.getKeyChar())) { 305 return; 306 } 307 308 int keyCode = e.getKeyCode(); 309 MenuSelectionManager manager = e.getMenuSelectionManager(); 310 MenuElement path[] = e.getPath(); 311 MenuElement items[] = popupMenu.getSubElements(); 312 int currentIndex = -1; 313 int matches = 0; 314 int firstMatch = -1; 315 int indexes[] = null; 316 317 for (int j = 0; j < items.length; j++) { 318 if (! (items[j] instanceof JMenuItem)) { 319 continue; 320 } 321 JMenuItem item = (JMenuItem)items[j]; 322 if (item.isEnabled() && 323 item.isVisible() && keyCode == item.getMnemonic()) { 324 if (matches == 0) { 325 firstMatch = j; 326 matches++; 327 } else { 328 if (indexes == null) { 329 indexes = new int[items.length]; 330 indexes[0] = firstMatch; 331 } 332 indexes[matches++] = j; 333 } 334 } 335 if (item.isArmed()) { 336 currentIndex = matches - 1; 337 } 338 } 339 340 if (matches == 0) { 341 ; } else if (matches == 1) { 343 JMenuItem item = (JMenuItem)items[firstMatch]; 345 if (item instanceof JMenu) { 346 menuToOpen = item; 348 } else if (item.isEnabled()) { 349 manager.clearSelectedPath(); 351 item.doClick(); 352 } 353 e.consume(); 354 } else { 355 MenuElement newItem = null; 359 360 newItem = items[indexes[(currentIndex + 1) % matches]]; 361 362 MenuElement newPath[] = new MenuElement[path.length+1]; 363 System.arraycopy(path, 0, newPath, 0, path.length); 364 newPath[path.length] = newItem; 365 manager.setSelectedPath(newPath); 366 e.consume(); 367 } 368 return; 369 } 370 371 public void menuKeyReleased(MenuKeyEvent e) { 372 } 373 } 374 375 private static class Actions extends UIAction { 376 private static final String CANCEL = "cancel"; 378 private static final String SELECT_NEXT = "selectNext"; 379 private static final String SELECT_PREVIOUS = "selectPrevious"; 380 private static final String SELECT_PARENT = "selectParent"; 381 private static final String SELECT_CHILD = "selectChild"; 382 private static final String RETURN = "return"; 383 384 private static final boolean FORWARD = true; 386 private static final boolean BACKWARD = false; 387 388 private static final boolean PARENT = false; 390 private static final boolean CHILD = true; 391 392 393 Actions(String key) { 394 super(key); 395 } 396 397 public void actionPerformed(ActionEvent e) { 398 String key = getName(); 399 if (key == CANCEL) { 400 cancel(); 401 } 402 else if (key == SELECT_NEXT) { 403 selectItem(FORWARD); 404 } 405 else if (key == SELECT_PREVIOUS) { 406 selectItem(BACKWARD); 407 } 408 else if (key == SELECT_PARENT) { 409 selectParentChild(PARENT); 410 } 411 else if (key == SELECT_CHILD) { 412 selectParentChild(CHILD); 413 } 414 else if (key == RETURN) { 415 doReturn(); 416 } 417 } 418 419 private void doReturn() { 420 KeyboardFocusManager fmgr = 421 KeyboardFocusManager.getCurrentKeyboardFocusManager(); 422 Component focusOwner = fmgr.getFocusOwner(); 423 if(focusOwner != null && !(focusOwner instanceof JRootPane)) { 424 return; 425 } 426 427 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 428 MenuElement path[] = msm.getSelectedPath(); 429 MenuElement lastElement; 430 if(path.length > 0) { 431 lastElement = path[path.length-1]; 432 if(lastElement instanceof JMenu) { 433 MenuElement newPath[] = new MenuElement[path.length+1]; 434 System.arraycopy(path,0,newPath,0,path.length); 435 newPath[path.length] = ((JMenu)lastElement).getPopupMenu(); 436 msm.setSelectedPath(newPath); 437 } else if(lastElement instanceof JMenuItem) { 438 JMenuItem mi = (JMenuItem)lastElement; 439 440 if (mi.getUI() instanceof BasicMenuItemUI ) { 441 ((BasicMenuItemUI )mi.getUI()).doClick(msm); 442 } 443 else { 444 msm.clearSelectedPath(); 445 mi.doClick(0); 446 } 447 } 448 } 449 } 450 private void selectParentChild(boolean direction) { 451 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 452 MenuElement path[] = msm.getSelectedPath(); 453 int len = path.length; 454 455 if (direction == PARENT) { 456 int popupIndex = len-1; 458 459 if (len > 2 && 460 (path[popupIndex] instanceof JPopupMenu || 464 path[--popupIndex] instanceof JPopupMenu) && 465 !((JMenu)path[popupIndex-1]).isTopLevelMenu()) { 466 467 MenuElement newPath[] = new MenuElement[popupIndex]; 469 System.arraycopy(path, 0, newPath, 0, popupIndex); 470 msm.setSelectedPath(newPath); 471 return; 472 } 473 } else { 474 if (len > 0 && path[len-1] instanceof JMenu && 476 !((JMenu)path[len-1]).isTopLevelMenu()) { 477 478 JMenu menu = (JMenu)path[len-1]; 480 JPopupMenu popup = menu.getPopupMenu(); 481 MenuElement[] subs = popup.getSubElements(); 482 MenuElement item = findEnabledChild(subs, -1, true); 483 MenuElement[] newPath; 484 485 if (item == null) { 486 newPath = new MenuElement[len+1]; 487 } else { 488 newPath = new MenuElement[len+2]; 489 newPath[len+1] = item; 490 } 491 System.arraycopy(path, 0, newPath, 0, len); 492 newPath[len] = popup; 493 msm.setSelectedPath(newPath); 494 return; 495 } 496 } 497 498 if (len > 1 && path[0] instanceof JMenuBar) { 501 MenuElement currentMenu = path[1]; 502 MenuElement nextMenu = findEnabledChild( 503 path[0].getSubElements(), currentMenu, direction); 504 505 if (nextMenu != null && nextMenu != currentMenu) { 506 MenuElement newSelection[]; 507 if (len == 2) { 508 newSelection = new MenuElement[2]; 510 newSelection[0] = path[0]; 511 newSelection[1] = nextMenu; 512 } else { 513 newSelection = new MenuElement[3]; 515 newSelection[0] = path[0]; 516 newSelection[1] = nextMenu; 517 newSelection[2] = ((JMenu)nextMenu).getPopupMenu(); 518 } 519 msm.setSelectedPath(newSelection); 520 } 521 } 522 } 523 524 private void selectItem(boolean direction) { 525 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 526 MenuElement path[] = msm.getSelectedPath(); 527 if (path.length < 2) { 528 return; 529 } 530 int len = path.length; 531 532 if (path[0] instanceof JMenuBar && 533 path[1] instanceof JMenu && len == 2) { 534 535 JPopupMenu popup = ((JMenu)path[1]).getPopupMenu(); 538 MenuElement next = 539 findEnabledChild(popup.getSubElements(), -1, FORWARD); 540 MenuElement[] newPath; 541 542 if (next != null) { 543 newPath = new MenuElement[4]; 545 newPath[3] = next; 546 } else { 547 newPath = new MenuElement[3]; 549 } 550 System.arraycopy(path, 0, newPath, 0, 2); 551 newPath[2] = popup; 552 msm.setSelectedPath(newPath); 553 554 } else if (path[len-1] instanceof JPopupMenu && 555 path[len-2] instanceof JMenu) { 556 557 JMenu menu = (JMenu)path[len-2]; 560 JPopupMenu popup = menu.getPopupMenu(); 561 MenuElement next = 562 findEnabledChild(popup.getSubElements(), -1, direction); 563 564 if (next != null) { 565 MenuElement[] newPath = new MenuElement[len+1]; 566 System.arraycopy(path, 0, newPath, 0, len); 567 newPath[len] = next; 568 msm.setSelectedPath(newPath); 569 } else { 570 if (len > 2 && path[len-3] instanceof JPopupMenu) { 575 popup = ((JPopupMenu)path[len-3]); 576 next = findEnabledChild(popup.getSubElements(), 577 menu, direction); 578 579 if (next != null && next != menu) { 580 MenuElement[] newPath = new MenuElement[len-1]; 581 System.arraycopy(path, 0, newPath, 0, len-2); 582 newPath[len-2] = next; 583 msm.setSelectedPath(newPath); 584 } 585 } 586 } 587 588 } else { 589 MenuElement subs[] = path[len-2].getSubElements(); 591 MenuElement nextChild = 592 findEnabledChild(subs, path[len-1], direction); 593 if (nextChild == null) { 594 nextChild = findEnabledChild(subs, -1, direction); 595 } 596 if (nextChild != null) { 597 path[len-1] = nextChild; 598 msm.setSelectedPath(path); 599 } 600 } 601 } 602 603 private void cancel() { 604 JPopupMenu lastPopup = (JPopupMenu)getLastPopup(); 608 if (lastPopup != null) { 609 lastPopup.putClientProperty("JPopupMenu.firePopupMenuCanceled", Boolean.TRUE); 610 } 611 612 MenuElement path[] = MenuSelectionManager.defaultManager().getSelectedPath(); 613 if(path.length > 4) { 614 MenuElement newPath[] = new MenuElement[path.length - 2]; 615 System.arraycopy(path,0,newPath,0,path.length-2); 616 MenuSelectionManager.defaultManager().setSelectedPath(newPath); 617 } else 618 MenuSelectionManager.defaultManager().clearSelectedPath(); 619 } 620 } 621 622 private static MenuElement nextEnabledChild(MenuElement e[], 623 int fromIndex, int toIndex) { 624 for (int i=fromIndex; i<=toIndex; i++) { 625 if (e[i] != null) { 626 Component comp = e[i].getComponent(); 627 if (comp != null && comp.isEnabled() && comp.isVisible()) { 628 return e[i]; 629 } 630 } 631 } 632 return null; 633 } 634 635 private static MenuElement previousEnabledChild(MenuElement e[], 636 int fromIndex, int toIndex) { 637 for (int i=fromIndex; i>=toIndex; i--) { 638 if (e[i] != null) { 639 Component comp = e[i].getComponent(); 640 if (comp != null && comp.isEnabled() && comp.isVisible()) { 641 return e[i]; 642 } 643 } 644 } 645 return null; 646 } 647 648 static MenuElement findEnabledChild(MenuElement e[], int fromIndex, 649 boolean forward) { 650 MenuElement result = null; 651 if (forward) { 652 result = nextEnabledChild(e, fromIndex+1, e.length-1); 653 if (result == null) result = nextEnabledChild(e, 0, fromIndex-1); 654 } else { 655 result = previousEnabledChild(e, fromIndex-1, 0); 656 if (result == null) result = previousEnabledChild(e, e.length-1, 657 fromIndex+1); 658 } 659 return result; 660 } 661 662 static MenuElement findEnabledChild(MenuElement e[], 663 MenuElement elem, boolean forward) { 664 for (int i=0; i<e.length; i++) { 665 if (e[i] == elem) { 666 return findEnabledChild(e, i, forward); 667 } 668 } 669 return null; 670 } 671 672 private transient static MouseGrabber mouseGrabber = null; 673 674 private static class MouseGrabber implements ChangeListener , 675 AWTEventListener, ComponentListener, WindowListener { 676 677 Window grabbedWindow; 678 MenuElement[] lastPathSelected; 679 680 public MouseGrabber() { 681 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 682 msm.addChangeListener(this); 683 this.lastPathSelected = msm.getSelectedPath(); 684 if(this.lastPathSelected.length != 0) { 685 grabWindow(this.lastPathSelected); 686 } 687 } 688 689 void grabWindow(MenuElement[] newPath) { 690 java.security.AccessController.doPrivileged( 692 new java.security.PrivilegedAction () { 693 public Object run() { 694 Toolkit.getDefaultToolkit() 695 .addAWTEventListener(MouseGrabber.this, 696 AWTEvent.MOUSE_EVENT_MASK | 697 AWTEvent.MOUSE_MOTION_EVENT_MASK | 698 AWTEvent.MOUSE_WHEEL_EVENT_MASK); 699 return null; 700 } 701 } 702 ); 703 704 Component invoker = newPath[0].getComponent(); 705 if (invoker instanceof JPopupMenu) { 706 invoker = ((JPopupMenu)invoker).getInvoker(); 707 } 708 grabbedWindow = invoker instanceof Window ? 709 (Window )invoker : 710 SwingUtilities.getWindowAncestor(invoker); 711 if(grabbedWindow != null) { 712 grabbedWindow.addComponentListener(this); 713 grabbedWindow.addWindowListener(this); 714 } 715 } 716 717 void ungrabWindow() { 718 java.security.AccessController.doPrivileged( 720 new java.security.PrivilegedAction () { 721 public Object run() { 722 Toolkit.getDefaultToolkit() 723 .removeAWTEventListener(MouseGrabber.this); 724 return null; 725 } 726 } 727 ); 728 if(grabbedWindow != null) { 729 grabbedWindow.removeComponentListener(this); 730 grabbedWindow.removeWindowListener(this); 731 grabbedWindow = null; 732 } 733 } 734 735 public void stateChanged(ChangeEvent e) { 736 MenuSelectionManager msm = MenuSelectionManager.defaultManager(); 737 MenuElement[] p = msm.getSelectedPath(); 738 739 if (lastPathSelected.length == 0 && p.length != 0) { 740 grabWindow(p); 741 } 742 743 if (lastPathSelected.length != 0 && p.length == 0) { 744 ungrabWindow(); 745 } 746 747 lastPathSelected = p; 748 } 749 750 public void eventDispatched(AWTEvent ev) { 751 switch (ev.getID()) { 752 case MouseEvent.MOUSE_PRESSED: 753 Component src = (Component )ev.getSource(); 754 if (isInPopup(src) || 755 (src instanceof JMenu && ((JMenu)src).isSelected())) { 756 return; 757 } 758 if (!(src instanceof JComponent) || 759 ! (((JComponent)src).getClientProperty("doNotCancelPopup") 760 == BasicComboBoxUI.HIDE_POPUP_KEY)) { 761 cancelPopupMenu(); 765 boolean consumeEvent = 768 UIManager.getBoolean("PopupMenu.consumeEventOnClose"); 769 if(consumeEvent && !(src instanceof MenuElement)) { 771 ((MouseEvent)ev).consume(); 772 } 773 } 774 break; 775 776 case MouseEvent.MOUSE_RELEASED: 777 src = (Component )ev.getSource(); 778 if(!(src instanceof MenuElement)) { 779 break; 781 } 782 if(src instanceof JMenu || !(src instanceof JMenuItem)) { 783 MenuSelectionManager.defaultManager(). 784 processMouseEvent((MouseEvent)ev); 785 } 786 break; 787 case MouseEvent.MOUSE_DRAGGED: 788 src = (Component )ev.getSource(); 789 if(!(src instanceof MenuElement)) { 790 break; 792 } 793 MenuSelectionManager.defaultManager(). 794 processMouseEvent((MouseEvent)ev); 795 break; 796 case MouseEvent.MOUSE_WHEEL: 797 if (isInPopup((Component )ev.getSource())) { 798 return; 799 } 800 cancelPopupMenu(); 801 break; 802 } 803 } 804 805 boolean isInPopup(Component src) { 806 for (Component c=src; c!=null; c=c.getParent()) { 807 if (c instanceof Applet || c instanceof Window ) { 808 break; 809 } else if (c instanceof JPopupMenu) { 810 return true; 811 } 812 } 813 return false; 814 } 815 816 void cancelPopupMenu() { 817 JPopupMenu firstPopup = (JPopupMenu)getFirstPopup(); 818 List popups = getPopups(); 822 Iterator iter = popups.iterator(); 823 while (iter.hasNext()) { 824 JPopupMenu popup = (JPopupMenu)iter.next(); 825 popup.putClientProperty("JPopupMenu.firePopupMenuCanceled", Boolean.TRUE); 826 } 827 MenuSelectionManager.defaultManager().clearSelectedPath(); 828 } 829 830 public void componentResized(ComponentEvent e) { 831 cancelPopupMenu(); 832 } 833 public void componentMoved(ComponentEvent e) { 834 cancelPopupMenu(); 835 } 836 public void componentShown(ComponentEvent e) { 837 cancelPopupMenu(); 838 } 839 public void componentHidden(ComponentEvent e) { 840 cancelPopupMenu(); 841 } 842 public void windowClosing(WindowEvent e) { 843 cancelPopupMenu(); 844 } 845 public void windowClosed(WindowEvent e) { 846 cancelPopupMenu(); 847 } 848 public void windowIconified(WindowEvent e) { 849 cancelPopupMenu(); 850 } 851 public void windowDeactivated(WindowEvent e) { 852 if(doUnpostPopupOnDeactivation()) { 853 cancelPopupMenu(); 854 } 855 } 856 public void windowOpened(WindowEvent e) {} 857 public void windowDeiconified(WindowEvent e) {} 858 public void windowActivated(WindowEvent e) {} 859 } 860 861 873 private static class MenuKeyboardHelper 874 implements ChangeListener , KeyListener { 875 876 private Component lastFocused = null; 877 private MenuElement[] lastPathSelected = new MenuElement[0]; 878 private JPopupMenu lastPopup; 879 880 private JRootPane invokerRootPane; 881 private ActionMap menuActionMap = getActionMap(); 882 private InputMap menuInputMap; 883 private boolean focusTraversalKeysEnabled; 884 885 891 private boolean receivedKeyPressed = false; 892 893 void removeItems() { 894 if (lastFocused != null) { 895 if(!lastFocused.requestFocusInWindow()) { 896 Window cfw = KeyboardFocusManager 902 .getCurrentKeyboardFocusManager() 903 .getFocusedWindow(); 904 if(cfw != null && 905 "###focusableSwingPopup###".equals(cfw.getName())) { 906 lastFocused.requestFocus(); 907 } 908 909 } 910 lastFocused = null; 911 } 912 if (invokerRootPane != null) { 913 invokerRootPane.removeKeyListener(menuKeyboardHelper); 914 invokerRootPane.setFocusTraversalKeysEnabled(focusTraversalKeysEnabled); 915 removeUIInputMap(invokerRootPane, menuInputMap); 916 removeUIActionMap(invokerRootPane, menuActionMap); 917 invokerRootPane = null; 918 } 919 receivedKeyPressed = false; 920 } 921 922 private FocusListener rootPaneFocusListener = new FocusAdapter() { 923 public void focusGained(FocusEvent ev) { 924 Component opposite = ev.getOppositeComponent(); 925 if (opposite != null) { 926 lastFocused = opposite; 927 } 928 ev.getComponent().removeFocusListener(this); 929 } 930 }; 931 932 936 JPopupMenu getActivePopup(MenuElement[] path) { 937 for (int i=path.length-1; i>=0; i--) { 938 MenuElement elem = path[i]; 939 if (elem instanceof JPopupMenu) { 940 return (JPopupMenu)elem; 941 } 942 } 943 return null; 944 } 945 946 void addUIInputMap(JComponent c, InputMap map) { 947 InputMap lastNonUI = null; 948 InputMap parent = c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); 949 950 while (parent != null && !(parent instanceof UIResource)) { 951 lastNonUI = parent; 952 parent = parent.getParent(); 953 } 954 955 if (lastNonUI == null) { 956 c.setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, map); 957 } else { 958 lastNonUI.setParent(map); 959 } 960 map.setParent(parent); 961 } 962 963 void addUIActionMap(JComponent c, ActionMap map) { 964 ActionMap lastNonUI = null; 965 ActionMap parent = c.getActionMap(); 966 967 while (parent != null && !(parent instanceof UIResource)) { 968 lastNonUI = parent; 969 parent = parent.getParent(); 970 } 971 972 if (lastNonUI == null) { 973 c.setActionMap(map); 974 } else { 975 lastNonUI.setParent(map); 976 } 977 map.setParent(parent); 978 } 979 980 void removeUIInputMap(JComponent c, InputMap map) { 981 InputMap im = null; 982 InputMap parent = c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); 983 984 while (parent != null) { 985 if (parent == map) { 986 if (im == null) { 987 c.setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, 988 map.getParent()); 989 } else { 990 im.setParent(map.getParent()); 991 } 992 break; 993 } 994 im = parent; 995 parent = parent.getParent(); 996 } 997 } 998 999 void removeUIActionMap(JComponent c, ActionMap map) { 1000 ActionMap im = null; 1001 ActionMap parent = c.getActionMap(); 1002 1003 while (parent != null) { 1004 if (parent == map) { 1005 if (im == null) { 1006 c.setActionMap(map.getParent()); 1007 } else { 1008 im.setParent(map.getParent()); 1009 } 1010 break; 1011 } 1012 im = parent; 1013 parent = parent.getParent(); 1014 } 1015 } 1016 1017 public void stateChanged(ChangeEvent ev) { 1018 if (!(UIManager.getLookAndFeel() instanceof BasicLookAndFeel )) { 1019 MenuSelectionManager msm = MenuSelectionManager. 1020 defaultManager(); 1021 msm.removeChangeListener(this); 1022 menuKeyboardHelperInstalled = false; 1023 return; 1024 } 1025 MenuSelectionManager msm = (MenuSelectionManager)ev.getSource(); 1026 MenuElement[] p = msm.getSelectedPath(); 1027 JPopupMenu popup = getActivePopup(p); 1028 if (popup != null && !popup.isFocusable()) { 1029 return; 1031 } 1032 1033 if (lastPathSelected.length != 0 && p.length != 0 ) { 1034 if (!checkInvokerEqual(p[0],lastPathSelected[0])) { 1035 removeItems(); 1036 lastPathSelected = new MenuElement[0]; 1037 } 1038 1039 } 1040 1041 1042 1043 1044 if (lastPathSelected.length == 0 && p.length > 0) { 1045 JComponent invoker; 1047 1048 if (popup == null) { 1049 if (p.length == 2 && p[0] instanceof JMenuBar && 1050 p[1] instanceof JMenu) { 1051 invoker = (JComponent)p[1]; 1053 popup = ((JMenu)invoker).getPopupMenu(); 1054 } else { 1055 return; 1056 } 1057 } else { 1058 Component c = popup.getInvoker(); 1059 if(c instanceof JFrame) { 1060 invoker = ((JFrame)c).getRootPane(); 1061 } else if(c instanceof JApplet) { 1062 invoker = ((JApplet)c).getRootPane(); 1063 } else { 1064 while (!(c instanceof JComponent)) { 1065 if (c == null) { 1066 return; 1067 } 1068 c = c.getParent(); 1069 } 1070 invoker = (JComponent)c; 1071 } 1072 } 1073 1074 lastFocused = KeyboardFocusManager. 1076 getCurrentKeyboardFocusManager().getFocusOwner(); 1077 1078 invokerRootPane = SwingUtilities.getRootPane(invoker); 1081 if (invokerRootPane != null) { 1082 invokerRootPane.addFocusListener(rootPaneFocusListener); 1083 invokerRootPane.requestFocus(true); 1084 invokerRootPane.addKeyListener(menuKeyboardHelper); 1085 focusTraversalKeysEnabled = invokerRootPane. 1086 getFocusTraversalKeysEnabled(); 1087 invokerRootPane.setFocusTraversalKeysEnabled(false); 1088 1089 menuInputMap = getInputMap(popup, invokerRootPane); 1090 addUIInputMap(invokerRootPane, menuInputMap); 1091 addUIActionMap(invokerRootPane, menuActionMap); 1092 } 1093 } else if (lastPathSelected.length != 0 && p.length == 0) { 1094 removeItems(); 1097 } else { 1098 if (popup != lastPopup) { 1099 receivedKeyPressed = false; 1100 } 1101 } 1102 1103 lastPathSelected = p; 1105 lastPopup = popup; 1106 } 1107 1108 public void keyPressed(KeyEvent ev) { 1109 receivedKeyPressed = true; 1110 MenuSelectionManager.defaultManager().processKeyEvent(ev); 1111 } 1112 1113 public void keyReleased(KeyEvent ev) { 1114 if (receivedKeyPressed) { 1115 receivedKeyPressed = false; 1116 MenuSelectionManager.defaultManager().processKeyEvent(ev); 1117 } 1118 } 1119 1120 public void keyTyped(KeyEvent ev) { 1121 if (receivedKeyPressed) { 1122 MenuSelectionManager.defaultManager().processKeyEvent(ev); 1123 } 1124 } 1125 } 1126} 1127 | Popular Tags |