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