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