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:     /**
 296:      * Make sure menus always have the label, while
 297:      * AbstractButtons only have a label when no icon is set
 298:      */
 299:     setText((String) (action.getValue(Action.NAME)));
 300: 
 301:         setAccelerator((KeyStroke) (action.getValue(Action.ACCELERATOR_KEY)));
 302:         if (accelerator != null)
 303:           super.registerKeyboardAction(action, accelerator, 
 304:                                        JComponent.WHEN_IN_FOCUSED_WINDOW);
 305:       }
 306:   }
 307: 
 308:   /**
 309:    * Creates PropertyChangeListener to listen for the changes in action
 310:    * properties.
 311:    *
 312:    * @param action action to listen to for property changes
 313:    *
 314:    * @return $PropertyChangeListener$ Listener that listens to changes in
 315:    * action properties.
 316:    */
 317:   protected PropertyChangeListener createActionPropertyChangeListener(Action action)
 318:   {
 319:     return new PropertyChangeListener()
 320:       {
 321:     public void propertyChange(PropertyChangeEvent e)
 322:     {
 323:       Action act = (Action) (e.getSource());
 324:       configurePropertiesFromAction(act);
 325:     }
 326:       };
 327:   }
 328: 
 329:   /**
 330:    * Process mouse events forwarded from MenuSelectionManager.
 331:    *
 332:    * @param ev event forwarded from MenuSelectionManager
 333:    * @param path path to the menu element from which event was generated
 334:    * @param manager MenuSelectionManager for the current menu hierarchy
 335:    */
 336:   public void processMouseEvent(MouseEvent ev, MenuElement[] path,
 337:                                 MenuSelectionManager manager)
 338:   {
 339:     MenuDragMouseEvent e = new MenuDragMouseEvent(ev.getComponent(),
 340:                                                   ev.getID(), ev.getWhen(),
 341:                                                   ev.getModifiers(), ev.getX(),
 342:                                                   ev.getY(),
 343:                                                   ev.getClickCount(),
 344:                                                   ev.isPopupTrigger(), path,
 345:                                                   manager);
 346:     processMenuDragMouseEvent(e);
 347:   }
 348: 
 349:   /**
 350:    * Process key events forwarded from MenuSelectionManager.
 351:    *
 352:    * @param event event forwarded from MenuSelectionManager
 353:    * @param path path to the menu element from which event was generated
 354:    * @param manager MenuSelectionManager for the current menu hierarchy
 355:    */
 356:   public void processKeyEvent(KeyEvent event, MenuElement[] path,
 357:                               MenuSelectionManager manager)
 358:   {
 359:     MenuKeyEvent e = new MenuKeyEvent(event.getComponent(), event.getID(),
 360:                                       event.getWhen(), event.getModifiers(),
 361:                                       event.getKeyCode(), event.getKeyChar(),
 362:                                       path, manager);
 363:     processMenuKeyEvent(e);
 364: 
 365:     // Consume original key event, if the menu key event has been consumed.
 366:     if (e.isConsumed())
 367:       event.consume();
 368:   }
 369: 
 370:   /**
 371:    * This method fires MenuDragMouseEvents to registered listeners.
 372:    * Different types of MenuDragMouseEvents are fired depending
 373:    * on the observed mouse event.
 374:    *
 375:    * @param event Mouse
 376:    */
 377:   public void processMenuDragMouseEvent(MenuDragMouseEvent event)
 378:   {
 379:     switch (event.getID())
 380:       {
 381:       case MouseEvent.MOUSE_ENTERED:
 382:         isDragging = false;
 383:     fireMenuDragMouseEntered(event);
 384:     break;
 385:       case MouseEvent.MOUSE_EXITED:
 386:         isDragging = false;
 387:     fireMenuDragMouseExited(event);
 388:     break;
 389:       case MouseEvent.MOUSE_DRAGGED:
 390:         isDragging = true;
 391:     fireMenuDragMouseDragged(event);
 392:     break;
 393:       case MouseEvent.MOUSE_RELEASED:
 394:         if (isDragging)
 395:           fireMenuDragMouseReleased(event);
 396:     break;
 397:       }
 398:   }
 399: 
 400:   /**
 401:    * This method fires MenuKeyEvent to registered listeners.
 402:    * Different types of MenuKeyEvents are fired depending
 403:    * on the observed key event.
 404:    *
 405:    * @param event DOCUMENT ME!
 406:    */
 407:   public void processMenuKeyEvent(MenuKeyEvent event)
 408:   {
 409:     switch (event.getID())
 410:     {
 411:       case KeyEvent.KEY_PRESSED:
 412:         fireMenuKeyPressed(event);
 413:         break;
 414:       case KeyEvent.KEY_RELEASED:
 415:         fireMenuKeyReleased(event);
 416:         break;
 417:       case KeyEvent.KEY_TYPED:
 418:         fireMenuKeyTyped(event);
 419:         break;
 420:       default:
 421:         break;
 422:     }
 423:   }
 424: 
 425:   /**
 426:    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
 427:    *
 428:    * @param event The event signifying that mouse entered menuItem while it was dragged
 429:    */
 430:   protected void fireMenuDragMouseEntered(MenuDragMouseEvent event)
 431:   {
 432:     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
 433: 
 434:     for (int i = 0; i < ll.length; i++)
 435:       ((MenuDragMouseListener) ll[i]).menuDragMouseEntered(event);
 436:   }
 437: 
 438:   /**
 439:    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
 440:    *
 441:    * @param event The event signifying that mouse has exited menu item, while it was dragged
 442:    */
 443:   protected void fireMenuDragMouseExited(MenuDragMouseEvent event)
 444:   {
 445:     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
 446: 
 447:     for (int i = 0; i < ll.length; i++)
 448:       ((MenuDragMouseListener) ll[i]).menuDragMouseExited(event);
 449:   }
 450: 
 451:   /**
 452:    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
 453:    *
 454:    * @param event The event signifying that mouse is being dragged over the menuItem
 455:    */
 456:   protected void fireMenuDragMouseDragged(MenuDragMouseEvent event)
 457:   {
 458:     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
 459: 
 460:     for (int i = 0; i < ll.length; i++)
 461:       ((MenuDragMouseListener) ll[i]).menuDragMouseDragged(event);
 462:   }
 463: 
 464:   /**
 465:    * This method fires a MenuDragMouseEvent to all the MenuItem's MouseInputListeners.
 466:    *
 467:    * @param event The event signifying that mouse was released while it was dragged over the menuItem
 468:    */
 469:   protected void fireMenuDragMouseReleased(MenuDragMouseEvent event)
 470:   {
 471:     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
 472: 
 473:     for (int i = 0; i < ll.length; i++)
 474:       ((MenuDragMouseListener) ll[i]).menuDragMouseReleased(event);
 475:   }
 476: 
 477:   /**
 478:    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
 479:    *
 480:    * @param event The event signifying that key associated with this menu was pressed
 481:    */
 482:   protected void fireMenuKeyPressed(MenuKeyEvent event)
 483:   {
 484:     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
 485: 
 486:     for (int i = 0; i < ll.length; i++)
 487:       ((MenuKeyListener) ll[i]).menuKeyPressed(event);
 488:   }
 489: 
 490:   /**
 491:    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
 492:    *
 493:    * @param event The event signifying that key associated with this menu was released
 494:    */
 495:   protected void fireMenuKeyReleased(MenuKeyEvent event)
 496:   {
 497:     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
 498: 
 499:     for (int i = 0; i < ll.length; i++)
 500:       ((MenuKeyListener) ll[i]).menuKeyTyped(event);
 501:   }
 502: 
 503:   /**
 504:    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
 505:    *
 506:    * @param event The event signifying that key associated with this menu was typed.
 507:    *        The key is typed when it was pressed and then released
 508:    */
 509:   protected void fireMenuKeyTyped(MenuKeyEvent event)
 510:   {
 511:     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
 512: 
 513:     for (int i = 0; i < ll.length; i++)
 514:       ((MenuKeyListener) ll[i]).menuKeyTyped(event);
 515:   }
 516: 
 517:   /**
 518:    * Method of the MenuElement interface.
 519:    * This method is invoked by MenuSelectionManager when selection of
 520:    * this menu item has changed. If this menu item was selected then
 521:    * arm it's model, and disarm the model otherwise. The menu item
 522:    * is considered to be selected, and thus highlighted when its model
 523:    * is armed.
 524:    *
 525:    * @param changed indicates selection status of this menu item. If changed is
 526:    * true then menu item is selected and deselected otherwise.
 527:    */
 528:   public void menuSelectionChanged(boolean changed)
 529:   {
 530:     Component parent = this.getParent();
 531:     if (changed)
 532:       {
 533:     model.setArmed(true);
 534: 
 535:     if (parent != null && parent instanceof JPopupMenu)
 536:       ((JPopupMenu) parent).setSelected(this);
 537:       }
 538:     else
 539:       {
 540:     model.setArmed(false);
 541: 
 542:     if (parent != null && parent instanceof JPopupMenu)
 543:       ((JPopupMenu) parent).getSelectionModel().clearSelection();
 544:       }
 545:   }
 546: 
 547:   /**
 548:    * Method of the MenuElement interface.
 549:    *
 550:    * @return $MenuElement[]$ Returns array of sub-components for this menu
 551:    *         item. By default menuItem doesn't have any subcomponents and so
 552:    *         empty array is returned instead.
 553:    */
 554:   public MenuElement[] getSubElements()
 555:   {
 556:     return new MenuElement[0];
 557:   }
 558: 
 559:   /**
 560:    * Returns reference to the component that will paint this menu item.
 561:    *
 562:    * @return $Component$ Component that will paint this menu item.
 563:    *         Simply returns reference to this menu item.
 564:    */
 565:   public Component getComponent()
 566:   {
 567:     return this;
 568:   }
 569: 
 570:   /**
 571:    * Adds a MenuDragMouseListener to this menu item. When mouse
 572:    * is dragged over the menu item the MenuDragMouseEvents will be
 573:    * fired, and these listeners will be called.
 574:    *
 575:    * @param listener The new listener to add
 576:    */
 577:   public void addMenuDragMouseListener(MenuDragMouseListener listener)
 578:   {
 579:     listenerList.add(MenuDragMouseListener.class, listener);
 580:   }
 581: 
 582:   /**
 583:    * Removes a MenuDragMouseListener from the menuItem's listener list.
 584:    *
 585:    * @param listener The listener to remove
 586:    */
 587:   public void removeMenuDragMouseListener(MenuDragMouseListener listener)
 588:   {
 589:     listenerList.remove(MenuDragMouseListener.class, listener);
 590:   }
 591: 
 592:   /**
 593:    * Returns all added MenuDragMouseListener objects.
 594:    *
 595:    * @return an array of listeners
 596:    *
 597:    * @since 1.4
 598:    */
 599:   public MenuDragMouseListener[] getMenuDragMouseListeners()
 600:   {
 601:     return (MenuDragMouseListener[]) listenerList.getListeners(MenuDragMouseListener.class);
 602:   }
 603: 
 604:   /**
 605:    * Adds an MenuKeyListener to this menu item.  This listener will be
 606:    * invoked when MenuKeyEvents will be fired by this menu item.
 607:    *
 608:    * @param listener The new listener to add
 609:    */
 610:   public void addMenuKeyListener(MenuKeyListener listener)
 611:   {
 612:     listenerList.add(MenuKeyListener.class, listener);
 613:   }
 614: 
 615:   /**
 616:    * Removes an MenuKeyListener from the menuItem's listener list.
 617:    *
 618:    * @param listener The listener to remove
 619:    */
 620:   public void removeMenuKeyListener(MenuKeyListener listener)
 621:   {
 622:     listenerList.remove(MenuKeyListener.class, listener);
 623:   }
 624: 
 625:   /**
 626:    * Returns all added MenuKeyListener objects.
 627:    *
 628:    * @return an array of listeners
 629:    *
 630:    * @since 1.4
 631:    */
 632:   public MenuKeyListener[] getMenuKeyListeners()
 633:   {
 634:     return (MenuKeyListener[]) listenerList.getListeners(MenuKeyListener.class);
 635:   }
 636: 
 637:   /**
 638:    * Returns a string describing the attributes for the <code>JMenuItem</code>
 639:    * component, for use in debugging.  The return value is guaranteed to be 
 640:    * non-<code>null</code>, but the format of the string may vary between
 641:    * implementations.
 642:    *
 643:    * @return A string describing the attributes of the <code>JMenuItem</code>.
 644:    */
 645:   protected String paramString()
 646:   {
 647:     // calling super seems to be sufficient here...
 648:     return super.paramString();
 649:   }
 650: 
 651:   /**
 652:    * Returns the object that provides accessibility features for this
 653:    * <code>JMenuItem</code> component.
 654:    *
 655:    * @return The accessible context (an instance of 
 656:    *     {@link AccessibleJMenuItem}).
 657:    */
 658:   public AccessibleContext getAccessibleContext()
 659:   {
 660:     if (accessibleContext == null)
 661:       {
 662:         AccessibleJMenuItem ctx = new AccessibleJMenuItem(); 
 663:         addChangeListener(ctx);
 664:         accessibleContext = ctx;
 665:       }
 666: 
 667:     return accessibleContext;
 668:   }
 669: 
 670:   /**
 671:    * Provides the accessibility features for the <code>JMenuItem</code> 
 672:    * component.
 673:    * 
 674:    * @see JMenuItem#getAccessibleContext()
 675:    */
 676:   protected class AccessibleJMenuItem extends AccessibleAbstractButton
 677:     implements ChangeListener
 678:   {
 679:     private static final long serialVersionUID = 6748924232082076534L;
 680: 
 681:     private boolean armed;
 682:     private boolean focusOwner;
 683:     private boolean pressed;
 684:     private boolean selected;
 685: 
 686:     /**
 687:      * Creates a new <code>AccessibleJMenuItem</code> instance.
 688:      */
 689:     AccessibleJMenuItem()
 690:     {
 691:       //super(component);
 692:     }
 693: 
 694:     /**
 695:      * Receives notification when the menu item's state changes and fires
 696:      * appropriate property change events to registered listeners.
 697:      *
 698:      * @param event the change event
 699:      */
 700:     public void stateChanged(ChangeEvent event)
 701:     {
 702:       // This is fired in all cases.
 703:       firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
 704:                          Boolean.FALSE, Boolean.TRUE);
 705: 
 706:       ButtonModel model = getModel();
 707: 
 708:       // Handle the armed property.
 709:       if (model.isArmed())
 710:         {
 711:           if (! armed)
 712:             {
 713:               armed = true;
 714:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 715:                                  AccessibleState.ARMED, null);
 716:             }
 717:         }
 718:       else
 719:         {
 720:           if (armed)
 721:             {
 722:               armed = false;
 723:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 724:                                  null, AccessibleState.ARMED);
 725:             }
 726:         }
 727: 
 728:       // Handle the pressed property.
 729:       if (model.isPressed())
 730:         {
 731:           if (! pressed)
 732:             {
 733:               pressed = true;
 734:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 735:                                  AccessibleState.PRESSED, null);
 736:             }
 737:         }
 738:       else
 739:         {
 740:           if (pressed)
 741:             {
 742:               pressed = false;
 743:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 744:                                  null, AccessibleState.PRESSED);
 745:             }
 746:         }
 747: 
 748:       // Handle the selected property.
 749:       if (model.isSelected())
 750:         {
 751:           if (! selected)
 752:             {
 753:               selected = true;
 754:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 755:                                  AccessibleState.SELECTED, null);
 756:             }
 757:         }
 758:       else
 759:         {
 760:           if (selected)
 761:             {
 762:               selected = false;
 763:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 764:                                  null, AccessibleState.SELECTED);
 765:             }
 766:         }
 767: 
 768:       // Handle the focusOwner property.
 769:       if (isFocusOwner())
 770:         {
 771:           if (! focusOwner)
 772:             {
 773:               focusOwner = true;
 774:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 775:                                  AccessibleState.FOCUSED, null);
 776:             }
 777:         }
 778:       else
 779:         {
 780:           if (focusOwner)
 781:             {
 782:               focusOwner = false;
 783:               firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
 784:                                  null, AccessibleState.FOCUSED);
 785:             }
 786:         }
 787:     }
 788: 
 789:     /**
 790:      * Returns the accessible role for the <code>JMenuItem</code> component.
 791:      *
 792:      * @return {@link AccessibleRole#MENU_ITEM}.
 793:      */
 794:     public AccessibleRole getAccessibleRole()
 795:     {
 796:       return AccessibleRole.MENU_ITEM;
 797:     }
 798:   }
 799: 
 800:   /**
 801:    * Returns <code>true</code> if the component is guaranteed to be painted
 802:    * on top of others. This returns false by default and is overridden by
 803:    * components like JMenuItem, JPopupMenu and JToolTip to return true for
 804:    * added efficiency.
 805:    *
 806:    * @return <code>true</code> if the component is guaranteed to be painted
 807:    *         on top of others
 808:    */
 809:   boolean onTop()
 810:   {
 811:     return SwingUtilities.getAncestorOfClass(JInternalFrame.class, this)
 812:            == null;
 813:   }
 814: 
 815: }