001: /*
002: * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package java.awt;
026:
027: import java.awt.peer.MenuItemPeer;
028: import java.awt.event.*;
029: import java.util.EventListener;
030: import java.io.ObjectOutputStream;
031: import java.io.ObjectInputStream;
032: import java.io.IOException;
033: import javax.accessibility.*;
034:
035: /**
036: * All items in a menu must belong to the class
037: * <code>MenuItem</code>, or one of its subclasses.
038: * <p>
039: * The default <code>MenuItem</code> object embodies
040: * a simple labeled menu item.
041: * <p>
042: * This picture of a menu bar shows five menu items:
043: * <IMG SRC="doc-files/MenuBar-1.gif" alt="The following text describes this graphic."
044: * ALIGN=CENTER HSPACE=10 VSPACE=7>
045: * <br CLEAR=LEFT>
046: * The first two items are simple menu items, labeled
047: * <code>"Basic"</code> and <code>"Simple"</code>.
048: * Following these two items is a separator, which is itself
049: * a menu item, created with the label <code>"-"</code>.
050: * Next is an instance of <code>CheckboxMenuItem</code>
051: * labeled <code>"Check"</code>. The final menu item is a
052: * submenu labeled <code>"More Examples"</code>,
053: * and this submenu is an instance of <code>Menu</code>.
054: * <p>
055: * When a menu item is selected, AWT sends an action event to
056: * the menu item. Since the event is an
057: * instance of <code>ActionEvent</code>, the <code>processEvent</code>
058: * method examines the event and passes it along to
059: * <code>processActionEvent</code>. The latter method redirects the
060: * event to any <code>ActionListener</code> objects that have
061: * registered an interest in action events generated by this
062: * menu item.
063: * <P>
064: * Note that the subclass <code>Menu</code> overrides this behavior and
065: * does not send any event to the frame until one of its subitems is
066: * selected.
067: *
068: * @version 1.101, 05/05/07
069: * @author Sami Shaio
070: */
071: public class MenuItem extends MenuComponent implements Accessible {
072:
073: static {
074: /* ensure that the necessary native libraries are loaded */
075: Toolkit.loadLibraries();
076: if (!GraphicsEnvironment.isHeadless()) {
077: initIDs();
078: }
079: }
080:
081: /**
082: * A value to indicate whether a menu item is enabled
083: * or not. If it is enabled, <code>enabled</code> will
084: * be set to true. Else <code>enabled</code> will
085: * be set to false.
086: *
087: * @serial
088: * @see #isEnabled()
089: * @see #setEnabled(boolean)
090: */
091: boolean enabled = true;
092:
093: /**
094: * <code>label</code> is the label of a menu item.
095: * It can be any string.
096: *
097: * @serial
098: * @see #getLabel()
099: * @see #setLabel(String)
100: */
101: String label;
102:
103: /**
104: * This field indicates the command tha has been issued
105: * by a particular menu item.
106: * By default the <code>actionCommand</code>
107: * is the label of the menu item, unless it has been
108: * set using setActionCommand.
109: *
110: * @serial
111: * @see #setActionCommand(String)
112: * @see #getActionCommand()
113: */
114: String actionCommand;
115:
116: /**
117: * The eventMask is ONLY set by subclasses via enableEvents.
118: * The mask should NOT be set when listeners are registered
119: * so that we can distinguish the difference between when
120: * listeners request events and subclasses request them.
121: *
122: * @serial
123: */
124: long eventMask;
125:
126: transient ActionListener actionListener;
127:
128: /**
129: * A sequence of key stokes that ia associated with
130: * a menu item.
131: * Note :in 1.1.2 you must use setActionCommand()
132: * on a menu item in order for its shortcut to
133: * work.
134: *
135: * @serial
136: * @see #getShortcut()
137: * @see #setShortcut(MenuShortcut)
138: * @see #deleteShortcut()
139: */
140: private MenuShortcut shortcut = null;
141:
142: private static final String base = "menuitem";
143: private static int nameCounter = 0;
144:
145: /*
146: * JDK 1.1 serialVersionUID
147: */
148: private static final long serialVersionUID = -21757335363267194L;
149:
150: /**
151: * Constructs a new MenuItem with an empty label and no keyboard
152: * shortcut.
153: * @exception HeadlessException if GraphicsEnvironment.isHeadless()
154: * returns true.
155: * @see java.awt.GraphicsEnvironment#isHeadless
156: * @since JDK1.1
157: */
158: public MenuItem() throws HeadlessException {
159: this ("", null);
160: }
161:
162: /**
163: * Constructs a new MenuItem with the specified label
164: * and no keyboard shortcut. Note that use of "-" in
165: * a label is reserved to indicate a separator between
166: * menu items. By default, all menu items except for
167: * separators are enabled.
168: * @param label the label for this menu item.
169: * @exception HeadlessException if GraphicsEnvironment.isHeadless()
170: * returns true.
171: * @see java.awt.GraphicsEnvironment#isHeadless
172: * @since JDK1.0
173: */
174: public MenuItem(String label) throws HeadlessException {
175: this (label, null);
176: }
177:
178: /**
179: * Create a menu item with an associated keyboard shortcut.
180: * Note that use of "-" in a label is reserved to indicate
181: * a separator between menu items. By default, all menu
182: * items except for separators are enabled.
183: * @param label the label for this menu item.
184: * @param s the instance of <code>MenuShortcut</code>
185: * associated with this menu item.
186: * @exception HeadlessException if GraphicsEnvironment.isHeadless()
187: * returns true.
188: * @see java.awt.GraphicsEnvironment#isHeadless
189: * @since JDK1.1
190: */
191: public MenuItem(String label, MenuShortcut s)
192: throws HeadlessException {
193: this .label = label;
194: this .shortcut = s;
195: }
196:
197: /**
198: * Construct a name for this MenuComponent. Called by getName() when
199: * the name is null.
200: */
201: String constructComponentName() {
202: synchronized (MenuItem.class) {
203: return base + nameCounter++;
204: }
205: }
206:
207: /**
208: * Creates the menu item's peer. The peer allows us to modify the
209: * appearance of the menu item without changing its functionality.
210: */
211: public void addNotify() {
212: synchronized (getTreeLock()) {
213: if (peer == null)
214: peer = Toolkit.getDefaultToolkit().createMenuItem(this );
215: }
216: }
217:
218: /**
219: * Gets the label for this menu item.
220: * @return the label of this menu item, or <code>null</code>
221: if this menu item has no label.
222: * @see java.awt.MenuItem#setLabel
223: * @since JDK1.0
224: */
225: public String getLabel() {
226: return label;
227: }
228:
229: /**
230: * Sets the label for this menu item to the specified label.
231: * @param label the new label, or <code>null</code> for no label.
232: * @see java.awt.MenuItem#getLabel
233: * @since JDK1.0
234: */
235: public synchronized void setLabel(String label) {
236: this .label = label;
237: MenuItemPeer peer = (MenuItemPeer) this .peer;
238: if (peer != null) {
239: peer.setLabel(label);
240: }
241: }
242:
243: /**
244: * Checks whether this menu item is enabled.
245: * @see java.awt.MenuItem#setEnabled
246: * @since JDK1.0
247: */
248: public boolean isEnabled() {
249: return enabled;
250: }
251:
252: /**
253: * Sets whether or not this menu item can be chosen.
254: * @param b if <code>true</code>, enables this menu item;
255: * if <code>false</code>, disables it.
256: * @see java.awt.MenuItem#isEnabled
257: * @since JDK1.1
258: */
259: public synchronized void setEnabled(boolean b) {
260: enable(b);
261: }
262:
263: /**
264: * @deprecated As of JDK version 1.1,
265: * replaced by <code>setEnabled(boolean)</code>.
266: */
267: @Deprecated
268: public synchronized void enable() {
269: enabled = true;
270: MenuItemPeer peer = (MenuItemPeer) this .peer;
271: if (peer != null) {
272: peer.enable();
273: }
274: }
275:
276: /**
277: * @deprecated As of JDK version 1.1,
278: * replaced by <code>setEnabled(boolean)</code>.
279: */
280: @Deprecated
281: public void enable(boolean b) {
282: if (b) {
283: enable();
284: } else {
285: disable();
286: }
287: }
288:
289: /**
290: * @deprecated As of JDK version 1.1,
291: * replaced by <code>setEnabled(boolean)</code>.
292: */
293: @Deprecated
294: public synchronized void disable() {
295: enabled = false;
296: MenuItemPeer peer = (MenuItemPeer) this .peer;
297: if (peer != null) {
298: peer.disable();
299: }
300: }
301:
302: /**
303: * Get the <code>MenuShortcut</code> object associated with this
304: * menu item,
305: * @return the menu shortcut associated with this menu item,
306: * or <code>null</code> if none has been specified.
307: * @see java.awt.MenuItem#setShortcut
308: * @since JDK1.1
309: */
310: public MenuShortcut getShortcut() {
311: return shortcut;
312: }
313:
314: /**
315: * Set the <code>MenuShortcut</code> object associated with this
316: * menu item. If a menu shortcut is already associated with
317: * this menu item, it is replaced.
318: * @param s the menu shortcut to associate
319: * with this menu item.
320: * @see java.awt.MenuItem#getShortcut
321: * @since JDK1.1
322: */
323: public void setShortcut(MenuShortcut s) {
324: shortcut = s;
325: MenuItemPeer peer = (MenuItemPeer) this .peer;
326: if (peer != null) {
327: peer.setLabel(label);
328: }
329: }
330:
331: /**
332: * Delete any <code>MenuShortcut</code> object associated
333: * with this menu item.
334: * @since JDK1.1
335: */
336: public void deleteShortcut() {
337: shortcut = null;
338: MenuItemPeer peer = (MenuItemPeer) this .peer;
339: if (peer != null) {
340: peer.setLabel(label);
341: }
342: }
343:
344: /*
345: * Delete a matching MenuShortcut associated with this MenuItem.
346: * Used when iterating Menus.
347: */
348: void deleteShortcut(MenuShortcut s) {
349: if (s.equals(shortcut)) {
350: shortcut = null;
351: MenuItemPeer peer = (MenuItemPeer) this .peer;
352: if (peer != null) {
353: peer.setLabel(label);
354: }
355: }
356: }
357:
358: /*
359: * The main goal of this method is to post an appropriate event
360: * to the event queue when menu shortcut is pressed. However,
361: * in subclasses this method may do more than just posting
362: * an event.
363: */
364: void doMenuEvent(long when, int modifiers) {
365: Toolkit.getEventQueue().postEvent(
366: new ActionEvent(this , ActionEvent.ACTION_PERFORMED,
367: getActionCommand(), when, modifiers));
368: }
369:
370: /*
371: * Returns true if the item and all its ancestors are
372: * enabled, false otherwise
373: */
374: private final boolean isItemEnabled() {
375: // Fix For 6185151: Menu shortcuts of all menuitems within a menu
376: // should be disabled when the menu itself is disabled
377: if (!isEnabled()) {
378: return false;
379: }
380: MenuContainer container = getParent_NoClientCode();
381: do {
382: if (!(container instanceof Menu)) {
383: return true;
384: }
385: Menu menu = (Menu) container;
386: if (!menu.isEnabled()) {
387: return false;
388: }
389: container = menu.getParent_NoClientCode();
390: } while (container != null);
391: return true;
392: }
393:
394: /*
395: * Post an ActionEvent to the target (on
396: * keydown) and the item is enabled.
397: * Returns true if there is an associated shortcut.
398: */
399: boolean handleShortcut(KeyEvent e) {
400: MenuShortcut s = new MenuShortcut(e.getKeyCode(), (e
401: .getModifiers() & InputEvent.SHIFT_MASK) > 0);
402: // Fix For 6185151: Menu shortcuts of all menuitems within a menu
403: // should be disabled when the menu itself is disabled
404: if (s.equals(shortcut) && isItemEnabled()) {
405: // MenuShortcut match -- issue an event on keydown.
406: if (e.getID() == KeyEvent.KEY_PRESSED) {
407: doMenuEvent(e.getWhen(), e.getModifiers());
408: } else {
409: // silently eat key release.
410: }
411: return true;
412: }
413: return false;
414: }
415:
416: MenuItem getShortcutMenuItem(MenuShortcut s) {
417: return (s.equals(shortcut)) ? this : null;
418: }
419:
420: /**
421: * Enables event delivery to this menu item for events
422: * to be defined by the specified event mask parameter
423: * <p>
424: * Since event types are automatically enabled when a listener for
425: * that type is added to the menu item, this method only needs
426: * to be invoked by subclasses of <code>MenuItem</code> which desire to
427: * have the specified event types delivered to <code>processEvent</code>
428: * regardless of whether a listener is registered.
429: *
430: * @param eventsToEnable the event mask defining the event types
431: * @see java.awt.MenuItem#processEvent
432: * @see java.awt.MenuItem#disableEvents
433: * @see java.awt.Component#enableEvents
434: * @since JDK1.1
435: */
436: protected final void enableEvents(long eventsToEnable) {
437: eventMask |= eventsToEnable;
438: newEventsOnly = true;
439: }
440:
441: /**
442: * Disables event delivery to this menu item for events
443: * defined by the specified event mask parameter.
444: *
445: * @param eventsToDisable the event mask defining the event types
446: * @see java.awt.MenuItem#processEvent
447: * @see java.awt.MenuItem#enableEvents
448: * @see java.awt.Component#disableEvents
449: * @since JDK1.1
450: */
451: protected final void disableEvents(long eventsToDisable) {
452: eventMask &= ~eventsToDisable;
453: }
454:
455: /**
456: * Sets the command name of the action event that is fired
457: * by this menu item.
458: * <p>
459: * By default, the action command is set to the label of
460: * the menu item.
461: * @param command the action command to be set
462: * for this menu item.
463: * @see java.awt.MenuItem#getActionCommand
464: * @since JDK1.1
465: */
466: public void setActionCommand(String command) {
467: actionCommand = command;
468: }
469:
470: /**
471: * Gets the command name of the action event that is fired
472: * by this menu item.
473: * @see java.awt.MenuItem#setActionCommand
474: * @since JDK1.1
475: */
476: public String getActionCommand() {
477: return getActionCommandImpl();
478: }
479:
480: // This is final so it can be called on the Toolkit thread.
481: final String getActionCommandImpl() {
482: return (actionCommand == null ? label : actionCommand);
483: }
484:
485: /**
486: * Adds the specified action listener to receive action events
487: * from this menu item.
488: * If l is null, no exception is thrown and no action is performed.
489: * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
490: * >AWT Threading Issues</a> for details on AWT's threading model.
491: *
492: * @param l the action listener.
493: * @see #removeActionListener
494: * @see #getActionListeners
495: * @see java.awt.event.ActionEvent
496: * @see java.awt.event.ActionListener
497: * @since JDK1.1
498: */
499: public synchronized void addActionListener(ActionListener l) {
500: if (l == null) {
501: return;
502: }
503: actionListener = AWTEventMulticaster.add(actionListener, l);
504: newEventsOnly = true;
505: }
506:
507: /**
508: * Removes the specified action listener so it no longer receives
509: * action events from this menu item.
510: * If l is null, no exception is thrown and no action is performed.
511: * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
512: * >AWT Threading Issues</a> for details on AWT's threading model.
513: *
514: * @param l the action listener.
515: * @see #addActionListener
516: * @see #getActionListeners
517: * @see java.awt.event.ActionEvent
518: * @see java.awt.event.ActionListener
519: * @since JDK1.1
520: */
521: public synchronized void removeActionListener(ActionListener l) {
522: if (l == null) {
523: return;
524: }
525: actionListener = AWTEventMulticaster.remove(actionListener, l);
526: }
527:
528: /**
529: * Returns an array of all the action listeners
530: * registered on this menu item.
531: *
532: * @return all of this menu item's <code>ActionListener</code>s
533: * or an empty array if no action
534: * listeners are currently registered
535: *
536: * @see #addActionListener
537: * @see #removeActionListener
538: * @see java.awt.event.ActionEvent
539: * @see java.awt.event.ActionListener
540: * @since 1.4
541: */
542: public synchronized ActionListener[] getActionListeners() {
543: return (ActionListener[]) (getListeners(ActionListener.class));
544: }
545:
546: /**
547: * Returns an array of all the objects currently registered
548: * as <code><em>Foo</em>Listener</code>s
549: * upon this <code>MenuItem</code>.
550: * <code><em>Foo</em>Listener</code>s are registered using the
551: * <code>add<em>Foo</em>Listener</code> method.
552: *
553: * <p>
554: * You can specify the <code>listenerType</code> argument
555: * with a class literal, such as
556: * <code><em>Foo</em>Listener.class</code>.
557: * For example, you can query a
558: * <code>MenuItem</code> <code>m</code>
559: * for its action listeners with the following code:
560: *
561: * <pre>ActionListener[] als = (ActionListener[])(m.getListeners(ActionListener.class));</pre>
562: *
563: * If no such listeners exist, this method returns an empty array.
564: *
565: * @param listenerType the type of listeners requested; this parameter
566: * should specify an interface that descends from
567: * <code>java.util.EventListener</code>
568: * @return an array of all objects registered as
569: * <code><em>Foo</em>Listener</code>s on this menu item,
570: * or an empty array if no such
571: * listeners have been added
572: * @exception ClassCastException if <code>listenerType</code>
573: * doesn't specify a class or interface that implements
574: * <code>java.util.EventListener</code>
575: *
576: * @see #getActionListeners
577: * @since 1.3
578: */
579: public <T extends EventListener> T[] getListeners(
580: Class<T> listenerType) {
581: EventListener l = null;
582: if (listenerType == ActionListener.class) {
583: l = actionListener;
584: }
585: return AWTEventMulticaster.getListeners(l, listenerType);
586: }
587:
588: /**
589: * Processes events on this menu item. If the event is an
590: * instance of <code>ActionEvent</code>, it invokes
591: * <code>processActionEvent</code>, another method
592: * defined by <code>MenuItem</code>.
593: * <p>
594: * Currently, menu items only support action events.
595: * <p>Note that if the event parameter is <code>null</code>
596: * the behavior is unspecified and may result in an
597: * exception.
598: *
599: * @param e the event
600: * @see java.awt.MenuItem#processActionEvent
601: * @since JDK1.1
602: */
603: protected void processEvent(AWTEvent e) {
604: if (e instanceof ActionEvent) {
605: processActionEvent((ActionEvent) e);
606: }
607: }
608:
609: // REMIND: remove when filtering is done at lower level
610: boolean eventEnabled(AWTEvent e) {
611: if (e.id == ActionEvent.ACTION_PERFORMED) {
612: if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0
613: || actionListener != null) {
614: return true;
615: }
616: return false;
617: }
618: return super .eventEnabled(e);
619: }
620:
621: /**
622: * Processes action events occurring on this menu item,
623: * by dispatching them to any registered
624: * <code>ActionListener</code> objects.
625: * This method is not called unless action events are
626: * enabled for this component. Action events are enabled
627: * when one of the following occurs:
628: * <p><ul>
629: * <li>An <code>ActionListener</code> object is registered
630: * via <code>addActionListener</code>.
631: * <li>Action events are enabled via <code>enableEvents</code>.
632: * </ul>
633: * <p>Note that if the event parameter is <code>null</code>
634: * the behavior is unspecified and may result in an
635: * exception.
636: *
637: * @param e the action event
638: * @see java.awt.event.ActionEvent
639: * @see java.awt.event.ActionListener
640: * @see java.awt.MenuItem#enableEvents
641: * @since JDK1.1
642: */
643: protected void processActionEvent(ActionEvent e) {
644: ActionListener listener = actionListener;
645: if (listener != null) {
646: listener.actionPerformed(e);
647: }
648: }
649:
650: /**
651: * Returns a string representing the state of this <code>MenuItem</code>.
652: * This method is intended to be used only for debugging purposes, and the
653: * content and format of the returned string may vary between
654: * implementations. The returned string may be empty but may not be
655: * <code>null</code>.
656: *
657: * @return the parameter string of this menu item
658: */
659: public String paramString() {
660: String str = ",label=" + label;
661: if (shortcut != null) {
662: str += ",shortcut=" + shortcut;
663: }
664: return super .paramString() + str;
665: }
666:
667: /* Serialization support.
668: */
669:
670: /**
671: * Menu item serialized data version.
672: *
673: * @serial
674: */
675: private int menuItemSerializedDataVersion = 1;
676:
677: /**
678: * Writes default serializable fields to stream. Writes
679: * a list of serializable <code>ActionListeners</code>
680: * as optional data. The non-serializable listeners are
681: * detected and no attempt is made to serialize them.
682: *
683: * @param s the <code>ObjectOutputStream</code> to write
684: * @serialData <code>null</code> terminated sequence of 0
685: * or more pairs; the pair consists of a <code>String</code>
686: * and an <code>Object</code>; the <code>String</code>
687: * indicates the type of object and is one of the following:
688: * <code>actionListenerK</code> indicating an
689: * <code>ActionListener</code> object
690: *
691: * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
692: * @see #readObject(ObjectInputStream)
693: */
694: private void writeObject(ObjectOutputStream s) throws IOException {
695: s.defaultWriteObject();
696:
697: AWTEventMulticaster.save(s, actionListenerK, actionListener);
698: s.writeObject(null);
699: }
700:
701: /**
702: * Reads the <code>ObjectInputStream</code> and if it
703: * isn't <code>null</code> adds a listener to receive
704: * action events fired by the <code>Menu</code> Item.
705: * Unrecognized keys or values will be ignored.
706: *
707: * @param s the <code>ObjectInputStream</code> to read
708: * @exception HeadlessException if
709: * <code>GraphicsEnvironment.isHeadless</code> returns
710: * <code>true</code>
711: * @see #removeActionListener(ActionListener)
712: * @see #addActionListener(ActionListener)
713: * @see #writeObject(ObjectOutputStream)
714: */
715: private void readObject(ObjectInputStream s)
716: throws ClassNotFoundException, IOException,
717: HeadlessException {
718: // HeadlessException will be thrown from MenuComponent's readObject
719: s.defaultReadObject();
720:
721: Object keyOrNull;
722: while (null != (keyOrNull = s.readObject())) {
723: String key = ((String) keyOrNull).intern();
724:
725: if (actionListenerK == key)
726: addActionListener((ActionListener) (s.readObject()));
727:
728: else
729: // skip value for unrecognized key
730: s.readObject();
731: }
732: }
733:
734: /**
735: * Initialize JNI field and method IDs
736: */
737: private static native void initIDs();
738:
739: /////////////////
740: // Accessibility support
741: ////////////////
742:
743: /**
744: * Gets the AccessibleContext associated with this MenuItem.
745: * For menu items, the AccessibleContext takes the form of an
746: * AccessibleAWTMenuItem.
747: * A new AccessibleAWTMenuItem instance is created if necessary.
748: *
749: * @return an AccessibleAWTMenuItem that serves as the
750: * AccessibleContext of this MenuItem
751: * @since 1.3
752: */
753: public AccessibleContext getAccessibleContext() {
754: if (accessibleContext == null) {
755: accessibleContext = new AccessibleAWTMenuItem();
756: }
757: return accessibleContext;
758: }
759:
760: /**
761: * Inner class of MenuItem used to provide default support for
762: * accessibility. This class is not meant to be used directly by
763: * application developers, but is instead meant only to be
764: * subclassed by menu component developers.
765: * <p>
766: * This class implements accessibility support for the
767: * <code>MenuItem</code> class. It provides an implementation of the
768: * Java Accessibility API appropriate to menu item user-interface elements.
769: * @since 1.3
770: */
771: protected class AccessibleAWTMenuItem extends
772: AccessibleAWTMenuComponent implements AccessibleAction,
773: AccessibleValue {
774: /*
775: * JDK 1.3 serialVersionUID
776: */
777: private static final long serialVersionUID = -217847831945965825L;
778:
779: /**
780: * Get the accessible name of this object.
781: *
782: * @return the localized name of the object -- can be null if this
783: * object does not have a name
784: */
785: public String getAccessibleName() {
786: if (accessibleName != null) {
787: return accessibleName;
788: } else {
789: if (getLabel() == null) {
790: return super .getAccessibleName();
791: } else {
792: return getLabel();
793: }
794: }
795: }
796:
797: /**
798: * Get the role of this object.
799: *
800: * @return an instance of AccessibleRole describing the role of the
801: * object
802: */
803: public AccessibleRole getAccessibleRole() {
804: return AccessibleRole.MENU_ITEM;
805: }
806:
807: /**
808: * Get the AccessibleAction associated with this object. In the
809: * implementation of the Java Accessibility API for this class,
810: * return this object, which is responsible for implementing the
811: * AccessibleAction interface on behalf of itself.
812: *
813: * @return this object
814: */
815: public AccessibleAction getAccessibleAction() {
816: return this ;
817: }
818:
819: /**
820: * Get the AccessibleValue associated with this object. In the
821: * implementation of the Java Accessibility API for this class,
822: * return this object, which is responsible for implementing the
823: * AccessibleValue interface on behalf of itself.
824: *
825: * @return this object
826: */
827: public AccessibleValue getAccessibleValue() {
828: return this ;
829: }
830:
831: /**
832: * Returns the number of Actions available in this object. The
833: * default behavior of a menu item is to have one action.
834: *
835: * @return 1, the number of Actions in this object
836: */
837: public int getAccessibleActionCount() {
838: return 1;
839: }
840:
841: /**
842: * Return a description of the specified action of the object.
843: *
844: * @param i zero-based index of the actions
845: */
846: public String getAccessibleActionDescription(int i) {
847: if (i == 0) {
848: // [[[PENDING: WDW -- need to provide a localized string]]]
849: return new String("click");
850: } else {
851: return null;
852: }
853: }
854:
855: /**
856: * Perform the specified Action on the object
857: *
858: * @param i zero-based index of actions
859: * @return true if the action was performed; otherwise false.
860: */
861: public boolean doAccessibleAction(int i) {
862: if (i == 0) {
863: // Simulate a button click
864: Toolkit
865: .getEventQueue()
866: .postEvent(
867: new ActionEvent(
868: MenuItem.this ,
869: ActionEvent.ACTION_PERFORMED,
870: MenuItem.this
871: .getActionCommand(),
872: EventQueue
873: .getMostRecentEventTime(),
874: 0));
875: return true;
876: } else {
877: return false;
878: }
879: }
880:
881: /**
882: * Get the value of this object as a Number.
883: *
884: * @return An Integer of 0 if this isn't selected or an Integer of 1 if
885: * this is selected.
886: * @see javax.swing.AbstractButton#isSelected()
887: */
888: public Number getCurrentAccessibleValue() {
889: return Integer.valueOf(0);
890: }
891:
892: /**
893: * Set the value of this object as a Number.
894: *
895: * @return True if the value was set.
896: */
897: public boolean setCurrentAccessibleValue(Number n) {
898: return false;
899: }
900:
901: /**
902: * Get the minimum value of this object as a Number.
903: *
904: * @return An Integer of 0.
905: */
906: public Number getMinimumAccessibleValue() {
907: return Integer.valueOf(0);
908: }
909:
910: /**
911: * Get the maximum value of this object as a Number.
912: *
913: * @return An Integer of 0.
914: */
915: public Number getMaximumAccessibleValue() {
916: return Integer.valueOf(0);
917: }
918:
919: } // class AccessibleAWTMenuItem
920:
921: }
|