001/* MenuItem.java -- An item in a menu 002 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package java.awt; 040 041import java.awt.event.ActionEvent; 042import java.awt.event.ActionListener; 043import java.awt.peer.MenuItemPeer; 044import java.io.Serializable; 045import java.lang.reflect.Array; 046import java.util.EventListener; 047 048import javax.accessibility.Accessible; 049import javax.accessibility.AccessibleAction; 050import javax.accessibility.AccessibleContext; 051import javax.accessibility.AccessibleRole; 052import javax.accessibility.AccessibleValue; 053 054/** 055 * This class represents an item in a menu. 056 * 057 * @author Aaron M. Renn (arenn@urbanophile.com) 058 */ 059public class MenuItem extends MenuComponent 060 implements Serializable, Accessible 061{ 062 063/* 064 * Static Variables 065 */ 066 067 068 /** 069 * The number used to generate the name returned by getName. 070 */ 071 private static transient long next_menuitem_number; 072 073 // Serialization Constant 074 private static final long serialVersionUID = - 21757335363267194L; 075 076/*************************************************************************/ 077 078/* 079 * Instance Variables 080 */ 081 082/** 083 * @serial The name of the action command generated by this item. 084 * This is package-private to avoid an accessor method. 085 */ 086String actionCommand; 087 088/** 089 * @serial Indicates whether or not this menu item is enabled. 090 * This is package-private to avoid an accessor method. 091 */ 092boolean enabled = true; 093 094/** 095 * @serial The mask of events that are enabled for this menu item. 096 */ 097long eventMask; 098 099/** 100 * @serial This menu item's label 101 * This is package-private to avoid an accessor method. 102 */ 103String label = ""; 104 105/** 106 * @serial The shortcut for this menu item, if any 107 */ 108private MenuShortcut shortcut; 109 110// The list of action listeners for this menu item. 111private 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 */ 226public 227MenuItem() 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 */ 239public 240MenuItem(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 */ 254public 255MenuItem(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 */ 272public String 273getLabel() 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 */ 285public synchronized void 286setLabel(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 */ 304public boolean 305isEnabled() 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 */ 318public synchronized void 319setEnabled(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 */ 334public void 335enable(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 */ 350public void 351enable() 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 */ 368public void 369disable() 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 */ 386public MenuShortcut 387getShortcut() 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 */ 400public void 401setShortcut(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 */ 412public void 413deleteShortcut() 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 */ 426public String 427getActionCommand() 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 */ 443public void 444setActionCommand(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 */ 459protected final void 460enableEvents(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 */ 474protected final void 475disableEvents(long events) 476{ 477 eventMask &= ~events; 478} 479 480/*************************************************************************/ 481 482/** 483 * Creates the native peer for this object. 484 */ 485public void 486addNotify() 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 */ 500public synchronized void 501addActionListener(ActionListener listener) 502{ 503 action_listeners = AWTEventMulticaster.add(action_listeners, listener); 504 505 enableEvents(AWTEvent.ACTION_EVENT_MASK); 506} 507 508public synchronized void 509removeActionListener(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 535void 536dispatchEventImpl(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 */ 556protected void 557processEvent(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 */ 570protected void 571processActionEvent(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 */ 587public String 588paramString() 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 */ 600public 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 */ 613String generateName() 614{ 615 return "menuitem" + getUniqueLong(); 616} 617 618private static synchronized long getUniqueLong() 619{ 620 return next_menuitem_number++; 621} 622 623} // class MenuItem