001 /* MenuItem.java -- An item in a menu
002 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.awt;
040
041 import java.awt.event.ActionEvent;
042 import java.awt.event.ActionListener;
043 import java.awt.peer.MenuItemPeer;
044 import java.io.Serializable;
045 import java.lang.reflect.Array;
046 import java.util.EventListener;
047
048 import javax.accessibility.Accessible;
049 import javax.accessibility.AccessibleAction;
050 import javax.accessibility.AccessibleContext;
051 import javax.accessibility.AccessibleRole;
052 import javax.accessibility.AccessibleValue;
053
054 /**
055 * This class represents an item in a menu.
056 *
057 * @author Aaron M. Renn (arenn@urbanophile.com)
058 */
059 public 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 */
086 String 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 */
092 boolean enabled = true;
093
094 /**
095 * @serial The mask of events that are enabled for this menu item.
096 */
097 long eventMask;
098
099 /**
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