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