Source for javax.swing.JMenuItem

   1: /* JMenuItem.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 java.awt.Component;
  42: import java.awt.event.InputEvent;
  43: import java.awt.event.KeyEvent;
  44: import java.awt.event.MouseEvent;
  45: import java.beans.PropertyChangeEvent;
  46: import java.beans.PropertyChangeListener;
  47: import java.util.EventListener;
  48: 
  49: import javax.accessibility.Accessible;
  50: import javax.accessibility.AccessibleContext;
  51: import javax.accessibility.AccessibleRole;
  52: import javax.accessibility.AccessibleState;
  53: import javax.swing.event.ChangeEvent;
  54: import javax.swing.event.ChangeListener;
  55: import javax.swing.event.MenuDragMouseEvent;
  56: import javax.swing.event.MenuDragMouseListener;
  57: import javax.swing.event.MenuKeyEvent;
  58: import javax.swing.event.MenuKeyListener;
  59: import javax.swing.plaf.MenuItemUI;
  60: 
  61: /**
  62:  * JMenuItem represents element in the menu. It inherits most of
  63:  * its functionality from AbstractButton, however its behavior somewhat
  64:  * varies from it. JMenuItem fire different kinds of events.
  65:  * PropertyChangeEvents are fired when menuItems properties are modified;
  66:  * ChangeEvents are fired when menuItem's state changes and actionEvents are
  67:  * fired when menu item is selected. In addition to this events menuItem also
  68:  * fire MenuDragMouseEvent and MenuKeyEvents when mouse is dragged over
  69:  * the menu item or associated key with menu item is invoked respectively.
  70:  */
  71: public class JMenuItem extends AbstractButton implements Accessible,
  72:                                                          MenuElement
  73: {
  74:   private static final long serialVersionUID = -1681004643499461044L;
  75: 
  76:   /** Combination of keyboard keys that can be used to activate this menu item */
  77:   private KeyStroke accelerator;
  78: 
  79:   /**
  80:    * Creates a new JMenuItem object.
  81:    */
  82:   public JMenuItem()
  83:   {
  84:     super();
  85:     init(null, null);
  86:   }
  87: 
  88:   /**
  89:    * Creates a new JMenuItem with the given icon.
  90:    *
  91:    * @param icon Icon that will be displayed on the menu item
  92:    */
  93:   public JMenuItem(Icon icon)
  94:   {
  95:     // FIXME: The requestedFocusEnabled property should
  96:     // be set to false, when only icon is set for menu item.
  97:     super();
  98:     init(null, icon);
  99:   }
 100: 
 101:   /**
 102:    * Creates a new JMenuItem with the given label.
 103:    *
 104:    * @param text label for the menu item
 105:    */
 106:   public JMenuItem(String text)
 107:   {
 108:     this(text, null);
 109:   }
 110: 
 111:   /**
 112:    * Creates a new JMenuItem associated with the specified action.
 113:    *
 114:    * @param action action for this menu item
 115:    */
 116:   public JMenuItem(Action action)
 117:   {
 118:     super();
 119:     super.setAction(action);
 120:     init(null, null);
 121:     if (action != null)
 122:       {
 123:     String name = (String) action.getValue(Action.NAME);
 124:     if (name != null)
 125:           setName(name);
 126: 
 127:     KeyStroke accel = (KeyStroke) action.getValue(Action.ACCELERATOR_KEY);
 128:     if (accel != null)
 129:           setAccelerator(accel);
 130: 
 131:     Integer mnemonic = (Integer) action.getValue(Action.MNEMONIC_KEY);
 132:     if (mnemonic != null)
 133:           setMnemonic(mnemonic.intValue());
 134: 
 135:     String command = (String) action.getValue(Action.ACTION_COMMAND_KEY);
 136:     if (command != null)
 137:           setActionCommand(command);
 138:       }
 139:   }
 140: 
 141:   /**
 142:    * Creates a new JMenuItem with specified text and icon.
 143:    * Text is displayed to the left of icon by default.
 144:    *
 145:    * @param text label for this menu item
 146:    * @param icon icon that will be displayed on this menu item
 147:    */
 148:   public JMenuItem(String text, Icon icon)
 149:   {
 150:     super();
 151:     init(text, icon);
 152:   }
 153: 
 154:   /**
 155:    * Creates a new JMenuItem object.
 156:    *
 157:    * @param text label for this menu item
 158:    * @param mnemonic - Single key that can be used with a
 159:    * look-and-feel meta key to activate this menu item. However
 160:    * menu item should be visible on the screen when mnemonic is used.
 161:    */
 162:   public JMenuItem(String text, int mnemonic)
 163:   {
 164:     this(text, null);
 165:     setMnemonic(mnemonic);
 166:   }
 167: 
 168:   /**
 169:    * Initializes this menu item
 170:    *
 171:    * @param text label for this menu item
 172:    * @param icon icon to be displayed for this menu item
 173:    */
 174:   protected void init(String text, Icon icon)
 175:   {
 176:     super.init(text, icon);
 177:     setModel(new DefaultButtonModel());
 178: 
 179:     // Initializes properties for this menu item, that are different
 180:     // from Abstract button properties. 
 181:     /* NOTE: According to java specifications paint_border should be set to false,
 182:       since menu item should not have a border. However running few java programs
 183:       it seems that menu items and menues can have a border. Commenting
 184:       out statement below for now. */
 185:     //borderPainted = false;
 186:     focusPainted = false;
 187:     horizontalAlignment = JButton.LEADING;
 188:     horizontalTextPosition = JButton.TRAILING;
 189:   }
 190: 
 191:   /**
 192:    * Set the "UI" property of the menu item, which is a look and feel class
 193:    * responsible for handling menuItem's input events and painting it.
 194:    *
 195:    * @param ui The new "UI" property
 196:    */
 197:   public void setUI(MenuItemUI ui)
 198:   {
 199:     super.setUI(ui);
 200:   }
 201:   
 202:   /**
 203:    * This method sets this menuItem's UI to the UIManager's default for the
 204:    * current look and feel.
 205:    */
 206:   public void updateUI()
 207:   {
 208:     setUI((MenuItemUI) UIManager.getUI(this));
 209:   }
 210: 
 211:   /**
 212:    * This method returns a name to identify which look and feel class will be
 213:    * the UI delegate for the menuItem.
 214:    *
 215:    * @return The Look and Feel classID. "MenuItemUI"
 216:    */
 217:   public String getUIClassID()
 218:   {
 219:     return "MenuItemUI";
 220:   }
 221: 
 222:   /**
 223:    * Returns true if button's model is armed and false otherwise. The
 224:    * button model is armed if menu item has focus or it is selected.
 225:    *
 226:    * @return $boolean$ true if button's model is armed and false otherwise
 227:    */
 228:   public boolean isArmed()
 229:   {
 230:     return getModel().isArmed();
 231:   }
 232: 
 233:   /**
 234:    * Sets menuItem's "ARMED" property
 235:    *
 236:    * @param armed DOCUMENT ME!
 237:    */
 238:   public void setArmed(boolean armed)
 239:   {
 240:     getModel().setArmed(armed);
 241:   }
 242: 
 243:   /**
 244:    * Enable or disable menu item. When menu item is disabled,
 245:    * its text and icon are grayed out if they exist.
 246:    *
 247:    * @param enabled if true enable menu item, and disable otherwise.
 248:    */
 249:   public void setEnabled(boolean enabled)
 250:   {
 251:     super.setEnabled(enabled);
 252:   }
 253: 
 254:   /**
 255:    * Return accelerator for this menu item.
 256:    *
 257:    * @return $KeyStroke$ accelerator for this menu item.
 258:    */
 259:   public KeyStroke getAccelerator()
 260:   {
 261:     return accelerator;
 262:   }
 263: 
 264:   /**
 265:    * Sets the key combination which invokes the menu item's action 
 266:    * listeners without navigating the menu hierarchy. Note that when the 
 267:    * keyboard accelerator is typed, it will work whether or not the 
 268:    * menu is currently displayed.
 269:    * 
 270:    * @param keystroke accelerator for this menu item.
 271:    */
 272:   public void setAccelerator(KeyStroke keystroke)
 273:   {
 274:     KeyStroke old = this.accelerator;
 275:     this.accelerator = keystroke;
 276:     firePropertyChange ("accelerator", old, keystroke);
 277:   }
 278: 
 279:   /**
 280:    * Configures menu items' properties from properties of the specified action.
 281:    * This method overrides configurePropertiesFromAction from AbstractButton
 282:    * to also set accelerator property.
 283:    *
 284:    * @param action action to configure properties from
 285:    */
 286:   protected void configurePropertiesFromAction(Action action)
 287:   {
 288:     super.configurePropertiesFromAction(action);
 289: 
 290:     if (! (this instanceof JMenu) && action != null)
 291:       {
 292:         setAccelerator((KeyStroke) (action.getValue(Action.ACCELERATOR_KEY)));
 293:         if (accelerator != null)
 294:           super.registerKeyboardAction(action, accelerator, 
 295:                                        JComponent.WHEN_IN_FOCUSED_WINDOW);
 296:       }
 297:   }
 298: 
 299:   /**
 300:    * Creates PropertyChangeListener to listen for the changes in action
 301:    * properties.
 302:    *
 303:    * @param action action to listen to for property changes
 304:    *
 305:    * @return $PropertyChangeListener$ Listener that listens to changes in
 306:    * action properties.
 307:    */
 308:   protected PropertyChangeListener createActionPropertyChangeListener(Action action)
 309:   {
 310:     return new PropertyChangeListener()
 311:       {
 312:     public void propertyChange(PropertyChangeEvent e)
 313:     {
 314:       Action act = (Action) (e.getSource());
 315:       configurePropertiesFromAction(act);
 316:     }
 317:       };
 318:   }
 319: 
 320:   /**
 321:    * Process mouse events forwarded from MenuSelectionManager.
 322:    *
 323:    * @param event event forwarded from MenuSelectionManager
 324:    * @param path path to the menu element from which event was generated
 325:    * @param manager MenuSelectionManager for the current menu hierarchy
 326:    */
 327:   public void processMouseEvent(MouseEvent event, MenuElement[] path,
 328:                                 MenuSelectionManager manager)
 329:   {
 330:     // Fire MenuDragMouseEvents if mouse is being dragged.
 331:     boolean dragged
 332:       = (event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0;
 333:     if (dragged)
 334:       processMenuDragMouseEvent(createMenuDragMouseEvent(event, path, manager));
 335: 
 336:     switch (event.getID())
 337:       {
 338:       case MouseEvent.MOUSE_CLICKED:
 339:     break;
 340:       case MouseEvent.MOUSE_ENTERED:
 341:     if (isRolloverEnabled())
 342:       model.setRollover(true);
 343:     break;
 344:       case MouseEvent.MOUSE_EXITED:
 345:     if (isRolloverEnabled())
 346:       model.setRollover(false);
 347: 
 348:     // for JMenu last element on the path is its popupMenu.
 349:     // JMenu shouldn't me disarmed.    
 350:     if (! (path[path.length - 1] instanceof JPopupMenu) && ! dragged)
 351:       setArmed(false);
 352:     break;
 353:       case MouseEvent.MOUSE_PRESSED:
 354:     if ((event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0)
 355:       {
 356:         model.setArmed(true);
 357:         model.setPressed(true);
 358:       }
 359:     break;
 360:       case MouseEvent.MOUSE_RELEASED:
 361:     break;
 362:       case MouseEvent.MOUSE_MOVED:
 363:     break;
 364:       case MouseEvent.MOUSE_DRAGGED:
 365:     break;
 366:       }
 367:   }
 368: 
 369:   /**
 370:    * Creates MenuDragMouseEvent.
 371:    *
 372:    * @param event MouseEvent that occured while mouse was pressed.
 373:    * @param path Path the the menu element where the dragging event was
 374:    *        originated
 375:    * @param manager MenuSelectionManager for the current menu hierarchy.
 376:    *
 377:    * @return new MenuDragMouseEvent
 378:    */
 379:   private MenuDragMouseEvent createMenuDragMouseEvent(MouseEvent event,
 380:                                                       MenuElement[] path,
 381:                                                       MenuSelectionManager manager)
 382:   {
 383:     return new MenuDragMouseEvent((Component) event.getSource(),
 384:                                   event.getID(), event.getWhen(),
 385:                                   event.getModifiers(), event.getX(),
 386:                                   event.getY(), event.getClickCount(),
 387:                                   event.isPopupTrigger(), path, manager);
 388:   }
 389: 
 390:   /**
 391:    * Process key events forwarded from MenuSelectionManager.
 392:    *
 393:    * @param event event forwarded from MenuSelectionManager
 394:    * @param path path to the menu element from which event was generated
 395:    * @param manager MenuSelectionManager for the current menu hierarchy
 396:    */
 397:   public void processKeyEvent(KeyEvent event, MenuElement[] path,
 398:                               MenuSelectionManager manager)
 399:   {
 400:     MenuKeyEvent e = new MenuKeyEvent(event.getComponent(), event.getID(),
 401:                                       event.getWhen(), event.getModifiers(),
 402:                                       event.getKeyCode(), event.getKeyChar(),
 403:                                       path, manager);
 404:     processMenuKeyEvent(e);
 405: 
 406:     // Consume original key event, if the menu key event has been consumed.
 407:     if (e.isConsumed())
 408:       event.consume();
 409:   }
 410: 
 411:   /**
 412:    * This method fires MenuDragMouseEvents to registered listeners.
 413:    * Different types of MenuDragMouseEvents are fired depending
 414:    * on the observed mouse event.
 415:    *
 416:    * @param event Mouse
 417:    */
 418:   public void processMenuDragMouseEvent(MenuDragMouseEvent event)
 419:   {
 420:     switch (event.getID())
 421:       {
 422:       case MouseEvent.MOUSE_ENTERED:
 423:     fireMenuDragMouseEntered(event);
 424:     break;
 425:       case MouseEvent.MOUSE_EXITED:
 426:     fireMenuDragMouseExited(event);
 427:     break;
 428:       case MouseEvent.MOUSE_DRAGGED:
 429:     fireMenuDragMouseDragged(event);
 430:     break;
 431:       case MouseEvent.MOUSE_RELEASED:
 432:     fireMenuDragMouseReleased(event);
 433:     break;
 434:       }
 435:   }
 436: 
 437:   /**
 438:    * This method fires MenuKeyEvent to registered listeners.
 439:    * Different types of MenuKeyEvents are fired depending
 440:    * on the observed key event.
 441:    *
 442:    * @param event DOCUMENT ME!
 443:    */
 444:   public void processMenuKeyEvent(MenuKeyEvent event)
 445:   {
 446:     switch (event.getID())
 447:     {
 448:       case KeyEvent.KEY_PRESSED:
 449:         fireMenuKeyPressed(event);
 450:         break;
 451:       case KeyEvent.KEY_RELEASED:
 452:         fireMenuKeyReleased(event);
 453:         break;
 454:       case KeyEvent.KEY_TYPED:
 455:         fireMenuKeyTyped(event);
 456:         break;
 457:       default:
 458:         break;
 459:     }
 460:   }
 461: 
 462:   /**
 463:    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
 464:    *
 465:    * @param event The event signifying that mouse entered menuItem while it was dragged
 466:    */
 467:   protected void fireMenuDragMouseEntered(MenuDragMouseEvent event)
 468:   {
 469:     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
 470: 
 471:     for (int i = 0; i < ll.length; i++)
 472:       ((MenuDragMouseListener) ll[i]).menuDragMouseEntered(event);
 473:   }
 474: 
 475:   /**
 476:    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
 477:    *
 478:    * @param event The event signifying that mouse has exited menu item, while it was dragged
 479:    */
 480:   protected void fireMenuDragMouseExited(MenuDragMouseEvent event)
 481:   {
 482:     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
 483: 
 484:     for (int i = 0; i < ll.length; i++)
 485:       ((MenuDragMouseListener) ll[i]).menuDragMouseExited(event);
 486:   }
 487: 
 488:   /**
 489:    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
 490:    *
 491:    * @param event The event signifying that mouse is being dragged over the menuItem
 492:    */
 493:   protected void fireMenuDragMouseDragged(MenuDragMouseEvent event)
 494:   {
 495:     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
 496: 
 497:     for (int i = 0; i < ll.length; i++)
 498:       ((MenuDragMouseListener) ll[i]).menuDragMouseDragged(event);
 499:   }
 500: 
 501:   /**
 502:    * This method fires a MenuDragMouseEvent to all the MenuItem's MouseInputListeners.
 503:    *
 504:    * @param event The event signifying that mouse was released while it was dragged over the menuItem
 505:    */
 506:   protected void fireMenuDragMouseReleased(MenuDragMouseEvent event)
 507:   {
 508:     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
 509: 
 510:     for (int i = 0; i < ll.length; i++)
 511:       ((MenuDragMouseListener) ll[i]).menuDragMouseReleased(event);
 512:   }
 513: 
 514:   /**
 515:    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
 516:    *
 517:    * @param event The event signifying that key associated with this menu was pressed
 518:    */
 519:   protected void fireMenuKeyPressed(MenuKeyEvent event)
 520:   {
 521:     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
 522: 
 523:     for (int i = 0; i < ll.length; i++)
 524:       ((MenuKeyListener) ll[i]).menuKeyPressed(event);
 525:   }
 526: 
 527:   /**
 528:    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
 529:    *
 530:    * @param event The event signifying that key associated with this menu was released
 531:    */
 532:   protected void fireMenuKeyReleased(MenuKeyEvent event)
 533:   {
 534:     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
 535: 
 536:     for (int i = 0; i < ll.length; i++)
 537:       ((MenuKeyListener) ll[i]).menuKeyTyped(event);
 538:   }
 539: 
 540:   /**
 541:    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
 542:    *
 543:    * @param event The event signifying that key associated with this menu was typed.
 544:    *        The key is typed when it was pressed and then released
 545:    */
 546:   protected void fireMenuKeyTyped(MenuKeyEvent event)
 547:   {
 548:     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
 549: 
 550:     for (int i = 0; i < ll.length; i++)
 551:       ((MenuKeyListener) ll[i]).menuKeyTyped(event);
 552:   }
 553: 
 554:   /**
 555:    * Method of the MenuElement interface.
 556:    * This method is invoked by MenuSelectionManager when selection of
 557:    * this menu item has changed. If this menu item was selected then
 558:    * arm it's model, and disarm the model otherwise. The menu item
 559:    * is considered to be selected, and thus highlighted when its model
 560:    * is armed.
 561:    *
 562:    * @param changed indicates selection status of this menu item. If changed is
 563:    * true then menu item is selected and deselected otherwise.
 564:    */
 565:   public void menuSelectionChanged(boolean changed)
 566:   {
 567:     Component parent = this.getParent();
 568:     if (changed)
 569:       {
 570:     model.setArmed(true);
 571: 
 572:     if (parent != null && parent instanceof JPopupMenu)
 573:       ((JPopupMenu) parent).setSelected(this);
 574:       }
 575:     else
 576:       {
 577:     model.setArmed(false);
 578: 
 579:     if (parent != null && parent instanceof JPopupMenu)
 580:       ((JPopupMenu) parent).getSelectionModel().clearSelection();
 581:       }
 582:   }
 583: 
 584:   /**
 585:    * Method of the MenuElement interface.
 586:    *
 587:    * @return $MenuElement[]$ Returns array of sub-components for this menu
 588:    *         item. By default menuItem doesn't have any subcomponents and so
 589:    *         empty array is returned instead.
 590:    */
 591:   public MenuElement[] getSubElements()
 592:   {
 593:     return new MenuElement[0];
 594:   }
 595: 
 596:   /**
 597:    * Returns reference to the component that will paint this menu item.
 598:    *
 599:    * @return $Component$ Component that will paint this menu item.
 600:    *         Simply returns reference to this menu item.
 601:    */
 602:   public Component getComponent()
 603:   {
 604:     return this;
 605:   }
 606: 
 607:   /**
 608:    * Adds a MenuDragMouseListener to this menu item. When mouse
 609:    * is dragged over the menu item the MenuDragMouseEvents will be
 610:    * fired, and these listeners will be called.
 611:    *
 612:    * @param listener The new listener to add
 613:    */
 614:   public void addMenuDragMouseListener(MenuDragMouseListener listener)
 615:   {
 616:     listenerList.add(MenuDragMouseListener.class, listener);
 617:   }
 618: 
 619:   /**
 620:    * Removes a MenuDragMouseListener from the menuItem's listener list.
 621:    *
 622:    * @param listener The listener to remove
 623:    */
 624:   public void removeMenuDragMouseListener(MenuDragMouseListener listener)
 625:   {
 626:     listenerList.remove(MenuDragMouseListener.class, listener);
 627:   }
 628: 
 629:   /**
 630:    * Returns all added MenuDragMouseListener objects.
 631:    *
 632:    * @return an array of listeners
 633:    *
 634:    * @since 1.4
 635:    */
 636:   public MenuDragMouseListener[] getMenuDragMouseListeners()
 637:   {
 638:     return (MenuDragMouseListener[]) listenerList.getListeners(MenuDragMouseListener.class);
 639:   }
 640: 
 641:   /**
 642:    * Adds an MenuKeyListener to this menu item.  This listener will be
 643:    * invoked when MenuKeyEvents will be fired by this menu item.
 644:    *
 645:    * @param listener The new listener to add
 646:    */
 647:   public void addMenuKeyListener(MenuKeyListener listener)
 648:   {
 649:     listenerList.add(MenuKeyListener.class, listener);
 650:   }
 651: 
 652:   /**
 653:    * Removes an MenuKeyListener from the menuItem's listener list.
 654:    *
 655:    * @param listener The listener to remove
 656:    */
 657:   public void removeMenuKeyListener(MenuKeyListener listener)
 658:   {
 659:     listenerList.remove(MenuKeyListener.class, listener);
 660:   }
 661: 
 662:   /**
 663:    * Returns all added MenuKeyListener objects.
 664:    *
 665:    * @return an array of listeners
 666:    *
 667:    * @since 1.4
 668:    */
 669:   public MenuKeyListener[] getMenuKeyListeners()
 670:   {
 671:     return (MenuKeyListener[]) listenerList.getListeners(MenuKeyListener.class);
 672:   }
 673: 
 674:   /**
 675:    * Returns a string describing the attributes for the <code>JMenuItem</code>
 676:    * component, for use in debugging.  The return value is guaranteed to be 
 677:    * non-<code>null</code>, but the format of the string may vary between
 678:    * implementations.
 679:    *
 680:    * @return A string describing the attributes of the <code>JMenuItem</code>.
 681:    */
 682:   protected String paramString()
 683:   {
 684:     // calling super seems to be sufficient here...
 685:     return super.paramString();
 686:   }
 687: 
 688:   /**
 689:    * Returns the object that provides accessibility features for this
 690:    * <code>JMenuItem</code> component.
 691:    *
 692:    * @return The accessible context (an instance of 
 693:    *     {@link AccessibleJMenuItem}).
 694:    */
 695:   public AccessibleContext getAccessibleContext()
 696:   {
 697:     if (accessibleContext == null)
 698:       {
 699:         AccessibleJMenuItem ctx = new AccessibleJMenuItem(); 
 700:         addChangeListener(ctx);
 701:         accessibleContext = ctx;
 702:       }
 703: 
 704:     return accessibleContext;
 705:   }
 706: 
 707:   /**
 708:    * Provides the accessibility features for the <code>JMenuItem</code> 
 709:    * component.
 710:    * 
 711:    * @see JMenuItem#getAccessibleContext()
 712:    */
 713:   protected class AccessibleJMenuItem extends AccessibleAbstractButton
 714:     implements ChangeListener
 715:   {
 716:     private static final long serialVersionUID = 6748924232082076534L;
 717: 
 718:     private boolean armed;
 719:     private boolean focusOwner;
 720:     private boolean pressed;
 721:     private boolean selected;
 722: 
 723:     /**
 724:      * Creates a new <code>AccessibleJMenuItem</code> instance.
 725:      */
 726:     AccessibleJMenuItem()
 727:     {
 728:       //super(component);
 729:     }
 730: 
 731:     /**
 732:      * Receives notification when the menu item's state changes and fires
 733:      * appropriate property change events to registered listeners.
 734:      *
 735:      * @param event the change event
 736:      */
 737:     public void stateChanged(ChangeEvent event)
 738:     {
 739:       // This is fired in all cases.
 740:       firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
 741:                          Boolean.FALSE, Boolean.TRUE);
 742: 
 743:       ButtonModel model = getModel();
 744: 
 745:       // Handle the armed property.
 746:       if (model.isArmed())
 747:         {
 748:           if (! armed)
 749:             {
 750:               armed = true;
 751:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 752:                                  AccessibleState.ARMED, null);
 753:             }
 754:         }
 755:       else
 756:         {
 757:           if (armed)
 758:             {
 759:               armed = false;
 760:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 761:                                  null, AccessibleState.ARMED);
 762:             }
 763:         }
 764: 
 765:       // Handle the pressed property.
 766:       if (model.isPressed())
 767:         {
 768:           if (! pressed)
 769:             {
 770:               pressed = true;
 771:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 772:                                  AccessibleState.PRESSED, null);
 773:             }
 774:         }
 775:       else
 776:         {
 777:           if (pressed)
 778:             {
 779:               pressed = false;
 780:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 781:                                  null, AccessibleState.PRESSED);
 782:             }
 783:         }
 784: 
 785:       // Handle the selected property.
 786:       if (model.isSelected())
 787:         {
 788:           if (! selected)
 789:             {
 790:               selected = true;
 791:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 792:                                  AccessibleState.SELECTED, null);
 793:             }
 794:         }
 795:       else
 796:         {
 797:           if (selected)
 798:             {
 799:               selected = false;
 800:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 801:                                  null, AccessibleState.SELECTED);
 802:             }
 803:         }
 804: 
 805:       // Handle the focusOwner property.
 806:       if (isFocusOwner())
 807:         {
 808:           if (! focusOwner)
 809:             {
 810:               focusOwner = true;
 811:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 812:                                  AccessibleState.FOCUSED, null);
 813:             }
 814:         }
 815:       else
 816:         {
 817:           if (focusOwner)
 818:             {
 819:               focusOwner = false;
 820:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 821:                                  null, AccessibleState.FOCUSED);
 822:             }
 823:         }
 824:     }
 825: 
 826:     /**
 827:      * Returns the accessible role for the <code>JMenuItem</code> component.
 828:      *
 829:      * @return {@link AccessibleRole#MENU_ITEM}.
 830:      */
 831:     public AccessibleRole getAccessibleRole()
 832:     {
 833:       return AccessibleRole.MENU_ITEM;
 834:     }
 835:   }
 836: }