/* BasicOptionPaneUI.java --
   Copyright (C) 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 java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Polygon;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.OptionPaneUI;

/**
 * This class is the UI delegate for JOptionPane in the Basic Look and Feel.
 */
public class BasicOptionPaneUI extends OptionPaneUI
{
  /**
   * This is a helper class that listens to the buttons located at the bottom
   * of the JOptionPane.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public class ButtonActionListener implements ActionListener
  {
    /** The index of the option this button represents. */
    protected int buttonIndex;

    /**
     * Creates a new ButtonActionListener object with the given buttonIndex.
     *
     * @param buttonIndex The index of the option this button represents.
     */
    public ButtonActionListener(int buttonIndex)
    {
      this.buttonIndex = buttonIndex;
    }

    /**
     * This method is called when one of the option buttons are pressed.
     *
     * @param e The ActionEvent.
     */
    public void actionPerformed(ActionEvent e)
    {
      Object value = new Integer(JOptionPane.CLOSED_OPTION);
      Object[] options = optionPane.getOptions();
      if (options != null)
	value = new Integer(buttonIndex);
      else
        {
	  String text = ((JButton) e.getSource()).getText();
	  if (text.equals(OK_STRING))
	    value = new Integer(JOptionPane.OK_OPTION);
	  if (text.equals(CANCEL_STRING))
	    value = new Integer(JOptionPane.CANCEL_OPTION);
	  if (text.equals(YES_STRING))
	    value = new Integer(JOptionPane.YES_OPTION);
	  if (text.equals(NO_STRING))
	    value = new Integer(JOptionPane.NO_OPTION);
        }
      optionPane.setValue(value);
      resetInputValue();

      Window owner = SwingUtilities.windowForComponent(optionPane);

      if (owner instanceof JDialog)
	((JDialog) owner).dispose();

      //else we probably have some kind of internal frame.
      JInternalFrame inf = (JInternalFrame) SwingUtilities.getAncestorOfClass(JInternalFrame.class,
                                                                              optionPane);
      if (inf != null)
        {
          try
            {
              inf.setClosed(true);
            }
          catch (PropertyVetoException pve)
            {
              // We do nothing if attempt has been vetoed.
            }
        }
    }
  }

  /**
   * This helper layout manager is responsible for the layout of the button
   * area. The button area is the panel that holds the buttons which
   * represent the options.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public static class ButtonAreaLayout implements LayoutManager
  {
    /** Whether this layout will center the buttons. */
    protected boolean centersChildren = true;

    /** The space between the buttons. */
    protected int padding;

    /** Whether the buttons will share the same widths. */
    protected boolean syncAllWidths;

    /** The width of the widest button. */
    private transient int widthOfWidestButton;

    /** The height of the tallest button. */
    private transient int tallestButton;

    /**
     * Creates a new ButtonAreaLayout object with the given sync widths
     * property and padding.
     *
     * @param syncAllWidths Whether the buttons will share the same widths.
     * @param padding The padding between the buttons.
     */
    public ButtonAreaLayout(boolean syncAllWidths, int padding)
    {
      this.syncAllWidths = syncAllWidths;
      this.padding = padding;
    }

    /**
     * This method is called when a component is added to the container.
     *
     * @param string The constraints string.
     * @param comp The component added.
     */
    public void addLayoutComponent(String string, Component comp)
    {
      // Do nothing.
    }

    /**
     * This method returns whether the children will be centered.
     *
     * @return Whether the children will be centered.
     */
    public boolean getCentersChildren()
    {
      return centersChildren;
    }

    /**
     * This method returns the amount of space between components.
     *
     * @return The amount of space between components.
     */
    public int getPadding()
    {
      return padding;
    }

    /**
     * This method returns whether all components will share widths (set to
     * largest width).
     *
     * @return Whether all components will share widths.
     */
    public boolean getSyncAllWidths()
    {
      return syncAllWidths;
    }

    /**
     * This method lays out the given container.
     *
     * @param container The container to lay out.
     */
    public void layoutContainer(Container container)
    {
      Component[] buttonList = container.getComponents();
      int x = container.getInsets().left;
      if (getCentersChildren())
	x += (int) ((double) (container.getSize().width) / 2
	- (double) (buttonRowLength(container)) / 2);
      for (int i = 0; i < buttonList.length; i++)
        {
	  Dimension dims = buttonList[i].getPreferredSize();
	  if (syncAllWidths)
	    {
	      buttonList[i].setBounds(x, 0, widthOfWidestButton, dims.height);
	      x += widthOfWidestButton + getPadding();
	    }
	  else
	    {
	      buttonList[i].setBounds(x, 0, dims.width, dims.height);
	      x += dims.width + getPadding();
	    }
        }
    }

    /**
     * This method returns the width of the given container taking into
     * consideration the padding and syncAllWidths.
     *
     * @param c The container to calculate width for.
     *
     * @return The width of the given container.
     */
    private int buttonRowLength(Container c)
    {
      Component[] buttonList = c.getComponents();

      int buttonLength = 0;
      int widest = 0;
      int tallest = 0;

      for (int i = 0; i < buttonList.length; i++)
        {
	  Dimension dims = buttonList[i].getPreferredSize();
	  buttonLength += dims.width + getPadding();
	  widest = Math.max(widest, dims.width);
	  tallest = Math.max(tallest, dims.height);
        }

      widthOfWidestButton = widest;
      tallestButton = tallest;

      int width;
      if (getSyncAllWidths())
	width = widest * buttonList.length
	        + getPadding() * (buttonList.length - 1);
      else
	width = buttonLength;

      Insets insets = c.getInsets();
      width += insets.left + insets.right;

      return width;
    }

    /**
     * This method returns the minimum layout size for the given container.
     *
     * @param c The container to measure.
     *
     * @return The minimum layout size.
     */
    public Dimension minimumLayoutSize(Container c)
    {
      return preferredLayoutSize(c);
    }

    /**
     * This method returns the preferred size of the given container.
     *
     * @param c The container to measure.
     *
     * @return The preferred size.
     */
    public Dimension preferredLayoutSize(Container c)
    {
      int w = buttonRowLength(c);

      return new Dimension(w, tallestButton);
    }

    /**
     * This method removes the given component from the layout manager's
     * knowledge.
     *
     * @param c The component to remove.
     */
    public void removeLayoutComponent(Component c)
    {
      // Do nothing.
    }

    /**
     * This method sets whether the children will be centered.
     *
     * @param newValue Whether the children will be centered.
     */
    public void setCentersChildren(boolean newValue)
    {
      centersChildren = newValue;
    }

    /**
     * This method sets the amount of space between each component.
     *
     * @param newPadding The padding between components.
     */
    public void setPadding(int newPadding)
    {
      padding = newPadding;
    }

    /**
     * This method sets whether the widths will be synced.
     *
     * @param newValue Whether the widths will be synced.
     */
    public void setSyncAllWidths(boolean newValue)
    {
      syncAllWidths = newValue;
    }
  }

  /**
   * This helper class handles property change events from the JOptionPane.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public class PropertyChangeHandler implements PropertyChangeListener
  {
    /**
     * This method is called when one of the properties of the JOptionPane
     * changes.
     *
     * @param e The PropertyChangeEvent.
     */
    public void propertyChange(PropertyChangeEvent e)
    {
      if (e.getPropertyName().equals(JOptionPane.ICON_PROPERTY)
          || e.getPropertyName().equals(JOptionPane.MESSAGE_TYPE_PROPERTY))
	addIcon(messageAreaContainer);
      else if (e.getPropertyName().equals(JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY))
	resetSelectedValue();
      else if (e.getPropertyName().equals(JOptionPane.INITIAL_VALUE_PROPERTY)
               || e.getPropertyName().equals(JOptionPane.OPTIONS_PROPERTY)
               || e.getPropertyName().equals(JOptionPane.OPTION_TYPE_PROPERTY))
        {
	  Container newButtons = createButtonArea();
	  optionPane.remove(buttonContainer);
	  optionPane.add(newButtons);
	  buttonContainer = newButtons;
        }

      else if (e.getPropertyName().equals(JOptionPane.MESSAGE_PROPERTY)
               || e.getPropertyName().equals(JOptionPane.WANTS_INPUT_PROPERTY)
               || e.getPropertyName().equals(JOptionPane.SELECTION_VALUES_PROPERTY))
        {
          optionPane.remove(messageAreaContainer);
          messageAreaContainer = createMessageArea();
          optionPane.add(messageAreaContainer);
          Container newButtons = createButtonArea();
          optionPane.remove(buttonContainer);
          optionPane.add(newButtons);
          buttonContainer = newButtons;
          optionPane.add(buttonContainer);
        }
      optionPane.invalidate();
      optionPane.repaint();
    }
  }

  /**
   * The minimum width for JOptionPanes.
   */
  public static final int MinimumWidth = 262;

  /**
   * The minimum height for JOptionPanes.
   */
  public static final int MinimumHeight = 90;

  /** Whether the JOptionPane contains custom components. */
  protected boolean hasCustomComponents = false;

  // The initialFocusComponent seems to always be set to a button (even if 
  // I try to set initialSelectionValue). This is different from what the 
  // javadocs state (which should switch this reference to the input component 
  // if one is present since that is what's going to get focus). 

  /**
   * The button that will receive focus based on initialValue when no input
   * component is present. If an input component is present, then the input
   * component will receive focus instead.
   */
  protected Component initialFocusComponent;

  /** The component that receives input when the JOptionPane needs it. */
  protected JComponent inputComponent;

  /** The minimum dimensions of the JOptionPane. */
  protected Dimension minimumSize;

  /** The propertyChangeListener for the JOptionPane. */
  protected PropertyChangeListener propertyChangeListener;

  /** The JOptionPane this UI delegate is used for. */
  protected JOptionPane optionPane;

  /** The size of the icons. */
  // FIXME: wrong name for a constant.
  private static final int iconSize = 36;

  /** The foreground color for the message area. */
  private transient Color messageForeground;

  /** The border around the message area. */
  private transient Border messageBorder;

  /** The border around the button area. */
  private transient Border buttonBorder;

  /** The string used to describe OK buttons. */
  private static final String OK_STRING = "OK";

  /** The string used to describe Yes buttons. */
  private static final String YES_STRING = "Yes";

  /** The string used to describe No buttons. */
  private static final String NO_STRING = "No";

  /** The string used to describe Cancel buttons. */
  private static final String CANCEL_STRING = "Cancel";

  /** The container for the message area.
   * This is package-private to avoid an accessor method. */
  transient Container messageAreaContainer;

  /** The container for the buttons.
   * This is package-private to avoid an accessor method.  */
  transient Container buttonContainer;

  /**
   * A helper class that implements Icon. This is used temporarily until
   * ImageIcons are fixed.
   */
  private static class MessageIcon implements Icon
  {
    /**
     * This method returns the width of the icon.
     *
     * @return The width of the icon.
     */
    public int getIconWidth()
    {
      return iconSize;
    }

    /**
     * This method returns the height of the icon.
     *
     * @return The height of the icon.
     */
    public int getIconHeight()
    {
      return iconSize;
    }

    /**
     * This method paints the icon as a part of the given component using the
     * given graphics and the given x and y position.
     *
     * @param c The component that owns this icon.
     * @param g The Graphics object to paint with.
     * @param x The x coordinate.
     * @param y The y coordinate.
     */
    public void paintIcon(Component c, Graphics g, int x, int y)
    {
      // Nothing to do here.
    }
  }

  /** The icon displayed for ERROR_MESSAGE. */
  private static MessageIcon errorIcon = new MessageIcon()
    {
      public void paintIcon(Component c, Graphics g, int x, int y)
      {
	Polygon oct = new Polygon(new int[] { 0, 0, 9, 27, 36, 36, 27, 9 },
	                          new int[] { 9, 27, 36, 36, 27, 9, 0, 0 }, 8);
	g.translate(x, y);

	Color saved = g.getColor();
	g.setColor(Color.RED);

	g.fillPolygon(oct);

	g.setColor(Color.BLACK);
	g.drawRect(13, 16, 10, 4);

	g.setColor(saved);
	g.translate(-x, -y);
      }
    };

  /** The icon displayed for INFORMATION_MESSAGE. */
  private static MessageIcon infoIcon = new MessageIcon()
    {
      public void paintIcon(Component c, Graphics g, int x, int y)
      {
	g.translate(x, y);
	Color saved = g.getColor();

	// Should be purple.
	g.setColor(Color.RED);

	g.fillOval(0, 0, iconSize, iconSize);

	g.setColor(Color.BLACK);
	g.drawOval(16, 6, 4, 4);

	Polygon bottomI = new Polygon(new int[] { 15, 15, 13, 13, 23, 23, 21, 21 },
	                              new int[] { 12, 28, 28, 30, 30, 28, 28, 12 },
	                              8);
	g.drawPolygon(bottomI);

	g.setColor(saved);
	g.translate(-x, -y);
      }
    };

  /** The icon displayed for WARNING_MESSAGE. */
  private static MessageIcon warningIcon = new MessageIcon()
    {
      public void paintIcon(Component c, Graphics g, int x, int y)
      {
	g.translate(x, y);
	Color saved = g.getColor();
	g.setColor(Color.YELLOW);

	Polygon triangle = new Polygon(new int[] { 0, 18, 36 },
	                               new int[] { 36, 0, 36 }, 3);
	g.fillPolygon(triangle);

	g.setColor(Color.BLACK);

	Polygon excl = new Polygon(new int[] { 15, 16, 20, 21 },
	                           new int[] { 8, 26, 26, 8 }, 4);
	g.drawPolygon(excl);
	g.drawOval(16, 30, 4, 4);

	g.setColor(saved);
	g.translate(-x, -y);
      }
    };

  /** The icon displayed for MESSAGE_ICON. */
  private static MessageIcon questionIcon = new MessageIcon()
    {
      public void paintIcon(Component c, Graphics g, int x, int y)
      {
	g.translate(x, y);
	Color saved = g.getColor();
	g.setColor(Color.GREEN);

	g.fillRect(0, 0, iconSize, iconSize);

	g.setColor(Color.BLACK);

	g.drawOval(11, 2, 16, 16);
	g.drawOval(14, 5, 10, 10);

	g.setColor(Color.GREEN);
	g.fillRect(0, 10, iconSize, iconSize - 10);

	g.setColor(Color.BLACK);

	g.drawLine(11, 10, 14, 10);

	g.drawLine(24, 10, 17, 22);
	g.drawLine(27, 10, 20, 22);
	g.drawLine(17, 22, 20, 22);

	g.drawOval(17, 25, 3, 3);

	g.setColor(saved);
	g.translate(-x, -y);
      }
    };

  // FIXME: Uncomment when the ImageIcons are fixed.

  /*  IconUIResource warningIcon, questionIcon, infoIcon, errorIcon;*/

  /**
   * Creates a new BasicOptionPaneUI object.
   */
  public BasicOptionPaneUI()
  {
    // Nothing to do here.
  }

  /**
   * This method is messaged to add the buttons to the given container.
   *
   * @param container The container to add components to.
   * @param buttons The buttons to add. (If it is an instance of component,
   *        the Object is added directly. If it is an instance of Icon, it is
   *        packed into a label and added. For all other cases, the string
   *        representation of the Object is retreived and packed into a
   *        label.)
   * @param initialIndex The index of the component that is the initialValue.
   */
  protected void addButtonComponents(Container container, Object[] buttons,
                                     int initialIndex)
  {
    if (buttons == null)
      return;
    for (int i = 0; i < buttons.length; i++)
      {
	if (buttons[i] != null)
	  {
	    Component toAdd;
	    if (buttons[i] instanceof Component)
	      toAdd = (Component) buttons[i];
	    else
	      {
		if (buttons[i] instanceof Icon)
		  toAdd = new JButton((Icon) buttons[i]);
		else
		  toAdd = new JButton(buttons[i].toString());
		hasCustomComponents = true;
	      }
	    if (toAdd instanceof JButton)
	      ((JButton) toAdd).addActionListener(createButtonActionListener(i));
	    if (i == initialIndex)
	      initialFocusComponent = toAdd;
	    container.add(toAdd);
	  }
      }
    selectInitialValue(optionPane);
  }

  /**
   * This method adds the appropriate icon the given container.
   *
   * @param top The container to add an icon to.
   */
  protected void addIcon(Container top)
  {
    JLabel iconLabel = null;
    Icon icon = getIcon();
    if (icon != null)
      {
	iconLabel = new JLabel(icon);
	top.add(iconLabel, BorderLayout.WEST);
      }
  }

  /**
   * A helper method that returns an instance of GridBagConstraints to be used
   * for creating the message area.
   *
   * @return An instance of GridBagConstraints.
   */
  private static GridBagConstraints createConstraints()
  {
    GridBagConstraints constraints = new GridBagConstraints();
    constraints.gridx = GridBagConstraints.REMAINDER;
    constraints.gridy = GridBagConstraints.REMAINDER;
    constraints.gridwidth = 0;
    constraints.anchor = GridBagConstraints.LINE_START;
    constraints.fill = GridBagConstraints.NONE;
    constraints.insets = new Insets(0, 0, 3, 0);

    return constraints;
  }

  /**
   * This method creates the proper object (if necessary) to represent msg.
   * (If msg is an instance of Component, it will add it directly. If it is
   * an icon, then it will pack it in a label and add it. Otherwise, it gets
   * treated as a string. If the string is longer than maxll, a box is
   * created and the burstStringInto is called with the box as the container.
   * The box is then added to the given container. Otherwise, the string is
   * packed in a label and placed in the given container.) This method is
   * also used for adding the inputComponent to the container.
   *
   * @param container The container to add to.
   * @param cons The constraints when adding.
   * @param msg The message to add.
   * @param maxll The max line length.
   * @param internallyCreated Whether the msg is internally created.
   */
  protected void addMessageComponents(Container container,
                                      GridBagConstraints cons, Object msg,
                                      int maxll, boolean internallyCreated)
  {
    if (msg == null)
      return;
    hasCustomComponents = internallyCreated;
    if (msg instanceof Object[])
      {
	Object[] arr = (Object[]) msg;
	for (int i = 0; i < arr.length; i++)
	  addMessageComponents(container, cons, arr[i], maxll,
	                       internallyCreated);
	return;
      }
    else if (msg instanceof Component)
      {
	container.add((Component) msg, cons);
	cons.gridy++;
      }
    else if (msg instanceof Icon)
      {
	container.add(new JLabel((Icon) msg), cons);
	cons.gridy++;
      }
    else
      {
	// Undocumented behaviour.
	// if msg.toString().length greater than maxll
	// it will create a box and burst the string.
	// otherwise, it will just create a label and re-call 
	// this method with the label o.O
	if (msg.toString().length() > maxll)
	  {
	    Box tmp = new Box(BoxLayout.Y_AXIS);
	    burstStringInto(tmp, msg.toString(), maxll);
	    addMessageComponents(container, cons, tmp, maxll, true);
	  }
	else
	  addMessageComponents(container, cons, new JLabel(msg.toString()),
	                       maxll, true);
      }
  }

  /**
   * This method creates instances of d (recursively if necessary based on
   * maxll) and adds to c.
   *
   * @param c The container to add to.
   * @param d The string to burst.
   * @param maxll The max line length.
   */
  protected void burstStringInto(Container c, String d, int maxll)
  {
    // FIXME: Verify that this is the correct behaviour.
    // One interpretation of the spec is that this method
    // should recursively call itself to create (and add) 
    // JLabels to the container if the length of the String d
    // is greater than maxll.
    // but in practice, even with a really long string, this is 
    // all that happens.
    if (d == null || c == null)
      return;
    JLabel label = new JLabel(d);
    c.add(label);
  }

  /**
   * This method returns true if the given JOptionPane contains custom
   * components.
   *
   * @param op The JOptionPane to check.
   *
   * @return True if the JOptionPane contains custom components.
   */
  public boolean containsCustomComponents(JOptionPane op)
  {
    return hasCustomComponents;
  }

  /**
   * This method creates a button action listener for the given button index.
   *
   * @param buttonIndex The index of the button in components.
   *
   * @return A new ButtonActionListener.
   */
  protected ActionListener createButtonActionListener(int buttonIndex)
  {
    return new ButtonActionListener(buttonIndex);
  }

  /**
   * This method creates the button area.
   *
   * @return A new Button Area.
   */
  protected Container createButtonArea()
  {
    JPanel buttonPanel = new JPanel();

    buttonPanel.setLayout(createLayoutManager());
    addButtonComponents(buttonPanel, getButtons(), getInitialValueIndex());

    return buttonPanel;
  }

  /**
   * This method creates a new LayoutManager for the button area.
   *
   * @return A new LayoutManager for the button area.
   */
  protected LayoutManager createLayoutManager()
  {
    return new ButtonAreaLayout(getSizeButtonsToSameWidth(), 6);
  }

  /**
   * This method creates the message area.
   *
   * @return A new message area.
   */
  protected Container createMessageArea()
  {
    JPanel messageArea = new JPanel();
    messageArea.setLayout(new BorderLayout());
    addIcon(messageArea);

    JPanel rightSide = new JPanel();
    rightSide.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    rightSide.setLayout(new GridBagLayout());
    GridBagConstraints con = createConstraints();
    
    addMessageComponents(rightSide, con, getMessage(),
                         getMaxCharactersPerLineCount(), false);

    if (optionPane.getWantsInput())
      {
	Object[] selection = optionPane.getSelectionValues();

	if (selection == null)
          inputComponent = new JTextField(15);
	else if (selection.length < 20)
          inputComponent = new JComboBox(selection);
	else
	  inputComponent = new JList(selection);
	if (inputComponent != null)
	  {
	    addMessageComponents(rightSide, con, inputComponent,
                                 getMaxCharactersPerLineCount(), false);
	    resetSelectedValue();
	    selectInitialValue(optionPane);
	  }
      }

    messageArea.add(rightSide, BorderLayout.CENTER);

    return messageArea;
  }

  /**
   * This method creates a new PropertyChangeListener for listening to the
   * JOptionPane.
   *
   * @return A new PropertyChangeListener.
   */
  protected PropertyChangeListener createPropertyChangeListener()
  {
    return new PropertyChangeHandler();
  }

  /**
   * This method creates a Container that will separate the message and button
   * areas.
   *
   * @return A Container that will separate the message and button areas.
   */
  protected Container createSeparator()
  {
    // FIXME: Figure out what this method is supposed to return and where
    // this should be added to the OptionPane.
    return null;
  }

  /**
   * This method creates a new BasicOptionPaneUI for the given component.
   *
   * @param x The component to create a UI for.
   *
   * @return A new BasicOptionPaneUI.
   */
  public static ComponentUI createUI(JComponent x)
  {
    return new BasicOptionPaneUI();
  }

  /**
   * This method returns the buttons for the JOptionPane. If no options are
   * set, a set of options will be created based upon the optionType.
   *
   * @return The buttons that will be added.
   */
  protected Object[] getButtons()
  {
    if (optionPane.getOptions() != null)
      return optionPane.getOptions();
    switch (optionPane.getOptionType())
      {
      case JOptionPane.YES_NO_OPTION:
	return new Object[] { YES_STRING, NO_STRING };
      case JOptionPane.YES_NO_CANCEL_OPTION:
	return new Object[] { YES_STRING, NO_STRING, CANCEL_STRING };
      case JOptionPane.OK_CANCEL_OPTION:
	return new Object[] { OK_STRING, CANCEL_STRING };
      case JOptionPane.DEFAULT_OPTION:
        return (optionPane.getWantsInput() ) ?
               new Object[] { OK_STRING, CANCEL_STRING } :
               ( optionPane.getMessageType() == JOptionPane.QUESTION_MESSAGE ) ?
               new Object[] { YES_STRING, NO_STRING, CANCEL_STRING } :
               // ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE
               new Object[] { OK_STRING };
      }
    return null;
  }

  /**
   * This method will return the icon the user has set or the icon that will
   * be used based on message type.
   *
   * @return The icon to use in the JOptionPane.
   */
  protected Icon getIcon()
  {
    if (optionPane.getIcon() != null)
      return optionPane.getIcon();
    else
      return getIconForType(optionPane.getMessageType());
  }

  /**
   * This method returns the icon for the given messageType.
   *
   * @param messageType The type of message.
   *
   * @return The icon for the given messageType.
   */
  protected Icon getIconForType(int messageType)
  {
    Icon tmp = null;
    switch (messageType)
      {
      case JOptionPane.ERROR_MESSAGE:
	tmp = errorIcon;
	break;
      case JOptionPane.INFORMATION_MESSAGE:
	tmp = infoIcon;
	break;
      case JOptionPane.WARNING_MESSAGE:
	tmp = warningIcon;
	break;
      case JOptionPane.QUESTION_MESSAGE:
	tmp = questionIcon;
	break;
      }
    return tmp;
    // FIXME: Don't cast till the default icons are in.
    // return new IconUIResource(tmp);
  }

  /**
   * This method returns the index of the initialValue in the options array.
   *
   * @return The index of the initalValue.
   */
  protected int getInitialValueIndex()
  {
    Object[] buttons = getButtons();

    if (buttons == null)
      return -1;

    Object select = optionPane.getInitialValue();

    for (int i = 0; i < buttons.length; i++)
      {
	if (select == buttons[i])
	  return i;
      }
    return 0;
  }

  /**
   * This method returns the maximum number of characters that should be
   * placed on a line.
   *
   * @return The maximum number of characteres that should be placed on a
   *         line.
   */
  protected int getMaxCharactersPerLineCount()
  {
    return optionPane.getMaxCharactersPerLineCount();
  }

  /**
   * This method returns the maximum size.
   *
   * @param c The JComponent to measure.
   *
   * @return The maximum size.
   */
  public Dimension getMaximumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the message of the JOptionPane.
   *
   * @return The message.
   */
  protected Object getMessage()
  {
    return optionPane.getMessage();
  }

  /**
   * This method returns the minimum size of the JOptionPane.
   *
   * @return The minimum size.
   */
  public Dimension getMinimumOptionPaneSize()
  {
    return minimumSize;
  }

  /**
   * This method returns the minimum size.
   *
   * @param c The JComponent to measure.
   *
   * @return The minimum size.
   */
  public Dimension getMinimumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the preferred size of the JOptionPane. The preferred
   * size is the maximum of the size desired by the layout and the minimum
   * size.
   *
   * @param c The JComponent to measure.
   *
   * @return The preferred size.
   */
  public Dimension getPreferredSize(JComponent c)
  {
    Dimension d = optionPane.getLayout().preferredLayoutSize(optionPane);
    Dimension d2 = getMinimumOptionPaneSize();

    int w = Math.max(d.width, d2.width);
    int h = Math.max(d.height, d2.height);
    return new Dimension(w, h);
  }

  /**
   * This method returns whether all buttons should have the same width.
   *
   * @return Whether all buttons should have the same width.
   */
  protected boolean getSizeButtonsToSameWidth()
  {
    return true;
  }

  /**
   * This method installs components for the JOptionPane.
   */
  protected void installComponents()
  {
    // reset it.
    hasCustomComponents = false;
    Container msg = createMessageArea();
    if (msg != null)
      {
	((JComponent) msg).setBorder(messageBorder);
	msg.setForeground(messageForeground);
	messageAreaContainer = msg;
	optionPane.add(msg);
      }

    // FIXME: Figure out if the separator should be inserted here or what
    // this thing is supposed to do. Note: The JDK does NOT insert another
    // component at this place. The JOptionPane only has two panels in it
    // and there actually are applications that depend on this beeing so.
    Container sep = createSeparator();
    if (sep != null)
      optionPane.add(sep);

    Container button = createButtonArea();
    if (button != null)
      {
	((JComponent) button).setBorder(buttonBorder);
	buttonContainer = button;
	optionPane.add(button);
      }

    optionPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11));
    optionPane.invalidate();
  }

  /**
   * This method installs defaults for the JOptionPane.
   */
  protected void installDefaults()
  {
    LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
                                     "OptionPane.foreground",
                                     "OptionPane.font");
    LookAndFeel.installBorder(optionPane, "OptionPane.border");
    optionPane.setOpaque(true);

    messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder");
    messageForeground = UIManager.getColor("OptionPane.messageForeground");
    buttonBorder = UIManager.getBorder("OptionPane.buttonAreaBorder");

    minimumSize = UIManager.getDimension("OptionPane.minimumSize");

    // FIXME: Image icons don't seem to work properly right now.
    // Once they do, replace the synthetic icons with these ones.

    /*
    warningIcon = (IconUIResource) defaults.getIcon("OptionPane.warningIcon");
    infoIcon = (IconUIResource) defaults.getIcon("OptionPane.informationIcon");
    errorIcon = (IconUIResource) defaults.getIcon("OptionPane.errorIcon");
    questionIcon = (IconUIResource) defaults.getIcon("OptionPane.questionIcon");
    */
  }

  /**
   * This method installs keyboard actions for the JOptionpane.
   */
  protected void installKeyboardActions()
  {
    // FIXME: implement.
  }

  /**
   * This method installs listeners for the JOptionPane.
   */
  protected void installListeners()
  {
    propertyChangeListener = createPropertyChangeListener();

    optionPane.addPropertyChangeListener(propertyChangeListener);
  }

  /**
   * This method installs the UI for the JOptionPane.
   *
   * @param c The JComponent to install the UI for.
   */
  public void installUI(JComponent c)
  {
    if (c instanceof JOptionPane)
      {
	optionPane = (JOptionPane) c;

	installDefaults();
	installComponents();
	installListeners();
	installKeyboardActions();
      }
  }

  /**
   * Changes the inputValue property in the JOptionPane based on the current
   * value of the inputComponent.
   */
  protected void resetInputValue()
  {
    if (optionPane.getWantsInput() && inputComponent != null)
      {
	Object output = null;
	if (inputComponent instanceof JTextField)
	  output = ((JTextField) inputComponent).getText();
	else if (inputComponent instanceof JComboBox)
	  output = ((JComboBox) inputComponent).getSelectedItem();
	else if (inputComponent instanceof JList)
	  output = ((JList) inputComponent).getSelectedValue();

	if (output != null)
	  optionPane.setInputValue(output);
      }
  }

  /**
   * This method requests focus to the inputComponent (if one is present) and
   * the initialFocusComponent otherwise.
   *
   * @param op The JOptionPane.
   */
  public void selectInitialValue(JOptionPane op)
  {
    if (inputComponent != null)
      {
	inputComponent.requestFocus();
	return;
      }
    if (initialFocusComponent != null)
      initialFocusComponent.requestFocus();
  }

  /**
   * This method resets the value in the inputComponent to the
   * initialSelectionValue property.
   * This is package-private to avoid an accessor method.
   */
  void resetSelectedValue()
  {
    if (inputComponent != null)
      {
	Object init = optionPane.getInitialSelectionValue();
	if (init == null)
	  return;
	if (inputComponent instanceof JTextField)
	  ((JTextField) inputComponent).setText((String) init);
	else if (inputComponent instanceof JComboBox)
	  ((JComboBox) inputComponent).setSelectedItem(init);
	else if (inputComponent instanceof JList)
	  {
	    //  ((JList) inputComponent).setSelectedValue(init, true);
	  }
      }
  }

  /**
   * This method uninstalls all the components in the JOptionPane.
   */
  protected void uninstallComponents()
  {
    optionPane.removeAll();
    buttonContainer = null;
    messageAreaContainer = null;
  }

  /**
   * This method uninstalls the defaults for the JOptionPane.
   */
  protected void uninstallDefaults()
  {
    optionPane.setFont(null);
    optionPane.setForeground(null);
    optionPane.setBackground(null);

    minimumSize = null;

    messageBorder = null;
    buttonBorder = null;
    messageForeground = null;

    // FIXME: ImageIcons don't seem to work properly

    /*
    warningIcon = null;
    errorIcon = null;
    questionIcon = null;
    infoIcon = null;
    */
  }

  /**
   * This method uninstalls keyboard actions for the JOptionPane.
   */
  protected void uninstallKeyboardActions()
  {
    // FIXME: implement.
  }

  /**
   * This method uninstalls listeners for the JOptionPane.
   */
  protected void uninstallListeners()
  {
    optionPane.removePropertyChangeListener(propertyChangeListener);
    propertyChangeListener = null;
  }

  /**
   * This method uninstalls the UI for the given JComponent.
   *
   * @param c The JComponent to uninstall for.
   */
  public void uninstallUI(JComponent c)
  {
    uninstallKeyboardActions();
    uninstallListeners();
    uninstallComponents();
    uninstallDefaults();

    optionPane = null;
  }
}
