- /*
- * @(#)JMenuItem.java 1.118 04/03/05
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package javax.swing;
-
- import java.util.EventListener;
- import java.awt.*;
- import java.awt.event.*;
- import java.awt.image.*;
-
- import java.beans.PropertyChangeEvent;
- import java.beans.PropertyChangeListener;
-
- import java.io.Serializable;
- import java.io.ObjectOutputStream;
- import java.io.ObjectInputStream;
- import java.io.IOException;
-
- import javax.swing.plaf.*;
- import javax.swing.plaf.basic.*;
- import javax.swing.event.*;
- import javax.accessibility.*;
-
- /**
- * An implementation of an item in a menu. A menu item is essentially a button
- * sitting in a list. When the user selects the "button", the action
- * associated with the menu item is performed. A <code>JMenuItem</code>
- * contained in a <code>JPopupMenu</code> performs exactly that function.
- * <p>
- * For further documentation and for examples, see
- * <a
- href="http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html">How to Use Menus</a>
- * in <em>The Java Tutorial.</em>
- * <p>
- * <strong>Warning:</strong>
- * Serialized objects of this class will not be compatible with
- * future Swing releases. The current serialization support is
- * appropriate for short term storage or RMI between applications running
- * the same version of Swing. As of 1.4, support for long term storage
- * of all JavaBeans<sup><font size="-2">TM</font></sup>
- * has been added to the <code>java.beans</code> package.
- * Please see {@link java.beans.XMLEncoder}.
- *
- * @beaninfo
- * attribute: isContainer false
- * description: An item which can be selected in a menu.
- *
- * @version 1.118 03/05/04
- * @author Georges Saab
- * @author David Karlton
- * @see JPopupMenu
- * @see JMenu
- * @see JCheckBoxMenuItem
- * @see JRadioButtonMenuItem
- */
- public class JMenuItem extends AbstractButton implements Accessible,MenuElement {
-
- /**
- * @see #getUIClassID
- * @see #readObject
- */
- private static final String uiClassID = "MenuItemUI";
-
- /* diagnostic aids -- should be false for production builds. */
- private static final boolean TRACE = false; // trace creates and disposes
- private static final boolean VERBOSE = false; // show reuse hits/misses
- private static final boolean DEBUG = false; // show bad params, misc.
-
- private boolean isMouseDragged = false;
-
- /**
- * Creates a <code>JMenuItem</code> with no set text or icon.
- */
- public JMenuItem() {
- this(null, (Icon)null);
- }
-
- /**
- * Creates a <code>JMenuItem</code> with the specified icon.
- *
- * @param icon the icon of the <code>JMenuItem</code>
- */
- public JMenuItem(Icon icon) {
- this(null, icon);
- }
-
- /**
- * Creates a <code>JMenuItem</code> with the specified text.
- *
- * @param text the text of the <code>JMenuItem</code>
- */
- public JMenuItem(String text) {
- this(text, (Icon)null);
- }
-
- /**
- * Creates a menu item whose properties are taken from the
- * specified <code>Action</code>.
- *
- * @param a the action of the <code>JMenuItem</code>
- * @since 1.3
- */
- public JMenuItem(Action a) {
- this();
- setAction(a);
- }
-
- /**
- * Creates a <code>JMenuItem</code> with the specified text and icon.
- *
- * @param text the text of the <code>JMenuItem</code>
- * @param icon the icon of the <code>JMenuItem</code>
- */
- public JMenuItem(String text, Icon icon) {
- setModel(new DefaultButtonModel());
- init(text, icon);
- initFocusability();
- }
-
- /**
- * Creates a <code>JMenuItem</code> with the specified text and
- * keyboard mnemonic.
- *
- * @param text the text of the <code>JMenuItem</code>
- * @param mnemonic the keyboard mnemonic for the <code>JMenuItem</code>
- */
- public JMenuItem(String text, int mnemonic) {
- setModel(new DefaultButtonModel());
- init(text, null);
- setMnemonic(mnemonic);
- initFocusability();
- }
-
- /**
- * Inititalizes the focusability of the the <code>JMenuItem</code>.
- * <code>JMenuItem</code>'s are focusable, but subclasses may
- * want to be, this provides them the opportunity to override this
- * and invoke something else, or nothing at all. Refer to
- * {@link javax.swing.JMenu#initFocusability} for the motivation of
- * this.
- */
- void initFocusability() {
- setFocusable(false);
- }
-
- /**
- * Initializes the menu item with the specified text and icon.
- *
- * @param text the text of the <code>JMenuItem</code>
- * @param icon the icon of the <code>JMenuItem</code>
- */
- protected void init(String text, Icon icon) {
- if(text != null) {
- setText(text);
- }
-
- if(icon != null) {
- setIcon(icon);
- }
-
- // Listen for Focus events
- addFocusListener(new MenuItemFocusListener());
- setUIProperty("borderPainted", Boolean.FALSE);
- setFocusPainted(false);
- setHorizontalTextPosition(JButton.TRAILING);
- setHorizontalAlignment(JButton.LEADING);
- updateUI();
- }
-
- private static class MenuItemFocusListener implements FocusListener,
- Serializable {
- public void focusGained(FocusEvent event) {}
- public void focusLost(FocusEvent event) {
- // When focus is lost, repaint if
- // the focus information is painted
- JMenuItem mi = (JMenuItem)event.getSource();
- if(mi.isFocusPainted()) {
- mi.repaint();
- }
- }
- }
-
-
- /**
- * Sets the look and feel object that renders this component.
- *
- * @param ui the <code>JMenuItemUI</code> L&F object
- * @see UIDefaults#getUI
- * @beaninfo
- * bound: true
- * hidden: true
- * attribute: visualUpdate true
- * description: The UI object that implements the Component's LookAndFeel.
- */
- public void setUI(MenuItemUI ui) {
- super.setUI(ui);
- }
-
- /**
- * Resets the UI property with a value from the current look and feel.
- *
- * @see JComponent#updateUI
- */
- public void updateUI() {
- setUI((MenuItemUI)UIManager.getUI(this));
- }
-
-
- /**
- * Returns the suffix used to construct the name of the L&F class used to
- * render this component.
- *
- * @return the string "MenuItemUI"
- * @see JComponent#getUIClassID
- * @see UIDefaults#getUI
- */
- public String getUIClassID() {
- return uiClassID;
- }
-
-
- /**
- * Identifies the menu item as "armed". If the mouse button is
- * released while it is over this item, the menu's action event
- * will fire. If the mouse button is released elsewhere, the
- * event will not fire and the menu item will be disarmed.
- *
- * @param b true to arm the menu item so it can be selected
- * @beaninfo
- * description: Mouse release will fire an action event
- * hidden: true
- */
- public void setArmed(boolean b) {
- ButtonModel model = (ButtonModel) getModel();
-
- boolean oldValue = model.isArmed();
- if(model.isArmed() != b) {
- model.setArmed(b);
- }
- }
-
- /**
- * Returns whether the menu item is "armed".
- *
- * @return true if the menu item is armed, and it can be selected
- * @see #setArmed
- */
- public boolean isArmed() {
- ButtonModel model = (ButtonModel) getModel();
- return model.isArmed();
- }
-
- /**
- * Enables or disables the menu item.
- *
- * @param b true to enable the item
- * @beaninfo
- * description: Does the component react to user interaction
- * bound: true
- * preferred: true
- */
- public void setEnabled(boolean b) {
- // Make sure we aren't armed!
- if (b == false)
- setArmed(false);
- super.setEnabled(b);
- }
-
-
- /**
- * Returns true since <code>Menu</code>s, by definition,
- * should always be on top of all other windows. If the menu is
- * in an internal frame false is returned due to the rollover effect
- * for windows laf where the menu is not always on top.
- */
- // package private
- boolean alwaysOnTop() {
- // Fix for bug #4482165
- if (SwingUtilities.getAncestorOfClass(JInternalFrame.class, this) !=
- null) {
- return false;
- }
- return true;
- }
-
-
- /* The keystroke which acts as the menu item's accelerator
- */
- private KeyStroke accelerator;
-
- /**
- * Sets the key combination which invokes the menu item's
- * action listeners without navigating the menu hierarchy. It is the
- * UI's responsibility to install the correct action. Note that
- * when the keyboard accelerator is typed, it will work whether or
- * not the menu is currently displayed.
- *
- * @param keyStroke the <code>KeyStroke</code> which will
- * serve as an accelerator
- * @beaninfo
- * description: The keystroke combination which will invoke the
- * JMenuItem's actionlisteners without navigating the
- * menu hierarchy
- * bound: true
- * preferred: true
- */
- public void setAccelerator(KeyStroke keyStroke) {
- KeyStroke oldAccelerator = accelerator;
- this.accelerator = keyStroke;
- firePropertyChange("accelerator", oldAccelerator, accelerator);
- }
-
- /**
- * Returns the <code>KeyStroke</code> which serves as an accelerator
- * for the menu item.
- * @return a <code>KeyStroke</code> object identifying the
- * accelerator key
- */
- public KeyStroke getAccelerator() {
- return this.accelerator;
- }
-
- /**
- * Factory method which sets the <code>ActionEvent</code> source's
- * properties according to values from the <code>Action</code> instance.
- * The properties which are set may differ for subclasses.
- * By default, this method sets the same properties as
- * <code>AbstractButton.configurePropertiesFromAction()</code>, plus
- * <code>Accelerator</code>.
- *
- * @param a the <code>Action</code> from which to get the properties,
- * or <code>null</code>
- * @since 1.3
- * @see Action
- */
- protected void configurePropertiesFromAction(Action a) {
- super.configurePropertiesFromAction(a);
- KeyStroke ks = (a==null) ? null :
- (KeyStroke)a.getValue(Action.ACCELERATOR_KEY);
- setAccelerator(ks==null ? null : ks);
- }
-
- /**
- * Factory method which creates the <code>PropertyChangeListener</code>
- * used to update the <code>ActionEvent</code> source as properties
- * change on its <code>Action</code> instance.
- * Subclasses may override this in order to provide their own
- * <code>PropertyChangeListener</code> if the set of
- * properties which should be kept up to date differs.
- * <p>
- * Note that <code>PropertyChangeListeners</code> should avoid holding
- * strong references to the <code>ActionEvent</code> source,
- * as this may hinder garbage collection of the <code>ActionEvent</code>
- * source and all components in its containment hierarchy.
- *
- * @param a the <code>Action</code> from which to get the properties,
- * or <code>null</code>
- *
- * @since 1.3
- * @see Action
- */
- protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
- return new MenuItemPropertyChangeListener(this, a);
- }
-
- private static class MenuItemPropertyChangeListener
- extends AbstractActionPropertyChangeListener
- implements Serializable {
-
- MenuItemPropertyChangeListener(JMenuItem m, Action a) {
- super(m, a);
- }
-
- public void propertyChange(PropertyChangeEvent e) {
- String propertyName = e.getPropertyName();
- JMenuItem mi = (JMenuItem)getTarget();
- if (mi == null) { //WeakRef GC'ed in 1.2
- Action action = (Action)e.getSource();
- action.removePropertyChangeListener(this);
- } else {
- if (e.getPropertyName().equals(Action.NAME)) {
- String text = (String) e.getNewValue();
- mi.setText(text);
- mi.repaint();
- } else if (propertyName.equals("enabled")) {
- Boolean enabledState = (Boolean) e.getNewValue();
- mi.setEnabled(enabledState.booleanValue());
- mi.repaint();
- } else if (e.getPropertyName().equals(Action.SMALL_ICON)) {
- Icon icon = (Icon) e.getNewValue();
- mi.setIcon(icon);
- mi.invalidate();
- mi.repaint();
- } else
- if (e.getPropertyName().equals(Action.MNEMONIC_KEY)) {
- Integer mn = (Integer) e.getNewValue();
- mi.setMnemonic(mn.intValue());
- mi.invalidate();
- mi.repaint();
- }
- }
- }
- }
-
- /**
- * Processes a mouse event forwarded from the
- * <code>MenuSelectionManager</code> and changes the menu
- * selection, if necessary, by using the
- * <code>MenuSelectionManager</code>'s API.
- * <p>
- * Note: you do not have to forward the event to sub-components.
- * This is done automatically by the <code>MenuSelectionManager</code>.
- *
- * @param e a <code>MouseEvent</code>
- * @param path the <code>MenuElement</code> path array
- * @param manager the <code>MenuSelectionManager</code>
- */
- public void processMouseEvent(MouseEvent e,MenuElement path[],MenuSelectionManager manager) {
- processMenuDragMouseEvent(
- new MenuDragMouseEvent(e.getComponent(), e.getID(),
- e.getWhen(),
- e.getModifiers(), e.getX(), e.getY(),
- e.getClickCount(), e.isPopupTrigger(),
- path, manager));
- }
-
-
- /**
- * Processes a key event forwarded from the
- * <code>MenuSelectionManager</code> and changes the menu selection,
- * if necessary, by using <code>MenuSelectionManager</code>'s API.
- * <p>
- * Note: you do not have to forward the event to sub-components.
- * This is done automatically by the <code>MenuSelectionManager</code>.
- *
- * @param e a <code>KeyEvent</code>
- * @param path the <code>MenuElement</code> path array
- * @param manager the <code>MenuSelectionManager</code>
- */
- public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
- if (DEBUG) {
- System.out.println("in JMenuItem.processKeyEvent/3 for " + getText() +
- " " + KeyStroke.getKeyStrokeForEvent(e));
- }
- MenuKeyEvent mke = new MenuKeyEvent(e.getComponent(), e.getID(),
- e.getWhen(), e.getModifiers(),
- e.getKeyCode(), e.getKeyChar(),
- path, manager);
- processMenuKeyEvent(mke);
-
- if (mke.isConsumed()) {
- e.consume();
- }
- }
-
-
-
- /**
- * Handles mouse drag in a menu.
- *
- * @param e a <code>MenuDragMouseEvent</code> object
- */
- public void processMenuDragMouseEvent(MenuDragMouseEvent e) {
- switch (e.getID()) {
- case MouseEvent.MOUSE_ENTERED:
- isMouseDragged = false; fireMenuDragMouseEntered(e); break;
- case MouseEvent.MOUSE_EXITED:
- isMouseDragged = false; fireMenuDragMouseExited(e); break;
- case MouseEvent.MOUSE_DRAGGED:
- isMouseDragged = true; fireMenuDragMouseDragged(e); break;
- case MouseEvent.MOUSE_RELEASED:
- if(isMouseDragged) fireMenuDragMouseReleased(e); break;
- default:
- break;
- }
- }
-
- /**
- * Handles a keystroke in a menu.
- *
- * @param e a <code>MenuKeyEvent</code> object
- */
- public void processMenuKeyEvent(MenuKeyEvent e) {
- if (DEBUG) {
- System.out.println("in JMenuItem.processMenuKeyEvent for " + getText()+
- " " + KeyStroke.getKeyStrokeForEvent(e));
- }
- switch (e.getID()) {
- case KeyEvent.KEY_PRESSED:
- fireMenuKeyPressed(e); break;
- case KeyEvent.KEY_RELEASED:
- fireMenuKeyReleased(e); break;
- case KeyEvent.KEY_TYPED:
- fireMenuKeyTyped(e); break;
- default:
- break;
- }
- }
-
- /**
- * Notifies all listeners that have registered interest for
- * notification on this event type.
- *
- * @param event a <code>MenuMouseDragEvent</code>
- * @see EventListenerList
- */
- protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) {
- // Guaranteed to return a non-null array
- Object[] listeners = listenerList.getListenerList();
- // Process the listeners last to first, notifying
- // those that are interested in this event
- for (int i = listeners.length-2; i>=0; i-=2) {
- if (listeners[i]==MenuDragMouseListener.class) {
- // Lazily create the event:
- ((MenuDragMouseListener)listeners[i+1]).menuDragMouseEntered(event);
- }
- }
- }
-
- /**
- * Notifies all listeners that have registered interest for
- * notification on this event type.
- *
- * @param event a <code>MenuDragMouseEvent</code>
- * @see EventListenerList
- */
- protected void fireMenuDragMouseExited(MenuDragMouseEvent event) {
- // Guaranteed to return a non-null array
- Object[] listeners = listenerList.getListenerList();
- // Process the listeners last to first, notifying
- // those that are interested in this event
- for (int i = listeners.length-2; i>=0; i-=2) {
- if (listeners[i]==MenuDragMouseListener.class) {
- // Lazily create the event:
- ((MenuDragMouseListener)listeners[i+1]).menuDragMouseExited(event);
- }
- }
- }
-
- /**
- * Notifies all listeners that have registered interest for
- * notification on this event type.
- *
- * @param event a <code>MenuDragMouseEvent</code>
- * @see EventListenerList
- */
- protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) {
- // Guaranteed to return a non-null array
- Object[] listeners = listenerList.getListenerList();
- // Process the listeners last to first, notifying
- // those that are interested in this event
- for (int i = listeners.length-2; i>=0; i-=2) {
- if (listeners[i]==MenuDragMouseListener.class) {
- // Lazily create the event:
- ((MenuDragMouseListener)listeners[i+1]).menuDragMouseDragged(event);
- }
- }
- }
-
- /**
- * Notifies all listeners that have registered interest for
- * notification on this event type.
- *
- * @param event a <code>MenuDragMouseEvent</code>
- * @see EventListenerList
- */
- protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) {
- // Guaranteed to return a non-null array
- Object[] listeners = listenerList.getListenerList();
- // Process the listeners last to first, notifying
- // those that are interested in this event
- for (int i = listeners.length-2; i>=0; i-=2) {
- if (listeners[i]==MenuDragMouseListener.class) {
- // Lazily create the event:
- ((MenuDragMouseListener)listeners[i+1]).menuDragMouseReleased(event);
- }
- }
- }
-
- /**
- * Notifies all listeners that have registered interest for
- * notification on this event type.
- *
- * @param event a <code>MenuKeyEvent</code>
- * @see EventListenerList
- */
- protected void fireMenuKeyPressed(MenuKeyEvent event) {
- if (DEBUG) {
- System.out.println("in JMenuItem.fireMenuKeyPressed for " + getText()+
- " " + KeyStroke.getKeyStrokeForEvent(event));
- }
- // Guaranteed to return a non-null array
- Object[] listeners = listenerList.getListenerList();
- // Process the listeners last to first, notifying
- // those that are interested in this event
- for (int i = listeners.length-2; i>=0; i-=2) {
- if (listeners[i]==MenuKeyListener.class) {
- // Lazily create the event:
- ((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
- }
- }
- }
-
- /**
- * Notifies all listeners that have registered interest for
- * notification on this event type.
- *
- * @param event a <code>MenuKeyEvent</code>
- * @see EventListenerList
- */
- protected void fireMenuKeyReleased(MenuKeyEvent event) {
- if (DEBUG) {
- System.out.println("in JMenuItem.fireMenuKeyReleased for " + getText()+
- " " + KeyStroke.getKeyStrokeForEvent(event));
- }
- // Guaranteed to return a non-null array
- Object[] listeners = listenerList.getListenerList();
- // Process the listeners last to first, notifying
- // those that are interested in this event
- for (int i = listeners.length-2; i>=0; i-=2) {
- if (listeners[i]==MenuKeyListener.class) {
- // Lazily create the event:
- ((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
- }
- }
- }
-
- /**
- * Notifies all listeners that have registered interest for
- * notification on this event type.
- *
- * @param event a <code>MenuKeyEvent</code>
- * @see EventListenerList
- */
- protected void fireMenuKeyTyped(MenuKeyEvent event) {
- if (DEBUG) {
- System.out.println("in JMenuItem.fireMenuKeyTyped for " + getText()+
- " " + KeyStroke.getKeyStrokeForEvent(event));
- }
- // Guaranteed to return a non-null array
- Object[] listeners = listenerList.getListenerList();
- // Process the listeners last to first, notifying
- // those that are interested in this event
- for (int i = listeners.length-2; i>=0; i-=2) {
- if (listeners[i]==MenuKeyListener.class) {
- // Lazily create the event:
- ((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
- }
- }
- }
-
- /**
- * Called by the <code>MenuSelectionManager</code> when the
- * <code>MenuElement</code> is selected or unselected.
- *
- * @param isIncluded true if this menu item is on the part of the menu
- * path that changed, false if this menu is part of the
- * a menu path that changed, but this particular part of
- * that path is still the same
- * @see MenuSelectionManager#setSelectedPath(MenuElement[])
- */
- public void menuSelectionChanged(boolean isIncluded) {
- setArmed(isIncluded);
- }
-
- /**
- * This method returns an array containing the sub-menu
- * components for this menu component.
- *
- * @return an array of <code>MenuElement</code>s
- */
- public MenuElement[] getSubElements() {
- return new MenuElement[0];
- }
-
- /**
- * Returns the <code>java.awt.Component</code> used to paint
- * this object. The returned component will be used to convert
- * events and detect if an event is inside a menu component.
- *
- * @return the <code>Component</code> that paints this menu item
- */
- public Component getComponent() {
- return this;
- }
-
- /**
- * Adds a <code>MenuDragMouseListener</code> to the menu item.
- *
- * @param l the <code>MenuDragMouseListener</code> to be added
- */
- public void addMenuDragMouseListener(MenuDragMouseListener l) {
- listenerList.add(MenuDragMouseListener.class, l);
- }
-
- /**
- * Removes a <code>MenuDragMouseListener</code> from the menu item.
- *
- * @param l the <code>MenuDragMouseListener</code> to be removed
- */
- public void removeMenuDragMouseListener(MenuDragMouseListener l) {
- listenerList.remove(MenuDragMouseListener.class, l);
- }
-
- /**
- * Returns an array of all the <code>MenuDragMouseListener</code>s added
- * to this JMenuItem with addMenuDragMouseListener().
- *
- * @return all of the <code>MenuDragMouseListener</code>s added or an empty
- * array if no listeners have been added
- * @since 1.4
- */
- public MenuDragMouseListener[] getMenuDragMouseListeners() {
- return (MenuDragMouseListener[])listenerList.getListeners(
- MenuDragMouseListener.class);
- }
-
- /**
- * Adds a <code>MenuKeyListener</code> to the menu item.
- *
- * @param l the <code>MenuKeyListener</code> to be added
- */
- public void addMenuKeyListener(MenuKeyListener l) {
- listenerList.add(MenuKeyListener.class, l);
- }
-
- /**
- * Removes a <code>MenuKeyListener</code> from the menu item.
- *
- * @param l the <code>MenuKeyListener</code> to be removed
- */
- public void removeMenuKeyListener(MenuKeyListener l) {
- listenerList.remove(MenuKeyListener.class, l);
- }
-
- /**
- * Returns an array of all the <code>MenuKeyListener</code>s added
- * to this JMenuItem with addMenuKeyListener().
- *
- * @return all of the <code>MenuKeyListener</code>s added or an empty
- * array if no listeners have been added
- * @since 1.4
- */
- public MenuKeyListener[] getMenuKeyListeners() {
- return (MenuKeyListener[])listenerList.getListeners(
- MenuKeyListener.class);
- }
-
- /**
- * See JComponent.readObject() for information about serialization
- * in Swing.
- */
- private void readObject(ObjectInputStream s)
- throws IOException, ClassNotFoundException
- {
- s.defaultReadObject();
- if (getUIClassID().equals(uiClassID)) {
- updateUI();
- }
- }
-
- private void writeObject(ObjectOutputStream s) throws IOException {
- s.defaultWriteObject();
- if (getUIClassID().equals(uiClassID)) {
- byte count = JComponent.getWriteObjCounter(this);
- JComponent.setWriteObjCounter(this, --count);
- if (count == 0 && ui != null) {
- ui.installUI(this);
- }
- }
- }
-
-
- /**
- * Returns a string representation of this <code>JMenuItem</code>.
- * This method is intended to be used only for debugging purposes,
- * and the content and format of the returned string may vary between
- * implementations. The returned string may be empty but may not
- * be <code>null</code>.
- *
- * @return a string representation of this <code>JMenuItem</code>
- */
- protected String paramString() {
- return super.paramString();
- }
-
- /////////////////
- // Accessibility support
- ////////////////
-
- /**
- * Returns the <code>AccessibleContext</code> associated with this
- * <code>JMenuItem</code>. For <code>JMenuItem</code>s,
- * the <code>AccessibleContext</code> takes the form of an
- * <code>AccessibleJMenuItem</code>.
- * A new AccessibleJMenuItme instance is created if necessary.
- *
- * @return an <code>AccessibleJMenuItem</code> that serves as the
- * <code>AccessibleContext</code> of this <code>JMenuItem</code>
- */
- public AccessibleContext getAccessibleContext() {
- if (accessibleContext == null) {
- accessibleContext = new AccessibleJMenuItem();
- }
- return accessibleContext;
- }
-
-
- /**
- * This class implements accessibility support for the
- * <code>JMenuItem</code> class. It provides an implementation of the
- * Java Accessibility API appropriate to menu item user-interface
- * elements.
- * <p>
- * <strong>Warning:</strong>
- * Serialized objects of this class will not be compatible with
- * future Swing releases. The current serialization support is
- * appropriate for short term storage or RMI between applications running
- * the same version of Swing. As of 1.4, support for long term storage
- * of all JavaBeans<sup><font size="-2">TM</font></sup>
- * has been added to the <code>java.beans</code> package.
- * Please see {@link java.beans.XMLEncoder}.
- */
- protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener {
-
- private boolean isArmed = false;
- private boolean hasFocus = false;
- private boolean isPressed = false;
- private boolean isSelected = false;
-
- AccessibleJMenuItem() {
- super();
- JMenuItem.this.addChangeListener(this);
- }
-
- /**
- * Get the role of this object.
- *
- * @return an instance of AccessibleRole describing the role of the
- * object
- */
- public AccessibleRole getAccessibleRole() {
- return AccessibleRole.MENU_ITEM;
- }
-
- private void fireAccessibilityFocusedEvent(JMenuItem toCheck) {
- MenuElement [] path =
- MenuSelectionManager.defaultManager().getSelectedPath();
- if (path.length > 0) {
- Object menuItem = path[path.length - 1];
- if (toCheck == menuItem) {
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- null, AccessibleState.FOCUSED);
- }
- }
- }
-
- /**
- * Supports the change listener interface and fires property changes.
- */
- public void stateChanged(ChangeEvent e) {
- firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
- Boolean.valueOf(false), Boolean.valueOf(true));
- if (JMenuItem.this.getModel().isArmed()) {
- if (!isArmed) {
- isArmed = true;
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- null, AccessibleState.ARMED);
- // Fix for 4848220 moved here to avoid major memory leak
- // Here we will fire the event in case of JMenuItem
- // See bug 4910323 for details [zav]
- fireAccessibilityFocusedEvent(JMenuItem.this);
- }
- } else {
- if (isArmed) {
- isArmed = false;
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- AccessibleState.ARMED, null);
- }
- }
- if (JMenuItem.this.isFocusOwner()) {
- if (!hasFocus) {
- hasFocus = true;
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- null, AccessibleState.FOCUSED);
- }
- } else {
- if (hasFocus) {
- hasFocus = false;
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- AccessibleState.FOCUSED, null);
- }
- }
- if (JMenuItem.this.getModel().isPressed()) {
- if (!isPressed) {
- isPressed = true;
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- null, AccessibleState.PRESSED);
- }
- } else {
- if (isPressed) {
- isPressed = false;
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- AccessibleState.PRESSED, null);
- }
- }
- if (JMenuItem.this.getModel().isSelected()) {
- if (!isSelected) {
- isSelected = true;
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- null, AccessibleState.CHECKED);
-
- // Fix for 4848220 moved here to avoid major memory leak
- // Here we will fire the event in case of JMenu
- // See bug 4910323 for details [zav]
- fireAccessibilityFocusedEvent(JMenuItem.this);
- }
- } else {
- if (isSelected) {
- isSelected = false;
- firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- AccessibleState.CHECKED, null);
- }
- }
-
- }
- } // inner class AccessibleJMenuItem
- }
-