home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / JPopupMenu.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  66.2 KB  |  2,118 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)JPopupMenu.java    1.117 98/08/28
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package javax.swing;
  16.  
  17. import java.awt.*;
  18. import java.awt.event.*;
  19. import java.io.IOException;
  20. import java.io.ObjectInputStream;
  21. import java.io.ObjectOutputStream;
  22. import java.io.Serializable;
  23. import java.beans.*;
  24.  
  25. import java.util.Locale;
  26. import java.util.Vector;
  27. import java.util.Hashtable;
  28. import javax.accessibility.*;
  29. import javax.swing.plaf.PopupMenuUI;
  30. import javax.swing.plaf.ComponentUI;
  31. import javax.swing.event.*;
  32.  
  33. import java.applet.Applet;
  34.  
  35. /**
  36.  * An implementation of a Popup Menu -- a small window which pops up
  37.  * and displays a series of choices. A JPopupMenu is used for the
  38.  * menu that appears when the user selects an item on the menu bar.
  39.  * It is also used for "pull-right" menu that appears when the
  40.  * selects a menu item that activates it. Finally, a JPopupMenu
  41.  * can also be used anywhere else you want a menu to appear -- for
  42.  * example, when the user right-clicks in a specified area.
  43.  * <p>
  44.  * For the keyboard keys used by this component in the standard Look and
  45.  * Feel (L&F) renditions, see the
  46.  * <a href="doc-files/Key-Index.html#JPopupMenu">JPopupMenu</a> key assignments.
  47.  * <p>
  48.  * <strong>Warning:</strong>
  49.  * Serialized objects of this class will not be compatible with 
  50.  * future Swing releases.  The current serialization support is appropriate
  51.  * for short term storage or RMI between applications running the same
  52.  * version of Swing.  A future release of Swing will provide support for
  53.  * long term persistence.
  54.  *
  55.  * @version 1.117 08/28/98
  56.  * @author Georges Saab
  57.  * @author David Karlton
  58.  * @author Arnaud Weber
  59.  */
  60. public class JPopupMenu extends JComponent implements Accessible,MenuElement {
  61.  
  62.     /**
  63.      * @see #getUIClassID
  64.      * @see #readObject
  65.      */
  66.     private static final String uiClassID = "PopupMenuUI";
  67.  
  68.     transient  Component invoker;
  69.     transient  Popup popup;
  70.     transient  Frame frame;
  71.     private    String     label                   = null;
  72.     private    boolean   paintBorder              = true;  
  73.     private    Insets    margin                   = null;
  74.     private    int desiredLocationX,desiredLocationY;
  75.     private    int lastPopupType = LIGHT_WEIGHT_POPUP;
  76.  
  77.     private static final Object heavyPopupCacheKey = 
  78.         new StringBuffer("JPopupMenu.heavyPopupCache");
  79.     private static final Object lightPopupCacheKey = 
  80.         new StringBuffer("JPopupMenu.lightPopupCache");
  81.     private static final Object mediumPopupCacheKey = 
  82.         new StringBuffer("JPopupMenu.mediumPopupCache");
  83.     private static final Object defaultLWPopupEnabledKey = 
  84.         new StringBuffer("JPopupMenu.defaultLWPopupEnabledKey");
  85.  
  86.     private static final int MAX_CACHE_SIZE = 5;
  87.     private boolean lightWeightPopupEnabled = true;
  88.  
  89.     /** A light weight popup is used when it fits and light weight popups are enabled **/
  90.     private static final int LIGHT_WEIGHT_POPUP   = 0;
  91.  
  92.     /** A "Medium weight" popup is a panel. We use this when downgrading an heavy weight in
  93.      *  dialogs
  94.      */
  95.     private static final int MEDIUM_WEIGHT_POPUP  = 1;
  96.  
  97.     /** A popup implemented with a window */
  98.     private static final int HEAVY_WEIGHT_POPUP   = 2;
  99.  
  100.     /*
  101.      * Model for the selected subcontrol
  102.      */
  103.     private SingleSelectionModel selectionModel;
  104.  
  105.     /* Registry of listeners created for Action-JMenuItem
  106.      * linkage.  This is needed so that references can
  107.      * be cleaned up at remove time to allow GC.
  108.      */
  109.     private static Hashtable listenerRegistry = null;
  110.  
  111.     /**
  112.      *  Set the default value for the <b>lightWeightPopupEnabled</b>
  113.      *  property.
  114.      */
  115.     /* Pending(arnaud) this property should scope to awt-context */
  116.     public static void setDefaultLightWeightPopupEnabled(boolean aFlag) {
  117.         SwingUtilities.appContextPut(defaultLWPopupEnabledKey, 
  118.                                      new Boolean(aFlag));
  119.     }
  120.  
  121.     /** 
  122.      *  Return the default value for the <b>lightWeightPopupEnabled</b> 
  123.      *  property.
  124.      */
  125.     public static boolean getDefaultLightWeightPopupEnabled() {
  126.         Boolean b = (Boolean)
  127.             SwingUtilities.appContextGet(defaultLWPopupEnabledKey);
  128.         if (b == null) {
  129.             SwingUtilities.appContextPut(defaultLWPopupEnabledKey, 
  130.                                          Boolean.TRUE);
  131.             return true;
  132.         }
  133.         return b.booleanValue();
  134.     }
  135.  
  136.     private static Hashtable getHeavyPopupCache() {
  137.         Hashtable cache = 
  138.             (Hashtable)SwingUtilities.appContextGet(heavyPopupCacheKey);
  139.         if (cache == null) {
  140.             cache = new Hashtable(2);
  141.             SwingUtilities.appContextPut(heavyPopupCacheKey, cache);
  142.         }
  143.         return cache;
  144.     }
  145.  
  146.     private static Vector getLightPopupCache() {
  147.         Vector cache = 
  148.             (Vector)SwingUtilities.appContextGet(lightPopupCacheKey);
  149.         if (cache == null) {
  150.             cache = new Vector();
  151.             SwingUtilities.appContextPut(lightPopupCacheKey, cache);
  152.         }
  153.         return cache;
  154.     }
  155.  
  156.     private static Vector getMediumPopupCache() {
  157.         Vector cache = 
  158.             (Vector)SwingUtilities.appContextGet(mediumPopupCacheKey);
  159.         if (cache == null) {
  160.             cache = new Vector();
  161.             SwingUtilities.appContextPut(mediumPopupCacheKey, cache);
  162.         }
  163.         return cache;
  164.     }
  165.  
  166.     static synchronized void recycleHeavyPopup(Popup aPopup) {
  167.         Vector cache;
  168.         final Frame  f = getFrame((Component)aPopup);
  169.         Hashtable heavyPopupCache = getHeavyPopupCache();
  170.         if (heavyPopupCache.containsKey(f)) {
  171.             cache = (Vector)heavyPopupCache.get(f);
  172.         } else {
  173.             cache = new Vector();
  174.             heavyPopupCache.put(f, cache);
  175.             // Clean up if the Frame is closed
  176.             f.addWindowListener(new WindowAdapter() {
  177.                 public void windowClosed(WindowEvent e) {
  178.                     Hashtable heavyPopupCache2 = getHeavyPopupCache();
  179.                     heavyPopupCache2.remove(f);
  180.                 }
  181.             });
  182.         }
  183.         
  184.         if(cache.size() < MAX_CACHE_SIZE) 
  185.             cache.addElement(aPopup);
  186.     }
  187.  
  188.     static synchronized Popup getRecycledHeavyPopup(Frame f) {
  189.         Vector cache;
  190.         Hashtable heavyPopupCache = getHeavyPopupCache();
  191.         if (heavyPopupCache.containsKey(f)) {
  192.             cache = (Vector)heavyPopupCache.get(f);
  193.         } else {
  194.             return null;
  195.         }
  196.         int c;
  197.         if((c=cache.size()) > 0) {
  198.             Popup r = (Popup)cache.elementAt(0);
  199.             cache.removeElementAt(0);
  200.             return r;
  201.         }
  202.         return null;
  203.     }
  204.  
  205.     
  206.     static synchronized void recycleLightPopup(Popup aPopup) {
  207.         Vector lightPopupCache = getLightPopupCache();
  208.         if(lightPopupCache.size() < MAX_CACHE_SIZE) 
  209.             lightPopupCache.addElement(aPopup);
  210.     }
  211.  
  212.     static synchronized Popup getRecycledLightPopup() {
  213.         Vector lightPopupCache = getLightPopupCache();
  214.         int c;
  215.         if((c=lightPopupCache.size()) > 0) {
  216.             Popup r = (Popup)lightPopupCache.elementAt(0);
  217.             lightPopupCache.removeElementAt(0);
  218.             return r;
  219.         }
  220.         return null;
  221.     }
  222.  
  223.     
  224.     static synchronized void recycleMediumPopup(Popup aPopup) {
  225.         Vector mediumPopupCache = getMediumPopupCache();
  226.         if(mediumPopupCache.size() < MAX_CACHE_SIZE) 
  227.             mediumPopupCache.addElement(aPopup);
  228.     }
  229.  
  230.     static synchronized Popup getRecycledMediumPopup() {
  231.         Vector mediumPopupCache = getMediumPopupCache();
  232.         int c;
  233.         if((c=mediumPopupCache.size()) > 0) {
  234.             Popup r = (Popup)mediumPopupCache.elementAt(0);
  235.             mediumPopupCache.removeElementAt(0);
  236.             return r;
  237.         }
  238.         return null;
  239.     }
  240.     
  241.  
  242.     static void recyclePopup(Popup aPopup) {
  243.         if(aPopup instanceof JPanelPopup)
  244.             recycleLightPopup(aPopup);
  245.         else if(aPopup instanceof WindowPopup) 
  246.             recycleHeavyPopup(aPopup);
  247.         else if(aPopup instanceof PanelPopup) 
  248.             recycleMediumPopup(aPopup);
  249.     }
  250.     /**
  251.      * Create a JPopupMenu without an "invoker".
  252.      */
  253.     public JPopupMenu() {
  254.         this(null);
  255.     }
  256.  
  257.     /**
  258.      * Create a JPopupMenu with the specified title.
  259.      *
  260.      * @param label  The string that a UI may use to display as a title 
  261.      * for the popup menu.
  262.      */
  263.     public JPopupMenu(String label) {
  264.         this.label = label;
  265.         this.lightWeightPopupEnabled = JPopupMenu.getDefaultLightWeightPopupEnabled();
  266.         setSelectionModel(new DefaultSingleSelectionModel());
  267.         addMouseListener(new MouseAdapter() {});
  268.         updateUI();
  269.     }
  270.  
  271.  
  272.  
  273.     /**
  274.      * Returns the L&F object that renders this component.
  275.      *
  276.      * @return the PopupMenuUI object that renders this component
  277.      */
  278.     public PopupMenuUI getUI() {
  279.         return (PopupMenuUI)ui;
  280.     }
  281.     
  282.     /**
  283.      * Sets the L&F object that renders this component.
  284.      *
  285.      * @param ui the new PopupMenuUI L&F object
  286.      * @see UIDefaults#getUI
  287.      * @beaninfo
  288.      * description: The popup menu UI delegate
  289.      *       bound: true
  290.      *      expert: true
  291.      *      hidden: true
  292.      */
  293.     public void setUI(PopupMenuUI ui) {
  294.         super.setUI(ui);
  295.     }
  296.     
  297.     /**
  298.      * Notification from the UIFactory that the L&F has changed. 
  299.      * Called to replace the UI with the latest version from the 
  300.      * UIFactory.
  301.      *
  302.      * @see JComponent#updateUI
  303.      */
  304.     public void updateUI() {
  305.         setUI((PopupMenuUI)UIManager.getUI(this));
  306.     }
  307.  
  308.  
  309.     /**
  310.      * Returns the name of the L&F class that renders this component.
  311.      *
  312.      * @return "PopupMenuUI"
  313.      * @see JComponent#getUIClassID
  314.      * @see UIDefaults#getUI
  315.      */
  316.     public String getUIClassID() {
  317.         return uiClassID;
  318.     }
  319.  
  320.  
  321.     /**
  322.      * Returns the model object that handles single selections.
  323.      *
  324.      * @return the SingleSelectionModel in use
  325.      * @see SingleSelectionModel
  326.      */
  327.     public SingleSelectionModel getSelectionModel() {
  328.         return selectionModel;
  329.     }
  330.  
  331.     /**
  332.      * Set the model object to handle single selections.
  333.      *
  334.      * @param model the SingleSelectionModel to use
  335.      * @see SingleSelectionModel
  336.      * @beaninfo
  337.      * description: The selection model for the popup menu
  338.      *      expert: true
  339.      */
  340.     public void setSelectionModel(SingleSelectionModel model) {
  341.         selectionModel = model;
  342.     }
  343.  
  344.     /**
  345.      * Appends the specified menu item to the end of this menu. 
  346.      *
  347.      * @param c the JMenuItem to add
  348.      * @return the JMenuItem added.
  349.      */
  350.     public JMenuItem add(JMenuItem menuItem) {
  351.         super.add(menuItem);
  352.         return menuItem;
  353.     }
  354.  
  355.     /**
  356.      * Creates a new menuitem with the specified text and appends
  357.      * it to the end of this menu.
  358.      *  
  359.      * @param s the string for the menuitem to be added
  360.      */
  361.     public JMenuItem add(String s) {
  362.         return add(new JMenuItem(s));
  363.     }
  364.  
  365.     /**
  366.      * Append a new menuitem to the end of the menu which 
  367.      * dispatches the specified Action object.
  368.      *
  369.      * @param a the Action to add to the menu
  370.      * @see Action
  371.      */
  372.     public JMenuItem add(Action a) {
  373.         JMenuItem mi = new JMenuItem((String)a.getValue(Action.NAME),
  374.                                      (Icon)a.getValue(Action.SMALL_ICON));
  375.         mi.setHorizontalTextPosition(JButton.RIGHT);
  376.         mi.setVerticalTextPosition(JButton.CENTER);
  377.         mi.setEnabled(a.isEnabled());
  378.         mi.addActionListener(a);
  379.         add(mi);
  380.         PropertyChangeListener actionPropertyChangeListener = 
  381.             createActionChangeListener(mi);
  382.     if (listenerRegistry == null) {
  383.         listenerRegistry = new Hashtable();
  384.     }
  385.     listenerRegistry.put(mi, a);
  386.     listenerRegistry.put(a, actionPropertyChangeListener);
  387.         a.addPropertyChangeListener(actionPropertyChangeListener);
  388.         return mi;
  389.     }
  390.  
  391.     /**
  392.      * Removes the specified component from this popup menu.
  393.      *
  394.      * @param       item the JMenuItem to be removed from the menu
  395.      */
  396.     public void remove(Component comp) {
  397.     super.remove(comp);
  398.     if (comp instanceof JMenuItem) {
  399.         JMenuItem item = (JMenuItem)comp;
  400.         if (listenerRegistry != null) { 
  401.         ActionChangedListener p = (ActionChangedListener)listenerRegistry.remove(item);
  402.         Action a = (Action)listenerRegistry.remove(p);
  403.         item.removeActionListener(a);
  404.         if (p!=null)
  405.             p.setTarget(null);
  406.         if (a!=null)
  407.             a.removePropertyChangeListener(p);
  408.         }
  409.     }
  410.     }
  411.  
  412.     protected PropertyChangeListener createActionChangeListener(JMenuItem b) {
  413.         return new ActionChangedListener(b);
  414.     }
  415.  
  416.     private class ActionChangedListener implements PropertyChangeListener {
  417.         JMenuItem menuItem;
  418.         
  419.         ActionChangedListener(JMenuItem mi) {
  420.             super();
  421.             setTarget(mi);
  422.         }
  423.         public void propertyChange(PropertyChangeEvent e) {
  424.             String propertyName = e.getPropertyName();
  425.             if (e.getPropertyName().equals(Action.NAME)) {
  426.                 String text = (String) e.getNewValue();
  427.                 menuItem.setText(text);
  428.             } else if (propertyName.equals("enabled")) {
  429.                 Boolean enabledState = (Boolean) e.getNewValue();
  430.                 menuItem.setEnabled(enabledState.booleanValue());
  431.             }
  432.         }
  433.     public void setTarget(JMenuItem b) {
  434.         this.menuItem = b;
  435.     }
  436.     }
  437.  
  438.     /**
  439.      * When displaying the popup, JPopupMenu choose to use a light weight popup if
  440.      * it fits. This method allows you to disable this feature. You have to do disable
  441.      * it if your application mixes light weight and heavy weights components.
  442.      * @beaninfo
  443.      * description: Determines whether lightweight popups are used when possible
  444.      *      expert: true
  445.      */
  446.     public void setLightWeightPopupEnabled(boolean aFlag) {
  447.         lightWeightPopupEnabled = aFlag;
  448.     }
  449.  
  450.     /**
  451.      * Returns true if lightweight (all-Java) popups are in use,
  452.      * or false if heavyweight (native peer) popups are being used.
  453.      *
  454.      * @return true if lightweight popups are in use
  455.      */
  456.     public boolean isLightWeightPopupEnabled() {
  457.         return lightWeightPopupEnabled;
  458.     }
  459.  
  460.     /**
  461.      * Returns the popup menu's label
  462.      * @return a String containing the popup menu's label
  463.      * @see #setLabel
  464.      */
  465.     public String getLabel() {
  466.         return label;
  467.     }
  468.     
  469.     /**
  470.      * Sets the popup menu's label.  Different Look and Feels may choose
  471.      * to display or not display this.
  472.      * @param label a String specifying the label for the popup menu
  473.      * @see #setLabel
  474.      * @beaninfo
  475.      * description: The label for the popup menu. 
  476.      *       bound: true
  477.      */
  478.     public void setLabel(String label) {
  479.         String oldValue = label;
  480.         this.label = label;
  481.         firePropertyChange("label", oldValue, label);
  482.         if (accessibleContext != null) {
  483.             accessibleContext.firePropertyChange(
  484.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  485.                 oldValue, label);
  486.         }
  487.         invalidate();
  488.         repaint();
  489.     }
  490.  
  491.     /**
  492.      * Appends a new separator at the end of the menu.
  493.      */
  494.     public void addSeparator() {
  495.         add( new JPopupMenu.Separator() );
  496.     }
  497.  
  498.     /**
  499.      * Inserts a menu item for the specified Action object at a given
  500.      * position.
  501.      *
  502.      * @param component  the Action object to insert
  503.      * @param index      an int specifying the position at which
  504.      *                   to insert the Action, where 0 is the first
  505.      * @see Action
  506.      */
  507.     public void insert(Action a, int index) {
  508.         throw new Error("void insert(Action, int) {} not yet implemented");
  509.     }
  510.  
  511.     /**
  512.      * Inserts the specified component into the menu at a given
  513.      * position.
  514.      *
  515.      * @param component  the Component to insert
  516.      * @param index      an int specifying the position at which
  517.      *                   to insert the component, where 0 is the first
  518.      */
  519.     public void insert(Component component, int index) {
  520.         if (index < 0) {
  521.             throw new IllegalArgumentException("index less than zero.");
  522.         }
  523.  
  524.         int nitems = getComponentCount();
  525.         Vector tempItems = new Vector();
  526.  
  527.         /* Remove the item at index, nitems-index times 
  528.            storing them in a temporary vector in the
  529.            order they appear on the menu.
  530.            */
  531.         for (int i = index ; i < nitems; i++) {
  532.             tempItems.addElement(getComponent(index));
  533.             remove(index);
  534.         }
  535.  
  536.         add(component);
  537.  
  538.         /* Add the removed items back to the menu, they are
  539.            already in the correct order in the temp vector.
  540.            */
  541.         for (int i = 0; i < tempItems.size()  ; i++) {
  542.             add((Component)tempItems.elementAt(i));
  543.         }
  544.     }
  545.  
  546.     /**
  547.      *  Add a PopupMenu listener
  548.      *
  549.      * param l  the PopupMenuListener to add
  550.      */
  551.     public void addPopupMenuListener(PopupMenuListener l) {
  552.         listenerList.add(PopupMenuListener.class,l);
  553.     }
  554.  
  555.     /**
  556.      * Remove a PopupMenu listener
  557.      *
  558.      * param l  the PopupMenuListener to remove
  559.      */
  560.     public void removePopupMenuListener(PopupMenuListener l) {
  561.         listenerList.remove(PopupMenuListener.class,l);
  562.     }
  563.  
  564.     /**
  565.      * Notifies PopupMenuListeners that this popup menu will become
  566.      * visible
  567.      */
  568.     protected void firePopupMenuWillBecomeVisible() {
  569.         Object[] listeners = listenerList.getListenerList();
  570.         PopupMenuEvent e=null;
  571.         for (int i = listeners.length-2; i>=0; i-=2) {
  572.             if (listeners[i]==PopupMenuListener.class) {
  573.                 if (e == null)
  574.                     e = new PopupMenuEvent(this);
  575.                 ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeVisible(e);
  576.             }
  577.         }    
  578.     }
  579.     
  580.     /**
  581.      * Notifies PopupMenuListeners that this popup menu will become
  582.      * invisible
  583.      */
  584.     protected void firePopupMenuWillBecomeInvisible() {
  585.         Object[] listeners = listenerList.getListenerList();
  586.         PopupMenuEvent e=null;
  587.         for (int i = listeners.length-2; i>=0; i-=2) {
  588.             if (listeners[i]==PopupMenuListener.class) {
  589.                 if (e == null)
  590.                     e = new PopupMenuEvent(this);
  591.                 ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeInvisible(e);
  592.             }
  593.         }            
  594.     }
  595.     
  596.     /**
  597.      * Notifies PopupMenuListeners that this popup menu is canceled
  598.      */
  599.     protected void firePopupMenuCanceled() {
  600.         Object[] listeners = listenerList.getListenerList();
  601.         PopupMenuEvent e=null;
  602.         for (int i = listeners.length-2; i>=0; i-=2) {
  603.             if (listeners[i]==PopupMenuListener.class) {
  604.                 if (e == null)
  605.                     e = new PopupMenuEvent(this);
  606.                 ((PopupMenuListener)listeners[i+1]).popupMenuCanceled(e);
  607.             }
  608.         }    
  609.     }
  610.  
  611.     /**
  612.      * Always return true since popups, by definition, should always
  613.      * be on top of all other windows.
  614.      */
  615.     // package private
  616.     boolean alwaysOnTop() {
  617.     return true;
  618.     }
  619.  
  620.     /**
  621.      * Layout the container so that it uses the minimum space
  622.      * needed to display its contents.
  623.      */
  624.     public void pack() {
  625.         if(popup != null)
  626.             popup.pack();
  627.     }
  628.  
  629.     private Popup createLightWeightPopup() {
  630.         Popup popup;
  631.         popup = JPopupMenu.getRecycledLightPopup();
  632.         if(popup == null) {
  633.             popup = new JPanelPopup();
  634.         }
  635.         return popup;
  636.     }
  637.     
  638.     private Popup createMediumWeightPopup() {
  639.         Popup popup;
  640.         popup = JPopupMenu.getRecycledMediumPopup();
  641.         if(popup == null) {
  642.             popup = new PanelPopup();
  643.         }
  644.         return popup;
  645.     }
  646.  
  647.     private Popup createHeavyWeightPopup() {
  648.         Frame frame = getFrame(invoker);
  649.  
  650.         if (frame != null) {
  651.             popup = JPopupMenu.getRecycledHeavyPopup(frame);
  652.         } else {
  653.             frame = new Frame();
  654.         }
  655.         if (popup == null)
  656.             popup = new WindowPopup(frame);
  657.  
  658.         return popup;
  659.     }
  660.  
  661.     private boolean popupFit(Rectangle popupRectInScreen) {
  662.         if(invoker != null) {
  663.             Container parent;
  664.             for(parent = invoker.getParent(); parent != null ; parent = parent.getParent()) {
  665.                 if(parent instanceof JFrame || parent instanceof JDialog ||
  666.            parent instanceof JWindow) {
  667.                     return SwingUtilities.isRectangleContainingRectangle(parent.getBounds(),popupRectInScreen);
  668.                 } else if(parent instanceof JApplet) {
  669.                     Rectangle r = parent.getBounds();
  670.                     Point p  = parent.getLocationOnScreen();
  671.  
  672.                     r.x = p.x;
  673.                     r.y = p.y;
  674.                     return SwingUtilities.isRectangleContainingRectangle(r,popupRectInScreen);
  675.                 } else if(parent instanceof java.awt.Frame) {
  676.                     return SwingUtilities.isRectangleContainingRectangle(parent.getBounds(),popupRectInScreen);                    
  677.                 }
  678.             }
  679.         }
  680.         return false;
  681.     }
  682.  
  683.     private boolean ancestorIsModalDialog(Component i) {
  684.         Container parent = null;
  685.     if (i !=null) {
  686.         for(parent = i.getParent() ; parent != null ; parent = parent.getParent())
  687.         if ((parent instanceof Dialog) && (((Dialog)parent).isModal() == true))
  688.             return true;
  689.     }
  690.     return false;
  691.     }
  692.  
  693.     private void replacePopup(int newType) {
  694.         popup.removeComponent(this);
  695.         recyclePopup(popup);
  696.     popup = null;
  697.         switch(newType) {
  698.         case LIGHT_WEIGHT_POPUP:
  699.             popup = createLightWeightPopup();
  700.             break;
  701.         case MEDIUM_WEIGHT_POPUP:
  702.             popup = createMediumWeightPopup();
  703.             break;
  704.         case HEAVY_WEIGHT_POPUP:
  705.             popup = createHeavyWeightPopup();
  706.             break;
  707.         }
  708.  
  709.         popup.setLocationOnScreen(desiredLocationX,desiredLocationY);
  710.         popup.addComponent(this,"Center");
  711.         invalidate();
  712.         popup.setBackground(getBackground());
  713.         popup.pack();
  714.     }
  715.  
  716.     /**
  717.      * Set the visibility of the popup menu.
  718.      * 
  719.      * @param b true to make the popup visible, or false to
  720.      *          hide it
  721.      * @beaninfo
  722.      * description: Makes the popup visible
  723.      */
  724.     public void setVisible(boolean b) {
  725.         // Is it a no-op?
  726.         if (b == isVisible())
  727.             return;
  728.  
  729.         // if closing, first close all Submenus
  730.         if (b == false) {
  731.             getSelectionModel().clearSelection();
  732.         
  733.         } else {
  734.             // This is a popupmenu with MenuElement children,
  735.             // set selection path before popping up!
  736.             if (isPopupMenu()) {
  737.         if (getSubElements().length > 0) {
  738.             MenuElement me[] = new MenuElement[2];
  739.             me[0]=(MenuElement)this;
  740.             me[1]=getSubElements()[0];
  741.             MenuSelectionManager.defaultManager().setSelectedPath(me);
  742.         } else {
  743.             MenuElement me[] = new MenuElement[1];
  744.             me[0]=(MenuElement)this;
  745.             MenuSelectionManager.defaultManager().setSelectedPath(me);
  746.         }
  747.         }
  748.         }
  749.  
  750.         if(b) {
  751.             int popupType;
  752.             int newPopupType;
  753.             boolean shouldDowngradeHeavyWeight = ancestorIsModalDialog(invoker);
  754.  
  755.             firePopupMenuWillBecomeVisible();
  756.             switch(lastPopupType) {
  757.             case LIGHT_WEIGHT_POPUP:
  758.                 popup = createLightWeightPopup();
  759.                 break;
  760.             case MEDIUM_WEIGHT_POPUP:
  761.                 popup = createMediumWeightPopup();
  762.                 break;
  763.             case HEAVY_WEIGHT_POPUP:
  764.                 popup = createHeavyWeightPopup();
  765.                 break;
  766.             }
  767.             popupType = lastPopupType;
  768.  
  769.             popup.setLocationOnScreen(desiredLocationX,desiredLocationY);
  770.             popup.addComponent(this,"Center");
  771.             popup.setBackground(getBackground());
  772.             popup.pack();
  773.  
  774.             Rectangle popupRect = new Rectangle(desiredLocationX,desiredLocationY,
  775.                                                 popup.getWidth(),popup.getHeight());
  776.  
  777.             if(popupFit(popupRect)) {
  778.                 if(lightWeightPopupEnabled)
  779.                     newPopupType = LIGHT_WEIGHT_POPUP;
  780.                 else
  781.                     newPopupType = MEDIUM_WEIGHT_POPUP;
  782.             } else {
  783.                 if(shouldDowngradeHeavyWeight)
  784.                     newPopupType = MEDIUM_WEIGHT_POPUP;
  785.                 else
  786.                     newPopupType = HEAVY_WEIGHT_POPUP;
  787.             }
  788.  
  789.         if(invokerInHeavyWeightPopup(invoker))
  790.         newPopupType = HEAVY_WEIGHT_POPUP;
  791.  
  792.         if(invoker == null) {
  793.         newPopupType = HEAVY_WEIGHT_POPUP;
  794.         }
  795.  
  796.             if(newPopupType != popupType) {
  797.                 replacePopup(newPopupType);
  798.                 popupType = newPopupType;
  799.             }
  800.  
  801.             lastPopupType = popupType;
  802.             popup.show(invoker);
  803.  
  804.         } else if(popup != null) {
  805.             firePopupMenuWillBecomeInvisible();
  806.             popup.hide();
  807.             popup.removeComponent(this);
  808.             recyclePopup(popup);
  809.             popup = null;
  810.         }
  811.         if (accessibleContext != null) {
  812.         if (b) {
  813.         accessibleContext.firePropertyChange(
  814.             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  815.             null, AccessibleState.VISIBLE);
  816.         } else {
  817.         accessibleContext.firePropertyChange(
  818.             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  819.             AccessibleState.VISIBLE, null);
  820.         }
  821.         }
  822.     }
  823.  
  824.     /**
  825.      * Returns true if the popupmenu is visible (currently
  826.      * being displayed).
  827.      */
  828.     public boolean isVisible() {
  829.         if(popup != null)
  830.             return popup.isShowing();
  831.         else
  832.             return false;
  833.     }
  834.  
  835.  
  836.     /**
  837.      * Set the location of the upper left corner of the
  838.      * popup menu using x, y coordinates.
  839.      *
  840.      * @param x the x coordinate of the popup's new position
  841.      * @param y the y coordinate of the popup's new position
  842.      * @beaninfo
  843.      * description: The location of the popup menu.
  844.      */
  845.     public void setLocation(int x, int y) {
  846.         if(popup != null)
  847.             popup.setLocationOnScreen(x, y);
  848.         else {
  849.             desiredLocationX = x;
  850.             desiredLocationY = y;
  851.         }
  852.     }
  853.  
  854.     /**
  855.      * Returns true if the popupmenu is a stand-alone popup menu
  856.      * rather than the submenu of a JMenu.
  857.      *
  858.      * @return true if this menu is a stand-alone popup menu
  859.      */
  860.     private boolean isPopupMenu() {
  861.         return  ((invoker != null) && !(invoker instanceof JMenu));
  862.     }
  863.  
  864.     /**
  865.      * Returns the component which is the 'invoker' of this 
  866.      * popup menu.
  867.      *
  868.      * @return the Component in which the popup menu is displayed
  869.      */
  870.     public Component getInvoker() {
  871.         return this.invoker;
  872.     }
  873.  
  874.     /**
  875.      * Sets the invoker of this popupmenu -- the component in which
  876.      * the popupmenu menu is to be displayed.
  877.      *
  878.      * @param invoker the Component in which the popup menu is displayed
  879.      * @beaninfo
  880.      * description: The invoking component for the popup menu
  881.      *      expert: true
  882.      */
  883.     public void setInvoker(Component invoker) {
  884.         Component oldInvoker = this.invoker;
  885.         this.invoker = invoker;
  886.         if ((oldInvoker != this.invoker) && (ui != null)) {
  887.             ui.uninstallUI(this);
  888.             ui.installUI(this);
  889.         }               
  890.         invalidate();
  891.     }
  892.  
  893.  
  894.     /**
  895.      * Display the popupmenu at the position x,y in the coordinate
  896.      * space of the component invoker.
  897.      *
  898.      * @param invoker The component in whose space the popupmenu is to appear
  899.      * @param x the x coordinate in invoker's coordinate space at which 
  900.      * the popup menu is to be displayed
  901.      * @param y the y coordinate in invoker's coordinate space at which 
  902.      * the popup menu is to be displayed
  903.      */
  904.     public void show(Component invoker, int x, int y) {
  905.         setInvoker(invoker);
  906.         Frame newFrame = getFrame(invoker);
  907.         if (newFrame != frame) {
  908.             // Use the invoker's frame so that events 
  909.             // are propogated properly
  910.             if (newFrame!=null) {
  911.                 this.frame = newFrame;
  912.                 if(popup != null) {
  913.                     setVisible(false);
  914.                 }
  915.             }
  916.         }
  917.     Point invokerOrigin;
  918.     if (invoker != null) {
  919.         invokerOrigin = invoker.getLocationOnScreen();
  920.         setLocation(invokerOrigin.x + x, 
  921.             invokerOrigin.y + y);
  922.     } else {
  923.         setLocation(x, y);
  924.     }
  925.         setVisible(true);       
  926.     }
  927.  
  928.     /**
  929.      * Returns the popupmenu which is at the root of the menu system
  930.      * for this popupmenu.
  931.      *
  932.      * @return the topmost grandparent JPopupMenu
  933.      */
  934.     JPopupMenu getRootPopupMenu() {
  935.         JPopupMenu mp = this;
  936.         while((mp!=null) && (mp.isPopupMenu()!=true) &&
  937.               (mp.getInvoker() != null) &&
  938.               (mp.getInvoker().getParent() != null) &&
  939.               (mp.getInvoker().getParent() instanceof JPopupMenu)
  940.               ) {
  941.             mp = (JPopupMenu) mp.getInvoker().getParent();
  942.         }
  943.         return mp;
  944.     }
  945.  
  946.     /**
  947.      * Returns the index of the specified component.
  948.      * 
  949.      * @param  the Component to find
  950.      * @return the index of the component, where 0 is the first,
  951.      *         or -1 if the component is not found
  952.      */
  953.     public int getComponentIndex(Component c) {
  954.         int ncomponents = this.getComponentCount();
  955.         Component[] component = this.getComponents();
  956.         for (int i = 0 ; i < ncomponents ; i++) {
  957.             Component comp = component[i];
  958.             if (comp == c) 
  959.                 return i;
  960.         }
  961.         return -1;
  962.     }
  963.  
  964.     /**
  965.      * Returns the component at the specified index.
  966.      * 
  967.      * @param i  the index of the component, where 0 is the first 
  968.      * @return the Component at that index 
  969.      */
  970.     public Component getComponentAtIndex(int i) {
  971.         int ncomponents = this.getComponentCount();
  972.         if (i <= ncomponents) {
  973.             Component[] component = this.getComponents();
  974.             return component[i];
  975.         }
  976.         return null;
  977.     }
  978.  
  979.     /**
  980.      * Sets the size of the Popup window using a Dimension object.
  981.      *
  982.      * @param <code>d</code> The dimension specifying the new size 
  983.      * of this component.
  984.      * @beaninfo
  985.      * description: The size of the popup menu
  986.      */
  987.     public void setPopupSize(Dimension d) {
  988.         if(popup != null)
  989.         popup.setSize(d.width,d.height);
  990.     }
  991.  
  992.     /**
  993.      * Sets the size of the Popup window to the specified width and
  994.      * height.
  995.      *
  996.      * @param <code>width</code> The new width of the Popup in pixels.
  997.      * @param <code>height</code> The new height of the Popup in pixels.
  998.      * @beaninfo
  999.      * description: The size of the popup menu
  1000.      */
  1001.     public void setPopupSize(int width, int height) {
  1002.         if(popup != null)
  1003.         popup.setSize(width, height);
  1004.     }
  1005.     
  1006.     /**
  1007.      * Sets the currently selected component,  This will result
  1008.      * in a change to the selection model.
  1009.      *
  1010.      * @param sel the Component to select
  1011.      * @beaninfo
  1012.      * description: The selected component on the popup menu
  1013.      *      expert: true
  1014.      *      hidden: true
  1015.      */
  1016.     public void setSelected(Component sel) {    
  1017.         SingleSelectionModel model = getSelectionModel();
  1018.         int index = getComponentIndex(sel);
  1019.         model.setSelectedIndex(index);
  1020.     }
  1021.  
  1022.     /**
  1023.      * Checks whether the border should be painted.
  1024.      *
  1025.      * @return true if the border is painted
  1026.      * @see #setBorderPainted
  1027.      */
  1028.     public boolean isBorderPainted() {
  1029.         return paintBorder;
  1030.     }
  1031.  
  1032.     /**
  1033.      * Sets whether the border should be painted.
  1034.      *
  1035.      * @param b if true, the border is painted.
  1036.      * @see #isBorderPainted
  1037.      * @beaninfo
  1038.      * description: Is the border of the popup menu painted
  1039.      */
  1040.     public void setBorderPainted(boolean b) {
  1041.         paintBorder = b;
  1042.         repaint();
  1043.     }
  1044.  
  1045.     /**
  1046.      * Paint the popup menu's border if BorderPainted property is true.
  1047.      * 
  1048.      * @see JComponent#paint
  1049.      * @see JComponent#setBorder
  1050.      */
  1051.     protected void paintBorder(Graphics g) {    
  1052.         if (isBorderPainted()) {
  1053.             super.paintBorder(g);
  1054.         }
  1055.     }
  1056.  
  1057.     /**
  1058.      * Returns the margin between the popupmenu's border and
  1059.      * its containees.
  1060.      *
  1061.      * return an Insets object containing the margin values.
  1062.      */
  1063.     public Insets getMargin() {
  1064.         if(margin == null) {
  1065.             return new Insets(0,0,0,0);
  1066.         } else {
  1067.             return margin;
  1068.         }
  1069.     }
  1070.  
  1071.  
  1072.     boolean isSubPopupMenu(JPopupMenu popup) {
  1073.         int ncomponents = this.getComponentCount();
  1074.         Component[] component = this.getComponents();
  1075.         for (int i = 0 ; i < ncomponents ; i++) {
  1076.             Component comp = component[i];
  1077.             if (comp instanceof JMenu) {
  1078.                 JMenu menu = (JMenu)comp;
  1079.                 JPopupMenu subPopup = menu.getPopupMenu();
  1080.                 if (subPopup == popup)
  1081.                     return true;
  1082.                 if (subPopup.isSubPopupMenu(popup))
  1083.                     return true;
  1084.             }
  1085.         }
  1086.         return false;
  1087.     }
  1088.  
  1089.     private boolean invokerInHeavyWeightPopup(Component i) {
  1090.     if (i !=null) {
  1091.         Container parent;
  1092.         for(parent = i.getParent() ; parent != null ; parent =
  1093.             parent.getParent()) {
  1094.         if(parent instanceof WindowPopup)
  1095.             return true;
  1096.         else if(parent instanceof PanelPopup)
  1097.             break;
  1098.         else if(parent instanceof JPanelPopup)
  1099.             break;
  1100.         }
  1101.     }
  1102.         return false;
  1103.     }
  1104.  
  1105.  
  1106.     private static Frame getFrame(Component c) {
  1107.         Component w = c;
  1108.  
  1109.         while(!(w instanceof Frame) && (w!=null)) {
  1110.             w = w.getParent();
  1111.         }
  1112.         return (Frame)w;
  1113.     }
  1114.  
  1115.     /*
  1116.      * The following interface describes what a popup should implement.
  1117.      * We do this because JPopupMenu uses popup that can be windows or
  1118.      * panels. 
  1119.      */
  1120.     private interface Popup {
  1121.         public void setSize(int width,int height);
  1122.         public int  getWidth();
  1123.         public int  getHeight();
  1124.         public void addComponent(Component aComponent,Object constraints);
  1125.         public void removeComponent(Component c);
  1126.         public void pack();
  1127.         public void setBackground(Color c);
  1128.         public void show(Component invoker);
  1129.         public void hide();
  1130.         public boolean isShowing();
  1131.         public Rectangle getBoundsOnScreen();
  1132.         public void setLocationOnScreen(int x,int y);
  1133.         public Component getComponent();
  1134.     }
  1135.  
  1136.   /**
  1137.    * A class used to popup a window.
  1138.    * <p>
  1139.    * <strong>Warning:</strong>
  1140.    * Serialized objects of this class will not be compatible with
  1141.    * future Swing releases.  The current serialization support is appropriate
  1142.    * for short term storage or RMI between applications running the same
  1143.    * version of Swing.  A future release of Swing will provide support for
  1144.    * long term persistence.
  1145.    */
  1146.   class WindowPopup extends JWindow implements Popup,Serializable,Accessible {
  1147.     int saveX,saveY;
  1148.     boolean  firstShow = true;
  1149.  
  1150.     public WindowPopup(Frame f) {
  1151.       super(f);
  1152.     }
  1153.         
  1154.     public Component getComponent() {
  1155.       return this;
  1156.     }
  1157.  
  1158.     public int  getWidth() {
  1159.       return getBounds().width;
  1160.     }
  1161.  
  1162.     public int  getHeight() {
  1163.       return getBounds().height;
  1164.     }
  1165.  
  1166.     public void update(Graphics g) {
  1167.       paint(g);
  1168.     }
  1169.         
  1170.     public void show(Component invoker) {
  1171.       this.setLocation(saveX,saveY);
  1172.       this.setVisible(true);
  1173.  
  1174.       /** This hack is to workaround a bug on Solaris where the windows does not really show
  1175.        *  the first time
  1176.        */
  1177.       if(firstShow) {
  1178.         this.hide();
  1179.         this.setVisible(true);
  1180.         firstShow = false;
  1181.       }
  1182.     }
  1183.         
  1184.     public void hide() {
  1185.       super.hide();
  1186.       /** We need to call removeNotify() here because hide() does something only if
  1187.        *  Component.visible is true. When the app frame is miniaturized, the parent 
  1188.        *  frame of this frame is invisible, causing AWT to believe that this frame
  1189.        *  is invisible and causing hide() to do nothing
  1190.        */
  1191.       removeNotify();
  1192.     }
  1193.  
  1194.     public Rectangle getBoundsOnScreen() {
  1195.       return getBounds();
  1196.     }
  1197.  
  1198.     public void setLocationOnScreen(int x,int y) {
  1199.       this.setLocation(x,y);
  1200.       saveX = x;
  1201.       saveY = y;
  1202.     }
  1203.  
  1204.     public void addComponent(Component aComponent,Object constraints) {
  1205.       this.getContentPane().add(aComponent,constraints);
  1206.     }
  1207.  
  1208.     public void removeComponent(Component c) {
  1209.       this.getContentPane().remove(c);
  1210.     }
  1211.  
  1212.     /////////////////
  1213.     // Accessibility support
  1214.     ////////////////
  1215.  
  1216.     protected AccessibleContext accessibleContext = null;
  1217.     
  1218.     /**
  1219.      * Get the AccessibleContext associated with this JWindow
  1220.      *
  1221.      * @return the AccessibleContext of this JWindow
  1222.      */
  1223.     public AccessibleContext getAccessibleContext() {
  1224.       if (accessibleContext == null) {
  1225.         accessibleContext = new AccessibleWindowPopup();
  1226.       }
  1227.       return accessibleContext;
  1228.     }
  1229.  
  1230.     /**
  1231.      * The class used to obtain the accessible role for this object.
  1232.      * <p>
  1233.      * <strong>Warning:</strong>
  1234.      * Serialized objects of this class will not be compatible with
  1235.      * future Swing releases.  The current serialization support is appropriate
  1236.      * for short term storage or RMI between applications running the same
  1237.      * version of Swing.  A future release of Swing will provide support for
  1238.      * long term persistence.
  1239.      */
  1240.     protected class AccessibleWindowPopup extends AccessibleContext
  1241.     implements Serializable, AccessibleComponent {
  1242.     
  1243.       // AccessibleContext methods
  1244.       //
  1245.       /**
  1246.        * Get the role of this object.
  1247.        *
  1248.        * @return an instance of AccessibleRole describing the role of
  1249.        * the object
  1250.        * @see AccessibleRole
  1251.        */
  1252.       public AccessibleRole getAccessibleRole() {
  1253.         return AccessibleRole.WINDOW;
  1254.       }
  1255.     
  1256.       /**
  1257.        * Get the state of this object.
  1258.        *
  1259.        * @return an instance of AccessibleStateSet containing the 
  1260.        * current state set of the object
  1261.        * @see AccessibleState
  1262.        */
  1263.       public AccessibleStateSet getAccessibleStateSet() {
  1264.         AccessibleStateSet states = SwingUtilities.getAccessibleStateSet(WindowPopup.this);
  1265.         if (getFocusOwner() != null) {
  1266.           states.add(AccessibleState.ACTIVE);
  1267.         }
  1268.         return states;
  1269.       }
  1270.  
  1271.       /**
  1272.        * Get the Accessible parent of this object.  If the parent of this
  1273.        * object implements Accessible, this method should simply return
  1274.        * getParent().
  1275.        *
  1276.        * @return the Accessible parent of this object -- can be null if 
  1277.        * this object does not have an Accessible parent
  1278.        */
  1279.       public Accessible getAccessibleParent() {
  1280.           if (accessibleParent != null) {
  1281.           return accessibleParent;
  1282.       } else {
  1283.               Container parent = getParent();
  1284.               if (parent instanceof Accessible) {
  1285.                   return (Accessible) parent;
  1286.           }
  1287.           }
  1288.           return null;
  1289.       }
  1290.     
  1291.       /**
  1292.        * Get the index of this object in its accessible parent. 
  1293.        *
  1294.        * @return the index of this object in its parent; -1 if this 
  1295.        * object does not have an accessible parent.
  1296.        * @see #getAccessibleParent
  1297.        */
  1298.       public int getAccessibleIndexInParent() {
  1299.         return SwingUtilities.getAccessibleIndexInParent(WindowPopup.this);
  1300.       }
  1301.     
  1302.       /**
  1303.        * Returns the number of accessible children in the object.  If all
  1304.        * of the children of this object implement Accessible, than this
  1305.        * method should return the number of children of this object.
  1306.        *
  1307.        * @return the number of accessible children in the object.
  1308.        */
  1309.       public int getAccessibleChildrenCount() {
  1310.         return SwingUtilities.getAccessibleChildrenCount(WindowPopup.this);
  1311.       }
  1312.     
  1313.       /**
  1314.        * Return the nth Accessible child of the object.  
  1315.        *
  1316.        * @param i zero-based index of child
  1317.        * @return the nth Accessible child of the object
  1318.        */
  1319.       public Accessible getAccessibleChild(int i) {
  1320.         return SwingUtilities.getAccessibleChild(WindowPopup.this,i);
  1321.       }
  1322.     
  1323.       /**
  1324.        * Return the locale of this object.
  1325.        *
  1326.        * @return the locale of this object
  1327.        */
  1328.       public Locale getLocale() {
  1329.         return WindowPopup.this.getLocale();
  1330.       }
  1331.     
  1332.       /**
  1333.        * Get the AccessibleComponent associated with this object if one
  1334.        * exists.  Otherwise return null.
  1335.        */
  1336.       public AccessibleComponent getAccessibleComponent() {
  1337.         return this;
  1338.       }
  1339.     
  1340.     
  1341.       // AccessibleComponent methods
  1342.       //
  1343.             /**
  1344.              * Get the background color of this object.
  1345.              *
  1346.              * @return the background color, if supported, of the object; 
  1347.              * otherwise, null
  1348.              */
  1349.             public Color getBackground() {
  1350.                 return WindowPopup.this.getBackground();
  1351.             }
  1352.     
  1353.             /**
  1354.              * Set the background color of this object.
  1355.              *
  1356.              * @param c the new Color for the background
  1357.              */
  1358.             public void setBackground(Color c) {
  1359.                 WindowPopup.this.setBackground(c);
  1360.             }
  1361.     
  1362.             /**
  1363.              * Get the foreground color of this object.
  1364.              *
  1365.              * @return the foreground color, if supported, of the object; 
  1366.              * otherwise, null
  1367.              */
  1368.             public Color getForeground() {
  1369.                 return WindowPopup.this.getForeground();
  1370.             }
  1371.     
  1372.             /**
  1373.              * Set the foreground color of this object.
  1374.              *
  1375.              * @param c the new Color for the foreground
  1376.              */
  1377.             public void setForeground(Color c) {
  1378.                 WindowPopup.this.setForeground(c);
  1379.             }
  1380.     
  1381.             /**
  1382.              * Get the Cursor of this object.
  1383.              *
  1384.              * @return the Cursor, if supported, of the object; otherwise, null
  1385.              */
  1386.             public Cursor getCursor() {
  1387.                 return WindowPopup.this.getCursor();
  1388.             }
  1389.     
  1390.             /**
  1391.              * Set the Cursor of this object.
  1392.              *
  1393.              * @param c the new Cursor for the object
  1394.              */
  1395.             public void setCursor(Cursor cursor) {
  1396.                 WindowPopup.this.setCursor(cursor);
  1397.             }
  1398.     
  1399.             /**
  1400.              * Get the Font of this object.
  1401.              *
  1402.              * @return the Font,if supported, for the object; otherwise, null
  1403.              */
  1404.             public Font getFont() {
  1405.                 return WindowPopup.this.getFont();
  1406.             }
  1407.     
  1408.             /**
  1409.              * Set the Font of this object.
  1410.              *
  1411.              * @param f the new Font for the object
  1412.              */
  1413.             public void setFont(Font f) {
  1414.                 WindowPopup.this.setFont(f);
  1415.             }
  1416.     
  1417.             /**
  1418.              * Get the FontMetrics of this object.
  1419.              *
  1420.              * @param f the Font
  1421.              * @return the FontMetrics, if supported, the object; 
  1422.              * otherwise, null
  1423.              * @see getFont
  1424.              */
  1425.             public FontMetrics getFontMetrics(Font f) {
  1426.                 return WindowPopup.this.getFontMetrics(f);
  1427.             }
  1428.     
  1429.             /**
  1430.              * Determine if the object is enabled.
  1431.              *
  1432.              * @return true if object is enabled; otherwise, false
  1433.              */
  1434.             public boolean isEnabled() {
  1435.                 return WindowPopup.this.isEnabled();
  1436.             }
  1437.     
  1438.             /**
  1439.              * Set the enabled state of the object.
  1440.              *
  1441.              * @param b if true, enables this object; otherwise, disables it 
  1442.              */
  1443.             public void setEnabled(boolean b) {
  1444.                 WindowPopup.this.setEnabled(b);
  1445.             }
  1446.             
  1447.             /**
  1448.              * Determine if the object is visible.  Note: this means that the
  1449.              * object intends to be visible; however, it may not in fact be
  1450.              * showing on the screen because one of the objects this object
  1451.              * is contained by is not visible.  To determine if an object is
  1452.              * showing on the screen, use isShowing().
  1453.              *
  1454.              * @return true if object is visible; otherwise, false
  1455.              */
  1456.             public boolean isVisible() {
  1457.                 return WindowPopup.this.isVisible();
  1458.             }
  1459.     
  1460.             /**
  1461.              * Set the visible state of the object.
  1462.              *
  1463.              * @param b if true, shows this object; otherwise, hides it 
  1464.              */
  1465.             public void setVisible(boolean b) {
  1466.                 WindowPopup.this.setVisible(b);
  1467.             }
  1468.     
  1469.             /**
  1470.              * Determine if the object is showing.  Determined by checking
  1471.              * the visibility of the object and ancestors of the object.  
  1472.              * This will return true even if the object is obscured by another 
  1473.              * (for example, it is underneath a menu that was pulled 
  1474.              * down).
  1475.              *
  1476.              * @return true if object is showing; otherwise, false
  1477.              */
  1478.             public boolean isShowing() {
  1479.                 return WindowPopup.this.isShowing();
  1480.             }
  1481.     
  1482.             /** 
  1483.              * Checks if the specified point is within this object's bounds,
  1484.              * where the point's x and y coordinates are defined to be relative
  1485.              * to the coordinate system of the object. 
  1486.              *
  1487.              * @param p the Point relative to the coordinate system of the 
  1488.              * object
  1489.              * @return true if object contains Point; otherwise false
  1490.              */
  1491.             public boolean contains(Point p) {
  1492.                 return WindowPopup.this.contains(p);
  1493.             }
  1494.         
  1495.             /** 
  1496.              * Returns the location of the object on the screen.
  1497.              *
  1498.              * @return location of object on screen -- can be null if this
  1499.              * object is not on the screen
  1500.              */
  1501.             public Point getLocationOnScreen() {
  1502.                 return WindowPopup.this.getLocationOnScreen();
  1503.             }
  1504.     
  1505.             /** 
  1506.              * Gets the location of the object relative to the parent in the 
  1507.              * form of a point specifying the object's top-left corner in the
  1508.              * screen's coordinate space.
  1509.              *
  1510.              * @return An instance of Point representing the top-left corner 
  1511.              * of the objects's bounds in the coordinate space of the screen; 
  1512.              * null if this object or its parent are not on the screen
  1513.              */
  1514.             public Point getLocation() {
  1515.                 return WindowPopup.this.getLocation();
  1516.             }
  1517.     
  1518.             /** 
  1519.              * Sets the location of the object relative to the parent.
  1520.              */
  1521.             public void setLocation(Point p) {
  1522.                 WindowPopup.this.setLocation(p);
  1523.             }
  1524.     
  1525.             /** 
  1526.              * Gets the bounds of this object in the form of a Rectangle 
  1527.              * object.  The bounds specify this object's width, height, 
  1528.              * and location relative to its parent. 
  1529.              *
  1530.              * @return A rectangle indicating this component's bounds; null if 
  1531.              * this object is not on the screen.
  1532.              */
  1533.             public Rectangle getBounds() {
  1534.                 return WindowPopup.this.getBounds();
  1535.             }
  1536.     
  1537.             /** 
  1538.              * Sets the bounds of this object in the form of a Rectangle 
  1539.              * object.  The bounds specify this object's width, height, 
  1540.              * and location relative to its parent.
  1541.              *      
  1542.              * @param A rectangle indicating this component's bounds
  1543.              */
  1544.             public void setBounds(Rectangle r) {
  1545.                 WindowPopup.this.setBounds(r);
  1546.             }
  1547.     
  1548.             /** 
  1549.              * Returns the size of this object in the form of a Dimension 
  1550.              * object.  The height field of the Dimension object contains 
  1551.              * this objects's height, and the width field of the Dimension 
  1552.              * object contains this object's width. 
  1553.              *
  1554.              * @return A Dimension object that indicates the size of this 
  1555.              * component; null if this object is not on the screen
  1556.              */
  1557.             public Dimension getSize() {
  1558.                 return WindowPopup.this.getSize();
  1559.             }
  1560.     
  1561.             /** 
  1562.              * Resizes this object so that it has width width and height. 
  1563.              *      
  1564.              * @param d - The dimension specifying the new size of the object. 
  1565.              */
  1566.             public void setSize(Dimension d) {
  1567.                 WindowPopup.this.setSize(d);
  1568.             }
  1569.     
  1570.             /**
  1571.              * Returns the Accessible child, if one exists, contained at the 
  1572.              * local coordinate Point.
  1573.              *
  1574.              * @param p The point defining the top-left corner of the 
  1575.              * Accessible, given in the coordinate space of the object's 
  1576.              * parent. 
  1577.              * @return the Accessible, if it exists, at the specified 
  1578.              * location; else null
  1579.              */
  1580.             public Accessible getAccessibleAt(Point p) {
  1581.                 return SwingUtilities.getAccessibleAt(WindowPopup.this,p);
  1582.             }
  1583.     
  1584.             /**
  1585.              * Returns whether this object can accept focus or not.
  1586.              *
  1587.              * @return true if object can accept focus; otherwise false
  1588.              */
  1589.             public boolean isFocusTraversable() {
  1590.                 return WindowPopup.this.isFocusTraversable();
  1591.             }
  1592.     
  1593.             /**
  1594.              * Requests focus for this object.
  1595.              */
  1596.             public void requestFocus() {
  1597.                 WindowPopup.this.requestFocus();
  1598.             }
  1599.     
  1600.             /**
  1601.              * Adds the specified focus listener to receive focus events from
  1602.              * this component. 
  1603.              *
  1604.              * @param l the focus listener
  1605.              */
  1606.             public void addFocusListener(FocusListener l) {
  1607.                 WindowPopup.this.addFocusListener(l);
  1608.             }
  1609.     
  1610.             /**
  1611.              * Removes the specified focus listener so it no longer receives 
  1612.              * focus events from this component.
  1613.              *
  1614.              * @param l the focus listener
  1615.              */
  1616.             public void removeFocusListener(FocusListener l) {
  1617.                 WindowPopup.this.removeFocusListener(l);
  1618.             }
  1619.         } // inner class AccessibleWindowPopup
  1620.     }
  1621.  
  1622.     /**
  1623.      * A class used to popup a JPanel.
  1624.      * <p>
  1625.      * <strong>Warning:</strong>
  1626.      * Serialized objects of this class will not be compatible with
  1627.      * future Swing releases.  The current serialization support is appropriate
  1628.      * for short term storage or RMI between applications running the same
  1629.      * version of Swing.  A future release of Swing will provide support for
  1630.      * long term persistence.
  1631.      */
  1632.     class JPanelPopup extends JPanel implements Popup,Serializable {
  1633.         int desiredLocationX,desiredLocationY;
  1634.  
  1635.         public JPanelPopup() {
  1636.             super();
  1637.             setLayout(new BorderLayout());
  1638.             setDoubleBuffered(true);
  1639.             this.setOpaque(true);
  1640.         }
  1641.  
  1642.         public Component getComponent() {
  1643.             return this;
  1644.         }
  1645.  
  1646.         public void addComponent(Component aComponent,Object constraints) {
  1647.             this.add(aComponent,constraints);
  1648.         }
  1649.  
  1650.         public void removeComponent(Component c) {
  1651.             this.remove(c);
  1652.         }
  1653.  
  1654.         public void update(Graphics g) {
  1655.             paint(g);
  1656.         }
  1657.         
  1658.         public void pack() {
  1659.             setSize(getPreferredSize());
  1660.         }
  1661.  
  1662.  
  1663.         public void show(Component invoker) {
  1664.         Container parent = null;
  1665.         if (invoker != null)
  1666.         parent = invoker.getParent();
  1667.             Window parentWindow = null;
  1668.  
  1669.             for(Container p = parent; p != null; p = p.getParent()) {
  1670.                 if(p instanceof JRootPane) {
  1671.             if(p.getParent() instanceof JInternalFrame)
  1672.             continue;            
  1673.                     parent = ((JRootPane)p).getLayeredPane();
  1674.                     for(p = parent.getParent(); p != null && !(p instanceof java.awt.Window) ; 
  1675.                         p = p.getParent());
  1676.                     parentWindow = (Window)p;
  1677.                     break;
  1678.                 } else if(p instanceof Window) {
  1679.                     parent = p;
  1680.                     parentWindow = (Window)p;
  1681.                     break;
  1682.                 }
  1683.             }
  1684.             Point p = convertScreenLocationToParent(parent,desiredLocationX,desiredLocationY);
  1685.             this.setLocation(p.x,p.y);
  1686.             if(parent instanceof JLayeredPane) {
  1687.                 ((JLayeredPane)parent).add(this,JLayeredPane.POPUP_LAYER,0);
  1688.             } else
  1689.                 parent.add(this);
  1690.         }
  1691.  
  1692.         public void hide() {
  1693.             Container parent = getParent();
  1694.             Rectangle r = this.getBounds();
  1695.             if(parent != null)
  1696.                 parent.remove(this);
  1697.             parent.repaint(r.x,r.y,r.width,r.height);
  1698.         }
  1699.  
  1700.         public Rectangle getBoundsOnScreen() {
  1701.             Container parent = getParent();
  1702.             if(parent != null) {
  1703.                 Rectangle r = getBounds();
  1704.                 Point p;
  1705.                 p = convertParentLocationToScreen(parent,r.x,r.y);
  1706.                 r.x = p.x;
  1707.                 r.y = p.y;
  1708.                 return r;
  1709.             } else 
  1710.                 throw new Error("getBoundsOnScreen called on an invisible popup");
  1711.         }
  1712.  
  1713.         Point convertParentLocationToScreen(Container parent,int x,int y) {
  1714.             Window parentWindow = null;
  1715.             Rectangle r;
  1716.             Container p;
  1717.             Point pt;
  1718.             for(p = this; p != null; p = p.getParent()) {
  1719.                 if(p instanceof Window) {
  1720.                     parentWindow = (Window)p;
  1721.                     break;
  1722.                 }
  1723.             }
  1724.             if(parentWindow != null) {
  1725.                 r = parentWindow.getBounds();
  1726.                 pt = new Point(x,y);
  1727.                 pt = SwingUtilities.convertPoint(parent,pt,null);
  1728.                 pt.x += r.x;
  1729.                 pt.y += r.y;
  1730.                 return pt;
  1731.             } else
  1732.                 throw new Error("convertParentLocationToScreen: no window ancestor found");                        }
  1733.  
  1734.         Point convertScreenLocationToParent(Container parent,int x,int y) {
  1735.             Window parentWindow = null;
  1736.             Rectangle r;
  1737.             for(Container p = parent; p != null; p = p.getParent()) {
  1738.                 if(p instanceof Window) {
  1739.                     parentWindow = (Window)p;
  1740.                     break;
  1741.                 }
  1742.             }
  1743.             if(parentWindow != null) {
  1744.                 Point p = new Point(x,y);
  1745.                 SwingUtilities.convertPointFromScreen(p,parent);
  1746.                 return p;
  1747.             } else
  1748.                 throw new Error("convertScreenLocationToParent: no window ancestor found");
  1749.         }
  1750.  
  1751.         public void setLocationOnScreen(int x,int y) {
  1752.             Container parent = getParent();
  1753.             if(parent != null) {
  1754.                 Point p = convertScreenLocationToParent(parent,x,y);
  1755.                 this.setLocation(p.x,p.y);
  1756.             } else {
  1757.                 desiredLocationX = x;
  1758.                 desiredLocationY = y;
  1759.             }
  1760.         }
  1761.     }
  1762.  
  1763.     /**
  1764.      * A class used to popup an AWT panel.
  1765.      * <p>
  1766.      * <strong>Warning:</strong>
  1767.      * Serialized objects of this class will not be compatible with
  1768.      * future Swing releases.  The current serialization support is appropriate
  1769.      * for short term storage or RMI between applications running the same
  1770.      * version of Swing.  A future release of Swing will provide support for
  1771.      * long term persistence.
  1772.      */
  1773.     class PanelPopup extends Panel implements Popup,Serializable {
  1774.         int desiredLocationX,desiredLocationY;
  1775.     JRootPane rootPane;
  1776.         public PanelPopup() {
  1777.             super();
  1778.             setLayout(new BorderLayout());
  1779.         rootPane = new JRootPane();
  1780.         this.add(rootPane, BorderLayout.CENTER);
  1781.         }
  1782.  
  1783.         public int getWidth() {
  1784.             return getBounds().width;
  1785.         }
  1786.  
  1787.         public int getHeight() {
  1788.             return getBounds().height;
  1789.         }
  1790.  
  1791.         public Component getComponent() {
  1792.             return this;
  1793.         }
  1794.  
  1795.         public void addComponent(Component aComponent,Object constraints) {
  1796.             rootPane.getContentPane().add(aComponent,constraints);
  1797.         }
  1798.  
  1799.         public void removeComponent(Component c) {
  1800.             rootPane.getContentPane().remove(c);
  1801.         }
  1802.  
  1803.         public void update(Graphics g) {
  1804.         // System.out.println("PanelPopup update " + getLocation());
  1805.             paint(g);
  1806.         }
  1807.         
  1808.         public void paint(Graphics g) {
  1809.         // System.out.println("PanelPopup paint " + getLocation());
  1810.             super.paint(g);
  1811.         }
  1812.         
  1813.         public void pack() {
  1814.             setSize(getPreferredSize());
  1815.         }
  1816.  
  1817.  
  1818.         public void show(Component invoker) {
  1819.         Container parent = null;
  1820.         if (invoker != null)
  1821.         parent = invoker.getParent();
  1822.             Window parentWindow = null;
  1823.         
  1824.             for(Container p = parent; p != null; p = p.getParent()) {
  1825.                 if(p instanceof JRootPane) {
  1826.                     parent = ((JRootPane)p).getLayeredPane();
  1827.                     for(p = parent.getParent(); p != null && !(p instanceof java.awt.Window) ; 
  1828.                         p = p.getParent());
  1829.                     parentWindow = (Window)p;
  1830.                     break;
  1831.                 } else if(p instanceof Window) {
  1832.                     parent = p;
  1833.                     parentWindow = (Window)p;
  1834.                     break;
  1835.                 }
  1836.             }
  1837.             Point p = convertScreenLocationToParent(parent,desiredLocationX,desiredLocationY);
  1838.             this.setLocation(p.x,p.y);
  1839.             if(parent instanceof JLayeredPane) {
  1840.         // System.out.println("PanelPopup added to LayeredPane");
  1841.  
  1842.                 ((JLayeredPane)parent).add(this,JLayeredPane.POPUP_LAYER,0);
  1843.             } else
  1844.                 parent.add(this);
  1845.         }
  1846.  
  1847.         public void hide() {
  1848.         // System.out.println("PanelPopup hide");
  1849.             Container parent = getParent();
  1850.             Rectangle r = this.getBounds();
  1851.             if(parent != null)
  1852.                 parent.remove(this);
  1853.             parent.repaint(r.x,r.y,r.width,r.height);
  1854.         }
  1855.  
  1856.         public Rectangle getBoundsOnScreen() {
  1857.             Container parent = getParent();
  1858.             if(parent != null) {
  1859.                 Rectangle r = getBounds();
  1860.                 Point p;
  1861.                 p = convertParentLocationToScreen(parent,r.x,r.y);
  1862.                 r.x = p.x;
  1863.                 r.y = p.y;
  1864.                 return r;
  1865.             } else 
  1866.                 throw new Error("getBoundsOnScreen called on an invisible popup");
  1867.         }
  1868.  
  1869.         Point convertParentLocationToScreen(Container parent,int x,int y) {
  1870.             Window parentWindow = null;
  1871.             Rectangle r;
  1872.             Container p;
  1873.             Point pt;
  1874.             for(p = this; p != null; p = p.getParent()) {
  1875.                 if(p instanceof Window) {
  1876.                     parentWindow = (Window)p;
  1877.                     break;
  1878.                 }
  1879.             }
  1880.             if(parentWindow != null) {
  1881.                 r = parentWindow.getBounds();
  1882.                 pt = new Point(x,y);
  1883.                 pt = SwingUtilities.convertPoint(parent,pt,null);
  1884.                 pt.x += r.x;
  1885.                 pt.y += r.y;
  1886.                 return pt;
  1887.             } else
  1888.                 throw new Error("convertParentLocationToScreen: no window ancestor found");                        }
  1889.  
  1890.         Point convertScreenLocationToParent(Container parent,int x,int y) {
  1891.             Window parentWindow = null;
  1892.             Rectangle r;
  1893.             for(Container p = parent; p != null; p = p.getParent()) {
  1894.                 if(p instanceof Window) {
  1895.                     parentWindow = (Window)p;
  1896.                     break;
  1897.                 }
  1898.             }
  1899.             if(parentWindow != null) {
  1900.                 Point p = new Point(x,y);
  1901.                 SwingUtilities.convertPointFromScreen(p,parent);
  1902.                 return p;
  1903.             } else
  1904.                 throw new Error("convertScreenLocationToParent: no window ancestor found");
  1905.         }
  1906.  
  1907.         public void setLocationOnScreen(int x,int y) {
  1908.         // System.out.println("PanelPopup set Location on screen");
  1909.             Container parent = getParent();
  1910.             if(parent != null) {
  1911.         // System.out.println("PanelPopup set Location on screen -- parent " + parent);
  1912.                 Point p = convertScreenLocationToParent(parent,x,y);
  1913.                 this.setLocation(p.x,p.y);
  1914.             } else {
  1915.         // System.out.println("PanelPopup set Location on screen -- NULL parent");
  1916.                 desiredLocationX = x;
  1917.                 desiredLocationY = y;
  1918.             }
  1919.         }
  1920.     }
  1921.  
  1922.  
  1923.     /**
  1924.      * Returns a string representation of this JPopupMenu. This method 
  1925.      * is intended to be used only for debugging purposes, and the 
  1926.      * content and format of the returned string may vary between      
  1927.      * implementations. The returned string may be empty but may not 
  1928.      * be <code>null</code>.
  1929.      * <P>
  1930.      * Overriding paramString() to provide information about the
  1931.      * specific new aspects of the JFC components.
  1932.      * 
  1933.      * @return  a string representation of this JPopupMenu.
  1934.      */
  1935.     protected String paramString() {
  1936.     String labelString = (label != null ?
  1937.                   label : "");
  1938.     String paintBorderString = (paintBorder ?
  1939.                     "true" : "false");
  1940.     String marginString = (margin != null ?
  1941.                   margin.toString() : "");
  1942.         String lastPopupTypeString;
  1943.         if (lastPopupType == LIGHT_WEIGHT_POPUP) {
  1944.             lastPopupTypeString = "LIGHT_WEIGHT_POPUP";
  1945.         } else if (lastPopupType == MEDIUM_WEIGHT_POPUP) {
  1946.             lastPopupTypeString = "MEDIUM_WEIGHT_POPUP";
  1947.         } else if (lastPopupType == HEAVY_WEIGHT_POPUP) {
  1948.             lastPopupTypeString = "HEAVY_WEIGHT_POPUP";
  1949.         } else lastPopupTypeString = "";
  1950.     String lightWeightPopupEnabledString = (lightWeightPopupEnabled ?
  1951.                         "true" : "false");
  1952.  
  1953.     return super.paramString() +
  1954.     ",desiredLocationX=" + desiredLocationX +
  1955.     ",desiredLocationY=" + desiredLocationY +
  1956.     ",label=" + labelString +
  1957.     ",lastPopupType=" + lastPopupTypeString +
  1958.     ",lightWeightPopupEnabled=" + lightWeightPopupEnabledString +
  1959.     ",margin=" + marginString +
  1960.     ",paintBorder=" + paintBorderString;
  1961.     }
  1962.  
  1963. /////////////////
  1964. // Accessibility support
  1965. ////////////////
  1966.  
  1967.     /**
  1968.      * Get the AccessibleContext associated with this JComponent
  1969.      *
  1970.      * @return the AccessibleContext of this JComponent
  1971.      */
  1972.     public AccessibleContext getAccessibleContext() {
  1973.         if (accessibleContext == null) {
  1974.             accessibleContext = new AccessibleJPopupMenu();
  1975.         }
  1976.         return accessibleContext;
  1977.     }
  1978.  
  1979.     protected class AccessibleJPopupMenu extends AccessibleJComponent {
  1980.         /**
  1981.          * Get the role of this object.
  1982.          *
  1983.          * @return an instance of AccessibleRole describing the role of 
  1984.          * the object
  1985.          */
  1986.         public AccessibleRole getAccessibleRole() {
  1987.             return AccessibleRole.POPUP_MENU;
  1988.         }
  1989.     } // inner class AccessibleJPopupMenu
  1990.  
  1991.  
  1992. ////////////
  1993. // Serialization support.  
  1994. ////////////
  1995.     private void writeObject(ObjectOutputStream s) throws IOException {
  1996.         Vector      values = new Vector();
  1997.  
  1998.         s.defaultWriteObject();
  1999.         // Save the invoker, if its Serializable.
  2000.         if(invoker != null && invoker instanceof Serializable) {
  2001.             values.addElement("invoker");
  2002.             values.addElement(invoker);
  2003.         }
  2004.         // Save the popup, if its Serializable.
  2005.         if(popup != null && popup instanceof Serializable) {
  2006.             values.addElement("popup");
  2007.             values.addElement(popup);
  2008.         }
  2009.         // Save the frame, if its Serializable.
  2010.         if(frame != null && frame instanceof Serializable) {
  2011.             values.addElement("frame");
  2012.             values.addElement(frame);
  2013.         }
  2014.         s.writeObject(values);
  2015.  
  2016.     if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  2017.         ui.installUI(this);
  2018.     }
  2019.     }
  2020.  
  2021.     // implements javax.swing.MenuElement
  2022.     private void readObject(ObjectInputStream s) 
  2023.         throws IOException, ClassNotFoundException {
  2024.         s.defaultReadObject();
  2025.  
  2026.         Vector          values = (Vector)s.readObject();
  2027.         int             indexCounter = 0;
  2028.         int             maxCounter = values.size();
  2029.  
  2030.         if(indexCounter < maxCounter && values.elementAt(indexCounter).
  2031.            equals("invoker")) {
  2032.             invoker = (Component)values.elementAt(++indexCounter);
  2033.             indexCounter++;
  2034.         }
  2035.         if(indexCounter < maxCounter && values.elementAt(indexCounter).
  2036.            equals("popup")) {
  2037.             popup = (Popup)values.elementAt(++indexCounter);
  2038.             indexCounter++;
  2039.         }
  2040.         if(indexCounter < maxCounter && values.elementAt(indexCounter).
  2041.            equals("frame")) {
  2042.             frame = (Frame)values.elementAt(++indexCounter);
  2043.             indexCounter++;
  2044.         }
  2045.     }
  2046.  
  2047.     
  2048.     // implements javax.swing.MenuElement
  2049.     public void processMouseEvent(MouseEvent event,MenuElement path[],MenuSelectionManager manager) {}
  2050.  
  2051.     // implements javax.swing.MenuElement
  2052.     public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
  2053.     }
  2054.  
  2055.     // implements javax.swing.MenuElement
  2056.     public void menuSelectionChanged(boolean isIncluded) {
  2057.         if(invoker instanceof JMenu) {
  2058.             JMenu m = (JMenu) invoker;
  2059.             if(isIncluded) 
  2060.                 m.setPopupMenuVisible(true);
  2061.             else
  2062.                 m.setPopupMenuVisible(false);
  2063.         }
  2064.         if (isPopupMenu() && !isIncluded)
  2065.           setVisible(false);
  2066.     }
  2067.  
  2068.     // implements javax.swing.MenuElement
  2069.     public MenuElement[] getSubElements() {
  2070.         MenuElement result[];
  2071.         Vector tmp = new Vector();
  2072.         int c = getComponentCount();
  2073.         int i;
  2074.         Component m;
  2075.  
  2076.         for(i=0 ; i < c ; i++) {
  2077.             m = getComponent(i);
  2078.             if(m instanceof MenuElement)
  2079.                 tmp.addElement(m);
  2080.         }
  2081.  
  2082.         result = new MenuElement[tmp.size()];
  2083.         for(i=0,c=tmp.size() ; i < c ; i++) 
  2084.             result[i] = (MenuElement) tmp.elementAt(i);
  2085.         return result;
  2086.     }
  2087.  
  2088.     public Component getComponent() {
  2089.         return this;
  2090.     }
  2091.  
  2092.  
  2093.     /**
  2094.      * A popupmenu-specific separator.
  2095.      */
  2096.     static public class Separator extends JSeparator
  2097.     {
  2098.         public Separator( )
  2099.     {
  2100.         super( JSeparator.HORIZONTAL );
  2101.         }
  2102.  
  2103.         /**
  2104.      * Returns the name of the L&F class that renders this component.
  2105.      *
  2106.      * @return "ToolBarSeparatorUI"
  2107.      * @see JComponent#getUIClassID
  2108.      * @see UIDefaults#getUI
  2109.      */
  2110.         public String getUIClassID()
  2111.     {
  2112.             return "PopupMenuSeparatorUI";
  2113.     }
  2114.     }
  2115.  
  2116. }
  2117.  
  2118.