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