Frames | No Frames |
1: /* MenuItem.java -- An item in a menu 2: Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.awt; 40: 41: import java.awt.event.ActionEvent; 42: import java.awt.event.ActionListener; 43: import java.awt.peer.MenuItemPeer; 44: import java.io.Serializable; 45: import java.lang.reflect.Array; 46: import java.util.EventListener; 47: 48: import javax.accessibility.Accessible; 49: import javax.accessibility.AccessibleAction; 50: import javax.accessibility.AccessibleContext; 51: import javax.accessibility.AccessibleRole; 52: import javax.accessibility.AccessibleValue; 53: 54: /** 55: * This class represents an item in a menu. 56: * 57: * @author Aaron M. Renn (arenn@urbanophile.com) 58: */ 59: public class MenuItem extends MenuComponent 60: implements Serializable, Accessible 61: { 62: 63: /* 64: * Static Variables 65: */ 66: 67: 68: /** 69: * The number used to generate the name returned by getName. 70: */ 71: private static transient long next_menuitem_number; 72: 73: // Serialization Constant 74: private static final long serialVersionUID = - 21757335363267194L; 75: 76: /*************************************************************************/ 77: 78: /* 79: * Instance Variables 80: */ 81: 82: /** 83: * @serial The name of the action command generated by this item. 84: * This is package-private to avoid an accessor method. 85: */ 86: String actionCommand; 87: 88: /** 89: * @serial Indicates whether or not this menu item is enabled. 90: * This is package-private to avoid an accessor method. 91: */ 92: boolean enabled = true; 93: 94: /** 95: * @serial The mask of events that are enabled for this menu item. 96: */ 97: long eventMask; 98: 99: /** 100: * @serial This menu item's label 101: * This is package-private to avoid an accessor method. 102: */ 103: String label = ""; 104: 105: /** 106: * @serial The shortcut for this menu item, if any 107: */ 108: private MenuShortcut shortcut; 109: 110: // The list of action listeners for this menu item. 111: private transient ActionListener action_listeners; 112: 113: protected class AccessibleAWTMenuItem 114: extends MenuComponent.AccessibleAWTMenuComponent 115: implements AccessibleAction, AccessibleValue 116: { 117: private static final long serialVersionUID = -217847831945965825L; 118: 119: /** Constructor */ 120: protected AccessibleAWTMenuItem() 121: { 122: super(); 123: } 124: 125: 126: 127: public String getAccessibleName() 128: { 129: return label; 130: } 131: 132: public AccessibleAction getAccessibleAction() 133: { 134: return this; 135: } 136: 137: public AccessibleRole getAccessibleRole() 138: { 139: return AccessibleRole.MENU_ITEM; 140: } 141: 142: /* (non-Javadoc) 143: * @see javax.accessibility.AccessibleAction#getAccessibleActionCount() 144: */ 145: public int getAccessibleActionCount() 146: { 147: return 1; 148: } 149: 150: /* (non-Javadoc) 151: * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int) 152: */ 153: public String getAccessibleActionDescription(int i) 154: { 155: if (i == 0) 156: return label; 157: else 158: return null; 159: } 160: 161: /* (non-Javadoc) 162: * @see javax.accessibility.AccessibleAction#doAccessibleAction(int) 163: */ 164: public boolean doAccessibleAction(int i) 165: { 166: if (i != 0) 167: return false; 168: processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand)); 169: return true; 170: } 171: 172: public AccessibleValue getAccessibleValue() 173: { 174: return this; 175: } 176: 177: /* (non-Javadoc) 178: * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue() 179: */ 180: public Number getCurrentAccessibleValue() 181: { 182: return (enabled) ? new Integer(1) : new Integer(0); 183: } 184: 185: /* (non-Javadoc) 186: * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number) 187: */ 188: public boolean setCurrentAccessibleValue(Number number) 189: { 190: boolean result = (number.intValue() != 0); 191: // this. is required by javac 1.3, otherwise it is confused with 192: // MenuItem.this.setEnabled. 193: this.setEnabled(result); 194: return result; 195: } 196: 197: /* (non-Javadoc) 198: * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue() 199: */ 200: public Number getMinimumAccessibleValue() 201: { 202: return new Integer(0); 203: } 204: 205: /* (non-Javadoc) 206: * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue() 207: */ 208: public Number getMaximumAccessibleValue() 209: { 210: return new Integer(0); 211: } 212: 213: } 214: 215: 216: /*************************************************************************/ 217: 218: /* 219: * Constructors 220: */ 221: 222: /** 223: * Initializes a new instance of <code>MenuItem</code> with no label 224: * and no shortcut. 225: */ 226: public 227: MenuItem() 228: { 229: } 230: 231: /*************************************************************************/ 232: 233: /** 234: * Initializes a new instance of <code>MenuItem</code> with the specified 235: * label and no shortcut. 236: * 237: * @param label The label for this menu item. 238: */ 239: public 240: MenuItem(String label) 241: { 242: this.label = label; 243: } 244: 245: /*************************************************************************/ 246: 247: /** 248: * Initializes a new instance of <code>MenuItem</code> with the specified 249: * label and shortcut. 250: * 251: * @param label The label for this menu item. 252: * @param shortcut The shortcut for this menu item. 253: */ 254: public 255: MenuItem(String label, MenuShortcut shortcut) 256: { 257: this.label = label; 258: this.shortcut = shortcut; 259: } 260: 261: /*************************************************************************/ 262: 263: /* 264: * Instance Methods 265: */ 266: 267: /** 268: * Returns the label for this menu item, which may be <code>null</code>. 269: * 270: * @return The label for this menu item. 271: */ 272: public String 273: getLabel() 274: { 275: return(label); 276: } 277: 278: /*************************************************************************/ 279: 280: /** 281: * This method sets the label for this menu to the specified value. 282: * 283: * @param label The new label for this menu item. 284: */ 285: public synchronized void 286: setLabel(String label) 287: { 288: this.label = label; 289: if (peer != null) 290: { 291: MenuItemPeer mp = (MenuItemPeer) peer; 292: mp.setLabel (label); 293: } 294: } 295: 296: /*************************************************************************/ 297: 298: /** 299: * Tests whether or not this menu item is enabled. 300: * 301: * @return <code>true</code> if this menu item is enabled, <code>false</code> 302: * otherwise. 303: */ 304: public boolean 305: isEnabled() 306: { 307: return(enabled); 308: } 309: 310: /*************************************************************************/ 311: 312: /** 313: * Sets the enabled status of this menu item. 314: * 315: * @param enabled <code>true</code> to enable this menu item, 316: * <code>false</code> otherwise. 317: */ 318: public synchronized void 319: setEnabled(boolean enabled) 320: { 321: enable (enabled); 322: } 323: 324: /*************************************************************************/ 325: 326: /** 327: * Sets the enabled status of this menu item. 328: * 329: * @param enabled <code>true</code> to enable this menu item, 330: * <code>false</code> otherwise. 331: * 332: * @deprecated This method is deprecated in favor of <code>setEnabled()</code>. 333: */ 334: public void 335: enable(boolean enabled) 336: { 337: if (enabled) 338: enable (); 339: else 340: disable (); 341: } 342: 343: /*************************************************************************/ 344: 345: /** 346: * Enables this menu item. 347: * 348: * @deprecated This method is deprecated in favor of <code>setEnabled()</code>. 349: */ 350: public void 351: enable() 352: { 353: if (enabled) 354: return; 355: 356: this.enabled = true; 357: if (peer != null) 358: ((MenuItemPeer) peer).setEnabled (true); 359: } 360: 361: /*************************************************************************/ 362: 363: /** 364: * Disables this menu item. 365: * 366: * @deprecated This method is deprecated in favor of <code>setEnabled()</code>. 367: */ 368: public void 369: disable() 370: { 371: if (!enabled) 372: return; 373: 374: this.enabled = false; 375: if (peer != null) 376: ((MenuItemPeer) peer).setEnabled (false); 377: } 378: 379: /*************************************************************************/ 380: 381: /** 382: * Returns the shortcut for this menu item, which may be <code>null</code>. 383: * 384: * @return The shortcut for this menu item. 385: */ 386: public MenuShortcut 387: getShortcut() 388: { 389: return(shortcut); 390: } 391: 392: /*************************************************************************/ 393: 394: /** 395: * Sets the shortcut for this menu item to the specified value. This 396: * must be done before the native peer is created. 397: * 398: * @param shortcut The new shortcut for this menu item. 399: */ 400: public void 401: setShortcut(MenuShortcut shortcut) 402: { 403: this.shortcut = shortcut; 404: } 405: 406: /*************************************************************************/ 407: 408: /** 409: * Deletes the shortcut for this menu item if one exists. This must be 410: * done before the native peer is created. 411: */ 412: public void 413: deleteShortcut() 414: { 415: shortcut = null; 416: } 417: 418: /*************************************************************************/ 419: 420: /** 421: * Returns the name of the action command in the action events 422: * generated by this menu item. 423: * 424: * @return The action command name 425: */ 426: public String 427: getActionCommand() 428: { 429: if (actionCommand == null) 430: return label; 431: else 432: return actionCommand; 433: } 434: 435: /*************************************************************************/ 436: 437: /** 438: * Sets the name of the action command in the action events generated by 439: * this menu item. 440: * 441: * @param actionCommand The new action command name. 442: */ 443: public void 444: setActionCommand(String actionCommand) 445: { 446: this.actionCommand = actionCommand; 447: } 448: 449: /*************************************************************************/ 450: 451: /** 452: * Enables the specified events. This is done automatically when a 453: * listener is added and does not normally need to be done by 454: * application code. 455: * 456: * @param events The events to enable, which should be the bit masks 457: * from <code>AWTEvent</code>. 458: */ 459: protected final void 460: enableEvents(long events) 461: { 462: eventMask |= events; 463: // TODO: see comment in Component.enableEvents(). 464: } 465: 466: /*************************************************************************/ 467: 468: /** 469: * Disables the specified events. 470: * 471: * @param events The events to enable, which should be the bit masks 472: * from <code>AWTEvent</code>. 473: */ 474: protected final void 475: disableEvents(long events) 476: { 477: eventMask &= ~events; 478: } 479: 480: /*************************************************************************/ 481: 482: /** 483: * Creates the native peer for this object. 484: */ 485: public void 486: addNotify() 487: { 488: if (peer == null) 489: peer = getToolkit ().createMenuItem (this); 490: } 491: 492: /*************************************************************************/ 493: 494: /** 495: * Adds the specified listener to the list of registered action listeners 496: * for this component. 497: * 498: * @param listener The listener to add. 499: */ 500: public synchronized void 501: addActionListener(ActionListener listener) 502: { 503: action_listeners = AWTEventMulticaster.add(action_listeners, listener); 504: 505: enableEvents(AWTEvent.ACTION_EVENT_MASK); 506: } 507: 508: public synchronized void 509: removeActionListener(ActionListener l) 510: { 511: action_listeners = AWTEventMulticaster.remove(action_listeners, l); 512: } 513: 514: public synchronized ActionListener[] getActionListeners() 515: { 516: return (ActionListener[]) 517: AWTEventMulticaster.getListeners(action_listeners, 518: ActionListener.class); 519: } 520: 521: /** Returns all registered EventListers of the given listenerType. 522: * listenerType must be a subclass of EventListener, or a 523: * ClassClassException is thrown. 524: * @since 1.3 525: */ 526: public <T extends EventListener> T[] getListeners(Class<T> listenerType) 527: { 528: if (listenerType == ActionListener.class) 529: return (T[]) getActionListeners(); 530: return (T[]) Array.newInstance(listenerType, 0); 531: } 532: 533: /*************************************************************************/ 534: 535: void 536: dispatchEventImpl(AWTEvent e) 537: { 538: if (e.id <= ActionEvent.ACTION_LAST 539: && e.id >= ActionEvent.ACTION_FIRST 540: && (action_listeners != null 541: || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0)) 542: processEvent(e); 543: 544: // Send the event to the parent menu if it has not yet been 545: // consumed. 546: if (!e.isConsumed ()) 547: ((Menu) getParent ()).processEvent (e); 548: } 549: 550: /** 551: * Processes the specified event by calling <code>processActionEvent()</code> 552: * if it is an instance of <code>ActionEvent</code>. 553: * 554: * @param event The event to process. 555: */ 556: protected void 557: processEvent(AWTEvent event) 558: { 559: if (event instanceof ActionEvent) 560: processActionEvent((ActionEvent)event); 561: } 562: 563: /*************************************************************************/ 564: 565: /** 566: * Processes the specified event by dispatching it to any registered listeners. 567: * 568: * @param event The event to process. 569: */ 570: protected void 571: processActionEvent(ActionEvent event) 572: { 573: if (action_listeners != null) 574: { 575: event.setSource(this); 576: action_listeners.actionPerformed(event); 577: } 578: } 579: 580: /*************************************************************************/ 581: 582: /** 583: * Returns a debugging string for this object. 584: * 585: * @return A debugging string for this object. 586: */ 587: public String 588: paramString() 589: { 590: return ("label=" + label + ",enabled=" + enabled + 591: ",actionCommand=" + actionCommand + "," + super.paramString()); 592: } 593: 594: /** 595: * Gets the AccessibleContext associated with this <code>MenuItem</code>. 596: * The context is created, if necessary. 597: * 598: * @return the associated context 599: */ 600: public AccessibleContext getAccessibleContext() 601: { 602: /* Create the context if this is the first request */ 603: if (accessibleContext == null) 604: accessibleContext = new AccessibleAWTMenuItem(); 605: return accessibleContext; 606: } 607: 608: /** 609: * Generate a unique name for this <code>MenuItem</code>. 610: * 611: * @return A unique name for this <code>MenuItem</code>. 612: */ 613: String generateName() 614: { 615: return "menuitem" + getUniqueLong(); 616: } 617: 618: private static synchronized long getUniqueLong() 619: { 620: return next_menuitem_number++; 621: } 622: 623: } // class MenuItem