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