< prev index next >

src/java.desktop/share/classes/javax/swing/JMenuItem.java

Print this page




  28 import java.awt.*;
  29 import java.awt.event.*;
  30 import java.awt.image.*;
  31 
  32 import java.beans.PropertyChangeEvent;
  33 import java.beans.PropertyChangeListener;
  34 
  35 import java.io.Serializable;
  36 import java.io.ObjectOutputStream;
  37 import java.io.ObjectInputStream;
  38 import java.io.IOException;
  39 
  40 import javax.swing.plaf.*;
  41 import javax.swing.plaf.basic.*;
  42 import javax.swing.event.*;
  43 import javax.accessibility.*;
  44 
  45 /**
  46  * An implementation of an item in a menu. A menu item is essentially a button
  47  * sitting in a list. When the user selects the "button", the action
  48  * associated with the menu item is performed. A <code>JMenuItem</code>
  49  * contained in a <code>JPopupMenu</code> performs exactly that function.
  50  * <p>
  51  * Menu items can be configured, and to some degree controlled, by
  52  * <code><a href="Action.html">Action</a></code>s.  Using an
  53  * <code>Action</code> with a menu item has many benefits beyond directly
  54  * configuring a menu item.  Refer to <a href="Action.html#buttonActions">
  55  * Swing Components Supporting <code>Action</code></a> for more
  56  * details, and you can find more information in <a
  57  * href="http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html">How
  58  * to Use Actions</a>, a section in <em>The Java Tutorial</em>.
  59  * <p>
  60  * For further documentation and for examples, see
  61  * <a
  62  href="http://docs.oracle.com/javase/tutorial/uiswing/components/menu.html">How to Use Menus</a>
  63  * in <em>The Java Tutorial.</em>
  64  * <p>
  65  * <strong>Warning:</strong> Swing is not thread safe. For more
  66  * information see <a
  67  * href="package-summary.html#threading">Swing's Threading
  68  * Policy</a>.
  69  * <p>
  70  * <strong>Warning:</strong>
  71  * Serialized objects of this class will not be compatible with
  72  * future Swing releases. The current serialization support is
  73  * appropriate for short term storage or RMI between applications running
  74  * the same version of Swing.  As of 1.4, support for long term storage
  75  * of all JavaBeans&trade;
  76  * has been added to the <code>java.beans</code> package.
  77  * Please see {@link java.beans.XMLEncoder}.
  78  *
  79  * @beaninfo
  80  *   attribute: isContainer false
  81  * description: An item which can be selected in a menu.
  82  *
  83  * @author Georges Saab
  84  * @author David Karlton
  85  * @see JPopupMenu
  86  * @see JMenu
  87  * @see JCheckBoxMenuItem
  88  * @see JRadioButtonMenuItem
  89  * @since 1.2
  90  */
  91 @SuppressWarnings("serial")
  92 public class JMenuItem extends AbstractButton implements Accessible,MenuElement  {
  93 
  94     /**
  95      * @see #getUIClassID
  96      * @see #readObject
  97      */
  98     private static final String uiClassID = "MenuItemUI";
  99 
 100     /* diagnostic aids -- should be false for production builds. */
 101     private static final boolean TRACE =   false; // trace creates and disposes
 102     private static final boolean VERBOSE = false; // show reuse hits/misses
 103     private static final boolean DEBUG =   false;  // show bad params, misc.
 104 
 105     private boolean isMouseDragged = false;
 106 
 107     /**
 108      * Creates a <code>JMenuItem</code> with no set text or icon.
 109      */
 110     public JMenuItem() {
 111         this(null, (Icon)null);
 112     }
 113 
 114     /**
 115      * Creates a <code>JMenuItem</code> with the specified icon.
 116      *
 117      * @param icon the icon of the <code>JMenuItem</code>
 118      */
 119     public JMenuItem(Icon icon) {
 120         this(null, icon);
 121     }
 122 
 123     /**
 124      * Creates a <code>JMenuItem</code> with the specified text.
 125      *
 126      * @param text the text of the <code>JMenuItem</code>
 127      */
 128     public JMenuItem(String text) {
 129         this(text, (Icon)null);
 130     }
 131 
 132     /**
 133      * Creates a menu item whose properties are taken from the
 134      * specified <code>Action</code>.
 135      *
 136      * @param a the action of the <code>JMenuItem</code>
 137      * @since 1.3
 138      */
 139     public JMenuItem(Action a) {
 140         this();
 141         setAction(a);
 142     }
 143 
 144     /**
 145      * Creates a <code>JMenuItem</code> with the specified text and icon.
 146      *
 147      * @param text the text of the <code>JMenuItem</code>
 148      * @param icon the icon of the <code>JMenuItem</code>
 149      */
 150     public JMenuItem(String text, Icon icon) {
 151         setModel(new DefaultButtonModel());
 152         init(text, icon);
 153         initFocusability();
 154     }
 155 
 156     /**
 157      * Creates a <code>JMenuItem</code> with the specified text and
 158      * keyboard mnemonic.
 159      *
 160      * @param text the text of the <code>JMenuItem</code>
 161      * @param mnemonic the keyboard mnemonic for the <code>JMenuItem</code>
 162      */
 163     public JMenuItem(String text, int mnemonic) {
 164         setModel(new DefaultButtonModel());
 165         init(text, null);
 166         setMnemonic(mnemonic);
 167         initFocusability();
 168     }
 169 
 170     /**
 171      * {@inheritDoc}
 172      */
 173     public void setModel(ButtonModel newModel) {
 174         super.setModel(newModel);
 175         if(newModel instanceof DefaultButtonModel) {
 176             ((DefaultButtonModel)newModel).setMenuItem(true);
 177         }
 178     }
 179 
 180     /**
 181      * Inititalizes the focusability of the <code>JMenuItem</code>.
 182      * <code>JMenuItem</code>'s are focusable, but subclasses may
 183      * want to be, this provides them the opportunity to override this
 184      * and invoke something else, or nothing at all. Refer to
 185      * {@link javax.swing.JMenu#initFocusability} for the motivation of
 186      * this.
 187      */
 188     void initFocusability() {
 189         setFocusable(false);
 190     }
 191 
 192     /**
 193      * Initializes the menu item with the specified text and icon.
 194      *
 195      * @param text the text of the <code>JMenuItem</code>
 196      * @param icon the icon of the <code>JMenuItem</code>
 197      */
 198     protected void init(String text, Icon icon) {
 199         if(text != null) {
 200             setText(text);
 201         }
 202 
 203         if(icon != null) {
 204             setIcon(icon);
 205         }
 206 
 207         // Listen for Focus events
 208         addFocusListener(new MenuItemFocusListener());
 209         setUIProperty("borderPainted", Boolean.FALSE);
 210         setFocusPainted(false);
 211         setHorizontalTextPosition(JButton.TRAILING);
 212         setHorizontalAlignment(JButton.LEADING);
 213         updateUI();
 214     }
 215 
 216     private static class MenuItemFocusListener implements FocusListener,
 217         Serializable {
 218         public void focusGained(FocusEvent event) {}
 219         public void focusLost(FocusEvent event) {
 220             // When focus is lost, repaint if
 221             // the focus information is painted
 222             JMenuItem mi = (JMenuItem)event.getSource();
 223             if(mi.isFocusPainted()) {
 224                 mi.repaint();
 225             }
 226         }
 227     }
 228 
 229 
 230     /**
 231      * Sets the look and feel object that renders this component.
 232      *
 233      * @param ui  the <code>JMenuItemUI</code> L&amp;F object
 234      * @see UIDefaults#getUI
 235      * @beaninfo
 236      *        bound: true
 237      *       hidden: true
 238      *    attribute: visualUpdate true
 239      *  description: The UI object that implements the Component's LookAndFeel.
 240      */
 241     public void setUI(MenuItemUI ui) {
 242         super.setUI(ui);
 243     }
 244 
 245     /**
 246      * Resets the UI property with a value from the current look and feel.
 247      *
 248      * @see JComponent#updateUI
 249      */
 250     public void updateUI() {
 251         setUI((MenuItemUI)UIManager.getUI(this));
 252     }
 253 


 298 
 299     /**
 300      * Enables or disables the menu item.
 301      *
 302      * @param b  true to enable the item
 303      * @beaninfo
 304      *    description: Does the component react to user interaction
 305      *          bound: true
 306      *      preferred: true
 307      */
 308     public void setEnabled(boolean b) {
 309         // Make sure we aren't armed!
 310         if (!b && !UIManager.getBoolean("MenuItem.disabledAreNavigable")) {
 311             setArmed(false);
 312         }
 313         super.setEnabled(b);
 314     }
 315 
 316 
 317     /**
 318      * Returns true since <code>Menu</code>s, by definition,
 319      * should always be on top of all other windows.  If the menu is
 320      * in an internal frame false is returned due to the rollover effect
 321      * for windows laf where the menu is not always on top.
 322      */
 323     // package private
 324     boolean alwaysOnTop() {
 325         // Fix for bug #4482165
 326         if (SwingUtilities.getAncestorOfClass(JInternalFrame.class, this) !=
 327                 null) {
 328             return false;
 329         }
 330         return true;
 331     }
 332 
 333 
 334     /* The keystroke which acts as the menu item's accelerator
 335      */
 336     private KeyStroke accelerator;
 337 
 338     /**
 339      * Sets the key combination which invokes the menu item's
 340      * action listeners without navigating the menu hierarchy. It is the
 341      * UI's responsibility to install the correct action.  Note that
 342      * when the keyboard accelerator is typed, it will work whether or
 343      * not the menu is currently displayed.
 344      *
 345      * @param keyStroke the <code>KeyStroke</code> which will
 346      *          serve as an accelerator
 347      * @beaninfo
 348      *     description: The keystroke combination which will invoke the
 349      *                  JMenuItem's actionlisteners without navigating the
 350      *                  menu hierarchy
 351      *           bound: true
 352      *       preferred: true
 353      */
 354     public void setAccelerator(KeyStroke keyStroke) {
 355         KeyStroke oldAccelerator = accelerator;
 356         this.accelerator = keyStroke;
 357         repaint();
 358         revalidate();
 359         firePropertyChange("accelerator", oldAccelerator, accelerator);
 360     }
 361 
 362     /**
 363      * Returns the <code>KeyStroke</code> which serves as an accelerator
 364      * for the menu item.
 365      * @return a <code>KeyStroke</code> object identifying the
 366      *          accelerator key
 367      */
 368     public KeyStroke getAccelerator() {
 369         return this.accelerator;
 370     }
 371 
 372     /**
 373      * {@inheritDoc}
 374      *
 375      * @since 1.3
 376      */
 377     protected void configurePropertiesFromAction(Action a) {
 378         super.configurePropertiesFromAction(a);
 379         configureAcceleratorFromAction(a);
 380     }
 381 
 382     void setIconFromAction(Action a) {
 383         Icon icon = null;
 384         if (a != null) {
 385             icon = (Icon)a.getValue(Action.SMALL_ICON);


 398         KeyStroke ks = (a==null) ? null :
 399             (KeyStroke)a.getValue(Action.ACCELERATOR_KEY);
 400         setAccelerator(ks);
 401     }
 402 
 403     /**
 404      * {@inheritDoc}
 405      * @since 1.6
 406      */
 407     protected void actionPropertyChanged(Action action, String propertyName) {
 408         if (propertyName == Action.ACCELERATOR_KEY) {
 409             configureAcceleratorFromAction(action);
 410         }
 411         else {
 412             super.actionPropertyChanged(action, propertyName);
 413         }
 414     }
 415 
 416     /**
 417      * Processes a mouse event forwarded from the
 418      * <code>MenuSelectionManager</code> and changes the menu
 419      * selection, if necessary, by using the
 420      * <code>MenuSelectionManager</code>'s API.
 421      * <p>
 422      * Note: you do not have to forward the event to sub-components.
 423      * This is done automatically by the <code>MenuSelectionManager</code>.
 424      *
 425      * @param e   a <code>MouseEvent</code>
 426      * @param path  the <code>MenuElement</code> path array
 427      * @param manager   the <code>MenuSelectionManager</code>
 428      */
 429     public void processMouseEvent(MouseEvent e,MenuElement path[],MenuSelectionManager manager) {
 430         processMenuDragMouseEvent(
 431                  new MenuDragMouseEvent(e.getComponent(), e.getID(),
 432                                         e.getWhen(),
 433                                         e.getModifiers(), e.getX(), e.getY(),
 434                                         e.getXOnScreen(), e.getYOnScreen(),
 435                                         e.getClickCount(), e.isPopupTrigger(),
 436                                         path, manager));
 437     }
 438 
 439 
 440     /**
 441      * Processes a key event forwarded from the
 442      * <code>MenuSelectionManager</code> and changes the menu selection,
 443      * if necessary, by using <code>MenuSelectionManager</code>'s API.
 444      * <p>
 445      * Note: you do not have to forward the event to sub-components.
 446      * This is done automatically by the <code>MenuSelectionManager</code>.
 447      *
 448      * @param e  a <code>KeyEvent</code>
 449      * @param path the <code>MenuElement</code> path array
 450      * @param manager   the <code>MenuSelectionManager</code>
 451      */
 452     public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
 453         if (DEBUG) {
 454             System.out.println("in JMenuItem.processKeyEvent/3 for " + getText() +
 455                                    "  " + KeyStroke.getKeyStrokeForEvent(e));
 456         }
 457         MenuKeyEvent mke = new MenuKeyEvent(e.getComponent(), e.getID(),
 458                                              e.getWhen(), e.getModifiers(),
 459                                              e.getKeyCode(), e.getKeyChar(),
 460                                              path, manager);
 461         processMenuKeyEvent(mke);
 462 
 463         if (mke.isConsumed())  {
 464             e.consume();
 465         }
 466     }
 467 
 468 
 469 
 470     /**
 471      * Handles mouse drag in a menu.
 472      *
 473      * @param e  a <code>MenuDragMouseEvent</code> object
 474      */
 475     public void processMenuDragMouseEvent(MenuDragMouseEvent e) {
 476         switch (e.getID()) {
 477         case MouseEvent.MOUSE_ENTERED:
 478             isMouseDragged = false; fireMenuDragMouseEntered(e); break;
 479         case MouseEvent.MOUSE_EXITED:
 480             isMouseDragged = false; fireMenuDragMouseExited(e); break;
 481         case MouseEvent.MOUSE_DRAGGED:
 482             isMouseDragged = true; fireMenuDragMouseDragged(e); break;
 483         case MouseEvent.MOUSE_RELEASED:
 484             if(isMouseDragged) fireMenuDragMouseReleased(e); break;
 485         default:
 486             break;
 487         }
 488     }
 489 
 490     /**
 491      * Handles a keystroke in a menu.
 492      *
 493      * @param e  a <code>MenuKeyEvent</code> object
 494      */
 495     public void processMenuKeyEvent(MenuKeyEvent e) {
 496         if (DEBUG) {
 497             System.out.println("in JMenuItem.processMenuKeyEvent for " + getText()+
 498                                    "  " + KeyStroke.getKeyStrokeForEvent(e));
 499         }
 500         switch (e.getID()) {
 501         case KeyEvent.KEY_PRESSED:
 502             fireMenuKeyPressed(e); break;
 503         case KeyEvent.KEY_RELEASED:
 504             fireMenuKeyReleased(e); break;
 505         case KeyEvent.KEY_TYPED:
 506             fireMenuKeyTyped(e); break;
 507         default:
 508             break;
 509         }
 510     }
 511 
 512     /**
 513      * Notifies all listeners that have registered interest for
 514      * notification on this event type.
 515      *
 516      * @param event a <code>MenuMouseDragEvent</code>
 517      * @see EventListenerList
 518      */
 519     protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) {
 520         // Guaranteed to return a non-null array
 521         Object[] listeners = listenerList.getListenerList();
 522         // Process the listeners last to first, notifying
 523         // those that are interested in this event
 524         for (int i = listeners.length-2; i>=0; i-=2) {
 525             if (listeners[i]==MenuDragMouseListener.class) {
 526                 // Lazily create the event:
 527                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseEntered(event);
 528             }
 529         }
 530     }
 531 
 532     /**
 533      * Notifies all listeners that have registered interest for
 534      * notification on this event type.
 535      *
 536      * @param event a <code>MenuDragMouseEvent</code>
 537      * @see EventListenerList
 538      */
 539     protected void fireMenuDragMouseExited(MenuDragMouseEvent event) {
 540         // Guaranteed to return a non-null array
 541         Object[] listeners = listenerList.getListenerList();
 542         // Process the listeners last to first, notifying
 543         // those that are interested in this event
 544         for (int i = listeners.length-2; i>=0; i-=2) {
 545             if (listeners[i]==MenuDragMouseListener.class) {
 546                 // Lazily create the event:
 547                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseExited(event);
 548             }
 549         }
 550     }
 551 
 552     /**
 553      * Notifies all listeners that have registered interest for
 554      * notification on this event type.
 555      *
 556      * @param event a <code>MenuDragMouseEvent</code>
 557      * @see EventListenerList
 558      */
 559     protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) {
 560         // Guaranteed to return a non-null array
 561         Object[] listeners = listenerList.getListenerList();
 562         // Process the listeners last to first, notifying
 563         // those that are interested in this event
 564         for (int i = listeners.length-2; i>=0; i-=2) {
 565             if (listeners[i]==MenuDragMouseListener.class) {
 566                 // Lazily create the event:
 567                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseDragged(event);
 568             }
 569         }
 570     }
 571 
 572     /**
 573      * Notifies all listeners that have registered interest for
 574      * notification on this event type.
 575      *
 576      * @param event a <code>MenuDragMouseEvent</code>
 577      * @see EventListenerList
 578      */
 579     protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) {
 580         // Guaranteed to return a non-null array
 581         Object[] listeners = listenerList.getListenerList();
 582         // Process the listeners last to first, notifying
 583         // those that are interested in this event
 584         for (int i = listeners.length-2; i>=0; i-=2) {
 585             if (listeners[i]==MenuDragMouseListener.class) {
 586                 // Lazily create the event:
 587                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseReleased(event);
 588             }
 589         }
 590     }
 591 
 592     /**
 593      * Notifies all listeners that have registered interest for
 594      * notification on this event type.
 595      *
 596      * @param event a <code>MenuKeyEvent</code>
 597      * @see EventListenerList
 598      */
 599     protected void fireMenuKeyPressed(MenuKeyEvent event) {
 600         if (DEBUG) {
 601             System.out.println("in JMenuItem.fireMenuKeyPressed for " + getText()+
 602                                    "  " + KeyStroke.getKeyStrokeForEvent(event));
 603         }
 604         // Guaranteed to return a non-null array
 605         Object[] listeners = listenerList.getListenerList();
 606         // Process the listeners last to first, notifying
 607         // those that are interested in this event
 608         for (int i = listeners.length-2; i>=0; i-=2) {
 609             if (listeners[i]==MenuKeyListener.class) {
 610                 // Lazily create the event:
 611                 ((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
 612             }
 613         }
 614     }
 615 
 616     /**
 617      * Notifies all listeners that have registered interest for
 618      * notification on this event type.
 619      *
 620      * @param event a <code>MenuKeyEvent</code>
 621      * @see EventListenerList
 622      */
 623     protected void fireMenuKeyReleased(MenuKeyEvent event) {
 624         if (DEBUG) {
 625             System.out.println("in JMenuItem.fireMenuKeyReleased for " + getText()+
 626                                    "  " + KeyStroke.getKeyStrokeForEvent(event));
 627         }
 628         // Guaranteed to return a non-null array
 629         Object[] listeners = listenerList.getListenerList();
 630         // Process the listeners last to first, notifying
 631         // those that are interested in this event
 632         for (int i = listeners.length-2; i>=0; i-=2) {
 633             if (listeners[i]==MenuKeyListener.class) {
 634                 // Lazily create the event:
 635                 ((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
 636             }
 637         }
 638     }
 639 
 640     /**
 641      * Notifies all listeners that have registered interest for
 642      * notification on this event type.
 643      *
 644      * @param event a <code>MenuKeyEvent</code>
 645      * @see EventListenerList
 646      */
 647     protected void fireMenuKeyTyped(MenuKeyEvent event) {
 648         if (DEBUG) {
 649             System.out.println("in JMenuItem.fireMenuKeyTyped for " + getText()+
 650                                    "  " + KeyStroke.getKeyStrokeForEvent(event));
 651         }
 652         // Guaranteed to return a non-null array
 653         Object[] listeners = listenerList.getListenerList();
 654         // Process the listeners last to first, notifying
 655         // those that are interested in this event
 656         for (int i = listeners.length-2; i>=0; i-=2) {
 657             if (listeners[i]==MenuKeyListener.class) {
 658                 // Lazily create the event:
 659                 ((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
 660             }
 661         }
 662     }
 663 
 664     /**
 665      * Called by the <code>MenuSelectionManager</code> when the
 666      * <code>MenuElement</code> is selected or unselected.
 667      *
 668      * @param isIncluded  true if this menu item is on the part of the menu
 669      *                    path that changed, false if this menu is part of the
 670      *                    a menu path that changed, but this particular part of
 671      *                    that path is still the same
 672      * @see MenuSelectionManager#setSelectedPath(MenuElement[])
 673      */
 674     public void menuSelectionChanged(boolean isIncluded) {
 675         setArmed(isIncluded);
 676     }
 677 
 678     /**
 679      * This method returns an array containing the sub-menu
 680      * components for this menu component.
 681      *
 682      * @return an array of <code>MenuElement</code>s
 683      */
 684     public MenuElement[] getSubElements() {
 685         return new MenuElement[0];
 686     }
 687 
 688     /**
 689      * Returns the <code>java.awt.Component</code> used to paint
 690      * this object. The returned component will be used to convert
 691      * events and detect if an event is inside a menu component.
 692      *
 693      * @return the <code>Component</code> that paints this menu item
 694      */
 695     public Component getComponent() {
 696         return this;
 697     }
 698 
 699     /**
 700      * Adds a <code>MenuDragMouseListener</code> to the menu item.
 701      *
 702      * @param l the <code>MenuDragMouseListener</code> to be added
 703      */
 704     public void addMenuDragMouseListener(MenuDragMouseListener l) {
 705         listenerList.add(MenuDragMouseListener.class, l);
 706     }
 707 
 708     /**
 709      * Removes a <code>MenuDragMouseListener</code> from the menu item.
 710      *
 711      * @param l the <code>MenuDragMouseListener</code> to be removed
 712      */
 713     public void removeMenuDragMouseListener(MenuDragMouseListener l) {
 714         listenerList.remove(MenuDragMouseListener.class, l);
 715     }
 716 
 717     /**
 718      * Returns an array of all the <code>MenuDragMouseListener</code>s added
 719      * to this JMenuItem with addMenuDragMouseListener().
 720      *
 721      * @return all of the <code>MenuDragMouseListener</code>s added or an empty
 722      *         array if no listeners have been added
 723      * @since 1.4
 724      */
 725     public MenuDragMouseListener[] getMenuDragMouseListeners() {
 726         return listenerList.getListeners(MenuDragMouseListener.class);
 727     }
 728 
 729     /**
 730      * Adds a <code>MenuKeyListener</code> to the menu item.
 731      *
 732      * @param l the <code>MenuKeyListener</code> to be added
 733      */
 734     public void addMenuKeyListener(MenuKeyListener l) {
 735         listenerList.add(MenuKeyListener.class, l);
 736     }
 737 
 738     /**
 739      * Removes a <code>MenuKeyListener</code> from the menu item.
 740      *
 741      * @param l the <code>MenuKeyListener</code> to be removed
 742      */
 743     public void removeMenuKeyListener(MenuKeyListener l) {
 744         listenerList.remove(MenuKeyListener.class, l);
 745     }
 746 
 747     /**
 748      * Returns an array of all the <code>MenuKeyListener</code>s added
 749      * to this JMenuItem with addMenuKeyListener().
 750      *
 751      * @return all of the <code>MenuKeyListener</code>s added or an empty
 752      *         array if no listeners have been added
 753      * @since 1.4
 754      */
 755     public MenuKeyListener[] getMenuKeyListeners() {
 756         return listenerList.getListeners(MenuKeyListener.class);
 757     }
 758 
 759     /**
 760      * See JComponent.readObject() for information about serialization
 761      * in Swing.
 762      */
 763     private void readObject(ObjectInputStream s)
 764         throws IOException, ClassNotFoundException
 765     {
 766         s.defaultReadObject();
 767         if (getUIClassID().equals(uiClassID)) {
 768             updateUI();
 769         }
 770     }
 771 
 772     private void writeObject(ObjectOutputStream s) throws IOException {
 773         s.defaultWriteObject();
 774         if (getUIClassID().equals(uiClassID)) {
 775             byte count = JComponent.getWriteObjCounter(this);
 776             JComponent.setWriteObjCounter(this, --count);
 777             if (count == 0 && ui != null) {
 778                 ui.installUI(this);
 779             }
 780         }
 781     }
 782 
 783 
 784     /**
 785      * Returns a string representation of this <code>JMenuItem</code>.
 786      * This method is intended to be used only for debugging purposes,
 787      * and the content and format of the returned string may vary between
 788      * implementations. The returned string may be empty but may not
 789      * be <code>null</code>.
 790      *
 791      * @return  a string representation of this <code>JMenuItem</code>
 792      */
 793     protected String paramString() {
 794         return super.paramString();
 795     }
 796 
 797 /////////////////
 798 // Accessibility support
 799 ////////////////
 800 
 801     /**
 802      * Returns the <code>AccessibleContext</code> associated with this
 803      * <code>JMenuItem</code>. For <code>JMenuItem</code>s,
 804      * the <code>AccessibleContext</code> takes the form of an
 805      * <code>AccessibleJMenuItem</code>.
 806      * A new AccessibleJMenuItme instance is created if necessary.
 807      *
 808      * @return an <code>AccessibleJMenuItem</code> that serves as the
 809      *         <code>AccessibleContext</code> of this <code>JMenuItem</code>
 810      */
 811     public AccessibleContext getAccessibleContext() {
 812         if (accessibleContext == null) {
 813             accessibleContext = new AccessibleJMenuItem();
 814         }
 815         return accessibleContext;
 816     }
 817 
 818 
 819     /**
 820      * This class implements accessibility support for the
 821      * <code>JMenuItem</code> class.  It provides an implementation of the
 822      * Java Accessibility API appropriate to menu item user-interface
 823      * elements.
 824      * <p>
 825      * <strong>Warning:</strong>
 826      * Serialized objects of this class will not be compatible with
 827      * future Swing releases. The current serialization support is
 828      * appropriate for short term storage or RMI between applications running
 829      * the same version of Swing.  As of 1.4, support for long term storage
 830      * of all JavaBeans&trade;
 831      * has been added to the <code>java.beans</code> package.
 832      * Please see {@link java.beans.XMLEncoder}.
 833      */
 834     @SuppressWarnings("serial")
 835     protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener {
 836 
 837         private boolean isArmed = false;
 838         private boolean hasFocus = false;
 839         private boolean isPressed = false;
 840         private boolean isSelected = false;
 841 
 842         AccessibleJMenuItem() {
 843             super();
 844             JMenuItem.this.addChangeListener(this);
 845         }
 846 
 847         /**
 848          * Get the role of this object.
 849          *
 850          * @return an instance of AccessibleRole describing the role of the
 851          * object




  28 import java.awt.*;
  29 import java.awt.event.*;
  30 import java.awt.image.*;
  31 
  32 import java.beans.PropertyChangeEvent;
  33 import java.beans.PropertyChangeListener;
  34 
  35 import java.io.Serializable;
  36 import java.io.ObjectOutputStream;
  37 import java.io.ObjectInputStream;
  38 import java.io.IOException;
  39 
  40 import javax.swing.plaf.*;
  41 import javax.swing.plaf.basic.*;
  42 import javax.swing.event.*;
  43 import javax.accessibility.*;
  44 
  45 /**
  46  * An implementation of an item in a menu. A menu item is essentially a button
  47  * sitting in a list. When the user selects the "button", the action
  48  * associated with the menu item is performed. A {@code JMenuItem}
  49  * contained in a {@code JPopupMenu} performs exactly that function.
  50  * <p>
  51  * Menu items can be configured, and to some degree controlled, by
  52  * <code><a href="Action.html">Action</a></code>s.  Using an
  53  * {@code Action} with a menu item has many benefits beyond directly
  54  * configuring a menu item.  Refer to <a href="Action.html#buttonActions">
  55  * Swing Components Supporting {@code Action}</a> for more
  56  * details, and you can find more information in <a
  57  * href="http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html">How
  58  * to Use Actions</a>, a section in <em>The Java Tutorial</em>.
  59  * <p>
  60  * For further documentation and for examples, see
  61  * <a
  62  href="http://docs.oracle.com/javase/tutorial/uiswing/components/menu.html">How to Use Menus</a>
  63  * in <em>The Java Tutorial.</em>
  64  * <p>
  65  * <strong>Warning:</strong> Swing is not thread safe. For more
  66  * information see <a
  67  * href="package-summary.html#threading">Swing's Threading
  68  * Policy</a>.
  69  * <p>
  70  * <strong>Warning:</strong>
  71  * Serialized objects of this class will not be compatible with
  72  * future Swing releases. The current serialization support is
  73  * appropriate for short term storage or RMI between applications running
  74  * the same version of Swing.  As of 1.4, support for long term storage
  75  * of all JavaBeans&trade;
  76  * has been added to the {@code java.beans} package.
  77  * Please see {@link java.beans.XMLEncoder}.
  78  *
  79  * @beaninfo
  80  *   attribute: isContainer false
  81  * description: An item which can be selected in a menu.
  82  *
  83  * @author Georges Saab
  84  * @author David Karlton
  85  * @see JPopupMenu
  86  * @see JMenu
  87  * @see JCheckBoxMenuItem
  88  * @see JRadioButtonMenuItem
  89  * @since 1.2
  90  */
  91 @SuppressWarnings("serial")
  92 public class JMenuItem extends AbstractButton implements Accessible,MenuElement  {
  93 
  94     /**
  95      * @see #getUIClassID
  96      * @see #readObject
  97      */
  98     private static final String uiClassID = "MenuItemUI";
  99 
 100     /* diagnostic aids -- should be false for production builds. */
 101     private static final boolean TRACE =   false; // trace creates and disposes
 102     private static final boolean VERBOSE = false; // show reuse hits/misses
 103     private static final boolean DEBUG =   false;  // show bad params, misc.
 104 
 105     private boolean isMouseDragged = false;
 106 
 107     /**
 108      * Creates a {@code JMenuItem} with no set text or icon.
 109      */
 110     public JMenuItem() {
 111         this(null, (Icon)null);
 112     }
 113 
 114     /**
 115      * Creates a {@code JMenuItem} with the specified icon.
 116      *
 117      * @param icon the icon of the {@code JMenuItem}
 118      */
 119     public JMenuItem(Icon icon) {
 120         this(null, icon);
 121     }
 122 
 123     /**
 124      * Creates a {@code JMenuItem} with the specified text.
 125      *
 126      * @param text the text of the {@code JMenuItem}
 127      */
 128     public JMenuItem(String text) {
 129         this(text, (Icon)null);
 130     }
 131 
 132     /**
 133      * Creates a menu item whose properties are taken from the
 134      * specified {@code Action}.
 135      *
 136      * @param a the action of the {@code JMenuItem}
 137      * @since 1.3
 138      */
 139     public JMenuItem(Action a) {
 140         this();
 141         setAction(a);
 142     }
 143 
 144     /**
 145      * Creates a {@code JMenuItem} with the specified text and icon.
 146      *
 147      * @param text the text of the {@code JMenuItem}
 148      * @param icon the icon of the {@code JMenuItem}
 149      */
 150     public JMenuItem(String text, Icon icon) {
 151         setModel(new DefaultButtonModel());
 152         init(text, icon);
 153         initFocusability();
 154     }
 155 
 156     /**
 157      * Creates a {@code JMenuItem} with the specified text and
 158      * keyboard mnemonic.
 159      *
 160      * @param text the text of the {@code JMenuItem}
 161      * @param mnemonic the keyboard mnemonic for the {@code JMenuItem}
 162      */
 163     public JMenuItem(String text, int mnemonic) {
 164         setModel(new DefaultButtonModel());
 165         init(text, null);
 166         setMnemonic(mnemonic);
 167         initFocusability();
 168     }
 169 
 170     /**
 171      * {@inheritDoc}
 172      */
 173     public void setModel(ButtonModel newModel) {
 174         super.setModel(newModel);
 175         if(newModel instanceof DefaultButtonModel) {
 176             ((DefaultButtonModel)newModel).setMenuItem(true);
 177         }
 178     }
 179 
 180     /**
 181      * Inititalizes the focusability of the {@code JMenuItem}.
 182      * {@code JMenuItem}'s are focusable, but subclasses may
 183      * want to be, this provides them the opportunity to override this
 184      * and invoke something else, or nothing at all. Refer to
 185      * {@link javax.swing.JMenu#initFocusability} for the motivation of
 186      * this.
 187      */
 188     void initFocusability() {
 189         setFocusable(false);
 190     }
 191 
 192     /**
 193      * Initializes the menu item with the specified text and icon.
 194      *
 195      * @param text the text of the {@code JMenuItem}
 196      * @param icon the icon of the {@code JMenuItem}
 197      */
 198     protected void init(String text, Icon icon) {
 199         if(text != null) {
 200             setText(text);
 201         }
 202 
 203         if(icon != null) {
 204             setIcon(icon);
 205         }
 206 
 207         // Listen for Focus events
 208         addFocusListener(new MenuItemFocusListener());
 209         setUIProperty("borderPainted", Boolean.FALSE);
 210         setFocusPainted(false);
 211         setHorizontalTextPosition(JButton.TRAILING);
 212         setHorizontalAlignment(JButton.LEADING);
 213         updateUI();
 214     }
 215 
 216     private static class MenuItemFocusListener implements FocusListener,
 217         Serializable {
 218         public void focusGained(FocusEvent event) {}
 219         public void focusLost(FocusEvent event) {
 220             // When focus is lost, repaint if
 221             // the focus information is painted
 222             JMenuItem mi = (JMenuItem)event.getSource();
 223             if(mi.isFocusPainted()) {
 224                 mi.repaint();
 225             }
 226         }
 227     }
 228 
 229 
 230     /**
 231      * Sets the look and feel object that renders this component.
 232      *
 233      * @param ui  the {@code JMenuItemUI} L&amp;F object
 234      * @see UIDefaults#getUI
 235      * @beaninfo
 236      *        bound: true
 237      *       hidden: true
 238      *    attribute: visualUpdate true
 239      *  description: The UI object that implements the Component's LookAndFeel.
 240      */
 241     public void setUI(MenuItemUI ui) {
 242         super.setUI(ui);
 243     }
 244 
 245     /**
 246      * Resets the UI property with a value from the current look and feel.
 247      *
 248      * @see JComponent#updateUI
 249      */
 250     public void updateUI() {
 251         setUI((MenuItemUI)UIManager.getUI(this));
 252     }
 253 


 298 
 299     /**
 300      * Enables or disables the menu item.
 301      *
 302      * @param b  true to enable the item
 303      * @beaninfo
 304      *    description: Does the component react to user interaction
 305      *          bound: true
 306      *      preferred: true
 307      */
 308     public void setEnabled(boolean b) {
 309         // Make sure we aren't armed!
 310         if (!b && !UIManager.getBoolean("MenuItem.disabledAreNavigable")) {
 311             setArmed(false);
 312         }
 313         super.setEnabled(b);
 314     }
 315 
 316 
 317     /**
 318      * Returns true since {@code Menu}s, by definition,
 319      * should always be on top of all other windows.  If the menu is
 320      * in an internal frame false is returned due to the rollover effect
 321      * for windows laf where the menu is not always on top.
 322      */
 323     // package private
 324     boolean alwaysOnTop() {
 325         // Fix for bug #4482165
 326         if (SwingUtilities.getAncestorOfClass(JInternalFrame.class, this) !=
 327                 null) {
 328             return false;
 329         }
 330         return true;
 331     }
 332 
 333 
 334     /* The keystroke which acts as the menu item's accelerator
 335      */
 336     private KeyStroke accelerator;
 337 
 338     /**
 339      * Sets the key combination which invokes the menu item's
 340      * action listeners without navigating the menu hierarchy. It is the
 341      * UI's responsibility to install the correct action.  Note that
 342      * when the keyboard accelerator is typed, it will work whether or
 343      * not the menu is currently displayed.
 344      *
 345      * @param keyStroke the {@code KeyStroke} which will
 346      *          serve as an accelerator
 347      * @beaninfo
 348      *     description: The keystroke combination which will invoke the
 349      *                  JMenuItem's actionlisteners without navigating the
 350      *                  menu hierarchy
 351      *           bound: true
 352      *       preferred: true
 353      */
 354     public void setAccelerator(KeyStroke keyStroke) {
 355         KeyStroke oldAccelerator = accelerator;
 356         this.accelerator = keyStroke;
 357         repaint();
 358         revalidate();
 359         firePropertyChange("accelerator", oldAccelerator, accelerator);
 360     }
 361 
 362     /**
 363      * Returns the {@code KeyStroke} which serves as an accelerator
 364      * for the menu item.
 365      * @return a {@code KeyStroke} object identifying the
 366      *          accelerator key
 367      */
 368     public KeyStroke getAccelerator() {
 369         return this.accelerator;
 370     }
 371 
 372     /**
 373      * {@inheritDoc}
 374      *
 375      * @since 1.3
 376      */
 377     protected void configurePropertiesFromAction(Action a) {
 378         super.configurePropertiesFromAction(a);
 379         configureAcceleratorFromAction(a);
 380     }
 381 
 382     void setIconFromAction(Action a) {
 383         Icon icon = null;
 384         if (a != null) {
 385             icon = (Icon)a.getValue(Action.SMALL_ICON);


 398         KeyStroke ks = (a==null) ? null :
 399             (KeyStroke)a.getValue(Action.ACCELERATOR_KEY);
 400         setAccelerator(ks);
 401     }
 402 
 403     /**
 404      * {@inheritDoc}
 405      * @since 1.6
 406      */
 407     protected void actionPropertyChanged(Action action, String propertyName) {
 408         if (propertyName == Action.ACCELERATOR_KEY) {
 409             configureAcceleratorFromAction(action);
 410         }
 411         else {
 412             super.actionPropertyChanged(action, propertyName);
 413         }
 414     }
 415 
 416     /**
 417      * Processes a mouse event forwarded from the
 418      * {@code MenuSelectionManager} and changes the menu
 419      * selection, if necessary, by using the
 420      * {@code MenuSelectionManager}'s API.
 421      * <p>
 422      * Note: you do not have to forward the event to sub-components.
 423      * This is done automatically by the {@code MenuSelectionManager}.
 424      *
 425      * @param e   a {@code MouseEvent}
 426      * @param path  the {@code MenuElement} path array
 427      * @param manager   the {@code MenuSelectionManager}
 428      */
 429     public void processMouseEvent(MouseEvent e,MenuElement path[],MenuSelectionManager manager) {
 430         processMenuDragMouseEvent(
 431                  new MenuDragMouseEvent(e.getComponent(), e.getID(),
 432                                         e.getWhen(),
 433                                         e.getModifiers(), e.getX(), e.getY(),
 434                                         e.getXOnScreen(), e.getYOnScreen(),
 435                                         e.getClickCount(), e.isPopupTrigger(),
 436                                         path, manager));
 437     }
 438 
 439 
 440     /**
 441      * Processes a key event forwarded from the
 442      * {@code MenuSelectionManager} and changes the menu selection,
 443      * if necessary, by using {@code MenuSelectionManager}'s API.
 444      * <p>
 445      * Note: you do not have to forward the event to sub-components.
 446      * This is done automatically by the {@code MenuSelectionManager}.
 447      *
 448      * @param e  a {@code KeyEvent}
 449      * @param path the {@code MenuElement} path array
 450      * @param manager   the {@code MenuSelectionManager}
 451      */
 452     public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
 453         if (DEBUG) {
 454             System.out.println("in JMenuItem.processKeyEvent/3 for " + getText() +
 455                                    "  " + KeyStroke.getKeyStrokeForEvent(e));
 456         }
 457         MenuKeyEvent mke = new MenuKeyEvent(e.getComponent(), e.getID(),
 458                                              e.getWhen(), e.getModifiers(),
 459                                              e.getKeyCode(), e.getKeyChar(),
 460                                              path, manager);
 461         processMenuKeyEvent(mke);
 462 
 463         if (mke.isConsumed())  {
 464             e.consume();
 465         }
 466     }
 467 
 468 
 469 
 470     /**
 471      * Handles mouse drag in a menu.
 472      *
 473      * @param e  a {@code MenuDragMouseEvent} object
 474      */
 475     public void processMenuDragMouseEvent(MenuDragMouseEvent e) {
 476         switch (e.getID()) {
 477         case MouseEvent.MOUSE_ENTERED:
 478             isMouseDragged = false; fireMenuDragMouseEntered(e); break;
 479         case MouseEvent.MOUSE_EXITED:
 480             isMouseDragged = false; fireMenuDragMouseExited(e); break;
 481         case MouseEvent.MOUSE_DRAGGED:
 482             isMouseDragged = true; fireMenuDragMouseDragged(e); break;
 483         case MouseEvent.MOUSE_RELEASED:
 484             if(isMouseDragged) fireMenuDragMouseReleased(e); break;
 485         default:
 486             break;
 487         }
 488     }
 489 
 490     /**
 491      * Handles a keystroke in a menu.
 492      *
 493      * @param e  a {@code MenuKeyEvent} object
 494      */
 495     public void processMenuKeyEvent(MenuKeyEvent e) {
 496         if (DEBUG) {
 497             System.out.println("in JMenuItem.processMenuKeyEvent for " + getText()+
 498                                    "  " + KeyStroke.getKeyStrokeForEvent(e));
 499         }
 500         switch (e.getID()) {
 501         case KeyEvent.KEY_PRESSED:
 502             fireMenuKeyPressed(e); break;
 503         case KeyEvent.KEY_RELEASED:
 504             fireMenuKeyReleased(e); break;
 505         case KeyEvent.KEY_TYPED:
 506             fireMenuKeyTyped(e); break;
 507         default:
 508             break;
 509         }
 510     }
 511 
 512     /**
 513      * Notifies all listeners that have registered interest for
 514      * notification on this event type.
 515      *
 516      * @param event a {@code MenuMouseDragEvent}
 517      * @see EventListenerList
 518      */
 519     protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) {
 520         // Guaranteed to return a non-null array
 521         Object[] listeners = listenerList.getListenerList();
 522         // Process the listeners last to first, notifying
 523         // those that are interested in this event
 524         for (int i = listeners.length-2; i>=0; i-=2) {
 525             if (listeners[i]==MenuDragMouseListener.class) {
 526                 // Lazily create the event:
 527                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseEntered(event);
 528             }
 529         }
 530     }
 531 
 532     /**
 533      * Notifies all listeners that have registered interest for
 534      * notification on this event type.
 535      *
 536      * @param event a {@code MenuDragMouseEvent}
 537      * @see EventListenerList
 538      */
 539     protected void fireMenuDragMouseExited(MenuDragMouseEvent event) {
 540         // Guaranteed to return a non-null array
 541         Object[] listeners = listenerList.getListenerList();
 542         // Process the listeners last to first, notifying
 543         // those that are interested in this event
 544         for (int i = listeners.length-2; i>=0; i-=2) {
 545             if (listeners[i]==MenuDragMouseListener.class) {
 546                 // Lazily create the event:
 547                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseExited(event);
 548             }
 549         }
 550     }
 551 
 552     /**
 553      * Notifies all listeners that have registered interest for
 554      * notification on this event type.
 555      *
 556      * @param event a {@code MenuDragMouseEvent}
 557      * @see EventListenerList
 558      */
 559     protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) {
 560         // Guaranteed to return a non-null array
 561         Object[] listeners = listenerList.getListenerList();
 562         // Process the listeners last to first, notifying
 563         // those that are interested in this event
 564         for (int i = listeners.length-2; i>=0; i-=2) {
 565             if (listeners[i]==MenuDragMouseListener.class) {
 566                 // Lazily create the event:
 567                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseDragged(event);
 568             }
 569         }
 570     }
 571 
 572     /**
 573      * Notifies all listeners that have registered interest for
 574      * notification on this event type.
 575      *
 576      * @param event a {@code MenuDragMouseEvent}
 577      * @see EventListenerList
 578      */
 579     protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) {
 580         // Guaranteed to return a non-null array
 581         Object[] listeners = listenerList.getListenerList();
 582         // Process the listeners last to first, notifying
 583         // those that are interested in this event
 584         for (int i = listeners.length-2; i>=0; i-=2) {
 585             if (listeners[i]==MenuDragMouseListener.class) {
 586                 // Lazily create the event:
 587                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseReleased(event);
 588             }
 589         }
 590     }
 591 
 592     /**
 593      * Notifies all listeners that have registered interest for
 594      * notification on this event type.
 595      *
 596      * @param event a {@code MenuKeyEvent}
 597      * @see EventListenerList
 598      */
 599     protected void fireMenuKeyPressed(MenuKeyEvent event) {
 600         if (DEBUG) {
 601             System.out.println("in JMenuItem.fireMenuKeyPressed for " + getText()+
 602                                    "  " + KeyStroke.getKeyStrokeForEvent(event));
 603         }
 604         // Guaranteed to return a non-null array
 605         Object[] listeners = listenerList.getListenerList();
 606         // Process the listeners last to first, notifying
 607         // those that are interested in this event
 608         for (int i = listeners.length-2; i>=0; i-=2) {
 609             if (listeners[i]==MenuKeyListener.class) {
 610                 // Lazily create the event:
 611                 ((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
 612             }
 613         }
 614     }
 615 
 616     /**
 617      * Notifies all listeners that have registered interest for
 618      * notification on this event type.
 619      *
 620      * @param event a {@code MenuKeyEvent}
 621      * @see EventListenerList
 622      */
 623     protected void fireMenuKeyReleased(MenuKeyEvent event) {
 624         if (DEBUG) {
 625             System.out.println("in JMenuItem.fireMenuKeyReleased for " + getText()+
 626                                    "  " + KeyStroke.getKeyStrokeForEvent(event));
 627         }
 628         // Guaranteed to return a non-null array
 629         Object[] listeners = listenerList.getListenerList();
 630         // Process the listeners last to first, notifying
 631         // those that are interested in this event
 632         for (int i = listeners.length-2; i>=0; i-=2) {
 633             if (listeners[i]==MenuKeyListener.class) {
 634                 // Lazily create the event:
 635                 ((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
 636             }
 637         }
 638     }
 639 
 640     /**
 641      * Notifies all listeners that have registered interest for
 642      * notification on this event type.
 643      *
 644      * @param event a {@code MenuKeyEvent}
 645      * @see EventListenerList
 646      */
 647     protected void fireMenuKeyTyped(MenuKeyEvent event) {
 648         if (DEBUG) {
 649             System.out.println("in JMenuItem.fireMenuKeyTyped for " + getText()+
 650                                    "  " + KeyStroke.getKeyStrokeForEvent(event));
 651         }
 652         // Guaranteed to return a non-null array
 653         Object[] listeners = listenerList.getListenerList();
 654         // Process the listeners last to first, notifying
 655         // those that are interested in this event
 656         for (int i = listeners.length-2; i>=0; i-=2) {
 657             if (listeners[i]==MenuKeyListener.class) {
 658                 // Lazily create the event:
 659                 ((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
 660             }
 661         }
 662     }
 663 
 664     /**
 665      * Called by the {@code MenuSelectionManager} when the
 666      * {@code MenuElement} is selected or unselected.
 667      *
 668      * @param isIncluded  true if this menu item is on the part of the menu
 669      *                    path that changed, false if this menu is part of the
 670      *                    a menu path that changed, but this particular part of
 671      *                    that path is still the same
 672      * @see MenuSelectionManager#setSelectedPath(MenuElement[])
 673      */
 674     public void menuSelectionChanged(boolean isIncluded) {
 675         setArmed(isIncluded);
 676     }
 677 
 678     /**
 679      * This method returns an array containing the sub-menu
 680      * components for this menu component.
 681      *
 682      * @return an array of {@code MenuElement}s
 683      */
 684     public MenuElement[] getSubElements() {
 685         return new MenuElement[0];
 686     }
 687 
 688     /**
 689      * Returns the {@code java.awt.Component} used to paint
 690      * this object. The returned component will be used to convert
 691      * events and detect if an event is inside a menu component.
 692      *
 693      * @return the {@code Component} that paints this menu item
 694      */
 695     public Component getComponent() {
 696         return this;
 697     }
 698 
 699     /**
 700      * Adds a {@code MenuDragMouseListener} to the menu item.
 701      *
 702      * @param l the {@code MenuDragMouseListener} to be added
 703      */
 704     public void addMenuDragMouseListener(MenuDragMouseListener l) {
 705         listenerList.add(MenuDragMouseListener.class, l);
 706     }
 707 
 708     /**
 709      * Removes a {@code MenuDragMouseListener} from the menu item.
 710      *
 711      * @param l the {@code MenuDragMouseListener} to be removed
 712      */
 713     public void removeMenuDragMouseListener(MenuDragMouseListener l) {
 714         listenerList.remove(MenuDragMouseListener.class, l);
 715     }
 716 
 717     /**
 718      * Returns an array of all the {@code MenuDragMouseListener}s added
 719      * to this JMenuItem with addMenuDragMouseListener().
 720      *
 721      * @return all of the {@code MenuDragMouseListener}s added or an empty
 722      *         array if no listeners have been added
 723      * @since 1.4
 724      */
 725     public MenuDragMouseListener[] getMenuDragMouseListeners() {
 726         return listenerList.getListeners(MenuDragMouseListener.class);
 727     }
 728 
 729     /**
 730      * Adds a {@code MenuKeyListener} to the menu item.
 731      *
 732      * @param l the {@code MenuKeyListener} to be added
 733      */
 734     public void addMenuKeyListener(MenuKeyListener l) {
 735         listenerList.add(MenuKeyListener.class, l);
 736     }
 737 
 738     /**
 739      * Removes a {@code MenuKeyListener} from the menu item.
 740      *
 741      * @param l the {@code MenuKeyListener} to be removed
 742      */
 743     public void removeMenuKeyListener(MenuKeyListener l) {
 744         listenerList.remove(MenuKeyListener.class, l);
 745     }
 746 
 747     /**
 748      * Returns an array of all the {@code MenuKeyListener}s added
 749      * to this JMenuItem with addMenuKeyListener().
 750      *
 751      * @return all of the {@code MenuKeyListener}s added or an empty
 752      *         array if no listeners have been added
 753      * @since 1.4
 754      */
 755     public MenuKeyListener[] getMenuKeyListeners() {
 756         return listenerList.getListeners(MenuKeyListener.class);
 757     }
 758 
 759     /**
 760      * See JComponent.readObject() for information about serialization
 761      * in Swing.
 762      */
 763     private void readObject(ObjectInputStream s)
 764         throws IOException, ClassNotFoundException
 765     {
 766         s.defaultReadObject();
 767         if (getUIClassID().equals(uiClassID)) {
 768             updateUI();
 769         }
 770     }
 771 
 772     private void writeObject(ObjectOutputStream s) throws IOException {
 773         s.defaultWriteObject();
 774         if (getUIClassID().equals(uiClassID)) {
 775             byte count = JComponent.getWriteObjCounter(this);
 776             JComponent.setWriteObjCounter(this, --count);
 777             if (count == 0 && ui != null) {
 778                 ui.installUI(this);
 779             }
 780         }
 781     }
 782 
 783 
 784     /**
 785      * Returns a string representation of this {@code JMenuItem}.
 786      * This method is intended to be used only for debugging purposes,
 787      * and the content and format of the returned string may vary between
 788      * implementations. The returned string may be empty but may not
 789      * be {@code null}.
 790      *
 791      * @return  a string representation of this {@code JMenuItem}
 792      */
 793     protected String paramString() {
 794         return super.paramString();
 795     }
 796 
 797 /////////////////
 798 // Accessibility support
 799 ////////////////
 800 
 801     /**
 802      * Returns the {@code AccessibleContext} associated with this
 803      * {@code JMenuItem}. For {@code JMenuItem}s,
 804      * the {@code AccessibleContext} takes the form of an
 805      * {@code AccessibleJMenuItem}.
 806      * A new AccessibleJMenuItme instance is created if necessary.
 807      *
 808      * @return an {@code AccessibleJMenuItem} that serves as the
 809      *         {@code AccessibleContext} of this {@code JMenuItem}
 810      */
 811     public AccessibleContext getAccessibleContext() {
 812         if (accessibleContext == null) {
 813             accessibleContext = new AccessibleJMenuItem();
 814         }
 815         return accessibleContext;
 816     }
 817 
 818 
 819     /**
 820      * This class implements accessibility support for the
 821      * {@code JMenuItem} class.  It provides an implementation of the
 822      * Java Accessibility API appropriate to menu item user-interface
 823      * elements.
 824      * <p>
 825      * <strong>Warning:</strong>
 826      * Serialized objects of this class will not be compatible with
 827      * future Swing releases. The current serialization support is
 828      * appropriate for short term storage or RMI between applications running
 829      * the same version of Swing.  As of 1.4, support for long term storage
 830      * of all JavaBeans&trade;
 831      * has been added to the {@code java.beans} package.
 832      * Please see {@link java.beans.XMLEncoder}.
 833      */
 834     @SuppressWarnings("serial")
 835     protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener {
 836 
 837         private boolean isArmed = false;
 838         private boolean hasFocus = false;
 839         private boolean isPressed = false;
 840         private boolean isSelected = false;
 841 
 842         AccessibleJMenuItem() {
 843             super();
 844             JMenuItem.this.addChangeListener(this);
 845         }
 846 
 847         /**
 848          * Get the role of this object.
 849          *
 850          * @return an instance of AccessibleRole describing the role of the
 851          * object


< prev index next >