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