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 */
AccessibleAWTMenuItem()120     protected AccessibleAWTMenuItem()
121     {
122       super();
123     }
124 
125 
126 
getAccessibleName()127     public String getAccessibleName()
128     {
129       return label;
130     }
131 
getAccessibleAction()132     public AccessibleAction getAccessibleAction()
133     {
134       return this;
135     }
136 
getAccessibleRole()137     public AccessibleRole getAccessibleRole()
138     {
139       return AccessibleRole.MENU_ITEM;
140     }
141 
142     /* (non-Javadoc)
143      * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
144      */
getAccessibleActionCount()145     public int getAccessibleActionCount()
146     {
147       return 1;
148     }
149 
150     /* (non-Javadoc)
151      * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
152      */
getAccessibleActionDescription(int i)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      */
doAccessibleAction(int i)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 
getAccessibleValue()172     public AccessibleValue getAccessibleValue()
173     {
174       return this;
175     }
176 
177     /* (non-Javadoc)
178      * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
179      */
getCurrentAccessibleValue()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      */
setCurrentAccessibleValue(Number number)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      */
getMinimumAccessibleValue()200     public Number getMinimumAccessibleValue()
201     {
202       return new Integer(0);
203     }
204 
205     /* (non-Javadoc)
206      * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
207      */
getMaximumAccessibleValue()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
MenuItem()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
MenuItem(String label)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
MenuItem(String label, MenuShortcut shortcut)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
getLabel()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
setLabel(String label)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
isEnabled()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
setEnabled(boolean enabled)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
enable(boolean enabled)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
enable()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
disable()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
getShortcut()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
setShortcut(MenuShortcut shortcut)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
deleteShortcut()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
getActionCommand()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
setActionCommand(String actionCommand)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
enableEvents(long events)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
disableEvents(long events)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
addNotify()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
addActionListener(ActionListener listener)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
removeActionListener(ActionListener l)509 removeActionListener(ActionListener l)
510 {
511   action_listeners = AWTEventMulticaster.remove(action_listeners, l);
512 }
513 
getActionListeners()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  */
getListeners(Class<T> listenerType)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
dispatchEventImpl(AWTEvent e)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
processEvent(AWTEvent event)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
processActionEvent(ActionEvent event)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
paramString()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  */
getAccessibleContext()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  */
generateName()613 String generateName()
614 {
615   return "menuitem" + getUniqueLong();
616 }
617 
getUniqueLong()618 private static synchronized long getUniqueLong()
619 {
620   return next_menuitem_number++;
621 }
622 
623 } // class MenuItem
624