/* * @(#)Dialog.java 1.100 05/10/19 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package java.awt; import java.awt.peer.DialogPeer; import java.awt.event.*; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; import javax.accessibility.*; import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.PeerEvent; import java.security.AccessController; import java.security.PrivilegedAction; /** * A Dialog is a top-level window with a title and a border * that is typically used to take some form of input from the user. * * The size of the dialog includes any area designated for the * border. The dimensions of the border area can be obtained * using the getInsets method, however, since * these dimensions are platform-dependent, a valid insets * value cannot be obtained until the dialog is made displayable * by either calling pack or show. * Since the border area is included in the overall size of the * dialog, the border effectively obscures a portion of the dialog, * constraining the area available for rendering and/or displaying * subcomponents to the rectangle which has an upper-left corner * location of (insets.left, insets.top), and has a size of * width - (insets.left + insets.right) by * height - (insets.top + insets.bottom). *

* The default layout for a dialog is BorderLayout. *

* A dialog may have its native decorations (i.e. Frame & Titlebar) turned off * with setUndecorated. This can only be done while the dialog * is not {@link Component#isDisplayable() displayable}. *

* A dialog must have either a frame or another dialog defined as its * owner when it's constructed. When the owner window of a visible dialog * is minimized, the dialog will automatically be hidden * from the user. When the owner window is subsequently restored, * the dialog is made visible to the user again. *

* In a multi-screen environment, you can create a Dialog * on a different screen device than its owner. See {@link java.awt.Frame} for * more information. *

* A dialog can be either modeless (the default) or modal. A modal * dialog is one which blocks input to all other toplevel windows * in the application, except for any windows created with the dialog * as their owner. *

* Dialogs are capable of generating the following * WindowEvents: * WindowOpened, WindowClosing, * WindowClosed, WindowActivated, * WindowDeactivated, WindowGainedFocus, * WindowLostFocus. * * @see WindowEvent * @see Window#addWindowListener * * @version 1.100, 10/19/05 * @author Sami Shaio * @author Arthur van Hoff * @since JDK1.0 */ public class Dialog extends Window { static { /* ensure that the necessary native libraries are loaded */ Toolkit.loadLibraries(); if (!GraphicsEnvironment.isHeadless()) { initIDs(); } } /** * A dialog's resizable property. Will be true * if the Dialog is to be resizable, otherwise * it will be false. * * @serial * @see #setResizable(boolean) */ boolean resizable = true; /** * This field indicates whether the dialog is undecorated. * This property can only be changed while the dialog is not displayable. * undecorated will be true if the dialog is * undecorated, otherwise it will be false. * * @serial * @see #setUndecorated(boolean) * @see #isUndecorated() * @see Component#isDisplayable() * @since 1.4 */ boolean undecorated = false; /** * Will be true if the Dialog is modal, * otherwise the dialog will be modeless. * A modal Dialog grabs all the input to * the owner frame from the user. * * @serial * @see #isModal() * @see #setModal(boolean) */ boolean modal; /** * Specifies the title of the Dialog. * This field can be null. * * @serial * @see #getTitle() * @see #setTitle(String) */ String title; private transient boolean keepBlocking = false; private static final String base = "dialog"; private static int nameCounter = 0; /* * JDK 1.1 serialVersionUID */ private static final long serialVersionUID = 5920926903803293709L; /** * Constructs an initially invisible, non-modal Dialog with * an empty title and the specified owner frame. * * @param owner the owner of the dialog * @exception IllegalArgumentException if the owner's * GraphicsConfiguration is not from a screen device * @exception java.lang.IllegalArgumentException if owner * is null; this exception is always thrown * when GraphicsEnvironment.isHeadless * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize * @see Component#setVisible */ public Dialog(Frame owner) { this(owner, "", false); } /** * Constructs an initially invisible Dialog with an empty title, * the specified owner frame and modality. * * @param owner the owner of the dialog * @param modal if true, dialog blocks input to other * app windows when shown * @exception IllegalArgumentException if the owner's * GraphicsConfiguration is not from a screen device * @exception java.lang.IllegalArgumentException if owner * is null; this exception is always thrown * when GraphicsEnvironment.isHeadless * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ public Dialog(Frame owner, boolean modal) { this(owner, "", modal); } /** * Constructs an initially invisible, non-modal Dialog with * the specified owner frame and title. * * @param owner the owner of the dialog * @param title the title of the dialog; a null value * will be accepted without causing a * NullPointerException to be thrown * @exception IllegalArgumentException if the owner's * GraphicsConfiguration is not from a screen device * @exception java.lang.IllegalArgumentException if owner * is null; this exception is always thrown * when GraphicsEnvironment.isHeadless * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize * @see Component#setVisible */ public Dialog(Frame owner, String title) { this(owner, title, false); } /** * Constructs an initially invisible Dialog with the * specified owner frame, title, and modality. * * @param owner the owner of the dialog * @param title the title of the dialog; a null value * will be accepted without causing a * NullPointerException to be thrown * @param modal if true, dialog blocks input to other app windows when shown * @exception IllegalArgumentException if the owner's * GraphicsConfiguration is not from a screen device * @exception java.lang.IllegalArgumentException if owner * is null. This exception is always thrown * when GraphicsEnvironment.isHeadless * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize * @see Component#setVisible */ public Dialog(Frame owner, String title, boolean modal) { super(owner); this.title = title; this.modal = modal; SunToolkit.checkAndSetPolicy(this, false); } /** * Constructs an initially invisible Dialog with the * specified owner frame, title, modality, and * GraphicsConfiguration. * @param owner the owner of the dialog * @param title the title of the dialog. A null value * will be accepted without causing a NullPointerException * to be thrown. * @param modal if true, dialog blocks input to other app windows when shown * @param gc the GraphicsConfiguration * of the target screen device. If gc is * null, the same * GraphicsConfiguration as the owning Frame is used. * @exception java.lang.IllegalArgumentException if owner * is null. This exception is always thrown * when GraphicsEnvironment.isHeadless() returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize * @see Component#setVisible * @since 1.4 */ public Dialog(Frame owner, String title, boolean modal, GraphicsConfiguration gc) { super(owner, gc); this.title = title; this.modal = modal; SunToolkit.checkAndSetPolicy(this, false); } /** * Constructs an initially invisible, non-modal Dialog with * an empty title and the specified owner dialog. * @param owner the owner of the dialog * @exception java.lang.IllegalArgumentException if owner * is null. This exception is always thrown * when GraphicsEnvironment.isHeadless() returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 */ public Dialog(Dialog owner) { this(owner, "", false); } /** * Constructs an initially invisible, non-modal Dialog * with the specified owner dialog and title. * @param owner the owner of the dialog * @param title the title of the dialog. A null value * will be accepted without causing a NullPointerException * to be thrown. * @exception java.lang.IllegalArgumentException if owner * is null. This exception is always thrown * when GraphicsEnvironment.isHeadless() returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 */ public Dialog(Dialog owner, String title) { this(owner, title, false); } /** * Constructs an initially invisible Dialog with the * specified owner dialog, title, and modality. * * @param owner the owner of the dialog * @exception IllegalArgumentException if the owner's * GraphicsConfiguration is not from a screen device * @param title the title of the dialog; a null value * will be accepted without causing a * NullPointerException to be thrown * @param modal if true, dialog blocks input to other app windows when shown * @exception java.lang.IllegalArgumentException if owner * is null; this exception is always thrown * when GraphicsEnvironment.isHeadless * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 */ public Dialog(Dialog owner, String title, boolean modal) { super(owner); this.title = title; this.modal = modal; SunToolkit.checkAndSetPolicy(this, false); } /** * Constructs an initially invisible Dialog with the * specified owner dialog, title, modality, and * GraphicsConfiguration. * * @param owner the owner of the dialog * @param title the title of the dialog; a null value * will be accepted without causing a * NullPointerException to be thrown * @param modal if true, dialog blocks input to other app windows when shown * @param gc the GraphicsConfiguration * of the target screen device; if gc is * null, the same * GraphicsConfiguration as the owning Dialog is used * @exception IllegalArgumentException if the owner's * GraphicsConfiguration is not from a screen device * @exception java.lang.IllegalArgumentException if owner * is null; this exception is always thrown * when GraphicsEnvironment.isHeadless * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize * @see Component#setVisible * @since 1.4 */ public Dialog(Dialog owner, String title, boolean modal, GraphicsConfiguration gc) { super(owner, gc); this.title = title; this.modal = modal; SunToolkit.checkAndSetPolicy(this, false); } /** * Construct a name for this component. Called by getName() when the * name is null. */ String constructComponentName() { synchronized (getClass()) { return base + nameCounter++; } } /** * Makes this Dialog displayable by connecting it to * a native screen resource. Making a dialog displayable will * cause any of its children to be made displayable. * This method is called internally by the toolkit and should * not be called directly by programs. * @see Component#isDisplayable * @see #removeNotify */ public void addNotify() { synchronized (getTreeLock()) { if (parent != null && parent.getPeer() == null) { parent.addNotify(); } if (peer == null) { peer = getToolkit().createDialog(this); } super.addNotify(); } } /** * Indicates whether the dialog is modal. * When a modal Dialog is made visible, user input will be * blocked to the other windows in the application, except for * any windows created with this dialog as their owner. * * @return true if this dialog window is modal; * false otherwise. * @see java.awt.Dialog#setModal */ public boolean isModal() { return modal; } /** * Specifies whether this dialog should be modal. * @see java.awt.Dialog#isModal * @since JDK1.1 */ public void setModal(boolean b) { this.modal = b; } /** * Gets the title of the dialog. The title is displayed in the * dialog's border. * @return the title of this dialog window. The title may be * null. * @see java.awt.Dialog#setTitle */ public String getTitle() { return title; } /** * Sets the title of the Dialog. * @param title the title displayed in the dialog's border; * a null value results in an empty title * @see #getTitle */ public void setTitle(String title) { String oldTitle = this.title; synchronized(this) { this.title = title; DialogPeer peer = (DialogPeer)this.peer; if (peer != null) { peer.setTitle(title); } } firePropertyChange("title", oldTitle, title); } /** * @return true if we actually showed, false if we just called toFront() */ private boolean conditionalShow() { boolean retval; synchronized (getTreeLock()) { if (peer == null) { addNotify(); } validate(); if (visible) { toFront(); retval = false; } else { visible = retval = true; peer.show(); // now guaranteed never to block createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, this, parent, HierarchyEvent.SHOWING_CHANGED, Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); } if (retval && (componentListener != null || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK))) { ComponentEvent e = new ComponentEvent(this, ComponentEvent.COMPONENT_SHOWN); Toolkit.getEventQueue().postEvent(e); } } if (retval && (state & OPENED) == 0) { postWindowEvent(WindowEvent.WINDOW_OPENED); state |= OPENED; } return retval; } /** * Stores the app context on which event dispatch thread the dialog * is being shown. Initialized in show(), used in hideAndDisposeHandler() */ transient private AppContext showAppContext; /** * @deprecated As of JDK version 1.5, replaced by * {@link Component#setVisible(boolean) Component.setVisible(boolean)}. */ @Deprecated public void show() { beforeFirstShow = false; if (!isModal()) { conditionalShow(); } else { // Set this variable before calling conditionalShow(). That // way, if the Dialog is hidden right after being shown, we // won't mistakenly block this thread. keepBlocking = true; // Store the app context on which this dialog is being shown. // Event dispatch thread of this app context will be sleeping until // we wake it by any event from hideAndDisposeHandler(). showAppContext = AppContext.getAppContext(); // keep the KeyEvents from being dispatched // until the focus has been transfered long time = Toolkit.getEventQueue().getMostRecentEventTimeEx(); Component predictedFocusOwner = getMostRecentFocusOwner(); KeyboardFocusManager.getCurrentKeyboardFocusManager(). enqueueKeyEvents(time, predictedFocusOwner); try { if (conditionalShow()) { // We have two mechanisms for blocking: 1. If we're on the // EventDispatchThread, start a new event pump. 2. If we're // on any other thread, call wait() on the treelock. final Runnable pumpEventsForHierarchy = new Runnable() { public void run() { EventDispatchThread dispatchThread = (EventDispatchThread)Thread.currentThread(); dispatchThread.pumpEventsForHierarchy(new Conditional() { public boolean evaluate() { return keepBlocking && windowClosingException == null; } }, Dialog.this); } }; if (EventQueue.isDispatchThread()) { /* * dispose SequencedEvent we are dispatching on current * AppContext, to prevent us from hang. * * BugId 4531693 (son@sparc.spb.su) */ SequencedEvent currentSequencedEvent = KeyboardFocusManager. getCurrentKeyboardFocusManager().getCurrentSequencedEvent(); if (currentSequencedEvent != null) { currentSequencedEvent.dispose(); } /* * Event processing is done inside doPrivileged block so that * it wouldn't matter even if user code is on the stack * Fix for BugId 6300270 */ AccessController.doPrivileged(new PrivilegedAction() { public Object run() { pumpEventsForHierarchy.run(); return null; } }); } else { synchronized (getTreeLock()) { Toolkit.getEventQueue(). postEvent(new PeerEvent(this, pumpEventsForHierarchy, PeerEvent.PRIORITY_EVENT)); while (keepBlocking && windowClosingException == null) { try { getTreeLock().wait(); } catch (InterruptedException e) { break; } } } } if (windowClosingException != null) { windowClosingException.fillInStackTrace(); throw windowClosingException; } } } finally { // Restore normal key event dispatching KeyboardFocusManager.getCurrentKeyboardFocusManager(). dequeueKeyEvents(time, predictedFocusOwner); } } } void interruptBlocking() { if (modal) { disposeImpl(); } else if (windowClosingException != null) { windowClosingException.fillInStackTrace(); windowClosingException.printStackTrace(); windowClosingException = null; } } final static class WakingRunnable implements Runnable { public void run() { } } private void hideAndDisposeHandler() { if (keepBlocking) { synchronized (getTreeLock()) { keepBlocking = false; if (showAppContext != null) { // Wake up event dispatch thread on which the dialog was // initially shown SunToolkit.postEvent(showAppContext, new PeerEvent(this, new WakingRunnable(), PeerEvent.PRIORITY_EVENT)); showAppContext = null; } EventQueue.invokeLater(new WakingRunnable()); getTreeLock().notifyAll(); } } } /** * @deprecated As of JDK version 1.5, replaced by * {@link Component#setVisible(boolean) Component.setVisible(boolean)}. */ @Deprecated public void hide() { super.hide(); hideAndDisposeHandler(); } /** * Disposes the Dialog and then causes show() to return if it is currently * blocked. */ void doDispose() { super.doDispose(); hideAndDisposeHandler(); } /** * Indicates whether this dialog is resizable by the user. * @return true if the user can resize the dialog; * false otherwise. * @see java.awt.Dialog#setResizable */ public boolean isResizable() { return resizable; } /** * Sets whether this dialog is resizable by the user. * @param resizable true if the user can * resize this dialog; false otherwise. * @see java.awt.Dialog#isResizable */ public void setResizable(boolean resizable) { boolean testvalid = false; synchronized (this) { this.resizable = resizable; DialogPeer peer = (DialogPeer)this.peer; if (peer != null) { peer.setResizable(resizable); testvalid = true; } } // On some platforms, changing the resizable state affects // the insets of the Dialog. If we could, we'd call invalidate() // from the peer, but we need to guarantee that we're not holding // the Dialog lock when we call invalidate(). if (testvalid && valid) { invalidate(); } } /** * Disables or enables decorations for this dialog. * This method can only be called while the dialog is not displayable. * @param undecorated true if no dialog decorations are * to be enabled; * false if dialog decorations are to be enabled. * @throws IllegalComponentStateException if the dialog * is displayable. * @see #isUndecorated * @see Component#isDisplayable * @since 1.4 */ public void setUndecorated(boolean undecorated) { /* Make sure we don't run in the middle of peer creation.*/ synchronized (getTreeLock()) { if (isDisplayable()) { throw new IllegalComponentStateException("The dialog is displayable."); } this.undecorated = undecorated; } } /** * Indicates whether this dialog is undecorated. * By default, all dialogs are initially decorated. * @return true if dialog is undecorated; * false otherwise. * @see java.awt.Dialog#setUndecorated * @since 1.4 */ public boolean isUndecorated() { return undecorated; } /** * Returns a string representing the state of this dialog. This * method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be * null. * * @return the parameter string of this dialog window. */ protected String paramString() { String str = super.paramString() + (modal ? ",modal" : ",modeless"); if (title != null) { str += ",title=" + title; } return str; } /** * Initialize JNI field and method IDs */ private static native void initIDs(); /* * --- Accessibility Support --- * */ /** * Gets the AccessibleContext associated with this Dialog. * For dialogs, the AccessibleContext takes the form of an * AccessibleAWTDialog. * A new AccessibleAWTDialog instance is created if necessary. * * @return an AccessibleAWTDialog that serves as the * AccessibleContext of this Dialog */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) { accessibleContext = new AccessibleAWTDialog(); } return accessibleContext; } /** * This class implements accessibility support for the * Dialog class. It provides an implementation of the * Java Accessibility API appropriate to dialog user-interface elements. */ protected class AccessibleAWTDialog extends AccessibleAWTWindow { /* * JDK 1.3 serialVersionUID */ private static final long serialVersionUID = 4837230331833941201L; /** * Get the role of this object. * * @return an instance of AccessibleRole describing the role of the * object * @see AccessibleRole */ public AccessibleRole getAccessibleRole() { return AccessibleRole.DIALOG; } /** * Get the state of this object. * * @return an instance of AccessibleStateSet containing the current * state set of the object * @see AccessibleState */ public AccessibleStateSet getAccessibleStateSet() { AccessibleStateSet states = super.getAccessibleStateSet(); if (getFocusOwner() != null) { states.add(AccessibleState.ACTIVE); } if (isModal()) { states.add(AccessibleState.MODAL); } if (isResizable()) { states.add(AccessibleState.RESIZABLE); } return states; } } // inner class AccessibleAWTDialog }