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