1 /* 2 * Copyright (c) 1995, 2009, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.peer.MenuItemPeer; 28 import java.awt.event.*; 29 import java.util.EventListener; 30 import java.io.ObjectOutputStream; 31 import java.io.ObjectInputStream; 32 import java.io.IOException; 33 import javax.accessibility.*; 34 35 36 /** 37 * All items in a menu must belong to the class 38 * <code>MenuItem</code>, or one of its subclasses. 39 * <p> 40 * The default <code>MenuItem</code> object embodies 41 * a simple labeled menu item. 42 * <p> 43 * This picture of a menu bar shows five menu items: 44 * <IMG SRC="doc-files/MenuBar-1.gif" alt="The following text describes this graphic." 45 * ALIGN=CENTER HSPACE=10 VSPACE=7> 46 * <br CLEAR=LEFT> 47 * The first two items are simple menu items, labeled 48 * <code>"Basic"</code> and <code>"Simple"</code>. 49 * Following these two items is a separator, which is itself 50 * a menu item, created with the label <code>"-"</code>. 51 * Next is an instance of <code>CheckboxMenuItem</code> 52 * labeled <code>"Check"</code>. The final menu item is a 53 * submenu labeled <code>"More Examples"</code>, 54 * and this submenu is an instance of <code>Menu</code>. 55 * <p> 56 * When a menu item is selected, AWT sends an action event to 57 * the menu item. Since the event is an 58 * instance of <code>ActionEvent</code>, the <code>processEvent</code> 59 * method examines the event and passes it along to 60 * <code>processActionEvent</code>. The latter method redirects the 61 * event to any <code>ActionListener</code> objects that have 62 * registered an interest in action events generated by this 63 * menu item. 64 * <P> 65 * Note that the subclass <code>Menu</code> overrides this behavior and 66 * does not send any event to the frame until one of its subitems is 67 * selected. 68 * 69 * @author Sami Shaio 70 */ 71 public class MenuItem extends MenuComponent implements Accessible { 72 73 static { 74 /* ensure that the necessary native libraries are loaded */ 75 Toolkit.loadLibraries(); 76 if (!GraphicsEnvironment.isHeadless()) { 77 initIDs(); 78 } 79 } 80 81 /** 82 * A value to indicate whether a menu item is enabled 83 * or not. If it is enabled, <code>enabled</code> will 84 * be set to true. Else <code>enabled</code> will 85 * be set to false. 86 * 87 * @serial 88 * @see #isEnabled() 89 * @see #setEnabled(boolean) 90 */ 91 boolean enabled = true; 92 93 /** 94 * <code>label</code> is the label of a menu item. 95 * It can be any string. 96 * 97 * @serial 98 * @see #getLabel() 99 * @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) throws HeadlessException { 192 this.label = label; 193 this.shortcut = s; 194 } 195 196 /** 197 * Construct a name for this MenuComponent. Called by getName() when 198 * the name is null. 199 */ 200 String constructComponentName() { 201 synchronized (MenuItem.class) { 202 return base + nameCounter++; 203 } 204 } 205 206 /** 207 * Creates the menu item's peer. The peer allows us to modify the 208 * appearance of the menu item without changing its functionality. 209 */ 210 public void addNotify() { 211 synchronized (getTreeLock()) { 212 if (peer == null) 213 peer = Toolkit.getDefaultToolkit().createMenuItem(this); 214 } 215 } 216 217 /** 218 * Gets the label for this menu item. 219 * @return the label of this menu item, or <code>null</code> 220 if this menu item has no label. 221 * @see java.awt.MenuItem#setLabel 222 * @since JDK1.0 223 */ 224 public String getLabel() { 225 return label; 226 } 227 228 /** 229 * Sets the label for this menu item to the specified label. 230 * @param label the new label, or <code>null</code> for no label. 231 * @see java.awt.MenuItem#getLabel 232 * @since JDK1.0 233 */ 234 public synchronized void setLabel(String label) { 235 this.label = label; 236 MenuItemPeer peer = (MenuItemPeer)this.peer; 237 if (peer != null) { 238 peer.setLabel(label); 239 } 240 } 241 242 /** 243 * Checks whether this menu item is enabled. 244 * @see java.awt.MenuItem#setEnabled 245 * @since JDK1.0 246 */ 247 public boolean isEnabled() { 248 return enabled; 249 } 250 251 /** 252 * Sets whether or not this menu item can be chosen. 253 * @param b if <code>true</code>, enables this menu item; 254 * if <code>false</code>, disables it. 255 * @see java.awt.MenuItem#isEnabled 256 * @since JDK1.1 257 */ 258 public synchronized void setEnabled(boolean b) { 259 enable(b); 260 } 261 262 /** 263 * @deprecated As of JDK version 1.1, 264 * replaced by <code>setEnabled(boolean)</code>. 265 */ 266 @Deprecated 267 public synchronized void enable() { 268 enabled = true; 269 MenuItemPeer peer = (MenuItemPeer)this.peer; 270 if (peer != null) { 271 peer.setEnabled(true); 272 } 273 } 274 275 /** 276 * @deprecated As of JDK version 1.1, 277 * replaced by <code>setEnabled(boolean)</code>. 278 */ 279 @Deprecated 280 public void enable(boolean b) { 281 if (b) { 282 enable(); 283 } else { 284 disable(); 285 } 286 } 287 288 /** 289 * @deprecated As of JDK version 1.1, 290 * replaced by <code>setEnabled(boolean)</code>. 291 */ 292 @Deprecated 293 public synchronized void disable() { 294 enabled = false; 295 MenuItemPeer peer = (MenuItemPeer)this.peer; 296 if (peer != null) { 297 peer.setEnabled(false); 298 } 299 } 300 301 /** 302 * Get the <code>MenuShortcut</code> object associated with this 303 * menu item, 304 * @return the menu shortcut associated with this menu item, 305 * or <code>null</code> if none has been specified. 306 * @see java.awt.MenuItem#setShortcut 307 * @since JDK1.1 308 */ 309 public MenuShortcut getShortcut() { 310 return shortcut; 311 } 312 313 /** 314 * Set the <code>MenuShortcut</code> object associated with this 315 * menu item. If a menu shortcut is already associated with 316 * this menu item, it is replaced. 317 * @param s the menu shortcut to associate 318 * with this menu item. 319 * @see java.awt.MenuItem#getShortcut 320 * @since JDK1.1 321 */ 322 public void setShortcut(MenuShortcut s) { 323 shortcut = s; 324 MenuItemPeer peer = (MenuItemPeer)this.peer; 325 if (peer != null) { 326 peer.setLabel(label); 327 } 328 } 329 330 /** 331 * Delete any <code>MenuShortcut</code> object associated 332 * with this menu item. 333 * @since JDK1.1 334 */ 335 public void deleteShortcut() { 336 shortcut = null; 337 MenuItemPeer peer = (MenuItemPeer)this.peer; 338 if (peer != null) { 339 peer.setLabel(label); 340 } 341 } 342 343 /* 344 * Delete a matching MenuShortcut associated with this MenuItem. 345 * Used when iterating Menus. 346 */ 347 void deleteShortcut(MenuShortcut s) { 348 if (s.equals(shortcut)) { 349 shortcut = null; 350 MenuItemPeer peer = (MenuItemPeer)this.peer; 351 if (peer != null) { 352 peer.setLabel(label); 353 } 354 } 355 } 356 357 /* 358 * The main goal of this method is to post an appropriate event 359 * to the event queue when menu shortcut is pressed. However, 360 * in subclasses this method may do more than just posting 361 * an event. 362 */ 363 void doMenuEvent(long when, int modifiers) { 364 Toolkit.getEventQueue().postEvent( 365 new ActionEvent(this, ActionEvent.ACTION_PERFORMED, 366 getActionCommand(), when, modifiers)); 367 } 368 369 /* 370 * Returns true if the item and all its ancestors are 371 * enabled, false otherwise 372 */ 373 private final boolean isItemEnabled() { 374 // Fix For 6185151: Menu shortcuts of all menuitems within a menu 375 // should be disabled when the menu itself is disabled 376 if (!isEnabled()) { 377 return false; 378 } 379 MenuContainer container = getParent_NoClientCode(); 380 do { 381 if (!(container instanceof Menu)) { 382 return true; 383 } 384 Menu menu = (Menu)container; 385 if (!menu.isEnabled()) { 386 return false; 387 } 388 container = menu.getParent_NoClientCode(); 389 } while (container != null); 390 return true; 391 } 392 393 /* 394 * Post an ActionEvent to the target (on 395 * keydown) and the item is enabled. 396 * Returns true if there is an associated shortcut. 397 */ 398 boolean handleShortcut(KeyEvent e) { 399 MenuShortcut s = new MenuShortcut(e.getKeyCode(), 400 (e.getModifiers() & InputEvent.SHIFT_MASK) > 0); 401 MenuShortcut sE = new MenuShortcut(e.getExtendedKeyCode(), 402 (e.getModifiers() & InputEvent.SHIFT_MASK) > 0); 403 // Fix For 6185151: Menu shortcuts of all menuitems within a menu 404 // should be disabled when the menu itself is disabled 405 if ((s.equals(shortcut) || sE.equals(shortcut)) && isItemEnabled()) { 406 // MenuShortcut match -- issue an event on keydown. 407 if (e.getID() == KeyEvent.KEY_PRESSED) { 408 doMenuEvent(e.getWhen(), e.getModifiers()); 409 } else { 410 // silently eat key release. 411 } 412 return true; 413 } 414 return false; 415 } 416 417 MenuItem getShortcutMenuItem(MenuShortcut s) { 418 return (s.equals(shortcut)) ? this : null; 419 } 420 421 /** 422 * Enables event delivery to this menu item for events 423 * to be defined by the specified event mask parameter 424 * <p> 425 * Since event types are automatically enabled when a listener for 426 * that type is added to the menu item, this method only needs 427 * to be invoked by subclasses of <code>MenuItem</code> which desire to 428 * have the specified event types delivered to <code>processEvent</code> 429 * regardless of whether a listener is registered. 430 * 431 * @param eventsToEnable the event mask defining the event types 432 * @see java.awt.MenuItem#processEvent 433 * @see java.awt.MenuItem#disableEvents 434 * @see java.awt.Component#enableEvents 435 * @since JDK1.1 436 */ 437 protected final void enableEvents(long eventsToEnable) { 438 eventMask |= eventsToEnable; 439 newEventsOnly = true; 440 } 441 442 /** 443 * Disables event delivery to this menu item for events 444 * defined by the specified event mask parameter. 445 * 446 * @param eventsToDisable the event mask defining the event types 447 * @see java.awt.MenuItem#processEvent 448 * @see java.awt.MenuItem#enableEvents 449 * @see java.awt.Component#disableEvents 450 * @since JDK1.1 451 */ 452 protected final void disableEvents(long eventsToDisable) { 453 eventMask &= ~eventsToDisable; 454 } 455 456 /** 457 * Sets the command name of the action event that is fired 458 * by this menu item. 459 * <p> 460 * By default, the action command is set to the label of 461 * the menu item. 462 * @param command the action command to be set 463 * for this menu item. 464 * @see java.awt.MenuItem#getActionCommand 465 * @since JDK1.1 466 */ 467 public void setActionCommand(String command) { 468 actionCommand = command; 469 } 470 471 /** 472 * Gets the command name of the action event that is fired 473 * by this menu item. 474 * @see java.awt.MenuItem#setActionCommand 475 * @since JDK1.1 476 */ 477 public String getActionCommand() { 478 return getActionCommandImpl(); 479 } 480 481 // This is final so it can be called on the Toolkit thread. 482 final String getActionCommandImpl() { 483 return (actionCommand == null? label : actionCommand); 484 } 485 486 /** 487 * Adds the specified action listener to receive action events 488 * from this menu item. 489 * If l is null, no exception is thrown and no action is performed. 490 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 491 * >AWT Threading Issues</a> for details on AWT's threading model. 492 * 493 * @param l the action listener. 494 * @see #removeActionListener 495 * @see #getActionListeners 496 * @see java.awt.event.ActionEvent 497 * @see java.awt.event.ActionListener 498 * @since JDK1.1 499 */ 500 public synchronized void addActionListener(ActionListener l) { 501 if (l == null) { 502 return; 503 } 504 actionListener = AWTEventMulticaster.add(actionListener, l); 505 newEventsOnly = true; 506 } 507 508 /** 509 * Removes the specified action listener so it no longer receives 510 * action events from this menu item. 511 * If l is null, no exception is thrown and no action is performed. 512 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 513 * >AWT Threading Issues</a> for details on AWT's threading model. 514 * 515 * @param l the action listener. 516 * @see #addActionListener 517 * @see #getActionListeners 518 * @see java.awt.event.ActionEvent 519 * @see java.awt.event.ActionListener 520 * @since JDK1.1 521 */ 522 public synchronized void removeActionListener(ActionListener l) { 523 if (l == null) { 524 return; 525 } 526 actionListener = AWTEventMulticaster.remove(actionListener, l); 527 } 528 529 /** 530 * Returns an array of all the action listeners 531 * registered on this menu item. 532 * 533 * @return all of this menu item's <code>ActionListener</code>s 534 * or an empty array if no action 535 * listeners are currently registered 536 * 537 * @see #addActionListener 538 * @see #removeActionListener 539 * @see java.awt.event.ActionEvent 540 * @see java.awt.event.ActionListener 541 * @since 1.4 542 */ 543 public synchronized ActionListener[] getActionListeners() { 544 return getListeners(ActionListener.class); 545 } 546 547 /** 548 * Returns an array of all the objects currently registered 549 * as <code><em>Foo</em>Listener</code>s 550 * upon this <code>MenuItem</code>. 551 * <code><em>Foo</em>Listener</code>s are registered using the 552 * <code>add<em>Foo</em>Listener</code> method. 553 * 554 * <p> 555 * You can specify the <code>listenerType</code> argument 556 * with a class literal, such as 557 * <code><em>Foo</em>Listener.class</code>. 558 * For example, you can query a 559 * <code>MenuItem</code> <code>m</code> 560 * for its action listeners with the following code: 561 * 562 * <pre>ActionListener[] als = (ActionListener[])(m.getListeners(ActionListener.class));</pre> 563 * 564 * If no such listeners exist, this method returns an empty array. 565 * 566 * @param listenerType the type of listeners requested; this parameter 567 * should specify an interface that descends from 568 * <code>java.util.EventListener</code> 569 * @return an array of all objects registered as 570 * <code><em>Foo</em>Listener</code>s on this menu item, 571 * or an empty array if no such 572 * listeners have been added 573 * @exception ClassCastException if <code>listenerType</code> 574 * doesn't specify a class or interface that implements 575 * <code>java.util.EventListener</code> 576 * 577 * @see #getActionListeners 578 * @since 1.3 579 */ 580 public <T extends EventListener> T[] getListeners(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 668 /* Serialization support. 669 */ 670 671 /** 672 * Menu item serialized data version. 673 * 674 * @serial 675 */ 676 private int menuItemSerializedDataVersion = 1; 677 678 /** 679 * Writes default serializable fields to stream. Writes 680 * a list of serializable <code>ActionListeners</code> 681 * as optional data. The non-serializable listeners are 682 * detected and no attempt is made to serialize them. 683 * 684 * @param s the <code>ObjectOutputStream</code> to write 685 * @serialData <code>null</code> terminated sequence of 0 686 * or more pairs; the pair consists of a <code>String</code> 687 * and an <code>Object</code>; the <code>String</code> 688 * indicates the type of object and is one of the following: 689 * <code>actionListenerK</code> indicating an 690 * <code>ActionListener</code> object 691 * 692 * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) 693 * @see #readObject(ObjectInputStream) 694 */ 695 private void writeObject(ObjectOutputStream s) 696 throws IOException 697 { 698 s.defaultWriteObject(); 699 700 AWTEventMulticaster.save(s, actionListenerK, actionListener); 701 s.writeObject(null); 702 } 703 704 /** 705 * Reads the <code>ObjectInputStream</code> and if it 706 * isn't <code>null</code> adds a listener to receive 707 * action events fired by the <code>Menu</code> Item. 708 * Unrecognized keys or values will be ignored. 709 * 710 * @param s the <code>ObjectInputStream</code> to read 711 * @exception HeadlessException if 712 * <code>GraphicsEnvironment.isHeadless</code> returns 713 * <code>true</code> 714 * @see #removeActionListener(ActionListener) 715 * @see #addActionListener(ActionListener) 716 * @see #writeObject(ObjectOutputStream) 717 */ 718 private void readObject(ObjectInputStream s) 719 throws ClassNotFoundException, IOException, HeadlessException 720 { 721 // HeadlessException will be thrown from MenuComponent's readObject 722 s.defaultReadObject(); 723 724 Object keyOrNull; 725 while(null != (keyOrNull = s.readObject())) { 726 String key = ((String)keyOrNull).intern(); 727 728 if (actionListenerK == key) 729 addActionListener((ActionListener)(s.readObject())); 730 731 else // skip value for unrecognized key 732 s.readObject(); 733 } 734 } 735 736 /** 737 * Initialize JNI field and method IDs 738 */ 739 private static native void initIDs(); 740 741 742 ///////////////// 743 // Accessibility support 744 //////////////// 745 746 /** 747 * Gets the AccessibleContext associated with this MenuItem. 748 * For menu items, the AccessibleContext takes the form of an 749 * AccessibleAWTMenuItem. 750 * A new AccessibleAWTMenuItem instance is created if necessary. 751 * 752 * @return an AccessibleAWTMenuItem that serves as the 753 * AccessibleContext of this MenuItem 754 * @since 1.3 755 */ 756 public AccessibleContext getAccessibleContext() { 757 if (accessibleContext == null) { 758 accessibleContext = new AccessibleAWTMenuItem(); 759 } 760 return accessibleContext; 761 } 762 763 /** 764 * Inner class of MenuItem used to provide default support for 765 * accessibility. This class is not meant to be used directly by 766 * application developers, but is instead meant only to be 767 * subclassed by menu component developers. 768 * <p> 769 * This class implements accessibility support for the 770 * <code>MenuItem</code> class. It provides an implementation of the 771 * Java Accessibility API appropriate to menu item user-interface elements. 772 * @since 1.3 773 */ 774 protected class AccessibleAWTMenuItem extends AccessibleAWTMenuComponent 775 implements AccessibleAction, AccessibleValue 776 { 777 /* 778 * JDK 1.3 serialVersionUID 779 */ 780 private static final long serialVersionUID = -217847831945965825L; 781 782 /** 783 * Get the accessible name of this object. 784 * 785 * @return the localized name of the object -- can be null if this 786 * object does not have a name 787 */ 788 public String getAccessibleName() { 789 if (accessibleName != null) { 790 return accessibleName; 791 } else { 792 if (getLabel() == null) { 793 return super.getAccessibleName(); 794 } else { 795 return getLabel(); 796 } 797 } 798 } 799 800 /** 801 * Get the role of this object. 802 * 803 * @return an instance of AccessibleRole describing the role of the 804 * object 805 */ 806 public AccessibleRole getAccessibleRole() { 807 return AccessibleRole.MENU_ITEM; 808 } 809 810 /** 811 * Get the AccessibleAction associated with this object. In the 812 * implementation of the Java Accessibility API for this class, 813 * return this object, which is responsible for implementing the 814 * AccessibleAction interface on behalf of itself. 815 * 816 * @return this object 817 */ 818 public AccessibleAction getAccessibleAction() { 819 return this; 820 } 821 822 /** 823 * Get the AccessibleValue associated with this object. In the 824 * implementation of the Java Accessibility API for this class, 825 * return this object, which is responsible for implementing the 826 * AccessibleValue interface on behalf of itself. 827 * 828 * @return this object 829 */ 830 public AccessibleValue getAccessibleValue() { 831 return this; 832 } 833 834 /** 835 * Returns the number of Actions available in this object. The 836 * default behavior of a menu item is to have one action. 837 * 838 * @return 1, the number of Actions in this object 839 */ 840 public int getAccessibleActionCount() { 841 return 1; 842 } 843 844 /** 845 * Return a description of the specified action of the object. 846 * 847 * @param i zero-based index of the actions 848 */ 849 public String getAccessibleActionDescription(int i) { 850 if (i == 0) { 851 // [[[PENDING: WDW -- need to provide a localized string]]] 852 return "click"; 853 } else { 854 return null; 855 } 856 } 857 858 /** 859 * Perform the specified Action on the object 860 * 861 * @param i zero-based index of actions 862 * @return true if the action was performed; otherwise false. 863 */ 864 public boolean doAccessibleAction(int i) { 865 if (i == 0) { 866 // Simulate a button click 867 Toolkit.getEventQueue().postEvent( 868 new ActionEvent(MenuItem.this, 869 ActionEvent.ACTION_PERFORMED, 870 MenuItem.this.getActionCommand(), 871 EventQueue.getMostRecentEventTime(), 872 0)); 873 return true; 874 } else { 875 return false; 876 } 877 } 878 879 /** 880 * Get the value of this object as a Number. 881 * 882 * @return An Integer of 0 if this isn't selected or an Integer of 1 if 883 * this is selected. 884 * @see javax.swing.AbstractButton#isSelected() 885 */ 886 public Number getCurrentAccessibleValue() { 887 return Integer.valueOf(0); 888 } 889 890 /** 891 * Set the value of this object as a Number. 892 * 893 * @return True if the value was set. 894 */ 895 public boolean setCurrentAccessibleValue(Number n) { 896 return false; 897 } 898 899 /** 900 * Get the minimum value of this object as a Number. 901 * 902 * @return An Integer of 0. 903 */ 904 public Number getMinimumAccessibleValue() { 905 return Integer.valueOf(0); 906 } 907 908 /** 909 * Get the maximum value of this object as a Number. 910 * 911 * @return An Integer of 0. 912 */ 913 public Number getMaximumAccessibleValue() { 914 return Integer.valueOf(0); 915 } 916 917 } // class AccessibleAWTMenuItem 918 919 }