OSDN Git Service

2005-04-19 Roman Kennke <roman@kennke.org>
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / JMenuItem.java
1 /* JMenuItem.java --
2    Copyright (C) 2002, 2004, 2005  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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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 javax.swing;
40
41 import java.awt.Component;
42 import java.awt.event.InputEvent;
43 import java.awt.event.KeyEvent;
44 import java.awt.event.MouseEvent;
45 import java.beans.PropertyChangeEvent;
46 import java.beans.PropertyChangeListener;
47 import java.io.IOException;
48 import java.io.ObjectInputStream;
49 import java.io.ObjectOutputStream;
50 import java.util.EventListener;
51
52 import javax.accessibility.Accessible;
53 import javax.accessibility.AccessibleContext;
54 import javax.accessibility.AccessibleRole;
55 import javax.swing.event.ChangeEvent;
56 import javax.swing.event.ChangeListener;
57 import javax.swing.event.MenuDragMouseEvent;
58 import javax.swing.event.MenuDragMouseListener;
59 import javax.swing.event.MenuKeyEvent;
60 import javax.swing.event.MenuKeyListener;
61 import javax.swing.plaf.MenuItemUI;
62
63 /**
64  * JMenuItem represents element in the menu. It inherits most of
65  * its functionality from AbstractButton, however its behavior somewhat
66  * varies from it. JMenuItem fire different kinds of events.
67  * PropertyChangeEvents are fired when menuItems properties are modified;
68  * ChangeEvents are fired when menuItem's state changes and actionEvents are
69  * fired when menu item is selected. In addition to this events menuItem also
70  * fire MenuDragMouseEvent and MenuKeyEvents when mouse is dragged over
71  * the menu item or associated key with menu item is invoked respectively.
72  */
73 public class JMenuItem extends AbstractButton implements Accessible,
74                                                          MenuElement
75 {
76   private static final long serialVersionUID = -1681004643499461044L;
77
78   /** Combination of keyboard keys that can be used to activate this menu item */
79   private KeyStroke accelerator;
80
81   /**
82    * Creates a new JMenuItem object.
83    */
84   public JMenuItem()
85   {
86     super(null, null);
87   }
88
89   /**
90    * Creates a new JMenuItem with the given icon.
91    *
92    * @param icon Icon that will be displayed on the menu item
93    */
94   public JMenuItem(Icon icon)
95   {
96     // FIXME: The requestedFocusEnabled property should
97     // be set to false, when only icon is set for menu item.
98     super(null, icon);
99   }
100
101   /**
102    * Creates a new JMenuItem with the given label.
103    *
104    * @param text label for the menu item
105    */
106   public JMenuItem(String text)
107   {
108     super(text, null);
109   }
110
111   /**
112    * Creates a new JMenuItem associated with the specified action.
113    *
114    * @param action action for this menu item
115    */
116   public JMenuItem(Action action)
117   {
118     super(null, null);
119     super.setAction(action);
120   }
121
122   /**
123    * Creates a new JMenuItem with specified text and icon.
124    * Text is displayed to the left of icon by default.
125    *
126    * @param text label for this menu item
127    * @param icon icon that will be displayed on this menu item
128    */
129   public JMenuItem(String text, Icon icon)
130   {
131     super(text, icon);
132   }
133
134   /**
135    * Creates a new JMenuItem object.
136    *
137    * @param text label for this menu item
138    * @param mnemonic - Single key that can be used with a
139    * look-and-feel meta key to activate this menu item. However
140    * menu item should be visible on the screen when mnemonic is used.
141    */
142   public JMenuItem(String text, int mnemonic)
143   {
144     super(text, null);
145     setMnemonic(mnemonic);
146   }
147
148   private void readObject(ObjectInputStream stream)
149                    throws IOException, ClassNotFoundException
150   {
151   }
152
153   private void writeObject(ObjectOutputStream stream) throws IOException
154   {
155   }
156
157   /**
158    * Initializes this menu item
159    *
160    * @param text label for this menu item
161    * @param icon icon to be displayed for this menu item
162    */
163   protected void init(String text, Icon icon)
164   {
165     super.init(text, icon);
166
167     // Initializes properties for this menu item, that are different
168     // from Abstract button properties. 
169     /* NOTE: According to java specifications paint_border should be set to false,
170       since menu item should not have a border. However running few java programs
171       it seems that menu items and menues can have a border. Commenting
172       out statement below for now. */
173     //borderPainted = false;
174     focusPainted = false;
175     horizontalAlignment = JButton.LEFT;
176     horizontalTextPosition = JButton.LEFT;
177   }
178
179   /**
180    * Set the "UI" property of the menu item, which is a look and feel class
181    * responsible for handling menuItem's input events and painting it.
182    *
183    * @param ui The new "UI" property
184    */
185   public void setUI(MenuItemUI ui)
186   {
187     super.setUI(ui);
188   }
189
190   /**
191    * This method sets this menuItem's UI to the UIManager's default for the
192    * current look and feel.
193    */
194   public void updateUI()
195   {
196     MenuItemUI mi = ((MenuItemUI) UIManager.getUI(this));
197     setUI(mi);
198     invalidate();
199   }
200
201   /**
202    * This method returns a name to identify which look and feel class will be
203    * the UI delegate for the menuItem.
204    *
205    * @return The Look and Feel classID. "MenuItemUI"
206    */
207   public String getUIClassID()
208   {
209     return "MenuItemUI";
210   }
211
212   /**
213    * Returns true if button's model is armed and false otherwise. The
214    * button model is armed if menu item has focus or it is selected.
215    *
216    * @return $boolean$ true if button's model is armed and false otherwise
217    */
218   public boolean isArmed()
219   {
220     return getModel().isArmed();
221   }
222
223   /**
224    * Sets menuItem's "ARMED" property
225    *
226    * @param armed DOCUMENT ME!
227    */
228   public void setArmed(boolean armed)
229   {
230     getModel().setArmed(armed);
231   }
232
233   /**
234    * Enable or disable menu item. When menu item is disabled,
235    * its text and icon are grayed out if they exist.
236    *
237    * @param enabled if true enable menu item, and disable otherwise.
238    */
239   public void setEnabled(boolean enabled)
240   {
241     super.setEnabled(enabled);
242   }
243
244   /**
245    * Return accelerator for this menu item.
246    *
247    * @return $KeyStroke$ accelerator for this menu item.
248    */
249   public KeyStroke getAccelerator()
250   {
251     return accelerator;
252   }
253
254   /**
255    * Sets accelerator for this menu item.
256    *
257    * @param keystroke accelerator for this menu item.
258    */
259   public void setAccelerator(KeyStroke keystroke)
260   {
261     this.accelerator = keystroke;
262   }
263
264   /**
265    * Configures menu items' properties from properties of the specified action.
266    * This method overrides configurePropertiesFromAction from AbstractButton
267    * to also set accelerator property.
268    *
269    * @param action action to configure properties from
270    */
271   protected void configurePropertiesFromAction(Action action)
272   {
273     super.configurePropertiesFromAction(action);
274
275     if (! (this instanceof JMenu) && action != null)
276       setAccelerator((KeyStroke) (action.getValue(Action.ACCELERATOR_KEY)));
277   }
278
279   /**
280    * Creates PropertyChangeListener to listen for the changes in action
281    * properties.
282    *
283    * @param action action to listen to for property changes
284    *
285    * @return $PropertyChangeListener$ Listener that listens to changes in
286    * action properties.
287    */
288   protected PropertyChangeListener createActionPropertyChangeListener(Action action)
289   {
290     return new PropertyChangeListener()
291       {
292         public void propertyChange(PropertyChangeEvent e)
293         {
294           Action act = (Action) (e.getSource());
295           configurePropertiesFromAction(act);
296         }
297       };
298   }
299
300   /**
301    * Process mouse events forwarded from MenuSelectionManager.
302    *
303    * @param event event forwarded from MenuSelectionManager
304    * @param path path to the menu element from which event was generated
305    * @param manager MenuSelectionManager for the current menu hierarchy
306    */
307   public void processMouseEvent(MouseEvent event, MenuElement[] path,
308                                 MenuSelectionManager manager)
309   {
310     // Fire MenuDragMouseEvents if mouse is being dragged.
311     boolean dragged
312       = (event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0;
313     if (dragged)
314       processMenuDragMouseEvent(createMenuDragMouseEvent(event, path, manager));
315
316     switch (event.getID())
317       {
318       case MouseEvent.MOUSE_CLICKED:
319         break;
320       case MouseEvent.MOUSE_ENTERED:
321         if (isRolloverEnabled())
322           model.setRollover(true);
323         break;
324       case MouseEvent.MOUSE_EXITED:
325         if (isRolloverEnabled())
326           model.setRollover(false);
327
328         // for JMenu last element on the path is its popupMenu.
329         // JMenu shouldn't me disarmed. 
330         if (! (path[path.length - 1] instanceof JPopupMenu) && ! dragged)
331           setArmed(false);
332         break;
333       case MouseEvent.MOUSE_PRESSED:
334         if ((event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0)
335           {
336             model.setArmed(true);
337             model.setPressed(true);
338           }
339         break;
340       case MouseEvent.MOUSE_RELEASED:
341         break;
342       case MouseEvent.MOUSE_MOVED:
343         break;
344       case MouseEvent.MOUSE_DRAGGED:
345         break;
346       }
347   }
348
349   /**
350    * Creates MenuDragMouseEvent.
351    *
352    * @param event MouseEvent that occured while mouse was pressed.
353    * @param path Path the the menu element where the dragging event was
354    *        originated
355    * @param manager MenuSelectionManager for the current menu hierarchy.
356    *
357    * @return new MenuDragMouseEvent
358    */
359   private MenuDragMouseEvent createMenuDragMouseEvent(MouseEvent event,
360                                                       MenuElement[] path,
361                                                       MenuSelectionManager manager)
362   {
363     return new MenuDragMouseEvent((Component) event.getSource(),
364                                   event.getID(), event.getWhen(),
365                                   event.getModifiers(), event.getX(),
366                                   event.getY(), event.getClickCount(),
367                                   event.isPopupTrigger(), path, manager);
368   }
369
370   /**
371    * Process key events forwarded from MenuSelectionManager.
372    *
373    * @param event event forwarded from MenuSelectionManager
374    * @param path path to the menu element from which event was generated
375    * @param manager MenuSelectionManager for the current menu hierarchy
376    */
377   public void processKeyEvent(KeyEvent event, MenuElement[] path,
378                               MenuSelectionManager manager)
379   {
380     // Need to implement.
381   }
382
383   /**
384    * This method fires MenuDragMouseEvents to registered listeners.
385    * Different types of MenuDragMouseEvents are fired depending
386    * on the observed mouse event.
387    *
388    * @param event Mouse
389    */
390   public void processMenuDragMouseEvent(MenuDragMouseEvent event)
391   {
392     switch (event.getID())
393       {
394       case MouseEvent.MOUSE_ENTERED:
395         fireMenuDragMouseEntered(event);
396         break;
397       case MouseEvent.MOUSE_EXITED:
398         fireMenuDragMouseExited(event);
399         break;
400       case MouseEvent.MOUSE_DRAGGED:
401         fireMenuDragMouseDragged(event);
402         break;
403       case MouseEvent.MOUSE_RELEASED:
404         fireMenuDragMouseReleased(event);
405         break;
406       }
407   }
408
409   /**
410    * This method fires MenuKeyEvent to registered listeners.
411    * Different types of MenuKeyEvents are fired depending
412    * on the observed key event.
413    *
414    * @param event DOCUMENT ME!
415    */
416   public void processMenuKeyEvent(MenuKeyEvent event)
417   {
418     // Need to implement.
419   }
420
421   /**
422    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
423    *
424    * @param event The event signifying that mouse entered menuItem while it was dragged
425    */
426   protected void fireMenuDragMouseEntered(MenuDragMouseEvent event)
427   {
428     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
429
430     for (int i = 0; i < ll.length; i++)
431       ((MenuDragMouseListener) ll[i]).menuDragMouseEntered(event);
432   }
433
434   /**
435    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
436    *
437    * @param event The event signifying that mouse has exited menu item, while it was dragged
438    */
439   protected void fireMenuDragMouseExited(MenuDragMouseEvent event)
440   {
441     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
442
443     for (int i = 0; i < ll.length; i++)
444       ((MenuDragMouseListener) ll[i]).menuDragMouseExited(event);
445   }
446
447   /**
448    * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners.
449    *
450    * @param event The event signifying that mouse is being dragged over the menuItem
451    */
452   protected void fireMenuDragMouseDragged(MenuDragMouseEvent event)
453   {
454     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
455
456     for (int i = 0; i < ll.length; i++)
457       ((MenuDragMouseListener) ll[i]).menuDragMouseDragged(event);
458   }
459
460   /**
461    * This method fires a MenuDragMouseEvent to all the MenuItem's MouseInputListeners.
462    *
463    * @param event The event signifying that mouse was released while it was dragged over the menuItem
464    */
465   protected void fireMenuDragMouseReleased(MenuDragMouseEvent event)
466   {
467     EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class);
468
469     for (int i = 0; i < ll.length; i++)
470       ((MenuDragMouseListener) ll[i]).menuDragMouseReleased(event);
471   }
472
473   /**
474    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
475    *
476    * @param event The event signifying that key associated with this menu was pressed
477    */
478   protected void fireMenuKeyPressed(MenuKeyEvent event)
479   {
480     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
481
482     for (int i = 0; i < ll.length; i++)
483       ((MenuKeyListener) ll[i]).menuKeyPressed(event);
484   }
485
486   /**
487    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
488    *
489    * @param event The event signifying that key associated with this menu was released
490    */
491   protected void fireMenuKeyReleased(MenuKeyEvent event)
492   {
493     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
494
495     for (int i = 0; i < ll.length; i++)
496       ((MenuKeyListener) ll[i]).menuKeyTyped(event);
497   }
498
499   /**
500    * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners.
501    *
502    * @param event The event signifying that key associated with this menu was typed.
503    *        The key is typed when it was pressed and then released
504    */
505   protected void fireMenuKeyTyped(MenuKeyEvent event)
506   {
507     EventListener[] ll = listenerList.getListeners(MenuKeyListener.class);
508
509     for (int i = 0; i < ll.length; i++)
510       ((MenuKeyListener) ll[i]).menuKeyTyped(event);
511   }
512
513   /**
514    * Method of the MenuElement interface.
515    * This method is invoked by MenuSelectionManager when selection of
516    * this menu item has changed. If this menu item was selected then
517    * arm it's model, and disarm the model otherwise. The menu item
518    * is considered to be selected, and thus highlighted when its model
519    * is armed.
520    *
521    * @param changed indicates selection status of this menu item. If changed is
522    * true then menu item is selected and deselected otherwise.
523    */
524   public void menuSelectionChanged(boolean changed)
525   {
526     Component parent = this.getParent();
527     if (changed)
528       {
529         model.setArmed(true);
530
531         if (parent != null && parent instanceof JPopupMenu)
532           ((JPopupMenu) parent).setSelected(this);
533       }
534     else
535       {
536         model.setArmed(false);
537
538         if (parent != null && parent instanceof JPopupMenu)
539           ((JPopupMenu) parent).getSelectionModel().clearSelection();
540       }
541   }
542
543   /**
544    * Method of the MenuElement interface.
545    *
546    * @return $MenuElement[]$ Returns array of sub-components for this menu
547    *         item. By default menuItem doesn't have any subcomponents and so
548    *         empty array is returned instead.
549    */
550   public MenuElement[] getSubElements()
551   {
552     return new MenuElement[0];
553   }
554
555   /**
556    * Returns reference to the component that will paint this menu item.
557    *
558    * @return $Component$ Component that will paint this menu item.
559    *         Simply returns reference to this menu item.
560    */
561   public Component getComponent()
562   {
563     return this;
564   }
565
566   /**
567    * Adds a MenuDragMouseListener to this menu item. When mouse
568    * is dragged over the menu item the MenuDragMouseEvents will be
569    * fired, and these listeners will be called.
570    *
571    * @param listener The new listener to add
572    */
573   public void addMenuDragMouseListener(MenuDragMouseListener listener)
574   {
575     listenerList.add(MenuDragMouseListener.class, listener);
576   }
577
578   /**
579    * Removes a MenuDragMouseListener from the menuItem's listener list.
580    *
581    * @param listener The listener to remove
582    */
583   public void removeMenuDragMouseListener(MenuDragMouseListener listener)
584   {
585     listenerList.remove(MenuDragMouseListener.class, listener);
586   }
587
588   /**
589    * Returns all added MenuDragMouseListener objects.
590    *
591    * @return an array of listeners
592    *
593    * @since 1.4
594    */
595   public MenuDragMouseListener[] getMenuDragMouseListeners()
596   {
597     return (MenuDragMouseListener[]) listenerList.getListeners(MenuDragMouseListener.class);
598   }
599
600   /**
601    * Adds an MenuKeyListener to this menu item.  This listener will be
602    * invoked when MenuKeyEvents will be fired by this menu item.
603    *
604    * @param listener The new listener to add
605    */
606   public void addMenuKeyListener(MenuKeyListener listener)
607   {
608     listenerList.add(MenuKeyListener.class, listener);
609   }
610
611   /**
612    * Removes an MenuKeyListener from the menuItem's listener list.
613    *
614    * @param listener The listener to remove
615    */
616   public void removeMenuKeyListener(MenuKeyListener listener)
617   {
618     listenerList.remove(MenuKeyListener.class, listener);
619   }
620
621   /**
622    * Returns all added MenuKeyListener objects.
623    *
624    * @return an array of listeners
625    *
626    * @since 1.4
627    */
628   public MenuKeyListener[] getMenuKeyListeners()
629   {
630     return (MenuKeyListener[]) listenerList.getListeners(MenuKeyListener.class);
631   }
632
633   /**
634    * A string that describes this JMenuItem. Normally only used
635    * for debugging.
636    *
637    * @return A string describing this JMenuItem
638    */
639   protected String paramString()
640   {
641     return super.paramString();
642   }
643
644   public AccessibleContext getAccessibleContext()
645   {
646     if (accessibleContext == null)
647       accessibleContext = new AccessibleJMenuItem();
648
649     return accessibleContext;
650   }
651
652   protected class AccessibleJMenuItem extends AccessibleAbstractButton
653     implements ChangeListener
654   {
655     private static final long serialVersionUID = 6748924232082076534L;
656
657     /**
658      * Creates a new AccessibleJMenuItem object.
659      */
660     AccessibleJMenuItem()
661     {
662       //super(component);
663     }
664
665     public void stateChanged(ChangeEvent event)
666     {
667     }
668
669     public AccessibleRole getAccessibleRole()
670     {
671       return AccessibleRole.MENU_ITEM;
672     }
673   }
674 }