Source for javax.swing.JMenu

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