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