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