1/*
2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package javax.swing;
26
27import java.awt.BorderLayout;
28import java.awt.Component;
29import java.awt.Container;
30import java.awt.Dialog;
31import java.awt.Dimension;
32import java.awt.KeyboardFocusManager;
33import java.awt.Frame;
34import java.awt.Point;
35import java.awt.HeadlessException;
36import java.awt.Window;
37import java.beans.JavaBean;
38import java.beans.BeanProperty;
39import java.beans.PropertyChangeEvent;
40import java.beans.PropertyChangeListener;
41import java.awt.event.WindowListener;
42import java.awt.event.WindowAdapter;
43import java.awt.event.WindowEvent;
44import java.awt.event.ComponentAdapter;
45import java.awt.event.ComponentEvent;
46import java.io.IOException;
47import java.io.InvalidObjectException;
48import java.io.ObjectInputStream;
49import java.io.ObjectOutputStream;
50import java.io.Serializable;
51import java.util.Arrays;
52import java.util.Vector;
53import javax.swing.plaf.OptionPaneUI;
54import javax.swing.event.InternalFrameEvent;
55import javax.swing.event.InternalFrameAdapter;
56import javax.accessibility.*;
57import static javax.swing.ClientPropertyKey.PopupFactory_FORCE_HEAVYWEIGHT_POPUP;
58import sun.awt.AWTAccessor;
59
60/**
61 * <code>JOptionPane</code> makes it easy to pop up a standard dialog box that
62 * prompts users for a value or informs them of something.
63 * For information about using <code>JOptionPane</code>, see
64 * <a
65 href="http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html">How to Make Dialogs</a>,
66 * a section in <em>The Java Tutorial</em>.
67 *
68 * <p>
69 *
70 * While the <code>JOptionPane</code>
71 * class may appear complex because of the large number of methods, almost
72 * all uses of this class are one-line calls to one of the static
73 * <code>showXxxDialog</code> methods shown below:
74 * <blockquote>
75 *
76 * <table class="striped">
77 * <caption>Common JOptionPane method names and their descriptions</caption>
78 * <thead>
79 * <tr>
80 *    <th>Method Name</th>
81 *    <th>Description</th>
82 * </tr>
83 * </thead>
84 * <tbody>
85 * <tr>
86 *    <td>showConfirmDialog</td>
87 *    <td>Asks a confirming question, like yes/no/cancel.</td>
88 * </tr>
89 * <tr>
90 *    <td>showInputDialog</td>
91 *    <td>Prompt for some input.</td>
92 * </tr>
93 * <tr>
94 *   <td>showMessageDialog</td>
95 *   <td>Tell the user about something that has happened.</td>
96 * </tr>
97 * <tr>
98 *   <td>showOptionDialog</td>
99 *   <td>The Grand Unification of the above three.</td>
100 * </tr>
101 * </tbody>
102 * </table>
103 *
104 * </blockquote>
105 * Each of these methods also comes in a <code>showInternalXXX</code>
106 * flavor, which uses an internal frame to hold the dialog box (see
107 * {@link JInternalFrame}).
108 * Multiple convenience methods have also been defined -- overloaded
109 * versions of the basic methods that use different parameter lists.
110 * <p>
111 * All dialogs are modal. Each <code>showXxxDialog</code> method blocks
112 * the caller until the user's interaction is complete.
113 *
114 * <table class="borderless">
115 * <caption>Common dialog</caption>
116 * <tr>
117 *  <td style="background-color:#FFe0d0" rowspan=2>icon</td>
118 *  <td style="background-color:#FFe0d0">message</td>
119 * </tr>
120 * <tr>
121 *  <td style="background-color:#FFe0d0">input value</td>
122 * </tr>
123 * <tr>
124 *   <td style="background-color:#FFe0d0" colspan=2>option buttons</td>
125 * </tr>
126 * </table>
127 *
128 * The basic appearance of one of these dialog boxes is generally
129 * similar to the picture above, although the various
130 * look-and-feels are
131 * ultimately responsible for the final result.  In particular, the
132 * look-and-feels will adjust the layout to accommodate the option pane's
133 * <code>ComponentOrientation</code> property.
134 * <br style="clear:all">
135 * <p>
136 * <b>Parameters:</b><br>
137 * The parameters to these methods follow consistent patterns:
138 * <blockquote>
139 * <dl>
140 * <dt>parentComponent<dd>
141 * Defines the <code>Component</code> that is to be the parent of this
142 * dialog box.
143 * It is used in two ways: the <code>Frame</code> that contains
144 * it is used as the <code>Frame</code>
145 * parent for the dialog box, and its screen coordinates are used in
146 * the placement of the dialog box. In general, the dialog box is placed
147 * just below the component. This parameter may be <code>null</code>,
148 * in which case a default <code>Frame</code> is used as the parent,
149 * and the dialog will be
150 * centered on the screen (depending on the {@literal L&F}).
151 * <dt><a id=message>message</a><dd>
152 * A descriptive message to be placed in the dialog box.
153 * In the most common usage, message is just a <code>String</code> or
154 * <code>String</code> constant.
155 * However, the type of this parameter is actually <code>Object</code>. Its
156 * interpretation depends on its type:
157 * <dl>
158 * <dt>Object[]<dd>An array of objects is interpreted as a series of
159 *                 messages (one per object) arranged in a vertical stack.
160 *                 The interpretation is recursive -- each object in the
161 *                 array is interpreted according to its type.
162 * <dt>Component<dd>The <code>Component</code> is displayed in the dialog.
163 * <dt>Icon<dd>The <code>Icon</code> is wrapped in a <code>JLabel</code>
164 *               and displayed in the dialog.
165 * <dt>others<dd>The object is converted to a <code>String</code> by calling
166 *               its <code>toString</code> method. The result is wrapped in a
167 *               <code>JLabel</code> and displayed.
168 * </dl>
169 * <dt>messageType<dd>Defines the style of the message. The Look and Feel
170 * manager may lay out the dialog differently depending on this value, and
171 * will often provide a default icon. The possible values are:
172 * <ul>
173 * <li><code>ERROR_MESSAGE</code>
174 * <li><code>INFORMATION_MESSAGE</code>
175 * <li><code>WARNING_MESSAGE</code>
176 * <li><code>QUESTION_MESSAGE</code>
177 * <li><code>PLAIN_MESSAGE</code>
178 * </ul>
179 * <dt>optionType<dd>Defines the set of option buttons that appear at
180 * the bottom of the dialog box:
181 * <ul>
182 * <li><code>DEFAULT_OPTION</code>
183 * <li><code>YES_NO_OPTION</code>
184 * <li><code>YES_NO_CANCEL_OPTION</code>
185 * <li><code>OK_CANCEL_OPTION</code>
186 * </ul>
187 * You aren't limited to this set of option buttons.  You can provide any
188 * buttons you want using the options parameter.
189 * <dt>options<dd>A more detailed description of the set of option buttons
190 * that will appear at the bottom of the dialog box.
191 * The usual value for the options parameter is an array of
192 * <code>String</code>s. But
193 * the parameter type is an array of <code>Objects</code>.
194 * A button is created for each object depending on its type:
195 * <dl>
196 * <dt>Component<dd>The component is added to the button row directly.
197 * <dt>Icon<dd>A <code>JButton</code> is created with this as its label.
198 * <dt>other<dd>The <code>Object</code> is converted to a string using its
199 *              <code>toString</code> method and the result is used to
200 *              label a <code>JButton</code>.
201 * </dl>
202 * <dt>icon<dd>A decorative icon to be placed in the dialog box. A default
203 * value for this is determined by the <code>messageType</code> parameter.
204 * <dt>title<dd>The title for the dialog box.
205 * <dt>initialValue<dd>The default selection (input value).
206 * </dl>
207 * </blockquote>
208 * <p>
209 * When the selection is changed, <code>setValue</code> is invoked,
210 * which generates a <code>PropertyChangeEvent</code>.
211 * <p>
212 * If a <code>JOptionPane</code> has configured to all input
213 * <code>setWantsInput</code>
214 * the bound property <code>JOptionPane.INPUT_VALUE_PROPERTY</code>
215 *  can also be listened
216 * to, to determine when the user has input or selected a value.
217 * <p>
218 * When one of the <code>showXxxDialog</code> methods returns an integer,
219 * the possible values are:
220 * <ul>
221 * <li><code>YES_OPTION</code>
222 * <li><code>NO_OPTION</code>
223 * <li><code>CANCEL_OPTION</code>
224 * <li><code>OK_OPTION</code>
225 * <li><code>CLOSED_OPTION</code>
226 * </ul>
227 * <b>Examples:</b>
228 * <dl>
229 * <dt>Show an error dialog that displays the message, 'alert':
230 * <dd><code>
231 * JOptionPane.showMessageDialog(null, "alert", "alert", JOptionPane.ERROR_MESSAGE);
232 * </code>
233 * <dt>Show an internal information dialog with the message, 'information':
234 * <dd><pre>
235 * JOptionPane.showInternalMessageDialog(frame, "information",
236 *             "information", JOptionPane.INFORMATION_MESSAGE);
237 * </pre>
238 * <dt>Show an information panel with the options yes/no and message 'choose one':
239 * <dd><pre>JOptionPane.showConfirmDialog(null,
240 *             "choose one", "choose one", JOptionPane.YES_NO_OPTION);
241 * </pre>
242 * <dt>Show an internal information dialog with the options yes/no/cancel and
243 * message 'please choose one' and title information:
244 * <dd><pre>JOptionPane.showInternalConfirmDialog(frame,
245 *             "please choose one", "information",
246 *             JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
247 * </pre>
248 * <dt>Show a warning dialog with the options OK, CANCEL, title 'Warning', and
249 * message 'Click OK to continue':
250 * <dd><pre>
251 * Object[] options = { "OK", "CANCEL" };
252 * JOptionPane.showOptionDialog(null, "Click OK to continue", "Warning",
253 *             JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
254 *             null, options, options[0]);
255 * </pre>
256 * <dt>Show a dialog asking the user to type in a String:
257 * <dd><code>
258 * String inputValue = JOptionPane.showInputDialog("Please input a value");
259 * </code>
260 * <dt>Show a dialog asking the user to select a String:
261 * <dd><pre>
262 * Object[] possibleValues = { "First", "Second", "Third" };<br>
263 * Object selectedValue = JOptionPane.showInputDialog(null,
264 *             "Choose one", "Input",
265 *             JOptionPane.INFORMATION_MESSAGE, null,
266 *             possibleValues, possibleValues[0]);
267 * </pre>
268 * </dl>
269 * <b>Direct Use:</b><br>
270 * To create and use an <code>JOptionPane</code> directly, the
271 * standard pattern is roughly as follows:
272 * <pre>
273 *     JOptionPane pane = new JOptionPane(<i>arguments</i>);
274 *     pane.set<i>.Xxxx(...); // Configure</i>
275 *     JDialog dialog = pane.createDialog(<i>parentComponent, title</i>);
276 *     dialog.show();
277 *     Object selectedValue = pane.getValue();
278 *     if(selectedValue == null)
279 *       return CLOSED_OPTION;
280 *     <i>//If there is <b>not</b> an array of option buttons:</i>
281 *     if(options == null) {
282 *       if(selectedValue instanceof Integer)
283 *          return ((Integer)selectedValue).intValue();
284 *       return CLOSED_OPTION;
285 *     }
286 *     <i>//If there is an array of option buttons:</i>
287 *     for(int counter = 0, maxCounter = options.length;
288 *        counter &lt; maxCounter; counter++) {
289 *        if(options[counter].equals(selectedValue))
290 *        return counter;
291 *     }
292 *     return CLOSED_OPTION;
293 * </pre>
294 * <p>
295 * <strong>Warning:</strong> Swing is not thread safe. For more
296 * information see <a
297 * href="package-summary.html#threading">Swing's Threading
298 * Policy</a>.
299 * <p>
300 * <strong>Warning:</strong>
301 * Serialized objects of this class will not be compatible with
302 * future Swing releases. The current serialization support is
303 * appropriate for short term storage or RMI between applications running
304 * the same version of Swing.  As of 1.4, support for long term storage
305 * of all JavaBeans&trade;
306 * has been added to the <code>java.beans</code> package.
307 * Please see {@link java.beans.XMLEncoder}.
308 *
309 * @see JInternalFrame
310 *
311 * @author James Gosling
312 * @author Scott Violet
313 * @since 1.2
314 */
315@JavaBean(defaultProperty = "UI", description = "A component which implements standard dialog box controls.")
316@SwingContainer
317@SuppressWarnings("serial") // Same-version serialization only
318public class JOptionPane extends JComponent implements Accessible
319{
320    /**
321     * @see #getUIClassID
322     * @see #readObject
323     */
324    private static final String uiClassID = "OptionPaneUI";
325
326    /**
327     * Indicates that the user has not yet selected a value.
328     */
329    public static final Object      UNINITIALIZED_VALUE = "uninitializedValue";
330
331    //
332    // Option types
333    //
334
335    /**
336     * Type meaning Look and Feel should not supply any options -- only
337     * use the options from the <code>JOptionPane</code>.
338     */
339    public static final int         DEFAULT_OPTION = -1;
340    /** Type used for <code>showConfirmDialog</code>. */
341    public static final int         YES_NO_OPTION = 0;
342    /** Type used for <code>showConfirmDialog</code>. */
343    public static final int         YES_NO_CANCEL_OPTION = 1;
344    /** Type used for <code>showConfirmDialog</code>. */
345    public static final int         OK_CANCEL_OPTION = 2;
346
347    //
348    // Return values.
349    //
350    /** Return value from class method if YES is chosen. */
351    public static final int         YES_OPTION = 0;
352    /** Return value from class method if NO is chosen. */
353    public static final int         NO_OPTION = 1;
354    /** Return value from class method if CANCEL is chosen. */
355    public static final int         CANCEL_OPTION = 2;
356    /** Return value form class method if OK is chosen. */
357    public static final int         OK_OPTION = 0;
358    /** Return value from class method if user closes window without selecting
359     * anything, more than likely this should be treated as either a
360     * <code>CANCEL_OPTION</code> or <code>NO_OPTION</code>. */
361    public static final int         CLOSED_OPTION = -1;
362
363    //
364    // Message types. Used by the UI to determine what icon to display,
365    // and possibly what behavior to give based on the type.
366    //
367    /** Used for error messages. */
368    public static final int  ERROR_MESSAGE = 0;
369    /** Used for information messages. */
370    public static final int  INFORMATION_MESSAGE = 1;
371    /** Used for warning messages. */
372    public static final int  WARNING_MESSAGE = 2;
373    /** Used for questions. */
374    public static final int  QUESTION_MESSAGE = 3;
375    /** No icon is used. */
376    public static final int   PLAIN_MESSAGE = -1;
377
378    /** Bound property name for <code>icon</code>. */
379    public static final String      ICON_PROPERTY = "icon";
380    /** Bound property name for <code>message</code>. */
381    public static final String      MESSAGE_PROPERTY = "message";
382    /** Bound property name for <code>value</code>. */
383    public static final String      VALUE_PROPERTY = "value";
384    /** Bound property name for <code>option</code>. */
385    public static final String      OPTIONS_PROPERTY = "options";
386    /** Bound property name for <code>initialValue</code>. */
387    public static final String      INITIAL_VALUE_PROPERTY = "initialValue";
388    /** Bound property name for <code>type</code>. */
389    public static final String      MESSAGE_TYPE_PROPERTY = "messageType";
390    /** Bound property name for <code>optionType</code>. */
391    public static final String      OPTION_TYPE_PROPERTY = "optionType";
392    /** Bound property name for <code>selectionValues</code>. */
393    public static final String      SELECTION_VALUES_PROPERTY = "selectionValues";
394    /** Bound property name for <code>initialSelectionValue</code>. */
395    public static final String      INITIAL_SELECTION_VALUE_PROPERTY = "initialSelectionValue";
396    /** Bound property name for <code>inputValue</code>. */
397    public static final String      INPUT_VALUE_PROPERTY = "inputValue";
398    /** Bound property name for <code>wantsInput</code>. */
399    public static final String      WANTS_INPUT_PROPERTY = "wantsInput";
400
401    /** Icon used in pane. */
402    protected transient Icon                  icon;
403    /** Message to display. */
404    protected transient Object                message;
405    /** Options to display to the user. */
406    protected transient Object[]              options;
407    /** Value that should be initially selected in <code>options</code>. */
408    protected transient Object                initialValue;
409    /** Message type. */
410    protected int                   messageType;
411    /**
412     * Option type, one of <code>DEFAULT_OPTION</code>,
413     * <code>YES_NO_OPTION</code>,
414     * <code>YES_NO_CANCEL_OPTION</code> or
415     * <code>OK_CANCEL_OPTION</code>.
416     */
417    protected int                   optionType;
418    /** Currently selected value, will be a valid option, or
419     * <code>UNINITIALIZED_VALUE</code> or <code>null</code>. */
420    protected transient Object                value;
421    /** Array of values the user can choose from. Look and feel will
422     * provide the UI component to choose this from. */
423    protected transient Object[]              selectionValues;
424    /** Value the user has input. */
425    protected transient Object                inputValue;
426    /** Initial value to select in <code>selectionValues</code>. */
427    protected transient Object                initialSelectionValue;
428    /** If true, a UI widget will be provided to the user to get input. */
429    protected boolean                         wantsInput;
430
431
432    /**
433     * Shows a question-message dialog requesting input from the user. The
434     * dialog uses the default frame, which usually means it is centered on
435     * the screen.
436     *
437     * @param message the <code>Object</code> to display
438     * @exception HeadlessException if
439     *   <code>GraphicsEnvironment.isHeadless</code> returns
440     *   <code>true</code>
441     * @return user's input
442     * @see java.awt.GraphicsEnvironment#isHeadless
443     */
444    public static String showInputDialog(Object message)
445        throws HeadlessException {
446        return showInputDialog(null, message);
447    }
448
449    /**
450     * Shows a question-message dialog requesting input from the user, with
451     * the input value initialized to <code>initialSelectionValue</code>. The
452     * dialog uses the default frame, which usually means it is centered on
453     * the screen.
454     *
455     * @param message the <code>Object</code> to display
456     * @param initialSelectionValue the value used to initialize the input
457     *                 field
458     * @return user's input
459     * @since 1.4
460     */
461    public static String showInputDialog(Object message, Object initialSelectionValue) {
462        return showInputDialog(null, message, initialSelectionValue);
463    }
464
465    /**
466     * Shows a question-message dialog requesting input from the user
467     * parented to <code>parentComponent</code>.
468     * The dialog is displayed on top of the <code>Component</code>'s
469     * frame, and is usually positioned below the <code>Component</code>.
470     *
471     * @param parentComponent  the parent <code>Component</code> for the
472     *          dialog
473     * @param message  the <code>Object</code> to display
474     * @exception HeadlessException if
475     *    <code>GraphicsEnvironment.isHeadless</code> returns
476     *    <code>true</code>
477     * @return user's input
478     * @see java.awt.GraphicsEnvironment#isHeadless
479     */
480    public static String showInputDialog(Component parentComponent,
481        Object message) throws HeadlessException {
482        return showInputDialog(parentComponent, message, UIManager.getString(
483            "OptionPane.inputDialogTitle", parentComponent), QUESTION_MESSAGE);
484    }
485
486    /**
487     * Shows a question-message dialog requesting input from the user and
488     * parented to <code>parentComponent</code>. The input value will be
489     * initialized to <code>initialSelectionValue</code>.
490     * The dialog is displayed on top of the <code>Component</code>'s
491     * frame, and is usually positioned below the <code>Component</code>.
492     *
493     * @param parentComponent  the parent <code>Component</code> for the
494     *          dialog
495     * @param message the <code>Object</code> to display
496     * @param initialSelectionValue the value used to initialize the input
497     *                 field
498     * @return user's input
499     * @since 1.4
500     */
501    public static String showInputDialog(Component parentComponent, Object message,
502                                         Object initialSelectionValue) {
503        return (String)showInputDialog(parentComponent, message,
504                      UIManager.getString("OptionPane.inputDialogTitle",
505                      parentComponent), QUESTION_MESSAGE, null, null,
506                      initialSelectionValue);
507    }
508
509    /**
510     * Shows a dialog requesting input from the user parented to
511     * <code>parentComponent</code> with the dialog having the title
512     * <code>title</code> and message type <code>messageType</code>.
513     *
514     * @param parentComponent  the parent <code>Component</code> for the
515     *                  dialog
516     * @param message  the <code>Object</code> to display
517     * @param title    the <code>String</code> to display in the dialog
518     *                  title bar
519     * @param messageType the type of message that is to be displayed:
520     *                  <code>ERROR_MESSAGE</code>,
521     *                  <code>INFORMATION_MESSAGE</code>,
522     *                  <code>WARNING_MESSAGE</code>,
523     *                  <code>QUESTION_MESSAGE</code>,
524     *                  or <code>PLAIN_MESSAGE</code>
525     * @return user's input
526     * @exception HeadlessException if
527     *   <code>GraphicsEnvironment.isHeadless</code> returns
528     *   <code>true</code>
529     * @see java.awt.GraphicsEnvironment#isHeadless
530     */
531    public static String showInputDialog(Component parentComponent,
532        Object message, String title, int messageType)
533        throws HeadlessException {
534        return (String)showInputDialog(parentComponent, message, title,
535                                       messageType, null, null, null);
536    }
537
538    /**
539     * Prompts the user for input in a blocking dialog where the
540     * initial selection, possible selections, and all other options can
541     * be specified. The user will able to choose from
542     * <code>selectionValues</code>, where <code>null</code> implies the
543     * user can input
544     * whatever they wish, usually by means of a <code>JTextField</code>.
545     * <code>initialSelectionValue</code> is the initial value to prompt
546     * the user with. It is up to the UI to decide how best to represent
547     * the <code>selectionValues</code>, but usually a
548     * <code>JComboBox</code>, <code>JList</code>, or
549     * <code>JTextField</code> will be used.
550     *
551     * @param parentComponent  the parent <code>Component</code> for the
552     *                  dialog
553     * @param message  the <code>Object</code> to display
554     * @param title    the <code>String</code> to display in the
555     *                  dialog title bar
556     * @param messageType the type of message to be displayed:
557     *                  <code>ERROR_MESSAGE</code>,
558     *                  <code>INFORMATION_MESSAGE</code>,
559     *                  <code>WARNING_MESSAGE</code>,
560     *                  <code>QUESTION_MESSAGE</code>,
561     *                  or <code>PLAIN_MESSAGE</code>
562     * @param icon     the <code>Icon</code> image to display
563     * @param selectionValues an array of <code>Object</code>s that
564     *                  gives the possible selections
565     * @param initialSelectionValue the value used to initialize the input
566     *                 field
567     * @return user's input, or <code>null</code> meaning the user
568     *                  canceled the input
569     * @exception HeadlessException if
570     *   <code>GraphicsEnvironment.isHeadless</code> returns
571     *   <code>true</code>
572     * @see java.awt.GraphicsEnvironment#isHeadless
573     */
574    @SuppressWarnings("deprecation")
575    public static Object showInputDialog(Component parentComponent,
576        Object message, String title, int messageType, Icon icon,
577        Object[] selectionValues, Object initialSelectionValue)
578        throws HeadlessException {
579        JOptionPane    pane = new JOptionPane(message, messageType,
580                                              OK_CANCEL_OPTION, icon,
581                                              null, null);
582
583        pane.setWantsInput(true);
584        pane.setSelectionValues(selectionValues);
585        pane.setInitialSelectionValue(initialSelectionValue);
586        pane.setComponentOrientation(((parentComponent == null) ?
587            getRootFrame() : parentComponent).getComponentOrientation());
588
589        int style = styleFromMessageType(messageType);
590        JDialog dialog = pane.createDialog(parentComponent, title, style);
591
592        pane.selectInitialValue();
593        dialog.show();
594        dialog.dispose();
595
596        Object value = pane.getInputValue();
597
598        if (value == UNINITIALIZED_VALUE) {
599            return null;
600        }
601        return value;
602    }
603
604    /**
605     * Brings up an information-message dialog titled "Message".
606     *
607     * @param parentComponent determines the <code>Frame</code> in
608     *          which the dialog is displayed; if <code>null</code>,
609     *          or if the <code>parentComponent</code> has no
610     *          <code>Frame</code>, a default <code>Frame</code> is used
611     * @param message   the <code>Object</code> to display
612     * @exception HeadlessException if
613     *   <code>GraphicsEnvironment.isHeadless</code> returns
614     *   <code>true</code>
615     * @see java.awt.GraphicsEnvironment#isHeadless
616     */
617    public static void showMessageDialog(Component parentComponent,
618        Object message) throws HeadlessException {
619        showMessageDialog(parentComponent, message, UIManager.getString(
620                    "OptionPane.messageDialogTitle", parentComponent),
621                    INFORMATION_MESSAGE);
622    }
623
624    /**
625     * Brings up a dialog that displays a message using a default
626     * icon determined by the <code>messageType</code> parameter.
627     *
628     * @param parentComponent determines the <code>Frame</code>
629     *          in which the dialog is displayed; if <code>null</code>,
630     *          or if the <code>parentComponent</code> has no
631     *          <code>Frame</code>, a default <code>Frame</code> is used
632     * @param message   the <code>Object</code> to display
633     * @param title     the title string for the dialog
634     * @param messageType the type of message to be displayed:
635     *                  <code>ERROR_MESSAGE</code>,
636     *                  <code>INFORMATION_MESSAGE</code>,
637     *                  <code>WARNING_MESSAGE</code>,
638     *                  <code>QUESTION_MESSAGE</code>,
639     *                  or <code>PLAIN_MESSAGE</code>
640     * @exception HeadlessException if
641     *   <code>GraphicsEnvironment.isHeadless</code> returns
642     *   <code>true</code>
643     * @see java.awt.GraphicsEnvironment#isHeadless
644     */
645    public static void showMessageDialog(Component parentComponent,
646        Object message, String title, int messageType)
647        throws HeadlessException {
648        showMessageDialog(parentComponent, message, title, messageType, null);
649    }
650
651    /**
652     * Brings up a dialog displaying a message, specifying all parameters.
653     *
654     * @param parentComponent determines the <code>Frame</code> in which the
655     *                  dialog is displayed; if <code>null</code>,
656     *                  or if the <code>parentComponent</code> has no
657     *                  <code>Frame</code>, a
658     *                  default <code>Frame</code> is used
659     * @param message   the <code>Object</code> to display
660     * @param title     the title string for the dialog
661     * @param messageType the type of message to be displayed:
662     *                  <code>ERROR_MESSAGE</code>,
663     *                  <code>INFORMATION_MESSAGE</code>,
664     *                  <code>WARNING_MESSAGE</code>,
665     *                  <code>QUESTION_MESSAGE</code>,
666     *                  or <code>PLAIN_MESSAGE</code>
667     * @param icon      an icon to display in the dialog that helps the user
668     *                  identify the kind of message that is being displayed
669     * @exception HeadlessException if
670     *   <code>GraphicsEnvironment.isHeadless</code> returns
671     *   <code>true</code>
672     * @see java.awt.GraphicsEnvironment#isHeadless
673     */
674    public static void showMessageDialog(Component parentComponent,
675        Object message, String title, int messageType, Icon icon)
676        throws HeadlessException {
677        showOptionDialog(parentComponent, message, title, DEFAULT_OPTION,
678                         messageType, icon, null, null);
679    }
680
681    /**
682     * Brings up a dialog with the options <i>Yes</i>,
683     * <i>No</i> and <i>Cancel</i>; with the
684     * title, <b>Select an Option</b>.
685     *
686     * @param parentComponent determines the <code>Frame</code> in which the
687     *                  dialog is displayed; if <code>null</code>,
688     *                  or if the <code>parentComponent</code> has no
689     *                  <code>Frame</code>, a
690     *                  default <code>Frame</code> is used
691     * @param message   the <code>Object</code> to display
692     * @return an integer indicating the option selected by the user
693     * @exception HeadlessException if
694     *   <code>GraphicsEnvironment.isHeadless</code> returns
695     *   <code>true</code>
696     * @see java.awt.GraphicsEnvironment#isHeadless
697     */
698    public static int showConfirmDialog(Component parentComponent,
699        Object message) throws HeadlessException {
700        return showConfirmDialog(parentComponent, message,
701                                 UIManager.getString("OptionPane.titleText"),
702                                 YES_NO_CANCEL_OPTION);
703    }
704
705    /**
706     * Brings up a dialog where the number of choices is determined
707     * by the <code>optionType</code> parameter.
708     *
709     * @param parentComponent determines the <code>Frame</code> in which the
710     *                  dialog is displayed; if <code>null</code>,
711     *                  or if the <code>parentComponent</code> has no
712     *                  <code>Frame</code>, a
713     *                  default <code>Frame</code> is used
714     * @param message   the <code>Object</code> to display
715     * @param title     the title string for the dialog
716     * @param optionType an int designating the options available on the dialog:
717     *                  <code>YES_NO_OPTION</code>,
718     *                  <code>YES_NO_CANCEL_OPTION</code>,
719     *                  or <code>OK_CANCEL_OPTION</code>
720     * @return an int indicating the option selected by the user
721     * @exception HeadlessException if
722     *   <code>GraphicsEnvironment.isHeadless</code> returns
723     *   <code>true</code>
724     * @see java.awt.GraphicsEnvironment#isHeadless
725     */
726    public static int showConfirmDialog(Component parentComponent,
727        Object message, String title, int optionType)
728        throws HeadlessException {
729        return showConfirmDialog(parentComponent, message, title, optionType,
730                                 QUESTION_MESSAGE);
731    }
732
733    /**
734     * Brings up a dialog where the number of choices is determined
735     * by the <code>optionType</code> parameter, where the
736     * <code>messageType</code>
737     * parameter determines the icon to display.
738     * The <code>messageType</code> parameter is primarily used to supply
739     * a default icon from the Look and Feel.
740     *
741     * @param parentComponent determines the <code>Frame</code> in
742     *                  which the dialog is displayed; if <code>null</code>,
743     *                  or if the <code>parentComponent</code> has no
744     *                  <code>Frame</code>, a
745     *                  default <code>Frame</code> is used.
746     * @param message   the <code>Object</code> to display
747     * @param title     the title string for the dialog
748     * @param optionType an integer designating the options available
749     *                   on the dialog: <code>YES_NO_OPTION</code>,
750     *                  <code>YES_NO_CANCEL_OPTION</code>,
751     *                  or <code>OK_CANCEL_OPTION</code>
752     * @param messageType an integer designating the kind of message this is;
753     *                  primarily used to determine the icon from the pluggable
754     *                  Look and Feel: <code>ERROR_MESSAGE</code>,
755     *                  <code>INFORMATION_MESSAGE</code>,
756     *                  <code>WARNING_MESSAGE</code>,
757     *                  <code>QUESTION_MESSAGE</code>,
758     *                  or <code>PLAIN_MESSAGE</code>
759     * @return an integer indicating the option selected by the user
760     * @exception HeadlessException if
761     *   <code>GraphicsEnvironment.isHeadless</code> returns
762     *   <code>true</code>
763     * @see java.awt.GraphicsEnvironment#isHeadless
764     */
765    public static int showConfirmDialog(Component parentComponent,
766        Object message, String title, int optionType, int messageType)
767        throws HeadlessException {
768        return showConfirmDialog(parentComponent, message, title, optionType,
769                                messageType, null);
770    }
771
772    /**
773     * Brings up a dialog with a specified icon, where the number of
774     * choices is determined by the <code>optionType</code> parameter.
775     * The <code>messageType</code> parameter is primarily used to supply
776     * a default icon from the look and feel.
777     *
778     * @param parentComponent determines the <code>Frame</code> in which the
779     *                  dialog is displayed; if <code>null</code>,
780     *                  or if the <code>parentComponent</code> has no
781     *                  <code>Frame</code>, a
782     *                  default <code>Frame</code> is used
783     * @param message   the Object to display
784     * @param title     the title string for the dialog
785     * @param optionType an int designating the options available on the dialog:
786     *                  <code>YES_NO_OPTION</code>,
787     *                  <code>YES_NO_CANCEL_OPTION</code>,
788     *                  or <code>OK_CANCEL_OPTION</code>
789     * @param messageType an int designating the kind of message this is,
790     *                  primarily used to determine the icon from the pluggable
791     *                  Look and Feel: <code>ERROR_MESSAGE</code>,
792     *                  <code>INFORMATION_MESSAGE</code>,
793     *                  <code>WARNING_MESSAGE</code>,
794     *                  <code>QUESTION_MESSAGE</code>,
795     *                  or <code>PLAIN_MESSAGE</code>
796     * @param icon      the icon to display in the dialog
797     * @return an int indicating the option selected by the user
798     * @exception HeadlessException if
799     *   <code>GraphicsEnvironment.isHeadless</code> returns
800     *   <code>true</code>
801     * @see java.awt.GraphicsEnvironment#isHeadless
802     */
803    public static int showConfirmDialog(Component parentComponent,
804        Object message, String title, int optionType,
805        int messageType, Icon icon) throws HeadlessException {
806        return showOptionDialog(parentComponent, message, title, optionType,
807                                messageType, icon, null, null);
808    }
809
810    /**
811     * Brings up a dialog with a specified icon, where the initial
812     * choice is determined by the <code>initialValue</code> parameter and
813     * the number of choices is determined by the <code>optionType</code>
814     * parameter.
815     * <p>
816     * If <code>optionType</code> is <code>YES_NO_OPTION</code>,
817     * or <code>YES_NO_CANCEL_OPTION</code>
818     * and the <code>options</code> parameter is <code>null</code>,
819     * then the options are
820     * supplied by the look and feel.
821     * <p>
822     * The <code>messageType</code> parameter is primarily used to supply
823     * a default icon from the look and feel.
824     *
825     * @param parentComponent determines the <code>Frame</code>
826     *                  in which the dialog is displayed;  if
827     *                  <code>null</code>, or if the
828     *                  <code>parentComponent</code> has no
829     *                  <code>Frame</code>, a
830     *                  default <code>Frame</code> is used
831     * @param message   the <code>Object</code> to display
832     * @param title     the title string for the dialog
833     * @param optionType an integer designating the options available on the
834     *                  dialog: <code>DEFAULT_OPTION</code>,
835     *                  <code>YES_NO_OPTION</code>,
836     *                  <code>YES_NO_CANCEL_OPTION</code>,
837     *                  or <code>OK_CANCEL_OPTION</code>
838     * @param messageType an integer designating the kind of message this is,
839     *                  primarily used to determine the icon from the
840     *                  pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
841     *                  <code>INFORMATION_MESSAGE</code>,
842     *                  <code>WARNING_MESSAGE</code>,
843     *                  <code>QUESTION_MESSAGE</code>,
844     *                  or <code>PLAIN_MESSAGE</code>
845     * @param icon      the icon to display in the dialog
846     * @param options   an array of objects indicating the possible choices
847     *                  the user can make; if the objects are components, they
848     *                  are rendered properly; non-<code>String</code>
849     *                  objects are
850     *                  rendered using their <code>toString</code> methods;
851     *                  if this parameter is <code>null</code>,
852     *                  the options are determined by the Look and Feel
853     * @param initialValue the object that represents the default selection
854     *                  for the dialog; only meaningful if <code>options</code>
855     *                  is used; can be <code>null</code>
856     * @return an integer indicating the option chosen by the user,
857     *                  or <code>CLOSED_OPTION</code> if the user closed
858     *                  the dialog
859     * @exception HeadlessException if
860     *   <code>GraphicsEnvironment.isHeadless</code> returns
861     *   <code>true</code>
862     * @see java.awt.GraphicsEnvironment#isHeadless
863     */
864    @SuppressWarnings("deprecation")
865    public static int showOptionDialog(Component parentComponent,
866        Object message, String title, int optionType, int messageType,
867        Icon icon, Object[] options, Object initialValue)
868        throws HeadlessException {
869        JOptionPane             pane = new JOptionPane(message, messageType,
870                                                       optionType, icon,
871                                                       options, initialValue);
872
873        pane.setInitialValue(initialValue);
874        pane.setComponentOrientation(((parentComponent == null) ?
875            getRootFrame() : parentComponent).getComponentOrientation());
876
877        int style = styleFromMessageType(messageType);
878        JDialog dialog = pane.createDialog(parentComponent, title, style);
879
880        pane.selectInitialValue();
881        dialog.show();
882        dialog.dispose();
883
884        Object        selectedValue = pane.getValue();
885
886        if(selectedValue == null)
887            return CLOSED_OPTION;
888        if(options == null) {
889            if(selectedValue instanceof Integer)
890                return ((Integer)selectedValue).intValue();
891            return CLOSED_OPTION;
892        }
893        for(int counter = 0, maxCounter = options.length;
894            counter < maxCounter; counter++) {
895            if(options[counter].equals(selectedValue))
896                return counter;
897        }
898        return CLOSED_OPTION;
899    }
900
901    /**
902     * Creates and returns a new <code>JDialog</code> wrapping
903     * <code>this</code> centered on the <code>parentComponent</code>
904     * in the <code>parentComponent</code>'s frame.
905     * <code>title</code> is the title of the returned dialog.
906     * The returned <code>JDialog</code> will not be resizable by the
907     * user, however programs can invoke <code>setResizable</code> on
908     * the <code>JDialog</code> instance to change this property.
909     * The returned <code>JDialog</code> will be set up such that
910     * once it is closed, or the user clicks on one of the buttons,
911     * the optionpane's value property will be set accordingly and
912     * the dialog will be closed.  Each time the dialog is made visible,
913     * it will reset the option pane's value property to
914     * <code>JOptionPane.UNINITIALIZED_VALUE</code> to ensure the
915     * user's subsequent action closes the dialog properly.
916     *
917     * @param parentComponent determines the frame in which the dialog
918     *          is displayed; if the <code>parentComponent</code> has
919     *          no <code>Frame</code>, a default <code>Frame</code> is used
920     * @param title     the title string for the dialog
921     * @return a new <code>JDialog</code> containing this instance
922     * @exception HeadlessException if
923     *   <code>GraphicsEnvironment.isHeadless</code> returns
924     *   <code>true</code>
925     * @see java.awt.GraphicsEnvironment#isHeadless
926     */
927    public JDialog createDialog(Component parentComponent, String title)
928        throws HeadlessException {
929        int style = styleFromMessageType(getMessageType());
930        return createDialog(parentComponent, title, style);
931    }
932
933    /**
934     * Creates and returns a new parentless <code>JDialog</code>
935     * with the specified title.
936     * The returned <code>JDialog</code> will not be resizable by the
937     * user, however programs can invoke <code>setResizable</code> on
938     * the <code>JDialog</code> instance to change this property.
939     * The returned <code>JDialog</code> will be set up such that
940     * once it is closed, or the user clicks on one of the buttons,
941     * the optionpane's value property will be set accordingly and
942     * the dialog will be closed.  Each time the dialog is made visible,
943     * it will reset the option pane's value property to
944     * <code>JOptionPane.UNINITIALIZED_VALUE</code> to ensure the
945     * user's subsequent action closes the dialog properly.
946     *
947     * @param title     the title string for the dialog
948     * @return a new <code>JDialog</code> containing this instance
949     * @exception HeadlessException if
950     *   <code>GraphicsEnvironment.isHeadless</code> returns
951     *   <code>true</code>
952     * @see java.awt.GraphicsEnvironment#isHeadless
953     * @since 1.6
954     */
955    public JDialog createDialog(String title) throws HeadlessException {
956        int style = styleFromMessageType(getMessageType());
957        JDialog dialog = new JDialog((Dialog) null, title, true);
958        initDialog(dialog, style, null);
959        return dialog;
960    }
961
962    private JDialog createDialog(Component parentComponent, String title,
963            int style)
964            throws HeadlessException {
965
966        final JDialog dialog;
967
968        Window window = JOptionPane.getWindowForComponent(parentComponent);
969        if (window instanceof Frame) {
970            dialog = new JDialog((Frame)window, title, true);
971        } else {
972            dialog = new JDialog((Dialog)window, title, true);
973        }
974        if (window instanceof SwingUtilities.SharedOwnerFrame) {
975            WindowListener ownerShutdownListener =
976                    SwingUtilities.getSharedOwnerFrameShutdownListener();
977            dialog.addWindowListener(ownerShutdownListener);
978        }
979        initDialog(dialog, style, parentComponent);
980        return dialog;
981    }
982
983    private void initDialog(final JDialog dialog, int style, Component parentComponent) {
984        dialog.setComponentOrientation(this.getComponentOrientation());
985        Container contentPane = dialog.getContentPane();
986
987        contentPane.setLayout(new BorderLayout());
988        contentPane.add(this, BorderLayout.CENTER);
989        dialog.setResizable(false);
990        if (JDialog.isDefaultLookAndFeelDecorated()) {
991            boolean supportsWindowDecorations =
992              UIManager.getLookAndFeel().getSupportsWindowDecorations();
993            if (supportsWindowDecorations) {
994                dialog.setUndecorated(true);
995                getRootPane().setWindowDecorationStyle(style);
996            }
997        }
998        dialog.pack();
999        dialog.setLocationRelativeTo(parentComponent);
1000
1001        final PropertyChangeListener listener = new PropertyChangeListener() {
1002            public void propertyChange(PropertyChangeEvent event) {
1003                // Let the defaultCloseOperation handle the closing
1004                // if the user closed the window without selecting a button
1005                // (newValue = null in that case).  Otherwise, close the dialog.
1006                if (dialog.isVisible() && event.getSource() == JOptionPane.this &&
1007                        (event.getPropertyName().equals(VALUE_PROPERTY)) &&
1008                        event.getNewValue() != null &&
1009                        event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
1010                    dialog.setVisible(false);
1011                }
1012            }
1013        };
1014
1015        WindowAdapter adapter = new WindowAdapter() {
1016            private boolean gotFocus = false;
1017            public void windowClosing(WindowEvent we) {
1018                setValue(null);
1019            }
1020
1021            public void windowClosed(WindowEvent e) {
1022                removePropertyChangeListener(listener);
1023                dialog.getContentPane().removeAll();
1024            }
1025
1026            public void windowGainedFocus(WindowEvent we) {
1027                // Once window gets focus, set initial focus
1028                if (!gotFocus) {
1029                    selectInitialValue();
1030                    gotFocus = true;
1031                }
1032            }
1033        };
1034        dialog.addWindowListener(adapter);
1035        dialog.addWindowFocusListener(adapter);
1036        dialog.addComponentListener(new ComponentAdapter() {
1037            public void componentShown(ComponentEvent ce) {
1038                // reset value to ensure closing works properly
1039                setValue(JOptionPane.UNINITIALIZED_VALUE);
1040            }
1041        });
1042
1043        addPropertyChangeListener(listener);
1044    }
1045
1046
1047    /**
1048     * Brings up an internal confirmation dialog panel. The dialog
1049     * is a information-message dialog titled "Message".
1050     *
1051     * @param parentComponent determines the <code>Frame</code>
1052     *          in which the dialog is displayed; if <code>null</code>,
1053     *          or if the <code>parentComponent</code> has no
1054     *          <code>Frame</code>, a default <code>Frame</code> is used
1055     * @param message   the object to display
1056     */
1057    public static void showInternalMessageDialog(Component parentComponent,
1058                                                 Object message) {
1059        showInternalMessageDialog(parentComponent, message, UIManager.
1060                                 getString("OptionPane.messageDialogTitle",
1061                                 parentComponent), INFORMATION_MESSAGE);
1062    }
1063
1064    /**
1065     * Brings up an internal dialog panel that displays a message
1066     * using a default icon determined by the <code>messageType</code>
1067     * parameter.
1068     *
1069     * @param parentComponent determines the <code>Frame</code>
1070     *          in which the dialog is displayed; if <code>null</code>,
1071     *          or if the <code>parentComponent</code> has no
1072     *          <code>Frame</code>, a default <code>Frame</code> is used
1073     * @param message   the <code>Object</code> to display
1074     * @param title     the title string for the dialog
1075     * @param messageType the type of message to be displayed:
1076     *                  <code>ERROR_MESSAGE</code>,
1077     *                  <code>INFORMATION_MESSAGE</code>,
1078     *                  <code>WARNING_MESSAGE</code>,
1079     *                  <code>QUESTION_MESSAGE</code>,
1080     *                  or <code>PLAIN_MESSAGE</code>
1081     */
1082    public static void showInternalMessageDialog(Component parentComponent,
1083                                                 Object message, String title,
1084                                                 int messageType) {
1085        showInternalMessageDialog(parentComponent, message, title, messageType,null);
1086    }
1087
1088    /**
1089     * Brings up an internal dialog panel displaying a message,
1090     * specifying all parameters.
1091     *
1092     * @param parentComponent determines the <code>Frame</code>
1093     *          in which the dialog is displayed; if <code>null</code>,
1094     *          or if the <code>parentComponent</code> has no
1095     *          <code>Frame</code>, a default <code>Frame</code> is used
1096     * @param message   the <code>Object</code> to display
1097     * @param title     the title string for the dialog
1098     * @param messageType the type of message to be displayed:
1099     *                  <code>ERROR_MESSAGE</code>,
1100     *                  <code>INFORMATION_MESSAGE</code>,
1101     *                  <code>WARNING_MESSAGE</code>,
1102     *                  <code>QUESTION_MESSAGE</code>,
1103     *                  or <code>PLAIN_MESSAGE</code>
1104     * @param icon      an icon to display in the dialog that helps the user
1105     *                  identify the kind of message that is being displayed
1106     */
1107    public static void showInternalMessageDialog(Component parentComponent,
1108                                         Object message,
1109                                         String title, int messageType,
1110                                         Icon icon){
1111        showInternalOptionDialog(parentComponent, message, title, DEFAULT_OPTION,
1112                                 messageType, icon, null, null);
1113    }
1114
1115    /**
1116     * Brings up an internal dialog panel with the options <i>Yes</i>, <i>No</i>
1117     * and <i>Cancel</i>; with the title, <b>Select an Option</b>.
1118     *
1119     * @param parentComponent determines the <code>Frame</code> in
1120     *          which the dialog is displayed; if <code>null</code>,
1121     *          or if the <code>parentComponent</code> has no
1122     *          <code>Frame</code>, a default <code>Frame</code> is used
1123     * @param message   the <code>Object</code> to display
1124     * @return an integer indicating the option selected by the user
1125     */
1126    public static int showInternalConfirmDialog(Component parentComponent,
1127                                                Object message) {
1128        return showInternalConfirmDialog(parentComponent, message,
1129                                 UIManager.getString("OptionPane.titleText"),
1130                                 YES_NO_CANCEL_OPTION);
1131    }
1132
1133    /**
1134     * Brings up a internal dialog panel where the number of choices
1135     * is determined by the <code>optionType</code> parameter.
1136     *
1137     * @param parentComponent determines the <code>Frame</code>
1138     *          in which the dialog is displayed; if <code>null</code>,
1139     *          or if the <code>parentComponent</code> has no
1140     *          <code>Frame</code>, a default <code>Frame</code> is used
1141     * @param message   the object to display in the dialog; a
1142     *          <code>Component</code> object is rendered as a
1143     *          <code>Component</code>; a <code>String</code>
1144     *          object is rendered as a string; other objects
1145     *          are converted to a <code>String</code> using the
1146     *          <code>toString</code> method
1147     * @param title     the title string for the dialog
1148     * @param optionType an integer designating the options
1149     *          available on the dialog: <code>YES_NO_OPTION</code>,
1150     *          or <code>YES_NO_CANCEL_OPTION</code>
1151     * @return an integer indicating the option selected by the user
1152     */
1153    public static int showInternalConfirmDialog(Component parentComponent,
1154                                                Object message, String title,
1155                                                int optionType) {
1156        return showInternalConfirmDialog(parentComponent, message, title, optionType,
1157                                         QUESTION_MESSAGE);
1158    }
1159
1160    /**
1161     * Brings up an internal dialog panel where the number of choices
1162     * is determined by the <code>optionType</code> parameter, where
1163     * the <code>messageType</code> parameter determines the icon to display.
1164     * The <code>messageType</code> parameter is primarily used to supply
1165     * a default icon from the Look and Feel.
1166     *
1167     * @param parentComponent determines the <code>Frame</code> in
1168     *          which the dialog is displayed; if <code>null</code>,
1169     *          or if the <code>parentComponent</code> has no
1170     *          <code>Frame</code>, a default <code>Frame</code> is used
1171     * @param message   the object to display in the dialog; a
1172     *          <code>Component</code> object is rendered as a
1173     *          <code>Component</code>; a <code>String</code>
1174     *          object is rendered as a string; other objects are
1175     *          converted to a <code>String</code> using the
1176     *          <code>toString</code> method
1177     * @param title     the title string for the dialog
1178     * @param optionType an integer designating the options
1179     *          available on the dialog:
1180     *          <code>YES_NO_OPTION</code>, or <code>YES_NO_CANCEL_OPTION</code>
1181     * @param messageType an integer designating the kind of message this is,
1182     *          primarily used to determine the icon from the
1183     *          pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
1184     *          <code>INFORMATION_MESSAGE</code>,
1185     *          <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
1186     *          or <code>PLAIN_MESSAGE</code>
1187     * @return an integer indicating the option selected by the user
1188     */
1189    public static int showInternalConfirmDialog(Component parentComponent,
1190                                        Object message,
1191                                        String title, int optionType,
1192                                        int messageType) {
1193        return showInternalConfirmDialog(parentComponent, message, title, optionType,
1194                                         messageType, null);
1195    }
1196
1197    /**
1198     * Brings up an internal dialog panel with a specified icon, where
1199     * the number of choices is determined by the <code>optionType</code>
1200     * parameter.
1201     * The <code>messageType</code> parameter is primarily used to supply
1202     * a default icon from the look and feel.
1203     *
1204     * @param parentComponent determines the <code>Frame</code>
1205     *          in which the dialog is displayed; if <code>null</code>,
1206     *          or if the parentComponent has no Frame, a
1207     *          default <code>Frame</code> is used
1208     * @param message   the object to display in the dialog; a
1209     *          <code>Component</code> object is rendered as a
1210     *          <code>Component</code>; a <code>String</code>
1211     *          object is rendered as a string; other objects are
1212     *          converted to a <code>String</code> using the
1213     *          <code>toString</code> method
1214     * @param title     the title string for the dialog
1215     * @param optionType an integer designating the options available
1216     *          on the dialog:
1217     *          <code>YES_NO_OPTION</code>, or
1218     *          <code>YES_NO_CANCEL_OPTION</code>.
1219     * @param messageType an integer designating the kind of message this is,
1220     *          primarily used to determine the icon from the pluggable
1221     *          Look and Feel: <code>ERROR_MESSAGE</code>,
1222     *          <code>INFORMATION_MESSAGE</code>,
1223     *          <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
1224     *          or <code>PLAIN_MESSAGE</code>
1225     * @param icon      the icon to display in the dialog
1226     * @return an integer indicating the option selected by the user
1227     */
1228    public static int showInternalConfirmDialog(Component parentComponent,
1229                                        Object message,
1230                                        String title, int optionType,
1231                                        int messageType, Icon icon) {
1232        return showInternalOptionDialog(parentComponent, message, title, optionType,
1233                                        messageType, icon, null, null);
1234    }
1235
1236    private static boolean checkFrameForComponent(Component parentComponent) {
1237        if (parentComponent == null) {
1238            return false;
1239        }
1240        if (parentComponent instanceof Frame) {
1241            return true;
1242        }
1243        return checkFrameForComponent(parentComponent.getParent());
1244    }
1245
1246    /**
1247     * Brings up an internal dialog panel with a specified icon, where
1248     * the initial choice is determined by the <code>initialValue</code>
1249     * parameter and the number of choices is determined by the
1250     * <code>optionType</code> parameter.
1251     * <p>
1252     * If <code>optionType</code> is <code>YES_NO_OPTION</code>, or
1253     * <code>YES_NO_CANCEL_OPTION</code>
1254     * and the <code>options</code> parameter is <code>null</code>,
1255     * then the options are supplied by the Look and Feel.
1256     * <p>
1257     * The <code>messageType</code> parameter is primarily used to supply
1258     * a default icon from the look and feel.
1259     *
1260     * @param parentComponent determines the <code>Frame</code>
1261     *          in which the dialog is displayed; if <code>null</code>,
1262     *          or if the <code>parentComponent</code> has no
1263     *          <code>Frame</code>, a default <code>Frame</code> is used
1264     * @param message   the object to display in the dialog; a
1265     *          <code>Component</code> object is rendered as a
1266     *          <code>Component</code>; a <code>String</code>
1267     *          object is rendered as a string. Other objects are
1268     *          converted to a <code>String</code> using the
1269     *          <code>toString</code> method
1270     * @param title     the title string for the dialog
1271     * @param optionType an integer designating the options available
1272     *          on the dialog: <code>YES_NO_OPTION</code>,
1273     *          or <code>YES_NO_CANCEL_OPTION</code>
1274     * @param messageType an integer designating the kind of message this is;
1275     *          primarily used to determine the icon from the
1276     *          pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
1277     *          <code>INFORMATION_MESSAGE</code>,
1278     *          <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
1279     *          or <code>PLAIN_MESSAGE</code>
1280     * @param icon      the icon to display in the dialog
1281     * @param options   an array of objects indicating the possible choices
1282     *          the user can make; if the objects are components, they
1283     *          are rendered properly; non-<code>String</code>
1284     *          objects are rendered using their <code>toString</code>
1285     *          methods; if this parameter is <code>null</code>,
1286     *          the options are determined by the Look and Feel
1287     * @param initialValue the object that represents the default selection
1288     *          for the dialog; only meaningful if <code>options</code>
1289     *          is used; can be <code>null</code>
1290     * @return an integer indicating the option chosen by the user,
1291     *          or <code>CLOSED_OPTION</code> if the user closed the Dialog
1292     */
1293    public static int showInternalOptionDialog(Component parentComponent,
1294                                       Object message,
1295                                       String title, int optionType,
1296                                       int messageType, Icon icon,
1297                                       Object[] options, Object initialValue) {
1298        JOptionPane pane = new JOptionPane(message, messageType,
1299                optionType, icon, options, initialValue);
1300        pane.putClientProperty(PopupFactory_FORCE_HEAVYWEIGHT_POPUP,
1301                Boolean.TRUE);
1302        Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().
1303                getFocusOwner();
1304
1305        pane.setInitialValue(initialValue);
1306        if (checkFrameForComponent(parentComponent)) {
1307            JInternalFrame dialog =
1308                    pane.createInternalFrame(parentComponent, title);
1309            pane.selectInitialValue();
1310            dialog.setVisible(true);
1311
1312            /* Since all input will be blocked until this dialog is dismissed,
1313             * make sure its parent containers are visible first (this component
1314             * is tested below).  This is necessary for JApplets, because
1315             * because an applet normally isn't made visible until after its
1316             * start() method returns -- if this method is called from start(),
1317             * the applet will appear to hang while an invisible modal frame
1318             * waits for input.
1319             */
1320            if (dialog.isVisible() && !dialog.isShowing()) {
1321                Container parent = dialog.getParent();
1322                while (parent != null) {
1323                    if (parent.isVisible() == false) {
1324                        parent.setVisible(true);
1325                    }
1326                    parent = parent.getParent();
1327                }
1328            }
1329
1330            AWTAccessor.getContainerAccessor().startLWModal(dialog);
1331        } else {
1332            pane.setComponentOrientation(getRootFrame().getComponentOrientation());
1333            int style = styleFromMessageType(messageType);
1334            JDialog dialog = pane.createDialog(parentComponent, title, style);
1335            pane.selectInitialValue();
1336            dialog.setVisible(true);
1337        }
1338
1339        if (parentComponent instanceof JInternalFrame) {
1340            try {
1341                ((JInternalFrame)parentComponent).setSelected(true);
1342            } catch (java.beans.PropertyVetoException e) {
1343            }
1344        }
1345
1346        Object selectedValue = pane.getValue();
1347
1348        if (fo != null && fo.isShowing()) {
1349            fo.requestFocus();
1350        }
1351        if (selectedValue == null) {
1352            return CLOSED_OPTION;
1353        }
1354        if (options == null) {
1355            if (selectedValue instanceof Integer) {
1356                return ((Integer)selectedValue).intValue();
1357            }
1358            return CLOSED_OPTION;
1359        }
1360        for(int counter = 0, maxCounter = options.length;
1361            counter < maxCounter; counter++) {
1362            if (options[counter].equals(selectedValue)) {
1363                return counter;
1364            }
1365        }
1366        return CLOSED_OPTION;
1367    }
1368
1369    /**
1370     * Shows an internal question-message dialog requesting input from
1371     * the user parented to <code>parentComponent</code>. The dialog
1372     * is displayed in the <code>Component</code>'s frame,
1373     * and is usually positioned below the <code>Component</code>.
1374     *
1375     * @param parentComponent  the parent <code>Component</code>
1376     *          for the dialog
1377     * @param message  the <code>Object</code> to display
1378     * @return user's input
1379     */
1380    public static String showInternalInputDialog(Component parentComponent,
1381                                                 Object message) {
1382        return showInternalInputDialog(parentComponent, message, UIManager.
1383               getString("OptionPane.inputDialogTitle", parentComponent),
1384               QUESTION_MESSAGE);
1385    }
1386
1387    /**
1388     * Shows an internal dialog requesting input from the user parented
1389     * to <code>parentComponent</code> with the dialog having the title
1390     * <code>title</code> and message type <code>messageType</code>.
1391     *
1392     * @param parentComponent the parent <code>Component</code> for the dialog
1393     * @param message  the <code>Object</code> to display
1394     * @param title    the <code>String</code> to display in the
1395     *          dialog title bar
1396     * @param messageType the type of message that is to be displayed:
1397     *                    ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE,
1398     *                    QUESTION_MESSAGE, or PLAIN_MESSAGE
1399     * @return user's input
1400     */
1401    public static String showInternalInputDialog(Component parentComponent,
1402                             Object message, String title, int messageType) {
1403        return (String)showInternalInputDialog(parentComponent, message, title,
1404                                       messageType, null, null, null);
1405    }
1406
1407    /**
1408     * Prompts the user for input in a blocking internal dialog where
1409     * the initial selection, possible selections, and all other
1410     * options can be specified. The user will able to choose from
1411     * <code>selectionValues</code>, where <code>null</code>
1412     * implies the user can input
1413     * whatever they wish, usually by means of a <code>JTextField</code>.
1414     * <code>initialSelectionValue</code> is the initial value to prompt
1415     * the user with. It is up to the UI to decide how best to represent
1416     * the <code>selectionValues</code>, but usually a
1417     * <code>JComboBox</code>, <code>JList</code>, or
1418     * <code>JTextField</code> will be used.
1419     *
1420     * @param parentComponent the parent <code>Component</code> for the dialog
1421     * @param message  the <code>Object</code> to display
1422     * @param title    the <code>String</code> to display in the dialog
1423     *          title bar
1424     * @param messageType the type of message to be displayed:
1425     *                  <code>ERROR_MESSAGE</code>, <code>INFORMATION_MESSAGE</code>,
1426     *                  <code>WARNING_MESSAGE</code>,
1427     *                  <code>QUESTION_MESSAGE</code>, or <code>PLAIN_MESSAGE</code>
1428     * @param icon     the <code>Icon</code> image to display
1429     * @param selectionValues an array of <code>Objects</code> that
1430     *                  gives the possible selections
1431     * @param initialSelectionValue the value used to initialize the input
1432     *                  field
1433     * @return user's input, or <code>null</code> meaning the user
1434     *          canceled the input
1435     */
1436    public static Object showInternalInputDialog(Component parentComponent,
1437            Object message, String title, int messageType, Icon icon,
1438            Object[] selectionValues, Object initialSelectionValue) {
1439        JOptionPane pane = new JOptionPane(message, messageType,
1440                OK_CANCEL_OPTION, icon, null, null);
1441        pane.putClientProperty(PopupFactory_FORCE_HEAVYWEIGHT_POPUP,
1442                Boolean.TRUE);
1443        Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().
1444                getFocusOwner();
1445
1446        pane.setWantsInput(true);
1447        pane.setSelectionValues(selectionValues);
1448        pane.setInitialSelectionValue(initialSelectionValue);
1449
1450        JInternalFrame dialog =
1451            pane.createInternalFrame(parentComponent, title);
1452
1453        pane.selectInitialValue();
1454        dialog.setVisible(true);
1455
1456        /* Since all input will be blocked until this dialog is dismissed,
1457         * make sure its parent containers are visible first (this component
1458         * is tested below).  This is necessary for JApplets, because
1459         * because an applet normally isn't made visible until after its
1460         * start() method returns -- if this method is called from start(),
1461         * the applet will appear to hang while an invisible modal frame
1462         * waits for input.
1463         */
1464        if (dialog.isVisible() && !dialog.isShowing()) {
1465            Container parent = dialog.getParent();
1466            while (parent != null) {
1467                if (parent.isVisible() == false) {
1468                    parent.setVisible(true);
1469                }
1470                parent = parent.getParent();
1471            }
1472        }
1473
1474        AWTAccessor.getContainerAccessor().startLWModal(dialog);
1475
1476        if (parentComponent instanceof JInternalFrame) {
1477            try {
1478                ((JInternalFrame)parentComponent).setSelected(true);
1479            } catch (java.beans.PropertyVetoException e) {
1480            }
1481        }
1482
1483        if (fo != null && fo.isShowing()) {
1484            fo.requestFocus();
1485        }
1486        Object value = pane.getInputValue();
1487
1488        if (value == UNINITIALIZED_VALUE) {
1489            return null;
1490        }
1491        return value;
1492    }
1493
1494    /**
1495     * Creates and returns an instance of <code>JInternalFrame</code>.
1496     * The internal frame is created with the specified title,
1497     * and wrapping the <code>JOptionPane</code>.
1498     * The returned <code>JInternalFrame</code> is
1499     * added to the <code>JDesktopPane</code> ancestor of
1500     * <code>parentComponent</code>, or components
1501     * parent if one its ancestors isn't a <code>JDesktopPane</code>,
1502     * or if <code>parentComponent</code>
1503     * doesn't have a parent then a <code>RuntimeException</code> is thrown.
1504     *
1505     * @param parentComponent  the parent <code>Component</code> for
1506     *          the internal frame
1507     * @param title    the <code>String</code> to display in the
1508     *          frame's title bar
1509     * @return a <code>JInternalFrame</code> containing a
1510     *          <code>JOptionPane</code>
1511     * @exception RuntimeException if <code>parentComponent</code> does
1512     *          not have a valid parent
1513     */
1514    public JInternalFrame createInternalFrame(Component parentComponent,
1515                                 String title) {
1516        Container parent =
1517                JOptionPane.getDesktopPaneForComponent(parentComponent);
1518
1519        if (parent == null && (parentComponent == null ||
1520                (parent = parentComponent.getParent()) == null)) {
1521            throw new RuntimeException("JOptionPane: parentComponent does " +
1522                    "not have a valid parent");
1523        }
1524
1525        // Option dialogs should be closable only
1526        final JInternalFrame  iFrame = new JInternalFrame(title, false, true,
1527                                                           false, false);
1528
1529        iFrame.putClientProperty("JInternalFrame.frameType", "optionDialog");
1530        iFrame.putClientProperty("JInternalFrame.messageType",
1531                                 Integer.valueOf(getMessageType()));
1532
1533        iFrame.addInternalFrameListener(new InternalFrameAdapter() {
1534            public void internalFrameClosing(InternalFrameEvent e) {
1535                if (getValue() == UNINITIALIZED_VALUE) {
1536                    setValue(null);
1537                }
1538            }
1539        });
1540        addPropertyChangeListener(new PropertyChangeListener() {
1541            public void propertyChange(PropertyChangeEvent event) {
1542                // Let the defaultCloseOperation handle the closing
1543                // if the user closed the iframe without selecting a button
1544                // (newValue = null in that case).  Otherwise, close the dialog.
1545                if (iFrame.isVisible() &&
1546                        event.getSource() == JOptionPane.this &&
1547                        event.getPropertyName().equals(VALUE_PROPERTY)) {
1548                    AWTAccessor.getContainerAccessor().stopLWModal(iFrame);
1549
1550                try {
1551                    iFrame.setClosed(true);
1552                }
1553                catch (java.beans.PropertyVetoException e) {
1554                }
1555
1556                iFrame.setVisible(false);
1557                }
1558            }
1559        });
1560        iFrame.getContentPane().add(this, BorderLayout.CENTER);
1561        if (parent instanceof JDesktopPane) {
1562            parent.add(iFrame, JLayeredPane.MODAL_LAYER);
1563        } else {
1564            parent.add(iFrame, BorderLayout.CENTER);
1565        }
1566        Dimension iFrameSize = iFrame.getPreferredSize();
1567        Dimension rootSize = parent.getSize();
1568        Dimension parentSize = parentComponent.getSize();
1569
1570        iFrame.setBounds((rootSize.width - iFrameSize.width) / 2,
1571                         (rootSize.height - iFrameSize.height) / 2,
1572                         iFrameSize.width, iFrameSize.height);
1573        // We want dialog centered relative to its parent component
1574        Point iFrameCoord =
1575          SwingUtilities.convertPoint(parentComponent, 0, 0, parent);
1576        int x = (parentSize.width - iFrameSize.width) / 2 + iFrameCoord.x;
1577        int y = (parentSize.height - iFrameSize.height) / 2 + iFrameCoord.y;
1578
1579        // If possible, dialog should be fully visible
1580        int ovrx = x + iFrameSize.width - rootSize.width;
1581        int ovry = y + iFrameSize.height - rootSize.height;
1582        x = Math.max((ovrx > 0? x - ovrx: x), 0);
1583        y = Math.max((ovry > 0? y - ovry: y), 0);
1584        iFrame.setBounds(x, y, iFrameSize.width, iFrameSize.height);
1585
1586        parent.validate();
1587        try {
1588            iFrame.setSelected(true);
1589        } catch (java.beans.PropertyVetoException e) {}
1590
1591        return iFrame;
1592    }
1593
1594    /**
1595     * Returns the specified component's <code>Frame</code>.
1596     *
1597     * @param parentComponent the <code>Component</code> to check for a
1598     *          <code>Frame</code>
1599     * @return the <code>Frame</code> that contains the component,
1600     *          or <code>getRootFrame</code>
1601     *          if the component is <code>null</code>,
1602     *          or does not have a valid <code>Frame</code> parent
1603     * @exception HeadlessException if
1604     *   <code>GraphicsEnvironment.isHeadless</code> returns
1605     *   <code>true</code>
1606     * @see #getRootFrame
1607     * @see java.awt.GraphicsEnvironment#isHeadless
1608     */
1609    public static Frame getFrameForComponent(Component parentComponent)
1610        throws HeadlessException {
1611        if (parentComponent == null)
1612            return getRootFrame();
1613        if (parentComponent instanceof Frame)
1614            return (Frame)parentComponent;
1615        return JOptionPane.getFrameForComponent(parentComponent.getParent());
1616    }
1617
1618    /**
1619     * Returns the specified component's toplevel <code>Frame</code> or
1620     * <code>Dialog</code>.
1621     *
1622     * @param parentComponent the <code>Component</code> to check for a
1623     *          <code>Frame</code> or <code>Dialog</code>
1624     * @return the <code>Frame</code> or <code>Dialog</code> that
1625     *          contains the component, or the default
1626     *          frame if the component is <code>null</code>,
1627     *          or does not have a valid
1628     *          <code>Frame</code> or <code>Dialog</code> parent
1629     * @exception HeadlessException if
1630     *   <code>GraphicsEnvironment.isHeadless</code> returns
1631     *   <code>true</code>
1632     * @see java.awt.GraphicsEnvironment#isHeadless
1633     */
1634    static Window getWindowForComponent(Component parentComponent)
1635        throws HeadlessException {
1636        if (parentComponent == null)
1637            return getRootFrame();
1638        if (parentComponent instanceof Frame || parentComponent instanceof Dialog)
1639            return (Window)parentComponent;
1640        return JOptionPane.getWindowForComponent(parentComponent.getParent());
1641    }
1642
1643
1644    /**
1645     * Returns the specified component's desktop pane.
1646     *
1647     * @param parentComponent the <code>Component</code> to check for a
1648     *          desktop
1649     * @return the <code>JDesktopPane</code> that contains the component,
1650     *          or <code>null</code> if the component is <code>null</code>
1651     *          or does not have an ancestor that is a
1652     *          <code>JInternalFrame</code>
1653     */
1654    public static JDesktopPane getDesktopPaneForComponent(Component parentComponent) {
1655        if(parentComponent == null)
1656            return null;
1657        if(parentComponent instanceof JDesktopPane)
1658            return (JDesktopPane)parentComponent;
1659        return getDesktopPaneForComponent(parentComponent.getParent());
1660    }
1661
1662    private static final Object sharedFrameKey = JOptionPane.class;
1663
1664    /**
1665     * Sets the frame to use for class methods in which a frame is
1666     * not provided.
1667     * <p>
1668     * <strong>Note:</strong>
1669     * It is recommended that rather than using this method you supply a valid parent.
1670     *
1671     * @param newRootFrame the default <code>Frame</code> to use
1672     */
1673    public static void setRootFrame(Frame newRootFrame) {
1674        if (newRootFrame != null) {
1675            SwingUtilities.appContextPut(sharedFrameKey, newRootFrame);
1676        } else {
1677            SwingUtilities.appContextRemove(sharedFrameKey);
1678        }
1679    }
1680
1681    /**
1682     * Returns the <code>Frame</code> to use for the class methods in
1683     * which a frame is not provided.
1684     *
1685     * @return the default <code>Frame</code> to use
1686     * @exception HeadlessException if
1687     *   <code>GraphicsEnvironment.isHeadless</code> returns
1688     *   <code>true</code>
1689     * @see #setRootFrame
1690     * @see java.awt.GraphicsEnvironment#isHeadless
1691     */
1692    public static Frame getRootFrame() throws HeadlessException {
1693        Frame sharedFrame =
1694            (Frame)SwingUtilities.appContextGet(sharedFrameKey);
1695        if (sharedFrame == null) {
1696            sharedFrame = SwingUtilities.getSharedOwnerFrame();
1697            SwingUtilities.appContextPut(sharedFrameKey, sharedFrame);
1698        }
1699        return sharedFrame;
1700    }
1701
1702    /**
1703     * Creates a <code>JOptionPane</code> with a test message.
1704     */
1705    public JOptionPane() {
1706        this("JOptionPane message");
1707    }
1708
1709    /**
1710     * Creates a instance of <code>JOptionPane</code> to display a
1711     * message using the
1712     * plain-message message type and the default options delivered by
1713     * the UI.
1714     *
1715     * @param message the <code>Object</code> to display
1716     */
1717    public JOptionPane(Object message) {
1718        this(message, PLAIN_MESSAGE);
1719    }
1720
1721    /**
1722     * Creates an instance of <code>JOptionPane</code> to display a message
1723     * with the specified message type and the default options,
1724     *
1725     * @param message the <code>Object</code> to display
1726     * @param messageType the type of message to be displayed:
1727     *                  <code>ERROR_MESSAGE</code>,
1728     *                  <code>INFORMATION_MESSAGE</code>,
1729     *                  <code>WARNING_MESSAGE</code>,
1730     *                  <code>QUESTION_MESSAGE</code>,
1731     *                  or <code>PLAIN_MESSAGE</code>
1732     */
1733    public JOptionPane(Object message, int messageType) {
1734        this(message, messageType, DEFAULT_OPTION);
1735    }
1736
1737    /**
1738     * Creates an instance of <code>JOptionPane</code> to display a message
1739     * with the specified message type and options.
1740     *
1741     * @param message the <code>Object</code> to display
1742     * @param messageType the type of message to be displayed:
1743     *                  <code>ERROR_MESSAGE</code>,
1744     *                  <code>INFORMATION_MESSAGE</code>,
1745     *                  <code>WARNING_MESSAGE</code>,
1746     *                  <code>QUESTION_MESSAGE</code>,
1747     *                  or <code>PLAIN_MESSAGE</code>
1748     * @param optionType the options to display in the pane:
1749     *                  <code>DEFAULT_OPTION</code>, <code>YES_NO_OPTION</code>,
1750     *                  <code>YES_NO_CANCEL_OPTION</code>,
1751     *                  <code>OK_CANCEL_OPTION</code>
1752     */
1753    public JOptionPane(Object message, int messageType, int optionType) {
1754        this(message, messageType, optionType, null);
1755    }
1756
1757    /**
1758     * Creates an instance of <code>JOptionPane</code> to display a message
1759     * with the specified message type, options, and icon.
1760     *
1761     * @param message the <code>Object</code> to display
1762     * @param messageType the type of message to be displayed:
1763     *                  <code>ERROR_MESSAGE</code>,
1764     *                  <code>INFORMATION_MESSAGE</code>,
1765     *                  <code>WARNING_MESSAGE</code>,
1766     *                  <code>QUESTION_MESSAGE</code>,
1767     *                  or <code>PLAIN_MESSAGE</code>
1768     * @param optionType the options to display in the pane:
1769     *                  <code>DEFAULT_OPTION</code>, <code>YES_NO_OPTION</code>,
1770     *                  <code>YES_NO_CANCEL_OPTION</code>,
1771     *                  <code>OK_CANCEL_OPTION</code>
1772     * @param icon the <code>Icon</code> image to display
1773     */
1774    public JOptionPane(Object message, int messageType, int optionType,
1775                       Icon icon) {
1776        this(message, messageType, optionType, icon, null);
1777    }
1778
1779    /**
1780     * Creates an instance of <code>JOptionPane</code> to display a message
1781     * with the specified message type, icon, and options.
1782     * None of the options is initially selected.
1783     * <p>
1784     * The options objects should contain either instances of
1785     * <code>Component</code>s, (which are added directly) or
1786     * <code>Strings</code> (which are wrapped in a <code>JButton</code>).
1787     * If you provide <code>Component</code>s, you must ensure that when the
1788     * <code>Component</code> is clicked it messages <code>setValue</code>
1789     * in the created <code>JOptionPane</code>.
1790     *
1791     * @param message the <code>Object</code> to display
1792     * @param messageType the type of message to be displayed:
1793     *                  <code>ERROR_MESSAGE</code>,
1794     *                  <code>INFORMATION_MESSAGE</code>,
1795     *                  <code>WARNING_MESSAGE</code>,
1796     *                  <code>QUESTION_MESSAGE</code>,
1797     *                  or <code>PLAIN_MESSAGE</code>
1798     * @param optionType the options to display in the pane:
1799     *                  <code>DEFAULT_OPTION</code>,
1800     *                  <code>YES_NO_OPTION</code>,
1801     *                  <code>YES_NO_CANCEL_OPTION</code>,
1802     *                  <code>OK_CANCEL_OPTION</code>
1803     * @param icon the <code>Icon</code> image to display
1804     * @param options  the choices the user can select
1805     */
1806    public JOptionPane(Object message, int messageType, int optionType,
1807                       Icon icon, Object[] options) {
1808        this(message, messageType, optionType, icon, options, null);
1809    }
1810
1811    /**
1812     * Creates an instance of <code>JOptionPane</code> to display a message
1813     * with the specified message type, icon, and options, with the
1814     * initially-selected option specified.
1815     *
1816     * @param message the <code>Object</code> to display
1817     * @param messageType the type of message to be displayed:
1818     *                  <code>ERROR_MESSAGE</code>,
1819     *                  <code>INFORMATION_MESSAGE</code>,
1820     *                  <code>WARNING_MESSAGE</code>,
1821     *                  <code>QUESTION_MESSAGE</code>,
1822     *                  or <code>PLAIN_MESSAGE</code>
1823     * @param optionType the options to display in the pane:
1824     *                  <code>DEFAULT_OPTION</code>,
1825     *                  <code>YES_NO_OPTION</code>,
1826     *                  <code>YES_NO_CANCEL_OPTION</code>,
1827     *                  <code>OK_CANCEL_OPTION</code>
1828     * @param icon the Icon image to display
1829     * @param options  the choices the user can select
1830     * @param initialValue the choice that is initially selected; if
1831     *                  <code>null</code>, then nothing will be initially selected;
1832     *                  only meaningful if <code>options</code> is used
1833     */
1834    public JOptionPane(Object message, int messageType, int optionType,
1835                       Icon icon, Object[] options, Object initialValue) {
1836
1837        this.message = message;
1838        this.options = options == null ? null : Arrays.copyOf(options, options.length);
1839        this.initialValue = initialValue;
1840        this.icon = icon;
1841        setMessageType(messageType);
1842        setOptionType(optionType);
1843        value = UNINITIALIZED_VALUE;
1844        inputValue = UNINITIALIZED_VALUE;
1845        updateUI();
1846    }
1847
1848    /**
1849     * Sets the UI object which implements the {@literal L&F} for this component.
1850     *
1851     * @param ui  the <code>OptionPaneUI</code> {@literal L&F} object
1852     * @see UIDefaults#getUI
1853     */
1854    @BeanProperty(hidden = true, description
1855            = "The UI object that implements the optionpane's LookAndFeel")
1856    public void setUI(OptionPaneUI ui) {
1857        if (this.ui != ui) {
1858            super.setUI(ui);
1859            invalidate();
1860        }
1861    }
1862
1863    /**
1864     * Returns the UI object which implements the {@literal L&F} for this component.
1865     *
1866     * @return the <code>OptionPaneUI</code> object
1867     */
1868    public OptionPaneUI getUI() {
1869        return (OptionPaneUI)ui;
1870    }
1871
1872    /**
1873     * Notification from the <code>UIManager</code> that the {@literal L&F} has changed.
1874     * Replaces the current UI object with the latest version from the
1875     * <code>UIManager</code>.
1876     *
1877     * @see JComponent#updateUI
1878     */
1879    public void updateUI() {
1880        setUI((OptionPaneUI)UIManager.getUI(this));
1881    }
1882
1883
1884    /**
1885     * Returns the name of the UI class that implements the
1886     * {@literal L&F} for this component.
1887     *
1888     * @return the string "OptionPaneUI"
1889     * @see JComponent#getUIClassID
1890     * @see UIDefaults#getUI
1891     */
1892    @BeanProperty(bound = false)
1893    public String getUIClassID() {
1894        return uiClassID;
1895    }
1896
1897
1898    /**
1899     * Sets the option pane's message-object.
1900     * @param newMessage the <code>Object</code> to display
1901     * @see #getMessage
1902     */
1903    @BeanProperty(preferred = true, description
1904            = "The optionpane's message object.")
1905    public void setMessage(Object newMessage) {
1906        Object           oldMessage = message;
1907
1908        message = newMessage;
1909        firePropertyChange(MESSAGE_PROPERTY, oldMessage, message);
1910    }
1911
1912    /**
1913     * Returns the message-object this pane displays.
1914     * @see #setMessage
1915     *
1916     * @return the <code>Object</code> that is displayed
1917     */
1918    public Object getMessage() {
1919        return message;
1920    }
1921
1922    /**
1923     * Sets the icon to display. If non-<code>null</code>, the look and feel
1924     * does not provide an icon.
1925     * @param newIcon the <code>Icon</code> to display
1926     *
1927     * @see #getIcon
1928     */
1929    @BeanProperty(preferred = true, description
1930            = "The option pane's type icon.")
1931    public void setIcon(Icon newIcon) {
1932        Object              oldIcon = icon;
1933
1934        icon = newIcon;
1935        firePropertyChange(ICON_PROPERTY, oldIcon, icon);
1936    }
1937
1938    /**
1939     * Returns the icon this pane displays.
1940     * @return the <code>Icon</code> that is displayed
1941     *
1942     * @see #setIcon
1943     */
1944    public Icon getIcon() {
1945        return icon;
1946    }
1947
1948    /**
1949     * Sets the value the user has chosen.
1950     * @param newValue  the chosen value
1951     *
1952     * @see #getValue
1953     */
1954    @BeanProperty(preferred = true, description
1955            = "The option pane's value object.")
1956    public void setValue(Object newValue) {
1957        Object               oldValue = value;
1958
1959        value = newValue;
1960        firePropertyChange(VALUE_PROPERTY, oldValue, value);
1961    }
1962
1963    /**
1964     * Returns the value the user has selected. <code>UNINITIALIZED_VALUE</code>
1965     * implies the user has not yet made a choice, <code>null</code> means the
1966     * user closed the window with out choosing anything. Otherwise
1967     * the returned value will be one of the options defined in this
1968     * object.
1969     *
1970     * @return the <code>Object</code> chosen by the user,
1971     *         <code>UNINITIALIZED_VALUE</code>
1972     *         if the user has not yet made a choice, or <code>null</code> if
1973     *         the user closed the window without making a choice
1974     *
1975     * @see #setValue
1976     */
1977    public Object getValue() {
1978        return value;
1979    }
1980
1981    /**
1982     * Sets the options this pane displays. If an element in
1983     * <code>newOptions</code> is a <code>Component</code>
1984     * it is added directly to the pane,
1985     * otherwise a button is created for the element.
1986     *
1987     * @param newOptions an array of <code>Objects</code> that create the
1988     *          buttons the user can click on, or arbitrary
1989     *          <code>Components</code> to add to the pane
1990     *
1991     * @see #getOptions
1992     */
1993    @BeanProperty(description
1994            = "The option pane's options objects.")
1995    public void setOptions(Object[] newOptions) {
1996        Object[]           oldOptions = options;
1997
1998        options = newOptions == null
1999                ? null
2000                : Arrays.copyOf(newOptions, newOptions.length);
2001        firePropertyChange(OPTIONS_PROPERTY, oldOptions, options);
2002    }
2003
2004    /**
2005     * Returns the choices the user can make.
2006     * @return the array of <code>Objects</code> that give the user's choices
2007     *
2008     * @see #setOptions
2009     */
2010    public Object[] getOptions() {
2011        return options == null ? null : Arrays.copyOf(options, options.length);
2012    }
2013
2014    /**
2015     * Sets the initial value that is to be enabled -- the
2016     * <code>Component</code>
2017     * that has the focus when the pane is initially displayed.
2018     *
2019     * @param newInitialValue the <code>Object</code> that gets the initial
2020     *                         keyboard focus
2021     *
2022     * @see #getInitialValue
2023     */
2024    @BeanProperty(preferred = true, description
2025            = "The option pane's initial value object.")
2026    public void setInitialValue(Object newInitialValue) {
2027        Object            oldIV = initialValue;
2028
2029        initialValue = newInitialValue;
2030        firePropertyChange(INITIAL_VALUE_PROPERTY, oldIV, initialValue);
2031    }
2032
2033    /**
2034     * Returns the initial value.
2035     *
2036     * @return the <code>Object</code> that gets the initial keyboard focus
2037     *
2038     * @see #setInitialValue
2039     */
2040    public Object getInitialValue() {
2041        return initialValue;
2042    }
2043
2044    /**
2045     * Sets the option pane's message type.
2046     * The message type is used by the Look and Feel to determine the
2047     * icon to display (if not supplied) as well as potentially how to
2048     * lay out the <code>parentComponent</code>.
2049     * @param newType an integer specifying the kind of message to display:
2050     *                <code>ERROR_MESSAGE</code>, <code>INFORMATION_MESSAGE</code>,
2051     *                <code>WARNING_MESSAGE</code>,
2052     *                <code>QUESTION_MESSAGE</code>, or <code>PLAIN_MESSAGE</code>
2053     * @exception RuntimeException if <code>newType</code> is not one of the
2054     *          legal values listed above
2055
2056     * @see #getMessageType
2057     */
2058    @BeanProperty(preferred = true, description
2059            = "The option pane's message type.")
2060    public void setMessageType(int newType) {
2061        checkMessageType(newType);
2062        int           oldType = messageType;
2063        messageType = newType;
2064        firePropertyChange(MESSAGE_TYPE_PROPERTY, oldType, messageType);
2065    }
2066
2067    private static void checkMessageType(int newType){
2068        if(newType != ERROR_MESSAGE && newType != INFORMATION_MESSAGE &&
2069           newType != WARNING_MESSAGE && newType != QUESTION_MESSAGE &&
2070           newType != PLAIN_MESSAGE)
2071            throw new RuntimeException("JOptionPane: type must be one of"
2072                    + " JOptionPane.ERROR_MESSAGE,"
2073                    + " JOptionPane.INFORMATION_MESSAGE,"
2074                    + " JOptionPane.WARNING_MESSAGE,"
2075                    + " JOptionPane.QUESTION_MESSAGE"
2076                    + " or JOptionPane.PLAIN_MESSAGE");
2077    }
2078
2079    /**
2080     * Returns the message type.
2081     *
2082     * @return an integer specifying the message type
2083     *
2084     * @see #setMessageType
2085     */
2086    public int getMessageType() {
2087        return messageType;
2088    }
2089
2090    /**
2091     * Sets the options to display.
2092     * The option type is used by the Look and Feel to
2093     * determine what buttons to show (unless options are supplied).
2094     * @param newType an integer specifying the options the {@literal L&F} is to display:
2095     *                  <code>DEFAULT_OPTION</code>,
2096     *                  <code>YES_NO_OPTION</code>,
2097     *                  <code>YES_NO_CANCEL_OPTION</code>,
2098     *                  or <code>OK_CANCEL_OPTION</code>
2099     * @exception RuntimeException if <code>newType</code> is not one of
2100     *          the legal values listed above
2101     *
2102     * @see #getOptionType
2103     * @see #setOptions
2104      */
2105    @BeanProperty(preferred = true, description
2106            = "The option pane's option type.")
2107    public void setOptionType(int newType) {
2108        checkOptionType(newType);
2109        int            oldType = optionType;
2110        optionType = newType;
2111        firePropertyChange(OPTION_TYPE_PROPERTY, oldType, optionType);
2112    }
2113
2114    private static void checkOptionType(int newType) {
2115        if (newType != DEFAULT_OPTION && newType != YES_NO_OPTION
2116                && newType != YES_NO_CANCEL_OPTION
2117                && newType != OK_CANCEL_OPTION) {
2118            throw new RuntimeException("JOptionPane: option type must be one of"
2119                    + " JOptionPane.DEFAULT_OPTION, JOptionPane.YES_NO_OPTION,"
2120                    + " JOptionPane.YES_NO_CANCEL_OPTION"
2121                    + " or JOptionPane.OK_CANCEL_OPTION");
2122        }
2123    }
2124
2125    /**
2126     * Returns the type of options that are displayed.
2127     *
2128     * @return an integer specifying the user-selectable options
2129     *
2130     * @see #setOptionType
2131     */
2132    public int getOptionType() {
2133        return optionType;
2134    }
2135
2136    /**
2137     * Sets the input selection values for a pane that provides the user
2138     * with a list of items to choose from. (The UI provides a widget
2139     * for choosing one of the values.)  A <code>null</code> value
2140     * implies the user can input whatever they wish, usually by means
2141     * of a <code>JTextField</code>.
2142     * <p>
2143     * Sets <code>wantsInput</code> to true. Use
2144     * <code>setInitialSelectionValue</code> to specify the initially-chosen
2145     * value. After the pane as been enabled, <code>inputValue</code> is
2146     * set to the value the user has selected.
2147     * @param newValues an array of <code>Objects</code> the user to be
2148     *                  displayed
2149     *                  (usually in a list or combo-box) from which
2150     *                  the user can make a selection
2151     * @see #setWantsInput
2152     * @see #setInitialSelectionValue
2153     * @see #getSelectionValues
2154     */
2155    @BeanProperty(description
2156            = "The option pane's selection values.")
2157    public void setSelectionValues(Object[] newValues) {
2158        Object[]           oldValues = selectionValues;
2159
2160        selectionValues = newValues == null
2161                ? null
2162                : Arrays.copyOf(newValues, newValues.length);
2163        firePropertyChange(SELECTION_VALUES_PROPERTY, oldValues, newValues);
2164        if(selectionValues != null)
2165            setWantsInput(true);
2166    }
2167
2168    /**
2169     * Returns the input selection values.
2170     *
2171     * @return the array of <code>Objects</code> the user can select
2172     * @see #setSelectionValues
2173     */
2174    public Object[] getSelectionValues() {
2175        return selectionValues == null
2176                ? null
2177                : Arrays.copyOf(selectionValues, selectionValues.length);
2178    }
2179
2180    /**
2181     * Sets the input value that is initially displayed as selected to the user.
2182     * Only used if <code>wantsInput</code> is true.
2183     * @param newValue the initially selected value
2184     * @see #setSelectionValues
2185     * @see #getInitialSelectionValue
2186     */
2187    @BeanProperty(description
2188            = "The option pane's initial selection value object.")
2189    public void setInitialSelectionValue(Object newValue) {
2190        Object          oldValue = initialSelectionValue;
2191
2192        initialSelectionValue = newValue;
2193        firePropertyChange(INITIAL_SELECTION_VALUE_PROPERTY, oldValue,
2194                           newValue);
2195    }
2196
2197    /**
2198     * Returns the input value that is displayed as initially selected to the user.
2199     *
2200     * @return the initially selected value
2201     * @see #setInitialSelectionValue
2202     * @see #setSelectionValues
2203     */
2204    public Object getInitialSelectionValue() {
2205        return initialSelectionValue;
2206    }
2207
2208    /**
2209     * Sets the input value that was selected or input by the user.
2210     * Only used if <code>wantsInput</code> is true.  Note that this method
2211     * is invoked internally by the option pane (in response to user action)
2212     * and should generally not be called by client programs.  To set the
2213     * input value initially displayed as selected to the user, use
2214     * <code>setInitialSelectionValue</code>.
2215     *
2216     * @param newValue the <code>Object</code> used to set the
2217     *          value that the user specified (usually in a text field)
2218     * @see #setSelectionValues
2219     * @see #setInitialSelectionValue
2220     * @see #setWantsInput
2221     * @see #getInputValue
2222     */
2223    @BeanProperty(preferred = true, description
2224            = "The option pane's input value object.")
2225    public void setInputValue(Object newValue) {
2226        Object              oldValue = inputValue;
2227
2228        inputValue = newValue;
2229        firePropertyChange(INPUT_VALUE_PROPERTY, oldValue, newValue);
2230    }
2231
2232    /**
2233     * Returns the value the user has input, if <code>wantsInput</code>
2234     * is true.
2235     *
2236     * @return the <code>Object</code> the user specified,
2237     *          if it was one of the objects, or a
2238     *          <code>String</code> if it was a value typed into a
2239     *          field
2240     * @see #setSelectionValues
2241     * @see #setWantsInput
2242     * @see #setInputValue
2243     */
2244    public Object getInputValue() {
2245        return inputValue;
2246    }
2247
2248    /**
2249     * Returns the maximum number of characters to place on a line in a
2250     * message. Default is to return <code>Integer.MAX_VALUE</code>.
2251     * The value can be
2252     * changed by overriding this method in a subclass.
2253     *
2254     * @return an integer giving the maximum number of characters on a line
2255     */
2256    @BeanProperty(bound = false)
2257    public int getMaxCharactersPerLineCount() {
2258        return Integer.MAX_VALUE;
2259    }
2260
2261    /**
2262     * Sets the <code>wantsInput</code> property.
2263     * If <code>newValue</code> is true, an input component
2264     * (such as a text field or combo box) whose parent is
2265     * <code>parentComponent</code> is provided to
2266     * allow the user to input a value. If <code>getSelectionValues</code>
2267     * returns a non-<code>null</code> array, the input value is one of the
2268     * objects in that array. Otherwise the input value is whatever
2269     * the user inputs.
2270     * <p>
2271     * This is a bound property.
2272     *
2273     * @param newValue if true, an input component whose parent is {@code parentComponent}
2274     *                 is provided to allow the user to input a value.
2275     * @see #setSelectionValues
2276     * @see #setInputValue
2277     */
2278    @BeanProperty(preferred = true, description
2279            = "Flag which allows the user to input a value.")
2280    public void setWantsInput(boolean newValue) {
2281        boolean            oldValue = wantsInput;
2282
2283        wantsInput = newValue;
2284        firePropertyChange(WANTS_INPUT_PROPERTY, oldValue, newValue);
2285    }
2286
2287    /**
2288     * Returns the value of the <code>wantsInput</code> property.
2289     *
2290     * @return true if an input component will be provided
2291     * @see #setWantsInput
2292     */
2293    public boolean getWantsInput() {
2294        return wantsInput;
2295    }
2296
2297    /**
2298     * Requests that the initial value be selected, which will set
2299     * focus to the initial value. This method
2300     * should be invoked after the window containing the option pane
2301     * is made visible.
2302     */
2303    public void selectInitialValue() {
2304        OptionPaneUI         ui = getUI();
2305        if (ui != null) {
2306            ui.selectInitialValue(this);
2307        }
2308    }
2309
2310
2311    private static int styleFromMessageType(int messageType) {
2312        switch (messageType) {
2313        case ERROR_MESSAGE:
2314            return JRootPane.ERROR_DIALOG;
2315        case QUESTION_MESSAGE:
2316            return JRootPane.QUESTION_DIALOG;
2317        case WARNING_MESSAGE:
2318            return JRootPane.WARNING_DIALOG;
2319        case INFORMATION_MESSAGE:
2320            return JRootPane.INFORMATION_DIALOG;
2321        case PLAIN_MESSAGE:
2322        default:
2323            return JRootPane.PLAIN_DIALOG;
2324        }
2325    }
2326
2327    // Serialization support.
2328    private void writeObject(ObjectOutputStream s) throws IOException {
2329        Vector<Object> values = new Vector<Object>();
2330
2331        s.defaultWriteObject();
2332        // Save the icon, if its Serializable.
2333        if(icon != null && icon instanceof Serializable) {
2334            values.addElement("icon");
2335            values.addElement(icon);
2336        }
2337        // Save the message, if its Serializable.
2338        if(message != null && message instanceof Serializable) {
2339            values.addElement("message");
2340            values.addElement(message);
2341        }
2342        // Save the treeModel, if its Serializable.
2343        if(options != null) {
2344            Vector<Object> serOptions = new Vector<Object>();
2345
2346            for(int counter = 0, maxCounter = options.length;
2347                counter < maxCounter; counter++)
2348                if(options[counter] instanceof Serializable)
2349                    serOptions.addElement(options[counter]);
2350            if(serOptions.size() > 0) {
2351                int             optionCount = serOptions.size();
2352                Object[]        arrayOptions = new Object[optionCount];
2353
2354                serOptions.copyInto(arrayOptions);
2355                values.addElement("options");
2356                values.addElement(arrayOptions);
2357            }
2358        }
2359        // Save the initialValue, if its Serializable.
2360        if(initialValue != null && initialValue instanceof Serializable) {
2361            values.addElement("initialValue");
2362            values.addElement(initialValue);
2363        }
2364        // Save the value, if its Serializable.
2365        if(value != null && value instanceof Serializable) {
2366            values.addElement("value");
2367            values.addElement(value);
2368        }
2369        // Save the selectionValues, if its Serializable.
2370        if(selectionValues != null) {
2371            boolean            serialize = true;
2372
2373            for(int counter = 0, maxCounter = selectionValues.length;
2374                counter < maxCounter; counter++) {
2375                if(selectionValues[counter] != null &&
2376                   !(selectionValues[counter] instanceof Serializable)) {
2377                    serialize = false;
2378                    break;
2379                }
2380            }
2381            if(serialize) {
2382                values.addElement("selectionValues");
2383                values.addElement(selectionValues);
2384            }
2385        }
2386        // Save the inputValue, if its Serializable.
2387        if(inputValue != null && inputValue instanceof Serializable) {
2388            values.addElement("inputValue");
2389            values.addElement(inputValue);
2390        }
2391        // Save the initialSelectionValue, if its Serializable.
2392        if(initialSelectionValue != null &&
2393           initialSelectionValue instanceof Serializable) {
2394            values.addElement("initialSelectionValue");
2395            values.addElement(initialSelectionValue);
2396        }
2397        s.writeObject(values);
2398    }
2399
2400    private void readObject(ObjectInputStream s)
2401        throws IOException, ClassNotFoundException {
2402        ObjectInputStream.GetField f = s.readFields();
2403
2404        int newMessageType = f.get("messageType", 0);
2405        checkMessageType(newMessageType);
2406        messageType = newMessageType;
2407        int newOptionType = f.get("optionType", 0);
2408        checkOptionType(newOptionType);
2409        optionType = newOptionType;
2410        wantsInput = f.get("wantsInput", false);
2411
2412        Vector<?>       values = (Vector)s.readObject();
2413        int             indexCounter = 0;
2414        int             maxCounter = values.size();
2415
2416        if(indexCounter < maxCounter && values.elementAt(indexCounter).
2417           equals("icon")) {
2418            icon = (Icon)values.elementAt(++indexCounter);
2419            indexCounter++;
2420        }
2421        if(indexCounter < maxCounter && values.elementAt(indexCounter).
2422           equals("message")) {
2423            message = values.elementAt(++indexCounter);
2424            indexCounter++;
2425        }
2426        if(indexCounter < maxCounter && values.elementAt(indexCounter).
2427           equals("options")) {
2428            options = (Object[])values.elementAt(++indexCounter);
2429            indexCounter++;
2430        }
2431        if(indexCounter < maxCounter && values.elementAt(indexCounter).
2432           equals("initialValue")) {
2433            initialValue = values.elementAt(++indexCounter);
2434            indexCounter++;
2435        }
2436        if(indexCounter < maxCounter && values.elementAt(indexCounter).
2437           equals("value")) {
2438            value = values.elementAt(++indexCounter);
2439            indexCounter++;
2440        }
2441        if(indexCounter < maxCounter && values.elementAt(indexCounter).
2442           equals("selectionValues")) {
2443            selectionValues = (Object[])values.elementAt(++indexCounter);
2444            indexCounter++;
2445        }
2446        if(indexCounter < maxCounter && values.elementAt(indexCounter).
2447           equals("inputValue")) {
2448            inputValue = values.elementAt(++indexCounter);
2449            indexCounter++;
2450        }
2451        if(indexCounter < maxCounter && values.elementAt(indexCounter).
2452           equals("initialSelectionValue")) {
2453            initialSelectionValue = values.elementAt(++indexCounter);
2454            indexCounter++;
2455        }
2456        if (getUIClassID().equals(uiClassID)) {
2457            byte count = JComponent.getWriteObjCounter(this);
2458            JComponent.setWriteObjCounter(this, --count);
2459            if (count == 0 && ui != null) {
2460                ui.installUI(this);
2461            }
2462        }
2463    }
2464
2465
2466    /**
2467     * Returns a string representation of this <code>JOptionPane</code>.
2468     * This method
2469     * is intended to be used only for debugging purposes, and the
2470     * content and format of the returned string may vary between
2471     * implementations. The returned string may be empty but may not
2472     * be <code>null</code>.
2473     *
2474     * @return  a string representation of this <code>JOptionPane</code>
2475     */
2476    protected String paramString() {
2477        String iconString = (icon != null ?
2478                             icon.toString() : "");
2479        String initialValueString = (initialValue != null ?
2480                                     initialValue.toString() : "");
2481        String messageString = (message != null ?
2482                                message.toString() : "");
2483        String messageTypeString;
2484        if (messageType == ERROR_MESSAGE) {
2485            messageTypeString = "ERROR_MESSAGE";
2486        } else if (messageType == INFORMATION_MESSAGE) {
2487            messageTypeString = "INFORMATION_MESSAGE";
2488        } else if (messageType == WARNING_MESSAGE) {
2489            messageTypeString = "WARNING_MESSAGE";
2490        } else if (messageType == QUESTION_MESSAGE) {
2491            messageTypeString = "QUESTION_MESSAGE";
2492        } else if (messageType == PLAIN_MESSAGE)  {
2493            messageTypeString = "PLAIN_MESSAGE";
2494        } else messageTypeString = "";
2495        String optionTypeString;
2496        if (optionType == DEFAULT_OPTION) {
2497            optionTypeString = "DEFAULT_OPTION";
2498        } else if (optionType == YES_NO_OPTION) {
2499            optionTypeString = "YES_NO_OPTION";
2500        } else if (optionType == YES_NO_CANCEL_OPTION) {
2501            optionTypeString = "YES_NO_CANCEL_OPTION";
2502        } else if (optionType == OK_CANCEL_OPTION) {
2503            optionTypeString = "OK_CANCEL_OPTION";
2504        } else optionTypeString = "";
2505        String wantsInputString = (wantsInput ?
2506                                   "true" : "false");
2507
2508        return super.paramString() +
2509        ",icon=" + iconString +
2510        ",initialValue=" + initialValueString +
2511        ",message=" + messageString +
2512        ",messageType=" + messageTypeString +
2513        ",optionType=" + optionTypeString +
2514        ",wantsInput=" + wantsInputString;
2515    }
2516
2517///////////////////
2518// Accessibility support
2519///////////////////
2520
2521    /**
2522     * Returns the <code>AccessibleContext</code> associated with this JOptionPane.
2523     * For option panes, the <code>AccessibleContext</code> takes the form of an
2524     * <code>AccessibleJOptionPane</code>.
2525     * A new <code>AccessibleJOptionPane</code> instance is created if necessary.
2526     *
2527     * @return an AccessibleJOptionPane that serves as the
2528     *         AccessibleContext of this AccessibleJOptionPane
2529     */
2530    @BeanProperty(bound = false, expert = true, description
2531            = "The AccessibleContext associated with this option pane")
2532    public AccessibleContext getAccessibleContext() {
2533        if (accessibleContext == null) {
2534            accessibleContext = new AccessibleJOptionPane();
2535        }
2536        return accessibleContext;
2537    }
2538
2539    /**
2540     * This class implements accessibility support for the
2541     * <code>JOptionPane</code> class.  It provides an implementation of the
2542     * Java Accessibility API appropriate to option pane user-interface
2543     * elements.
2544     * <p>
2545     * <strong>Warning:</strong>
2546     * Serialized objects of this class will not be compatible with
2547     * future Swing releases. The current serialization support is
2548     * appropriate for short term storage or RMI between applications running
2549     * the same version of Swing.  As of 1.4, support for long term storage
2550     * of all JavaBeans&trade;
2551     * has been added to the <code>java.beans</code> package.
2552     * Please see {@link java.beans.XMLEncoder}.
2553     */
2554    @SuppressWarnings("serial") // Same-version serialization only
2555    protected class AccessibleJOptionPane extends AccessibleJComponent {
2556
2557        /**
2558         * Get the role of this object.
2559         *
2560         * @return an instance of AccessibleRole describing the role of the object
2561         * @see AccessibleRole
2562         */
2563        public AccessibleRole getAccessibleRole() {
2564            switch (messageType) {
2565            case ERROR_MESSAGE:
2566            case INFORMATION_MESSAGE:
2567            case WARNING_MESSAGE:
2568                return AccessibleRole.ALERT;
2569
2570            default:
2571                return AccessibleRole.OPTION_PANE;
2572            }
2573        }
2574
2575    } // inner class AccessibleJOptionPane
2576}
2577