/* BasicMenuItemUI.java --
   Copyright (C) 2002, 2004, 2005  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.plaf.basic;

import gnu.classpath.SystemProperties;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;

import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.ActionMap;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.LookAndFeel;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.MenuDragMouseEvent;
import javax.swing.event.MenuDragMouseListener;
import javax.swing.event.MenuKeyEvent;
import javax.swing.event.MenuKeyListener;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentInputMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.MenuItemUI;
import javax.swing.text.View;

/**
 * UI Delegate for JMenuItem.
 */
public class BasicMenuItemUI extends MenuItemUI
{
  /**
   * Font to be used when displaying menu item's accelerator.
   */
  protected Font acceleratorFont;

  /**
   * Color to be used when displaying menu item's accelerator.
   */
  protected Color acceleratorForeground;

  /**
   * Color to be used when displaying menu item's accelerator when menu item is
   * selected.
   */
  protected Color acceleratorSelectionForeground;

  /**
   * Icon that is displayed after the text to indicated that this menu contains
   * submenu.
   */
  protected Icon arrowIcon;

  /**
   * Icon that is displayed before the text. This icon is only used in
   * JCheckBoxMenuItem or JRadioBoxMenuItem.
   */
  protected Icon checkIcon;

  /**
   * Number of spaces between icon and text.
   */
  protected int defaultTextIconGap = 4;

  /**
   * Color of the text when menu item is disabled
   */
  protected Color disabledForeground;

  /**
   * The menu Drag mouse listener listening to the menu item.
   */
  protected MenuDragMouseListener menuDragMouseListener;

  /**
   * The menu item itself
   */
  protected JMenuItem menuItem;

  /**
   * Menu Key listener listening to the menu item.
   */
  protected MenuKeyListener menuKeyListener;

  /**
   * mouse input listener listening to menu item.
   */
  protected MouseInputListener mouseInputListener;

  /**
   * Indicates if border should be painted
   */
  protected boolean oldBorderPainted;

  /**
   * Color of text that is used when menu item is selected
   */
  protected Color selectionBackground;

  /**
   * Color of the text that is used when menu item is selected.
   */
  protected Color selectionForeground;

  /**
   * String that separates description of the modifiers and the key
   */
  private String acceleratorDelimiter;

  /**
   * ItemListener to listen for item changes in the menu item
   */
  private ItemListener itemListener;

  /**
   * A PropertyChangeListener to make UI updates after property changes.
   */
  private PropertyChangeHandler propertyChangeListener;

  /**
   * The view rectangle used for layout of the menu item.
   */
  private Rectangle viewRect;

  /**
   * The rectangle that holds the area of the label.
   */
  private Rectangle textRect;

  /**
   * The rectangle that holds the area of the accelerator.
   */
  private Rectangle accelRect;

  /**
   * The rectangle that holds the area of the icon.
   */
  private Rectangle iconRect;

  /**
   * The rectangle that holds the area of the icon.
   */
  private Rectangle arrowIconRect;

  /**
   * The rectangle that holds the area of the check icon.
   */
  private Rectangle checkIconRect;

  /**
   * A rectangle used for temporary storage to avoid creation of new
   * rectangles.
   */
  private Rectangle cachedRect;

  /**
   * A class to handle PropertChangeEvents for the JMenuItem
   * @author Anthony Balkissoon abalkiss at redhat dot com.
   */
  class PropertyChangeHandler implements PropertyChangeListener
  {
    /**
     * This method is called when a property of the menuItem is changed.
     * Currently it is only used to update the accelerator key bindings.
     *
     * @param e
     *          the PropertyChangeEvent
     */
    public void propertyChange(PropertyChangeEvent e)
    {
      String property = e.getPropertyName();
      if (property.equals("accelerator"))
        {
          InputMap map = SwingUtilities.getUIInputMap(menuItem,
              JComponent.WHEN_IN_FOCUSED_WINDOW);
          if (map != null)
            map.remove((KeyStroke) e.getOldValue());
          else
            map = new ComponentInputMapUIResource(menuItem);

          KeyStroke accelerator = (KeyStroke) e.getNewValue();
          if (accelerator != null)
            map.put(accelerator, "doClick");
        }
      // TextLayout caching for speed-up drawing of text.
      else if ((property.equals(AbstractButton.TEXT_CHANGED_PROPERTY)
                || property.equals("font"))
               && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D")
               == null)
        {
          AbstractButton b = (AbstractButton) e.getSource();
          String text = b.getText();
          if (text == null)
            text = "";
          FontRenderContext frc = new FontRenderContext(new AffineTransform(),
                                                        false, false);
          TextLayout layout = new TextLayout(text, b.getFont(), frc);
          b.putClientProperty(BasicGraphicsUtils.CACHED_TEXT_LAYOUT, layout);
        }
    }
  }

  /**
   * A class to handle accelerator keys.  This is the Action we will
   * perform when the accelerator key for this JMenuItem is pressed.
   * @author Anthony Balkissoon abalkiss at redhat dot com
   *
   */
  class ClickAction extends AbstractAction
  {
    /**
     * This is what is done when the accelerator key for the JMenuItem is
     * pressed.
     */
    public void actionPerformed(ActionEvent event)
    {
      doClick(MenuSelectionManager.defaultManager());
    }
  }

  /**
   * Creates a new BasicMenuItemUI object.
   */
  public BasicMenuItemUI()
  {
    mouseInputListener = createMouseInputListener(menuItem);
    menuDragMouseListener = createMenuDragMouseListener(menuItem);
    menuKeyListener = createMenuKeyListener(menuItem);
    itemListener = new ItemHandler();
    propertyChangeListener = new PropertyChangeHandler();

    // Initialize rectangles for layout.
    viewRect = new Rectangle();
    textRect = new Rectangle();
    iconRect = new Rectangle();
    arrowIconRect = new Rectangle();
    checkIconRect = new Rectangle();
    accelRect = new Rectangle();
    cachedRect = new Rectangle();
  }

  /**
   * Create MenuDragMouseListener to listen for mouse dragged events.
   *
   * @param c
   *          menu item to listen to
   * @return The MenuDragMouseListener
   */
  protected MenuDragMouseListener createMenuDragMouseListener(JComponent c)
  {
    return new MenuDragMouseHandler();
  }

  /**
   * Creates MenuKeyListener to listen to key events occuring when menu item is
   * visible on the screen.
   *
   * @param c
   *          menu item to listen to
   * @return The MenuKeyListener
   */
  protected MenuKeyListener createMenuKeyListener(JComponent c)
  {
    return new MenuKeyHandler();
  }

  /**
   * Handles mouse input events occuring for this menu item
   *
   * @param c
   *          menu item to listen to
   * @return The MouseInputListener
   */
  protected MouseInputListener createMouseInputListener(JComponent c)
  {
    return new MouseInputHandler();
  }

  /**
   * Factory method to create a BasicMenuItemUI for the given {@link
   * JComponent}, which should be a {@link JMenuItem}.
   *
   * @param c
   *          The {@link JComponent} a UI is being created for.
   * @return A BasicMenuItemUI for the {@link JComponent}.
   */
  public static ComponentUI createUI(JComponent c)
  {
    return new BasicMenuItemUI();
  }

  /**
   * Programatically clicks menu item.
   *
   * @param msm
   *          MenuSelectionManager for the menu hierarchy
   */
  protected void doClick(MenuSelectionManager msm)
  {
    menuItem.doClick(0);
    msm.clearSelectedPath();
  }

  /**
   * Returns maximum size for the specified menu item
   *
   * @param c
   *          component for which to get maximum size
   * @return Maximum size for the specified menu item.
   */
  public Dimension getMaximumSize(JComponent c)
  {
    return null;
  }

  /**
   * Returns minimum size for the specified menu item
   *
   * @param c
   *          component for which to get minimum size
   * @return Minimum size for the specified menu item.
   */
  public Dimension getMinimumSize(JComponent c)
  {
    return null;
  }

  /**
   * Returns path to this menu item.
   *
   * @return $MenuElement[]$ Returns array of menu elements that constitute a
   *         path to this menu item.
   */
  public MenuElement[] getPath()
  {
    ArrayList path = new ArrayList();

    Component c = menuItem;
    while (c instanceof MenuElement)
      {
        path.add(0, c);

        if (c instanceof JPopupMenu)
          c = ((JPopupMenu) c).getInvoker();
        else
          c = c.getParent();
      }

    MenuElement[] pathArray = new MenuElement[path.size()];
    path.toArray(pathArray);
    return pathArray;
  }

  /**
   * Returns preferred size for the given menu item.
   *
   * @param c
   *          menu item for which to get preferred size
   * @param checkIcon
   *          check icon displayed in the given menu item
   * @param arrowIcon
   *          arrow icon displayed in the given menu item
   * @param defaultTextIconGap
   *          space between icon and text in the given menuItem
   * @return $Dimension$ preferred size for the given menu item
   */
  protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
                                               Icon arrowIcon,
                                               int defaultTextIconGap)
  {
    JMenuItem m = (JMenuItem) c;
    String accelText = getAcceleratorString(m);

    // Layout the menu item. The result gets stored in the rectangle
    // fields of this class.
    resetRectangles(null);
    layoutMenuItem(m, accelText);

    // The union of the text and icon areas is the label area.
    cachedRect.setBounds(textRect);
    Rectangle pref = SwingUtilities.computeUnion(iconRect.x, iconRect.y,
                                                 iconRect.width,
                                                 iconRect.height,
                                                 cachedRect);

    // Find the widest menu item text and accelerator and store it in
    // client properties of the parent, so that we can align the accelerators
    // properly. Of course, we only need can do this, if the parent is
    // a JComponent and this menu item is not a toplevel menu.
    Container parent = m.getParent();
    if (parent != null && parent instanceof JComponent
        && !(m instanceof JMenu && ((JMenu) m).isTopLevelMenu()))
      {
        JComponent p = (JComponent) parent;

        // The widest text so far.
        Integer maxTextWidth = (Integer) p.getClientProperty("maxTextWidth");
        int maxTextValue = maxTextWidth == null ? 0 : maxTextWidth.intValue();
        if (pref.width < maxTextValue)
          pref.width = maxTextValue;
        else
          p.putClientProperty("maxTextWidth", new Integer(pref.width));

        // The widest accelerator so far.
        Integer maxAccelWidth = (Integer) p.getClientProperty("maxAccelWidth");
        int maxAccelValue = maxAccelWidth == null ? 0
                                                  : maxAccelWidth.intValue();
        if (accelRect.width > maxAccelValue)
          {
            maxAccelValue = accelRect.width;
            p.putClientProperty("maxAccelWidth", new Integer(accelRect.width));
          }
        pref.width += maxAccelValue;
        pref.width += defaultTextIconGap;
      }

    // Add arrow and check size if appropriate.
    if (! (m instanceof JMenu && ((JMenu) m).isTopLevelMenu()))
      {
        pref.width += checkIconRect.width;
        pref.width += defaultTextIconGap;
        pref.width += arrowIconRect.width;
        pref.width += defaultTextIconGap;
      }

    // Add a gap ~2 times as wide as the defaultTextIconGap.
    pref.width += 2 * defaultTextIconGap;

    // Respect the insets of the menu item.
    Insets i = m.getInsets();
    pref.width += i.left + i.right;
    pref.height += i.top + i.bottom;

    // Return a copy, so that nobody messes with our textRect.
    return pref.getSize();
  }

  /**
   * Returns preferred size of the given component
   *
   * @param c
   *          component for which to return preferred size
   * @return $Dimension$ preferred size for the given component
   */
  public Dimension getPreferredSize(JComponent c)
  {
    return getPreferredMenuItemSize(c, checkIcon, arrowIcon,
                                    defaultTextIconGap);
  }

  /**
   * Returns the prefix for entries in the {@link UIDefaults} table.
   *
   * @return "MenuItem"
   */
  protected String getPropertyPrefix()
  {
    return "MenuItem";
  }

  /**
   * This method installs the components for this {@link JMenuItem}.
   *
   * @param menuItem
   *          The {@link JMenuItem} to install components for.
   */
  protected void installComponents(JMenuItem menuItem)
  {
    // FIXME: Need to implement
  }

  /**
   * This method installs the defaults that are defined in the Basic look and
   * feel for this {@link JMenuItem}.
   */
  protected void installDefaults()
  {
    String prefix = getPropertyPrefix();
    LookAndFeel.installBorder(menuItem, prefix + ".border");
    LookAndFeel.installColorsAndFont(menuItem, prefix + ".background",
                                     prefix + ".foreground", prefix + ".font");
    menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
    acceleratorFont = UIManager.getFont(prefix + ".acceleratorFont");
    acceleratorForeground = UIManager.getColor(prefix
        + ".acceleratorForeground");
    acceleratorSelectionForeground = UIManager.getColor(prefix
        + ".acceleratorSelectionForeground");
    selectionBackground = UIManager.getColor(prefix + ".selectionBackground");
    selectionForeground = UIManager.getColor(prefix + ".selectionForeground");
    acceleratorDelimiter = UIManager.getString(prefix + ".acceleratorDelimiter");
    checkIcon = UIManager.getIcon(prefix + ".checkIcon");

    menuItem.setHorizontalTextPosition(SwingConstants.TRAILING);
    menuItem.setHorizontalAlignment(SwingConstants.LEADING);
  }

  /**
   * This method installs the keyboard actions for this {@link JMenuItem}.
   */
  protected void installKeyboardActions()
  {
    InputMap focusedWindowMap = SwingUtilities.getUIInputMap(menuItem,
        JComponent.WHEN_IN_FOCUSED_WINDOW);
    if (focusedWindowMap == null)
      focusedWindowMap = new ComponentInputMapUIResource(menuItem);
    KeyStroke accelerator = menuItem.getAccelerator();
    if (accelerator != null)
      focusedWindowMap.put(accelerator, "doClick");
    SwingUtilities.replaceUIInputMap(menuItem,
        JComponent.WHEN_IN_FOCUSED_WINDOW, focusedWindowMap);

    ActionMap UIActionMap = SwingUtilities.getUIActionMap(menuItem);
    if (UIActionMap == null)
      UIActionMap = new ActionMapUIResource();
    UIActionMap.put("doClick", new ClickAction());
    SwingUtilities.replaceUIActionMap(menuItem, UIActionMap);
  }

  /**
   * This method installs the listeners for the {@link JMenuItem}.
   */
  protected void installListeners()
  {
    menuItem.addMouseListener(mouseInputListener);
    menuItem.addMouseMotionListener(mouseInputListener);
    menuItem.addMenuDragMouseListener(menuDragMouseListener);
    menuItem.addMenuKeyListener(menuKeyListener);
    menuItem.addItemListener(itemListener);
    menuItem.addPropertyChangeListener(propertyChangeListener);
    // Fire synthetic property change event to let the listener update
    // the TextLayout cache.
    propertyChangeListener.propertyChange(new PropertyChangeEvent(menuItem,
                                                                  "font", null,
                                                          menuItem.getFont()));
  }

  /**
   * Installs and initializes all fields for this UI delegate. Any properties of
   * the UI that need to be initialized and/or set to defaults will be done now.
   * It will also install any listeners necessary.
   *
   * @param c
   *          The {@link JComponent} that is having this UI installed.
   */
  public void installUI(JComponent c)
  {
    super.installUI(c);
    menuItem = (JMenuItem) c;
    installDefaults();
    installComponents(menuItem);
    installListeners();
    installKeyboardActions();
  }

  /**
   * Paints given menu item using specified graphics context
   *
   * @param g
   *          The graphics context used to paint this menu item
   * @param c
   *          Menu Item to paint
   */
  public void paint(Graphics g, JComponent c)
  {
    paintMenuItem(g, c, checkIcon, arrowIcon, selectionBackground,
                  c.getForeground(), defaultTextIconGap);
  }

  /**
   * Paints background of the menu item
   *
   * @param g
   *          The graphics context used to paint this menu item
   * @param menuItem
   *          menu item to paint
   * @param bgColor
   *          Background color to use when painting menu item
   */
  protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor)
  {
    // Menu item is considered to be highlighted when it is selected.
    // But we don't want to paint the background of JCheckBoxMenuItems
    ButtonModel mod = menuItem.getModel();
    Color saved = g.getColor();
    if (mod.isArmed() || ((menuItem instanceof JMenu) && mod.isSelected()))
      {
        g.setColor(bgColor);
        g.fillRect(0, 0, menuItem.getWidth(), menuItem.getHeight());
      }
    else if (menuItem.isOpaque())
      {
        g.setColor(menuItem.getBackground());
        g.fillRect(0, 0, menuItem.getWidth(), menuItem.getHeight());
      }
    g.setColor(saved);
  }

  /**
   * Paints specified menu item
   *
   * @param g
   *          The graphics context used to paint this menu item
   * @param c
   *          menu item to paint
   * @param checkIcon
   *          check icon to use when painting menu item
   * @param arrowIcon
   *          arrow icon to use when painting menu item
   * @param background
   *          Background color of the menu item
   * @param foreground
   *          Foreground color of the menu item
   * @param defaultTextIconGap
   *          space to use between icon and text when painting menu item
   */
  protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
                               Icon arrowIcon, Color background,
                               Color foreground, int defaultTextIconGap)
  {
    JMenuItem m = (JMenuItem) c;

    // Fetch fonts.
    Font oldFont = g.getFont();
    Font font = c.getFont();
    g.setFont(font);
    FontMetrics accelFm = m.getFontMetrics(acceleratorFont);

    // Create accelerator string.
    String accelText = getAcceleratorString(m);

    // Layout menu item. The result gets stored in the rectangle fields
    // of this class.
    resetRectangles(m);

    layoutMenuItem(m, accelText);

    // Paint the background.
    paintBackground(g, m, background);

    Color oldColor = g.getColor();

    // Paint the check icon.
    if (checkIcon != null)
      {
        checkIcon.paintIcon(m, g, checkIconRect.x, checkIconRect.y);
      }

    // Paint the icon.
    ButtonModel model = m.getModel();
    if (m.getIcon() != null)
      {
        // Determine icon depending on the menu item
        // state (normal/disabled/pressed).
        Icon icon;
        if (! m.isEnabled())
          {
            icon = m.getDisabledIcon();
          }
        else if (model.isPressed() && model.isArmed())
          {
            icon = m.getPressedIcon();
            if (icon == null)
              {
                icon = m.getIcon();
              }
          }
        else
          {
            icon = m.getIcon();
          }

        if (icon != null)
          {
            icon.paintIcon(m, g, iconRect.x, iconRect.y);
          }
      }

    // Paint the text.
    String text = m.getText();
    if (text != null)
      {
        // Handle HTML.
        View html = (View) m.getClientProperty(BasicHTML.propertyKey);
        if (html != null)
          {
            html.paint(g, textRect);
          }
        else
          {
            paintText(g, m, textRect, text);
          }
      }

    // Paint accelerator text.
    if (! accelText.equals(""))
      {
        // Align the accelerator text. In getPreferredMenuItemSize() we
        // store a client property 'maxAccelWidth' in the parent which holds
        // the maximum accelerator width for the children of this parent.
        // We use this here to align the accelerators properly.
        int accelOffset = 0;
        Container parent = m.getParent();
        if (parent != null && parent instanceof JComponent)
          {
            JComponent p = (JComponent) parent;
            Integer maxAccelWidth =
              (Integer) p.getClientProperty("maxAccelWidth");
            int maxAccelValue = maxAccelWidth == null ? 0
                                                    : maxAccelWidth.intValue();
            accelOffset = maxAccelValue - accelRect.width;
          }

        g.setFont(acceleratorFont);
        if (! m.isEnabled())
          {
            // Paint accelerator disabled.
            g.setColor(disabledForeground);
          }
        else
          {
            if (m.isArmed() || (m instanceof JMenu && m.isSelected()))
              g.setColor(acceleratorSelectionForeground);
            else
              g.setColor(acceleratorForeground);
          }
        g.drawString(accelText, accelRect.x - accelOffset,
                     accelRect.y + accelFm.getAscent());
      }

    // Paint arrow.
    if (arrowIcon != null
        && ! (m instanceof JMenu && ((JMenu) m).isTopLevelMenu()))
      {
        arrowIcon.paintIcon(m, g, arrowIconRect.x, arrowIconRect.y);
      }

    g.setFont(oldFont);
    g.setColor(oldColor);

  }

  /**
   * Paints label for the given menu item
   *
   * @param g
   *          The graphics context used to paint this menu item
   * @param menuItem
   *          menu item for which to draw its label
   * @param textRect
   *          rectangle specifiying position of the text relative to the given
   *          menu item
   * @param text
   *          label of the menu item
   */
  protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect,
                           String text)
  {
    Font f = menuItem.getFont();
    g.setFont(f);
    FontMetrics fm = g.getFontMetrics(f);

    if (text != null && !text.equals(""))
      {
        if (menuItem.isEnabled())
          {
            // Menu item is considered to be highlighted when it is selected.
            // But not if it's a JCheckBoxMenuItem
            ButtonModel mod = menuItem.getModel();
            if ((menuItem.isSelected() && checkIcon == null)
                || (mod != null && mod.isArmed())
                && (menuItem.getParent() instanceof MenuElement))
              g.setColor(selectionForeground);
            else
              g.setColor(menuItem.getForeground());
          }
        else
          // FIXME: should fix this to use 'disabledForeground', but its
          // default value in BasicLookAndFeel is null.

          // FIXME: should there be different foreground colours for selected
          // or deselected, when disabled?
          g.setColor(Color.gray);

        int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();

        if (mnemonicIndex != -1)
          BasicGraphicsUtils.drawStringUnderlineCharAt(menuItem, g, text,
                                                       mnemonicIndex,
                                                       textRect.x,
                                                       textRect.y
                                                           + fm.getAscent());
        else
          BasicGraphicsUtils.drawString(menuItem, g, text, 0, textRect.x,
                                        textRect.y + fm.getAscent());
      }
  }

  /**
   * This method uninstalls the components for this {@link JMenuItem}.
   *
   * @param menuItem
   *          The {@link JMenuItem} to uninstall components for.
   */
  protected void uninstallComponents(JMenuItem menuItem)
  {
    // FIXME: need to implement
  }

  /**
   * This method uninstalls the defaults and sets any objects created during
   * install to null
   */
  protected void uninstallDefaults()
  {
    menuItem.setForeground(null);
    menuItem.setBackground(null);
    menuItem.setBorder(null);
    menuItem.setMargin(null);
    menuItem.setBackground(null);
    menuItem.setBorder(null);
    menuItem.setFont(null);
    menuItem.setForeground(null);
    menuItem.setMargin(null);
    acceleratorFont = null;
    acceleratorForeground = null;
    acceleratorSelectionForeground = null;
    arrowIcon = null;
    selectionBackground = null;
    selectionForeground = null;
    acceleratorDelimiter = null;
  }

  /**
   * Uninstalls any keyboard actions.
   */
  protected void uninstallKeyboardActions()
  {
    SwingUtilities.replaceUIInputMap(menuItem,
                                     JComponent.WHEN_IN_FOCUSED_WINDOW, null);
  }

  /**
   * Unregisters all the listeners that this UI delegate was using.
   */
  protected void uninstallListeners()
  {
    menuItem.removeMouseListener(mouseInputListener);
    menuItem.removeMenuDragMouseListener(menuDragMouseListener);
    menuItem.removeMenuKeyListener(menuKeyListener);
    menuItem.removeItemListener(itemListener);
    menuItem.removePropertyChangeListener(propertyChangeListener);
  }

  /**
   * Performs the opposite of installUI. Any properties or resources that need
   * to be cleaned up will be done now. It will also uninstall any listeners it
   * has. In addition, any properties of this UI will be nulled.
   *
   * @param c
   *          The {@link JComponent} that is having this UI uninstalled.
   */
  public void uninstallUI(JComponent c)
  {
    uninstallListeners();
    uninstallDefaults();
    uninstallComponents(menuItem);
    c.putClientProperty(BasicGraphicsUtils.CACHED_TEXT_LAYOUT, null);
    menuItem = null;
  }

  /**
   * This method calls paint.
   *
   * @param g
   *          The graphics context used to paint this menu item
   * @param c
   *          The menu item to paint
   */
  public void update(Graphics g, JComponent c)
  {
    paint(g, c);
  }

  /**
   * This class handles mouse events occuring inside the menu item. Most of the
   * events are forwarded for processing to MenuSelectionManager of the current
   * menu hierarchy.
   */
  protected class MouseInputHandler implements MouseInputListener
  {
    /**
     * Creates a new MouseInputHandler object.
     */
    protected MouseInputHandler()
    {
      // Nothing to do here.
    }

    /**
     * This method is called when mouse is clicked on the menu item. It forwards
     * this event to MenuSelectionManager.
     *
     * @param e
     *          A {@link MouseEvent}.
     */
    public void mouseClicked(MouseEvent e)
    {
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
      manager.processMouseEvent(e);
    }

    /**
     * This method is called when mouse is dragged inside the menu item. It
     * forwards this event to MenuSelectionManager.
     *
     * @param e
     *          A {@link MouseEvent}.
     */
    public void mouseDragged(MouseEvent e)
    {
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
      manager.processMouseEvent(e);
    }

    /**
     * This method is called when mouse enters menu item. When this happens menu
     * item is considered to be selected and selection path in
     * MenuSelectionManager is set. This event is also forwarded to
     * MenuSelection Manager for further processing.
     *
     * @param e
     *          A {@link MouseEvent}.
     */
    public void mouseEntered(MouseEvent e)
    {
      Component source = (Component) e.getSource();
      if (source.getParent() instanceof MenuElement)
        {
          MenuSelectionManager manager = MenuSelectionManager.defaultManager();
          manager.setSelectedPath(getPath());
          manager.processMouseEvent(e);
        }
    }

    /**
     * This method is called when mouse exits menu item. The event is forwarded
     * to MenuSelectionManager for processing.
     *
     * @param e
     *          A {@link MouseEvent}.
     */
    public void mouseExited(MouseEvent e)
    {
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
      manager.processMouseEvent(e);
    }

    /**
     * This method is called when mouse is inside the menu item. This event is
     * forwarder to MenuSelectionManager for further processing.
     *
     * @param e
     *          A {@link MouseEvent}.
     */
    public void mouseMoved(MouseEvent e)
    {
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
      manager.processMouseEvent(e);
    }

    /**
     * This method is called when mouse is pressed. This event is forwarded to
     * MenuSelectionManager for further processing.
     *
     * @param e
     *          A {@link MouseEvent}.
     */
    public void mousePressed(MouseEvent e)
    {
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
      manager.processMouseEvent(e);
    }

    /**
     * This method is called when mouse is released. If the mouse is released
     * inside this menuItem, then this menu item is considered to be chosen and
     * the menu hierarchy should be closed.
     *
     * @param e
     *          A {@link MouseEvent}.
     */
    public void mouseReleased(MouseEvent e)
    {
      MenuSelectionManager manager = MenuSelectionManager.defaultManager();
      int x = e.getX();
      int y = e.getY();
      if (x > 0 && x < menuItem.getWidth() && y > 0
          && y < menuItem.getHeight())
        {
          doClick(manager);
        }
      else
        manager.processMouseEvent(e);
    }
  }

  /**
   * This class handles mouse dragged events.
   */
  private class MenuDragMouseHandler implements MenuDragMouseListener
  {
    /**
     * Tbis method is invoked when mouse is dragged over the menu item.
     *
     * @param e
     *          The MenuDragMouseEvent
     */
    public void menuDragMouseDragged(MenuDragMouseEvent e)
    {
      MenuSelectionManager manager = e.getMenuSelectionManager();
      manager.setSelectedPath(e.getPath());
    }

    /**
     * Tbis method is invoked when mouse enters the menu item while it is being
     * dragged.
     *
     * @param e
     *          The MenuDragMouseEvent
     */
    public void menuDragMouseEntered(MenuDragMouseEvent e)
    {
      MenuSelectionManager manager = e.getMenuSelectionManager();
      manager.setSelectedPath(e.getPath());
    }

    /**
     * Tbis method is invoked when mouse exits the menu item while it is being
     * dragged
     *
     * @param e the MenuDragMouseEvent
     */
    public void menuDragMouseExited(MenuDragMouseEvent e)
    {
      // Nothing to do here yet.
    }

    /**
     * Tbis method is invoked when mouse was dragged and released inside the
     * menu item.
     *
     * @param e
     *          The MenuDragMouseEvent
     */
    public void menuDragMouseReleased(MenuDragMouseEvent e)
    {
      MenuSelectionManager manager = e.getMenuSelectionManager();
      int x = e.getX();
      int y = e.getY();
      if (x >= 0 && x < menuItem.getWidth() && y >= 0
          && y < menuItem.getHeight())
        doClick(manager);
      else
        manager.clearSelectedPath();
    }
  }

  /**
   * This class handles key events occuring when menu item is visible on the
   * screen.
   */
  private class MenuKeyHandler implements MenuKeyListener
  {
    /**
     * This method is invoked when key has been pressed
     *
     * @param e
     *          A {@link MenuKeyEvent}.
     */
    public void menuKeyPressed(MenuKeyEvent e)
    {
      // TODO: What should be done here, if anything?
    }

    /**
     * This method is invoked when key has been pressed
     *
     * @param e
     *          A {@link MenuKeyEvent}.
     */
    public void menuKeyReleased(MenuKeyEvent e)
    {
      // TODO: What should be done here, if anything?
    }

    /**
     * This method is invoked when key has been typed It handles the mnemonic
     * key for the menu item.
     *
     * @param e
     *          A {@link MenuKeyEvent}.
     */
    public void menuKeyTyped(MenuKeyEvent e)
    {
      // TODO: What should be done here, if anything?
    }
  }

  /**
   * Helper class that listens for item changes to the properties of the {@link
   * JMenuItem}.
   */
  private class ItemHandler implements ItemListener
  {
    /**
     * This method is called when one of the menu item changes.
     *
     * @param evt A {@link ItemEvent}.
     */
    public void itemStateChanged(ItemEvent evt)
    {
      boolean state = false;
      if (menuItem instanceof JCheckBoxMenuItem)
        {
          if (evt.getStateChange() == ItemEvent.SELECTED)
            state = true;
          ((JCheckBoxMenuItem) menuItem).setState(state);
        }
      menuItem.revalidate();
      menuItem.repaint();
    }
  }

  /**
   * A helper method to create the accelerator string from the menu item's
   * accelerator property. The returned string is empty if there is
   * no accelerator defined.
   *
   * @param m the menu item
   *
   * @return the accelerator string, not null
   */
  private String getAcceleratorString(JMenuItem m)
  {
    // Create accelerator string.
    KeyStroke accel = m.getAccelerator();
    String accelText = "";
    if (accel != null)
      {
        int mods = accel.getModifiers();
        if (mods > 0)
          {
            accelText = KeyEvent.getKeyModifiersText(mods);
            accelText += acceleratorDelimiter;
          }
        int keycode = accel.getKeyCode();
        if (keycode != 0)
          accelText += KeyEvent.getKeyText(keycode);
        else
          accelText += accel.getKeyChar();
      }
    return accelText;
  }

  /**
   * Resets the cached layout rectangles. If <code>i</code> is not null, then
   * the view rectangle is set to the inner area of the component, otherwise
   * it is set to (0, 0, Short.MAX_VALUE, Short.MAX_VALUE), this is needed
   * for layouting.
   *
   * @param i the component for which to initialize the rectangles
   */
  private void resetRectangles(JMenuItem i)
  {
    // Reset rectangles.
    iconRect.setBounds(0, 0, 0, 0);
    textRect.setBounds(0, 0, 0, 0);
    accelRect.setBounds(0, 0, 0, 0);
    checkIconRect.setBounds(0, 0, 0, 0);
    arrowIconRect.setBounds(0, 0, 0, 0);
    if (i == null)
      viewRect.setBounds(0, 0, Short.MAX_VALUE, Short.MAX_VALUE);
    else
      {
        Insets insets = i.getInsets();
        viewRect.setBounds(insets.left, insets.top,
                           i.getWidth() - insets.left - insets.right,
                           i.getHeight() - insets.top - insets.bottom);
      }
  }

  /**
   * A helper method that lays out the menu item. The layout is stored
   * in the fields of this class.
   *
   * @param m the menu item to layout
   * @param accelText the accelerator text
   */
  private void layoutMenuItem(JMenuItem m, String accelText)
  {
    // Fetch the fonts.
    Font font = m.getFont();
    FontMetrics fm = m.getFontMetrics(font);
    FontMetrics accelFm = m.getFontMetrics(acceleratorFont);

    String text = m.getText();
    SwingUtilities.layoutCompoundLabel(m, fm, text, m.getIcon(),
                                       m.getVerticalAlignment(),
                                       m.getHorizontalAlignment(),
                                       m.getVerticalTextPosition(),
                                       m.getHorizontalTextPosition(),
                                       viewRect, iconRect, textRect,
                                       defaultTextIconGap);

    // Initialize accelerator width and height.
    if (! accelText.equals(""))
      {
        accelRect.width = accelFm.stringWidth(accelText);
        accelRect.height = accelFm.getHeight();
      }

    // Initialize check and arrow icon width and height.
    if (! (m instanceof JMenu && ((JMenu) m).isTopLevelMenu()))
      {
        if (checkIcon != null)
          {
            checkIconRect.width = checkIcon.getIconWidth();
            checkIconRect.height = checkIcon.getIconHeight();
          }
        if (arrowIcon != null)
          {
            arrowIconRect.width = arrowIcon.getIconWidth();
            arrowIconRect.height = arrowIcon.getIconHeight();
          }
      }

    // The union of the icon and text of the menu item is the 'label area'.
    cachedRect.setBounds(textRect);
    Rectangle labelRect = SwingUtilities.computeUnion(iconRect.x,
                                                      iconRect.y,
                                                      iconRect.width,
                                                      iconRect.height,
                                                      cachedRect);
    textRect.x += defaultTextIconGap;
    iconRect.x += defaultTextIconGap;

    // Layout accelerator rect.
    accelRect.x = viewRect.x + viewRect.width - arrowIconRect.width
      - defaultTextIconGap - accelRect.width;
    // Layout check and arrow icons only when not in toplevel menu.
    if (! (m instanceof JMenu && ((JMenu) m).isTopLevelMenu()))
      {
        checkIconRect.x = viewRect.x + defaultTextIconGap;
        textRect.x += defaultTextIconGap + checkIconRect.width;
        iconRect.x += defaultTextIconGap + checkIconRect.width;
        arrowIconRect.x = viewRect.x + viewRect.width - defaultTextIconGap
          - arrowIconRect.width;
      }

    // Align the accelerator text and all the icons vertically centered to
    // the menu text.
    accelRect.y = labelRect.y + (labelRect.height / 2)
      - (accelRect.height / 2);
    if (! (m instanceof JMenu && ((JMenu) m).isTopLevelMenu()))
      {
        arrowIconRect.y = labelRect.y + (labelRect.height / 2)
          - (arrowIconRect.height / 2);
        checkIconRect.y = labelRect.y + (labelRect.height / 2)
          - (checkIconRect.height / 2);
      }
  }
}
