KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > JPopupMenu


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

7
8 package javax.swing;
9
10 import java.awt.*;
11 import java.awt.event.*;
12 import java.io.IOException JavaDoc;
13 import java.io.ObjectInputStream JavaDoc;
14 import java.io.ObjectOutputStream JavaDoc;
15 import java.io.Serializable JavaDoc;
16 import java.beans.*;
17
18 import java.util.Locale JavaDoc;
19 import java.util.Vector JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import javax.accessibility.*;
22 import javax.swing.plaf.PopupMenuUI JavaDoc;
23 import javax.swing.plaf.ComponentUI JavaDoc;
24 import javax.swing.plaf.basic.BasicComboPopup JavaDoc;
25 import javax.swing.event.*;
26
27 import java.applet.Applet JavaDoc;
28
29 /**
30  * An implementation of a popup menu -- a small window that pops up
31  * and displays a series of choices. A <code>JPopupMenu</code> is used for the
32  * menu that appears when the user selects an item on the menu bar.
33  * It is also used for "pull-right" menu that appears when the
34  * selects a menu item that activates it. Finally, a <code>JPopupMenu</code>
35  * can also be used anywhere else you want a menu to appear. For
36  * example, when the user right-clicks in a specified area.
37  * <p>
38  * For information and examples of using popup menus, see
39  * <a
40  href="http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html">How to Use Menus</a>
41  * in <em>The Java Tutorial.</em>
42  * <p>
43  * <strong>Warning:</strong>
44  * Serialized objects of this class will not be compatible with
45  * future Swing releases. The current serialization support is
46  * appropriate for short term storage or RMI between applications running
47  * the same version of Swing. As of 1.4, support for long term storage
48  * of all JavaBeans<sup><font size="-2">TM</font></sup>
49  * has been added to the <code>java.beans</code> package.
50  * Please see {@link java.beans.XMLEncoder}.
51  *
52  * @beaninfo
53  * attribute: isContainer false
54  * description: A small window that pops up and displays a series of choices.
55  *
56  * @version 1.191 @(#)JPopupMenu.java 1.191
57  * @author Georges Saab
58  * @author David Karlton
59  * @author Arnaud Weber
60  */

61 public class JPopupMenu extends JComponent JavaDoc implements Accessible,MenuElement JavaDoc {
62
63     /**
64      * @see #getUIClassID
65      * @see #readObject
66      */

67     private static final String JavaDoc uiClassID = "PopupMenuUI";
68
69     /**
70      * Key used in AppContext to determine if light way popups are the default.
71      */

72     private static final Object JavaDoc defaultLWPopupEnabledKey =
73         new StringBuffer JavaDoc("JPopupMenu.defaultLWPopupEnabledKey");
74
75     /** Bug#4425878-Property javax.swing.adjustPopupLocationToFit introduced */
76     static boolean popupPostionFixDisabled = false;
77
78     static {
79         popupPostionFixDisabled = java.security.AccessController.doPrivileged(
80                 new sun.security.action.GetPropertyAction(
81                 "javax.swing.adjustPopupLocationToFit","")).equals("false");
82
83     }
84
85     transient Component invoker;
86     transient Popup JavaDoc popup;
87     transient Frame frame;
88     private int desiredLocationX,desiredLocationY;
89
90     private String JavaDoc label = null;
91     private boolean paintBorder = true;
92     private Insets margin = null;
93
94     /**
95      * Used to indicate if lightweight popups should be used.
96      */

97     private boolean lightWeightPopup = true;
98
99     /*
100      * Model for the selected subcontrol.
101      */

102     private SingleSelectionModel JavaDoc selectionModel;
103
104     /* Lock object used in place of class object for synchronization.
105      * (4187686)
106      */

107     private static final Object JavaDoc classLock = new Object JavaDoc();
108
109     /* diagnostic aids -- should be false for production builds. */
110     private static final boolean TRACE = false; // trace creates and disposes
111
private static final boolean VERBOSE = false; // show reuse hits/misses
112
private static final boolean DEBUG = false; // show bad params, misc.
113

114     /**
115      * Sets the default value of the <code>lightWeightPopupEnabled</code>
116      * property.
117      *
118      * @param aFlag <code>true</code> if popups can be lightweight,
119      * otherwise <code>false</code>
120      * @see #getDefaultLightWeightPopupEnabled
121      * @see #setLightWeightPopupEnabled
122      */

123     public static void setDefaultLightWeightPopupEnabled(boolean aFlag) {
124         SwingUtilities.appContextPut(defaultLWPopupEnabledKey,
125                                      Boolean.valueOf(aFlag));
126     }
127
128     /**
129      * Gets the <code>defaultLightWeightPopupEnabled</code> property,
130      * which by default is <code>true</code>.
131      *
132      * @return the value of the <code>defaultLightWeightPopupEnabled</code>
133      * property
134      *
135      * @see #setDefaultLightWeightPopupEnabled
136      */

137     public static boolean getDefaultLightWeightPopupEnabled() {
138         Boolean JavaDoc b = (Boolean JavaDoc)
139             SwingUtilities.appContextGet(defaultLWPopupEnabledKey);
140         if (b == null) {
141             SwingUtilities.appContextPut(defaultLWPopupEnabledKey,
142                                          Boolean.TRUE);
143             return true;
144         }
145         return b.booleanValue();
146     }
147
148     /**
149      * Constructs a <code>JPopupMenu</code> without an "invoker".
150      */

151     public JPopupMenu() {
152         this(null);
153     }
154
155     /**
156      * Constructs a <code>JPopupMenu</code> with the specified title.
157      *
158      * @param label the string that a UI may use to display as a title
159      * for the popup menu.
160      */

161     public JPopupMenu(String JavaDoc label) {
162         this.label = label;
163         lightWeightPopup = getDefaultLightWeightPopupEnabled();
164         setSelectionModel(new DefaultSingleSelectionModel JavaDoc());
165         enableEvents(AWTEvent.MOUSE_EVENT_MASK);
166     setFocusTraversalKeysEnabled(false);
167         updateUI();
168     }
169
170
171
172     /**
173      * Returns the look and feel (L&F) object that renders this component.
174      *
175      * @return the <code>PopupMenuUI</code> object that renders this component
176      */

177     public PopupMenuUI JavaDoc getUI() {
178         return (PopupMenuUI JavaDoc)ui;
179     }
180     
181     /**
182      * Sets the L&F object that renders this component.
183      *
184      * @param ui the new <code>PopupMenuUI</code> L&F object
185      * @see UIDefaults#getUI
186      * @beaninfo
187      * bound: true
188      * hidden: true
189      * attribute: visualUpdate true
190      * description: The UI object that implements the Component's LookAndFeel.
191      */

192     public void setUI(PopupMenuUI JavaDoc ui) {
193         super.setUI(ui);
194     }
195     
196     /**
197      * Resets the UI property to a value from the current look and feel.
198      *
199      * @see JComponent#updateUI
200      */

201     public void updateUI() {
202         setUI((PopupMenuUI JavaDoc)UIManager.getUI(this));
203     }
204
205
206     /**
207      * Returns the name of the L&F class that renders this component.
208      *
209      * @return the string "PopupMenuUI"
210      * @see JComponent#getUIClassID
211      * @see UIDefaults#getUI
212      */

213     public String JavaDoc getUIClassID() {
214         return uiClassID;
215     }
216
217     protected void processFocusEvent(FocusEvent evt) {
218     super.processFocusEvent(evt);
219     }
220
221     /**
222      * Processes key stroke events such as mnemonics and accelerators.
223      *
224      * @param evt the key event to be processed
225      */

226     protected void processKeyEvent(KeyEvent evt) {
227         MenuSelectionManager.defaultManager().processKeyEvent(evt);
228     if (evt.isConsumed()) {
229         return;
230     }
231     super.processKeyEvent(evt);
232     }
233
234
235     /**
236      * Returns the model object that handles single selections.
237      *
238      * @return the <code>selectionModel</code> property
239      * @see SingleSelectionModel
240      */

241     public SingleSelectionModel JavaDoc getSelectionModel() {
242         return selectionModel;
243     }
244
245     /**
246      * Sets the model object to handle single selections.
247      *
248      * @param model the new <code>SingleSelectionModel</code>
249      * @see SingleSelectionModel
250      * @beaninfo
251      * description: The selection model for the popup menu
252      * expert: true
253      */

254     public void setSelectionModel(SingleSelectionModel JavaDoc model) {
255         selectionModel = model;
256     }
257
258     /**
259      * Appends the specified menu item to the end of this menu.
260      *
261      * @param menuItem the <code>JMenuItem</code> to add
262      * @return the <code>JMenuItem</code> added
263      */

264     public JMenuItem JavaDoc add(JMenuItem JavaDoc menuItem) {
265         super.add(menuItem);
266         return menuItem;
267     }
268
269     /**
270      * Creates a new menu item with the specified text and appends
271      * it to the end of this menu.
272      *
273      * @param s the string for the menu item to be added
274      */

275     public JMenuItem JavaDoc add(String JavaDoc s) {
276         return add(new JMenuItem JavaDoc(s));
277     }
278
279     /**
280      * Appends a new menu item to the end of the menu which
281      * dispatches the specified <code>Action</code> object.
282      *
283      * As of JDK 1.3, this is no longer the preferred method for adding
284      * <code>Actions</code> to
285      * a container. Instead it is recommended to configure a control with
286      * an action using <code>setAction</code>, and then add that control
287      * directly to the <code>Container</code>.
288      *
289      * @param a the <code>Action</code> to add to the menu
290      * @return the new menu item
291      * @see Action
292      */

293     public JMenuItem JavaDoc add(Action JavaDoc a) {
294     JMenuItem JavaDoc mi = createActionComponent(a);
295     mi.setAction(a);
296         add(mi);
297         return mi;
298     }
299     
300     /**
301      * Returns an point which has been adjusted to take into account of the
302      * desktop bounds, taskbar and multi-monitor configuration.
303      * <p>
304      * This adustment may be cancelled by invoking the application with
305      * -Djavax.swing.adjustPopupLocationToFit=false
306      */

307     Point adjustPopupLocationToFitScreen(int xposition, int yposition) {
308     Point p = new Point(xposition, yposition);
309
310         if(popupPostionFixDisabled == true || GraphicsEnvironment.isHeadless())
311             return p;
312
313         Toolkit toolkit = Toolkit.getDefaultToolkit();
314         Rectangle screenBounds;
315         Insets screenInsets;
316         GraphicsConfiguration gc = null;
317         // Try to find GraphicsConfiguration, that includes mouse
318
// pointer position
319
GraphicsEnvironment ge =
320             GraphicsEnvironment.getLocalGraphicsEnvironment();
321         GraphicsDevice[] gd = ge.getScreenDevices();
322         for(int i = 0; i < gd.length; i++) {
323             if(gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
324                 GraphicsConfiguration dgc =
325                     gd[i].getDefaultConfiguration();
326                 if(dgc.getBounds().contains(p)) {
327                     gc = dgc;
328                     break;
329                 }
330             }
331         }
332
333         // If not found and we have invoker, ask invoker about his gc
334
if(gc == null && getInvoker() != null) {
335             gc = getInvoker().getGraphicsConfiguration();
336         }
337
338         if(gc != null) {
339             // If we have GraphicsConfiguration use it to get
340
// screen bounds and insets
341
screenInsets = toolkit.getScreenInsets(gc);
342             screenBounds = gc.getBounds();
343         } else {
344             // If we don't have GraphicsConfiguration use primary screen
345
// and empty insets
346
screenInsets = new Insets(0, 0, 0, 0);
347             screenBounds = new Rectangle(toolkit.getScreenSize());
348         }
349
350         int scrWidth = screenBounds.width -
351                     Math.abs(screenInsets.left+screenInsets.right);
352         int scrHeight = screenBounds.height -
353                     Math.abs(screenInsets.top+screenInsets.bottom);
354
355         Dimension size;
356
357         size = JPopupMenu.this.getPreferredSize();
358
359         if( (p.x + size.width) > screenBounds.x + scrWidth )
360              p.x = screenBounds.x + scrWidth - size.width;
361
362         if( (p.y + size.height) > screenBounds.y + scrHeight)
363              p.y = screenBounds.y + scrHeight - size.height;
364
365         /* Change is made to the desired (X,Y) values, when the
366            PopupMenu is too tall OR too wide for the screen
367         */

368         if( p.x < screenBounds.x )
369             p.x = screenBounds.x ;
370         if( p.y < screenBounds.y )
371             p.y = screenBounds.y;
372
373         return p;
374     }
375
376
377     /**
378      * Factory method which creates the <code>JMenuItem</code> for
379      * <code>Actions</code> added to the <code>JPopupMenu</code>.
380      * As of JDK 1.3, this is no
381      * longer the preferred method, instead it is recommended to configure
382      * a control with an action using <code>setAction</code>,
383      * and then adding that
384      * control directly to the <code>Container</code>.
385      *
386      * @param a the <code>Action</code> for the menu item to be added
387      * @return the new menu item
388      * @see Action
389      *
390      * @since 1.3
391      */

392     protected JMenuItem JavaDoc createActionComponent(Action JavaDoc a) {
393         JMenuItem JavaDoc mi = new JMenuItem JavaDoc((String JavaDoc)a.getValue(Action.NAME),
394                                      (Icon JavaDoc)a.getValue(Action.SMALL_ICON)){
395         protected PropertyChangeListener createActionPropertyChangeListener(Action JavaDoc a) {
396         PropertyChangeListener pcl = createActionChangeListener(this);
397         if (pcl == null) {
398             pcl = super.createActionPropertyChangeListener(a);
399         }
400         return pcl;
401         }
402     };
403         mi.setHorizontalTextPosition(JButton.TRAILING);
404         mi.setVerticalTextPosition(JButton.CENTER);
405         mi.setEnabled(a.isEnabled());
406     return mi;
407     }
408
409     /**
410      * Returns a properly configured <code>PropertyChangeListener</code>
411      * which updates the control as changes to the <code>Action</code> occur.
412      * As of JDK 1.3, this is no longer the preferred method for adding
413      * <code>Actions</code> to
414      * a container. Instead it is recommended to configure a control with
415      * an action using <code>setAction</code>, and then add that control
416      * directly to the <code>Container</code>.
417      */

418     protected PropertyChangeListener createActionChangeListener(JMenuItem JavaDoc b) {
419         return new ActionChangedListener(b);
420     }
421
422     private class ActionChangedListener implements PropertyChangeListener, Serializable JavaDoc {
423         private JMenuItem JavaDoc menuItem;
424         
425         public ActionChangedListener(JMenuItem JavaDoc mi) {
426             super();
427             setTarget(mi);
428         }
429         public void propertyChange(PropertyChangeEvent e) {
430             String JavaDoc propertyName = e.getPropertyName();
431             if (e.getPropertyName().equals(Action.NAME)) {
432                 String JavaDoc text = (String JavaDoc) e.getNewValue();
433                 menuItem.setText(text);
434             } else if (propertyName.equals("enabled")) {
435                 Boolean JavaDoc enabledState = (Boolean JavaDoc) e.getNewValue();
436                 menuItem.setEnabled(enabledState.booleanValue());
437             } else if (e.getPropertyName().equals(Action.SMALL_ICON)) {
438                 Icon JavaDoc icon = (Icon JavaDoc) e.getNewValue();
439                 menuItem.setIcon(icon);
440                 menuItem.invalidate();
441                 menuItem.repaint();
442             }
443         }
444     public void setTarget(JMenuItem JavaDoc b) {
445         this.menuItem = b;
446     }
447     }
448
449     /**
450      * Removes the component at the specified index from this popup menu.
451      *
452      * @param pos the position of the item to be removed
453      * @exception IllegalArgumentException if the value of
454      * <code>pos</code> < 0, or if the value of
455      * <code>pos</code> is greater than the
456      * number of items
457      */

458     public void remove(int pos) {
459         if (pos < 0) {
460             throw new IllegalArgumentException JavaDoc("index less than zero.");
461         }
462         if (pos > getComponentCount() -1) {
463             throw new IllegalArgumentException JavaDoc("index greater than the number of items.");
464         }
465     super.remove(pos);
466     }
467
468     /**
469      * Sets the value of the <code>lightWeightPopupEnabled</code> property,
470      * which by default is <code>true</code>.
471      * By default, when a look and feel displays a popup,
472      * it can choose to
473      * use a lightweight (all-Java) popup.
474      * Lightweight popup windows are more efficient than heavyweight
475      * (native peer) windows,
476      * but lightweight and heavyweight components do not mix well in a GUI.
477      * If your application mixes lightweight and heavyweight components,
478      * you should disable lightweight popups.
479      * Some look and feels might always use heavyweight popups,
480      * no matter what the value of this property.
481      *
482      * @param aFlag <code>false</code> to disable lightweight popups
483      * @beaninfo
484      * description: Determines whether lightweight popups are used when possible
485      * expert: true
486      *
487      * @see #isLightWeightPopupEnabled
488      */

489     public void setLightWeightPopupEnabled(boolean aFlag) {
490         // NOTE: this use to set the flag on a shared JPopupMenu, which meant
491
// this effected ALL JPopupMenus.
492
lightWeightPopup = aFlag;
493     }
494
495     /**
496      * Gets the <code>lightWeightPopupEnabled</code> property.
497      *
498      * @return the value of the <code>lightWeightPopupEnabled</code> property
499      * @see #setLightWeightPopupEnabled
500      */

501     public boolean isLightWeightPopupEnabled() {
502         return lightWeightPopup;
503     }
504
505     /**
506      * Returns the popup menu's label
507      *
508      * @return a string containing the popup menu's label
509      * @see #setLabel
510      */

511     public String JavaDoc getLabel() {
512         return label;
513     }
514     
515     /**
516      * Sets the popup menu's label. Different look and feels may choose
517      * to display or not display this.
518      *
519      * @param label a string specifying the label for the popup menu
520      *
521      * @see #setLabel
522      * @beaninfo
523      * description: The label for the popup menu.
524      * bound: true
525      */

526     public void setLabel(String JavaDoc label) {
527         String JavaDoc oldValue = this.label;
528         this.label = label;
529         firePropertyChange("label", oldValue, label);
530         if (accessibleContext != null) {
531             accessibleContext.firePropertyChange(
532                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
533                 oldValue, label);
534         }
535         invalidate();
536         repaint();
537     }
538
539     /**
540      * Appends a new separator at the end of the menu.
541      */

542     public void addSeparator() {
543         add( new JPopupMenu.Separator JavaDoc() );
544     }
545
546     /**
547      * Inserts a menu item for the specified <code>Action</code> object at
548      * a given position.
549      *
550      * @param a the <code>Action</code> object to insert
551      * @param index specifies the position at which to insert the
552      * <code>Action</code>, where 0 is the first
553      * @exception IllegalArgumentException if <code>index</code> < 0
554      * @see Action
555      */

556     public void insert(Action JavaDoc a, int index) {
557     JMenuItem JavaDoc mi = createActionComponent(a);
558     mi.setAction(a);
559         insert(mi, index);
560     }
561
562     /**
563      * Inserts the specified component into the menu at a given
564      * position.
565      *
566      * @param component the <code>Component</code> to insert
567      * @param index specifies the position at which
568      * to insert the component, where 0 is the first
569      * @exception IllegalArgumentException if <code>index</code> < 0
570      */

571     public void insert(Component component, int index) {
572         if (index < 0) {
573             throw new IllegalArgumentException JavaDoc("index less than zero.");
574         }
575
576         int nitems = getComponentCount();
577     // PENDING(ges): Why not use an array?
578
Vector JavaDoc tempItems = new Vector JavaDoc();
579
580         /* Remove the item at index, nitems-index times
581            storing them in a temporary vector in the
582            order they appear on the menu.
583            */

584         for (int i = index ; i < nitems; i++) {
585             tempItems.addElement(getComponent(index));
586             remove(index);
587         }
588
589         add(component);
590
591         /* Add the removed items back to the menu, they are
592            already in the correct order in the temp vector.
593            */

594         for (int i = 0; i < tempItems.size() ; i++) {
595             add((Component)tempItems.elementAt(i));
596         }
597     }
598
599     /**
600      * Adds a <code>PopupMenu</code> listener.
601      *
602      * @param l the <code>PopupMenuListener</code> to add
603      */

604     public void addPopupMenuListener(PopupMenuListener l) {
605         listenerList.add(PopupMenuListener.class,l);
606     }
607
608     /**
609      * Removes a <code>PopupMenu</code> listener.
610      *
611      * @param l the <code>PopupMenuListener</code> to remove
612      */

613     public void removePopupMenuListener(PopupMenuListener l) {
614         listenerList.remove(PopupMenuListener.class,l);
615     }
616
617     /**
618      * Returns an array of all the <code>PopupMenuListener</code>s added
619      * to this JMenuItem with addPopupMenuListener().
620      *
621      * @return all of the <code>PopupMenuListener</code>s added or an empty
622      * array if no listeners have been added
623      * @since 1.4
624      */

625     public PopupMenuListener[] getPopupMenuListeners() {
626         return (PopupMenuListener[])listenerList.getListeners(
627                 PopupMenuListener.class);
628     }
629
630     /**
631      * Adds a <code>MenuKeyListener</code> to the popup menu.
632      *
633      * @param l the <code>MenuKeyListener</code> to be added
634      * @since 1.5
635      */

636     public void addMenuKeyListener(MenuKeyListener l) {
637         listenerList.add(MenuKeyListener.class, l);
638     }
639
640     /**
641      * Removes a <code>MenuKeyListener</code> from the popup menu.
642      *
643      * @param l the <code>MenuKeyListener</code> to be removed
644      * @since 1.5
645      */

646     public void removeMenuKeyListener(MenuKeyListener l) {
647         listenerList.remove(MenuKeyListener.class, l);
648     }
649
650     /**
651      * Returns an array of all the <code>MenuKeyListener</code>s added
652      * to this JPopupMenu with addMenuKeyListener().
653      *
654      * @return all of the <code>MenuKeyListener</code>s added or an empty
655      * array if no listeners have been added
656      * @since 1.5
657      */

658     public MenuKeyListener[] getMenuKeyListeners() {
659         return (MenuKeyListener[])listenerList.getListeners(
660                 MenuKeyListener.class);
661     }
662
663     /**
664      * Notifies <code>PopupMenuListener</code>s that this popup menu will
665      * become visible.
666      */

667     protected void firePopupMenuWillBecomeVisible() {
668         Object JavaDoc[] listeners = listenerList.getListenerList();
669         PopupMenuEvent e=null;
670         for (int i = listeners.length-2; i>=0; i-=2) {
671             if (listeners[i]==PopupMenuListener.class) {
672                 if (e == null)
673                     e = new PopupMenuEvent(this);
674                 ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeVisible(e);
675             }
676         }
677     }
678     
679     /**
680      * Notifies <code>PopupMenuListener</code>s that this popup menu will
681      * become invisible.
682      */

683     protected void firePopupMenuWillBecomeInvisible() {
684         Object JavaDoc[] listeners = listenerList.getListenerList();
685         PopupMenuEvent e=null;
686         for (int i = listeners.length-2; i>=0; i-=2) {
687             if (listeners[i]==PopupMenuListener.class) {
688                 if (e == null)
689                     e = new PopupMenuEvent(this);
690                 ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeInvisible(e);
691             }
692         }
693     }
694     
695     /**
696      * Notifies <code>PopupMenuListeners</code> that this popup menu is
697      * cancelled.
698      */

699     protected void firePopupMenuCanceled() {
700         Object JavaDoc[] listeners = listenerList.getListenerList();
701         PopupMenuEvent e=null;
702         for (int i = listeners.length-2; i>=0; i-=2) {
703             if (listeners[i]==PopupMenuListener.class) {
704                 if (e == null)
705                     e = new PopupMenuEvent(this);
706                 ((PopupMenuListener)listeners[i+1]).popupMenuCanceled(e);
707             }
708         }
709     }
710
711     /**
712      * Always returns true since popups, by definition, should always
713      * be on top of all other windows.
714      * @return true
715      */

716     // package private
717
boolean alwaysOnTop() {
718     return true;
719     }
720
721     /**
722      * Lays out the container so that it uses the minimum space
723      * needed to display its contents.
724      */

725     public void pack() {
726         if(popup != null) {
727             Dimension pref = getPreferredSize();
728
729             if (pref == null || pref.width != getWidth() ||
730                                 pref.height != getHeight()) {
731                 popup = getPopup();
732             } else {
733                 validate();
734             }
735         }
736     }
737
738     /**
739      * Sets the visibility of the popup menu.
740      *
741      * @param b true to make the popup visible, or false to
742      * hide it
743      * @beaninfo
744      * bound: true
745      * description: Makes the popup visible
746      */

747     public void setVisible(boolean b) {
748     if (DEBUG) {
749         System.out.println("JPopupMenu.setVisible " + b);
750     }
751
752         // Is it a no-op?
753
if (b == isVisible())
754             return;
755
756         // if closing, first close all Submenus
757
if (b == false) {
758
759         // 4234793: This is a workaround because JPopupMenu.firePopupMenuCanceled is
760
// a protected method and cannot be called from BasicPopupMenuUI directly
761
// The real solution could be to make
762
// firePopupMenuCanceled public and call it directly.
763
Boolean JavaDoc doCanceled = (Boolean JavaDoc)getClientProperty("JPopupMenu.firePopupMenuCanceled");
764         if (doCanceled != null && doCanceled == Boolean.TRUE) {
765         putClientProperty("JPopupMenu.firePopupMenuCanceled", Boolean.FALSE);
766         firePopupMenuCanceled();
767         }
768             getSelectionModel().clearSelection();
769         
770         } else {
771             // This is a popup menu with MenuElement children,
772
// set selection path before popping up!
773
if (isPopupMenu()) {
774         if (getSubElements().length > 0) {
775             MenuElement JavaDoc me[] = new MenuElement JavaDoc[2];
776             me[0]=(MenuElement JavaDoc)this;
777             me[1]=getSubElements()[0];
778             MenuSelectionManager.defaultManager().setSelectedPath(me);
779         } else {
780             MenuElement JavaDoc me[] = new MenuElement JavaDoc[1];
781             me[0]=(MenuElement JavaDoc)this;
782             MenuSelectionManager.defaultManager().setSelectedPath(me);
783         }
784         }
785         }
786
787         if(b) {
788             firePopupMenuWillBecomeVisible();
789             popup = getPopup();
790         firePropertyChange("visible", Boolean.FALSE, Boolean.TRUE);
791
792        
793     } else if(popup != null) {
794             firePopupMenuWillBecomeInvisible();
795             popup.hide();
796             popup = null;
797         firePropertyChange("visible", Boolean.TRUE, Boolean.FALSE);
798             // 4694797: When popup menu is made invisible, selected path
799
// should be cleared
800
if (isPopupMenu()) {
801                 MenuSelectionManager.defaultManager().clearSelectedPath();
802             }
803         }
804     }
805
806     /**
807      * Returns a <code>Popup</code> instance from the
808      * <code>PopupMenuUI</code> that has had <code>show</code> invoked on
809      * it. If the current <code>popup</code> is non-null,
810      * this will invoke <code>dispose</code> of it, and then
811      * <code>show</code> the new one.
812      * <p>
813      * This does NOT fire any events, it is up the caller to dispatch
814      * the necessary events.
815      */

816     private Popup JavaDoc getPopup() {
817         Popup JavaDoc oldPopup = popup;
818
819         if (oldPopup != null) {
820             oldPopup.hide();
821         }
822         PopupFactory JavaDoc popupFactory = PopupFactory.getSharedInstance();
823
824         if (isLightWeightPopupEnabled()) {
825             popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
826         }
827         else {
828             popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
829         }
830
831         // adjust the location of the popup
832
Point p = adjustPopupLocationToFitScreen(desiredLocationX,desiredLocationY);
833     desiredLocationX = p.x;
834     desiredLocationY = p.y;
835
836         Popup JavaDoc newPopup = getUI().getPopup(this, desiredLocationX,
837                                           desiredLocationY);
838
839         popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
840         newPopup.show();
841         return newPopup;
842     }
843
844     /**
845      * Returns true if the popup menu is visible (currently
846      * being displayed).
847      */

848     public boolean isVisible() {
849     if(popup != null)
850         return true;
851     else
852         return false;
853     }
854
855     /**
856      * Sets the location of the upper left corner of the
857      * popup menu using x, y coordinates.
858      *
859      * @param x the x coordinate of the popup's new position
860      * in the screen's coordinate space
861      * @param y the y coordinate of the popup's new position
862      * in the screen's coordinate space
863      * @beaninfo
864      * description: The location of the popup menu.
865      */

866     public void setLocation(int x, int y) {
867         int oldX = desiredLocationX;
868         int oldY = desiredLocationY;
869
870         desiredLocationX = x;
871         desiredLocationY = y;
872         if(popup != null && (x != oldX || y != oldY)) {
873             popup = getPopup();
874         }
875     }
876
877     /**
878      * Returns true if the popup menu is a standalone popup menu
879      * rather than the submenu of a <code>JMenu</code>.
880      *
881      * @return true if this menu is a standalone popup menu, otherwise false
882      */

883     private boolean isPopupMenu() {
884         return ((invoker != null) && !(invoker instanceof JMenu JavaDoc));
885     }
886
887     /**
888      * Returns the component which is the 'invoker' of this
889      * popup menu.
890      *
891      * @return the <code>Component</code> in which the popup menu is displayed
892      */

893     public Component getInvoker() {
894         return this.invoker;
895     }
896
897     /**
898      * Sets the invoker of this popup menu -- the component in which
899      * the popup menu menu is to be displayed.
900      *
901      * @param invoker the <code>Component</code> in which the popup
902      * menu is displayed
903      * @beaninfo
904      * description: The invoking component for the popup menu
905      * expert: true
906      */

907     public void setInvoker(Component invoker) {
908         Component oldInvoker = this.invoker;
909         this.invoker = invoker;
910         if ((oldInvoker != this.invoker) && (ui != null)) {
911             ui.uninstallUI(this);
912             ui.installUI(this);
913         }
914         invalidate();
915     }
916
917     /**
918      * Displays the popup menu at the position x,y in the coordinate
919      * space of the component invoker.
920      *
921      * @param invoker the component in whose space the popup menu is to appear
922      * @param x the x coordinate in invoker's coordinate space at which
923      * the popup menu is to be displayed
924      * @param y the y coordinate in invoker's coordinate space at which
925      * the popup menu is to be displayed
926      */

927     public void show(Component invoker, int x, int y) {
928     if (DEBUG) {
929         System.out.println("in JPopupMenu.show " );
930     }
931         setInvoker(invoker);
932         Frame newFrame = getFrame(invoker);
933         if (newFrame != frame) {
934             // Use the invoker's frame so that events
935
// are propagated properly
936
if (newFrame!=null) {
937                 this.frame = newFrame;
938                 if(popup != null) {
939                     setVisible(false);
940                 }
941             }
942         }
943     Point invokerOrigin;
944     if (invoker != null) {
945         invokerOrigin = invoker.getLocationOnScreen();
946         setLocation(invokerOrigin.x + x,
947             invokerOrigin.y + y);
948     } else {
949         setLocation(x, y);
950     }
951         setVisible(true);
952     }
953
954     /**
955      * Returns the popup menu which is at the root of the menu system
956      * for this popup menu.
957      *
958      * @return the topmost grandparent <code>JPopupMenu</code>
959      */

960     JPopupMenu JavaDoc getRootPopupMenu() {
961         JPopupMenu JavaDoc mp = this;
962         while((mp!=null) && (mp.isPopupMenu()!=true) &&
963               (mp.getInvoker() != null) &&
964               (mp.getInvoker().getParent() != null) &&
965               (mp.getInvoker().getParent() instanceof JPopupMenu JavaDoc)
966               ) {
967             mp = (JPopupMenu JavaDoc) mp.getInvoker().getParent();
968         }
969         return mp;
970     }
971
972     /**
973      * Returns the component at the specified index.
974      *
975      * @param i the index of the component, where 0 is the first
976      * @return the <code>Component</code> at that index
977      * @deprecated replaced by <code>getComponent(int i)</code>
978      */

979     @Deprecated JavaDoc
980     public Component getComponentAtIndex(int i) {
981         return getComponent(i);
982     }
983
984     /**
985      * Returns the index of the specified component.
986      *
987      * @param c the <code>Component</code> to find
988      * @return the index of the component, where 0 is the first;
989      * or -1 if the component is not found
990      */

991     public int getComponentIndex(Component c) {
992         int ncomponents = this.getComponentCount();
993         Component[] component = this.getComponents();
994         for (int i = 0 ; i < ncomponents ; i++) {
995             Component comp = component[i];
996             if (comp == c)
997                 return i;
998         }
999         return -1;
1000    }
1001
1002    /**
1003     * Sets the size of the Popup window using a <code>Dimension</code> object.
1004     * This is equivalent to <code>setPreferredSize(d)</code>.
1005     *
1006     * @param d the <code>Dimension</code> specifying the new size
1007     * of this component.
1008     * @beaninfo
1009     * description: The size of the popup menu
1010     */

1011    public void setPopupSize(Dimension d) {
1012        Dimension oldSize = getPreferredSize();
1013
1014        setPreferredSize(d);
1015        if (popup != null) {
1016            Dimension newSize = getPreferredSize();
1017
1018            if (!oldSize.equals(newSize)) {
1019                popup = getPopup();
1020            }
1021        }
1022    }
1023
1024    /**
1025     * Sets the size of the Popup window to the specified width and
1026     * height. This is equivalent to
1027     * <code>setPreferredSize(new Dimension(width, height))</code>.
1028     *
1029     * @param width the new width of the Popup in pixels
1030     * @param height the new height of the Popup in pixels
1031     * @beaninfo
1032     * description: The size of the popup menu
1033     */

1034    public void setPopupSize(int width, int height) {
1035        setPopupSize(new Dimension(width, height));
1036    }
1037    
1038    /**
1039     * Sets the currently selected component, This will result
1040     * in a change to the selection model.
1041     *
1042     * @param sel the <code>Component</code> to select
1043     * @beaninfo
1044     * description: The selected component on the popup menu
1045     * expert: true
1046     * hidden: true
1047     */

1048    public void setSelected(Component sel) {
1049        SingleSelectionModel JavaDoc model = getSelectionModel();
1050        int index = getComponentIndex(sel);
1051        model.setSelectedIndex(index);
1052    }
1053
1054    /**
1055     * Checks whether the border should be painted.
1056     *
1057     * @return true if the border is painted, false otherwise
1058     * @see #setBorderPainted
1059     */

1060    public boolean isBorderPainted() {
1061        return paintBorder;
1062    }
1063
1064    /**
1065     * Sets whether the border should be painted.
1066     *
1067     * @param b if true, the border is painted.
1068     * @see #isBorderPainted
1069     * @beaninfo
1070     * description: Is the border of the popup menu painted
1071     */

1072    public void setBorderPainted(boolean b) {
1073        paintBorder = b;
1074        repaint();
1075    }
1076
1077    /**
1078     * Paints the popup menu's border if the <code>borderPainted</code>
1079     * property is <code>true</code>.
1080     * @param g the <code>Graphics</code> object
1081     *
1082     * @see JComponent#paint
1083     * @see JComponent#setBorder
1084     */

1085    protected void paintBorder(Graphics g) {
1086        if (isBorderPainted()) {
1087            super.paintBorder(g);
1088        }
1089    }
1090
1091    /**
1092     * Returns the margin, in pixels, between the popup menu's border and
1093     * its containees.
1094     *
1095     * @return an <code>Insets</code> object containing the margin values.
1096     */

1097    public Insets getMargin() {
1098        if(margin == null) {
1099            return new Insets(0,0,0,0);
1100        } else {
1101            return margin;
1102        }
1103    }
1104
1105
1106    /**
1107     * Examines the list of menu items to determine whether
1108     * <code>popup</code> is a popup menu.
1109     *
1110     * @param popup a <code>JPopupMenu</code>
1111     * @return true if <code>popup</code>
1112     */

1113    boolean isSubPopupMenu(JPopupMenu JavaDoc popup) {
1114        int ncomponents = this.getComponentCount();
1115        Component[] component = this.getComponents();
1116        for (int i = 0 ; i < ncomponents ; i++) {
1117            Component comp = component[i];
1118            if (comp instanceof JMenu JavaDoc) {
1119                JMenu JavaDoc menu = (JMenu JavaDoc)comp;
1120                JPopupMenu JavaDoc subPopup = menu.getPopupMenu();
1121                if (subPopup == popup)
1122                    return true;
1123                if (subPopup.isSubPopupMenu(popup))
1124                    return true;
1125            }
1126        }
1127        return false;
1128    }
1129
1130
1131    private static Frame getFrame(Component c) {
1132        Component w = c;
1133
1134        while(!(w instanceof Frame) && (w!=null)) {
1135            w = w.getParent();
1136        }
1137        return (Frame)w;
1138    }
1139
1140
1141    /**
1142     * Returns a string representation of this <code>JPopupMenu</code>.
1143     * This method
1144     * is intended to be used only for debugging purposes, and the
1145     * content and format of the returned string may vary between
1146     * implementations. The returned string may be empty but may not
1147     * be <code>null</code>.
1148     *
1149     * @return a string representation of this <code>JPopupMenu</code>.
1150     */

1151    protected String JavaDoc paramString() {
1152    String JavaDoc labelString = (label != null ?
1153                  label : "");
1154    String JavaDoc paintBorderString = (paintBorder ?
1155                    "true" : "false");
1156    String JavaDoc marginString = (margin != null ?
1157                  margin.toString() : "");
1158    String JavaDoc lightWeightPopupEnabledString = (isLightWeightPopupEnabled() ?
1159                        "true" : "false");
1160    return super.paramString() +
1161        ",desiredLocationX=" + desiredLocationX +
1162        ",desiredLocationY=" + desiredLocationY +
1163    ",label=" + labelString +
1164    ",lightWeightPopupEnabled=" + lightWeightPopupEnabledString +
1165    ",margin=" + marginString +
1166    ",paintBorder=" + paintBorderString;
1167    }
1168
1169/////////////////
1170
// Accessibility support
1171
////////////////
1172

1173    /**
1174     * Gets the AccessibleContext associated with this JPopupMenu.
1175     * For JPopupMenus, the AccessibleContext takes the form of an
1176     * AccessibleJPopupMenu.
1177     * A new AccessibleJPopupMenu instance is created if necessary.
1178     *
1179     * @return an AccessibleJPopupMenu that serves as the
1180     * AccessibleContext of this JPopupMenu
1181     */

1182    public AccessibleContext getAccessibleContext() {
1183        if (accessibleContext == null) {
1184            accessibleContext = new AccessibleJPopupMenu();
1185        }
1186        return accessibleContext;
1187    }
1188
1189    /**
1190     * This class implements accessibility support for the
1191     * <code>JPopupMenu</code> class. It provides an implementation of the
1192     * Java Accessibility API appropriate to popup menu user-interface
1193     * elements.
1194     */

1195    protected class AccessibleJPopupMenu extends AccessibleJComponent
1196        implements PropertyChangeListener {
1197
1198    /**
1199     * AccessibleJPopupMenu constructor
1200     *
1201     * @since 1.5
1202     */

1203    protected AccessibleJPopupMenu() {
1204        JPopupMenu.this.addPropertyChangeListener(this);
1205    }
1206
1207    /**
1208         * Get the role of this object.
1209         *
1210         * @return an instance of AccessibleRole describing the role of
1211         * the object
1212         */

1213        public AccessibleRole getAccessibleRole() {
1214            return AccessibleRole.POPUP_MENU;
1215        }
1216
1217    /**
1218     * This method gets called when a bound property is changed.
1219     * @param evt A <code>PropertyChangeEvent</code> object describing
1220     * the event source and the property that has changed. Must not be null.
1221     *
1222     * @throws NullPointerException if the parameter is null.
1223     * @since 1.5
1224     */

1225    public void propertyChange(PropertyChangeEvent e) {
1226        String JavaDoc propertyName = e.getPropertyName();
1227        if (propertyName == "visible") {
1228        if (e.getOldValue() == Boolean.FALSE &&
1229            e.getNewValue() == Boolean.TRUE) {
1230            handlePopupIsVisibleEvent(true);
1231
1232        } else if (e.getOldValue() == Boolean.TRUE &&
1233               e.getNewValue() == Boolean.FALSE) {
1234            handlePopupIsVisibleEvent(false);
1235        }
1236        }
1237    }
1238
1239    /*
1240     * Handles popup "visible" PropertyChangeEvent
1241     */

1242    private void handlePopupIsVisibleEvent(boolean visible) {
1243        if (visible) {
1244        // notify listeners that the popup became visible
1245
firePropertyChange(ACCESSIBLE_STATE_PROPERTY,
1246                   null, AccessibleState.VISIBLE);
1247        // notify listeners that a popup list item is selected
1248
fireActiveDescendant();
1249        } else {
1250        // notify listeners that the popup became hidden
1251
firePropertyChange(ACCESSIBLE_STATE_PROPERTY,
1252                   AccessibleState.VISIBLE, null);
1253        }
1254    }
1255
1256    /*
1257     * Fires AccessibleActiveDescendant PropertyChangeEvent to notify listeners
1258     * on the popup menu invoker that a popup list item has been selected
1259     */

1260    private void fireActiveDescendant() {
1261        if (JPopupMenu.this instanceof BasicComboPopup JavaDoc) {
1262        // get the popup list
1263
JList JavaDoc popupList = ((BasicComboPopup JavaDoc)JPopupMenu.this).getList();
1264        if (popupList == null) {
1265            return;
1266        }
1267        
1268        // get the first selected item
1269
AccessibleContext ac = popupList.getAccessibleContext();
1270        AccessibleSelection selection = ac.getAccessibleSelection();
1271        if (selection == null) {
1272            return;
1273        }
1274        Accessible a = selection.getAccessibleSelection(0);
1275        if (a == null) {
1276            return;
1277        }
1278        AccessibleContext selectedItem = a.getAccessibleContext();
1279        
1280        // fire the event with the popup invoker as the source.
1281
if (selectedItem != null && invoker != null) {
1282            AccessibleContext invokerContext = invoker.getAccessibleContext();
1283            if (invokerContext != null) {
1284            // Check invokerContext because Component.getAccessibleContext
1285
// returns null. Classes that extend Component are responsible
1286
// for returning a non-null AccessibleContext.
1287
invokerContext.firePropertyChange(
1288                            ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY,
1289                null, selectedItem);
1290            }
1291        }
1292        }
1293    }
1294    } // inner class AccessibleJPopupMenu
1295

1296
1297////////////
1298
// Serialization support.
1299
////////////
1300
private void writeObject(ObjectOutputStream JavaDoc s) throws IOException JavaDoc {
1301        Vector JavaDoc values = new Vector JavaDoc();
1302
1303        s.defaultWriteObject();
1304        // Save the invoker, if its Serializable.
1305
if(invoker != null && invoker instanceof Serializable JavaDoc) {
1306            values.addElement("invoker");
1307            values.addElement(invoker);
1308        }
1309        // Save the popup, if its Serializable.
1310
if(popup != null && popup instanceof Serializable JavaDoc) {
1311            values.addElement("popup");
1312            values.addElement(popup);
1313        }
1314        s.writeObject(values);
1315
1316        if (getUIClassID().equals(uiClassID)) {
1317            byte count = JComponent.getWriteObjCounter(this);
1318            JComponent.setWriteObjCounter(this, --count);
1319            if (count == 0 && ui != null) {
1320                ui.installUI(this);
1321            }
1322        }
1323    }
1324
1325    // implements javax.swing.MenuElement
1326
private void readObject(ObjectInputStream JavaDoc s)
1327        throws IOException JavaDoc, ClassNotFoundException JavaDoc {
1328        s.defaultReadObject();
1329
1330        Vector JavaDoc values = (Vector JavaDoc)s.readObject();
1331        int indexCounter = 0;
1332        int maxCounter = values.size();
1333
1334        if(indexCounter < maxCounter && values.elementAt(indexCounter).
1335           equals("invoker")) {
1336            invoker = (Component)values.elementAt(++indexCounter);
1337            indexCounter++;
1338        }
1339        if(indexCounter < maxCounter && values.elementAt(indexCounter).
1340           equals("popup")) {
1341            popup = (Popup JavaDoc)values.elementAt(++indexCounter);
1342            indexCounter++;
1343        }
1344    }
1345
1346    
1347    /**
1348     * This method is required to conform to the
1349     * <code>MenuElement</code> interface, but it not implemented.
1350     * @see MenuElement#processMouseEvent(MouseEvent, MenuElement[], MenuSelectionManager)
1351     */

1352    public void processMouseEvent(MouseEvent event,MenuElement JavaDoc path[],MenuSelectionManager JavaDoc manager) {}
1353
1354    /**
1355     * Processes a key event forwarded from the
1356     * <code>MenuSelectionManager</code> and changes the menu selection,
1357     * if necessary, by using <code>MenuSelectionManager</code>'s API.
1358     * <p>
1359     * Note: you do not have to forward the event to sub-components.
1360     * This is done automatically by the <code>MenuSelectionManager</code>.
1361     *
1362     * @param e a <code>KeyEvent</code>
1363     * @param path the <code>MenuElement</code> path array
1364     * @param manager the <code>MenuSelectionManager</code>
1365     */

1366    public void processKeyEvent(KeyEvent e, MenuElement JavaDoc path[],
1367                                MenuSelectionManager JavaDoc manager) {
1368        MenuKeyEvent mke = new MenuKeyEvent(e.getComponent(), e.getID(),
1369                         e.getWhen(), e.getModifiers(),
1370                         e.getKeyCode(), e.getKeyChar(),
1371                         path, manager);
1372        processMenuKeyEvent(mke);
1373
1374        if (mke.isConsumed()) {
1375            e.consume();
1376    }
1377    }
1378
1379    /**
1380     * Handles a keystroke in a menu.
1381     *
1382     * @param e a <code>MenuKeyEvent</code> object
1383     * @since 1.5
1384     */

1385    private void processMenuKeyEvent(MenuKeyEvent e) {
1386        switch (e.getID()) {
1387        case KeyEvent.KEY_PRESSED:
1388            fireMenuKeyPressed(e); break;
1389        case KeyEvent.KEY_RELEASED:
1390            fireMenuKeyReleased(e); break;
1391        case KeyEvent.KEY_TYPED:
1392            fireMenuKeyTyped(e); break;
1393        default:
1394            break;
1395        }
1396    }
1397
1398    /**
1399     * Notifies all listeners that have registered interest for
1400     * notification on this event type.
1401     *
1402     * @param event a <code>MenuKeyEvent</code>
1403     * @see EventListenerList
1404     */

1405    private void fireMenuKeyPressed(MenuKeyEvent event) {
1406        Object JavaDoc[] listeners = listenerList.getListenerList();
1407        for (int i = listeners.length-2; i>=0; i-=2) {
1408            if (listeners[i]==MenuKeyListener.class) {
1409                ((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
1410            }
1411        }
1412    }
1413
1414    /**
1415     * Notifies all listeners that have registered interest for
1416     * notification on this event type.
1417     *
1418     * @param event a <code>MenuKeyEvent</code>
1419     * @see EventListenerList
1420     */

1421    private void fireMenuKeyReleased(MenuKeyEvent event) {
1422        Object JavaDoc[] listeners = listenerList.getListenerList();
1423        for (int i = listeners.length-2; i>=0; i-=2) {
1424            if (listeners[i]==MenuKeyListener.class) {
1425                ((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
1426            }
1427        }
1428    }
1429
1430    /**
1431     * Notifies all listeners that have registered interest for
1432     * notification on this event type.
1433     *
1434     * @param event a <code>MenuKeyEvent</code>
1435     * @see EventListenerList
1436     */

1437    private void fireMenuKeyTyped(MenuKeyEvent event) {
1438        Object JavaDoc[] listeners = listenerList.getListenerList();
1439        for (int i = listeners.length-2; i>=0; i-=2) {
1440            if (listeners[i]==MenuKeyListener.class) {
1441                ((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
1442            }
1443        }
1444    }
1445
1446    /**
1447     * Messaged when the menubar selection changes to activate or
1448     * deactivate this menu. This implements the
1449     * <code>javax.swing.MenuElement</code> interface.
1450     * Overrides <code>MenuElement.menuSelectionChanged</code>.
1451     *
1452     * @param isIncluded true if this menu is active, false if
1453     * it is not
1454     * @see MenuElement#menuSelectionChanged(boolean)
1455     */

1456    public void menuSelectionChanged(boolean isIncluded) {
1457    if (DEBUG) {
1458        System.out.println("In JPopupMenu.menuSelectionChanged " + isIncluded);
1459    }
1460        if(invoker instanceof JMenu JavaDoc) {
1461            JMenu JavaDoc m = (JMenu JavaDoc) invoker;
1462            if(isIncluded)
1463                m.setPopupMenuVisible(true);
1464            else
1465                m.setPopupMenuVisible(false);
1466        }
1467        if (isPopupMenu() && !isIncluded)
1468          setVisible(false);
1469    }
1470
1471    /**
1472     * Returns an array of <code>MenuElement</code>s containing the submenu
1473     * for this menu component. It will only return items conforming to
1474     * the <code>JMenuElement</code> interface.
1475     * If popup menu is <code>null</code> returns
1476     * an empty array. This method is required to conform to the
1477     * <code>MenuElement</code> interface.
1478     *
1479     * @return an array of <code>MenuElement</code> objects
1480     * @see MenuElement#getSubElements
1481     */

1482    public MenuElement JavaDoc[] getSubElements() {
1483        MenuElement JavaDoc result[];
1484        Vector JavaDoc tmp = new Vector JavaDoc();
1485        int c = getComponentCount();
1486        int i;
1487        Component m;
1488
1489        for(i=0 ; i < c ; i++) {
1490            m = getComponent(i);
1491            if(m instanceof MenuElement JavaDoc)
1492                tmp.addElement(m);
1493        }
1494
1495        result = new MenuElement JavaDoc[tmp.size()];
1496        for(i=0,c=tmp.size() ; i < c ; i++)
1497            result[i] = (MenuElement JavaDoc) tmp.elementAt(i);
1498        return result;
1499    }
1500
1501    /**
1502     * Returns this <code>JPopupMenu</code> component.
1503     * @return this <code>JPopupMenu</code> object
1504     * @see MenuElement#getComponent
1505     */

1506    public Component getComponent() {
1507        return this;
1508    }
1509
1510
1511    /**
1512     * A popup menu-specific separator.
1513     */

1514    static public class Separator extends JSeparator JavaDoc
1515    {
1516        public Separator( )
1517    {
1518        super( JSeparator.HORIZONTAL );
1519        }
1520
1521        /**
1522     * Returns the name of the L&F class that renders this component.
1523     *
1524     * @return the string "PopupMenuSeparatorUI"
1525     * @see JComponent#getUIClassID
1526     * @see UIDefaults#getUI
1527     */

1528        public String JavaDoc getUIClassID()
1529    {
1530            return "PopupMenuSeparatorUI";
1531    
1532    }
1533    }
1534    
1535    /**
1536     * Returns true if the <code>MouseEvent</code> is considered a popup trigger
1537     * by the <code>JPopupMenu</code>'s currently installed UI.
1538     *
1539     * @return true if the mouse event is a popup trigger
1540     * @since 1.3
1541     */

1542    public boolean isPopupTrigger(MouseEvent e) {
1543    return getUI().isPopupTrigger(e);
1544    }
1545}
1546
1547
Popular Tags