1. /*
  2. * @(#)JMenuItem.java 1.92 00/04/06
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package javax.swing;
  11. import java.util.EventListener;
  12. import java.awt.*;
  13. import java.awt.event.*;
  14. import java.awt.image.*;
  15. import java.beans.PropertyChangeEvent;
  16. import java.beans.PropertyChangeListener;
  17. import java.io.Serializable;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21. import javax.swing.plaf.*;
  22. import javax.swing.plaf.basic.*;
  23. import javax.swing.event.*;
  24. import javax.accessibility.*;
  25. /**
  26. * An implementation of an item in a menu. A menu item is essentially a button
  27. * sitting in a list. When the user selects the "button", the action
  28. * associated with the menu item is performed. A JMenuItem contained
  29. * in a JPopupMenu performs exactly that function.
  30. * <p>
  31. * For further documentation and for examples, see
  32. * <a
  33. href="http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html">How to Use Menus</a>
  34. * in <em>The Java Tutorial.</em>
  35. * For the keyboard keys used by this component in the standard Look and
  36. * Feel (L&F) renditions, see the
  37. * <a href="doc-files/Key-Index.html#JMenuItem">JMenuItem</a> key assignments.
  38. * <p>
  39. * <strong>Warning:</strong>
  40. * Serialized objects of this class will not be compatible with
  41. * future Swing releases. The current serialization support is appropriate
  42. * for short term storage or RMI between applications running the same
  43. * version of Swing. A future release of Swing will provide support for
  44. * long term persistence.
  45. *
  46. * @beaninfo
  47. * attribute: isContainer false
  48. * description: An item which can be selected in a menu.
  49. *
  50. * @version 1.92 04/06/00
  51. * @author Georges Saab
  52. * @author David Karlton
  53. * @see JPopupMenu
  54. * @see JMenu
  55. * @see JCheckBoxMenuItem
  56. * @see JRadioButtonMenuItem
  57. */
  58. public class JMenuItem extends AbstractButton implements Accessible,MenuElement {
  59. /**
  60. * @see #getUIClassID
  61. * @see #readObject
  62. */
  63. private static final String uiClassID = "MenuItemUI";
  64. /* diagnostic aids -- should be false for production builds. */
  65. private static final boolean TRACE = false; // trace creates and disposes
  66. private static final boolean VERBOSE = false; // show reuse hits/misses
  67. private static final boolean DEBUG = false; // show bad params, misc.
  68. /**
  69. * Creates a menuItem with no set text or icon.
  70. */
  71. public JMenuItem() {
  72. this(null, (Icon)null);
  73. setRequestFocusEnabled(false);
  74. }
  75. /**
  76. * Creates a menuItem with an icon.
  77. *
  78. * @param icon the icon of the MenuItem.
  79. */
  80. public JMenuItem(Icon icon) {
  81. this(null, icon);
  82. setRequestFocusEnabled(false);
  83. }
  84. /**
  85. * Creates a menuItem with text.
  86. *
  87. * @param text the text of the MenuItem.
  88. */
  89. public JMenuItem(String text) {
  90. this(text, (Icon)null);
  91. }
  92. /**
  93. * Creates a menu item whose properties are taken from the
  94. * Action supplied.
  95. *
  96. * @since 1.3
  97. */
  98. public JMenuItem(Action a) {
  99. this();
  100. setAction(a);
  101. }
  102. /**
  103. * Creates a menu item with the supplied text and icon.
  104. *
  105. * @param text the text of the MenuItem.
  106. * @param icon the icon of the MenuItem.
  107. */
  108. public JMenuItem(String text, Icon icon) {
  109. setModel(new DefaultButtonModel());
  110. init(text, icon);
  111. }
  112. /**
  113. * Creates a menuItem with the specified text and
  114. * keyboard mnemonic.
  115. *
  116. * @param text the text of the MenuItem.
  117. * @param mnemonic the keyboard mnemonic for the MenuItem
  118. */
  119. public JMenuItem(String text, int mnemonic) {
  120. setModel(new DefaultButtonModel());
  121. init(text, null);
  122. setMnemonic(mnemonic);
  123. }
  124. /**
  125. * Initialize the menu item with the specified text and icon.
  126. *
  127. * @param text the text of the MenuItem.
  128. * @param icon the icon of the MenuItem.
  129. */
  130. protected void init(String text, Icon icon) {
  131. if(text != null) {
  132. setText(text);
  133. }
  134. if(icon != null) {
  135. setIcon(icon);
  136. }
  137. // Listen for Focus events
  138. addFocusListener(new MenuItemFocusListener());
  139. setBorderPainted(false);
  140. setFocusPainted(false);
  141. setHorizontalTextPosition(JButton.TRAILING);
  142. setHorizontalAlignment(JButton.LEADING);
  143. updateUI();
  144. }
  145. private static class MenuItemFocusListener implements FocusListener,
  146. Serializable {
  147. public void focusGained(FocusEvent event) {}
  148. public void focusLost(FocusEvent event) {
  149. // When focus is lost, repaint if
  150. // the focus information is painted
  151. JMenuItem mi = (JMenuItem)event.getSource();
  152. if(mi.isFocusPainted()) {
  153. mi.repaint();
  154. }
  155. }
  156. }
  157. /**
  158. * Sets the L&F object that renders this component.
  159. *
  160. * @param ui the MenuItemUI L&F object
  161. * @see UIDefaults#getUI
  162. * @beaninfo
  163. * description: The menu item's UI delegate
  164. * bound: true
  165. * expert: true
  166. * hidden: true
  167. */
  168. public void setUI(MenuItemUI ui) {
  169. super.setUI(ui);
  170. }
  171. /**
  172. * Resets the UI property with a value from the current look and feel.
  173. *
  174. * @see JComponent#updateUI
  175. */
  176. public void updateUI() {
  177. setUI((MenuItemUI)UIManager.getUI(this));
  178. }
  179. /**
  180. * Returns the name of the L&F class that renders this component.
  181. *
  182. * @return "MenuItemUI"
  183. * @see JComponent#getUIClassID
  184. * @see UIDefaults#getUI
  185. */
  186. public String getUIClassID() {
  187. return uiClassID;
  188. }
  189. /**
  190. * Identifies the menu item as "armed". If the mouse button is
  191. * released while it is over this item, the menu's action event
  192. * will fire. If the mouse button is released elsewhere, the
  193. * event will not fire and the menu item will be disarmed.
  194. *
  195. * @param b true to arm the menu item so it can be selected
  196. * @beaninfo
  197. * description: Mouse release will fire an action event
  198. * hidden: true
  199. */
  200. public void setArmed(boolean b) {
  201. ButtonModel model = (ButtonModel) getModel();
  202. boolean oldValue = model.isArmed();
  203. if ((accessibleContext != null) && (oldValue != b)) {
  204. if (b) {
  205. accessibleContext.firePropertyChange(
  206. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  207. null,
  208. AccessibleState.ARMED);
  209. } else {
  210. accessibleContext.firePropertyChange(
  211. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  212. AccessibleState.ARMED,
  213. null);
  214. }
  215. }
  216. if(model.isArmed() != b) {
  217. model.setArmed(b);
  218. }
  219. }
  220. /**
  221. * Returns whether the menu item is "armed".
  222. *
  223. * @return true if the menu item is armed, and it can be selected
  224. * @see #setArmed
  225. */
  226. public boolean isArmed() {
  227. ButtonModel model = (ButtonModel) getModel();
  228. return model.isArmed();
  229. }
  230. /**
  231. * Enable or disable the menu item.
  232. *
  233. * @param b true to enable the item
  234. * @beaninfo
  235. * description: Does the component react to user interaction
  236. * bound: true
  237. * preferred: true
  238. */
  239. public void setEnabled(boolean b) {
  240. // Make sure we aren't armed!
  241. if (b == false)
  242. setArmed(false);
  243. super.setEnabled(b);
  244. }
  245. /**
  246. * Always return true since Menus, by definition,
  247. * should always be on top of all other windows.
  248. */
  249. // package private
  250. boolean alwaysOnTop() {
  251. return true;
  252. }
  253. /* The keystroke which acts as the menu item's accelerator
  254. */
  255. private KeyStroke accelerator;
  256. /**
  257. * Set the key combination which invokes the Menu Item's
  258. * action listeners without navigating the menu hierarchy. It is the
  259. * UIs responsibility to do install the correct action.
  260. *
  261. * @param keyStroke the KeyStroke which will serve as an accelerator
  262. * @beaninfo
  263. * description: The keystroke combination which will invoke the JMenuItem's
  264. * actionlisteners without navigating the menu hierarchy
  265. * bound: true
  266. * preferred: true
  267. */
  268. public void setAccelerator(KeyStroke keyStroke) {
  269. KeyStroke oldAccelerator = accelerator;
  270. this.accelerator = keyStroke;
  271. firePropertyChange("accelerator", oldAccelerator, accelerator);
  272. }
  273. /**
  274. * Returns the KeyStroke which serves as an accelerator
  275. * for the menu item.
  276. * @return a KeyStroke object identifying the accelerator key
  277. */
  278. public KeyStroke getAccelerator() {
  279. return this.accelerator;
  280. }
  281. /**
  282. * Factory method which sets the ActionEvent source's properties
  283. * according to values from the Action instance. The properties
  284. * which are set may differ for subclasses.
  285. * By default, the properties which get set are Text, Icon
  286. *
  287. * @param a the Action from which to get the properties, or null
  288. * @since 1.3
  289. * @see Action
  290. * @see #setAction
  291. */
  292. protected void configurePropertiesFromAction(Action a) {
  293. setText((a!=null?(String)a.getValue(Action.NAME):null));
  294. setIcon((a!=null?(Icon)a.getValue(Action.SMALL_ICON):null));
  295. setEnabled((a!=null?a.isEnabled():true));
  296. if (a != null) {
  297. Integer i = (Integer)a.getValue(Action.MNEMONIC_KEY);
  298. if (i != null)
  299. setMnemonic(i.intValue());
  300. }
  301. }
  302. /**
  303. * Factory method which creates the PropertyChangeListener
  304. * used to update the ActionEvent source as properties change on
  305. * its Action instance. Subclasses may override this in order
  306. * to provide their own PropertyChangeListener if the set of
  307. * properties which should be kept up to date differs from the
  308. *
  309. * Note that PropertyChangeListeners should avoid holding
  310. * strong references to the ActionEvent source, as this may hinder
  311. * garbage collection of the ActionEvent source and all components
  312. * in its containment hierarchy.
  313. *
  314. * @since 1.3
  315. * @see Action
  316. * @see #setAction
  317. */
  318. protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
  319. return new AbstractActionPropertyChangeListener(this, a){
  320. public void propertyChange(PropertyChangeEvent e) {
  321. String propertyName = e.getPropertyName();
  322. JMenuItem mi = (JMenuItem)getTarget();
  323. if (mi == null) { //WeakRef GC'ed in 1.2
  324. Action action = (Action)e.getSource();
  325. action.removePropertyChangeListener(this);
  326. } else {
  327. if (e.getPropertyName().equals(Action.NAME)) {
  328. String text = (String) e.getNewValue();
  329. mi.setText(text);
  330. mi.repaint();
  331. } else if (propertyName.equals("enabled")) {
  332. Boolean enabledState = (Boolean) e.getNewValue();
  333. mi.setEnabled(enabledState.booleanValue());
  334. mi.repaint();
  335. } else if (e.getPropertyName().equals(Action.SMALL_ICON)) {
  336. Icon icon = (Icon) e.getNewValue();
  337. mi.setIcon(icon);
  338. mi.invalidate();
  339. mi.repaint();
  340. } else if (e.getPropertyName().equals(Action.MNEMONIC_KEY)) {
  341. Integer mn = (Integer) e.getNewValue();
  342. mi.setMnemonic(mn.intValue());
  343. mi.invalidate();
  344. mi.repaint();
  345. }
  346. }
  347. }
  348. };
  349. }
  350. /**
  351. * Process a mouse event forwarded from the MenuSelectionManager.
  352. * @param event A MouseEvent with source being the receiving component.
  353. * @param componentPath The MenuElement path array to the receiving component.
  354. * @param manager The MenuSelectionManager for the menu hierarchy.
  355. * This method should process the MouseEvent and change the menu selection if necessary
  356. * by using MenuSelectionManager's API.
  357. * <p>
  358. * Note: you do not have to forward the event to sub-components. This is done automatically
  359. * by the MenuSelectionManager
  360. */
  361. public void processMouseEvent(MouseEvent e,MenuElement path[],MenuSelectionManager manager) {
  362. processMenuDragMouseEvent(
  363. new MenuDragMouseEvent(e.getComponent(), e.getID(),
  364. e.getWhen(),
  365. e.getModifiers(), e.getX(), e.getY(),
  366. e.getClickCount(), e.isPopupTrigger(),
  367. path, manager));
  368. }
  369. /**
  370. * Process a key event forwarded from the MenuSelectionManager.
  371. * @param event A KeyEvent with source being the receiving component.
  372. * @param componentPath The MenuElement path array to the receiving component.
  373. * @param manager The MenuSelectionManager for the menu hierarchy.
  374. * This method should process the KeyEvent and change the menu selection if necessary
  375. * by using MenuSelectionManager's API.
  376. * <p>
  377. * Note: you do not have to forward the event to sub-components. This is done automatically
  378. * by the MenuSelectionManager
  379. */
  380. public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
  381. if (DEBUG) {
  382. System.out.println("in JMenuItem.processKeyEvent/3 for " + getText() +
  383. " " + KeyStroke.getKeyStrokeForEvent(e));
  384. }
  385. MenuKeyEvent mke = new MenuKeyEvent(e.getComponent(), e.getID(),
  386. e.getWhen(), e.getModifiers(),
  387. e.getKeyCode(), e.getKeyChar(),
  388. path, manager);
  389. processMenuKeyEvent(mke);
  390. if (mke.isConsumed()) {
  391. e.consume();
  392. }
  393. }
  394. /**
  395. * Handle mouse drag in a menu.
  396. *
  397. * @param e a MenuDragMouseEvent object
  398. */
  399. public void processMenuDragMouseEvent(MenuDragMouseEvent e) {
  400. switch (e.getID()) {
  401. case MouseEvent.MOUSE_ENTERED:
  402. fireMenuDragMouseEntered(e); break;
  403. case MouseEvent.MOUSE_EXITED:
  404. fireMenuDragMouseExited(e); break;
  405. case MouseEvent.MOUSE_DRAGGED:
  406. fireMenuDragMouseDragged(e); break;
  407. case MouseEvent.MOUSE_RELEASED:
  408. fireMenuDragMouseReleased(e); break;
  409. default:
  410. break;
  411. }
  412. }
  413. /**
  414. * Handle a keystroke in a menu.
  415. *
  416. * @param e a MenuKeyEvent object
  417. */
  418. public void processMenuKeyEvent(MenuKeyEvent e) {
  419. if (DEBUG) {
  420. System.out.println("in JMenuItem.processMenuKeyEvent for " + getText()+
  421. " " + KeyStroke.getKeyStrokeForEvent(e));
  422. }
  423. switch (e.getID()) {
  424. case KeyEvent.KEY_PRESSED:
  425. fireMenuKeyPressed(e); break;
  426. case KeyEvent.KEY_RELEASED:
  427. fireMenuKeyReleased(e); break;
  428. case KeyEvent.KEY_TYPED:
  429. fireMenuKeyTyped(e); break;
  430. default:
  431. break;
  432. }
  433. }
  434. /*
  435. * Notify all listeners that have registered interest for
  436. * notification on this event type.
  437. * @see EventListenerList
  438. */
  439. protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) {
  440. // Guaranteed to return a non-null array
  441. Object[] listeners = listenerList.getListenerList();
  442. // Process the listeners last to first, notifying
  443. // those that are interested in this event
  444. for (int i = listeners.length-2; i>=0; i-=2) {
  445. if (listeners[i]==MenuDragMouseListener.class) {
  446. // Lazily create the event:
  447. ((MenuDragMouseListener)listeners[i+1]).menuDragMouseEntered(event);
  448. }
  449. }
  450. }
  451. /*
  452. * Notify all listeners that have registered interest for
  453. * notification on this event type.
  454. * @see EventListenerList
  455. */
  456. protected void fireMenuDragMouseExited(MenuDragMouseEvent event) {
  457. // Guaranteed to return a non-null array
  458. Object[] listeners = listenerList.getListenerList();
  459. // Process the listeners last to first, notifying
  460. // those that are interested in this event
  461. for (int i = listeners.length-2; i>=0; i-=2) {
  462. if (listeners[i]==MenuDragMouseListener.class) {
  463. // Lazily create the event:
  464. ((MenuDragMouseListener)listeners[i+1]).menuDragMouseExited(event);
  465. }
  466. }
  467. }
  468. /*
  469. * Notify all listeners that have registered interest for
  470. * notification on this event type.
  471. * @see EventListenerList
  472. */
  473. protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) {
  474. // Guaranteed to return a non-null array
  475. Object[] listeners = listenerList.getListenerList();
  476. // Process the listeners last to first, notifying
  477. // those that are interested in this event
  478. for (int i = listeners.length-2; i>=0; i-=2) {
  479. if (listeners[i]==MenuDragMouseListener.class) {
  480. // Lazily create the event:
  481. ((MenuDragMouseListener)listeners[i+1]).menuDragMouseDragged(event);
  482. }
  483. }
  484. }
  485. /*
  486. * Notify all listeners that have registered interest for
  487. * notification on this event type.
  488. * @see EventListenerList
  489. */
  490. protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) {
  491. // Guaranteed to return a non-null array
  492. Object[] listeners = listenerList.getListenerList();
  493. // Process the listeners last to first, notifying
  494. // those that are interested in this event
  495. for (int i = listeners.length-2; i>=0; i-=2) {
  496. if (listeners[i]==MenuDragMouseListener.class) {
  497. // Lazily create the event:
  498. ((MenuDragMouseListener)listeners[i+1]).menuDragMouseReleased(event);
  499. }
  500. }
  501. }
  502. /*
  503. * Notify all listeners that have registered interest for
  504. * notification on this event type.
  505. * @see EventListenerList
  506. */
  507. protected void fireMenuKeyPressed(MenuKeyEvent event) {
  508. if (DEBUG) {
  509. System.out.println("in JMenuItem.fireMenuKeyPressed for " + getText()+
  510. " " + KeyStroke.getKeyStrokeForEvent(event));
  511. }
  512. // Guaranteed to return a non-null array
  513. Object[] listeners = listenerList.getListenerList();
  514. // Process the listeners last to first, notifying
  515. // those that are interested in this event
  516. for (int i = listeners.length-2; i>=0; i-=2) {
  517. if (listeners[i]==MenuKeyListener.class) {
  518. // Lazily create the event:
  519. ((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
  520. }
  521. }
  522. }
  523. /*
  524. * Notify all listeners that have registered interest for
  525. * notification on this event type.
  526. * @see EventListenerList
  527. */
  528. protected void fireMenuKeyReleased(MenuKeyEvent event) {
  529. if (DEBUG) {
  530. System.out.println("in JMenuItem.fireMenuKeyReleased for " + getText()+
  531. " " + KeyStroke.getKeyStrokeForEvent(event));
  532. }
  533. // Guaranteed to return a non-null array
  534. Object[] listeners = listenerList.getListenerList();
  535. // Process the listeners last to first, notifying
  536. // those that are interested in this event
  537. for (int i = listeners.length-2; i>=0; i-=2) {
  538. if (listeners[i]==MenuKeyListener.class) {
  539. // Lazily create the event:
  540. ((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
  541. }
  542. }
  543. }
  544. /*
  545. * Notify all listeners that have registered interest for
  546. * notification on this event type.
  547. * @see EventListenerList
  548. */
  549. protected void fireMenuKeyTyped(MenuKeyEvent event) {
  550. if (DEBUG) {
  551. System.out.println("in JMenuItem.fireMenuKeyTyped for " + getText()+
  552. " " + KeyStroke.getKeyStrokeForEvent(event));
  553. }
  554. // Guaranteed to return a non-null array
  555. Object[] listeners = listenerList.getListenerList();
  556. // Process the listeners last to first, notifying
  557. // those that are interested in this event
  558. for (int i = listeners.length-2; i>=0; i-=2) {
  559. if (listeners[i]==MenuKeyListener.class) {
  560. // Lazily create the event:
  561. ((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
  562. }
  563. }
  564. }
  565. /**
  566. * Called by the MenuSelectionManager when the MenuElement is selected
  567. * or unselected.
  568. *
  569. * @param isIncluded true if this menu item is on the part of the menu
  570. * path that changed, false if this menu is part of the
  571. * a menu path that changed, but this particular part of
  572. * that path is still the same
  573. * @see MenuSelectionManager#setSelectedPath(MenuElement[])
  574. */
  575. public void menuSelectionChanged(boolean isIncluded) {
  576. setArmed(isIncluded);
  577. }
  578. /**
  579. * This method returns an array containing the sub-menu components for this menu component.
  580. *
  581. * @return an array of MenuElements
  582. */
  583. public MenuElement[] getSubElements() {
  584. return new MenuElement[0];
  585. }
  586. /**
  587. * This method returns the java.awt.Component used to paint this object.
  588. * The returned component will be used to convert events and detect if an event is inside
  589. * a menu component.
  590. *
  591. * @return the Component that paints this menu item
  592. */
  593. public Component getComponent() {
  594. return this;
  595. }
  596. /**
  597. * Adds a MenuDragMouseListener to the menu item
  598. */
  599. public void addMenuDragMouseListener(MenuDragMouseListener l) {
  600. listenerList.add(MenuDragMouseListener.class, l);
  601. }
  602. /**
  603. * Removes a MenuDragMouseListener from the menu item
  604. */
  605. public void removeMenuDragMouseListener(MenuDragMouseListener l) {
  606. listenerList.remove(MenuDragMouseListener.class, l);
  607. }
  608. /**
  609. * Adds a MenuKeyListener to the menu item
  610. */
  611. public void addMenuKeyListener(MenuKeyListener l) {
  612. listenerList.add(MenuKeyListener.class, l);
  613. }
  614. /**
  615. * Removes a MenuKeyListener from the menu item
  616. */
  617. public void removeMenuKeyListener(MenuKeyListener l) {
  618. listenerList.remove(MenuKeyListener.class, l);
  619. }
  620. /**
  621. * See JComponent.readObject() for information about serialization
  622. * in Swing.
  623. */
  624. private void readObject(ObjectInputStream s)
  625. throws IOException, ClassNotFoundException
  626. {
  627. s.defaultReadObject();
  628. if (getUIClassID().equals(uiClassID)) {
  629. updateUI();
  630. }
  631. }
  632. private void writeObject(ObjectOutputStream s) throws IOException {
  633. s.defaultWriteObject();
  634. if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  635. ui.installUI(this);
  636. }
  637. }
  638. /**
  639. * Returns a string representation of this JMenuItem. This method
  640. * is intended to be used only for debugging purposes, and the
  641. * content and format of the returned string may vary between
  642. * implementations. The returned string may be empty but may not
  643. * be <code>null</code>.
  644. *
  645. * @return a string representation of this JMenuItem.
  646. */
  647. protected String paramString() {
  648. return super.paramString();
  649. }
  650. /////////////////
  651. // Accessibility support
  652. ////////////////
  653. /**
  654. * Gets the AccessibleContext associated with this JMenuItem.
  655. * For JMenuItems, the AccessibleContext takes the form of an
  656. * AccessibleJMenuItem.
  657. * A new AccessibleJMenuItme instance is created if necessary.
  658. *
  659. * @return an AccessibleJMenuItem that serves as the
  660. * AccessibleContext of this JMenuItem
  661. */
  662. public AccessibleContext getAccessibleContext() {
  663. if (accessibleContext == null) {
  664. accessibleContext = new AccessibleJMenuItem();
  665. }
  666. return accessibleContext;
  667. }
  668. /**
  669. * This class implements accessibility support for the
  670. * <code>JMenuItem</code> class. It provides an implementation of the
  671. * Java Accessibility API appropriate to menu item user-interface
  672. * elements.
  673. * <p>
  674. * <strong>Warning:</strong>
  675. * Serialized objects of this class will not be compatible with
  676. * future Swing releases. The current serialization support is appropriate
  677. * for short term storage or RMI between applications running the same
  678. * version of Swing. A future release of Swing will provide support for
  679. * long term persistence.
  680. */
  681. protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener {
  682. AccessibleJMenuItem() {
  683. super();
  684. JMenuItem.this.addChangeListener(this);
  685. }
  686. /**
  687. * Get the role of this object.
  688. *
  689. * @return an instance of AccessibleRole describing the role of the
  690. * object
  691. */
  692. public AccessibleRole getAccessibleRole() {
  693. return AccessibleRole.MENU_ITEM;
  694. }
  695. /**
  696. * Supports the change listener interface and fires property change
  697. */
  698. public void stateChanged(ChangeEvent e) {
  699. firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  700. new Boolean(false), new Boolean(true));
  701. }
  702. } // inner class AccessibleJMenuItem
  703. }