/* JMenu.java --
   Copyright (C) 2002, 2004, 2005, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.EventListener;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleSelection;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.plaf.MenuItemUI;

/**
 * This class represents a menu that can be added to a menu bar or
 * can be a submenu in some other menu. When JMenu is selected it
 * displays JPopupMenu containing its menu items.
 *
 * <p>
 * JMenu's fires MenuEvents when this menu's selection changes. If this menu
 * is selected, then fireMenuSelectedEvent() is invoked. In case when menu is
 * deselected or cancelled, then fireMenuDeselectedEvent() or 
 * fireMenuCancelledEvent() is invoked, respectivelly.
 * </p>
 */
public class JMenu extends JMenuItem implements Accessible, MenuElement
{
  /**
   * Receives notifications when the JMenu's ButtonModel is changed and
   * fires menuSelected or menuDeselected events when appropriate.
   */
  private class MenuChangeListener
    implements ChangeListener
  {
    /**
     * Indicates the last selected state.
     */
    private boolean selected;

    /**
     * Receives notification when the JMenu's ButtonModel changes.
     */
    public void stateChanged(ChangeEvent ev)
    {
      ButtonModel m = (ButtonModel) ev.getSource();
      boolean s = m.isSelected();
      if (s != selected)
        {
          if (s)
            fireMenuSelected();
          else
            fireMenuDeselected();
          selected = s;
        }
    }
  }

  private static final long serialVersionUID = 4227225638931828014L;

  /** A Popup menu associated with this menu, which pops up when menu is selected */
  private JPopupMenu popupMenu = null;

  /** Whenever menu is selected or deselected the MenuEvent is fired to
     menu's registered listeners. */
  private MenuEvent menuEvent = new MenuEvent(this);

  /*Amount of time, in milliseconds, that should pass before popupMenu
    associated with this menu appears or disappers */
  private int delay;

  /* PopupListener */
  protected WinListener popupListener;

  /**
   * Location at which popup menu associated with this menu will be
   * displayed
   */
  private Point menuLocation;

  /**
   * The ChangeListener for the ButtonModel.
   *
   * @see MenuChangeListener
   */
  private ChangeListener menuChangeListener;

  /**
   * Creates a new JMenu object.
   */
  public JMenu()
  {
    super();
    setOpaque(false);
  }

  /**
   * Creates a new <code>JMenu</code> with the specified label.
   *
   * @param text label for this menu
   */
  public JMenu(String text)
  {
    super(text);
    popupMenu = new JPopupMenu(); 
    popupMenu.setInvoker(this);
    setOpaque(false);
  }

  /**
   * Creates a new <code>JMenu</code> object.
   *
   * @param action Action that is used to create menu item tha will be
   * added to the menu.
   */
  public JMenu(Action action)
  {
    super(action);
    createActionChangeListener(this);
    popupMenu = new JPopupMenu();
    popupMenu.setInvoker(this);
    setOpaque(false);
  }

  /**
   * Creates a new <code>JMenu</code> with specified label and an option
   * for this menu to be tear-off menu.
   *
   * @param text label for this menu
   * @param tearoff true if this menu should be tear-off and false otherwise
   */
  public JMenu(String text, boolean tearoff)
  {
    // FIXME: tearoff not implemented
    this(text);
  }

  /**
   * Adds specified menu item to this menu
   *
   * @param item Menu item to add to this menu
   *
   * @return Menu item that was added
   */
  public JMenuItem add(JMenuItem item)
  {
    return getPopupMenu().add(item);
  }

  /**
   * Adds specified component to this menu.
   *
   * @param component Component to add to this menu
   *
   * @return Component that was added
   */
  public Component add(Component component)
  {
    getPopupMenu().insert(component, -1);
    return component;
  }

  /**
   * Adds specified component to this menu at the given index
   *
   * @param component Component to add
   * @param index Position of this menu item in the menu
   *
   * @return Component that was added
   */
  public Component add(Component component, int index)
  {
    return getPopupMenu().add(component, index);
  }

  /**
   * Adds JMenuItem constructed with the specified label to this menu
   *
   * @param text label for the menu item that will be added
   *
   * @return Menu Item that was added to this menu
   */
  public JMenuItem add(String text)
  {
    return add(new JMenuItem(text));
  }

  /**
   * Adds JMenuItem constructed using properties from specified action.
   *
   * @param action action to construct the menu item with
   *
   * @return Menu Item that was added to this menu
   */
  public JMenuItem add(Action action)
  {
    JMenuItem i = createActionComponent(action);
    i.setAction(action);
    add(i);
    return i;
  }

  /**
   * Removes given menu item from this menu. Nothing happens if
   * this menu doesn't contain specified menu item.
   *
   * @param item Menu Item which needs to be removed
   */
  public void remove(JMenuItem item)
  {
    getPopupMenu().remove(item);
  }

  /**
   * Removes component at the specified index from this menu
   *
   * @param index Position of the component that needs to be removed in the menu
   */
  public void remove(int index)
  {
    if (index < 0 || (index > 0 && getMenuComponentCount() == 0))
      throw new IllegalArgumentException();
  
    if (getMenuComponentCount() > 0)
      popupMenu.remove(index);
  }

  /**
   * Removes given component from this menu.
   *
   * @param component Component to remove
   */
  public void remove(Component component)
  {
    int index = getPopupMenu().getComponentIndex(component);
    if (index >= 0)
      getPopupMenu().remove(index);
  }

  /**
   * Removes all menu items from the menu
   */
  public void removeAll()
  {
    if (popupMenu != null)
      popupMenu.removeAll();
  }

  /**
   * Creates JMenuItem with the specified text and inserts it in the
   * at the specified index
   *
   * @param text label for the new menu item
   * @param index index at which to insert newly created menu item.
   */
  public void insert(String text, int index)
  {
    this.insert(new JMenuItem(text), index);
  }

  /**
   * Creates JMenuItem with the specified text and inserts it in the
   * at the specified index. IllegalArgumentException is thrown
   * if index is less than 0
   *
   * @param item menu item to insert
   * @param index index at which to insert menu item.
   * @return Menu item that was added to the menu
   */
  public JMenuItem insert(JMenuItem item, int index)
  {
    if (index < 0)
      throw new IllegalArgumentException("index less than zero");

    getPopupMenu().insert(item, index);
    return item;
  }

  /**
   * Creates JMenuItem with the associated action and inserts it to the menu
   * at the specified index. IllegalArgumentException is thrown
   * if index is less than 0
   *
   * @param action Action for the new menu item
   * @param index index at which to insert newly created menu item.
   * @return Menu item that was added to the menu
   */
  public JMenuItem insert(Action action, int index)
  {
    JMenuItem item = new JMenuItem(action);
    this.insert(item, index);

    return item;
  }

  /**
   * This method sets this menuItem's UI to the UIManager's default for the
   * current look and feel.
   */
  public void updateUI()
  {
    setUI((MenuItemUI) UIManager.getUI(this));
  }

  /**
   * This method returns a name to identify which look and feel class will be
   * the UI delegate for the menu.
   *
   * @return The Look and Feel classID. "MenuUI"
   */
  public String getUIClassID()
  {
    return "MenuUI";
  }

  /**
   * Sets model for this menu.
   *
   * @param model model to set
   */
  public void setModel(ButtonModel model)
  {
    ButtonModel oldModel = getModel();
    if (oldModel != null && menuChangeListener != null)
      oldModel.removeChangeListener(menuChangeListener);

    super.setModel(model);

    if (model != null)
      {
        if (menuChangeListener == null)
          menuChangeListener = new MenuChangeListener();
        model.addChangeListener(menuChangeListener);
      }
  }

  /**
   * Returns true if the menu is selected and false otherwise
   *
   * @return true if the menu is selected and false otherwise
   */
  public boolean isSelected()
  {
    return super.isSelected();
  }

  /**
   * Changes this menu selected state if selected is true and false otherwise
   * This method fires menuEvents to menu's registered listeners.
   *
   * @param selected true if the menu should be selected and false otherwise
   */
  public void setSelected(boolean selected)
  {
    ButtonModel m = getModel();
    if (selected != m.isSelected())
      m.setSelected(selected);
  }

  /**
   * Checks if PopupMenu associated with this menu is visible
   *
   * @return true if the popup associated with this menu is currently visible
   * on the screen and false otherwise.
   */
  public boolean isPopupMenuVisible()
  {
    return getPopupMenu().isVisible();
  }

  /**
   * Sets popup menu visibility
   *
   * @param popup true if popup should be visible and false otherwise
   */
  public void setPopupMenuVisible(boolean popup)
  {
    if (popup != isPopupMenuVisible() && (isEnabled() || ! popup))
      {
        if (popup && isShowing())
          {
            // Set location as determined by getPopupLocation().
            Point loc = menuLocation == null ? getPopupMenuOrigin()
                                             : menuLocation;
            getPopupMenu().show(this, loc.x, loc.y);
          }
        else
          getPopupMenu().setVisible(false);
      }
  }

  /**
   * Returns origin point of the popup menu. This takes the screen bounds
   * into account and places the popup where it fits best. 
   *
   * @return the origin of the popup menu
   */
  protected Point getPopupMenuOrigin()
  {
    // The menu's screen location and size.
    Point screenLoc = getLocationOnScreen();
    Dimension size = getSize();

    // Determine the popup's size.
    JPopupMenu popup = getPopupMenu();
    Dimension popupSize = popup.getSize();
    if (popupSize.width == 0 || popupSize.height == 0)
      popupSize = popup.getPreferredSize(); 

    // Determine screen bounds.
    Toolkit tk = Toolkit.getDefaultToolkit();
    Rectangle screenBounds = new Rectangle(tk.getScreenSize());
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice gd = ge.getDefaultScreenDevice();
    GraphicsConfiguration gc = gd.getDefaultConfiguration();
    Insets screenInsets = tk.getScreenInsets(gc);
    screenBounds.x -= screenInsets.left;
    screenBounds.width -= screenInsets.left + screenInsets.right;
    screenBounds.y -= screenInsets.top;
    screenBounds.height -= screenInsets.top + screenInsets.bottom;
    screenLoc.x -= screenInsets.left;
    screenLoc.y -= screenInsets.top;

    Point point = new Point();
    if (isTopLevelMenu())
      {
        // If menu in the menu bar.
        int xOffset = UIManager.getInt("Menu.menuPopupOffsetX");
        int yOffset = UIManager.getInt("Menu.menuPopupOffsetY");
        // Determine X location.
        if (getComponentOrientation().isLeftToRight())
          {
            // Prefer popup to the right.
            point.x = xOffset;
            // Check if it fits, otherwise place popup wherever it fits.
            if (screenLoc.x + point.x + popupSize.width
                > screenBounds.width + screenBounds.width
                && screenBounds.width - size.width
                   < 2 * (screenLoc.x - screenBounds.x))
              // Popup to the right if there's not enough room.
              point.x = size.width - xOffset - popupSize.width;
          }
        else
          {
            // Prefer popup to the left.
            point.x = size.width - xOffset - popupSize.width;
            if (screenLoc.x + point.x < screenBounds.x
                && screenBounds.width - size.width
                   > 2 * (screenLoc.x - screenBounds.x))
              // Popup to the left if there's not enough room.
              point.x = xOffset;
          }
        // Determine Y location. Prefer popping down.
        point.y = size.height + yOffset;
        if (screenLoc.y + point.y + popupSize.height >= screenBounds.height
            && screenBounds.height - size.height
               < 2 * (screenLoc.y - screenBounds.y))
          // Position above if there's not enough room below.
          point.y = - yOffset - popupSize.height;
      }
    else
      {
        // If submenu.
        int xOffset = UIManager.getInt("Menu.submenuPopupOffsetX");
        int yOffset = UIManager.getInt("Menu.submenuPopupOffsetY");
        // Determine X location.
        if (getComponentOrientation().isLeftToRight())
          {
            // Prefer popup to the right.
            point.x = size.width + xOffset;
            if (screenLoc.x + point.x + popupSize.width
                >= screenBounds.x + screenBounds.width
                && screenBounds.width - size.width
                   < 2 * (screenLoc.x - screenBounds.x))
              // Position to the left if there's not enough room on the right.
              point.x = - xOffset - popupSize.width;
          }
        else
          {
            // Prefer popup on the left side.
            point.x = - xOffset - popupSize.width;
            if (screenLoc.x + point.x < screenBounds.x
                && screenBounds.width - size.width
                > 2 * (screenLoc.x - screenBounds.x))
              // Popup to the right if there's not enough room.
              point.x = size.width + xOffset;
          }
        // Determine Y location. Prefer popping down.
        point.y = yOffset;
        if (screenLoc.y + point.y + popupSize.height
            >= screenBounds.y + screenBounds.height
            && screenBounds.height - size.height
            < 2 * (screenLoc.y - screenBounds.y))
          // Pop up if there's not enough room below.
          point.y = size.height - yOffset - popupSize.height;
      }
    return point;
  }

  /**
   * Returns delay property.
   *
   * @return delay property, indicating number of milliseconds before
   * popup menu associated with the menu appears or disappears after
   * menu was selected or deselected respectively
   */
  public int getDelay()
  {
    return delay;
  }

  /**
   * Sets delay property for this menu. If given time for the delay
   * property is negative, then IllegalArgumentException is thrown
   *
   * @param delay number of milliseconds before
   * popup menu associated with the menu appears or disappears after
   * menu was selected or deselected respectively
   */
  public void setDelay(int delay)
  {
    if (delay < 0)
      throw new IllegalArgumentException("delay less than 0");
    this.delay = delay;
  }

  /**
   * Sets location at which popup menu should be displayed
   * The location given is relative to this menu item
   *
   * @param x x-coordinate of the menu location
   * @param y y-coordinate of the menu location
   */
  public void setMenuLocation(int x, int y)
  {
    menuLocation = new Point(x, y);
    if (popupMenu != null)
      popupMenu.setLocation(x, y);
  }

  /**
   * Creates and returns JMenuItem associated with the given action
   *
   * @param action Action to use for creation of JMenuItem
   *
   * @return JMenuItem that was creted with given action
   */
  protected JMenuItem createActionComponent(Action action)
  {
    return new JMenuItem(action);
  }

  /**
   * Creates ActionChangeListener to listen for PropertyChangeEvents occuring
   * in the action that is associated with this menu
   *
   * @param item menu that contains action to listen to
   *
   * @return The PropertyChangeListener
   */
  protected PropertyChangeListener createActionChangeListener(JMenuItem item)
  {
    return new ActionChangedListener(item);
  }

  /**
   * Adds separator to the end of the menu items in the menu.
   */
  public void addSeparator()
  {
    getPopupMenu().addSeparator();
  }

  /**
   * Inserts separator in the menu at the specified index.
   *
   * @param index Index at which separator should be inserted
   */
  public void insertSeparator(int index)
  {
    if (index < 0)
      throw new IllegalArgumentException("index less than 0");

    getPopupMenu().insert(new JPopupMenu.Separator(), index);
  }

  /**
   * Returns menu item located at the specified index in the menu
   *
   * @param index Index at which to look for the menu item
   *
   * @return menu item located at the specified index in the menu
   */
  public JMenuItem getItem(int index)
  {
    if (index < 0)
      throw new IllegalArgumentException("index less than 0");

    if (getItemCount() == 0)
      return null;
    
    Component c = popupMenu.getComponentAtIndex(index);

    if (c instanceof JMenuItem)
      return (JMenuItem) c;
    else
      return null;
  }

  /**
   * Returns number of items in the menu including separators.
   *
   * @return number of items in the menu
   *
   * @see #getMenuComponentCount()
   */
  public int getItemCount()
  {
    return getMenuComponentCount();
  }

  /**
   * Checks if this menu is a tear-off menu.
   *
   * @return true if this menu is a tear-off menu and false otherwise
   */
  public boolean isTearOff()
  {
    // NOT YET IMPLEMENTED 
    throw new Error("The method isTearOff() has not yet been implemented.");
  }

  /**
   * Returns number of menu components in this menu
   *
   * @return number of menu components in this menu
   */
  public int getMenuComponentCount()
  {
    return getPopupMenu().getComponentCount();
  }

  /**
   * Returns menu component located at the givent index
   * in the menu
   *
   * @param index index at which to get the menu component in the menu
   *
   * @return Menu Component located in the menu at the specified index
   */
  public Component getMenuComponent(int index)
  {
    if (getPopupMenu() == null || getMenuComponentCount() == 0)
      return null;
    
    return popupMenu.getComponentAtIndex(index);
  }

  /**
   * Return components belonging to this menu
   *
   * @return components belonging to this menu
   */
  public Component[] getMenuComponents()
  {
    return getPopupMenu().getComponents();
  }

  /**
   * Checks if this menu is a top level menu. The menu is top
   * level menu if it is inside the menu bar. While if the menu
   * inside some other menu, it is considered to be a pull-right menu.
   *
   * @return true if this menu is top level menu, and false otherwise
   */
  public boolean isTopLevelMenu()
  {
    return getParent() instanceof JMenuBar;
  }

  /**
   * Checks if given component exists in this menu. The submenus of
   * this menu are checked as well
   *
   * @param component Component to look for
   *
   * @return true if the given component exists in this menu, and false otherwise
   */
  public boolean isMenuComponent(Component component)
  {
    return false;
  }

  /**
   * Returns popup menu associated with the menu.
   *
   * @return popup menu associated with the menu.
   */
  public JPopupMenu getPopupMenu()
  {
    if (popupMenu == null)
      {
        popupMenu = new JPopupMenu();
        popupMenu.setInvoker(this);
      }
    return popupMenu;
  }

  /**
   * Adds MenuListener to the menu
   *
   * @param listener MenuListener to add
   */
  public void addMenuListener(MenuListener listener)
  {
    listenerList.add(MenuListener.class, listener);
  }

  /**
   * Removes MenuListener from the menu
   *
   * @param listener MenuListener to remove
   */
  public void removeMenuListener(MenuListener listener)
  {
    listenerList.remove(MenuListener.class, listener);
  }

  /**
   * Returns all registered <code>MenuListener</code> objects.
   *
   * @return an array of listeners
   * 
   * @since 1.4
   */
  public MenuListener[] getMenuListeners()
  {
    return (MenuListener[]) listenerList.getListeners(MenuListener.class);
  }

  /**
   * This method fires MenuEvents to all menu's MenuListeners. In this case
   * menuSelected() method of MenuListeners is called to indicated that the menu
   * was selected.
   */
  protected void fireMenuSelected()
  {
    MenuListener[] listeners = getMenuListeners();

    for (int index = 0; index < listeners.length; ++index)
      listeners[index].menuSelected(menuEvent);
  }

  /**
   * This method fires MenuEvents to all menu's MenuListeners. In this case
   * menuDeselected() method of MenuListeners is called to indicated that the menu
   * was deselected.
   */
  protected void fireMenuDeselected()
  {
    EventListener[] ll = listenerList.getListeners(MenuListener.class);

    for (int i = 0; i < ll.length; i++)
      ((MenuListener) ll[i]).menuDeselected(menuEvent);
  }

  /**
   * This method fires MenuEvents to all menu's MenuListeners. In this case
   * menuSelected() method of MenuListeners is called to indicated that the menu
   * was cancelled. The menu is cancelled when it's popup menu is close without selection.
   */
  protected void fireMenuCanceled()
  {
    EventListener[] ll = listenerList.getListeners(MenuListener.class);

    for (int i = 0; i < ll.length; i++)
      ((MenuListener) ll[i]).menuCanceled(menuEvent);
  }

  /**
   * Creates WinListener that listens to the menu;s popup menu.
   *
   * @param popup JPopupMenu to listen to
   *
   * @return The WinListener
   */
  protected WinListener createWinListener(JPopupMenu popup)
  {
    return new WinListener(popup);
  }

  /**
   * Method of the MenuElementInterface. It reacts to the selection
   * changes in the menu. If this menu was selected, then it
   * displayes popup menu associated with it and if this menu was
   * deselected it hides the popup menu.
   *
   * @param changed true if the menu was selected and false otherwise
   */
  public void menuSelectionChanged(boolean changed)
  {
    // if this menu selection is true, then activate this menu and 
    // display popup associated with this menu
    setSelected(changed);
  }

  /**
   * Method of MenuElement interface. Returns sub components of
   * this menu.
   *
   * @return array containing popupMenu that is associated with this menu
   */
  public MenuElement[] getSubElements()
  {
    return new MenuElement[] { popupMenu };
  }

  /**
   * @return Returns reference to itself
   */
  public Component getComponent()
  {
    return this;
  }

  /**
   * This method is overriden with empty implementation, s.t the
   * accelerator couldn't be set for the menu. The mnemonic should
   * be used for the menu instead.
   *
   * @param keystroke accelerator for this menu
   */
  public void setAccelerator(KeyStroke keystroke)
  {
    throw new Error("setAccelerator() is not defined for JMenu.  Use setMnemonic() instead.");
  }

  /**
   * This method process KeyEvent occuring when the menu is visible
   *
   * @param event The KeyEvent
   */
  protected void processKeyEvent(KeyEvent event)
  {
    MenuSelectionManager.defaultManager().processKeyEvent(event);
  }

  /**
   * Programatically performs click
   *
   * @param time Number of milliseconds for which this menu stays pressed
   */
  public void doClick(int time)
  {
    getModel().setArmed(true);
    getModel().setPressed(true);
    try
      {
	java.lang.Thread.sleep(time);
      }
    catch (java.lang.InterruptedException e)
      {
	// probably harmless
      }

    getModel().setPressed(false);
    getModel().setArmed(false);
    popupMenu.show(this, this.getWidth(), 0);
  }

  /**
   * A string that describes this JMenu. Normally only used
   * for debugging.
   *
   * @return A string describing this JMenu
   */
  protected String paramString()
  {
    return super.paramString();
  }

  public AccessibleContext getAccessibleContext()
  {
    if (accessibleContext == null)
      accessibleContext = new AccessibleJMenu();

    return accessibleContext;
  }

  /**
   * Implements support for assisitive technologies for <code>JMenu</code>.
   */
  protected class AccessibleJMenu extends AccessibleJMenuItem
    implements AccessibleSelection
  {
    private static final long serialVersionUID = -8131864021059524309L;

    protected AccessibleJMenu()
    {
      // Nothing to do here.
    }

    /**
     * Returns the number of accessible children of this object.
     *
     * @return the number of accessible children of this object
     */
    public int getAccessibleChildrenCount()
    {
      Component[] children = getMenuComponents();
      int count = 0;
      for (int i = 0; i < children.length; i++)
        {
          if (children[i] instanceof Accessible)
            count++;
        }
      return count;
    }

    /**
     * Returns the accessible child with the specified <code>index</code>.
     *
     * @param index the index of the child to fetch
     *
     * @return the accessible child with the specified <code>index</code>
     */
    public Accessible getAccessibleChild(int index)
    {
      Component[] children = getMenuComponents();
      int count = 0;
      Accessible found = null;
      for (int i = 0; i < children.length; i++)
        {
          if (children[i] instanceof Accessible)
            {
              if (count == index)
                {
                  found = (Accessible) children[i];
                  break;
                }
              count++;
            }
        }
      return found;
    }

    /**
     * Returns the accessible selection of this object. AccessibleJMenus handle
     * their selection themselves, so we always return <code>this</code> here.
     *
     * @return the accessible selection of this object
     */
    public AccessibleSelection getAccessibleSelection()
    {
      return this;
    }

    /**
     * Returns the selected accessible child with the specified
     * <code>index</code>.
     *
     * @param index the index of the accessible selected child to return
     *
     * @return the selected accessible child with the specified
     *         <code>index</code>
     */
    public Accessible getAccessibleSelection(int index)
    {
      Accessible selected = null;
      // Only one item can be selected, which must therefore have index == 0.
      if (index == 0)
        {
          MenuSelectionManager msm = MenuSelectionManager.defaultManager();
          MenuElement[] me = msm.getSelectedPath();
          if (me != null)
            {
              for (int i = 0; i < me.length; i++)
                {
                  if (me[i] == JMenu.this)
                    {
                      // This JMenu is selected, find and return the next
                      // JMenuItem in the path.
                      do
                        {
                          if (me[i] instanceof Accessible)
                            {
                              selected = (Accessible) me[i];
                              break;
                            }
                          i++;
                        } while (i < me.length);
                    }
                  if (selected != null)
                    break;
                }
            }
        }
      return selected;
    }

    /**
     * Returns <code>true</code> if the accessible child with the specified
     * index is selected, <code>false</code> otherwise.
     *
     * @param index the index of the accessible child to check
     *
     * @return <code>true</code> if the accessible child with the specified
     *         index is selected, <code>false</code> otherwise
     */
    public boolean isAccessibleChildSelected(int index)
    {
      boolean selected = false;
      MenuSelectionManager msm = MenuSelectionManager.defaultManager();
      MenuElement[] me = msm.getSelectedPath();
      if (me != null)
        {
          Accessible toBeFound = getAccessibleChild(index);
          for (int i = 0; i < me.length; i++)
            {
              if (me[i] == toBeFound)
                {
                  selected = true;
                  break;
                }
            }
        }
      return selected;
    }

    /**
     * Returns the accessible role of this object, which is
     * {@link AccessibleRole#MENU} for the AccessibleJMenu.
     *
     * @return the accessible role of this object
     */
    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.MENU;
    }

    /**
     * Returns the number of selected accessible children. This will be
     * <code>0</code> if no item is selected, or <code>1</code> if an item
     * is selected. AccessibleJMenu can have maximum 1 selected item.
     *
     * @return the number of selected accessible children
     */
    public int getAccessibleSelectionCount()
    {
      int count = 0;
      MenuSelectionManager msm = MenuSelectionManager.defaultManager();
      MenuElement[] me = msm.getSelectedPath();
      if (me != null)
        {
          for (int i = 0; i < me.length; i++)
            {
              if (me[i] == JMenu.this)
                {
                  if (i + 1 < me.length)
                    {
                      count = 1;
                      break;
                    }
                }
            }
        }
      return count;
    }

    /**
     * Selects the accessible child with the specified index.
     *
     * @param index the index of the accessible child to select
     */
    public void addAccessibleSelection(int index)
    {
      Accessible child = getAccessibleChild(index);
      if (child != null && child instanceof JMenuItem)
        {
          JMenuItem mi = (JMenuItem) child;
          MenuSelectionManager msm = MenuSelectionManager.defaultManager();
          msm.setSelectedPath(createPath(JMenu.this));
        }
    }

    /**
     * Removes the item with the specified index from the selection.
     *
     * @param index the index of the selected item to remove from the selection
     */
    public void removeAccessibleSelection(int index)
    {
      Accessible child = getAccessibleChild(index);
      if (child != null)
        {
          MenuSelectionManager msm = MenuSelectionManager.defaultManager();
          MenuElement[] oldSelection = msm.getSelectedPath();
          for (int i = 0; i < oldSelection.length; i++)
            {
              if (oldSelection[i] == child)
                {
                  // Found the specified child in the selection. Remove it
                  // from the selection.
                  MenuElement[] newSel = new MenuElement[i - 1];
                  System.arraycopy(oldSelection, 0, newSel, 0, i - 1);
                  msm.setSelectedPath(newSel);
                  break;
                }
            }
        }
    }

    /**
     * Removes all possibly selected accessible children of this object from
     * the selection.
     */
    public void clearAccessibleSelection()
    {
      MenuSelectionManager msm = MenuSelectionManager.defaultManager();
      MenuElement[] oldSelection = msm.getSelectedPath();
      for (int i = 0; i < oldSelection.length; i++)
        {
          if (oldSelection[i] == JMenu.this)
            {
              // Found this menu in the selection. Remove all children from
              // the selection.
              MenuElement[] newSel = new MenuElement[i];
              System.arraycopy(oldSelection, 0, newSel, 0, i);
              msm.setSelectedPath(newSel);
              break;
            }
        }
    }

    /**
     * AccessibleJMenu don't support multiple selection, so this method
     * does nothing.
     */
    public void selectAllAccessibleSelection()
    {
      // Nothing to do here.
    }
  }

  protected class WinListener extends WindowAdapter implements Serializable
  {
    private static final long serialVersionUID = -6415815570638474823L;

    /**
     * Creates a new <code>WinListener</code>.
     *
     * @param popup the popup menu which is observed
     */
    public WinListener(JPopupMenu popup)
    {
      // TODO: What should we do with the popup argument?
    }

    /**
     * Receives notification when the popup menu is closing and deselects
     * the menu.
     *
     * @param event the window event
     */
    public void windowClosing(WindowEvent event)
    {
      setSelected(false);
    }
  }

  /**
   * This class listens to PropertyChangeEvents occuring in menu's action
   */
  private class ActionChangedListener implements PropertyChangeListener
  {
    /** menu item associated with the action */
    private JMenuItem menuItem;

    /** Creates new ActionChangedListener and adds it to menuItem's action */
    public ActionChangedListener(JMenuItem menuItem)
    {
      this.menuItem = menuItem;

      Action a = menuItem.getAction();
      if (a != null)
	a.addPropertyChangeListener(this);
    }

    /**This method is invoked when some change occures in menuItem's action*/
    public void propertyChange(PropertyChangeEvent evt)
    {
      // FIXME: Need to implement
    }
  }

  /**
   * Creates an array to be feeded as argument to
   * {@link MenuSelectionManager#setSelectedPath(MenuElement[])} for the
   * specified element. This has the effect of selecting the specified element
   * and all its parents.
   *
   * @param leaf the leaf element for which to create the selected path
   *
   * @return the selected path array
   */
  MenuElement[] createPath(JMenu leaf)
  {
    ArrayList path = new ArrayList();
    MenuElement[] array = null;
    Component current = leaf.getPopupMenu();
    while (true)
      {
        if (current instanceof JPopupMenu)
          {
            JPopupMenu popupMenu = (JPopupMenu) current;
            path.add(0, popupMenu);
            current = popupMenu.getInvoker();
          }
        else if (current instanceof JMenu)
          {
            JMenu menu = (JMenu) current;
            path.add(0, menu);
            current = menu.getParent();
          }
        else if (current instanceof JMenuBar)
          {
            JMenuBar menuBar = (JMenuBar) current;
            path.add(0, menuBar);
            array = new MenuElement[path.size()];
            array = (MenuElement[]) path.toArray(array);
            break;
          }
      }
    return array;
  }
}
