/* BasicComboBoxUI.java --
   Copyright (C) 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.plaf.basic;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.CellRendererPane;
import javax.swing.ComboBoxEditor;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;

/**
 * A UI delegate for the {@link JComboBox} component.
 *
 * @author Olga Rodimina
 * @author Robert Schuster
 */
public class BasicComboBoxUI extends ComboBoxUI
{
  /**
   * The arrow button that is displayed in the right side of JComboBox. This
   * button is used to hide and show combo box's list of items.
   */
  protected JButton arrowButton;

  /**
   * The combo box represented by this UI delegate.
   */
  protected JComboBox comboBox;

  /**
   * The component that is responsible for displaying/editing the selected 
   * item of the combo box. 
   * 
   * @see BasicComboBoxEditor#getEditorComponent()
   */
  protected Component editor;

  /**
   * A listener listening to focus events occurring in the {@link JComboBox}.
   */
  protected FocusListener focusListener;

  /**
   * A flag indicating whether JComboBox currently has the focus.
   */
  protected boolean hasFocus;

  /**
   * A listener listening to item events fired by the {@link JComboBox}.
   */
  protected ItemListener itemListener;

  /**
   * A listener listening to key events that occur while {@link JComboBox} has
   * the focus.
   */
  protected KeyListener keyListener;

  /**
   * List used when rendering selected item of the combo box. The selection
   * and foreground colors for combo box renderer are configured from this
   * list.
   */
  protected JList listBox;

  /**
   * ListDataListener listening to JComboBox model
   */
  protected ListDataListener listDataListener;

  /**
   * Popup list containing the combo box's menu items.
   */
  protected ComboPopup popup;
  
  protected KeyListener popupKeyListener;
  
  protected MouseListener popupMouseListener;
  
  protected MouseMotionListener popupMouseMotionListener;

  /**
   * Listener listening to changes in the bound properties of JComboBox
   */
  protected PropertyChangeListener propertyChangeListener;

  /* Size of the largest item in the comboBox
   * This is package-private to avoid an accessor method.
   */
  Dimension displaySize = new Dimension();

  /**
   * Used to render the combo box values.
   */
  protected CellRendererPane currentValuePane;

  /**
   * The current minimum size if isMinimumSizeDirty is false.
   * Setup by getMinimumSize() and invalidated by the various listeners.
   */
  protected Dimension cachedMinimumSize;

  /**
   * Indicates whether or not the cachedMinimumSize field is valid or not.
   */
  protected boolean isMinimumSizeDirty = true;

  /**
   * Creates a new <code>BasicComboBoxUI</code> object.
   */
  public BasicComboBoxUI()
  {
    currentValuePane = new CellRendererPane();
    cachedMinimumSize = new Dimension();
  }

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

  /**
   * Installs the UI for the given {@link JComponent}.
   *
   * @param c  the JComponent to install a UI for.
   * 
   * @see #uninstallUI(JComponent)
   */
  public void installUI(JComponent c)
  {
    super.installUI(c);

    if (c instanceof JComboBox)
      {
        isMinimumSizeDirty = true;
        comboBox = (JComboBox) c;
        installDefaults();

        // Set editor and renderer for the combo box. Editor is used
        // only if combo box becomes editable, otherwise renderer is used
        // to paint the selected item; combobox is not editable by default.
        ListCellRenderer renderer = comboBox.getRenderer();
        if (renderer == null || renderer instanceof UIResource)
          comboBox.setRenderer(createRenderer());

        ComboBoxEditor currentEditor = comboBox.getEditor();
        if (currentEditor == null || currentEditor instanceof UIResource)
          {
            currentEditor = createEditor();
            comboBox.setEditor(currentEditor);
          } 
        editor = currentEditor.getEditorComponent();

        installComponents();
        installListeners();
        if (arrowButton != null)
          configureArrowButton();
        if (editor != null)
          configureEditor();
        comboBox.setLayout(createLayoutManager());
        comboBox.setFocusable(true);
        installKeyboardActions();
        comboBox.putClientProperty(BasicLookAndFeel.DONT_CANCEL_POPUP,
                                   Boolean.TRUE);
      }
  }

  /**
   * Uninstalls the UI for the given {@link JComponent}.
   *
   * @param c The JComponent that is having this UI removed.
   * 
   * @see #installUI(JComponent)
   */
  public void uninstallUI(JComponent c)
  {
    setPopupVisible(comboBox, false);
    popup.uninstallingUI();
    uninstallKeyboardActions();
    comboBox.setLayout(null);
    uninstallComponents();
    uninstallListeners();
    uninstallDefaults();
    comboBox = null;
  }

  /**
   * Installs the defaults that are defined in the {@link BasicLookAndFeel} 
   * for this {@link JComboBox}.
   * 
   * @see #uninstallDefaults()
   */
  protected void installDefaults()
  {
    LookAndFeel.installColorsAndFont(comboBox, "ComboBox.background",
                                     "ComboBox.foreground", "ComboBox.font");
    LookAndFeel.installBorder(comboBox, "ComboBox.border");
  }

  /**
   * Creates and installs the listeners for this UI.
   * 
   * @see #uninstallListeners()
   */
  protected void installListeners()
  {
    // install combo box's listeners
    propertyChangeListener = createPropertyChangeListener();
    comboBox.addPropertyChangeListener(propertyChangeListener);

    focusListener = createFocusListener();
    comboBox.addFocusListener(focusListener);

    itemListener = createItemListener();
    comboBox.addItemListener(itemListener);

    keyListener = createKeyListener();
    comboBox.addKeyListener(keyListener);

    // install listeners that listen to combo box model
    listDataListener = createListDataListener();
    comboBox.getModel().addListDataListener(listDataListener);

    // Install mouse and key listeners from the popup.
    popupMouseListener = popup.getMouseListener();
    comboBox.addMouseListener(popupMouseListener);

    popupMouseMotionListener = popup.getMouseMotionListener();
    comboBox.addMouseMotionListener(popupMouseMotionListener);

    popupKeyListener = popup.getKeyListener();
    comboBox.addKeyListener(popupKeyListener);
  }

  /**
   * Uninstalls the defaults and sets any objects created during
   * install to <code>null</code>.
   * 
   * @see #installDefaults()
   */
  protected void uninstallDefaults()
  {
    if (comboBox.getFont() instanceof UIResource)
      comboBox.setFont(null);

    if (comboBox.getForeground() instanceof UIResource)
      comboBox.setForeground(null);
    
    if (comboBox.getBackground() instanceof UIResource)
      comboBox.setBackground(null);

    LookAndFeel.uninstallBorder(comboBox);
  }

  /**
   * Detaches all the listeners we attached in {@link #installListeners}.
   * 
   * @see #installListeners()
   */
  protected void uninstallListeners()
  {
    comboBox.removePropertyChangeListener(propertyChangeListener);
    propertyChangeListener = null;

    comboBox.removeFocusListener(focusListener);
    listBox.removeFocusListener(focusListener);
    focusListener = null;

    comboBox.removeItemListener(itemListener);
    itemListener = null;

    comboBox.removeKeyListener(keyListener);
    keyListener = null;

    comboBox.getModel().removeListDataListener(listDataListener);
    listDataListener = null;

    if (popupMouseListener != null)
      comboBox.removeMouseListener(popupMouseListener);
    popupMouseListener = null;

    if (popupMouseMotionListener != null)
      comboBox.removeMouseMotionListener(popupMouseMotionListener);
    popupMouseMotionListener = null;

    if (popupKeyListener != null)
      comboBox.removeKeyListener(popupKeyListener);
    popupKeyListener = null;
  }

  /**
   * Creates the popup that will contain list of combo box's items.
   *
   * @return popup containing list of combo box's items
   */
  protected ComboPopup createPopup()
  {
    return new BasicComboPopup(comboBox);
  }

  /**
   * Creates a {@link KeyListener} to listen to key events.
   *
   * @return KeyListener that listens to key events.
   */
  protected KeyListener createKeyListener()
  {
    return new KeyHandler();
  }

  /**
   * Creates the {@link FocusListener} that will listen to changes in this
   * JComboBox's focus.
   *
   * @return the FocusListener.
   */
  protected FocusListener createFocusListener()
  {
    return new FocusHandler();
  }

  /**
   * Creates a {@link ListDataListener} to listen to the combo box's data model.
   *
   * @return The new listener.
   */
  protected ListDataListener createListDataListener()
  {
    return new ListDataHandler();
  }

  /**
   * Creates an {@link ItemListener} that will listen to the changes in
   * the JComboBox's selection.
   *
   * @return The ItemListener
   */
  protected ItemListener createItemListener()
  {
    return new ItemHandler();
  }

  /**
   * Creates a {@link PropertyChangeListener} to listen to the changes in
   * the JComboBox's bound properties.
   *
   * @return The PropertyChangeListener
   */
  protected PropertyChangeListener createPropertyChangeListener()
  {
    return new PropertyChangeHandler();
  }

  /**
   * Creates and returns a layout manager for the combo box.  Subclasses can 
   * override this method to provide a different layout.
   *
   * @return a layout manager for the combo box.
   */
  protected LayoutManager createLayoutManager()
  {
    return new ComboBoxLayoutManager();
  }

  /**
   * Creates a component that will be responsible for rendering the
   * selected component in the combo box.
   *
   * @return A renderer for the combo box.
   */
  protected ListCellRenderer createRenderer()
  {
    return new BasicComboBoxRenderer.UIResource();
  }

  /**
   * Creates the component that will be responsible for displaying/editing
   * the selected item in the combo box. This editor is used only when combo 
   * box is editable.
   *
   * @return A new component that will be responsible for displaying/editing
   *         the selected item in the combo box.
   */
  protected ComboBoxEditor createEditor()
  {
    return new BasicComboBoxEditor.UIResource();
  }

  /**
   * Installs the components for this JComboBox. ArrowButton, main
   * part of combo box (upper part) and popup list of items are created and
   * configured here.
   */
  protected void installComponents()
  {
    // create drop down list of items
    popup = createPopup();
    listBox = popup.getList();

    // create and install arrow button
    arrowButton = createArrowButton();
    comboBox.add(arrowButton);

    if (comboBox.isEditable())
      addEditor();

    comboBox.add(currentValuePane);
  }

  /**
   * Uninstalls components from this {@link JComboBox}.
   * 
   * @see #installComponents()
   */
  protected void uninstallComponents()
  {
    // uninstall arrow button
    unconfigureArrowButton();
    comboBox.remove(arrowButton);
    arrowButton = null;

    popup = null;

    if (comboBox.getRenderer() instanceof UIResource)
      comboBox.setRenderer(null);

    // if the editor is not an instanceof UIResource, it was not set by the
    // UI delegate, so don't clear it...
    ComboBoxEditor currentEditor = comboBox.getEditor();
    if (currentEditor instanceof UIResource)
      {
        comboBox.setEditor(null);
        editor = null;
      }
  }

  /**
   * Adds the current editor to the combo box.
   */
  public void addEditor()
  {
    removeEditor();
    editor = comboBox.getEditor().getEditorComponent();
    comboBox.add(editor);
  }

  /**
   * Removes the current editor from the combo box.
   */
  public void removeEditor()
  {
    if (editor != null)
      {
        unconfigureEditor();
        comboBox.remove(editor);
      }
  }

  /**
   * Configures the editor for this combo box.
   */
  protected void configureEditor()
  {
    editor.setFont(comboBox.getFont());
    if (popupKeyListener != null)
      editor.addKeyListener(popupKeyListener);
    if (keyListener != null)
      editor.addKeyListener(keyListener);
    comboBox.configureEditor(comboBox.getEditor(),
                             comboBox.getSelectedItem());
  }

  /**
   * Unconfigures the editor for this combo box. 
   */
  protected void unconfigureEditor()
  {
    if (popupKeyListener != null)
      editor.removeKeyListener(popupKeyListener);
    if (keyListener != null)
      editor.removeKeyListener(keyListener);
  }

  /**
   * Configures the arrow button.
   * 
   * @see #configureArrowButton()
   */
  public void configureArrowButton()
  {
    if (arrowButton != null)
      {
        arrowButton.setEnabled(comboBox.isEnabled());
        arrowButton.setFocusable(false);
        if (popupMouseListener != null)
          arrowButton.addMouseListener(popupMouseListener);
        if (popupMouseMotionListener != null)
          arrowButton.addMouseMotionListener(popupMouseMotionListener);
        
        // Mark the button as not closing the popup, we handle this ourselves.
        arrowButton.putClientProperty(BasicLookAndFeel.DONT_CANCEL_POPUP,
                                      Boolean.TRUE);
      }
  }

  /**
   * Unconfigures the arrow button.
   * 
   * @see #configureArrowButton()
   *
   * @specnote The specification says this method is implementation specific
   *           and should not be used or overridden.
   */
  public void unconfigureArrowButton()
  {
    if (arrowButton != null)
      {
        if (popupMouseListener != null)
          arrowButton.removeMouseListener(popupMouseListener);
        if (popupMouseMotionListener != null)
          arrowButton.removeMouseMotionListener(popupMouseMotionListener);
      }
  }

  /**
   * Creates an arrow button for this {@link JComboBox}.  The arrow button is
   * displayed at the right end of the combo box and is used to display/hide
   * the drop down list of items.
   *
   * @return A new button.
   */
  protected JButton createArrowButton()
  {
    return new BasicArrowButton(BasicArrowButton.SOUTH);
  }

  /**
   * Returns <code>true</code> if the popup is visible, and <code>false</code>
   * otherwise.
   *
   * @param c The JComboBox to check
   *
   * @return <code>true</code> if popup part of the JComboBox is visible and 
   *         <code>false</code> otherwise.
   */
  public boolean isPopupVisible(JComboBox c)
  {
    return popup.isVisible();
  }

  /**
   * Displays/hides the {@link JComboBox}'s list of items on the screen.
   *
   * @param c The combo box, for which list of items should be
   *        displayed/hidden
   * @param v true if show popup part of the jcomboBox and false to hide.
   */
  public void setPopupVisible(JComboBox c, boolean v)
  {
    if (v)
      popup.show();
    else
      popup.hide();
  }

  /**
   * JComboBox is focus traversable if it is editable and not otherwise.
   *
   * @param c combo box for which to check whether it is focus traversable
   *
   * @return true if focus tranversable and false otherwise
   */
  public boolean isFocusTraversable(JComboBox c)
  {
    if (!comboBox.isEditable())
      return true;

    return false;
  }

  /**
   * Paints given menu item using specified graphics context
   *
   * @param g The graphics context used to paint this combo box
   * @param c comboBox which needs to be painted.
   */
  public void paint(Graphics g, JComponent c)
  {
    hasFocus = comboBox.hasFocus();
    if (! comboBox.isEditable())
      {
        Rectangle rect = rectangleForCurrentValue();
        paintCurrentValueBackground(g, rect, hasFocus);
        paintCurrentValue(g, rect, hasFocus);
      }
  }

  /**
   * Returns preferred size for the combo box.
   *
   * @param c comboBox for which to get preferred size
   *
   * @return The preferred size for the given combo box
   */
  public Dimension getPreferredSize(JComponent c)
  {
    return getMinimumSize(c);
  }

  /**
   * Returns the minimum size for this {@link JComboBox} for this
   * look and feel. Also makes sure cachedMinimimSize is setup correctly.
   *
   * @param c The {@link JComponent} to find the minimum size for.
   *
   * @return The dimensions of the minimum size.
   */
  public Dimension getMinimumSize(JComponent c)
  {
    if (isMinimumSizeDirty)
      {
        Insets i = getInsets();
        Dimension d = getDisplaySize();
        d.width += i.left + i.right + d.height;
        cachedMinimumSize = new Dimension(d.width, d.height + i.top + i.bottom);
        isMinimumSizeDirty = false;
      }
    return new Dimension(cachedMinimumSize);
  }

  /**
   * Returns the maximum size for this {@link JComboBox} for this
   * look and feel.
   *
   * @param c The {@link JComponent} to find the maximum size for
   *
   * @return The maximum size (<code>Dimension(32767, 32767)</code>).
   */
  public Dimension getMaximumSize(JComponent c)
  {
    return new Dimension(32767, 32767);
  }

  /**
   * Returns the number of accessible children of the combobox.
   *
   * @param c the component (combobox) to check, ignored
   *
   * @return the number of accessible children of the combobox
   */
  public int getAccessibleChildrenCount(JComponent c)
  {
    int count = 1;
    if (comboBox.isEditable())
      count = 2;
    return count;
  }

  /**
   * Returns the accessible child with the specified index.
   *
   * @param c the component, this is ignored
   * @param i the index of the accessible child to return
   */
  public Accessible getAccessibleChild(JComponent c, int i)
  {
    Accessible child = null;
    switch (i)
    {
      case 0: // The popup.
        if (popup instanceof Accessible)
          {
            AccessibleContext ctx = ((Accessible) popup).getAccessibleContext();
            ctx.setAccessibleParent(comboBox);
            child = (Accessible) popup;
          }
        break;
      case 1: // The editor, if any.
        if (comboBox.isEditable() && editor instanceof Accessible)
          {
            AccessibleContext ctx =
              ((Accessible) editor).getAccessibleContext();
            ctx.setAccessibleParent(comboBox);
            child = (Accessible) editor;
          }
        break;
    }
    return child;
  }

  /**
   * Returns true if the specified key is a navigation key and false otherwise
   *
   * @param keyCode a key for which to check whether it is navigation key or
   *        not.
   *
   * @return true if the specified key is a navigation key and false otherwis
   */
  protected boolean isNavigationKey(int keyCode)
  {
    return keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN
           || keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT
           || keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_ESCAPE
           || keyCode == KeyEvent.VK_TAB;
  }

  /**
   * Selects next possible item relative to the current selection
   * to be next selected item in the combo box.
   */
  protected void selectNextPossibleValue()
  {
    int index = comboBox.getSelectedIndex();
    if (index != comboBox.getItemCount() - 1)
      comboBox.setSelectedIndex(index + 1);
  }

  /**
   * Selects previous item relative to current selection to be
   * next selected item.
   */
  protected void selectPreviousPossibleValue()
  {
    int index = comboBox.getSelectedIndex();
    if (index > 0)
      comboBox.setSelectedIndex(index - 1);
  }

  /**
   * Displays combo box popup if the popup is not currently shown
   * on the screen and hides it if it is currently shown
   */
  protected void toggleOpenClose()
  {
    setPopupVisible(comboBox, ! isPopupVisible(comboBox));
  }

  /**
   * Returns the bounds in which comboBox's selected item will be
   * displayed.
   *
   * @return rectangle bounds in which comboBox's selected Item will be
   *         displayed
   */
  protected Rectangle rectangleForCurrentValue()
  {
    int w = comboBox.getWidth();
    int h = comboBox.getHeight();
    Insets i = comboBox.getInsets();
    int arrowSize = h - (i.top + i.bottom);
    if (arrowButton != null)
      arrowSize = arrowButton.getWidth();
    return new Rectangle(i.left, i.top, w - (i.left + i.right + arrowSize),
                         h - (i.top + i.left));
  }

  /**
   * Returns the insets of the current border.
   *
   * @return Insets representing space between combo box and its border
   */
  protected Insets getInsets()
  {
    return comboBox.getInsets();
  }

  /**
   * Paints currently selected value in the main part of the combo
   * box (part without popup).
   *
   * @param g graphics context
   * @param bounds Rectangle representing the size of the area in which
   *        selected item should be drawn
   * @param hasFocus true if combo box has focus and false otherwise
   */
  public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus)
  {
    Object currentValue = comboBox.getSelectedItem();
    boolean isPressed = arrowButton.getModel().isPressed();

    /* Gets the component to be drawn for the current value.
     * If there is currently no selected item we will take an empty
     * String as replacement.
     */
    ListCellRenderer renderer = comboBox.getRenderer();
    if (comboBox.getSelectedIndex() != -1)
      {
        Component comp;
        if (hasFocus && ! isPopupVisible(comboBox))
          {
            comp = renderer.getListCellRendererComponent(listBox,
                comboBox.getSelectedItem(), -1, true, false);
          }
        else
          {
            comp = renderer.getListCellRendererComponent(listBox,
                comboBox.getSelectedItem(), -1, false, false);
            Color bg = UIManager.getColor("ComboBox.disabledForeground");
            comp.setBackground(bg);
          }
        comp.setFont(comboBox.getFont());
        if (hasFocus && ! isPopupVisible(comboBox))
          {
            comp.setForeground(listBox.getSelectionForeground());
            comp.setBackground(listBox.getSelectionBackground());
          }
        else if (comboBox.isEnabled())
          {
            comp.setForeground(comboBox.getForeground());
            comp.setBackground(comboBox.getBackground());
          }
        else
          {
            Color fg = UIManager.getColor("ComboBox.disabledForeground");
            comp.setForeground(fg);
            Color bg = UIManager.getColor("ComboBox.disabledBackground");
            comp.setBackground(bg);
          }
        currentValuePane.paintComponent(g, comp, comboBox, bounds.x, bounds.y,
                                        bounds.width, bounds.height);
      }
  }

  /**
   * Paints the background of part of the combo box, where currently
   * selected value is displayed. If the combo box has focus this method
   * should also paint focus rectangle around the combo box.
   *
   * @param g graphics context
   * @param bounds Rectangle representing the size of the largest item  in the
   *        comboBox
   * @param hasFocus true if combo box has fox and false otherwise
   */
  public void paintCurrentValueBackground(Graphics g, Rectangle bounds,
                                          boolean hasFocus)
  {
    Color saved = g.getColor();
    if (comboBox.isEnabled())
      g.setColor(UIManager.getColor("UIManager.background"));
    else
      g.setColor(UIManager.getColor("UIManager.disabledBackground"));
    g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
    g.setColor(saved);
  }

  private static final ListCellRenderer DEFAULT_RENDERER
    = new DefaultListCellRenderer();

  /**
   * Returns the default size for the display area of a combo box that does 
   * not contain any elements.  This method returns the width and height of
   * a single space in the current font, plus a margin of 1 pixel. 
   *
   * @return The default display size.
   * 
   * @see #getDisplaySize()
   */
  protected Dimension getDefaultSize()
  {
    Component comp = DEFAULT_RENDERER.getListCellRendererComponent(listBox,
        " ", -1, false, false);
    currentValuePane.add(comp);
    comp.setFont(comboBox.getFont());
    Dimension d = comp.getPreferredSize();
    currentValuePane.remove(comp);
    return d;
  }

  /**
   * Returns the size of the display area for the combo box. This size will be 
   * the size of the combo box, not including the arrowButton.
   *
   * @return The size of the display area for the combo box.
   */
  protected Dimension getDisplaySize()
  {
    Dimension dim = new Dimension();
    ListCellRenderer renderer = comboBox.getRenderer();
    if (renderer == null)
      {
        renderer = DEFAULT_RENDERER;
      }
    
    Object prototype = comboBox.getPrototypeDisplayValue();
    if (prototype != null)
      {
        Component comp = renderer.getListCellRendererComponent(listBox, 
            prototype, -1, false, false);
        currentValuePane.add(comp);
        comp.setFont(comboBox.getFont());
        Dimension renderSize = comp.getPreferredSize();
        currentValuePane.remove(comp);
        dim.height = renderSize.height;
        dim.width = renderSize.width;
      }
    else
      {
        ComboBoxModel model = comboBox.getModel();
        int size = model.getSize();
        if (size > 0)
          {
            for (int i = 0; i < size; ++i)
              {
                Component comp = renderer.getListCellRendererComponent(listBox, 
                    model.getElementAt(i), -1, false, false);
                currentValuePane.add(comp);
                comp.setFont(comboBox.getFont());
                Dimension renderSize = comp.getPreferredSize();
                currentValuePane.remove(comp);
                dim.width = Math.max(dim.width, renderSize.width);
                dim.height = Math.max(dim.height, renderSize.height);
              }
          }
        else
          {
            dim = getDefaultSize();
            if (comboBox.isEditable())
              dim.width = 100;
          }
      }
    if (comboBox.isEditable())
      {
        Dimension editSize = editor.getPreferredSize();
        dim.width = Math.max(dim.width, editSize.width);
        dim.height = Math.max(dim.height, editSize.height);
      }
    displaySize.setSize(dim.width, dim.height);
    return dim;
  }

  /**
   * Installs the keyboard actions for the {@link JComboBox} as specified
   * by the look and feel.
   */
  protected void installKeyboardActions()
  {
    SwingUtilities.replaceUIInputMap(comboBox,
        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
        (InputMap) UIManager.get("ComboBox.ancestorInputMap"));
    // Install any action maps here.
  }
  
  /**
   * Uninstalls the keyboard actions for the {@link JComboBox} there were
   * installed by in {@link #installListeners}.
   */
  protected void uninstallKeyboardActions()
  {
    SwingUtilities.replaceUIInputMap(comboBox,
        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
    // Uninstall any action maps here.
  }

  /**
   * A {@link LayoutManager} used to position the sub-components of the
   * {@link JComboBox}.
   * 
   * @see BasicComboBoxUI#createLayoutManager()
   */
  public class ComboBoxLayoutManager implements LayoutManager
  {
    /**
     * Creates a new ComboBoxLayoutManager object.
     */
    public ComboBoxLayoutManager()
    {
      // Nothing to do here.
    }

    /**
     * Adds a component to the layout.  This method does nothing, since the
     * layout manager doesn't need to track the components.
     * 
     * @param name  the name to associate the component with (ignored).
     * @param comp  the component (ignored).
     */
    public void addLayoutComponent(String name, Component comp)
    {
      // Do nothing
    }

    /**
     * Removes a component from the layout.  This method does nothing, since
     * the layout manager doesn't need to track the components.
     * 
     * @param comp  the component.
     */
    public void removeLayoutComponent(Component comp)
    {
      // Do nothing
    }

    /**
     * Returns preferred layout size of the JComboBox.
     *
     * @param parent  the Container for which the preferred size should be 
     *                calculated.
     *
     * @return The preferred size for the given container
     */
    public Dimension preferredLayoutSize(Container parent)
    {
      return parent.getPreferredSize();
    }

    /**
     * Returns the minimum layout size.
     * 
     * @param parent  the container.
     * 
     * @return The minimum size.
     */
    public Dimension minimumLayoutSize(Container parent)
    {
      return parent.getMinimumSize();
    }

    /**
     * Arranges the components in the container.  It puts arrow
     * button right end part of the comboBox. If the comboBox is editable
     * then editor is placed to the left of arrow  button, starting from the
     * beginning.
     *
     * @param parent Container that should be layed out.
     */
    public void layoutContainer(Container parent)
    {
      // Position editor component to the left of arrow button if combo box is 
      // editable
      Insets i = getInsets();
      int arrowSize = comboBox.getHeight() - (i.top + i.bottom);
      int editorWidth = comboBox.getBounds().width - arrowSize;

      if (arrowButton != null)
        arrowButton.setBounds(comboBox.getWidth() - (i.right + arrowSize),
                              i.top, arrowSize, arrowSize);
      if (editor != null)
        editor.setBounds(rectangleForCurrentValue());
    }
  }

  /**
   * Handles focus changes occuring in the combo box. This class is
   * responsible for repainting combo box whenever focus is gained or lost
   * and also for hiding popup list of items whenever combo box loses its
   * focus.
   */
  public class FocusHandler extends Object implements FocusListener
  {
    /**
     * Creates a new FocusHandler object.
     */
    public FocusHandler()
    {
      // Nothing to do here.
    }

    /**
     * Invoked when combo box gains focus. It repaints main
     * part of combo box accordingly.
     *
     * @param e the FocusEvent
     */
    public void focusGained(FocusEvent e)
    {
      hasFocus = true;
      comboBox.repaint();
    }

    /**
     * Invoked when the combo box loses focus.  It repaints the main part
     * of the combo box accordingly and hides the popup list of items.
     *
     * @param e the FocusEvent
     */
    public void focusLost(FocusEvent e)
    {
      hasFocus = false;
      if (! e.isTemporary() && comboBox.isLightWeightPopupEnabled())
        setPopupVisible(comboBox, false);
      comboBox.repaint();
    }
  }

  /**
   * Handles {@link ItemEvent}s fired by the {@link JComboBox} when its 
   * selected item changes.
   */
  public class ItemHandler extends Object implements ItemListener
  {
    /**
     * Creates a new ItemHandler object.
     */
    public ItemHandler()
    {
      // Nothing to do here.
    }

    /**
     * Invoked when selected item becomes deselected or when
     * new item becomes selected.
     *
     * @param e the ItemEvent representing item's state change.
     */
    public void itemStateChanged(ItemEvent e)
    {
      ComboBoxModel model = comboBox.getModel();
      Object v = model.getSelectedItem();
      if (editor != null)
        comboBox.configureEditor(comboBox.getEditor(), v);
      comboBox.repaint();
    }
  }

  /**
   * KeyHandler handles key events occuring while JComboBox has focus.
   */
  public class KeyHandler extends KeyAdapter
  {
    public KeyHandler()
    {
      // Nothing to do here.
    }

    /**
     * Invoked whenever key is pressed while JComboBox is in focus.
     */
    public void keyPressed(KeyEvent e)
    {
      if (comboBox.getModel().getSize() != 0 && comboBox.isEnabled())
        {
          if (! isNavigationKey(e.getKeyCode()))
            {
              if (! comboBox.isEditable())
                if (comboBox.selectWithKeyChar(e.getKeyChar()))
                  e.consume();
            }
          else
            {
              if (e.getKeyCode() == KeyEvent.VK_UP && comboBox.isPopupVisible())
                selectPreviousPossibleValue();
              else if (e.getKeyCode() == KeyEvent.VK_DOWN)
                {
                  if (comboBox.isPopupVisible())
                    selectNextPossibleValue();
                  else
                    comboBox.showPopup();
                }
              else if (e.getKeyCode() == KeyEvent.VK_ENTER
                       || e.getKeyCode() == KeyEvent.VK_ESCAPE)
                popup.hide();
            }
        }
    }
  }

  /**
   * Handles the changes occurring in the JComboBox's data model.
   */
  public class ListDataHandler extends Object implements ListDataListener
  {
    /**
     * Creates a new ListDataHandler object.
     */
    public ListDataHandler()
    {
      // Nothing to do here.
    }

    /**
     * Invoked if the content's of JComboBox's data model are changed.
     *
     * @param e ListDataEvent describing the change.
     */
    public void contentsChanged(ListDataEvent e)
    {
      if (e.getIndex0() != -1 || e.getIndex1() != -1)
        {
          isMinimumSizeDirty = true;
          comboBox.revalidate();
        }
      if (editor != null)
        comboBox.configureEditor(comboBox.getEditor(),
            comboBox.getSelectedItem());
      comboBox.repaint();
    }

    /**
     * Invoked when items are added to the JComboBox's data model.
     *
     * @param e ListDataEvent describing the change.
     */
    public void intervalAdded(ListDataEvent e)
    {
      int start = e.getIndex0();
      int end = e.getIndex1();
      if (start == 0 && comboBox.getItemCount() - (end - start + 1) == 0)
        contentsChanged(e);
      else if (start != -1  || end != -1)
        {
          ListCellRenderer renderer = comboBox.getRenderer();
          ComboBoxModel model = comboBox.getModel();
          int w = displaySize.width;
          int h = displaySize.height;
          // TODO: Optimize using prototype here.
          for (int i = start; i <= end; ++i)
            {
              Component comp = renderer.getListCellRendererComponent(listBox,
                  model.getElementAt(i), -1, false, false);
              currentValuePane.add(comp);
              comp.setFont(comboBox.getFont());
              Dimension dim = comp.getPreferredSize();
              w = Math.max(w, dim.width);
              h = Math.max(h, dim.height);
              currentValuePane.remove(comp);
            }
          if (displaySize.width < w || displaySize.height < h)
            {
              if (displaySize.width < w)
                displaySize.width = w;
              if (displaySize.height < h)
                displaySize.height = h;
              comboBox.revalidate();
              if (editor != null)
                {
                  comboBox.configureEditor(comboBox.getEditor(),
                                           comboBox.getSelectedItem());
                }
            }
        }
      
    }

    /**
     * Invoked when items are removed from the JComboBox's
     * data model.
     *
     * @param e ListDataEvent describing the change.
     */
    public void intervalRemoved(ListDataEvent e)
    {
      contentsChanged(e);
    }
  }

  /**
   * Handles {@link PropertyChangeEvent}s fired by the {@link JComboBox}.
   */
  public class PropertyChangeHandler extends Object
    implements PropertyChangeListener
  {
    /**
     * Creates a new instance.
     */
    public PropertyChangeHandler()
    {
      // Nothing to do here.
    }

    /**
     * Invoked whenever bound property of JComboBox changes.
     * 
     * @param e  the event.
     */
    public void propertyChange(PropertyChangeEvent e)
    {
      // Lets assume every change invalidates the minimumsize.
      isMinimumSizeDirty = true;

      if (e.getPropertyName().equals("enabled"))
        {
          arrowButton.setEnabled(comboBox.isEnabled());

          if (comboBox.isEditable())
            comboBox.getEditor().getEditorComponent().setEnabled(
                comboBox.isEnabled());
        }
      else if (e.getPropertyName().equals("editable"))
        {
          if (comboBox.isEditable())
            {
              configureEditor();
              addEditor();
            }
          else
            {
              unconfigureEditor();
              removeEditor();
            }

          comboBox.revalidate();
          comboBox.repaint();
        }
      else if (e.getPropertyName().equals("dataModel"))
        {
          // remove ListDataListener from old model and add it to new model
          ComboBoxModel oldModel = (ComboBoxModel) e.getOldValue();
          if (oldModel != null)
            oldModel.removeListDataListener(listDataListener);

          if ((ComboBoxModel) e.getNewValue() != null)
            comboBox.getModel().addListDataListener(listDataListener);
        }
      else if (e.getPropertyName().equals("font"))
        {
          Font font = (Font) e.getNewValue();
          editor.setFont(font);
          listBox.setFont(font);
          arrowButton.setFont(font);
          comboBox.revalidate();
          comboBox.repaint();
        }

      // FIXME: Need to handle changes in other bound properties.       
    }
  }
}
