KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > JMenuItem


1 /*
2  * @(#)JMenuItem.java 1.118 04/03/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing;
8
9 import java.util.EventListener JavaDoc;
10 import java.awt.*;
11 import java.awt.event.*;
12 import java.awt.image.*;
13
14 import java.beans.PropertyChangeEvent JavaDoc;
15 import java.beans.PropertyChangeListener JavaDoc;
16
17 import java.io.Serializable JavaDoc;
18 import java.io.ObjectOutputStream JavaDoc;
19 import java.io.ObjectInputStream JavaDoc;
20 import java.io.IOException JavaDoc;
21
22 import javax.swing.plaf.*;
23 import javax.swing.plaf.basic.*;
24 import javax.swing.event.*;
25 import javax.accessibility.*;
26
27 /**
28  * An implementation of an item in a menu. A menu item is essentially a button
29  * sitting in a list. When the user selects the "button", the action
30  * associated with the menu item is performed. A <code>JMenuItem</code>
31  * contained in a <code>JPopupMenu</code> performs exactly that function.
32  * <p>
33  * For further documentation and for examples, see
34  * <a
35  href="http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html">How to Use Menus</a>
36  * in <em>The Java Tutorial.</em>
37  * <p>
38  * <strong>Warning:</strong>
39  * Serialized objects of this class will not be compatible with
40  * future Swing releases. The current serialization support is
41  * appropriate for short term storage or RMI between applications running
42  * the same version of Swing. As of 1.4, support for long term storage
43  * of all JavaBeans<sup><font size="-2">TM</font></sup>
44  * has been added to the <code>java.beans</code> package.
45  * Please see {@link java.beans.XMLEncoder}.
46  *
47  * @beaninfo
48  * attribute: isContainer false
49  * description: An item which can be selected in a menu.
50  *
51  * @version 1.118 03/05/04
52  * @author Georges Saab
53  * @author David Karlton
54  * @see JPopupMenu
55  * @see JMenu
56  * @see JCheckBoxMenuItem
57  * @see JRadioButtonMenuItem
58  */

59 public class JMenuItem extends AbstractButton JavaDoc implements Accessible,MenuElement JavaDoc {
60
61     /**
62      * @see #getUIClassID
63      * @see #readObject
64      */

65     private static final String JavaDoc uiClassID = "MenuItemUI";
66
67     /* diagnostic aids -- should be false for production builds. */
68     private static final boolean TRACE = false; // trace creates and disposes
69
private static final boolean VERBOSE = false; // show reuse hits/misses
70
private static final boolean DEBUG = false; // show bad params, misc.
71

72     private boolean isMouseDragged = false;
73
74     /**
75      * Creates a <code>JMenuItem</code> with no set text or icon.
76      */

77     public JMenuItem() {
78         this(null, (Icon JavaDoc)null);
79     }
80
81     /**
82      * Creates a <code>JMenuItem</code> with the specified icon.
83      *
84      * @param icon the icon of the <code>JMenuItem</code>
85      */

86     public JMenuItem(Icon JavaDoc icon) {
87         this(null, icon);
88     }
89
90     /**
91      * Creates a <code>JMenuItem</code> with the specified text.
92      *
93      * @param text the text of the <code>JMenuItem</code>
94      */

95     public JMenuItem(String JavaDoc text) {
96         this(text, (Icon JavaDoc)null);
97     }
98     
99     /**
100      * Creates a menu item whose properties are taken from the
101      * specified <code>Action</code>.
102      *
103      * @param a the action of the <code>JMenuItem</code>
104      * @since 1.3
105      */

106     public JMenuItem(Action JavaDoc a) {
107         this();
108     setAction(a);
109     }
110
111     /**
112      * Creates a <code>JMenuItem</code> with the specified text and icon.
113      *
114      * @param text the text of the <code>JMenuItem</code>
115      * @param icon the icon of the <code>JMenuItem</code>
116      */

117     public JMenuItem(String JavaDoc text, Icon JavaDoc icon) {
118         setModel(new DefaultButtonModel JavaDoc());
119         init(text, icon);
120         initFocusability();
121     }
122
123     /**
124      * Creates a <code>JMenuItem</code> with the specified text and
125      * keyboard mnemonic.
126      *
127      * @param text the text of the <code>JMenuItem</code>
128      * @param mnemonic the keyboard mnemonic for the <code>JMenuItem</code>
129      */

130     public JMenuItem(String JavaDoc text, int mnemonic) {
131         setModel(new DefaultButtonModel JavaDoc());
132         init(text, null);
133         setMnemonic(mnemonic);
134         initFocusability();
135     }
136
137     /**
138      * Inititalizes the focusability of the the <code>JMenuItem</code>.
139      * <code>JMenuItem</code>'s are focusable, but subclasses may
140      * want to be, this provides them the opportunity to override this
141      * and invoke something else, or nothing at all. Refer to
142      * {@link javax.swing.JMenu#initFocusability} for the motivation of
143      * this.
144      */

145     void initFocusability() {
146     setFocusable(false);
147     }
148
149     /**
150      * Initializes the menu item with the specified text and icon.
151      *
152      * @param text the text of the <code>JMenuItem</code>
153      * @param icon the icon of the <code>JMenuItem</code>
154      */

155     protected void init(String JavaDoc text, Icon JavaDoc icon) {
156         if(text != null) {
157             setText(text);
158         }
159         
160         if(icon != null) {
161             setIcon(icon);
162         }
163         
164         // Listen for Focus events
165
addFocusListener(new MenuItemFocusListener());
166         setUIProperty("borderPainted", Boolean.FALSE);
167         setFocusPainted(false);
168         setHorizontalTextPosition(JButton.TRAILING);
169         setHorizontalAlignment(JButton.LEADING);
170     updateUI();
171     }
172
173     private static class MenuItemFocusListener implements FocusListener,
174         Serializable JavaDoc {
175         public void focusGained(FocusEvent event) {}
176         public void focusLost(FocusEvent event) {
177             // When focus is lost, repaint if
178
// the focus information is painted
179
JMenuItem JavaDoc mi = (JMenuItem JavaDoc)event.getSource();
180             if(mi.isFocusPainted()) {
181                 mi.repaint();
182             }
183         }
184     }
185         
186     
187     /**
188      * Sets the look and feel object that renders this component.
189      *
190      * @param ui the <code>JMenuItemUI</code> L&F object
191      * @see UIDefaults#getUI
192      * @beaninfo
193      * bound: true
194      * hidden: true
195      * attribute: visualUpdate true
196      * description: The UI object that implements the Component's LookAndFeel.
197      */

198     public void setUI(MenuItemUI ui) {
199         super.setUI(ui);
200     }
201     
202     /**
203      * Resets the UI property with a value from the current look and feel.
204      *
205      * @see JComponent#updateUI
206      */

207     public void updateUI() {
208         setUI((MenuItemUI)UIManager.getUI(this));
209     }
210
211
212     /**
213      * Returns the suffix used to construct the name of the L&F class used to
214      * render this component.
215      *
216      * @return the string "MenuItemUI"
217      * @see JComponent#getUIClassID
218      * @see UIDefaults#getUI
219      */

220     public String JavaDoc getUIClassID() {
221         return uiClassID;
222     }
223
224
225     /**
226      * Identifies the menu item as "armed". If the mouse button is
227      * released while it is over this item, the menu's action event
228      * will fire. If the mouse button is released elsewhere, the
229      * event will not fire and the menu item will be disarmed.
230      *
231      * @param b true to arm the menu item so it can be selected
232      * @beaninfo
233      * description: Mouse release will fire an action event
234      * hidden: true
235      */

236     public void setArmed(boolean b) {
237         ButtonModel JavaDoc model = (ButtonModel JavaDoc) getModel();
238
239         boolean oldValue = model.isArmed();
240         if(model.isArmed() != b) {
241             model.setArmed(b);
242         }
243     }
244
245     /**
246      * Returns whether the menu item is "armed".
247      *
248      * @return true if the menu item is armed, and it can be selected
249      * @see #setArmed
250      */

251     public boolean isArmed() {
252         ButtonModel JavaDoc model = (ButtonModel JavaDoc) getModel();
253         return model.isArmed();
254     }
255
256     /**
257      * Enables or disables the menu item.
258      *
259      * @param b true to enable the item
260      * @beaninfo
261      * description: Does the component react to user interaction
262      * bound: true
263      * preferred: true
264      */

265     public void setEnabled(boolean b) {
266         // Make sure we aren't armed!
267
if (b == false)
268             setArmed(false);
269         super.setEnabled(b);
270     }
271
272
273     /**
274      * Returns true since <code>Menu</code>s, by definition,
275      * should always be on top of all other windows. If the menu is
276      * in an internal frame false is returned due to the rollover effect
277      * for windows laf where the menu is not always on top.
278      */

279     // package private
280
boolean alwaysOnTop() {
281         // Fix for bug #4482165
282
if (SwingUtilities.getAncestorOfClass(JInternalFrame JavaDoc.class, this) !=
283                 null) {
284             return false;
285         }
286     return true;
287     }
288
289
290     /* The keystroke which acts as the menu item's accelerator
291      */

292     private KeyStroke JavaDoc accelerator;
293
294     /**
295      * Sets the key combination which invokes the menu item's
296      * action listeners without navigating the menu hierarchy. It is the
297      * UI's responsibility to install the correct action. Note that
298      * when the keyboard accelerator is typed, it will work whether or
299      * not the menu is currently displayed.
300      *
301      * @param keyStroke the <code>KeyStroke</code> which will
302      * serve as an accelerator
303      * @beaninfo
304      * description: The keystroke combination which will invoke the
305      * JMenuItem's actionlisteners without navigating the
306      * menu hierarchy
307      * bound: true
308      * preferred: true
309      */

310     public void setAccelerator(KeyStroke JavaDoc keyStroke) {
311     KeyStroke JavaDoc oldAccelerator = accelerator;
312         this.accelerator = keyStroke;
313     firePropertyChange("accelerator", oldAccelerator, accelerator);
314     }
315
316     /**
317      * Returns the <code>KeyStroke</code> which serves as an accelerator
318      * for the menu item.
319      * @return a <code>KeyStroke</code> object identifying the
320      * accelerator key
321      */

322     public KeyStroke JavaDoc getAccelerator() {
323         return this.accelerator;
324     }
325
326     /**
327      * Factory method which sets the <code>ActionEvent</code> source's
328      * properties according to values from the <code>Action</code> instance.
329      * The properties which are set may differ for subclasses.
330      * By default, this method sets the same properties as
331      * <code>AbstractButton.configurePropertiesFromAction()</code>, plus
332      * <code>Accelerator</code>.
333      *
334      * @param a the <code>Action</code> from which to get the properties,
335      * or <code>null</code>
336      * @since 1.3
337      * @see Action
338      */

339     protected void configurePropertiesFromAction(Action JavaDoc a) {
340         super.configurePropertiesFromAction(a);
341         KeyStroke JavaDoc ks = (a==null) ? null :
342             (KeyStroke JavaDoc)a.getValue(Action.ACCELERATOR_KEY);
343         setAccelerator(ks==null ? null : ks);
344     }
345
346     /**
347      * Factory method which creates the <code>PropertyChangeListener</code>
348      * used to update the <code>ActionEvent</code> source as properties
349      * change on its <code>Action</code> instance.
350      * Subclasses may override this in order to provide their own
351      * <code>PropertyChangeListener</code> if the set of
352      * properties which should be kept up to date differs.
353      * <p>
354      * Note that <code>PropertyChangeListeners</code> should avoid holding
355      * strong references to the <code>ActionEvent</code> source,
356      * as this may hinder garbage collection of the <code>ActionEvent</code>
357      * source and all components in its containment hierarchy.
358      *
359      * @param a the <code>Action</code> from which to get the properties,
360      * or <code>null</code>
361      *
362      * @since 1.3
363      * @see Action
364      */

365     protected PropertyChangeListener JavaDoc createActionPropertyChangeListener(Action JavaDoc a) {
366         return new MenuItemPropertyChangeListener(this, a);
367     }
368
369     private static class MenuItemPropertyChangeListener
370                 extends AbstractActionPropertyChangeListener JavaDoc
371                 implements Serializable JavaDoc {
372
373         MenuItemPropertyChangeListener(JMenuItem JavaDoc m, Action JavaDoc a) {
374             super(m, a);
375         }
376
377         public void propertyChange(PropertyChangeEvent JavaDoc e) {
378             String JavaDoc propertyName = e.getPropertyName();
379             JMenuItem JavaDoc mi = (JMenuItem JavaDoc)getTarget();
380             if (mi == null) { //WeakRef GC'ed in 1.2
381
Action JavaDoc action = (Action JavaDoc)e.getSource();
382                 action.removePropertyChangeListener(this);
383             } else {
384                 if (e.getPropertyName().equals(Action.NAME)) {
385                     String JavaDoc text = (String JavaDoc) e.getNewValue();
386                     mi.setText(text);
387                     mi.repaint();
388                 } else if (propertyName.equals("enabled")) {
389                     Boolean JavaDoc enabledState = (Boolean JavaDoc) e.getNewValue();
390                     mi.setEnabled(enabledState.booleanValue());
391                     mi.repaint();
392                 } else if (e.getPropertyName().equals(Action.SMALL_ICON)) {
393                     Icon JavaDoc icon = (Icon JavaDoc) e.getNewValue();
394                     mi.setIcon(icon);
395                     mi.invalidate();
396                     mi.repaint();
397                 } else
398                     if (e.getPropertyName().equals(Action.MNEMONIC_KEY)) {
399                     Integer JavaDoc mn = (Integer JavaDoc) e.getNewValue();
400                     mi.setMnemonic(mn.intValue());
401                     mi.invalidate();
402                     mi.repaint();
403                 }
404             }
405         }
406     }
407
408     /**
409      * Processes a mouse event forwarded from the
410      * <code>MenuSelectionManager</code> and changes the menu
411      * selection, if necessary, by using the
412      * <code>MenuSelectionManager</code>'s API.
413      * <p>
414      * Note: you do not have to forward the event to sub-components.
415      * This is done automatically by the <code>MenuSelectionManager</code>.
416      *
417      * @param e a <code>MouseEvent</code>
418      * @param path the <code>MenuElement</code> path array
419      * @param manager the <code>MenuSelectionManager</code>
420      */

421     public void processMouseEvent(MouseEvent e,MenuElement JavaDoc path[],MenuSelectionManager JavaDoc manager) {
422     processMenuDragMouseEvent(
423          new MenuDragMouseEvent(e.getComponent(), e.getID(),
424                     e.getWhen(),
425                     e.getModifiers(), e.getX(), e.getY(),
426                     e.getClickCount(), e.isPopupTrigger(),
427                     path, manager));
428     }
429
430
431     /**
432      * Processes a key event forwarded from the
433      * <code>MenuSelectionManager</code> and changes the menu selection,
434      * if necessary, by using <code>MenuSelectionManager</code>'s API.
435      * <p>
436      * Note: you do not have to forward the event to sub-components.
437      * This is done automatically by the <code>MenuSelectionManager</code>.
438      *
439      * @param e a <code>KeyEvent</code>
440      * @param path the <code>MenuElement</code> path array
441      * @param manager the <code>MenuSelectionManager</code>
442      */

443     public void processKeyEvent(KeyEvent e,MenuElement JavaDoc path[],MenuSelectionManager JavaDoc manager) {
444     if (DEBUG) {
445         System.out.println("in JMenuItem.processKeyEvent/3 for " + getText() +
446                    " " + KeyStroke.getKeyStrokeForEvent(e));
447     }
448         MenuKeyEvent mke = new MenuKeyEvent(e.getComponent(), e.getID(),
449                          e.getWhen(), e.getModifiers(),
450                          e.getKeyCode(), e.getKeyChar(),
451                          path, manager);
452         processMenuKeyEvent(mke);
453     
454         if (mke.isConsumed()) {
455             e.consume();
456         }
457     }
458
459
460
461     /**
462      * Handles mouse drag in a menu.
463      *
464      * @param e a <code>MenuDragMouseEvent</code> object
465      */

466     public void processMenuDragMouseEvent(MenuDragMouseEvent e) {
467     switch (e.getID()) {
468     case MouseEvent.MOUSE_ENTERED:
469         isMouseDragged = false; fireMenuDragMouseEntered(e); break;
470     case MouseEvent.MOUSE_EXITED:
471         isMouseDragged = false; fireMenuDragMouseExited(e); break;
472     case MouseEvent.MOUSE_DRAGGED:
473         isMouseDragged = true; fireMenuDragMouseDragged(e); break;
474     case MouseEvent.MOUSE_RELEASED:
475         if(isMouseDragged) fireMenuDragMouseReleased(e); break;
476     default:
477         break;
478     }
479     }
480
481     /**
482      * Handles a keystroke in a menu.
483      *
484      * @param e a <code>MenuKeyEvent</code> object
485      */

486     public void processMenuKeyEvent(MenuKeyEvent e) {
487     if (DEBUG) {
488         System.out.println("in JMenuItem.processMenuKeyEvent for " + getText()+
489                    " " + KeyStroke.getKeyStrokeForEvent(e));
490     }
491     switch (e.getID()) {
492     case KeyEvent.KEY_PRESSED:
493         fireMenuKeyPressed(e); break;
494     case KeyEvent.KEY_RELEASED:
495         fireMenuKeyReleased(e); break;
496     case KeyEvent.KEY_TYPED:
497         fireMenuKeyTyped(e); break;
498     default:
499         break;
500     }
501     }
502
503     /**
504      * Notifies all listeners that have registered interest for
505      * notification on this event type.
506      *
507      * @param event a <code>MenuMouseDragEvent</code>
508      * @see EventListenerList
509      */

510     protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) {
511         // Guaranteed to return a non-null array
512
Object JavaDoc[] listeners = listenerList.getListenerList();
513         // Process the listeners last to first, notifying
514
// those that are interested in this event
515
for (int i = listeners.length-2; i>=0; i-=2) {
516             if (listeners[i]==MenuDragMouseListener.class) {
517                 // Lazily create the event:
518
((MenuDragMouseListener)listeners[i+1]).menuDragMouseEntered(event);
519             }
520         }
521     }
522
523     /**
524      * Notifies all listeners that have registered interest for
525      * notification on this event type.
526      *
527      * @param event a <code>MenuDragMouseEvent</code>
528      * @see EventListenerList
529      */

530     protected void fireMenuDragMouseExited(MenuDragMouseEvent event) {
531         // Guaranteed to return a non-null array
532
Object JavaDoc[] listeners = listenerList.getListenerList();
533         // Process the listeners last to first, notifying
534
// those that are interested in this event
535
for (int i = listeners.length-2; i>=0; i-=2) {
536             if (listeners[i]==MenuDragMouseListener.class) {
537                 // Lazily create the event:
538
((MenuDragMouseListener)listeners[i+1]).menuDragMouseExited(event);
539             }
540         }
541     }
542
543     /**
544      * Notifies all listeners that have registered interest for
545      * notification on this event type.
546      *
547      * @param event a <code>MenuDragMouseEvent</code>
548      * @see EventListenerList
549      */

550     protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) {
551         // Guaranteed to return a non-null array
552
Object JavaDoc[] listeners = listenerList.getListenerList();
553         // Process the listeners last to first, notifying
554
// those that are interested in this event
555
for (int i = listeners.length-2; i>=0; i-=2) {
556             if (listeners[i]==MenuDragMouseListener.class) {
557                 // Lazily create the event:
558
((MenuDragMouseListener)listeners[i+1]).menuDragMouseDragged(event);
559             }
560         }
561     }
562
563     /**
564      * Notifies all listeners that have registered interest for
565      * notification on this event type.
566      *
567      * @param event a <code>MenuDragMouseEvent</code>
568      * @see EventListenerList
569      */

570     protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) {
571         // Guaranteed to return a non-null array
572
Object JavaDoc[] listeners = listenerList.getListenerList();
573         // Process the listeners last to first, notifying
574
// those that are interested in this event
575
for (int i = listeners.length-2; i>=0; i-=2) {
576             if (listeners[i]==MenuDragMouseListener.class) {
577                 // Lazily create the event:
578
((MenuDragMouseListener)listeners[i+1]).menuDragMouseReleased(event);
579             }
580         }
581     }
582
583     /**
584      * Notifies all listeners that have registered interest for
585      * notification on this event type.
586      *
587      * @param event a <code>MenuKeyEvent</code>
588      * @see EventListenerList
589      */

590     protected void fireMenuKeyPressed(MenuKeyEvent event) {
591     if (DEBUG) {
592         System.out.println("in JMenuItem.fireMenuKeyPressed for " + getText()+
593                    " " + KeyStroke.getKeyStrokeForEvent(event));
594     }
595         // Guaranteed to return a non-null array
596
Object JavaDoc[] listeners = listenerList.getListenerList();
597         // Process the listeners last to first, notifying
598
// those that are interested in this event
599
for (int i = listeners.length-2; i>=0; i-=2) {
600             if (listeners[i]==MenuKeyListener.class) {
601                 // Lazily create the event:
602
((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
603             }
604         }
605     }
606
607     /**
608      * Notifies all listeners that have registered interest for
609      * notification on this event type.
610      *
611      * @param event a <code>MenuKeyEvent</code>
612      * @see EventListenerList
613      */

614     protected void fireMenuKeyReleased(MenuKeyEvent event) {
615     if (DEBUG) {
616         System.out.println("in JMenuItem.fireMenuKeyReleased for " + getText()+
617                    " " + KeyStroke.getKeyStrokeForEvent(event));
618     }
619         // Guaranteed to return a non-null array
620
Object JavaDoc[] listeners = listenerList.getListenerList();
621         // Process the listeners last to first, notifying
622
// those that are interested in this event
623
for (int i = listeners.length-2; i>=0; i-=2) {
624             if (listeners[i]==MenuKeyListener.class) {
625                 // Lazily create the event:
626
((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
627             }
628         }
629     }
630
631     /**
632      * Notifies all listeners that have registered interest for
633      * notification on this event type.
634      *
635      * @param event a <code>MenuKeyEvent</code>
636      * @see EventListenerList
637      */

638     protected void fireMenuKeyTyped(MenuKeyEvent event) {
639     if (DEBUG) {
640         System.out.println("in JMenuItem.fireMenuKeyTyped for " + getText()+
641                    " " + KeyStroke.getKeyStrokeForEvent(event));
642     }
643         // Guaranteed to return a non-null array
644
Object JavaDoc[] listeners = listenerList.getListenerList();
645         // Process the listeners last to first, notifying
646
// those that are interested in this event
647
for (int i = listeners.length-2; i>=0; i-=2) {
648             if (listeners[i]==MenuKeyListener.class) {
649                 // Lazily create the event:
650
((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
651             }
652         }
653     }
654
655     /**
656      * Called by the <code>MenuSelectionManager</code> when the
657      * <code>MenuElement</code> is selected or unselected.
658      *
659      * @param isIncluded true if this menu item is on the part of the menu
660      * path that changed, false if this menu is part of the
661      * a menu path that changed, but this particular part of
662      * that path is still the same
663      * @see MenuSelectionManager#setSelectedPath(MenuElement[])
664      */

665     public void menuSelectionChanged(boolean isIncluded) {
666         setArmed(isIncluded);
667     }
668
669     /**
670      * This method returns an array containing the sub-menu
671      * components for this menu component.
672      *
673      * @return an array of <code>MenuElement</code>s
674      */

675     public MenuElement JavaDoc[] getSubElements() {
676         return new MenuElement JavaDoc[0];
677     }
678     
679     /**
680      * Returns the <code>java.awt.Component</code> used to paint
681      * this object. The returned component will be used to convert
682      * events and detect if an event is inside a menu component.
683      *
684      * @return the <code>Component</code> that paints this menu item
685      */

686     public Component getComponent() {
687         return this;
688     }
689
690     /**
691      * Adds a <code>MenuDragMouseListener</code> to the menu item.
692      *
693      * @param l the <code>MenuDragMouseListener</code> to be added
694      */

695     public void addMenuDragMouseListener(MenuDragMouseListener l) {
696         listenerList.add(MenuDragMouseListener.class, l);
697     }
698
699     /**
700      * Removes a <code>MenuDragMouseListener</code> from the menu item.
701      *
702      * @param l the <code>MenuDragMouseListener</code> to be removed
703      */

704     public void removeMenuDragMouseListener(MenuDragMouseListener l) {
705         listenerList.remove(MenuDragMouseListener.class, l);
706     }
707
708     /**
709      * Returns an array of all the <code>MenuDragMouseListener</code>s added
710      * to this JMenuItem with addMenuDragMouseListener().
711      *
712      * @return all of the <code>MenuDragMouseListener</code>s added or an empty
713      * array if no listeners have been added
714      * @since 1.4
715      */

716     public MenuDragMouseListener[] getMenuDragMouseListeners() {
717         return (MenuDragMouseListener[])listenerList.getListeners(
718                 MenuDragMouseListener.class);
719     }
720
721     /**
722      * Adds a <code>MenuKeyListener</code> to the menu item.
723      *
724      * @param l the <code>MenuKeyListener</code> to be added
725      */

726     public void addMenuKeyListener(MenuKeyListener l) {
727         listenerList.add(MenuKeyListener.class, l);
728     }
729
730     /**
731      * Removes a <code>MenuKeyListener</code> from the menu item.
732      *
733      * @param l the <code>MenuKeyListener</code> to be removed
734      */

735     public void removeMenuKeyListener(MenuKeyListener l) {
736         listenerList.remove(MenuKeyListener.class, l);
737     }
738
739     /**
740      * Returns an array of all the <code>MenuKeyListener</code>s added
741      * to this JMenuItem with addMenuKeyListener().
742      *
743      * @return all of the <code>MenuKeyListener</code>s added or an empty
744      * array if no listeners have been added
745      * @since 1.4
746      */

747     public MenuKeyListener[] getMenuKeyListeners() {
748         return (MenuKeyListener[])listenerList.getListeners(
749                 MenuKeyListener.class);
750     }
751
752     /**
753      * See JComponent.readObject() for information about serialization
754      * in Swing.
755      */

756     private void readObject(ObjectInputStream JavaDoc s)
757     throws IOException JavaDoc, ClassNotFoundException JavaDoc
758     {
759         s.defaultReadObject();
760     if (getUIClassID().equals(uiClassID)) {
761         updateUI();
762     }
763     }
764
765     private void writeObject(ObjectOutputStream JavaDoc s) throws IOException JavaDoc {
766         s.defaultWriteObject();
767         if (getUIClassID().equals(uiClassID)) {
768             byte count = JComponent.getWriteObjCounter(this);
769             JComponent.setWriteObjCounter(this, --count);
770             if (count == 0 && ui != null) {
771                 ui.installUI(this);
772             }
773         }
774     }
775
776
777     /**
778      * Returns a string representation of this <code>JMenuItem</code>.
779      * This method is intended to be used only for debugging purposes,
780      * and the content and format of the returned string may vary between
781      * implementations. The returned string may be empty but may not
782      * be <code>null</code>.
783      *
784      * @return a string representation of this <code>JMenuItem</code>
785      */

786     protected String JavaDoc paramString() {
787     return super.paramString();
788     }
789
790 /////////////////
791
// Accessibility support
792
////////////////
793

794     /**
795      * Returns the <code>AccessibleContext</code> associated with this
796      * <code>JMenuItem</code>. For <code>JMenuItem</code>s,
797      * the <code>AccessibleContext</code> takes the form of an
798      * <code>AccessibleJMenuItem</code>.
799      * A new AccessibleJMenuItme instance is created if necessary.
800      *
801      * @return an <code>AccessibleJMenuItem</code> that serves as the
802      * <code>AccessibleContext</code> of this <code>JMenuItem</code>
803      */

804     public AccessibleContext getAccessibleContext() {
805         if (accessibleContext == null) {
806             accessibleContext = new AccessibleJMenuItem();
807         }
808         return accessibleContext;
809     }
810
811
812     /**
813      * This class implements accessibility support for the
814      * <code>JMenuItem</code> class. It provides an implementation of the
815      * Java Accessibility API appropriate to menu item user-interface
816      * elements.
817      * <p>
818      * <strong>Warning:</strong>
819      * Serialized objects of this class will not be compatible with
820      * future Swing releases. The current serialization support is
821      * appropriate for short term storage or RMI between applications running
822      * the same version of Swing. As of 1.4, support for long term storage
823      * of all JavaBeans<sup><font size="-2">TM</font></sup>
824      * has been added to the <code>java.beans</code> package.
825      * Please see {@link java.beans.XMLEncoder}.
826      */

827     protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener JavaDoc {
828
829     private boolean isArmed = false;
830     private boolean hasFocus = false;
831     private boolean isPressed = false;
832     private boolean isSelected = false;
833
834         AccessibleJMenuItem() {
835             super();
836             JMenuItem.this.addChangeListener(this);
837         }
838
839         /**
840          * Get the role of this object.
841          *
842          * @return an instance of AccessibleRole describing the role of the
843          * object
844          */

845         public AccessibleRole getAccessibleRole() {
846             return AccessibleRole.MENU_ITEM;
847         }
848
849         private void fireAccessibilityFocusedEvent(JMenuItem JavaDoc toCheck) {
850             MenuElement JavaDoc [] path =
851                 MenuSelectionManager.defaultManager().getSelectedPath();
852             if (path.length > 0) {
853                 Object JavaDoc menuItem = path[path.length - 1];
854                 if (toCheck == menuItem) {
855                     firePropertyChange(
856                         AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
857                         null, AccessibleState.FOCUSED);
858                 }
859             }
860         }
861
862         /**
863          * Supports the change listener interface and fires property changes.
864          */

865         public void stateChanged(ChangeEvent JavaDoc e) {
866             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
867                                Boolean.valueOf(false), Boolean.valueOf(true));
868             if (JMenuItem.this.getModel().isArmed()) {
869         if (!isArmed) {
870             isArmed = true;
871             firePropertyChange(
872                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
873                         null, AccessibleState.ARMED);
874                     // Fix for 4848220 moved here to avoid major memory leak
875
// Here we will fire the event in case of JMenuItem
876
// See bug 4910323 for details [zav]
877
fireAccessibilityFocusedEvent(JMenuItem.this);
878         }
879             } else {
880         if (isArmed) {
881             isArmed = false;
882             firePropertyChange(
883                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
884                         AccessibleState.ARMED, null);
885         }
886         }
887             if (JMenuItem.this.isFocusOwner()) {
888         if (!hasFocus) {
889             hasFocus = true;
890             firePropertyChange(
891                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
892                         null, AccessibleState.FOCUSED);
893         }
894             } else {
895         if (hasFocus) {
896             hasFocus = false;
897             firePropertyChange(
898                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
899                         AccessibleState.FOCUSED, null);
900         }
901         }
902             if (JMenuItem.this.getModel().isPressed()) {
903         if (!isPressed) {
904             isPressed = true;
905             firePropertyChange(
906                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
907                         null, AccessibleState.PRESSED);
908         }
909             } else {
910         if (isPressed) {
911             isPressed = false;
912             firePropertyChange(
913                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
914                         AccessibleState.PRESSED, null);
915         }
916         }
917             if (JMenuItem.this.getModel().isSelected()) {
918         if (!isSelected) {
919             isSelected = true;
920             firePropertyChange(
921                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
922                         null, AccessibleState.CHECKED);
923
924                     // Fix for 4848220 moved here to avoid major memory leak
925
// Here we will fire the event in case of JMenu
926
// See bug 4910323 for details [zav]
927
fireAccessibilityFocusedEvent(JMenuItem.this);
928                 }
929             } else {
930         if (isSelected) {
931             isSelected = false;
932             firePropertyChange(
933                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
934                         AccessibleState.CHECKED, null);
935         }
936         }
937
938         }
939     } // inner class AccessibleJMenuItem
940
}
941
942
Popular Tags