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