Source for javax.swing.JMenu

   1: /* JMenu.java --
   2:    Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing;
  40: 
  41: import java.awt.Component;
  42: import java.awt.Point;
  43: import java.awt.event.KeyEvent;
  44: import java.awt.event.WindowAdapter;
  45: import java.awt.event.WindowEvent;
  46: import java.beans.PropertyChangeEvent;
  47: import java.beans.PropertyChangeListener;
  48: import java.io.Serializable;
  49: import java.util.EventListener;
  50: 
  51: import javax.accessibility.Accessible;
  52: import javax.accessibility.AccessibleContext;
  53: import javax.accessibility.AccessibleRole;
  54: import javax.accessibility.AccessibleSelection;
  55: import javax.swing.event.MenuEvent;
  56: import javax.swing.event.MenuListener;
  57: import javax.swing.plaf.MenuItemUI;
  58: 
  59: /**
  60:  * This class represents a menu that can be added to a menu bar or
  61:  * can be a submenu in some other menu. When JMenu is selected it
  62:  * displays JPopupMenu containing its menu items.
  63:  *
  64:  * <p>
  65:  * JMenu's fires MenuEvents when this menu's selection changes. If this menu
  66:  * is selected, then fireMenuSelectedEvent() is invoked. In case when menu is
  67:  * deselected or cancelled, then fireMenuDeselectedEvent() or 
  68:  * fireMenuCancelledEvent() is invoked, respectivelly.
  69:  * </p>
  70:  */
  71: public class JMenu extends JMenuItem implements Accessible, MenuElement
  72: {
  73:   private static final long serialVersionUID = 4227225638931828014L;
  74: 
  75:   /** A Popup menu associated with this menu, which pops up when menu is selected */
  76:   private JPopupMenu popupMenu = new JPopupMenu();
  77: 
  78:   /** Whenever menu is selected or deselected the MenuEvent is fired to
  79:      menu's registered listeners. */
  80:   private MenuEvent menuEvent = new MenuEvent(this);
  81: 
  82:   /*Amount of time, in milliseconds, that should pass before popupMenu
  83:     associated with this menu appears or disappers */
  84:   private int delay;
  85: 
  86:   /* PopupListener */
  87:   protected WinListener popupListener;
  88: 
  89:   /** Location at which popup menu associated with this menu will be
  90:      displayed */
  91:   private Point menuLocation;
  92: 
  93:   /**
  94:    * Creates a new JMenu object.
  95:    */
  96:   public JMenu()
  97:   {
  98:     super();
  99:   }
 100: 
 101:   /**
 102:    * Creates a new <code>JMenu</code> with the specified label.
 103:    *
 104:    * @param text label for this menu
 105:    */
 106:   public JMenu(String text)
 107:   {
 108:     super(text);
 109:     popupMenu.setInvoker(this);
 110:   }
 111: 
 112:   /**
 113:    * Creates a new <code>JMenu</code> object.
 114:    *
 115:    * @param action Action that is used to create menu item tha will be
 116:    * added to the menu.
 117:    */
 118:   public JMenu(Action action)
 119:   {
 120:     super(action);
 121:     createActionChangeListener(this);
 122:     popupMenu.setInvoker(this);
 123:   }
 124: 
 125:   /**
 126:    * Creates a new <code>JMenu</code> with specified label and an option
 127:    * for this menu to be tear-off menu.
 128:    *
 129:    * @param text label for this menu
 130:    * @param tearoff true if this menu should be tear-off and false otherwise
 131:    */
 132:   public JMenu(String text, boolean tearoff)
 133:   {
 134:     // FIXME: tearoff not implemented
 135:     this(text);
 136:   }
 137: 
 138:   /**
 139:    * Adds specified menu item to this menu
 140:    *
 141:    * @param item Menu item to add to this menu
 142:    *
 143:    * @return Menu item that was added
 144:    */
 145:   public JMenuItem add(JMenuItem item)
 146:   {
 147:     return popupMenu.add(item);
 148:   }
 149: 
 150:   /**
 151:    * Adds specified component to this menu.
 152:    *
 153:    * @param component Component to add to this menu
 154:    *
 155:    * @return Component that was added
 156:    */
 157:   public Component add(Component component)
 158:   {
 159:     popupMenu.insert(component, -1);
 160:     return component;
 161:   }
 162: 
 163:   /**
 164:    * Adds specified component to this menu at the given index
 165:    *
 166:    * @param component Component to add
 167:    * @param index Position of this menu item in the menu
 168:    *
 169:    * @return Component that was added
 170:    */
 171:   public Component add(Component component, int index)
 172:   {
 173:     return popupMenu.add(component, index);
 174:   }
 175: 
 176:   /**
 177:    * Adds JMenuItem constructed with the specified label to this menu
 178:    *
 179:    * @param text label for the menu item that will be added
 180:    *
 181:    * @return Menu Item that was added to this menu
 182:    */
 183:   public JMenuItem add(String text)
 184:   {
 185:     return popupMenu.add(text);
 186:   }
 187: 
 188:   /**
 189:    * Adds JMenuItem constructed using properties from specified action.
 190:    *
 191:    * @param action action to construct the menu item with
 192:    *
 193:    * @return Menu Item that was added to this menu
 194:    */
 195:   public JMenuItem add(Action action)
 196:   {
 197:     return popupMenu.add(action);
 198:   }
 199: 
 200:   /**
 201:    * Removes given menu item from this menu. Nothing happens if
 202:    * this menu doesn't contain specified menu item.
 203:    *
 204:    * @param item Menu Item which needs to be removed
 205:    */
 206:   public void remove(JMenuItem item)
 207:   {
 208:     popupMenu.remove(item);
 209:   }
 210: 
 211:   /**
 212:    * Removes component at the specified index from this menu
 213:    *
 214:    * @param index Position of the component that needs to be removed in the menu
 215:    */
 216:   public void remove(int index)
 217:   {
 218:     popupMenu.remove(index);
 219:   }
 220: 
 221:   /**
 222:    * Removes given component from this menu.
 223:    *
 224:    * @param component Component to remove
 225:    */
 226:   public void remove(Component component)
 227:   {
 228:     int index = popupMenu.getComponentIndex(component);
 229:     popupMenu.remove(index);
 230:   }
 231: 
 232:   /**
 233:    * Removes all menu items from the menu
 234:    */
 235:   public void removeAll()
 236:   {
 237:     popupMenu.removeAll();
 238:   }
 239: 
 240:   /**
 241:    * Creates JMenuItem with the specified text and inserts it in the
 242:    * at the specified index
 243:    *
 244:    * @param text label for the new menu item
 245:    * @param index index at which to insert newly created menu item.
 246:    */
 247:   public void insert(String text, int index)
 248:   {
 249:     this.insert(new JMenuItem(text), index);
 250:   }
 251: 
 252:   /**
 253:    * Creates JMenuItem with the specified text and inserts it in the
 254:    * at the specified index. IllegalArgumentException is thrown
 255:    * if index is less than 0
 256:    *
 257:    * @param item menu item to insert
 258:    * @param index index at which to insert menu item.
 259:    * @return Menu item that was added to the menu
 260:    */
 261:   public JMenuItem insert(JMenuItem item, int index)
 262:   {
 263:     if (index < 0)
 264:       throw new IllegalArgumentException("index less than zero");
 265: 
 266:     popupMenu.insert(item, index);
 267:     return item;
 268:   }
 269: 
 270:   /**
 271:    * Creates JMenuItem with the associated action and inserts it to the menu
 272:    * at the specified index. IllegalArgumentException is thrown
 273:    * if index is less than 0
 274:    *
 275:    * @param action Action for the new menu item
 276:    * @param index index at which to insert newly created menu item.
 277:    * @return Menu item that was added to the menu
 278:    */
 279:   public JMenuItem insert(Action action, int index)
 280:   {
 281:     JMenuItem item = new JMenuItem(action);
 282:     this.insert(item, index);
 283: 
 284:     return item;
 285:   }
 286: 
 287:   /**
 288:    * This method sets this menuItem's UI to the UIManager's default for the
 289:    * current look and feel.
 290:    */
 291:   public void updateUI()
 292:   {
 293:     super.setUI((MenuItemUI) UIManager.getUI(this));
 294:     invalidate();
 295:   }
 296: 
 297:   /**
 298:    * This method returns a name to identify which look and feel class will be
 299:    * the UI delegate for the menu.
 300:    *
 301:    * @return The Look and Feel classID. "MenuUI"
 302:    */
 303:   public String getUIClassID()
 304:   {
 305:     return "MenuUI";
 306:   }
 307: 
 308:   /**
 309:    * Sets model for this menu.
 310:    *
 311:    * @param model model to set
 312:    */
 313:   public void setModel(ButtonModel model)
 314:   {
 315:     super.setModel(model);
 316:   }
 317: 
 318:   /**
 319:    * Returns true if the menu is selected and false otherwise
 320:    *
 321:    * @return true if the menu is selected and false otherwise
 322:    */
 323:   public boolean isSelected()
 324:   {
 325:     return super.isSelected();
 326:   }
 327: 
 328:   /**
 329:    * A helper method to handle setSelected calls from both mouse events and 
 330:    * direct calls to setSelected.  Direct calls shouldn't expand the popup
 331:    * menu and should select the JMenu even if it is disabled.  Mouse events
 332:    * only select the JMenu if it is enabled and should expand the popup menu
 333:    * associated with this JMenu.
 334:    * @param selected whether or not the JMenu was selected
 335:    * @param menuEnabled whether or not selecting the menu is "enabled".  This
 336:    * is always true for direct calls, and is set to isEnabled() for mouse 
 337:    * based calls.
 338:    * @param showMenu whether or not to show the popup menu
 339:    */
 340:   private void setSelectedHelper(boolean selected, boolean menuEnabled, boolean showMenu)
 341:   {
 342:     // If menu is selected and enabled, activates the menu and 
 343:     // displays associated popup.    
 344:     if (selected && menuEnabled)
 345:       {
 346:     super.setArmed(true);
 347:     super.setSelected(true);
 348: 
 349:         // FIXME: The popup menu should be shown on the screen after certain
 350:         // number of seconds pass. The 'delay' property of this menu indicates
 351:         // this amount of seconds. 'delay' property is 0 by default.
 352:     if (isShowing())
 353:       {
 354:         fireMenuSelected();
 355:             
 356:         int x = 0;
 357:         int y = 0;
 358:             if (showMenu)
 359:               if (menuLocation == null)
 360:                 {
 361:                   // Calculate correct position of the popup. Note that location of the popup 
 362:                   // passed to show() should be relative to the popup's invoker
 363:                   if (isTopLevelMenu())
 364:                     y = this.getHeight();
 365:                   else
 366:                     x = this.getWidth();
 367:                   getPopupMenu().show(this, x, y);
 368:                 }
 369:               else
 370:                 {
 371:                   getPopupMenu().show(this, menuLocation.x, menuLocation.y);
 372:                 }
 373:       }
 374:       }
 375:     
 376:     else
 377:       {
 378:     super.setSelected(false);
 379:     super.setArmed(false);
 380:     fireMenuDeselected();
 381:     popupMenu.setVisible(false);
 382:       }
 383:   }
 384: 
 385:   /**
 386:    * Changes this menu selected state if selected is true and false otherwise
 387:    * This method fires menuEvents to menu's registered listeners.
 388:    *
 389:    * @param selected true if the menu should be selected and false otherwise
 390:    */
 391:   public void setSelected(boolean selected)
 392:   {
 393:     setSelectedHelper(selected, true, false); 
 394:   }
 395: 
 396:   /**
 397:    * Checks if PopupMenu associated with this menu is visible
 398:    *
 399:    * @return true if the popup associated with this menu is currently visible
 400:    * on the screen and false otherwise.
 401:    */
 402:   public boolean isPopupMenuVisible()
 403:   {
 404:     return popupMenu.isVisible();
 405:   }
 406: 
 407:   /**
 408:    * Sets popup menu visibility
 409:    *
 410:    * @param popup true if popup should be visible and false otherwise
 411:    */
 412:   public void setPopupMenuVisible(boolean popup)
 413:   {
 414:     if (getModel().isEnabled())
 415:       popupMenu.setVisible(popup);
 416:   }
 417: 
 418:   /**
 419:    * Returns origin point of the popup menu
 420:    *
 421:    * @return Point containing
 422:    */
 423:   protected Point getPopupMenuOrigin()
 424:   {
 425:     // if menu in the menu bar
 426:     if (isTopLevelMenu())
 427:       return new Point(0, this.getHeight());
 428: 
 429:     // if submenu            
 430:     return new Point(this.getWidth(), 0);
 431:   }
 432: 
 433:   /**
 434:    * Returns delay property.
 435:    *
 436:    * @return delay property, indicating number of milliseconds before
 437:    * popup menu associated with the menu appears or disappears after
 438:    * menu was selected or deselected respectively
 439:    */
 440:   public int getDelay()
 441:   {
 442:     return delay;
 443:   }
 444: 
 445:   /**
 446:    * Sets delay property for this menu. If given time for the delay
 447:    * property is negative, then IllegalArgumentException is thrown
 448:    *
 449:    * @param delay number of milliseconds before
 450:    * popup menu associated with the menu appears or disappears after
 451:    * menu was selected or deselected respectively
 452:    */
 453:   public void setDelay(int delay)
 454:   {
 455:     if (delay < 0)
 456:       throw new IllegalArgumentException("delay less than 0");
 457:     this.delay = delay;
 458:   }
 459: 
 460:   /**
 461:    * Sets location at which popup menu should be displayed
 462:    * The location given is relative to this menu item
 463:    *
 464:    * @param x x-coordinate of the menu location
 465:    * @param y y-coordinate of the menu location
 466:    */
 467:   public void setMenuLocation(int x, int y)
 468:   {
 469:     menuLocation = new Point(x, y);
 470:   }
 471: 
 472:   /**
 473:    * Creates and returns JMenuItem associated with the given action
 474:    *
 475:    * @param action Action to use for creation of JMenuItem
 476:    *
 477:    * @return JMenuItem that was creted with given action
 478:    */
 479:   protected JMenuItem createActionComponent(Action action)
 480:   {
 481:     return new JMenuItem(action);
 482:   }
 483: 
 484:   /**
 485:    * Creates ActionChangeListener to listen for PropertyChangeEvents occuring
 486:    * in the action that is associated with this menu
 487:    *
 488:    * @param item menu that contains action to listen to
 489:    *
 490:    * @return The PropertyChangeListener
 491:    */
 492:   protected PropertyChangeListener createActionChangeListener(JMenuItem item)
 493:   {
 494:     return new ActionChangedListener(item);
 495:   }
 496: 
 497:   /**
 498:    * Adds separator to the end of the menu items in the menu.
 499:    */
 500:   public void addSeparator()
 501:   {
 502:     getPopupMenu().addSeparator();
 503:   }
 504: 
 505:   /**
 506:    * Inserts separator in the menu at the specified index.
 507:    *
 508:    * @param index Index at which separator should be inserted
 509:    */
 510:   public void insertSeparator(int index)
 511:   {
 512:     if (index < 0)
 513:       throw new IllegalArgumentException("index less than 0");
 514: 
 515:     getPopupMenu().insert(new JPopupMenu.Separator(), index);
 516:   }
 517: 
 518:   /**
 519:    * Returns menu item located at the specified index in the menu
 520:    *
 521:    * @param index Index at which to look for the menu item
 522:    *
 523:    * @return menu item located at the specified index in the menu
 524:    */
 525:   public JMenuItem getItem(int index)
 526:   {
 527:     if (index < 0)
 528:       throw new IllegalArgumentException("index less than 0");
 529: 
 530:     Component c = popupMenu.getComponentAtIndex(index);
 531: 
 532:     if (c instanceof JMenuItem)
 533:       return (JMenuItem) c;
 534:     else
 535:       return null;
 536:   }
 537: 
 538:   /**
 539:    * Returns number of items in the menu including separators.
 540:    *
 541:    * @return number of items in the menu
 542:    *
 543:    * @see #getMenuComponentCount()
 544:    */
 545:   public int getItemCount()
 546:   {
 547:     return getMenuComponentCount();
 548:   }
 549: 
 550:   /**
 551:    * Checks if this menu is a tear-off menu.
 552:    *
 553:    * @return true if this menu is a tear-off menu and false otherwise
 554:    */
 555:   public boolean isTearOff()
 556:   {
 557:     // NOT YET IMPLEMENTED 
 558:     return false;
 559:   }
 560: 
 561:   /**
 562:    * Returns number of menu components in this menu
 563:    *
 564:    * @return number of menu components in this menu
 565:    */
 566:   public int getMenuComponentCount()
 567:   {
 568:     return popupMenu.getComponentCount();
 569:   }
 570: 
 571:   /**
 572:    * Returns menu component located at the givent index
 573:    * in the menu
 574:    *
 575:    * @param index index at which to get the menu component in the menu
 576:    *
 577:    * @return Menu Component located in the menu at the specified index
 578:    */
 579:   public Component getMenuComponent(int index)
 580:   {
 581:     return (Component) popupMenu.getComponentAtIndex(index);
 582:   }
 583: 
 584:   /**
 585:    * Return components belonging to this menu
 586:    *
 587:    * @return components belonging to this menu
 588:    */
 589:   public Component[] getMenuComponents()
 590:   {
 591:     return popupMenu.getComponents();
 592:   }
 593: 
 594:   /**
 595:    * Checks if this menu is a top level menu. The menu is top
 596:    * level menu if it is inside the menu bar. While if the menu
 597:    * inside some other menu, it is considered to be a pull-right menu.
 598:    *
 599:    * @return true if this menu is top level menu, and false otherwise
 600:    */
 601:   public boolean isTopLevelMenu()
 602:   {
 603:     return getParent() instanceof JMenuBar;
 604:   }
 605: 
 606:   /**
 607:    * Checks if given component exists in this menu. The submenus of
 608:    * this menu are checked as well
 609:    *
 610:    * @param component Component to look for
 611:    *
 612:    * @return true if the given component exists in this menu, and false otherwise
 613:    */
 614:   public boolean isMenuComponent(Component component)
 615:   {
 616:     return false;
 617:   }
 618: 
 619:   /**
 620:    * Returns popup menu associated with the menu.
 621:    *
 622:    * @return popup menu associated with the menu.
 623:    */
 624:   public JPopupMenu getPopupMenu()
 625:   {
 626:     return popupMenu;
 627:   }
 628: 
 629:   /**
 630:    * Adds MenuListener to the menu
 631:    *
 632:    * @param listener MenuListener to add
 633:    */
 634:   public void addMenuListener(MenuListener listener)
 635:   {
 636:     listenerList.add(MenuListener.class, listener);
 637:   }
 638: 
 639:   /**
 640:    * Removes MenuListener from the menu
 641:    *
 642:    * @param listener MenuListener to remove
 643:    */
 644:   public void removeMenuListener(MenuListener listener)
 645:   {
 646:     listenerList.remove(MenuListener.class, listener);
 647:   }
 648: 
 649:   /**
 650:    * Returns all registered <code>MenuListener</code> objects.
 651:    *
 652:    * @return an array of listeners
 653:    * 
 654:    * @since 1.4
 655:    */
 656:   public MenuListener[] getMenuListeners()
 657:   {
 658:     return (MenuListener[]) listenerList.getListeners(MenuListener.class);
 659:   }
 660: 
 661:   /**
 662:    * This method fires MenuEvents to all menu's MenuListeners. In this case
 663:    * menuSelected() method of MenuListeners is called to indicated that the menu
 664:    * was selected.
 665:    */
 666:   protected void fireMenuSelected()
 667:   {
 668:     MenuListener[] listeners = getMenuListeners();
 669: 
 670:     for (int index = 0; index < listeners.length; ++index)
 671:       listeners[index].menuSelected(menuEvent);
 672:   }
 673: 
 674:   /**
 675:    * This method fires MenuEvents to all menu's MenuListeners. In this case
 676:    * menuDeselected() method of MenuListeners is called to indicated that the menu
 677:    * was deselected.
 678:    */
 679:   protected void fireMenuDeselected()
 680:   {
 681:     EventListener[] ll = listenerList.getListeners(MenuListener.class);
 682: 
 683:     for (int i = 0; i < ll.length; i++)
 684:       ((MenuListener) ll[i]).menuDeselected(menuEvent);
 685:   }
 686: 
 687:   /**
 688:    * This method fires MenuEvents to all menu's MenuListeners. In this case
 689:    * menuSelected() method of MenuListeners is called to indicated that the menu
 690:    * was cancelled. The menu is cancelled when it's popup menu is close without selection.
 691:    */
 692:   protected void fireMenuCanceled()
 693:   {
 694:     EventListener[] ll = listenerList.getListeners(MenuListener.class);
 695: 
 696:     for (int i = 0; i < ll.length; i++)
 697:       ((MenuListener) ll[i]).menuCanceled(menuEvent);
 698:   }
 699: 
 700:   /**
 701:    * Creates WinListener that listens to the menu;s popup menu.
 702:    *
 703:    * @param popup JPopupMenu to listen to
 704:    *
 705:    * @return The WinListener
 706:    */
 707:   protected WinListener createWinListener(JPopupMenu popup)
 708:   {
 709:     return new WinListener(popup);
 710:   }
 711: 
 712:   /**
 713:    * Method of the MenuElementInterface. It reacts to the selection
 714:    * changes in the menu. If this menu was selected, then it
 715:    * displayes popup menu associated with it and if this menu was
 716:    * deselected it hides the popup menu.
 717:    *
 718:    * @param changed true if the menu was selected and false otherwise
 719:    */
 720:   public void menuSelectionChanged(boolean changed)
 721:   {
 722:     // if this menu selection is true, then activate this menu and 
 723:     // display popup associated with this menu
 724:     setSelectedHelper(changed, isEnabled(), true);
 725:   }
 726: 
 727:   /**
 728:    * Method of MenuElement interface. Returns sub components of
 729:    * this menu.
 730:    *
 731:    * @return array containing popupMenu that is associated with this menu
 732:    */
 733:   public MenuElement[] getSubElements()
 734:   {
 735:     return new MenuElement[] { popupMenu };
 736:   }
 737: 
 738:   /**
 739:    * @return Returns reference to itself
 740:    */
 741:   public Component getComponent()
 742:   {
 743:     return this;
 744:   }
 745: 
 746:   /**
 747:    * This method is overriden with empty implementation, s.t the
 748:    * accelerator couldn't be set for the menu. The mnemonic should
 749:    * be used for the menu instead.
 750:    *
 751:    * @param keystroke accelerator for this menu
 752:    */
 753:   public void setAccelerator(KeyStroke keystroke)
 754:   {
 755:     throw new Error("setAccelerator() is not defined for JMenu.  Use setMnemonic() instead.");
 756:   }
 757: 
 758:   /**
 759:    * This method process KeyEvent occuring when the menu is visible
 760:    *
 761:    * @param event The KeyEvent
 762:    */
 763:   protected void processKeyEvent(KeyEvent event)
 764:   {
 765:     // TODO: Implement this properly.
 766:   }
 767: 
 768:   /**
 769:    * Programatically performs click
 770:    *
 771:    * @param time Number of milliseconds for which this menu stays pressed
 772:    */
 773:   public void doClick(int time)
 774:   {
 775:     getModel().setArmed(true);
 776:     getModel().setPressed(true);
 777:     try
 778:       {
 779:     java.lang.Thread.sleep(time);
 780:       }
 781:     catch (java.lang.InterruptedException e)
 782:       {
 783:     // probably harmless
 784:       }
 785: 
 786:     getModel().setPressed(false);
 787:     getModel().setArmed(false);
 788:     popupMenu.show(this, this.getWidth(), 0);
 789:   }
 790: 
 791:   /**
 792:    * A string that describes this JMenu. Normally only used
 793:    * for debugging.
 794:    *
 795:    * @return A string describing this JMenu
 796:    */
 797:   protected String paramString()
 798:   {
 799:     return super.paramString();
 800:   }
 801: 
 802:   public AccessibleContext getAccessibleContext()
 803:   {
 804:     if (accessibleContext == null)
 805:       accessibleContext = new AccessibleJMenu();
 806: 
 807:     return accessibleContext;
 808:   }
 809: 
 810:   // FIXME: This inner class is a complete stub and needs to be implemented.
 811:   protected class AccessibleJMenu extends AccessibleJMenuItem
 812:     implements AccessibleSelection
 813:   {
 814:     private static final long serialVersionUID = -8131864021059524309L;
 815: 
 816:     protected AccessibleJMenu()
 817:     {
 818:       // Nothing to do here.
 819:     }
 820: 
 821:     public int getAccessibleChildrenCount()
 822:     {
 823:       return 0;
 824:     }
 825: 
 826:     public Accessible getAccessibleChild(int value0)
 827:     {
 828:       return null;
 829:     }
 830: 
 831:     public AccessibleSelection getAccessibleSelection()
 832:     {
 833:       return null;
 834:     }
 835: 
 836:     public Accessible getAccessibleSelection(int value0)
 837:     {
 838:       return null;
 839:     }
 840: 
 841:     public boolean isAccessibleChildSelected(int value0)
 842:     {
 843:       return false;
 844:     }
 845: 
 846:     public AccessibleRole getAccessibleRole()
 847:     {
 848:       return AccessibleRole.MENU;
 849:     }
 850: 
 851:     public int getAccessibleSelectionCount()
 852:     {
 853:       return 0;
 854:     }
 855: 
 856:     public void addAccessibleSelection(int value0)
 857:     {
 858:       // TODO: Implement this properly.
 859:     }
 860: 
 861:     public void removeAccessibleSelection(int value0)
 862:     {
 863:       // TODO: Implement this properly.
 864:     }
 865: 
 866:     public void clearAccessibleSelection()
 867:     {
 868:       // TODO: Implement this properly.
 869:     }
 870: 
 871:     public void selectAllAccessibleSelection()
 872:     {
 873:       // TODO: Implement this properly.
 874:     }
 875:   }
 876: 
 877:   protected class WinListener extends WindowAdapter implements Serializable
 878:   {
 879:     private static final long serialVersionUID = -6415815570638474823L;
 880: 
 881:     /**
 882:      * Creates a new <code>WinListener</code>.
 883:      *
 884:      * @param popup the popup menu which is observed
 885:      */
 886:     public WinListener(JPopupMenu popup)
 887:     {
 888:       // TODO: What should we do with the popup argument?
 889:     }
 890: 
 891:     /**
 892:      * Receives notification when the popup menu is closing and deselects
 893:      * the menu.
 894:      *
 895:      * @param event the window event
 896:      */
 897:     public void windowClosing(WindowEvent event)
 898:     {
 899:       setSelected(false);
 900:     }
 901:   }
 902: 
 903:   /**
 904:    * This class listens to PropertyChangeEvents occuring in menu's action
 905:    */
 906:   protected class ActionChangedListener implements PropertyChangeListener
 907:   {
 908:     /** menu item associated with the action */
 909:     private JMenuItem menuItem;
 910: 
 911:     /** Creates new ActionChangedListener and adds it to menuItem's action */
 912:     public ActionChangedListener(JMenuItem menuItem)
 913:     {
 914:       this.menuItem = menuItem;
 915: 
 916:       Action a = menuItem.getAction();
 917:       if (a != null)
 918:     a.addPropertyChangeListener(this);
 919:     }
 920: 
 921:     /**This method is invoked when some change occures in menuItem's action*/
 922:     public void propertyChange(PropertyChangeEvent evt)
 923:     {
 924:       // FIXME: Need to implement
 925:     }
 926:   }
 927: 
 928: }