/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.swing.plaf.basic;

import sun.swing.DefaultLookup;
import sun.swing.UIAction;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.OptionPaneUI;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Locale;
import java.security.AccessController;

import sun.security.action.GetPropertyAction;


/**
 * Provides the basic look and feel for a <code>JOptionPane</code>.
 * <code>BasicMessagePaneUI</code> provides a means to place an icon,
 * message and buttons into a <code>Container</code>.
 * Generally, the layout will look like:<p>
 * <pre>
 *        ------------------
 *        | i | message    |
 *        | c | message    |
 *        | o | message    |
 *        | n | message    |
 *        ------------------
 *        |     buttons    |
 *        |________________|
 * </pre>
 * icon is an instance of <code>Icon</code> that is wrapped inside a
 * <code>JLabel</code>.  The message is an opaque object and is tested
 * for the following: if the message is a <code>Component</code> it is
 * added to the <code>Container</code>, if it is an <code>Icon</code>
 * it is wrapped inside a <code>JLabel</code> and added to the
 * <code>Container</code> otherwise it is wrapped inside a <code>JLabel</code>.
 * <p>
 * The above layout is used when the option pane's
 * <code>ComponentOrientation</code> property is horizontal, left-to-right.
 * The layout will be adjusted appropriately for other orientations.
 * <p>
 * The <code>Container</code>, message, icon, and buttons are all
 * determined from abstract methods.
 *
 * @author James Gosling
 * @author Scott Violet
 * @author Amy Fowler
 */
public class BasicOptionPaneUI extends OptionPaneUI {

    public static final int MinimumWidth = 262;
    public static final int MinimumHeight = 90;

    private static String newline;

    /**
     * <code>JOptionPane</code> that the receiver is providing the
     * look and feel for.
     */
    protected JOptionPane         optionPane;

    protected Dimension minimumSize;

    /** JComponent provide for input if optionPane.getWantsInput() returns
     * true. */
    protected JComponent          inputComponent;

    /** Component to receive focus when messaged with selectInitialValue. */
    protected Component           initialFocusComponent;

    /** This is set to true in validateComponent if a Component is contained
     * in either the message or the buttons. */
    protected boolean             hasCustomComponents;

    protected PropertyChangeListener propertyChangeListener;

    private Handler handler;


    static {
        newline = (String)java.security.AccessController.doPrivileged(
                                new GetPropertyAction("line.separator"));
        if (newline == null) {
            newline = "\n";
        }
    }

    static void loadActionMap(LazyActionMap map) {
        map.put(new Actions(Actions.CLOSE));
        BasicLookAndFeel.installAudioActionMap(map);
    }



    /**
      * Creates a new BasicOptionPaneUI instance.
      */
    public static ComponentUI createUI(JComponent x) {
        return new BasicOptionPaneUI();
    }

    /**
      * Installs the receiver as the L&F for the passed in
      * <code>JOptionPane</code>.
      */
    public void installUI(JComponent c) {
        optionPane = (JOptionPane)c;
        installDefaults();
        optionPane.setLayout(createLayoutManager());
        installComponents();
        installListeners();
        installKeyboardActions();
    }

    /**
      * Removes the receiver from the L&F controller of the passed in split
      * pane.
      */
    public void uninstallUI(JComponent c) {
        uninstallComponents();
        optionPane.setLayout(null);
        uninstallKeyboardActions();
        uninstallListeners();
        uninstallDefaults();
        optionPane = null;
    }

    protected void installDefaults() {
        LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
                                         "OptionPane.foreground", "OptionPane.font");
        LookAndFeel.installBorder(optionPane, "OptionPane.border");
        minimumSize = UIManager.getDimension("OptionPane.minimumSize");
        LookAndFeel.installProperty(optionPane, "opaque", Boolean.TRUE);
    }

    protected void uninstallDefaults() {
        LookAndFeel.uninstallBorder(optionPane);
    }

    protected void installComponents() {
        optionPane.add(createMessageArea());

        Container separator = createSeparator();
        if (separator != null) {
            optionPane.add(separator);
        }
        optionPane.add(createButtonArea());
        optionPane.applyComponentOrientation(optionPane.getComponentOrientation());
    }

    protected void uninstallComponents() {
        hasCustomComponents = false;
        inputComponent = null;
        initialFocusComponent = null;
        optionPane.removeAll();
    }

    protected LayoutManager createLayoutManager() {
        return new BoxLayout(optionPane, BoxLayout.Y_AXIS);
    }

    protected void installListeners() {
        if ((propertyChangeListener = createPropertyChangeListener()) != null) {
            optionPane.addPropertyChangeListener(propertyChangeListener);
        }
    }

    protected void uninstallListeners() {
        if (propertyChangeListener != null) {
            optionPane.removePropertyChangeListener(propertyChangeListener);
            propertyChangeListener = null;
        }
        handler = null;
    }

    protected PropertyChangeListener createPropertyChangeListener() {
        return getHandler();
    }

    private Handler getHandler() {
        if (handler == null) {
            handler = new Handler();
        }
        return handler;
    }

    protected void installKeyboardActions() {
        InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

        SwingUtilities.replaceUIInputMap(optionPane, JComponent.
                                       WHEN_IN_FOCUSED_WINDOW, map);

        LazyActionMap.installLazyActionMap(optionPane, BasicOptionPaneUI.class,
                                           "OptionPane.actionMap");
    }

    protected void uninstallKeyboardActions() {
        SwingUtilities.replaceUIInputMap(optionPane, JComponent.
                                       WHEN_IN_FOCUSED_WINDOW, null);
        SwingUtilities.replaceUIActionMap(optionPane, null);
    }

    InputMap getInputMap(int condition) {
        if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
            Object[] bindings = (Object[])DefaultLookup.get(
                             optionPane, this, "OptionPane.windowBindings");
            if (bindings != null) {
                return LookAndFeel.makeComponentInputMap(optionPane, bindings);
            }
        }
        return null;
    }

    /**
     * Returns the minimum size the option pane should be. Primarily
     * provided for subclassers wishing to offer a different minimum size.
     */
    public Dimension getMinimumOptionPaneSize() {
        if (minimumSize == null) {
            return new Dimension(MinimumWidth, MinimumHeight);
        }
        return new Dimension(minimumSize.width,
                             minimumSize.height);
    }

    /**
     * If <code>c</code> is the <code>JOptionPane</code> the receiver
     * is contained in, the preferred
     * size that is returned is the maximum of the preferred size of
     * the <code>LayoutManager</code> for the <code>JOptionPane</code>, and
     * <code>getMinimumOptionPaneSize</code>.
     */
    public Dimension getPreferredSize(JComponent c) {
        if ((JOptionPane)c == optionPane) {
            Dimension            ourMin = getMinimumOptionPaneSize();
            LayoutManager        lm = c.getLayout();

            if (lm != null) {
                Dimension         lmSize = lm.preferredLayoutSize(c);

                if (ourMin != null)
                    return new Dimension
                        (Math.max(lmSize.width, ourMin.width),
                         Math.max(lmSize.height, ourMin.height));
                return lmSize;
            }
            return ourMin;
        }
        return null;
    }

    /**
     * Messaged from installComponents to create a Container containing the
     * body of the message. The icon is the created by calling
     * <code>addIcon</code>.
     */
    protected Container createMessageArea() {
        JPanel top = new JPanel();
        Border topBorder = (Border)DefaultLookup.get(optionPane, this,
                                             "OptionPane.messageAreaBorder");
        if (topBorder != null) {
            top.setBorder(topBorder);
        }
        top.setLayout(new BorderLayout());

        /* Fill the body. */
        Container          body = new JPanel(new GridBagLayout());
        Container          realBody = new JPanel(new BorderLayout());

        body.setName("OptionPane.body");
        realBody.setName("OptionPane.realBody");

        if (getIcon() != null) {
            JPanel sep = new JPanel();
            sep.setName("OptionPane.separator");
            sep.setPreferredSize(new Dimension(15, 1));
            realBody.add(sep, BorderLayout.BEFORE_LINE_BEGINS);
        }
        realBody.add(body, BorderLayout.CENTER);

        GridBagConstraints cons = new GridBagConstraints();
        cons.gridx = cons.gridy = 0;
        cons.gridwidth = GridBagConstraints.REMAINDER;
        cons.gridheight = 1;
        cons.anchor = DefaultLookup.getInt(optionPane, this,
                      "OptionPane.messageAnchor", GridBagConstraints.CENTER);
        cons.insets = new Insets(0,0,3,0);

        addMessageComponents(body, cons, getMessage(),
                          getMaxCharactersPerLineCount(), false);
        top.add(realBody, BorderLayout.CENTER);

        addIcon(top);
        return top;
    }

    /**
     * Creates the appropriate object to represent <code>msg</code> and
     * places it into <code>container</code>. If <code>msg</code> is an
     * instance of Component, it is added directly, if it is an Icon,
     * a JLabel is created to represent it, otherwise a JLabel is
     * created for the string, if <code>d</code> is an Object[], this
     * method will be recursively invoked for the children.
     * <code>internallyCreated</code> is true if Objc is an instance
     * of Component and was created internally by this method (this is
     * used to correctly set hasCustomComponents only if !internallyCreated).
     */
    protected void addMessageComponents(Container container,
                                     GridBagConstraints cons,
                                     Object msg, int maxll,
                                     boolean internallyCreated) {
        if (msg == null) {
            return;
        }
        if (msg instanceof Component) {
            // To workaround problem where Gridbad will set child
            // to its minimum size if its preferred size will not fit
            // within allocated cells
            if (msg instanceof JScrollPane || msg instanceof JPanel) {
                cons.fill = GridBagConstraints.BOTH;
                cons.weighty = 1;
            } else {
                cons.fill = GridBagConstraints.HORIZONTAL;
            }
            cons.weightx = 1;

            container.add((Component) msg, cons);
            cons.weightx = 0;
            cons.weighty = 0;
            cons.fill = GridBagConstraints.NONE;
            cons.gridy++;
            if (!internallyCreated) {
                hasCustomComponents = true;
            }

        } else if (msg instanceof Object[]) {
            Object [] msgs = (Object[]) msg;
            for (int i = 0; i < msgs.length; i++) {
                addMessageComponents(container, cons, msgs[i], maxll, false);
            }

        } else if (msg instanceof Icon) {
            JLabel label = new JLabel( (Icon)msg, SwingConstants.CENTER );
            configureMessageLabel(label);
            addMessageComponents(container, cons, label, maxll, true);

        } else {
            String s = msg.toString();
            int len = s.length();
            if (len <= 0) {
                return;
            }
            int nl = -1;
            int nll = 0;

            if ((nl = s.indexOf(newline)) >= 0) {
                nll = newline.length();
            } else if ((nl = s.indexOf("\r\n")) >= 0) {
                nll = 2;
            } else if ((nl = s.indexOf('\n')) >= 0) {
                nll = 1;
            }
            if (nl >= 0) {
                // break up newlines
                if (nl == 0) {
                    JPanel breakPanel = new JPanel() {
                        public Dimension getPreferredSize() {
                            Font       f = getFont();

                            if (f != null) {
                                return new Dimension(1, f.getSize() + 2);
                            }
                            return new Dimension(0, 0);
                        }
                    };
                    breakPanel.setName("OptionPane.break");
                    addMessageComponents(container, cons, breakPanel, maxll,
                                         true);
                } else {
                    addMessageComponents(container, cons, s.substring(0, nl),
                                      maxll, false);
                }
                addMessageComponents(container, cons, s.substring(nl + nll), maxll,
                                  false);

            } else if (len > maxll) {
                Container c = Box.createVerticalBox();
                c.setName("OptionPane.verticalBox");
                burstStringInto(c, s, maxll);
                addMessageComponents(container, cons, c, maxll, true );

            } else {
                JLabel label;
                label = new JLabel( s, JLabel.LEADING );
                label.setName("OptionPane.label");
                configureMessageLabel(label);
                addMessageComponents(container, cons, label, maxll, true);
            }
        }
    }

    /**
     * Returns the message to display from the JOptionPane the receiver is
     * providing the look and feel for.
     */
    protected Object getMessage() {
        inputComponent = null;
        if (optionPane != null) {
            if (optionPane.getWantsInput()) {
                /* Create a user component to capture the input. If the
                   selectionValues are non null the component and there
                   are < 20 values it'll be a combobox, if non null and
                   >= 20, it'll be a list, otherwise it'll be a textfield. */
                Object             message = optionPane.getMessage();
                Object[]           sValues = optionPane.getSelectionValues();
                Object             inputValue = optionPane
                                           .getInitialSelectionValue();
                JComponent         toAdd;

                if (sValues != null) {
                    if (sValues.length < 20) {
                        JComboBox            cBox = new JComboBox();

                        cBox.setName("OptionPane.comboBox");
                        for(int counter = 0, maxCounter = sValues.length;
                            counter < maxCounter; counter++) {
                            cBox.addItem(sValues[counter]);
                        }
                        if (inputValue != null) {
                            cBox.setSelectedItem(inputValue);
                        }
                        inputComponent = cBox;
                        toAdd = cBox;

                    } else {
                        JList                list = new JList(sValues);
                        JScrollPane          sp = new JScrollPane(list);

                        sp.setName("OptionPane.scrollPane");
                        list.setName("OptionPane.list");
                        list.setVisibleRowCount(10);
                        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                        if(inputValue != null)
                            list.setSelectedValue(inputValue, true);
                        list.addMouseListener(getHandler());
                        toAdd = sp;
                        inputComponent = list;
                    }

                } else {
                    MultiplexingTextField   tf = new MultiplexingTextField(20);

                    tf.setName("OptionPane.textField");
                    tf.setKeyStrokes(new KeyStroke[] {
                                     KeyStroke.getKeyStroke("ENTER") } );
                    if (inputValue != null) {
                        String inputString = inputValue.toString();
                        tf.setText(inputString);
                        tf.setSelectionStart(0);
                        tf.setSelectionEnd(inputString.length());
                    }
                    tf.addActionListener(getHandler());
                    toAdd = inputComponent = tf;
                }

                Object[]           newMessage;

                if (message == null) {
                    newMessage = new Object[1];
                    newMessage[0] = toAdd;

                } else {
                    newMessage = new Object[2];
                    newMessage[0] = message;
                    newMessage[1] = toAdd;
                }
                return newMessage;
            }
            return optionPane.getMessage();
        }
        return null;
    }

    /**
     * Creates and adds a JLabel representing the icon returned from
     * <code>getIcon</code> to <code>top</code>. This is messaged from
     * <code>createMessageArea</code>
     */
    protected void addIcon(Container top) {
        /* Create the icon. */
        Icon                  sideIcon = getIcon();

        if (sideIcon != null) {
            JLabel            iconLabel = new JLabel(sideIcon);

            iconLabel.setName("OptionPane.iconLabel");
            iconLabel.setVerticalAlignment(SwingConstants.TOP);
            top.add(iconLabel, BorderLayout.BEFORE_LINE_BEGINS);
        }
    }

    /**
     * Returns the icon from the JOptionPane the receiver is providing
     * the look and feel for, or the default icon as returned from
     * <code>getDefaultIcon</code>.
     */
    protected Icon getIcon() {
        Icon      mIcon = (optionPane == null ? null : optionPane.getIcon());

        if(mIcon == null && optionPane != null)
            mIcon = getIconForType(optionPane.getMessageType());
        return mIcon;
    }

    /**
     * Returns the icon to use for the passed in type.
     */
    protected Icon getIconForType(int messageType) {
        if(messageType < 0 || messageType > 3)
            return null;
        String propertyName = null;
        switch(messageType) {
        case 0:
            propertyName = "OptionPane.errorIcon";
            break;
        case 1:
            propertyName = "OptionPane.informationIcon";
            break;
        case 2:
            propertyName = "OptionPane.warningIcon";
            break;
        case 3:
            propertyName = "OptionPane.questionIcon";
            break;
        }
        if (propertyName != null) {
            return (Icon)DefaultLookup.get(optionPane, this, propertyName);
        }
        return null;
    }

    /**
     * Returns the maximum number of characters to place on a line.
     */
    protected int getMaxCharactersPerLineCount() {
        return optionPane.getMaxCharactersPerLineCount();
    }

   /**
     * Recursively creates new JLabel instances to represent <code>d</code>.
     * Each JLabel instance is added to <code>c</code>.
     */
    protected void burstStringInto(Container c, String d, int maxll) {
        // Primitive line wrapping
        int len = d.length();
        if (len <= 0)
            return;
        if (len > maxll) {
            int p = d.lastIndexOf(' ', maxll);
            if (p <= 0)
                p = d.indexOf(' ', maxll);
            if (p > 0 && p < len) {
                burstStringInto(c, d.substring(0, p), maxll);
                burstStringInto(c, d.substring(p + 1), maxll);
                return;
            }
        }
        JLabel label = new JLabel(d, JLabel.LEFT);
        label.setName("OptionPane.label");
        configureMessageLabel(label);
        c.add(label);
    }

    protected Container createSeparator() {
        return null;
    }

    /**
     * Creates and returns a Container containing the buttons. The buttons
     * are created by calling <code>getButtons</code>.
     */
    protected Container createButtonArea() {
        JPanel bottom = new JPanel();
        Border border = (Border)DefaultLookup.get(optionPane, this,
                                          "OptionPane.buttonAreaBorder");
        bottom.setName("OptionPane.buttonArea");
        if (border != null) {
            bottom.setBorder(border);
        }
        bottom.setLayout(new ButtonAreaLayout(
           DefaultLookup.getBoolean(optionPane, this,
                                    "OptionPane.sameSizeButtons", true),
           DefaultLookup.getInt(optionPane, this, "OptionPane.buttonPadding",
                                6),
           DefaultLookup.getInt(optionPane, this,
                        "OptionPane.buttonOrientation", SwingConstants.CENTER),
           DefaultLookup.getBoolean(optionPane, this, "OptionPane.isYesLast",
                                    false)));
        addButtonComponents(bottom, getButtons(), getInitialValueIndex());
        return bottom;
    }

    /**
     * Creates the appropriate object to represent each of the objects in
     * <code>buttons</code> and adds it to <code>container</code>. This
     * differs from addMessageComponents in that it will recurse on
     * <code>buttons</code> and that if button is not a Component
     * it will create an instance of JButton.
     */
    protected void addButtonComponents(Container container, Object[] buttons,
                                 int initialIndex) {
        if (buttons != null && buttons.length > 0) {
            boolean            sizeButtonsToSame = getSizeButtonsToSameWidth();
            boolean            createdAll = true;
            int                numButtons = buttons.length;
            JButton[]          createdButtons = null;
            int                maxWidth = 0;

            if (sizeButtonsToSame) {
                createdButtons = new JButton[numButtons];
            }

            for(int counter = 0; counter < numButtons; counter++) {
                Object       button = buttons[counter];
                Component    newComponent;

                if (button instanceof Component) {
                    createdAll = false;
                    newComponent = (Component)button;
                    container.add(newComponent);
                    hasCustomComponents = true;

                } else {
                    JButton      aButton;

                    if (button instanceof ButtonFactory) {
                        aButton = ((ButtonFactory)button).createButton();
                    }
                    else if (button instanceof Icon)
                        aButton = new JButton((Icon)button);
                    else
                        aButton = new JButton(button.toString());

                    aButton.setName("OptionPane.button");
                    aButton.setMultiClickThreshhold(DefaultLookup.getInt(
                          optionPane, this, "OptionPane.buttonClickThreshhold",
                          0));
                    configureButton(aButton);

                    container.add(aButton);

                    ActionListener buttonListener = createButtonActionListener(counter);
                    if (buttonListener != null) {
                        aButton.addActionListener(buttonListener);
                    }
                    newComponent = aButton;
                }
                if (sizeButtonsToSame && createdAll &&
                   (newComponent instanceof JButton)) {
                    createdButtons[counter] = (JButton)newComponent;
                    maxWidth = Math.max(maxWidth,
                                        newComponent.getMinimumSize().width);
                }
                if (counter == initialIndex) {
                    initialFocusComponent = newComponent;
                    if (initialFocusComponent instanceof JButton) {
                        JButton defaultB = (JButton)initialFocusComponent;
                        defaultB.addHierarchyListener(new HierarchyListener() {
                            public void hierarchyChanged(HierarchyEvent e) {
                                if ((e.getChangeFlags() &
                                        HierarchyEvent.PARENT_CHANGED) != 0) {
                                    JButton defaultButton = (JButton) e.getComponent();
                                    JRootPane root =
                                            SwingUtilities.getRootPane(defaultButton);
                                    if (root != null) {
                                        root.setDefaultButton(defaultButton);
                                    }
                                }
                            }
                        });
                    }
                }
            }
            ((ButtonAreaLayout)container.getLayout()).
                              setSyncAllWidths((sizeButtonsToSame && createdAll));
            /* Set the padding, windows seems to use 8 if <= 2 components,
               otherwise 4 is used. It may actually just be the size of the
               buttons is always the same, not sure. */
            if (DefaultLookup.getBoolean(optionPane, this,
                   "OptionPane.setButtonMargin", true) && sizeButtonsToSame &&
                   createdAll) {
                JButton               aButton;
                int                   padSize;

                padSize = (numButtons <= 2? 8 : 4);

                for(int counter = 0; counter < numButtons; counter++) {
                    aButton = createdButtons[counter];
                    aButton.setMargin(new Insets(2, padSize, 2, padSize));
                }
            }
        }
    }

    protected ActionListener createButtonActionListener(int buttonIndex) {
        return new ButtonActionListener(buttonIndex);
    }

    /**
     * Returns the buttons to display from the JOptionPane the receiver is
     * providing the look and feel for. If the JOptionPane has options
     * set, they will be provided, otherwise if the optionType is
     * YES_NO_OPTION, yesNoOptions is returned, if the type is
     * YES_NO_CANCEL_OPTION yesNoCancelOptions is returned, otherwise
     * defaultButtons are returned.
     */
    protected Object[] getButtons() {
        if (optionPane != null) {
            Object[] suppliedOptions = optionPane.getOptions();

            if (suppliedOptions == null) {
                Object[] defaultOptions;
                int type = optionPane.getOptionType();
                Locale l = optionPane.getLocale();
                int minimumWidth =
                    DefaultLookup.getInt(optionPane, this,
                                        "OptionPane.buttonMinimumWidth",-1);
                if (type == JOptionPane.YES_NO_OPTION) {
                    defaultOptions = new ButtonFactory[2];
                    defaultOptions[0] = new ButtonFactory(
                        UIManager.getString("OptionPane.yesButtonText", l),
                        getMnemonic("OptionPane.yesButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.yesIcon"), minimumWidth);
                    defaultOptions[1] = new ButtonFactory(
                        UIManager.getString("OptionPane.noButtonText", l),
                        getMnemonic("OptionPane.noButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.noIcon"), minimumWidth);
                } else if (type == JOptionPane.YES_NO_CANCEL_OPTION) {
                    defaultOptions = new ButtonFactory[3];
                    defaultOptions[0] = new ButtonFactory(
                        UIManager.getString("OptionPane.yesButtonText", l),
                        getMnemonic("OptionPane.yesButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.yesIcon"), minimumWidth);
                    defaultOptions[1] = new ButtonFactory(
                        UIManager.getString("OptionPane.noButtonText",l),
                        getMnemonic("OptionPane.noButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.noIcon"), minimumWidth);
                    defaultOptions[2] = new ButtonFactory(
                        UIManager.getString("OptionPane.cancelButtonText",l),
                        getMnemonic("OptionPane.cancelButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.cancelIcon"), minimumWidth);
                } else if (type == JOptionPane.OK_CANCEL_OPTION) {
                    defaultOptions = new ButtonFactory[2];
                    defaultOptions[0] = new ButtonFactory(
                        UIManager.getString("OptionPane.okButtonText",l),
                        getMnemonic("OptionPane.okButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.okIcon"), minimumWidth);
                    defaultOptions[1] = new ButtonFactory(
                        UIManager.getString("OptionPane.cancelButtonText",l),
                        getMnemonic("OptionPane.cancelButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.cancelIcon"), minimumWidth);
                } else {
                    defaultOptions = new ButtonFactory[1];
                    defaultOptions[0] = new ButtonFactory(
                        UIManager.getString("OptionPane.okButtonText",l),
                        getMnemonic("OptionPane.okButtonMnemonic", l),
                        (Icon)DefaultLookup.get(optionPane, this,
                                          "OptionPane.okIcon"), minimumWidth);
                }
                return defaultOptions;

            }
            return suppliedOptions;
        }
        return null;
    }

    private int getMnemonic(String key, Locale l) {
        String value = (String)UIManager.get(key, l);

        if (value == null) {
            return 0;
        }
        try {
            return Integer.parseInt(value);
        }
        catch (NumberFormatException nfe) { }
        return 0;
    }

    /**
     * Returns true, basic L&F wants all the buttons to have the same
     * width.
     */
    protected boolean getSizeButtonsToSameWidth() {
        return true;
    }

    /**
     * Returns the initial index into the buttons to select. The index
     * is calculated from the initial value from the JOptionPane and
     * options of the JOptionPane or 0.
     */
    protected int getInitialValueIndex() {
        if (optionPane != null) {
            Object             iv = optionPane.getInitialValue();
            Object[]           options = optionPane.getOptions();

            if(options == null) {
                return 0;
            }
            else if(iv != null) {
                for(int counter = options.length - 1; counter >= 0; counter--){
                    if(options[counter].equals(iv))
                        return counter;
                }
            }
        }
        return -1;
    }

    /**
     * Sets the input value in the option pane the receiver is providing
     * the look and feel for based on the value in the inputComponent.
     */
    protected void resetInputValue() {
        if(inputComponent != null && (inputComponent instanceof JTextField)) {
            optionPane.setInputValue(((JTextField)inputComponent).getText());

        } else if(inputComponent != null &&
                  (inputComponent instanceof JComboBox)) {
            optionPane.setInputValue(((JComboBox)inputComponent)
                                     .getSelectedItem());
        } else if(inputComponent != null) {
            optionPane.setInputValue(((JList)inputComponent)
                                     .getSelectedValue());
        }
    }


    /**
     * If inputComponent is non-null, the focus is requested on that,
     * otherwise request focus on the default value
     */
    public void selectInitialValue(JOptionPane op) {
        if (inputComponent != null)
            inputComponent.requestFocus();
        else {
            if (initialFocusComponent != null)
                initialFocusComponent.requestFocus();

            if (initialFocusComponent instanceof JButton) {
                JRootPane root = SwingUtilities.getRootPane(initialFocusComponent);
                if (root != null) {
                    root.setDefaultButton((JButton)initialFocusComponent);
                }
            }
        }
    }

    /**
     * Returns true if in the last call to validateComponent the message
     * or buttons contained a subclass of Component.
     */
    public boolean containsCustomComponents(JOptionPane op) {
        return hasCustomComponents;
    }


    /**
     * <code>ButtonAreaLayout</code> behaves in a similar manner to
     * <code>FlowLayout</code>. It lays out all components from left to
     * right. If <code>syncAllWidths</code> is true, the widths of each
     * component will be set to the largest preferred size width.
     *
     * This inner class is marked &quot;public&quot; due to a compiler bug.
     * This class should be treated as a &quot;protected&quot; inner class.
     * Instantiate it only within subclasses of BasicOptionPaneUI.
     */
    public static class ButtonAreaLayout implements LayoutManager {
        protected boolean           syncAllWidths;
        protected int               padding;
        /** If true, children are lumped together in parent. */
        protected boolean           centersChildren;
        private int orientation;
        private boolean reverseButtons;
        /**
         * Indicates whether or not centersChildren should be used vs
         * the orientation. This is done for backward compatability
         * for subclassers.
         */
        private boolean useOrientation;

        public ButtonAreaLayout(boolean syncAllWidths, int padding) {
            this.syncAllWidths = syncAllWidths;
            this.padding = padding;
            centersChildren = true;
            useOrientation = false;
        }

        ButtonAreaLayout(boolean syncAllSizes, int padding, int orientation,
                         boolean reverseButtons) {
            this(syncAllSizes, padding);
            useOrientation = true;
            this.orientation = orientation;
            this.reverseButtons = reverseButtons;
        }

        public void setSyncAllWidths(boolean newValue) {
            syncAllWidths = newValue;
        }

        public boolean getSyncAllWidths() {
            return syncAllWidths;
        }

        public void setPadding(int newPadding) {
            this.padding = newPadding;
        }

        public int getPadding() {
            return padding;
        }

        public void setCentersChildren(boolean newValue) {
            centersChildren = newValue;
            useOrientation = false;
        }

        public boolean getCentersChildren() {
            return centersChildren;
        }

        private int getOrientation(Container container) {
            if (!useOrientation) {
                return SwingConstants.CENTER;
            }
            if (container.getComponentOrientation().isLeftToRight()) {
                return orientation;
            }
            switch (orientation) {
            case SwingConstants.LEFT:
                return SwingConstants.RIGHT;
            case SwingConstants.RIGHT:
                return SwingConstants.LEFT;
            case SwingConstants.CENTER:
                return SwingConstants.CENTER;
            }
            return SwingConstants.LEFT;
        }

        public void addLayoutComponent(String string, Component comp) {
        }

        public void layoutContainer(Container container) {
            Component[]      children = container.getComponents();

            if(children != null && children.length > 0) {
                int               numChildren = children.length;
                Insets            insets = container.getInsets();
                int maxWidth = 0;
                int maxHeight = 0;
                int totalButtonWidth = 0;
                int x = 0;
                int xOffset = 0;
                boolean ltr = container.getComponentOrientation().
                                        isLeftToRight();
                boolean reverse = (ltr) ? reverseButtons : !reverseButtons;

                for(int counter = 0; counter < numChildren; counter++) {
                    Dimension pref = children[counter].getPreferredSize();
                    maxWidth = Math.max(maxWidth, pref.width);
                    maxHeight = Math.max(maxHeight, pref.height);
                    totalButtonWidth += pref.width;
                }
                if (getSyncAllWidths()) {
                    totalButtonWidth = maxWidth * numChildren;
                }
                totalButtonWidth += (numChildren - 1) * padding;

                switch (getOrientation(container)) {
                case SwingConstants.LEFT:
                    x = insets.left;
                    break;
                case SwingConstants.RIGHT:
                    x = container.getWidth() - insets.right - totalButtonWidth;
                    break;
                case SwingConstants.CENTER:
                    if (getCentersChildren() || numChildren < 2) {
                        x = (container.getWidth() - totalButtonWidth) / 2;
                    }
                    else {
                        x = insets.left;
                        if (getSyncAllWidths()) {
                            xOffset = (container.getWidth() - insets.left -
                                       insets.right - totalButtonWidth) /
                                (numChildren - 1) + maxWidth;
                        }
                        else {
                            xOffset = (container.getWidth() - insets.left -
                                       insets.right - totalButtonWidth) /
                                      (numChildren - 1);
                        }
                    }
                    break;
                }

                for (int counter = 0; counter < numChildren; counter++) {
                    int index = (reverse) ? numChildren - counter - 1 :
                                counter;
                    Dimension pref = children[index].getPreferredSize();

                    if (getSyncAllWidths()) {
                        children[index].setBounds(x, insets.top,
                                                  maxWidth, maxHeight);
                    }
                    else {
                        children[index].setBounds(x, insets.top, pref.width,
                                                  pref.height);
                    }
                    if (xOffset != 0) {
                        x += xOffset;
                    }
                    else {
                        x += children[index].getWidth() + padding;
                    }
                }
            }
        }

        public Dimension minimumLayoutSize(Container c) {
            if(c != null) {
                Component[]       children = c.getComponents();

                if(children != null && children.length > 0) {
                    Dimension     aSize;
                    int           numChildren = children.length;
                    int           height = 0;
                    Insets        cInsets = c.getInsets();
                    int           extraHeight = cInsets.top + cInsets.bottom;
                    int           extraWidth = cInsets.left + cInsets.right;

                    if (syncAllWidths) {
                        int              maxWidth = 0;

                        for(int counter = 0; counter < numChildren; counter++){
                            aSize = children[counter].getPreferredSize();
                            height = Math.max(height, aSize.height);
                            maxWidth = Math.max(maxWidth, aSize.width);
                        }
                        return new Dimension(extraWidth + (maxWidth * numChildren) +
                                             (numChildren - 1) * padding,
                                             extraHeight + height);
                    }
                    else {
                        int        totalWidth = 0;

                        for(int counter = 0; counter < numChildren; counter++){
                            aSize = children[counter].getPreferredSize();
                            height = Math.max(height, aSize.height);
                            totalWidth += aSize.width;
                        }
                        totalWidth += ((numChildren - 1) * padding);
                        return new Dimension(extraWidth + totalWidth, extraHeight + height);
                    }
                }
            }
            return new Dimension(0, 0);
        }

        public Dimension preferredLayoutSize(Container c) {
            return minimumLayoutSize(c);
        }

        public void removeLayoutComponent(Component c) { }
    }


    /**
     * This inner class is marked &quot;public&quot; due to a compiler bug.
     * This class should be treated as a &quot;protected&quot; inner class.
     * Instantiate it only within subclasses of BasicOptionPaneUI.
     */
    public class PropertyChangeHandler implements PropertyChangeListener {
        /**
         * If the source of the PropertyChangeEvent <code>e</code> equals the
         * optionPane and is one of the ICON_PROPERTY, MESSAGE_PROPERTY,
         * OPTIONS_PROPERTY or INITIAL_VALUE_PROPERTY,
         * validateComponent is invoked.
         */
        public void propertyChange(PropertyChangeEvent e) {
            getHandler().propertyChange(e);
        }
    }

    /**
     * Configures any necessary colors/fonts for the specified label
     * used representing the message.
     */
    private void configureMessageLabel(JLabel label) {
        Color color = (Color)DefaultLookup.get(optionPane, this,
                                               "OptionPane.messageForeground");
        if (color != null) {
            label.setForeground(color);
        }
        Font messageFont = (Font)DefaultLookup.get(optionPane, this,
                                                   "OptionPane.messageFont");
        if (messageFont != null) {
            label.setFont(messageFont);
        }
    }

    /**
     * Configures any necessary colors/fonts for the specified button
     * used representing the button portion of the optionpane.
     */
    private void configureButton(JButton button) {
        Font buttonFont = (Font)DefaultLookup.get(optionPane, this,
                                            "OptionPane.buttonFont");
        if (buttonFont != null) {
            button.setFont(buttonFont);
        }
    }

    /**
     * This inner class is marked &quot;public&quot; due to a compiler bug.
     * This class should be treated as a &quot;protected&quot; inner class.
     * Instantiate it only within subclasses of BasicOptionPaneUI.
     */
    public class ButtonActionListener implements ActionListener {
        protected int buttonIndex;

        public ButtonActionListener(int buttonIndex) {
            this.buttonIndex = buttonIndex;
        }

        public void actionPerformed(ActionEvent e) {
            if (optionPane != null) {
                int optionType = optionPane.getOptionType();
                Object[] options = optionPane.getOptions();

                /* If the option pane takes input, then store the input value
                 * if custom options were specified, if the option type is
                 * DEFAULT_OPTION, OR if option type is set to a predefined
                 * one and the user chose the affirmative answer.
                 */
                if (inputComponent != null) {
                    if (options != null ||
                        optionType == JOptionPane.DEFAULT_OPTION ||
                        ((optionType == JOptionPane.YES_NO_OPTION ||
                         optionType == JOptionPane.YES_NO_CANCEL_OPTION ||
                         optionType == JOptionPane.OK_CANCEL_OPTION) &&
                         buttonIndex == 0)) {
                        resetInputValue();
                    }
                }
                if (options == null) {
                    if (optionType == JOptionPane.OK_CANCEL_OPTION &&
                        buttonIndex == 1) {
                        optionPane.setValue(new Integer(2));

                    } else {
                        optionPane.setValue(new Integer(buttonIndex));
                    }
                } else {
                    optionPane.setValue(options[buttonIndex]);
                }
            }
        }
    }


    private class Handler implements ActionListener, MouseListener,
                                     PropertyChangeListener {
        //
        // ActionListener
        //
        public void actionPerformed(ActionEvent e) {
            optionPane.setInputValue(((JTextField)e.getSource()).getText());
        }


        //
        // MouseListener
        //
        public void mouseClicked(MouseEvent e) {
        }

        public void mouseReleased(MouseEvent e) {
        }

        public void mouseEntered(MouseEvent e) {
        }

        public void mouseExited(MouseEvent e) {
        }

        public void mousePressed(MouseEvent e) {
            if (e.getClickCount() == 2) {
                JList     list = (JList)e.getSource();
                int       index = list.locationToIndex(e.getPoint());

                optionPane.setInputValue(list.getModel().getElementAt(index));
            }
        }

        //
        // PropertyChangeListener
        //
        public void propertyChange(PropertyChangeEvent e) {
            if(e.getSource() == optionPane) {
                // Option Pane Auditory Cue Activation
                // only respond to "ancestor" changes
                // the idea being that a JOptionPane gets a JDialog when it is
                // set to appear and loses it's JDialog when it is dismissed.
                if ("ancestor" == e.getPropertyName()) {
                    JOptionPane op = (JOptionPane)e.getSource();
                    boolean isComingUp;

                    // if the old value is null, then the JOptionPane is being
                    // created since it didn't previously have an ancestor.
                    if (e.getOldValue() == null) {
                        isComingUp = true;
                    } else {
                        isComingUp = false;
                    }

                    // figure out what to do based on the message type
                    switch (op.getMessageType()) {
                    case JOptionPane.PLAIN_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                               "OptionPane.informationSound");
                        }
                        break;
                    case JOptionPane.QUESTION_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                             "OptionPane.questionSound");
                        }
                        break;
                    case JOptionPane.INFORMATION_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                             "OptionPane.informationSound");
                        }
                        break;
                    case JOptionPane.WARNING_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                             "OptionPane.warningSound");
                        }
                        break;
                    case JOptionPane.ERROR_MESSAGE:
                        if (isComingUp) {
                            BasicLookAndFeel.playSound(optionPane,
                                             "OptionPane.errorSound");
                        }
                        break;
                    default:
                        System.err.println("Undefined JOptionPane type: " +
                                           op.getMessageType());
                        break;
                    }
                }
                // Visual activity
                String         changeName = e.getPropertyName();

                if(changeName == JOptionPane.OPTIONS_PROPERTY ||
                   changeName == JOptionPane.INITIAL_VALUE_PROPERTY ||
                   changeName == JOptionPane.ICON_PROPERTY ||
                   changeName == JOptionPane.MESSAGE_TYPE_PROPERTY ||
                   changeName == JOptionPane.OPTION_TYPE_PROPERTY ||
                   changeName == JOptionPane.MESSAGE_PROPERTY ||
                   changeName == JOptionPane.SELECTION_VALUES_PROPERTY ||
                   changeName == JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY ||
                   changeName == JOptionPane.WANTS_INPUT_PROPERTY) {
                   uninstallComponents();
                   installComponents();
                   optionPane.validate();
                }
                else if (changeName == "componentOrientation") {
                    ComponentOrientation o = (ComponentOrientation)e.getNewValue();
                    JOptionPane op = (JOptionPane)e.getSource();
                    if (o != (ComponentOrientation)e.getOldValue()) {
                        op.applyComponentOrientation(o);
                    }
                }
            }
        }
    }


    //
    // Classes used when optionPane.getWantsInput returns true.
    //

    /**
     * A JTextField that allows you to specify an array of KeyStrokes that
     * that will have their bindings processed regardless of whether or
     * not they are registered on the JTextField. This is used as we really
     * want the ActionListener to be notified so that we can push the
     * change to the JOptionPane, but we also want additional bindings
     * (those of the JRootPane) to be processed as well.
     */
    private static class MultiplexingTextField extends JTextField {
        private KeyStroke[] strokes;

        MultiplexingTextField(int cols) {
            super(cols);
        }

        /**
         * Sets the KeyStrokes that will be additional processed for
         * ancestor bindings.
         */
        void setKeyStrokes(KeyStroke[] strokes) {
            this.strokes = strokes;
        }

        protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
                                            int condition, boolean pressed) {
            boolean processed = super.processKeyBinding(ks, e, condition,
                                                        pressed);

            if (processed && condition != JComponent.WHEN_IN_FOCUSED_WINDOW) {
                for (int counter = strokes.length - 1; counter >= 0;
                         counter--) {
                    if (strokes[counter].equals(ks)) {
                        // Returning false will allow further processing
                        // of the bindings, eg our parent Containers will get a
                        // crack at them.
                        return false;
                    }
                }
            }
            return processed;
        }
    }



    /**
     * Registered in the ActionMap. Sets the value of the option pane
     * to <code>JOptionPane.CLOSED_OPTION</code>.
     */
    private static class Actions extends UIAction {
        private static final String CLOSE = "close";

        Actions(String key) {
            super(key);
        }

        public void actionPerformed(ActionEvent e) {
            if (getName() == CLOSE) {
                JOptionPane optionPane = (JOptionPane)e.getSource();

                optionPane.setValue(new Integer(JOptionPane.CLOSED_OPTION));
            }
        }
    }


    /**
     * This class is used to create the default buttons. This indirection is
     * used so that addButtonComponents can tell which Buttons were created
     * by us vs subclassers or from the JOptionPane itself.
     */
    private static class ButtonFactory {
        private String text;
        private int mnemonic;
        private Icon icon;
        private int minimumWidth = -1;

        ButtonFactory(String text, int mnemonic, Icon icon, int minimumWidth) {
            this.text = text;
            this.mnemonic = mnemonic;
            this.icon = icon;
            this.minimumWidth = minimumWidth;
        }

        JButton createButton() {
            JButton button = null;

            if (minimumWidth > 0) {
                button = new ConstrainedButton(text, minimumWidth);
            } else {
                button = new JButton(text);
            }
            if (icon != null) {
                button.setIcon(icon);
            }
            if (mnemonic != 0) {
                button.setMnemonic(mnemonic);
            }
            return button;
        }

        private static class ConstrainedButton extends JButton {
            int minimumWidth;

            ConstrainedButton(String text, int minimumWidth) {
                super(text);
                this.minimumWidth = minimumWidth;
            }

            public Dimension getMinimumSize() {
                Dimension min = super.getMinimumSize();
                min.width = Math.max(min.width, minimumWidth);
                return min;
            }

            public Dimension getPreferredSize() {
                Dimension pref = super.getPreferredSize();
                pref.width = Math.max(pref.width, minimumWidth);
                return pref;
            }
        }
    }
}
