Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]
    1   /*
    2    * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   package javax.swing;
   26   
   27   import java.util.EventListener;
   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://java.sun.com/docs/books/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://java.sun.com/docs/books/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<sup><font size="-2">TM</font></sup>
   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    */
   90   public class JMenuItem extends AbstractButton implements Accessible,MenuElement  {
   91   
   92       /**
   93        * @see #getUIClassID
   94        * @see #readObject
   95        */
   96       private static final String uiClassID = "MenuItemUI";
   97   
   98       /* diagnostic aids -- should be false for production builds. */
   99       private static final boolean TRACE =   false; // trace creates and disposes
  100       private static final boolean VERBOSE = false; // show reuse hits/misses
  101       private static final boolean DEBUG =   false;  // show bad params, misc.
  102   
  103       private boolean isMouseDragged = false;
  104   
  105       /**
  106        * Creates a <code>JMenuItem</code> with no set text or icon.
  107        */
  108       public JMenuItem() {
  109           this(null, (Icon)null);
  110       }
  111   
  112       /**
  113        * Creates a <code>JMenuItem</code> with the specified icon.
  114        *
  115        * @param icon the icon of the <code>JMenuItem</code>
  116        */
  117       public JMenuItem(Icon icon) {
  118           this(null, icon);
  119       }
  120   
  121       /**
  122        * Creates a <code>JMenuItem</code> with the specified text.
  123        *
  124        * @param text the text of the <code>JMenuItem</code>
  125        */
  126       public JMenuItem(String text) {
  127           this(text, (Icon)null);
  128       }
  129   
  130       /**
  131        * Creates a menu item whose properties are taken from the
  132        * specified <code>Action</code>.
  133        *
  134        * @param a the action of the <code>JMenuItem</code>
  135        * @since 1.3
  136        */
  137       public JMenuItem(Action a) {
  138           this();
  139           setAction(a);
  140       }
  141   
  142       /**
  143        * Creates a <code>JMenuItem</code> with the specified text and icon.
  144        *
  145        * @param text the text of the <code>JMenuItem</code>
  146        * @param icon the icon of the <code>JMenuItem</code>
  147        */
  148       public JMenuItem(String text, Icon icon) {
  149           setModel(new DefaultButtonModel());
  150           init(text, icon);
  151           initFocusability();
  152       }
  153   
  154       /**
  155        * Creates a <code>JMenuItem</code> with the specified text and
  156        * keyboard mnemonic.
  157        *
  158        * @param text the text of the <code>JMenuItem</code>
  159        * @param mnemonic the keyboard mnemonic for the <code>JMenuItem</code>
  160        */
  161       public JMenuItem(String text, int mnemonic) {
  162           setModel(new DefaultButtonModel());
  163           init(text, null);
  164           setMnemonic(mnemonic);
  165           initFocusability();
  166       }
  167   
  168       /**
  169        * {@inheritDoc}
  170        */
  171       public void setModel(ButtonModel newModel) {
  172           super.setModel(newModel);
  173           if(newModel instanceof DefaultButtonModel) {
  174               ((DefaultButtonModel)newModel).setMenuItem(true);
  175           }
  176       }
  177   
  178       /**
  179        * Inititalizes the focusability of the the <code>JMenuItem</code>.
  180        * <code>JMenuItem</code>'s are focusable, but subclasses may
  181        * want to be, this provides them the opportunity to override this
  182        * and invoke something else, or nothing at all. Refer to
  183        * {@link javax.swing.JMenu#initFocusability} for the motivation of
  184        * this.
  185        */
  186       void initFocusability() {
  187           setFocusable(false);
  188       }
  189   
  190       /**
  191        * Initializes the menu item with the specified text and icon.
  192        *
  193        * @param text the text of the <code>JMenuItem</code>
  194        * @param icon the icon of the <code>JMenuItem</code>
  195        */
  196       protected void init(String text, Icon icon) {
  197           if(text != null) {
  198               setText(text);
  199           }
  200   
  201           if(icon != null) {
  202               setIcon(icon);
  203           }
  204   
  205           // Listen for Focus events
  206           addFocusListener(new MenuItemFocusListener());
  207           setUIProperty("borderPainted", Boolean.FALSE);
  208           setFocusPainted(false);
  209           setHorizontalTextPosition(JButton.TRAILING);
  210           setHorizontalAlignment(JButton.LEADING);
  211           updateUI();
  212       }
  213   
  214       private static class MenuItemFocusListener implements FocusListener,
  215           Serializable {
  216           public void focusGained(FocusEvent event) {}
  217           public void focusLost(FocusEvent event) {
  218               // When focus is lost, repaint if
  219               // the focus information is painted
  220               JMenuItem mi = (JMenuItem)event.getSource();
  221               if(mi.isFocusPainted()) {
  222                   mi.repaint();
  223               }
  224           }
  225       }
  226   
  227   
  228       /**
  229        * Sets the look and feel object that renders this component.
  230        *
  231        * @param ui  the <code>JMenuItemUI</code> L&F object
  232        * @see UIDefaults#getUI
  233        * @beaninfo
  234        *        bound: true
  235        *       hidden: true
  236        *    attribute: visualUpdate true
  237        *  description: The UI object that implements the Component's LookAndFeel.
  238        */
  239       public void setUI(MenuItemUI ui) {
  240           super.setUI(ui);
  241       }
  242   
  243       /**
  244        * Resets the UI property with a value from the current look and feel.
  245        *
  246        * @see JComponent#updateUI
  247        */
  248       public void updateUI() {
  249           setUI((MenuItemUI)UIManager.getUI(this));
  250       }
  251   
  252   
  253       /**
  254        * Returns the suffix used to construct the name of the L&F class used to
  255        * render this component.
  256        *
  257        * @return the string "MenuItemUI"
  258        * @see JComponent#getUIClassID
  259        * @see UIDefaults#getUI
  260        */
  261       public String getUIClassID() {
  262           return uiClassID;
  263       }
  264   
  265   
  266       /**
  267        * Identifies the menu item as "armed". If the mouse button is
  268        * released while it is over this item, the menu's action event
  269        * will fire. If the mouse button is released elsewhere, the
  270        * event will not fire and the menu item will be disarmed.
  271        *
  272        * @param b true to arm the menu item so it can be selected
  273        * @beaninfo
  274        *    description: Mouse release will fire an action event
  275        *         hidden: true
  276        */
  277       public void setArmed(boolean b) {
  278           ButtonModel model = (ButtonModel) getModel();
  279   
  280           boolean oldValue = model.isArmed();
  281           if(model.isArmed() != b) {
  282               model.setArmed(b);
  283           }
  284       }
  285   
  286       /**
  287        * Returns whether the menu item is "armed".
  288        *
  289        * @return true if the menu item is armed, and it can be selected
  290        * @see #setArmed
  291        */
  292       public boolean isArmed() {
  293           ButtonModel model = (ButtonModel) getModel();
  294           return model.isArmed();
  295       }
  296   
  297       /**
  298        * Enables or disables the menu item.
  299        *
  300        * @param b  true to enable the item
  301        * @beaninfo
  302        *    description: Does the component react to user interaction
  303        *          bound: true
  304        *      preferred: true
  305        */
  306       public void setEnabled(boolean b) {
  307           // Make sure we aren't armed!
  308           if (!b && !UIManager.getBoolean("MenuItem.disabledAreNavigable")) {
  309               setArmed(false);
  310           }
  311           super.setEnabled(b);
  312       }
  313   
  314   
  315       /**
  316        * Returns true since <code>Menu</code>s, by definition,
  317        * should always be on top of all other windows.  If the menu is
  318        * in an internal frame false is returned due to the rollover effect
  319        * for windows laf where the menu is not always on top.
  320        */
  321       // package private
  322       boolean alwaysOnTop() {
  323           // Fix for bug #4482165
  324           if (SwingUtilities.getAncestorOfClass(JInternalFrame.class, this) !=
  325                   null) {
  326               return false;
  327           }
  328           return true;
  329       }
  330   
  331   
  332       /* The keystroke which acts as the menu item's accelerator
  333        */
  334       private KeyStroke accelerator;
  335   
  336       /**
  337        * Sets the key combination which invokes the menu item's
  338        * action listeners without navigating the menu hierarchy. It is the
  339        * UI's responsibility to install the correct action.  Note that
  340        * when the keyboard accelerator is typed, it will work whether or
  341        * not the menu is currently displayed.
  342        *
  343        * @param keyStroke the <code>KeyStroke</code> which will
  344        *          serve as an accelerator
  345        * @beaninfo
  346        *     description: The keystroke combination which will invoke the
  347        *                  JMenuItem's actionlisteners without navigating the
  348        *                  menu hierarchy
  349        *           bound: true
  350        *       preferred: true
  351        */
  352       public void setAccelerator(KeyStroke keyStroke) {
  353           KeyStroke oldAccelerator = accelerator;
  354           this.accelerator = keyStroke;
  355           repaint();
  356           revalidate();
  357           firePropertyChange("accelerator", oldAccelerator, accelerator);
  358       }
  359   
  360       /**
  361        * Returns the <code>KeyStroke</code> which serves as an accelerator
  362        * for the menu item.
  363        * @return a <code>KeyStroke</code> object identifying the
  364        *          accelerator key
  365        */
  366       public KeyStroke getAccelerator() {
  367           return this.accelerator;
  368       }
  369   
  370       /**
  371        * {@inheritDoc}
  372        *
  373        * @since 1.3
  374        */
  375       protected void configurePropertiesFromAction(Action a) {
  376           super.configurePropertiesFromAction(a);
  377           configureAcceleratorFromAction(a);
  378       }
  379   
  380       void setIconFromAction(Action a) {
  381           Icon icon = null;
  382           if (a != null) {
  383               icon = (Icon)a.getValue(Action.SMALL_ICON);
  384           }
  385           setIcon(icon);
  386       }
  387   
  388       void largeIconChanged(Action a) {
  389       }
  390   
  391       void smallIconChanged(Action a) {
  392           setIconFromAction(a);
  393       }
  394   
  395       void configureAcceleratorFromAction(Action a) {
  396           KeyStroke ks = (a==null) ? null :
  397               (KeyStroke)a.getValue(Action.ACCELERATOR_KEY);
  398           setAccelerator(ks);
  399       }
  400   
  401       /**
  402        * {@inheritDoc}
  403        * @since 1.6
  404        */
  405       protected void actionPropertyChanged(Action action, String propertyName) {
  406           if (propertyName == Action.ACCELERATOR_KEY) {
  407               configureAcceleratorFromAction(action);
  408           }
  409           else {
  410               super.actionPropertyChanged(action, propertyName);
  411           }
  412       }
  413   
  414       /**
  415        * Processes a mouse event forwarded from the
  416        * <code>MenuSelectionManager</code> and changes the menu
  417        * selection, if necessary, by using the
  418        * <code>MenuSelectionManager</code>'s API.
  419        * <p>
  420        * Note: you do not have to forward the event to sub-components.
  421        * This is done automatically by the <code>MenuSelectionManager</code>.
  422        *
  423        * @param e   a <code>MouseEvent</code>
  424        * @param path  the <code>MenuElement</code> path array
  425        * @param manager   the <code>MenuSelectionManager</code>
  426        */
  427       public void processMouseEvent(MouseEvent e,MenuElement path[],MenuSelectionManager manager) {
  428           processMenuDragMouseEvent(
  429                    new MenuDragMouseEvent(e.getComponent(), e.getID(),
  430                                           e.getWhen(),
  431                                           e.getModifiers(), e.getX(), e.getY(),
  432                                           e.getXOnScreen(), e.getYOnScreen(),
  433                                           e.getClickCount(), e.isPopupTrigger(),
  434                                           path, manager));
  435       }
  436   
  437   
  438       /**
  439        * Processes a key event forwarded from the
  440        * <code>MenuSelectionManager</code> and changes the menu selection,
  441        * if necessary, by using <code>MenuSelectionManager</code>'s API.
  442        * <p>
  443        * Note: you do not have to forward the event to sub-components.
  444        * This is done automatically by the <code>MenuSelectionManager</code>.
  445        *
  446        * @param e  a <code>KeyEvent</code>
  447        * @param path the <code>MenuElement</code> path array
  448        * @param manager   the <code>MenuSelectionManager</code>
  449        */
  450       public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
  451           if (DEBUG) {
  452               System.out.println("in JMenuItem.processKeyEvent/3 for " + getText() +
  453                                      "  " + KeyStroke.getKeyStrokeForEvent(e));
  454           }
  455           MenuKeyEvent mke = new MenuKeyEvent(e.getComponent(), e.getID(),
  456                                                e.getWhen(), e.getModifiers(),
  457                                                e.getKeyCode(), e.getKeyChar(),
  458                                                path, manager);
  459           processMenuKeyEvent(mke);
  460   
  461           if (mke.isConsumed())  {
  462               e.consume();
  463           }
  464       }
  465   
  466   
  467   
  468       /**
  469        * Handles mouse drag in a menu.
  470        *
  471        * @param e  a <code>MenuDragMouseEvent</code> object
  472        */
  473       public void processMenuDragMouseEvent(MenuDragMouseEvent e) {
  474           switch (e.getID()) {
  475           case MouseEvent.MOUSE_ENTERED:
  476               isMouseDragged = false; fireMenuDragMouseEntered(e); break;
  477           case MouseEvent.MOUSE_EXITED:
  478               isMouseDragged = false; fireMenuDragMouseExited(e); break;
  479           case MouseEvent.MOUSE_DRAGGED:
  480               isMouseDragged = true; fireMenuDragMouseDragged(e); break;
  481           case MouseEvent.MOUSE_RELEASED:
  482               if(isMouseDragged) fireMenuDragMouseReleased(e); break;
  483           default:
  484               break;
  485           }
  486       }
  487   
  488       /**
  489        * Handles a keystroke in a menu.
  490        *
  491        * @param e  a <code>MenuKeyEvent</code> object
  492        */
  493       public void processMenuKeyEvent(MenuKeyEvent e) {
  494           if (DEBUG) {
  495               System.out.println("in JMenuItem.processMenuKeyEvent for " + getText()+
  496                                      "  " + KeyStroke.getKeyStrokeForEvent(e));
  497           }
  498           switch (e.getID()) {
  499           case KeyEvent.KEY_PRESSED:
  500               fireMenuKeyPressed(e); break;
  501           case KeyEvent.KEY_RELEASED:
  502               fireMenuKeyReleased(e); break;
  503           case KeyEvent.KEY_TYPED:
  504               fireMenuKeyTyped(e); break;
  505           default:
  506               break;
  507           }
  508       }
  509   
  510       /**
  511        * Notifies all listeners that have registered interest for
  512        * notification on this event type.
  513        *
  514        * @param event a <code>MenuMouseDragEvent</code>
  515        * @see EventListenerList
  516        */
  517       protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) {
  518           // Guaranteed to return a non-null array
  519           Object[] listeners = listenerList.getListenerList();
  520           // Process the listeners last to first, notifying
  521           // those that are interested in this event
  522           for (int i = listeners.length-2; i>=0; i-=2) {
  523               if (listeners[i]==MenuDragMouseListener.class) {
  524                   // Lazily create the event:
  525                   ((MenuDragMouseListener)listeners[i+1]).menuDragMouseEntered(event);
  526               }
  527           }
  528       }
  529   
  530       /**
  531        * Notifies all listeners that have registered interest for
  532        * notification on this event type.
  533        *
  534        * @param event a <code>MenuDragMouseEvent</code>
  535        * @see EventListenerList
  536        */
  537       protected void fireMenuDragMouseExited(MenuDragMouseEvent event) {
  538           // Guaranteed to return a non-null array
  539           Object[] listeners = listenerList.getListenerList();
  540           // Process the listeners last to first, notifying
  541           // those that are interested in this event
  542           for (int i = listeners.length-2; i>=0; i-=2) {
  543               if (listeners[i]==MenuDragMouseListener.class) {
  544                   // Lazily create the event:
  545                   ((MenuDragMouseListener)listeners[i+1]).menuDragMouseExited(event);
  546               }
  547           }
  548       }
  549   
  550       /**
  551        * Notifies all listeners that have registered interest for
  552        * notification on this event type.
  553        *
  554        * @param event a <code>MenuDragMouseEvent</code>
  555        * @see EventListenerList
  556        */
  557       protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) {
  558           // Guaranteed to return a non-null array
  559           Object[] listeners = listenerList.getListenerList();
  560           // Process the listeners last to first, notifying
  561           // those that are interested in this event
  562           for (int i = listeners.length-2; i>=0; i-=2) {
  563               if (listeners[i]==MenuDragMouseListener.class) {
  564                   // Lazily create the event:
  565                   ((MenuDragMouseListener)listeners[i+1]).menuDragMouseDragged(event);
  566               }
  567           }
  568       }
  569   
  570       /**
  571        * Notifies all listeners that have registered interest for
  572        * notification on this event type.
  573        *
  574        * @param event a <code>MenuDragMouseEvent</code>
  575        * @see EventListenerList
  576        */
  577       protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) {
  578           // Guaranteed to return a non-null array
  579           Object[] listeners = listenerList.getListenerList();
  580           // Process the listeners last to first, notifying
  581           // those that are interested in this event
  582           for (int i = listeners.length-2; i>=0; i-=2) {
  583               if (listeners[i]==MenuDragMouseListener.class) {
  584                   // Lazily create the event:
  585                   ((MenuDragMouseListener)listeners[i+1]).menuDragMouseReleased(event);
  586               }
  587           }
  588       }
  589   
  590       /**
  591        * Notifies all listeners that have registered interest for
  592        * notification on this event type.
  593        *
  594        * @param event a <code>MenuKeyEvent</code>
  595        * @see EventListenerList
  596        */
  597       protected void fireMenuKeyPressed(MenuKeyEvent event) {
  598           if (DEBUG) {
  599               System.out.println("in JMenuItem.fireMenuKeyPressed for " + getText()+
  600                                      "  " + KeyStroke.getKeyStrokeForEvent(event));
  601           }
  602           // Guaranteed to return a non-null array
  603           Object[] listeners = listenerList.getListenerList();
  604           // Process the listeners last to first, notifying
  605           // those that are interested in this event
  606           for (int i = listeners.length-2; i>=0; i-=2) {
  607               if (listeners[i]==MenuKeyListener.class) {
  608                   // Lazily create the event:
  609                   ((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
  610               }
  611           }
  612       }
  613   
  614       /**
  615        * Notifies all listeners that have registered interest for
  616        * notification on this event type.
  617        *
  618        * @param event a <code>MenuKeyEvent</code>
  619        * @see EventListenerList
  620        */
  621       protected void fireMenuKeyReleased(MenuKeyEvent event) {
  622           if (DEBUG) {
  623               System.out.println("in JMenuItem.fireMenuKeyReleased for " + getText()+
  624                                      "  " + KeyStroke.getKeyStrokeForEvent(event));
  625           }
  626           // Guaranteed to return a non-null array
  627           Object[] listeners = listenerList.getListenerList();
  628           // Process the listeners last to first, notifying
  629           // those that are interested in this event
  630           for (int i = listeners.length-2; i>=0; i-=2) {
  631               if (listeners[i]==MenuKeyListener.class) {
  632                   // Lazily create the event:
  633                   ((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
  634               }
  635           }
  636       }
  637   
  638       /**
  639        * Notifies all listeners that have registered interest for
  640        * notification on this event type.
  641        *
  642        * @param event a <code>MenuKeyEvent</code>
  643        * @see EventListenerList
  644        */
  645       protected void fireMenuKeyTyped(MenuKeyEvent event) {
  646           if (DEBUG) {
  647               System.out.println("in JMenuItem.fireMenuKeyTyped for " + getText()+
  648                                      "  " + KeyStroke.getKeyStrokeForEvent(event));
  649           }
  650           // Guaranteed to return a non-null array
  651           Object[] listeners = listenerList.getListenerList();
  652           // Process the listeners last to first, notifying
  653           // those that are interested in this event
  654           for (int i = listeners.length-2; i>=0; i-=2) {
  655               if (listeners[i]==MenuKeyListener.class) {
  656                   // Lazily create the event:
  657                   ((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
  658               }
  659           }
  660       }
  661   
  662       /**
  663        * Called by the <code>MenuSelectionManager</code> when the
  664        * <code>MenuElement</code> is selected or unselected.
  665        *
  666        * @param isIncluded  true if this menu item is on the part of the menu
  667        *                    path that changed, false if this menu is part of the
  668        *                    a menu path that changed, but this particular part of
  669        *                    that path is still the same
  670        * @see MenuSelectionManager#setSelectedPath(MenuElement[])
  671        */
  672       public void menuSelectionChanged(boolean isIncluded) {
  673           setArmed(isIncluded);
  674       }
  675   
  676       /**
  677        * This method returns an array containing the sub-menu
  678        * components for this menu component.
  679        *
  680        * @return an array of <code>MenuElement</code>s
  681        */
  682       public MenuElement[] getSubElements() {
  683           return new MenuElement[0];
  684       }
  685   
  686       /**
  687        * Returns the <code>java.awt.Component</code> used to paint
  688        * this object. The returned component will be used to convert
  689        * events and detect if an event is inside a menu component.
  690        *
  691        * @return the <code>Component</code> that paints this menu item
  692        */
  693       public Component getComponent() {
  694           return this;
  695       }
  696   
  697       /**
  698        * Adds a <code>MenuDragMouseListener</code> to the menu item.
  699        *
  700        * @param l the <code>MenuDragMouseListener</code> to be added
  701        */
  702       public void addMenuDragMouseListener(MenuDragMouseListener l) {
  703           listenerList.add(MenuDragMouseListener.class, l);
  704       }
  705   
  706       /**
  707        * Removes a <code>MenuDragMouseListener</code> from the menu item.
  708        *
  709        * @param l the <code>MenuDragMouseListener</code> to be removed
  710        */
  711       public void removeMenuDragMouseListener(MenuDragMouseListener l) {
  712           listenerList.remove(MenuDragMouseListener.class, l);
  713       }
  714   
  715       /**
  716        * Returns an array of all the <code>MenuDragMouseListener</code>s added
  717        * to this JMenuItem with addMenuDragMouseListener().
  718        *
  719        * @return all of the <code>MenuDragMouseListener</code>s added or an empty
  720        *         array if no listeners have been added
  721        * @since 1.4
  722        */
  723       public MenuDragMouseListener[] getMenuDragMouseListeners() {
  724           return (MenuDragMouseListener[])listenerList.getListeners(
  725                   MenuDragMouseListener.class);
  726       }
  727   
  728       /**
  729        * Adds a <code>MenuKeyListener</code> to the menu item.
  730        *
  731        * @param l the <code>MenuKeyListener</code> to be added
  732        */
  733       public void addMenuKeyListener(MenuKeyListener l) {
  734           listenerList.add(MenuKeyListener.class, l);
  735       }
  736   
  737       /**
  738        * Removes a <code>MenuKeyListener</code> from the menu item.
  739        *
  740        * @param l the <code>MenuKeyListener</code> to be removed
  741        */
  742       public void removeMenuKeyListener(MenuKeyListener l) {
  743           listenerList.remove(MenuKeyListener.class, l);
  744       }
  745   
  746       /**
  747        * Returns an array of all the <code>MenuKeyListener</code>s added
  748        * to this JMenuItem with addMenuKeyListener().
  749        *
  750        * @return all of the <code>MenuKeyListener</code>s added or an empty
  751        *         array if no listeners have been added
  752        * @since 1.4
  753        */
  754       public MenuKeyListener[] getMenuKeyListeners() {
  755           return (MenuKeyListener[])listenerList.getListeners(
  756                   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<sup><font size="-2">TM</font></sup>
  831        * has been added to the <code>java.beans</code> package.
  832        * Please see {@link java.beans.XMLEncoder}.
  833        */
  834       protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener {
  835   
  836           private boolean isArmed = false;
  837           private boolean hasFocus = false;
  838           private boolean isPressed = false;
  839           private boolean isSelected = false;
  840   
  841           AccessibleJMenuItem() {
  842               super();
  843               JMenuItem.this.addChangeListener(this);
  844           }
  845   
  846           /**
  847            * Get the role of this object.
  848            *
  849            * @return an instance of AccessibleRole describing the role of the
  850            * object
  851            */
  852           public AccessibleRole getAccessibleRole() {
  853               return AccessibleRole.MENU_ITEM;
  854           }
  855   
  856           private void fireAccessibilityFocusedEvent(JMenuItem toCheck) {
  857               MenuElement [] path =
  858                   MenuSelectionManager.defaultManager().getSelectedPath();
  859               if (path.length > 0) {
  860                   Object menuItem = path[path.length - 1];
  861                   if (toCheck == menuItem) {
  862                       firePropertyChange(
  863                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  864                           null, AccessibleState.FOCUSED);
  865                   }
  866               }
  867           }
  868   
  869           /**
  870            * Supports the change listener interface and fires property changes.
  871            */
  872           public void stateChanged(ChangeEvent e) {
  873               firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  874                                  Boolean.valueOf(false), Boolean.valueOf(true));
  875               if (JMenuItem.this.getModel().isArmed()) {
  876                   if (!isArmed) {
  877                       isArmed = true;
  878                       firePropertyChange(
  879                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  880                           null, AccessibleState.ARMED);
  881                       // Fix for 4848220 moved here to avoid major memory leak
  882                       // Here we will fire the event in case of JMenuItem
  883                       // See bug 4910323 for details [zav]
  884                       fireAccessibilityFocusedEvent(JMenuItem.this);
  885                   }
  886               } else {
  887                   if (isArmed) {
  888                       isArmed = false;
  889                       firePropertyChange(
  890                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  891                           AccessibleState.ARMED, null);
  892                   }
  893               }
  894               if (JMenuItem.this.isFocusOwner()) {
  895                   if (!hasFocus) {
  896                       hasFocus = true;
  897                       firePropertyChange(
  898                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  899                           null, AccessibleState.FOCUSED);
  900                   }
  901               } else {
  902                   if (hasFocus) {
  903                       hasFocus = false;
  904                       firePropertyChange(
  905                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  906                           AccessibleState.FOCUSED, null);
  907                   }
  908               }
  909               if (JMenuItem.this.getModel().isPressed()) {
  910                   if (!isPressed) {
  911                       isPressed = true;
  912                       firePropertyChange(
  913                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  914                           null, AccessibleState.PRESSED);
  915                   }
  916               } else {
  917                   if (isPressed) {
  918                       isPressed = false;
  919                       firePropertyChange(
  920                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  921                           AccessibleState.PRESSED, null);
  922                   }
  923               }
  924               if (JMenuItem.this.getModel().isSelected()) {
  925                   if (!isSelected) {
  926                       isSelected = true;
  927                       firePropertyChange(
  928                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  929                           null, AccessibleState.CHECKED);
  930   
  931                       // Fix for 4848220 moved here to avoid major memory leak
  932                       // Here we will fire the event in case of JMenu
  933                       // See bug 4910323 for details [zav]
  934                       fireAccessibilityFocusedEvent(JMenuItem.this);
  935                   }
  936               } else {
  937                   if (isSelected) {
  938                       isSelected = false;
  939                       firePropertyChange(
  940                           AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  941                           AccessibleState.CHECKED, null);
  942                   }
  943               }
  944   
  945           }
  946       } // inner class AccessibleJMenuItem
  947   
  948   
  949   }

Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]