home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / JPopupMenu.java < prev    next >
Text File  |  1998-02-26  |  68KB  |  2,099 lines

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