rev 47711 : Fixed JDK-8178430: JMenu in GridBagLayout flickers when label text shows "..."
and is updated.
JDK-8178430: Fixed following issues with the test:
1. Throw exception in case the menu bar size is not proper.
2. Run the test for about 10 seconds, and then automatically
close the window.
3. Moved the fix from BasicMenuItemUI.java to BasicMenuUI.java
as per Sergey's suggestion.
4. Fixed the test case to correct the access to UI elements in EDT. Also, now made
sure that the main thread won't exit until the test is complete.
5.Removed unnecessary space in BasicMenuItemUI.java
6. Removed unnecessary import.
7. Moved the declaration of member variables into the constructor scope.
8. Fixed the test case to update/access all the swing components inside
SwingUtilities->invokeLater.
9. Modified the fix as suggested by Sergey.

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