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