1 /* 2 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.peer.DialogPeer; 28 import java.awt.event.*; 29 import java.io.ObjectInputStream; 30 import java.io.IOException; 31 import java.util.Iterator; 32 import java.util.concurrent.atomic.AtomicLong; 33 import java.security.AccessController; 34 import java.security.PrivilegedAction; 35 import javax.accessibility.*; 36 import sun.awt.AppContext; 37 import sun.awt.AWTPermissions; 38 import sun.awt.SunToolkit; 39 import sun.awt.PeerEvent; 40 import sun.awt.util.IdentityArrayList; 41 import sun.awt.util.IdentityLinkedList; 42 import java.security.AccessControlException; 43 44 /** 45 * A Dialog is a top-level window with a title and a border 46 * that is typically used to take some form of input from the user. 47 * 48 * The size of the dialog includes any area designated for the 49 * border. The dimensions of the border area can be obtained 50 * using the <code>getInsets</code> method, however, since 51 * these dimensions are platform-dependent, a valid insets 52 * value cannot be obtained until the dialog is made displayable 53 * by either calling <code>pack</code> or <code>show</code>. 54 * Since the border area is included in the overall size of the 55 * dialog, the border effectively obscures a portion of the dialog, 56 * constraining the area available for rendering and/or displaying 57 * subcomponents to the rectangle which has an upper-left corner 58 * location of <code>(insets.left, insets.top)</code>, and has a size of 59 * <code>width - (insets.left + insets.right)</code> by 60 * <code>height - (insets.top + insets.bottom)</code>. 61 * <p> 62 * The default layout for a dialog is <code>BorderLayout</code>. 63 * <p> 64 * A dialog may have its native decorations (i.e. Frame & Titlebar) turned off 65 * with <code>setUndecorated</code>. This can only be done while the dialog 66 * is not {@link Component#isDisplayable() displayable}. 67 * <p> 68 * A dialog may have another window as its owner when it's constructed. When 69 * the owner window of a visible dialog is minimized, the dialog will 70 * automatically be hidden from the user. When the owner window is subsequently 71 * restored, the dialog is made visible to the user again. 72 * <p> 73 * In a multi-screen environment, you can create a <code>Dialog</code> 74 * on a different screen device than its owner. See {@link java.awt.Frame} for 75 * more information. 76 * <p> 77 * A dialog can be either modeless (the default) or modal. A modal 78 * dialog is one which blocks input to some other top-level windows 79 * in the application, except for any windows created with the dialog 80 * as their owner. See <a href="doc-files/Modality.html">AWT Modality</a> 81 * specification for details. 82 * <p> 83 * Dialogs are capable of generating the following 84 * <code>WindowEvents</code>: 85 * <code>WindowOpened</code>, <code>WindowClosing</code>, 86 * <code>WindowClosed</code>, <code>WindowActivated</code>, 87 * <code>WindowDeactivated</code>, <code>WindowGainedFocus</code>, 88 * <code>WindowLostFocus</code>. 89 * 90 * @see WindowEvent 91 * @see Window#addWindowListener 92 * 93 * @author Sami Shaio 94 * @author Arthur van Hoff 95 * @since JDK1.0 96 */ 97 public class Dialog extends Window { 98 99 static { 100 /* ensure that the necessary native libraries are loaded */ 101 Toolkit.loadLibraries(); 102 if (!GraphicsEnvironment.isHeadless()) { 103 initIDs(); 104 } 105 } 106 107 /** 108 * A dialog's resizable property. Will be true 109 * if the Dialog is to be resizable, otherwise 110 * it will be false. 111 * 112 * @serial 113 * @see #setResizable(boolean) 114 */ 115 boolean resizable = true; 116 117 118 /** 119 * This field indicates whether the dialog is undecorated. 120 * This property can only be changed while the dialog is not displayable. 121 * <code>undecorated</code> will be true if the dialog is 122 * undecorated, otherwise it will be false. 123 * 124 * @serial 125 * @see #setUndecorated(boolean) 126 * @see #isUndecorated() 127 * @see Component#isDisplayable() 128 * @since 1.4 129 */ 130 boolean undecorated = false; 131 132 private transient boolean initialized = false; 133 134 /** 135 * Modal dialogs block all input to some top-level windows. 136 * Whether a particular window is blocked depends on dialog's type 137 * of modality; this is called the "scope of blocking". The 138 * <code>ModalityType</code> enum specifies modal types and their 139 * associated scopes. 140 * 141 * @see Dialog#getModalityType 142 * @see Dialog#setModalityType 143 * @see Toolkit#isModalityTypeSupported 144 * 145 * @since 1.6 146 */ 147 public static enum ModalityType { 148 /** 149 * <code>MODELESS</code> dialog doesn't block any top-level windows. 150 */ 151 MODELESS, 152 /** 153 * A <code>DOCUMENT_MODAL</code> dialog blocks input to all top-level windows 154 * from the same document except those from its own child hierarchy. 155 * A document is a top-level window without an owner. It may contain child 156 * windows that, together with the top-level window are treated as a single 157 * solid document. Since every top-level window must belong to some 158 * document, its root can be found as the top-nearest window without an owner. 159 */ 160 DOCUMENT_MODAL, 161 /** 162 * An <code>APPLICATION_MODAL</code> dialog blocks all top-level windows 163 * from the same Java application except those from its own child hierarchy. 164 * If there are several applets launched in a browser, they can be 165 * treated either as separate applications or a single one. This behavior 166 * is implementation-dependent. 167 */ 168 APPLICATION_MODAL, 169 /** 170 * A <code>TOOLKIT_MODAL</code> dialog blocks all top-level windows run 171 * from the same toolkit except those from its own child hierarchy. If there 172 * are several applets launched in a browser, all of them run with the same 173 * toolkit; thus, a toolkit-modal dialog displayed by an applet may affect 174 * other applets and all windows of the browser instance which embeds the 175 * Java runtime environment for this toolkit. 176 * Special <code>AWTPermission</code> "toolkitModality" must be granted to use 177 * toolkit-modal dialogs. If a <code>TOOLKIT_MODAL</code> dialog is being created 178 * and this permission is not granted, a <code>SecurityException</code> will be 179 * thrown, and no dialog will be created. If a modality type is being changed 180 * to <code>TOOLKIT_MODAL</code> and this permission is not granted, a 181 * <code>SecurityException</code> will be thrown, and the modality type will 182 * be left unchanged. 183 */ 184 TOOLKIT_MODAL 185 }; 186 187 /** 188 * Default modality type for modal dialogs. The default modality type is 189 * <code>APPLICATION_MODAL</code>. Calling the oldstyle <code>setModal(true)</code> 190 * is equal to <code>setModalityType(DEFAULT_MODALITY_TYPE)</code>. 191 * 192 * @see java.awt.Dialog.ModalityType 193 * @see java.awt.Dialog#setModal 194 * 195 * @since 1.6 196 */ 197 public final static ModalityType DEFAULT_MODALITY_TYPE = ModalityType.APPLICATION_MODAL; 198 199 /** 200 * True if this dialog is modal, false is the dialog is modeless. 201 * A modal dialog blocks user input to some application top-level 202 * windows. This field is kept only for backwards compatibility. Use the 203 * {@link Dialog.ModalityType ModalityType} enum instead. 204 * 205 * @serial 206 * 207 * @see #isModal 208 * @see #setModal 209 * @see #getModalityType 210 * @see #setModalityType 211 * @see ModalityType 212 * @see ModalityType#MODELESS 213 * @see #DEFAULT_MODALITY_TYPE 214 */ 215 boolean modal; 216 217 /** 218 * Modality type of this dialog. If the dialog's modality type is not 219 * {@link Dialog.ModalityType#MODELESS ModalityType.MODELESS}, it blocks all 220 * user input to some application top-level windows. 221 * 222 * @serial 223 * 224 * @see ModalityType 225 * @see #getModalityType 226 * @see #setModalityType 227 * 228 * @since 1.6 229 */ 230 ModalityType modalityType; 231 232 /** 233 * Any top-level window can be marked not to be blocked by modal 234 * dialogs. This is called "modal exclusion". This enum specifies 235 * the possible modal exclusion types. 236 * 237 * @see Window#getModalExclusionType 238 * @see Window#setModalExclusionType 239 * @see Toolkit#isModalExclusionTypeSupported 240 * 241 * @since 1.6 242 */ 243 public static enum ModalExclusionType { 244 /** 245 * No modal exclusion. 246 */ 247 NO_EXCLUDE, 248 /** 249 * <code>APPLICATION_EXCLUDE</code> indicates that a top-level window 250 * won't be blocked by any application-modal dialogs. Also, it isn't 251 * blocked by document-modal dialogs from outside of its child hierarchy. 252 */ 253 APPLICATION_EXCLUDE, 254 /** 255 * <code>TOOLKIT_EXCLUDE</code> indicates that a top-level window 256 * won't be blocked by application-modal or toolkit-modal dialogs. Also, 257 * it isn't blocked by document-modal dialogs from outside of its 258 * child hierarchy. 259 * The "toolkitModality" <code>AWTPermission</code> must be granted 260 * for this exclusion. If an exclusion property is being changed to 261 * <code>TOOLKIT_EXCLUDE</code> and this permission is not granted, a 262 * <code>SecurityEcxeption</code> will be thrown, and the exclusion 263 * property will be left unchanged. 264 */ 265 TOOLKIT_EXCLUDE 266 }; 267 268 /* operations with this list should be synchronized on tree lock*/ 269 transient static IdentityArrayList<Dialog> modalDialogs = new IdentityArrayList<Dialog>(); 270 271 transient IdentityArrayList<Window> blockedWindows = new IdentityArrayList<Window>(); 272 273 /** 274 * Specifies the title of the Dialog. 275 * This field can be null. 276 * 277 * @serial 278 * @see #getTitle() 279 * @see #setTitle(String) 280 */ 281 String title; 282 283 private transient ModalEventFilter modalFilter; 284 private transient volatile SecondaryLoop secondaryLoop; 285 286 /* 287 * Indicates that this dialog is being hidden. This flag is set to true at 288 * the beginning of hide() and to false at the end of hide(). 289 * 290 * @see #hide() 291 * @see #hideAndDisposePreHandler() 292 * @see #hideAndDisposeHandler() 293 * @see #shouldBlock() 294 */ 295 transient volatile boolean isInHide = false; 296 297 /* 298 * Indicates that this dialog is being disposed. This flag is set to true at 299 * the beginning of doDispose() and to false at the end of doDispose(). 300 * 301 * @see #hide() 302 * @see #hideAndDisposePreHandler() 303 * @see #hideAndDisposeHandler() 304 * @see #doDispose() 305 */ 306 transient volatile boolean isInDispose = false; 307 308 private static final String base = "dialog"; 309 private static int nameCounter = 0; 310 311 /* 312 * JDK 1.1 serialVersionUID 313 */ 314 private static final long serialVersionUID = 5920926903803293709L; 315 316 /** 317 * Constructs an initially invisible, modeless <code>Dialog</code> with 318 * the specified owner <code>Frame</code> and an empty title. 319 * 320 * @param owner the owner of the dialog or <code>null</code> if 321 * this dialog has no owner 322 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 323 * <code>GraphicsConfiguration</code> is not from a screen device 324 * @exception HeadlessException when 325 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 326 * 327 * @see java.awt.GraphicsEnvironment#isHeadless 328 * @see Component#setSize 329 * @see Component#setVisible 330 */ 331 public Dialog(Frame owner) { 332 this(owner, "", false); 333 } 334 335 /** 336 * Constructs an initially invisible <code>Dialog</code> with the specified 337 * owner <code>Frame</code> and modality and an empty title. 338 * 339 * @param owner the owner of the dialog or <code>null</code> if 340 * this dialog has no owner 341 * @param modal specifies whether dialog blocks user input to other top-level 342 * windows when shown. If <code>false</code>, the dialog is <code>MODELESS</code>; 343 * if <code>true</code>, the modality type property is set to 344 * <code>DEFAULT_MODALITY_TYPE</code> 345 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 346 * <code>GraphicsConfiguration</code> is not from a screen device 347 * @exception HeadlessException when 348 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 349 * 350 * @see java.awt.Dialog.ModalityType 351 * @see java.awt.Dialog.ModalityType#MODELESS 352 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 353 * @see java.awt.Dialog#setModal 354 * @see java.awt.Dialog#setModalityType 355 * @see java.awt.GraphicsEnvironment#isHeadless 356 */ 357 public Dialog(Frame owner, boolean modal) { 358 this(owner, "", modal); 359 } 360 361 /** 362 * Constructs an initially invisible, modeless <code>Dialog</code> with 363 * the specified owner <code>Frame</code> and title. 364 * 365 * @param owner the owner of the dialog or <code>null</code> if 366 * this dialog has no owner 367 * @param title the title of the dialog or <code>null</code> if this dialog 368 * has no title 369 * @exception IllegalArgumentException if the <code>owner</code>'s 370 * <code>GraphicsConfiguration</code> is not from a screen device 371 * @exception HeadlessException when 372 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 373 * 374 * @see java.awt.GraphicsEnvironment#isHeadless 375 * @see Component#setSize 376 * @see Component#setVisible 377 */ 378 public Dialog(Frame owner, String title) { 379 this(owner, title, false); 380 } 381 382 /** 383 * Constructs an initially invisible <code>Dialog</code> with the 384 * specified owner <code>Frame</code>, title and modality. 385 * 386 * @param owner the owner of the dialog or <code>null</code> if 387 * this dialog has no owner 388 * @param title the title of the dialog or <code>null</code> if this dialog 389 * has no title 390 * @param modal specifies whether dialog blocks user input to other top-level 391 * windows when shown. If <code>false</code>, the dialog is <code>MODELESS</code>; 392 * if <code>true</code>, the modality type property is set to 393 * <code>DEFAULT_MODALITY_TYPE</code> 394 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 395 * <code>GraphicsConfiguration</code> is not from a screen device 396 * @exception HeadlessException when 397 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 398 * 399 * @see java.awt.Dialog.ModalityType 400 * @see java.awt.Dialog.ModalityType#MODELESS 401 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 402 * @see java.awt.Dialog#setModal 403 * @see java.awt.Dialog#setModalityType 404 * @see java.awt.GraphicsEnvironment#isHeadless 405 * @see Component#setSize 406 * @see Component#setVisible 407 */ 408 public Dialog(Frame owner, String title, boolean modal) { 409 this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS); 410 } 411 412 /** 413 * Constructs an initially invisible <code>Dialog</code> with the specified owner 414 * <code>Frame</code>, title, modality, and <code>GraphicsConfiguration</code>. 415 * @param owner the owner of the dialog or <code>null</code> if this dialog 416 * has no owner 417 * @param title the title of the dialog or <code>null</code> if this dialog 418 * has no title 419 * @param modal specifies whether dialog blocks user input to other top-level 420 * windows when shown. If <code>false</code>, the dialog is <code>MODELESS</code>; 421 * if <code>true</code>, the modality type property is set to 422 * <code>DEFAULT_MODALITY_TYPE</code> 423 * @param gc the <code>GraphicsConfiguration</code> of the target screen device; 424 * if <code>null</code>, the default system <code>GraphicsConfiguration</code> 425 * is assumed 426 * @exception java.lang.IllegalArgumentException if <code>gc</code> 427 * is not from a screen device 428 * @exception HeadlessException when 429 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 430 * 431 * @see java.awt.Dialog.ModalityType 432 * @see java.awt.Dialog.ModalityType#MODELESS 433 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 434 * @see java.awt.Dialog#setModal 435 * @see java.awt.Dialog#setModalityType 436 * @see java.awt.GraphicsEnvironment#isHeadless 437 * @see Component#setSize 438 * @see Component#setVisible 439 * @since 1.4 440 */ 441 public Dialog(Frame owner, String title, boolean modal, 442 GraphicsConfiguration gc) { 443 this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS, gc); 444 } 445 446 /** 447 * Constructs an initially invisible, modeless <code>Dialog</code> with 448 * the specified owner <code>Dialog</code> and an empty title. 449 * 450 * @param owner the owner of the dialog or <code>null</code> if this 451 * dialog has no owner 452 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 453 * <code>GraphicsConfiguration</code> is not from a screen device 454 * @exception HeadlessException when 455 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 456 * @see java.awt.GraphicsEnvironment#isHeadless 457 * @since 1.2 458 */ 459 public Dialog(Dialog owner) { 460 this(owner, "", false); 461 } 462 463 /** 464 * Constructs an initially invisible, modeless <code>Dialog</code> 465 * with the specified owner <code>Dialog</code> and title. 466 * 467 * @param owner the owner of the dialog or <code>null</code> if this 468 * has no owner 469 * @param title the title of the dialog or <code>null</code> if this dialog 470 * has no title 471 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 472 * <code>GraphicsConfiguration</code> is not from a screen device 473 * @exception HeadlessException when 474 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 475 * 476 * @see java.awt.GraphicsEnvironment#isHeadless 477 * @since 1.2 478 */ 479 public Dialog(Dialog owner, String title) { 480 this(owner, title, false); 481 } 482 483 /** 484 * Constructs an initially invisible <code>Dialog</code> with the 485 * specified owner <code>Dialog</code>, title, and modality. 486 * 487 * @param owner the owner of the dialog or <code>null</code> if this 488 * dialog has no owner 489 * @param title the title of the dialog or <code>null</code> if this 490 * dialog has no title 491 * @param modal specifies whether dialog blocks user input to other top-level 492 * windows when shown. If <code>false</code>, the dialog is <code>MODELESS</code>; 493 * if <code>true</code>, the modality type property is set to 494 * <code>DEFAULT_MODALITY_TYPE</code> 495 * @exception IllegalArgumentException if the <code>owner</code>'s 496 * <code>GraphicsConfiguration</code> is not from a screen device 497 * @exception HeadlessException when 498 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 499 * 500 * @see java.awt.Dialog.ModalityType 501 * @see java.awt.Dialog.ModalityType#MODELESS 502 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 503 * @see java.awt.Dialog#setModal 504 * @see java.awt.Dialog#setModalityType 505 * @see java.awt.GraphicsEnvironment#isHeadless 506 * 507 * @since 1.2 508 */ 509 public Dialog(Dialog owner, String title, boolean modal) { 510 this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS); 511 } 512 513 /** 514 * Constructs an initially invisible <code>Dialog</code> with the 515 * specified owner <code>Dialog</code>, title, modality and 516 * <code>GraphicsConfiguration</code>. 517 * 518 * @param owner the owner of the dialog or <code>null</code> if this 519 * dialog has no owner 520 * @param title the title of the dialog or <code>null</code> if this 521 * dialog has no title 522 * @param modal specifies whether dialog blocks user input to other top-level 523 * windows when shown. If <code>false</code>, the dialog is <code>MODELESS</code>; 524 * if <code>true</code>, the modality type property is set to 525 * <code>DEFAULT_MODALITY_TYPE</code> 526 * @param gc the <code>GraphicsConfiguration</code> of the target screen device; 527 * if <code>null</code>, the default system <code>GraphicsConfiguration</code> 528 * is assumed 529 * @exception java.lang.IllegalArgumentException if <code>gc</code> 530 * is not from a screen device 531 * @exception HeadlessException when 532 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 533 * 534 * @see java.awt.Dialog.ModalityType 535 * @see java.awt.Dialog.ModalityType#MODELESS 536 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 537 * @see java.awt.Dialog#setModal 538 * @see java.awt.Dialog#setModalityType 539 * @see java.awt.GraphicsEnvironment#isHeadless 540 * @see Component#setSize 541 * @see Component#setVisible 542 * 543 * @since 1.4 544 */ 545 public Dialog(Dialog owner, String title, boolean modal, 546 GraphicsConfiguration gc) { 547 this(owner, title, modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS, gc); 548 } 549 550 /** 551 * Constructs an initially invisible, modeless <code>Dialog</code> with the 552 * specified owner <code>Window</code> and an empty title. 553 * 554 * @param owner the owner of the dialog. The owner must be an instance of 555 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 556 * of their descendents or <code>null</code> 557 * 558 * @exception java.lang.IllegalArgumentException if the <code>owner</code> 559 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 560 * java.awt.Frame Frame} 561 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 562 * <code>GraphicsConfiguration</code> is not from a screen device 563 * @exception HeadlessException when 564 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 565 * 566 * @see java.awt.GraphicsEnvironment#isHeadless 567 * 568 * @since 1.6 569 */ 570 public Dialog(Window owner) { 571 this(owner, "", ModalityType.MODELESS); 572 } 573 574 /** 575 * Constructs an initially invisible, modeless <code>Dialog</code> with 576 * the specified owner <code>Window</code> and title. 577 * 578 * @param owner the owner of the dialog. The owner must be an instance of 579 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 580 * of their descendents or <code>null</code> 581 * @param title the title of the dialog or <code>null</code> if this dialog 582 * has no title 583 * 584 * @exception java.lang.IllegalArgumentException if the <code>owner</code> 585 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 586 * java.awt.Frame Frame} 587 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 588 * <code>GraphicsConfiguration</code> is not from a screen device 589 * @exception HeadlessException when 590 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 591 * 592 * @see java.awt.GraphicsEnvironment#isHeadless 593 * 594 * @since 1.6 595 */ 596 public Dialog(Window owner, String title) { 597 this(owner, title, ModalityType.MODELESS); 598 } 599 600 /** 601 * Constructs an initially invisible <code>Dialog</code> with the 602 * specified owner <code>Window</code> and modality and an empty title. 603 * 604 * @param owner the owner of the dialog. The owner must be an instance of 605 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 606 * of their descendents or <code>null</code> 607 * @param modalityType specifies whether dialog blocks input to other 608 * windows when shown. <code>null</code> value and unsupported modality 609 * types are equivalent to <code>MODELESS</code> 610 * 611 * @exception java.lang.IllegalArgumentException if the <code>owner</code> 612 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 613 * java.awt.Frame Frame} 614 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 615 * <code>GraphicsConfiguration</code> is not from a screen device 616 * @exception HeadlessException when 617 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 618 * @exception SecurityException if the calling thread does not have permission 619 * to create modal dialogs with the given <code>modalityType</code> 620 * 621 * @see java.awt.Dialog.ModalityType 622 * @see java.awt.Dialog#setModal 623 * @see java.awt.Dialog#setModalityType 624 * @see java.awt.GraphicsEnvironment#isHeadless 625 * @see java.awt.Toolkit#isModalityTypeSupported 626 * 627 * @since 1.6 628 */ 629 public Dialog(Window owner, ModalityType modalityType) { 630 this(owner, "", modalityType); 631 } 632 633 /** 634 * Constructs an initially invisible <code>Dialog</code> with the 635 * specified owner <code>Window</code>, title and modality. 636 * 637 * @param owner the owner of the dialog. The owner must be an instance of 638 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 639 * of their descendents or <code>null</code> 640 * @param title the title of the dialog or <code>null</code> if this dialog 641 * has no title 642 * @param modalityType specifies whether dialog blocks input to other 643 * windows when shown. <code>null</code> value and unsupported modality 644 * types are equivalent to <code>MODELESS</code> 645 * 646 * @exception java.lang.IllegalArgumentException if the <code>owner</code> 647 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 648 * java.awt.Frame Frame} 649 * @exception java.lang.IllegalArgumentException if the <code>owner</code>'s 650 * <code>GraphicsConfiguration</code> is not from a screen device 651 * @exception HeadlessException when 652 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 653 * @exception SecurityException if the calling thread does not have permission 654 * to create modal dialogs with the given <code>modalityType</code> 655 * 656 * @see java.awt.Dialog.ModalityType 657 * @see java.awt.Dialog#setModal 658 * @see java.awt.Dialog#setModalityType 659 * @see java.awt.GraphicsEnvironment#isHeadless 660 * @see java.awt.Toolkit#isModalityTypeSupported 661 * 662 * @since 1.6 663 */ 664 public Dialog(Window owner, String title, ModalityType modalityType) { 665 super(owner); 666 667 if ((owner != null) && 668 !(owner instanceof Frame) && 669 !(owner instanceof Dialog)) 670 { 671 throw new IllegalArgumentException("Wrong parent window"); 672 } 673 674 this.title = title; 675 setModalityType(modalityType); 676 SunToolkit.checkAndSetPolicy(this); 677 initialized = true; 678 } 679 680 /** 681 * Constructs an initially invisible <code>Dialog</code> with the 682 * specified owner <code>Window</code>, title, modality and 683 * <code>GraphicsConfiguration</code>. 684 * 685 * @param owner the owner of the dialog. The owner must be an instance of 686 * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any 687 * of their descendents or <code>null</code> 688 * @param title the title of the dialog or <code>null</code> if this dialog 689 * has no title 690 * @param modalityType specifies whether dialog blocks input to other 691 * windows when shown. <code>null</code> value and unsupported modality 692 * types are equivalent to <code>MODELESS</code> 693 * @param gc the <code>GraphicsConfiguration</code> of the target screen device; 694 * if <code>null</code>, the default system <code>GraphicsConfiguration</code> 695 * is assumed 696 * 697 * @exception java.lang.IllegalArgumentException if the <code>owner</code> 698 * is not an instance of {@link java.awt.Dialog Dialog} or {@link 699 * java.awt.Frame Frame} 700 * @exception java.lang.IllegalArgumentException if <code>gc</code> 701 * is not from a screen device 702 * @exception HeadlessException when 703 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 704 * @exception SecurityException if the calling thread does not have permission 705 * to create modal dialogs with the given <code>modalityType</code> 706 * 707 * @see java.awt.Dialog.ModalityType 708 * @see java.awt.Dialog#setModal 709 * @see java.awt.Dialog#setModalityType 710 * @see java.awt.GraphicsEnvironment#isHeadless 711 * @see java.awt.Toolkit#isModalityTypeSupported 712 * 713 * @since 1.6 714 */ 715 public Dialog(Window owner, String title, ModalityType modalityType, 716 GraphicsConfiguration gc) { 717 super(owner, gc); 718 719 if ((owner != null) && 720 !(owner instanceof Frame) && 721 !(owner instanceof Dialog)) 722 { 723 throw new IllegalArgumentException("wrong owner window"); 724 } 725 726 this.title = title; 727 setModalityType(modalityType); 728 SunToolkit.checkAndSetPolicy(this); 729 initialized = true; 730 } 731 732 /** 733 * Construct a name for this component. Called by getName() when the 734 * name is null. 735 */ 736 String constructComponentName() { 737 synchronized (Dialog.class) { 738 return base + nameCounter++; 739 } 740 } 741 742 /** 743 * Makes this Dialog displayable by connecting it to 744 * a native screen resource. Making a dialog displayable will 745 * cause any of its children to be made displayable. 746 * This method is called internally by the toolkit and should 747 * not be called directly by programs. 748 * @see Component#isDisplayable 749 * @see #removeNotify 750 */ 751 public void addNotify() { 752 synchronized (getTreeLock()) { 753 if (parent != null && parent.getPeer() == null) { 754 parent.addNotify(); 755 } 756 757 if (peer == null) { 758 peer = getToolkit().createDialog(this); 759 } 760 super.addNotify(); 761 } 762 } 763 764 /** 765 * Indicates whether the dialog is modal. 766 * <p> 767 * This method is obsolete and is kept for backwards compatibility only. 768 * Use {@link #getModalityType getModalityType()} instead. 769 * 770 * @return <code>true</code> if this dialog window is modal; 771 * <code>false</code> otherwise 772 * 773 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 774 * @see java.awt.Dialog.ModalityType#MODELESS 775 * @see java.awt.Dialog#setModal 776 * @see java.awt.Dialog#getModalityType 777 * @see java.awt.Dialog#setModalityType 778 */ 779 public boolean isModal() { 780 return isModal_NoClientCode(); 781 } 782 final boolean isModal_NoClientCode() { 783 return modalityType != ModalityType.MODELESS; 784 } 785 786 /** 787 * Specifies whether this dialog should be modal. 788 * <p> 789 * This method is obsolete and is kept for backwards compatibility only. 790 * Use {@link #setModalityType setModalityType()} instead. 791 * <p> 792 * Note: changing modality of the visible dialog may have no effect 793 * until it is hidden and then shown again. 794 * 795 * @param modal specifies whether dialog blocks input to other windows 796 * when shown; calling to <code>setModal(true)</code> is equivalent to 797 * <code>setModalityType(Dialog.DEFAULT_MODALITY_TYPE)</code>, and 798 * calling to <code>setModal(false)</code> is equvivalent to 799 * <code>setModalityType(Dialog.ModalityType.MODELESS)</code> 800 * 801 * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE 802 * @see java.awt.Dialog.ModalityType#MODELESS 803 * @see java.awt.Dialog#isModal 804 * @see java.awt.Dialog#getModalityType 805 * @see java.awt.Dialog#setModalityType 806 * 807 * @since 1.1 808 */ 809 public void setModal(boolean modal) { 810 this.modal = modal; 811 setModalityType(modal ? DEFAULT_MODALITY_TYPE : ModalityType.MODELESS); 812 } 813 814 /** 815 * Returns the modality type of this dialog. 816 * 817 * @return modality type of this dialog 818 * 819 * @see java.awt.Dialog#setModalityType 820 * 821 * @since 1.6 822 */ 823 public ModalityType getModalityType() { 824 return modalityType; 825 } 826 827 /** 828 * Sets the modality type for this dialog. See {@link 829 * java.awt.Dialog.ModalityType ModalityType} for possible modality types. 830 * <p> 831 * If the given modality type is not supported, <code>MODELESS</code> 832 * is used. You may want to call <code>getModalityType()</code> after calling 833 * this method to ensure that the modality type has been set. 834 * <p> 835 * Note: changing modality of the visible dialog may have no effect 836 * until it is hidden and then shown again. 837 * 838 * @param type specifies whether dialog blocks input to other 839 * windows when shown. <code>null</code> value and unsupported modality 840 * types are equivalent to <code>MODELESS</code> 841 * @exception SecurityException if the calling thread does not have permission 842 * to create modal dialogs with the given <code>modalityType</code> 843 * 844 * @see java.awt.Dialog#getModalityType 845 * @see java.awt.Toolkit#isModalityTypeSupported 846 * 847 * @since 1.6 848 */ 849 public void setModalityType(ModalityType type) { 850 if (type == null) { 851 type = Dialog.ModalityType.MODELESS; 852 } 853 if (!Toolkit.getDefaultToolkit().isModalityTypeSupported(type)) { 854 type = Dialog.ModalityType.MODELESS; 855 } 856 if (modalityType == type) { 857 return; 858 } 859 860 checkModalityPermission(type); 861 862 modalityType = type; 863 modal = (modalityType != ModalityType.MODELESS); 864 } 865 866 /** 867 * Gets the title of the dialog. The title is displayed in the 868 * dialog's border. 869 * @return the title of this dialog window. The title may be 870 * <code>null</code>. 871 * @see java.awt.Dialog#setTitle 872 */ 873 public String getTitle() { 874 return title; 875 } 876 877 /** 878 * Sets the title of the Dialog. 879 * @param title the title displayed in the dialog's border; 880 * a null value results in an empty title 881 * @see #getTitle 882 */ 883 public void setTitle(String title) { 884 String oldTitle = this.title; 885 886 synchronized(this) { 887 this.title = title; 888 DialogPeer peer = (DialogPeer)this.peer; 889 if (peer != null) { 890 peer.setTitle(title); 891 } 892 } 893 firePropertyChange("title", oldTitle, title); 894 } 895 896 /** 897 * @return true if we actually showed, false if we just called toFront() 898 */ 899 private boolean conditionalShow(Component toFocus, AtomicLong time) { 900 boolean retval; 901 902 closeSplashScreen(); 903 904 synchronized (getTreeLock()) { 905 if (peer == null) { 906 addNotify(); 907 } 908 validateUnconditionally(); 909 if (visible) { 910 toFront(); 911 retval = false; 912 } else { 913 visible = retval = true; 914 915 // check if this dialog should be modal blocked BEFORE calling peer.show(), 916 // otherwise, a pair of FOCUS_GAINED and FOCUS_LOST may be mistakenly 917 // generated for the dialog 918 if (!isModal()) { 919 checkShouldBeBlocked(this); 920 } else { 921 modalDialogs.add(this); 922 modalShow(); 923 } 924 925 if (toFocus != null && time != null && isFocusable() && 926 isEnabled() && !isModalBlocked()) { 927 // keep the KeyEvents from being dispatched 928 // until the focus has been transfered 929 time.set(Toolkit.getEventQueue().getMostRecentKeyEventTime()); 930 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 931 enqueueKeyEvents(time.get(), toFocus); 932 } 933 934 // This call is required as the show() method of the Dialog class 935 // does not invoke the super.show(). So wried... :( 936 mixOnShowing(); 937 938 peer.setVisible(true); // now guaranteed never to block 939 if (isModalBlocked()) { 940 modalBlocker.toFront(); 941 } 942 943 setLocationByPlatform(false); 944 for (int i = 0; i < ownedWindowList.size(); i++) { 945 Window child = ownedWindowList.elementAt(i).get(); 946 if ((child != null) && child.showWithParent) { 947 child.show(); 948 child.showWithParent = false; 949 } // endif 950 } // endfor 951 Window.updateChildFocusableWindowState(this); 952 953 createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, 954 this, parent, 955 HierarchyEvent.SHOWING_CHANGED, 956 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 957 if (componentListener != null || 958 (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || 959 Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) { 960 ComponentEvent e = 961 new ComponentEvent(this, ComponentEvent.COMPONENT_SHOWN); 962 Toolkit.getEventQueue().postEvent(e); 963 } 964 } 965 } 966 967 if (retval && (state & OPENED) == 0) { 968 postWindowEvent(WindowEvent.WINDOW_OPENED); 969 state |= OPENED; 970 } 971 972 return retval; 973 } 974 975 /** 976 * Shows or hides this {@code Dialog} depending on the value of parameter 977 * {@code b}. 978 * @param b if {@code true}, makes the {@code Dialog} visible, 979 * otherwise hides the {@code Dialog}. 980 * If the dialog and/or its owner 981 * are not yet displayable, both are made displayable. The 982 * dialog will be validated prior to being made visible. 983 * If {@code false}, hides the {@code Dialog} and then causes {@code setVisible(true)} 984 * to return if it is currently blocked. 985 * <p> 986 * <b>Notes for modal dialogs</b>. 987 * <ul> 988 * <li>{@code setVisible(true)}: If the dialog is not already 989 * visible, this call will not return until the dialog is 990 * hidden by calling {@code setVisible(false)} or 991 * {@code dispose}. 992 * <li>{@code setVisible(false)}: Hides the dialog and then 993 * returns on {@code setVisible(true)} if it is currently blocked. 994 * <li>It is OK to call this method from the event dispatching 995 * thread because the toolkit ensures that other events are 996 * not blocked while this method is blocked. 997 * </ul> 998 * @see java.awt.Window#setVisible 999 * @see java.awt.Window#dispose 1000 * @see java.awt.Component#isDisplayable 1001 * @see java.awt.Component#validate 1002 * @see java.awt.Dialog#isModal 1003 */ 1004 public void setVisible(boolean b) { 1005 super.setVisible(b); 1006 } 1007 1008 /** 1009 * Makes the {@code Dialog} visible. If the dialog and/or its owner 1010 * are not yet displayable, both are made displayable. The 1011 * dialog will be validated prior to being made visible. 1012 * If the dialog is already visible, this will bring the dialog 1013 * to the front. 1014 * <p> 1015 * If the dialog is modal and is not already visible, this call 1016 * will not return until the dialog is hidden by calling hide or 1017 * dispose. It is permissible to show modal dialogs from the event 1018 * dispatching thread because the toolkit will ensure that another 1019 * event pump runs while the one which invoked this method is blocked. 1020 * @see Component#hide 1021 * @see Component#isDisplayable 1022 * @see Component#validate 1023 * @see #isModal 1024 * @see Window#setVisible(boolean) 1025 * @deprecated As of JDK version 1.5, replaced by 1026 * {@link #setVisible(boolean) setVisible(boolean)}. 1027 */ 1028 @Deprecated 1029 public void show() { 1030 if (!initialized) { 1031 throw new IllegalStateException("The dialog component " + 1032 "has not been initialized properly"); 1033 } 1034 1035 beforeFirstShow = false; 1036 if (!isModal()) { 1037 conditionalShow(null, null); 1038 } else { 1039 AppContext showAppContext = AppContext.getAppContext(); 1040 1041 AtomicLong time = new AtomicLong(); 1042 Component predictedFocusOwner = null; 1043 try { 1044 predictedFocusOwner = getMostRecentFocusOwner(); 1045 if (conditionalShow(predictedFocusOwner, time)) { 1046 modalFilter = ModalEventFilter.createFilterForDialog(this); 1047 final Conditional cond = new Conditional() { 1048 @Override 1049 public boolean evaluate() { 1050 return windowClosingException == null; 1051 } 1052 }; 1053 1054 // if this dialog is toolkit-modal, the filter should be added 1055 // to all EDTs (for all AppContexts) 1056 if (modalityType == ModalityType.TOOLKIT_MODAL) { 1057 Iterator<AppContext> it = AppContext.getAppContexts().iterator(); 1058 while (it.hasNext()) { 1059 AppContext appContext = it.next(); 1060 if (appContext == showAppContext) { 1061 continue; 1062 } 1063 EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); 1064 // it may occur that EDT for appContext hasn't been started yet, so 1065 // we post an empty invocation event to trigger EDT initialization 1066 Runnable createEDT = new Runnable() { 1067 public void run() {}; 1068 }; 1069 eventQueue.postEvent(new InvocationEvent(this, createEDT)); 1070 EventDispatchThread edt = eventQueue.getDispatchThread(); 1071 edt.addEventFilter(modalFilter); 1072 } 1073 } 1074 1075 modalityPushed(); 1076 try { 1077 final EventQueue eventQueue = AccessController.doPrivileged( 1078 new PrivilegedAction<EventQueue>() { 1079 public EventQueue run() { 1080 return Toolkit.getDefaultToolkit().getSystemEventQueue(); 1081 } 1082 }); 1083 secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 0); 1084 if (!secondaryLoop.enter()) { 1085 secondaryLoop = null; 1086 } 1087 } finally { 1088 modalityPopped(); 1089 } 1090 1091 // if this dialog is toolkit-modal, its filter must be removed 1092 // from all EDTs (for all AppContexts) 1093 if (modalityType == ModalityType.TOOLKIT_MODAL) { 1094 Iterator<AppContext> it = AppContext.getAppContexts().iterator(); 1095 while (it.hasNext()) { 1096 AppContext appContext = it.next(); 1097 if (appContext == showAppContext) { 1098 continue; 1099 } 1100 EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); 1101 EventDispatchThread edt = eventQueue.getDispatchThread(); 1102 edt.removeEventFilter(modalFilter); 1103 } 1104 } 1105 1106 if (windowClosingException != null) { 1107 windowClosingException.fillInStackTrace(); 1108 throw windowClosingException; 1109 } 1110 } 1111 } finally { 1112 if (predictedFocusOwner != null) { 1113 // Restore normal key event dispatching 1114 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 1115 dequeueKeyEvents(time.get(), predictedFocusOwner); 1116 } 1117 } 1118 } 1119 } 1120 1121 final void modalityPushed() { 1122 Toolkit tk = Toolkit.getDefaultToolkit(); 1123 if (tk instanceof SunToolkit) { 1124 SunToolkit stk = (SunToolkit)tk; 1125 stk.notifyModalityPushed(this); 1126 } 1127 } 1128 1129 final void modalityPopped() { 1130 Toolkit tk = Toolkit.getDefaultToolkit(); 1131 if (tk instanceof SunToolkit) { 1132 SunToolkit stk = (SunToolkit)tk; 1133 stk.notifyModalityPopped(this); 1134 } 1135 } 1136 1137 void interruptBlocking() { 1138 if (isModal()) { 1139 disposeImpl(); 1140 } else if (windowClosingException != null) { 1141 windowClosingException.fillInStackTrace(); 1142 windowClosingException.printStackTrace(); 1143 windowClosingException = null; 1144 } 1145 } 1146 1147 private void hideAndDisposePreHandler() { 1148 isInHide = true; 1149 synchronized (getTreeLock()) { 1150 if (secondaryLoop != null) { 1151 modalHide(); 1152 // dialog can be shown and then disposed before its 1153 // modal filter is created 1154 if (modalFilter != null) { 1155 modalFilter.disable(); 1156 } 1157 modalDialogs.remove(this); 1158 } 1159 } 1160 } 1161 private void hideAndDisposeHandler() { 1162 if (secondaryLoop != null) { 1163 secondaryLoop.exit(); 1164 secondaryLoop = null; 1165 } 1166 isInHide = false; 1167 } 1168 1169 /** 1170 * Hides the Dialog and then causes {@code show} to return if it is currently 1171 * blocked. 1172 * @see Window#show 1173 * @see Window#dispose 1174 * @see Window#setVisible(boolean) 1175 * @deprecated As of JDK version 1.5, replaced by 1176 * {@link #setVisible(boolean) setVisible(boolean)}. 1177 */ 1178 @Deprecated 1179 public void hide() { 1180 hideAndDisposePreHandler(); 1181 super.hide(); 1182 // fix for 5048370: if hide() is called from super.doDispose(), then 1183 // hideAndDisposeHandler() should not be called here as it will be called 1184 // at the end of doDispose() 1185 if (!isInDispose) { 1186 hideAndDisposeHandler(); 1187 } 1188 } 1189 1190 /** 1191 * Disposes the Dialog and then causes show() to return if it is currently 1192 * blocked. 1193 */ 1194 void doDispose() { 1195 // fix for 5048370: set isInDispose flag to true to prevent calling 1196 // to hideAndDisposeHandler() from hide() 1197 isInDispose = true; 1198 super.doDispose(); 1199 hideAndDisposeHandler(); 1200 isInDispose = false; 1201 } 1202 1203 /** 1204 * {@inheritDoc} 1205 * <p> 1206 * If this dialog is modal and blocks some windows, then all of them are 1207 * also sent to the back to keep them below the blocking dialog. 1208 * 1209 * @see java.awt.Window#toBack 1210 */ 1211 public void toBack() { 1212 super.toBack(); 1213 if (visible) { 1214 synchronized (getTreeLock()) { 1215 for (Window w : blockedWindows) { 1216 w.toBack_NoClientCode(); 1217 } 1218 } 1219 } 1220 } 1221 1222 /** 1223 * Indicates whether this dialog is resizable by the user. 1224 * By default, all dialogs are initially resizable. 1225 * @return <code>true</code> if the user can resize the dialog; 1226 * <code>false</code> otherwise. 1227 * @see java.awt.Dialog#setResizable 1228 */ 1229 public boolean isResizable() { 1230 return resizable; 1231 } 1232 1233 /** 1234 * Sets whether this dialog is resizable by the user. 1235 * @param resizable <code>true</code> if the user can 1236 * resize this dialog; <code>false</code> otherwise. 1237 * @see java.awt.Dialog#isResizable 1238 */ 1239 public void setResizable(boolean resizable) { 1240 boolean testvalid = false; 1241 1242 synchronized (this) { 1243 this.resizable = resizable; 1244 DialogPeer peer = (DialogPeer)this.peer; 1245 if (peer != null) { 1246 peer.setResizable(resizable); 1247 testvalid = true; 1248 } 1249 } 1250 1251 // On some platforms, changing the resizable state affects 1252 // the insets of the Dialog. If we could, we'd call invalidate() 1253 // from the peer, but we need to guarantee that we're not holding 1254 // the Dialog lock when we call invalidate(). 1255 if (testvalid) { 1256 invalidateIfValid(); 1257 } 1258 } 1259 1260 1261 /** 1262 * Disables or enables decorations for this dialog. 1263 * <p> 1264 * This method can only be called while the dialog is not displayable. To 1265 * make this dialog decorated, it must be opaque and have the default shape, 1266 * otherwise the {@code IllegalComponentStateException} will be thrown. 1267 * Refer to {@link Window#setShape}, {@link Window#setOpacity} and {@link 1268 * Window#setBackground} for details 1269 * 1270 * @param undecorated {@code true} if no dialog decorations are to be 1271 * enabled; {@code false} if dialog decorations are to be enabled 1272 * 1273 * @throws IllegalComponentStateException if the dialog is displayable 1274 * @throws IllegalComponentStateException if {@code undecorated} is 1275 * {@code false}, and this dialog does not have the default shape 1276 * @throws IllegalComponentStateException if {@code undecorated} is 1277 * {@code false}, and this dialog opacity is less than {@code 1.0f} 1278 * @throws IllegalComponentStateException if {@code undecorated} is 1279 * {@code false}, and the alpha value of this dialog background 1280 * color is less than {@code 1.0f} 1281 * 1282 * @see #isUndecorated 1283 * @see Component#isDisplayable 1284 * @see Window#getShape 1285 * @see Window#getOpacity 1286 * @see Window#getBackground 1287 * 1288 * @since 1.4 1289 */ 1290 public void setUndecorated(boolean undecorated) { 1291 /* Make sure we don't run in the middle of peer creation.*/ 1292 synchronized (getTreeLock()) { 1293 if (isDisplayable()) { 1294 throw new IllegalComponentStateException("The dialog is displayable."); 1295 } 1296 if (!undecorated) { 1297 if (getOpacity() < 1.0f) { 1298 throw new IllegalComponentStateException("The dialog is not opaque"); 1299 } 1300 if (getShape() != null) { 1301 throw new IllegalComponentStateException("The dialog does not have a default shape"); 1302 } 1303 Color bg = getBackground(); 1304 if ((bg != null) && (bg.getAlpha() < 255)) { 1305 throw new IllegalComponentStateException("The dialog background color is not opaque"); 1306 } 1307 } 1308 this.undecorated = undecorated; 1309 } 1310 } 1311 1312 /** 1313 * Indicates whether this dialog is undecorated. 1314 * By default, all dialogs are initially decorated. 1315 * @return <code>true</code> if dialog is undecorated; 1316 * <code>false</code> otherwise. 1317 * @see java.awt.Dialog#setUndecorated 1318 * @since 1.4 1319 */ 1320 public boolean isUndecorated() { 1321 return undecorated; 1322 } 1323 1324 /** 1325 * {@inheritDoc} 1326 */ 1327 @Override 1328 public void setOpacity(float opacity) { 1329 synchronized (getTreeLock()) { 1330 if ((opacity < 1.0f) && !isUndecorated()) { 1331 throw new IllegalComponentStateException("The dialog is decorated"); 1332 } 1333 super.setOpacity(opacity); 1334 } 1335 } 1336 1337 /** 1338 * {@inheritDoc} 1339 */ 1340 @Override 1341 public void setShape(Shape shape) { 1342 synchronized (getTreeLock()) { 1343 if ((shape != null) && !isUndecorated()) { 1344 throw new IllegalComponentStateException("The dialog is decorated"); 1345 } 1346 super.setShape(shape); 1347 } 1348 } 1349 1350 /** 1351 * {@inheritDoc} 1352 */ 1353 @Override 1354 public void setBackground(Color bgColor) { 1355 synchronized (getTreeLock()) { 1356 if ((bgColor != null) && (bgColor.getAlpha() < 255) && !isUndecorated()) { 1357 throw new IllegalComponentStateException("The dialog is decorated"); 1358 } 1359 super.setBackground(bgColor); 1360 } 1361 } 1362 1363 /** 1364 * Returns a string representing the state of this dialog. This 1365 * method is intended to be used only for debugging purposes, and the 1366 * content and format of the returned string may vary between 1367 * implementations. The returned string may be empty but may not be 1368 * <code>null</code>. 1369 * 1370 * @return the parameter string of this dialog window. 1371 */ 1372 protected String paramString() { 1373 String str = super.paramString() + "," + modalityType; 1374 if (title != null) { 1375 str += ",title=" + title; 1376 } 1377 return str; 1378 } 1379 1380 /** 1381 * Initialize JNI field and method IDs 1382 */ 1383 private static native void initIDs(); 1384 1385 /* 1386 * --- Modality support --- 1387 * 1388 */ 1389 1390 /* 1391 * This method is called only for modal dialogs. 1392 * 1393 * Goes through the list of all visible top-level windows and 1394 * divide them into three distinct groups: blockers of this dialog, 1395 * blocked by this dialog and all others. Then blocks this dialog 1396 * by first met dialog from the first group (if any) and blocks all 1397 * the windows from the second group. 1398 */ 1399 void modalShow() { 1400 // find all the dialogs that block this one 1401 IdentityArrayList<Dialog> blockers = new IdentityArrayList<Dialog>(); 1402 for (Dialog d : modalDialogs) { 1403 if (d.shouldBlock(this)) { 1404 Window w = d; 1405 while ((w != null) && (w != this)) { 1406 w = w.getOwner_NoClientCode(); 1407 } 1408 if ((w == this) || !shouldBlock(d) || (modalityType.compareTo(d.getModalityType()) < 0)) { 1409 blockers.add(d); 1410 } 1411 } 1412 } 1413 1414 // add all blockers' blockers to blockers :) 1415 for (int i = 0; i < blockers.size(); i++) { 1416 Dialog blocker = blockers.get(i); 1417 if (blocker.isModalBlocked()) { 1418 Dialog blockerBlocker = blocker.getModalBlocker(); 1419 if (!blockers.contains(blockerBlocker)) { 1420 blockers.add(i + 1, blockerBlocker); 1421 } 1422 } 1423 } 1424 1425 if (blockers.size() > 0) { 1426 blockers.get(0).blockWindow(this); 1427 } 1428 1429 // find all windows from blockers' hierarchies 1430 IdentityArrayList<Window> blockersHierarchies = new IdentityArrayList<Window>(blockers); 1431 int k = 0; 1432 while (k < blockersHierarchies.size()) { 1433 Window w = blockersHierarchies.get(k); 1434 Window[] ownedWindows = w.getOwnedWindows_NoClientCode(); 1435 for (Window win : ownedWindows) { 1436 blockersHierarchies.add(win); 1437 } 1438 k++; 1439 } 1440 1441 java.util.List<Window> toBlock = new IdentityLinkedList<Window>(); 1442 // block all windows from scope of blocking except from blockers' hierarchies 1443 IdentityArrayList<Window> unblockedWindows = Window.getAllUnblockedWindows(); 1444 for (Window w : unblockedWindows) { 1445 if (shouldBlock(w) && !blockersHierarchies.contains(w)) { 1446 if ((w instanceof Dialog) && ((Dialog)w).isModal_NoClientCode()) { 1447 Dialog wd = (Dialog)w; 1448 if (wd.shouldBlock(this) && (modalDialogs.indexOf(wd) > modalDialogs.indexOf(this))) { 1449 continue; 1450 } 1451 } 1452 toBlock.add(w); 1453 } 1454 } 1455 blockWindows(toBlock); 1456 1457 if (!isModalBlocked()) { 1458 updateChildrenBlocking(); 1459 } 1460 } 1461 1462 /* 1463 * This method is called only for modal dialogs. 1464 * 1465 * Unblocks all the windows blocked by this modal dialog. After 1466 * each of them has been unblocked, it is checked to be blocked by 1467 * any other modal dialogs. 1468 */ 1469 void modalHide() { 1470 // we should unblock all the windows first... 1471 IdentityArrayList<Window> save = new IdentityArrayList<Window>(); 1472 int blockedWindowsCount = blockedWindows.size(); 1473 for (int i = 0; i < blockedWindowsCount; i++) { 1474 Window w = blockedWindows.get(0); 1475 save.add(w); 1476 unblockWindow(w); // also removes w from blockedWindows 1477 } 1478 // ... and only after that check if they should be blocked 1479 // by another dialogs 1480 for (int i = 0; i < blockedWindowsCount; i++) { 1481 Window w = save.get(i); 1482 if ((w instanceof Dialog) && ((Dialog)w).isModal_NoClientCode()) { 1483 Dialog d = (Dialog)w; 1484 d.modalShow(); 1485 } else { 1486 checkShouldBeBlocked(w); 1487 } 1488 } 1489 } 1490 1491 /* 1492 * Returns whether the given top-level window should be blocked by 1493 * this dialog. Note, that the given window can be also a modal dialog 1494 * and it should block this dialog, but this method do not take such 1495 * situations into consideration (such checks are performed in the 1496 * modalShow() and modalHide() methods). 1497 * 1498 * This method should be called on the getTreeLock() lock. 1499 */ 1500 boolean shouldBlock(Window w) { 1501 if (!isVisible_NoClientCode() || 1502 (!w.isVisible_NoClientCode() && !w.isInShow) || 1503 isInHide || 1504 (w == this) || 1505 !isModal_NoClientCode()) 1506 { 1507 return false; 1508 } 1509 if ((w instanceof Dialog) && ((Dialog)w).isInHide) { 1510 return false; 1511 } 1512 // check if w is from children hierarchy 1513 // fix for 6271546: we should also take into consideration child hierarchies 1514 // of this dialog's blockers 1515 Window blockerToCheck = this; 1516 while (blockerToCheck != null) { 1517 Component c = w; 1518 while ((c != null) && (c != blockerToCheck)) { 1519 c = c.getParent_NoClientCode(); 1520 } 1521 if (c == blockerToCheck) { 1522 return false; 1523 } 1524 blockerToCheck = blockerToCheck.getModalBlocker(); 1525 } 1526 switch (modalityType) { 1527 case MODELESS: 1528 return false; 1529 case DOCUMENT_MODAL: 1530 if (w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE)) { 1531 // application- and toolkit-excluded windows are not blocked by 1532 // document-modal dialogs from outside their children hierarchy 1533 Component c = this; 1534 while ((c != null) && (c != w)) { 1535 c = c.getParent_NoClientCode(); 1536 } 1537 return c == w; 1538 } else { 1539 return getDocumentRoot() == w.getDocumentRoot(); 1540 } 1541 case APPLICATION_MODAL: 1542 return !w.isModalExcluded(ModalExclusionType.APPLICATION_EXCLUDE) && 1543 (appContext == w.appContext); 1544 case TOOLKIT_MODAL: 1545 return !w.isModalExcluded(ModalExclusionType.TOOLKIT_EXCLUDE); 1546 } 1547 1548 return false; 1549 } 1550 1551 /* 1552 * Adds the given top-level window to the list of blocked 1553 * windows for this dialog and marks it as modal blocked. 1554 * If the window is already blocked by some modal dialog, 1555 * does nothing. 1556 */ 1557 void blockWindow(Window w) { 1558 if (!w.isModalBlocked()) { 1559 w.setModalBlocked(this, true, true); 1560 blockedWindows.add(w); 1561 } 1562 } 1563 1564 void blockWindows(java.util.List<Window> toBlock) { 1565 DialogPeer dpeer = (DialogPeer)peer; 1566 if (dpeer == null) { 1567 return; 1568 } 1569 Iterator<Window> it = toBlock.iterator(); 1570 while (it.hasNext()) { 1571 Window w = it.next(); 1572 if (!w.isModalBlocked()) { 1573 w.setModalBlocked(this, true, false); 1574 } else { 1575 it.remove(); 1576 } 1577 } 1578 dpeer.blockWindows(toBlock); 1579 blockedWindows.addAll(toBlock); 1580 } 1581 1582 /* 1583 * Removes the given top-level window from the list of blocked 1584 * windows for this dialog and marks it as unblocked. If the 1585 * window is not modal blocked, does nothing. 1586 */ 1587 void unblockWindow(Window w) { 1588 if (w.isModalBlocked() && blockedWindows.contains(w)) { 1589 blockedWindows.remove(w); 1590 w.setModalBlocked(this, false, true); 1591 } 1592 } 1593 1594 /* 1595 * Checks if any other modal dialog D blocks the given window. 1596 * If such D exists, mark the window as blocked by D. 1597 */ 1598 static void checkShouldBeBlocked(Window w) { 1599 synchronized (w.getTreeLock()) { 1600 for (int i = 0; i < modalDialogs.size(); i++) { 1601 Dialog modalDialog = modalDialogs.get(i); 1602 if (modalDialog.shouldBlock(w)) { 1603 modalDialog.blockWindow(w); 1604 break; 1605 } 1606 } 1607 } 1608 } 1609 1610 private void checkModalityPermission(ModalityType mt) { 1611 if (mt == ModalityType.TOOLKIT_MODAL) { 1612 SecurityManager sm = System.getSecurityManager(); 1613 if (sm != null) { 1614 sm.checkPermission(AWTPermissions.TOOLKIT_MODALITY_PERMISSION); 1615 } 1616 } 1617 } 1618 1619 private void readObject(ObjectInputStream s) 1620 throws ClassNotFoundException, IOException, HeadlessException 1621 { 1622 GraphicsEnvironment.checkHeadless(); 1623 1624 java.io.ObjectInputStream.GetField fields = 1625 s.readFields(); 1626 1627 ModalityType localModalityType = (ModalityType)fields.get("modalityType", null); 1628 1629 try { 1630 checkModalityPermission(localModalityType); 1631 } catch (AccessControlException ace) { 1632 localModalityType = DEFAULT_MODALITY_TYPE; 1633 } 1634 1635 // in 1.5 or earlier modalityType was absent, so use "modal" instead 1636 if (localModalityType == null) { 1637 this.modal = fields.get("modal", false); 1638 setModal(modal); 1639 } else { 1640 this.modalityType = localModalityType; 1641 } 1642 1643 this.resizable = fields.get("resizable", true); 1644 this.undecorated = fields.get("undecorated", false); 1645 this.title = (String)fields.get("title", ""); 1646 1647 blockedWindows = new IdentityArrayList<>(); 1648 1649 SunToolkit.checkAndSetPolicy(this); 1650 1651 initialized = true; 1652 1653 } 1654 1655 /* 1656 * --- Accessibility Support --- 1657 * 1658 */ 1659 1660 /** 1661 * Gets the AccessibleContext associated with this Dialog. 1662 * For dialogs, the AccessibleContext takes the form of an 1663 * AccessibleAWTDialog. 1664 * A new AccessibleAWTDialog instance is created if necessary. 1665 * 1666 * @return an AccessibleAWTDialog that serves as the 1667 * AccessibleContext of this Dialog 1668 * @since 1.3 1669 */ 1670 public AccessibleContext getAccessibleContext() { 1671 if (accessibleContext == null) { 1672 accessibleContext = new AccessibleAWTDialog(); 1673 } 1674 return accessibleContext; 1675 } 1676 1677 /** 1678 * This class implements accessibility support for the 1679 * <code>Dialog</code> class. It provides an implementation of the 1680 * Java Accessibility API appropriate to dialog user-interface elements. 1681 * @since 1.3 1682 */ 1683 protected class AccessibleAWTDialog extends AccessibleAWTWindow 1684 { 1685 /* 1686 * JDK 1.3 serialVersionUID 1687 */ 1688 private static final long serialVersionUID = 4837230331833941201L; 1689 1690 /** 1691 * Get the role of this object. 1692 * 1693 * @return an instance of AccessibleRole describing the role of the 1694 * object 1695 * @see AccessibleRole 1696 */ 1697 public AccessibleRole getAccessibleRole() { 1698 return AccessibleRole.DIALOG; 1699 } 1700 1701 /** 1702 * Get the state of this object. 1703 * 1704 * @return an instance of AccessibleStateSet containing the current 1705 * state set of the object 1706 * @see AccessibleState 1707 */ 1708 public AccessibleStateSet getAccessibleStateSet() { 1709 AccessibleStateSet states = super.getAccessibleStateSet(); 1710 if (getFocusOwner() != null) { 1711 states.add(AccessibleState.ACTIVE); 1712 } 1713 if (isModal()) { 1714 states.add(AccessibleState.MODAL); 1715 } 1716 if (isResizable()) { 1717 states.add(AccessibleState.RESIZABLE); 1718 } 1719 return states; 1720 } 1721 1722 } // inner class AccessibleAWTDialog 1723 }