OSDN Git Service

* javax/naming/CompoundName.java (CompoundName): Don't check for
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / JPopupMenu.java
1 /* JPopupMenu.java
2    Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package javax.swing;
39
40 import java.awt.BorderLayout;
41 import java.awt.Component;
42 import java.awt.Container;
43 import java.awt.Dimension;
44 import java.awt.Frame;
45 import java.awt.Graphics;
46 import java.awt.GridBagConstraints;
47 import java.awt.GridBagLayout;
48 import java.awt.Insets;
49 import java.awt.LayoutManager;
50 import java.awt.Panel;
51 import java.awt.Point;
52 import java.awt.Window;
53 import java.awt.event.KeyEvent;
54 import java.awt.event.MouseEvent;
55 import java.beans.PropertyChangeEvent;
56 import java.beans.PropertyChangeListener;
57 import java.io.IOException;
58 import java.io.ObjectInputStream;
59 import java.io.ObjectOutputStream;
60 import java.util.EventListener;
61 import java.util.Vector;
62 import javax.accessibility.Accessible;
63 import javax.accessibility.AccessibleContext;
64 import javax.accessibility.AccessibleRole;
65 import javax.swing.event.PopupMenuEvent;
66 import javax.swing.event.PopupMenuListener;
67 import javax.swing.plaf.PopupMenuUI;
68
69
70 /**
71  * JPopupMenu is a container that is used to display popup menu's menu
72  * items. By default JPopupMenu is a lightweight container, however if it
73  * is the case that JPopupMenu's bounds are outside of main window, then
74  * heawyweight container will be used to display menu items. It is also
75  * possible to change JPopupMenu's default  behavior and set JPopupMenu
76  * to always use heavyweight container.
77  *
78  * JPopupMenu can be displayed anywhere; it is a floating free popup menu.
79  * However before JPopupMenu is diplayed, its invoker property should be set.
80  * JPopupMenu's invoker is a component relative to which popup menu is
81  * displayed.
82  *
83  * JPopupMenu fires PopupMenuEvents to its registered listeners. Whenever
84  * JPopupMenu becomes visible on the screen then PopupMenuEvent indicating
85  * that popup menu became visible will be fired. In the case when
86  * JPopupMenu becomes invisible or cancelled without selection, then
87  * popupMenuBecomeInvisible() or popupMenuCancelled() methods of
88  * PopupMenuListeners will be invoked.
89  *
90  * JPopupMenu also fires PropertyChangeEvents when its bound properties 
91  * change.In addittion to inheritted bound properties, JPopupMenu has 
92  * 'visible' bound property. When JPopupMenu becomes visible/invisible on
93  * the screen it fires PropertyChangeEvents to its registered 
94  * PropertyChangeListeners.
95  */
96 public class JPopupMenu extends JComponent implements Accessible, MenuElement
97 {
98   private static final long serialVersionUID = -8336996630009646009L;
99
100   /** name for the UI delegate for this menuItem. */
101   private static final String uiClassID = "PopupMenuUI";
102
103   /** Fire a PropertyChangeEvent when the "borderPainted" property changes. */
104   public static final String LABEL_CHANGED_PROPERTY = "label";
105
106   /* indicates if popup's menu border should be painted*/
107   private boolean borderPainted = true;
108
109   /** Flag indicating whether lightweight, mediumweight or heavyweight popup
110      is used to display menu items.
111
112      These are the possible cases:
113
114      1. if DefaultLightWeightPopupEnabled true
115          (i)  use lightweight container if popup feets inside top-level window
116          (ii) only use heavyweight container (JWindow) if popup doesn't fit.
117
118      2. if DefaultLightWeightPopupEnabled false
119          (i) if popup fits, use awt.Panel (mediumWeight)
120          (ii) if popup doesn't fit, use JWindow (heavyWeight)
121   */
122   private static boolean DefaultLightWeightPopupEnabled = true;
123
124   /* Component that invokes popup menu. */
125   transient Component invoker;
126
127   /* Label for this popup menu. It is not used in most of the look and feel themes. */
128   private String label;
129
130   /*Amount of space between menuItem's in JPopupMenu and JPopupMenu's border */
131   private Insets margin;
132
133   /** Indicates whether ligthWeight container can be used to display popup
134      menu. This flag is the same as DefaultLightWeightPopupEnabled, but setting
135      this flag can change popup menu after creation of the object */
136   private boolean lightWeightPopupEnabled;
137
138   /** SelectionModel that keeps track of menu selection. */
139   private SingleSelectionModel selectionModel;
140
141   /* Popup that is used to display JPopupMenu */
142   private transient Popup popup;
143
144   /* Location of the popup */
145   private Point popupLocation;
146
147   /* Field indicating if popup menu is visible or not */
148   private boolean visible = false;
149   
150   /* Bound Property indicating visibility of the popup menu*/
151   public static final String VISIBLE_CHANGED_PROPERTY = "visible";
152
153   /**
154    * Creates a new JPopupMenu object.
155    */
156   public JPopupMenu()
157   {
158     updateUI();
159
160     lightWeightPopupEnabled = DefaultLightWeightPopupEnabled;
161     selectionModel = new DefaultSingleSelectionModel();
162     super.setVisible(false);
163   }
164
165   /**
166    * Creates a new JPopupMenu with specified label
167    *
168    * @param label Label for popup menu.
169    */
170   public JPopupMenu(String label)
171   {
172     setLabel(label);
173   }
174
175   private void readObject(ObjectInputStream stream)
176                    throws IOException, ClassNotFoundException
177   {
178   }
179
180   private void writeObject(ObjectOutputStream stream) throws IOException
181   {
182   }
183
184   /**
185    * Adds given menu item to the popup menu
186    *
187    * @param item menu item to add to the popup menu
188    *
189    * @return menu item that was added to the popup menu
190    */
191   public JMenuItem add(JMenuItem item)
192   {
193     this.insert(item, -1);
194     return item;
195   }
196
197   /**
198    * Constructs menu item with a specified label and adds it to
199    * popup menu
200    *
201    * @param text label for the menu item to be added
202    *
203    * @return constructed menu item that was added to the popup menu
204    */
205   public JMenuItem add(String text)
206   {
207     JMenuItem item = new JMenuItem(text);
208     return add(item);
209   }
210
211   /**
212    * Constructs menu item associated with the specified action
213    * and adds it to the popup menu
214    *
215    * @param action Action for the new menu item
216    *
217    * @return menu item that was added to the menu
218    */
219   public JMenuItem add(Action action)
220   {
221     JMenuItem item = createActionComponent(action);
222
223     if (action != null)
224       action.addPropertyChangeListener(createActionChangeListener(item));
225
226     return add(item);
227   }
228
229   /**
230    * Revomes component at the given index from the menu.
231    *
232    * @param index index of the component that will be removed in the menu
233    */
234   public void remove(int index)
235   {
236     super.remove(index);
237
238     GridBagConstraints constraints = new GridBagConstraints();
239     constraints.fill = GridBagConstraints.BOTH;
240     constraints.weightx = 100.0;
241     constraints.weighty = 100.0;
242
243     Component[] items = getComponents();
244     for (int i = index; i < items.length; i++)
245       {
246         constraints.gridy = i;
247         super.add(items[i], constraints, i);
248       }
249   }
250
251   /**
252    * Create menu item associated with the given action
253    * and inserts it into the popup menu at the specified index
254    *
255    * @param action Action for the new menu item
256    * @param index index in the popup menu at which to insert new menu item.
257    */
258   public void insert(Action action, int index)
259   {
260     JMenuItem item = new JMenuItem(action);
261     this.insert(item, index);
262   }
263
264   /**
265    * Insert given component to the popup menu at the
266    * specified index
267    *
268    * @param component Component to insert
269    * @param index Index at which to insert given component
270    */
271   public void insert(Component component, int index)
272   {
273     GridBagConstraints constraints = new GridBagConstraints();
274     constraints.fill = GridBagConstraints.BOTH;
275     constraints.weightx = 100.0;
276     constraints.weighty = 100.0;
277
278     if (index == -1)
279       index = getComponents().length;
280
281     constraints.gridy = index;
282     super.add(component, constraints, index);
283
284     // need to change constraints for the components that were moved by 1
285     // due to the insertion
286     if (index != -1)
287       {
288         Component[] items = getComponents();
289
290         for (int i = index + 1; i < items.length; i++)
291           {
292             constraints.gridy = i;
293             super.add(items[i], constraints, i);
294           }
295       }
296   }
297
298   /**
299    * Paints popup menu's border if borderPainted is true
300    *
301    * @param graphics graphics context used to paint this popup's menu border.
302    */
303   protected void borderPainted(Graphics graphics)
304   {
305     if (borderPainted)
306       getBorder().paintBorder(this, graphics, 0, 0, getSize(null).width,
307                               getSize(null).height);
308   }
309
310   /**
311    * Returns flag indicating if newly created JPopupMenu will use
312    * heavyweight or lightweight container to display its menu items
313    *
314    * @return true if JPopupMenu will use lightweight container to display
315    * menu items by default, and false otherwise.
316    */
317   public static boolean getDefaultLightWeightPopupEnabled()
318   {
319     return DefaultLightWeightPopupEnabled;
320   }
321
322   /**
323    * Sets whether JPopupMenu should use ligthWeight container to
324    * display it menu items by default
325    *
326    * @param enabled true if JPopupMenu should use lightweight container
327    * for displaying its menu items, and false otherwise.
328    */
329   public static void setDefaultLightWeightPopupEnabled(boolean enabled)
330   {
331     DefaultLightWeightPopupEnabled = enabled;
332   }
333
334   /**
335    * This method returns the UI used to display the JPopupMenu.
336    *
337    * @return The UI used to display the JPopupMenu.
338    */
339   public PopupMenuUI getUI()
340   {
341     return (PopupMenuUI) ui;
342   }
343
344   /**
345    * Set the "UI" property of the menu item, which is a look and feel class
346    * responsible for handling popupMenu's input events and painting it.
347    *
348    * @param ui The new "UI" property
349    */
350   public void setUI(PopupMenuUI ui)
351   {
352     super.setUI(ui);
353   }
354
355   /**
356    * This method sets this menuItem's UI to the UIManager's default for the
357    * current look and feel.
358    */
359   public void updateUI()
360   {
361     setUI((PopupMenuUI) UIManager.getUI(this));
362     invalidate();
363   }
364
365   /**
366    * This method returns a name to identify which look and feel class will be
367    * the UI delegate for the menuItem.
368    *
369    * @return The Look and Feel classID. "PopupMenuUI"
370    */
371   public String getUIClassID()
372   {
373     return "PopupMenuUI";
374   }
375
376   /**
377    * Returns selectionModel used by this popup menu to keep
378    * track of the selection.
379    *
380    * @return popup menu's selection model
381    */
382   public SingleSelectionModel getSelectionModel()
383   {
384     return selectionModel;
385   }
386
387   /**
388    * Sets selection model for this popup menu
389    *
390    * @param model new selection model of this popup menu
391    */
392   public void setSelectionModel(SingleSelectionModel model)
393   {
394     if (selectionModel != model)
395       {
396         SingleSelectionModel oldModel = this.selectionModel;
397       }
398   }
399
400   /**
401    * Creates new menu item associated with a given action.
402    *
403    * @param action Action used to create new menu item
404    *
405    * @return new created menu item associated with a given action.
406    */
407   protected JMenuItem createActionComponent(Action action)
408   {
409     return new JMenuItem(action);
410   }
411
412   /**
413    * Creates PropertyChangeListener that listens to PropertyChangeEvents
414    * occuring in the Action associated with given menu item in this popup menu.
415    *
416    * @param item MenuItem
417    *
418    * @return The PropertyChangeListener
419    */
420   protected PropertyChangeListener createActionChangeListener(JMenuItem item)
421   {
422     return new ActionChangeListener();
423   }
424
425   /**
426    * Returns true if this popup menu will display its menu item in
427    * a lightweight container and false otherwise.
428    *
429    * @return true if this popup menu will display its menu items
430    * in a lightweight container and false otherwise.
431    */
432   public boolean isLightWeightPopupEnabled()
433   {
434     return lightWeightPopupEnabled;
435   }
436
437   /**
438    * DOCUMENT ME!
439    *
440    * @param enabled DOCUMENT ME!
441    */
442   public void setLightWeightPopupEnabled(boolean enabled)
443   {
444     lightWeightPopupEnabled = enabled;
445   }
446
447   /**
448    * Returns label for this popup menu
449    *
450    * @return label for this popup menu
451    */
452   public String getLabel()
453   {
454     return label;
455   }
456
457   /**
458    * Sets label for this popup menu. This method fires PropertyChangeEvent
459    * when the label property is changed. Please note that most
460    * of the Look & Feel will ignore this property.
461    *
462    * @param label label for this popup menu
463    */
464   public void setLabel(String label)
465   {
466     if (label != this.label)
467       {
468         String oldLabel = this.label;
469     this.label = label;
470         firePropertyChange(LABEL_CHANGED_PROPERTY, oldLabel, label);
471       }
472   }
473
474   /**
475    * Adds separator to this popup menu
476    */
477   public void addSeparator()
478   {
479     // insert separator at the end of the list of menu items    
480     this.insert(new Separator(), -1);
481   }
482
483   /**
484    * Adds popupMenuListener to listen for PopupMenuEvents fired
485    * by the JPopupMenu
486    *
487    * @param listener PopupMenuListener to add to JPopupMenu
488    */
489   public void addPopupMenuListener(PopupMenuListener listener)
490   {
491     listenerList.add(PopupMenuListener.class, listener);
492   }
493
494   /**
495    * Removes PopupMenuListener from JPopupMenu's list of listeners
496    *
497    * @param listener PopupMenuListener which needs to be removed
498    */
499   public void removePopupMenuListener(PopupMenuListener listener)
500   {
501     listenerList.remove(PopupMenuListener.class, listener);
502   }
503
504   /**
505    * Returns array of PopupMenuListeners that are listening to JPopupMenu
506    *
507    * @return Array of PopupMenuListeners that are listening to JPopupMenu
508    */
509   public PopupMenuListener[] getPopupMenuListeners()
510   {
511     return ((PopupMenuListener[]) listenerList.getListeners(PopupMenuListener.class));
512   }
513
514   /**
515    * This method calls popupMenuWillBecomeVisible() of popup menu's
516    * PopupMenuListeners. This method is invoked just before popup menu
517    * will appear on the screen.
518    */
519   protected void firePopupMenuWillBecomeVisible()
520   {
521     EventListener[] ll = listenerList.getListeners(PopupMenuListener.class);
522
523     for (int i = 0; i < ll.length; i++)
524       ((PopupMenuListener) ll[i]).popupMenuWillBecomeVisible(new PopupMenuEvent(this));
525   }
526
527   /**
528    * This method calls popupMenuWillBecomeInvisible() of popup
529    * menu's PopupMenuListeners. This method is invoked just before popup
530    * menu will disappear from the screen
531    */
532   protected void firePopupMenuWillBecomeInvisible()
533   {
534     EventListener[] ll = listenerList.getListeners(PopupMenuListener.class);
535
536     for (int i = 0; i < ll.length; i++)
537       ((PopupMenuListener) ll[i]).popupMenuWillBecomeInvisible(new PopupMenuEvent(this));
538   }
539
540   /**
541    * This method calls popupMenuCanceled() of popup menu's PopupMenuListeners.
542    * This method is invoked just before popup menu is cancelled. This happens
543    * when popup menu is closed without selecting any of its menu items. This
544    * usually happens when the top-level window is resized or moved.
545    */
546   protected void firePopupMenuCanceled()
547   {
548     EventListener[] ll = listenerList.getListeners(PopupMenuListener.class);
549
550     for (int i = 0; i < ll.length; i++)
551       ((PopupMenuListener) ll[i]).popupMenuCanceled(new PopupMenuEvent(this));
552   }
553
554   /**
555    * This methods sets popup menu's size to its' preferred size. If the
556    * popup menu's size is previously set it will be ignored.
557    */
558   public void pack()
559   {
560     super.setSize(null);
561   }
562
563   /**
564    * Return visibility of the popup menu
565    *
566    * @return true if popup menu is visible on the screen and false otherwise.
567    */
568   public boolean isVisible()
569   {
570     return visible;
571   }
572
573   /**
574    * Sets visibility property of this popup menu. If the property is
575    * set to true then popup menu will be dispayed and popup menu will
576    * hide itself if visible property is set to false.
577    *
578    * @param visible true if popup menu will become visible and false otherwise.
579    */
580   public void setVisible(boolean visible)
581   {
582     boolean old = isVisible();
583     this.visible = visible;
584     if (old != isVisible())
585       {
586         firePropertyChange(VISIBLE_CHANGED_PROPERTY, old, (boolean) isVisible());
587         if (visible)
588           {
589             firePopupMenuWillBecomeVisible();
590             Container rootContainer = (Container) SwingUtilities.getRoot(invoker);
591
592             boolean fit = true;
593             Dimension size;
594
595             // Determine the size of the popup menu
596             if (this.getSize().width == 0 && this.getSize().width == 0)
597               size = this.getPreferredSize();
598             else
599               size = this.getSize();
600
601             if ((size.width > (rootContainer.getWidth() - popupLocation.x))
602                 || (size.height > (rootContainer.getHeight() - popupLocation.y)))
603               fit = false;
604             if (lightWeightPopupEnabled && fit)
605               popup = new LightWeightPopup(this);
606             else
607               {
608                 if (fit)
609                   popup = new MediumWeightPopup(this);
610                 else
611                   popup = new HeavyWeightPopup(this);
612               }
613             if (popup instanceof LightWeightPopup
614                 || popup instanceof MediumWeightPopup)
615               {
616                 JLayeredPane layeredPane;
617                 layeredPane = SwingUtilities.getRootPane(invoker)
618                                             .getLayeredPane();
619                 Point p = new Point(popupLocation.x, popupLocation.y);
620                 SwingUtilities.convertPointFromScreen(p, layeredPane);
621                 popup.show(p.x, p.y, size.width, size.height);  
622               }
623             else
624               {
625                 // Subtract insets of the top-level container if popup menu's
626                 // top-left corner is inside it.
627                     Insets insets = rootContainer.getInsets();
628                     popup.show(popupLocation.x - insets.left,
629                                popupLocation.y - insets.top, size.width,
630                                size.height);
631                   }
632           }
633         else
634           {
635             firePopupMenuWillBecomeInvisible();
636             popup.hide();
637           }
638       }
639   }
640
641   /**
642    * Sets location of the popup menu.
643    *
644    * @param x X coordinate of the popup menu's location
645    * @param y Y coordinate of the popup menu's location
646    */
647   public void setLocation(int x, int y)
648   {
649     if (popupLocation == null)
650       popupLocation = new Point();
651
652     popupLocation.x = x;
653     popupLocation.y = y;
654   }
655
656   /**
657    * Returns popup menu's invoker.
658    *
659    * @return popup menu's invoker
660    */
661   public Component getInvoker()
662   {
663     return invoker;
664   }
665
666   /**
667    * Sets popup menu's invoker.
668    *
669    * @param component The new invoker of this popup menu
670    */
671   public void setInvoker(Component component)
672   {
673     invoker = component;
674   }
675
676   /**
677    * This method displays JPopupMenu on the screen at the specified
678    * location. Note that x and y coordinates given to this method
679    * should be expressed in terms of the popup menus' invoker.
680    *
681    * @param component Invoker for this popup menu
682    * @param x x-coordinate of the popup menu relative to the specified invoker
683    * @param y y-coordiate of the popup menu relative to the specified invoker
684    */
685   public void show(Component component, int x, int y)
686   {
687     setInvoker(component);
688     Point p = new Point(x, y);
689     SwingUtilities.convertPointToScreen(p, component);
690     setLocation(p.x, p.y);
691     setVisible(true);
692   }
693
694   /**
695    * Returns component located at the specified index in the popup menu
696    *
697    * @param index index of the component to return
698    *
699    * @return component located at the specified index in the popup menu
700    *
701    * @deprecated Replaced by getComponent(int)
702    */
703   public Component getComponentAtIndex(int index)
704   {
705     return getComponent(index);
706   }
707
708   /**
709    * Returns index of the specified component in the popup menu
710    *
711    * @param component Component to look for
712    *
713    * @return index of the specified component in the popup menu
714    */
715   public int getComponentIndex(Component component)
716   {
717     Component[] items = getComponents();
718
719     for (int i = 0; i < items.length; i++)
720       {
721         if (items[i].equals(component))
722           return i;
723       }
724
725     return -1;
726   }
727
728   /**
729    * Sets size of the popup
730    *
731    * @param size Dimensions representing new size of the popup menu
732    */
733   public void setPopupSize(Dimension size)
734   {
735     super.setSize(size);
736   }
737
738   /**
739    * Sets size of the popup menu
740    *
741    * @param width width for the new size
742    * @param height height for the new size
743    */
744   public void setPopupSize(int width, int height)
745   {
746     super.setSize(width, height);
747   }
748
749   /**
750    * Selects specified component in this popup menu.
751    *
752    * @param selected component to select
753    */
754   public void setSelected(Component selected)
755   {
756     int index = getComponentIndex(selected);
757     selectionModel.setSelectedIndex(index);
758   }
759
760   /**
761    * Checks if this popup menu paints its border.
762    *
763    * @return true if this popup menu paints its border and false otherwise.
764    */
765   public boolean isBorderPainted()
766   {
767     return borderPainted;
768   }
769
770   /**
771    * Sets if the border of the popup menu should be
772    * painter or not.
773    *
774    * @param painted true if the border should be painted and false otherwise
775    */
776   public void setBorderPainted(boolean painted)
777   {
778     borderPainted = painted;
779   }
780
781   /**
782    * Returns margin for this popup menu.
783    *
784    * @return margin for this popup menu.
785    */
786   public Insets getMargin()
787   {
788     return margin;
789   }
790
791   /**
792    * A string that describes this JPopupMenu. Normally only used
793    * for debugging.
794    *
795    * @return A string describing this JMenuItem
796    */
797   protected String paramString()
798   {
799     return "JPopupMenu";
800   }
801
802   /**
803   * Process mouse events forwarded from MenuSelectionManager. This method 
804   * doesn't do anything. It is here to conform to the MenuElement interface.
805   *
806   * @param event event forwarded from MenuSelectionManager
807   * @param path path to the menu element from which event was generated
808   * @param manager MenuSelectionManager for the current menu hierarchy
809   */
810   public void processMouseEvent(MouseEvent event, MenuElement[] path,
811                                 MenuSelectionManager manager)
812   {
813     // Empty Implementation. This method is needed for the implementation
814     // of MenuElement interface
815   }
816
817   /**
818    * Process key events forwarded from MenuSelectionManager. This method
819    * doesn't do anything. It is here to conform to the MenuElement interface.
820    *
821    * @param event event forwarded from MenuSelectionManager
822    * @param path path to the menu element from which event was generated
823    * @param manager MenuSelectionManager for the current menu hierarchy
824    *
825    */
826   public void processKeyEvent(KeyEvent event, MenuElement[] path,
827                               MenuSelectionManager manager)
828   {
829     // Empty Implementation. This method is needed for the implementation
830     // of MenuElement interface
831   }
832
833   /**
834    * Method of MenuElement Interface. It is invoked when
835    * popupMenu's selection has changed
836    *
837    * @param changed true if this popupMenu is part of current menu
838    * hierarchy and false otherwise.
839    */
840   public void menuSelectionChanged(boolean changed)
841   {
842     if (! changed)
843       setVisible(false);
844   }
845
846   /**
847    * Return subcomonents of this popup menu.
848    *
849    * @return Array containing menuItem's of belonging to this popup menu.
850    */
851   public MenuElement[] getSubElements()
852   {
853     Component[] items = getComponents();
854     MenuElement[] subElements = new MenuElement[items.length];
855
856     for (int i = 0; i < items.length; i++)
857       subElements[i] = (MenuElement) items[i];
858
859     return subElements;
860   }
861
862   /**
863    * Method of the MenuElement interface. Returns reference to itself.
864    *
865    * @return Returns reference to itself
866    */
867   public Component getComponent()
868   {
869     return this;
870   }
871
872   /**
873    * Checks if observing mouse event should trigger popup
874    * menu to show on the screen.
875    *
876    * @param event MouseEvent to check
877    *
878    * @return true if the observing mouse event is popup trigger and false otherwise
879    */
880   public boolean isPopupTrigger(MouseEvent event)
881   {
882     return ((PopupMenuUI) getUI()).isPopupTrigger(event);
883   }
884
885   /**
886    * DOCUMENT ME!
887    *
888    * @return DOCUMENT ME!
889    */
890   public AccessibleContext getAccessibleContext()
891   {
892     if (accessibleContext == null)
893       accessibleContext = new AccessibleJPopupMenu();
894
895     return accessibleContext;
896   }
897
898   /**
899    * This interface is used to display menu items of the JPopupMenu
900    */
901   private interface Popup
902   {
903     /**
904      * Displays container on the screen
905      *
906      * @param x x-coordinate of popup menu's location on the screen
907      * @param y y-coordinate of popup menu's location on the screen
908      * @param width width of the container that is used to display menu
909      * item's for popup menu
910      * @param height height of the container that is used to display menu
911      * item's for popup menu
912      */
913     void show(int x, int y, int width, int height);
914
915     /**
916      * Hides container used to display popup menu item's from the screen
917      */
918     void hide();
919   }
920
921   /**
922    * This class represents Popup menu that uses light weight container
923    * to display its contents.
924    */
925   private class LightWeightPopup extends Container implements Popup
926   {
927     /**
928      * Creates a new LightWeightPopup menu
929      *
930      * @param c Container containing menu items
931      */
932     private Component c;
933
934     public LightWeightPopup(Container c)
935     {
936       this.c = c;
937     }
938
939     /**
940      * Displayes lightweight container with menu items to the screen
941      *
942      * @param x x-coordinate of lightweight container on the screen
943      * @param y y-coordinate of lightweight container on the screen
944      * @param width width of the lightweight container
945      * @param height height of the lightweight container
946      */
947     public void show(int x, int y, int width, int height)
948     {
949       JLayeredPane layeredPane;
950       layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane();
951       c.setBounds(x, y, width, height);
952       layeredPane.add(c, JLayeredPane.POPUP_LAYER, 0);
953     }
954
955     /**
956      * Hides lightweight container from the screen
957      */
958     public void hide()
959     {
960       // FIXME: Right now the lightweight container is removed from JLayered
961       // pane. It is probably would be better in order to improve performance
962       // to make the container invisible instead of removing it everytime.
963       JLayeredPane layeredPane;
964       layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane();
965       int index = layeredPane.getIndexOf(c);
966       layeredPane.remove(index);
967     }
968   }
969
970   /**
971    * MediumWeightPopup is an AWT Panel with JPopupMenu's menu items.
972    * It is used to display JPopupMenu's menu items on the screen
973    */
974   private class MediumWeightPopup extends Panel implements Popup
975   {
976     /**
977      * Creates a new MediumWeightPopup object.
978      *
979      * @param c Container with JPopupMenu's menu items
980      */
981     public MediumWeightPopup(Container c)
982     {
983       this.add(c);
984     }
985
986     /**
987      * Displays AWT Panel with its components on the screen
988      *
989      * @param x x-coordinate of the upper-left corner of the panel's
990      * @param y y-coordinate of the upper-left corner of the panel's
991      * @param width width of the panel
992      * @param height height of the panel
993      */
994     public void show(int x, int y, int width, int height)
995     {
996       JLayeredPane layeredPane;
997       layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane();
998       layeredPane.add(this, JLayeredPane.POPUP_LAYER, 0);
999       this.setBounds(x, y, width, height);
1000     }
1001
1002     /**
1003      * Hides This panel from the screen
1004      */
1005     public void hide()
1006     {
1007       // FIXME: Right now the lightweight container is removed from JLayered
1008       // pane. It is probably would be better in order to improve performance
1009       // to make the container invisible instead of removing it everytime.
1010       JLayeredPane layeredPane;
1011       layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane();
1012       int index = layeredPane.getIndexOf(this);
1013       layeredPane.remove(index);
1014     }
1015   }
1016
1017   /**
1018    * HeavyWeightPopup is JWindow that is used to display JPopupMenu menu item's
1019    * on the screen
1020    */
1021   private class HeavyWeightPopup extends JWindow implements Popup
1022   {
1023     /**
1024      * Creates a new HeavyWeightPopup object.
1025      *
1026      * @param c Container containing menu items
1027      */
1028     public HeavyWeightPopup(Container c)
1029     {
1030       this.setContentPane(c);
1031     }
1032
1033     /**
1034      * Displays JWindow container JPopupMenu's menu items to the screen
1035      *
1036      * @param x x-coordinate of JWindow containing menu items
1037      * @param y y-coordinate of JWindow containing menu items
1038      * @param width width of the JWindow
1039      * @param height height of the JWindow
1040      */
1041     public void show(int x, int y, int width, int height)
1042     {
1043       this.setBounds(x, y, width, height);
1044       this.show();
1045     }
1046
1047     /**
1048      * Hides JWindow with menu item's from the screen.
1049      */
1050     public void hide()
1051     {
1052       super.hide();
1053     }
1054   }
1055
1056   /**
1057    * This is the separator that can be used in popup menu.
1058    */
1059   public static class Separator extends JSeparator
1060   {
1061     public Separator()
1062     {
1063     }
1064
1065     public String getUIClassID()
1066     {
1067       return "PopupMenuSeparatorUI";
1068     }
1069   }
1070
1071   protected class AccessibleJPopupMenu extends AccessibleJComponent
1072   {
1073     private static final long serialVersionUID = 7423261328879849768L;
1074
1075     protected AccessibleJPopupMenu()
1076     {
1077     }
1078
1079     public AccessibleRole getAccessibleRole()
1080     {
1081       return AccessibleRole.POPUP_MENU;
1082     }
1083   }
1084
1085   /* This class resizes popup menu and repaints popup menu appropriately if one
1086    of item's action has changed */
1087   protected class ActionChangeListener implements PropertyChangeListener
1088   {
1089     public void propertyChange(PropertyChangeEvent evt)
1090     {
1091       JPopupMenu.this.revalidate();
1092       JPopupMenu.this.repaint();
1093     }
1094   }
1095 }