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