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