/*
* @(#)Dialog.java 1.62 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
package java.awt;
import java.awt.event.*;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
/**
* A dialog component is a top level window, . It resembles a
* frame, but has fewer properties. It does not have an icon or
* a settable cursor. In PersonalJava and Personal Profile
* implementations, the display of the title is optional.
* <p>
* A modal dialog, when visible, prevents the user from interacting
* with AWT components. A modeless dialog behaves more like a Frame.
* A Personal Profile Implementation must support modal dialogs.
* Multiple (nested) Modal Dialogs may be implemented so that only
* a single dialog is visible at a time: when a new modal is shown,
* it must become visible, and when it is dismissed, the previous modal
* dialog must be shown.
* <p>
* Nonmodal dialogs are optional in a Personal Profile implementation.
* If they are not supported, an <em> UnsupportedOperationException </em> is
* thrown when the consturctor is called and the system property
* <em> java.awt.dialog.SupportsNonmodal </em> is set to "false".
* <p>
* The modality of a dialog cannot be changed after the dialog has been created.
* <h3>System Properties</h3>
* The following system properties will be set to either <code>"true"</code> or <code>"false"</code>
* indicating which optional dialog features are supported by the Personal
* Profile implementation:
* <li>java.awt.dialog.SupportsNonmodal
* <li>java.awt.dialog.SupportsMultipleModal
* <li>java.awt.dialog.SupportsResize
* <li>java.awt.dialog.SupportsTitle
* @see WindowEvent
* @see Window#addWindowListener
*
* @version 1.46, 03/12/01
* @author Sami Shaio
* @author Arthur van Hoff
* @since JDK1.0
*/
public class Dialog extends Window {
boolean resizable = true;
/**
* Sets to true if the Dialog is modal. A modal
* Dialog grabs all the input to the parent frame from the user.
*/
boolean modal;
/**
* The title of the Dialog.
*/
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;
/**
* Creates a dialog.
* @param parent the non null parent of the dialog
* @see Component#setSize
* @see Component#setVisible
* @exception UnsupportedOperationException If the implementation does not support
* modeless dialogs.
* @exception IllegalArgumentException if the parent in null
* @since JDK1.0
*/
public Dialog(Frame parent) {
this(parent, "", false);
}
/**
* Creates a dialog.
* @param parent the non null parent of the dialog
* @param modal the modality of the dialog. If true the dialog is modal,
* otherwise it is modeless. If the implementation does not
* support modeless dialogs and modal is false, an
* <em>UnsupportedOperationException</em> should be thrown.
* @see Component#setSize
* @see Component#setVisible
* @exception UnsupportedOperationException If the implementation does not support
* modeless dialogs.
* @exception IllegalArgumentException if the parent in null
* @since JDK1.0
*/
public Dialog(Frame parent, boolean modal) {
this(parent, "", modal);
}
/**
* Creates a dialog.
* @param parent the non null parent of the dialog
* @param title the title of the dialog
* @see Component#setSize
* @see Component#setVisible
* @exception UnsupportedOperationException If the implementation does not support
* modeless dialogs.
* @exception IllegalArgumentException if the parent in null
* @since JDK1.0
*/
public Dialog(Frame parent, String title) {
this(parent, title, false);
}
/**
* Creates a dialog.
* @param parent the non null parent of the dialog
* @param title the title of the dialog
* @param modal the modality of the dialog. If true the dialog is modal,
* otherwise it is modeless. If the implementation does not
* support modeless dialogs and modal is false, an
* <em>UnsupportedOperationException</em> should be thrown.
* @see Component#setSize
* @see Component#setVisible
* @exception UnsupportedOperationException If the implementation does not support
* modeless dialogs.
* @exception IllegalArgumentException if the parent in null
* @since JDK1.0
*/
public Dialog(Frame parent, String title, boolean modal) {
super(parent);
if (parent == null) {
throw new IllegalArgumentException("null parent frame");
}
this.title = title;
setModal(modal);
}
/**
* Construct a name for this component. Called by getName() when the
* name is null.
*/
String constructComponentName() {
return base + nameCounter++;
}
/**
* Creates the dialog's peer. The peer allows us to change the appearance
* of the frame without changing its functionality.
* @since JDK1.0
*/
// public void addNotify() {
// synchronized (getTreeLock()) {
// if (peer == null) {
// peer = ((PeerBasedToolkit)getToolkit()).createDialog(this);
// }
// super.addNotify();
// }
// }
/**
* Indicates whether the dialog is modal.
* A modal dialog grabs all input from the user.
* @return <code>true</code> if this dialog window is modal;
* <code>false</code> otherwise.
* @see java.awt.Dialog#setModal
* @since JDK1.0
*/
public boolean isModal() {
return modal;
}
/**
* Specifies the modality of the dialog.
* This method sets the modal property as specified by modal. A
* Personal Profile implementation may optionally support non-modal
* dialogs or not allow the modal property to be changed after the
* dialog is created. isModal() may be called to verify the setting
* of the modal property.
* @param <code>modal</code> desired modality for the dialog
* @see java.awt.Dialog#isModal
* @since JDK1.1
*/
public void setModal(boolean modal) {
this.modal = modal;
DialogXWindow xwindow = (DialogXWindow) this.xwindow;
if (xwindow != null)
xwindow.setModal(modal);
}
/**
* Gets the title of the dialog.
* @return the title of this dialog window.
* @see java.awt.Dialog#setTitle
* @since JDK1.0
*/
public String getTitle() {
return title;
}
/**
* Sets the title of the Dialog.
* @param title the new title being given to the dialog
* @see #getTitle
* @since JDK1.0
*/
public synchronized void setTitle(String title) {
this.title = title;
DialogXWindow xwindow = (DialogXWindow) this.xwindow;
if (xwindow != null)
xwindow.setTitle(title);
}
ComponentXWindow createXWindow() {
return new DialogXWindow(this);
}
/**
* @return true if we actually showed, false if we just called toFront()
*/
private boolean conditionalShow() {
boolean retval;
synchronized (getTreeLock()) {
if (xwindow == null) {
addNotify();
}
validate();
if (visible) {
toFront();
retval = false;
} else {
visible = retval = true;
xwindow.map(); // now guaranteed never to block
// createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
// this, parent,
// HierarchyEvent.SHOWING_CHANGED);
}
if (retval && (componentListener != null ||
(eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)) {
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;
}
/**
* Makes this dialog visible and in front of all windows.
* This method calls the dialog's addNotify() method,
* validates the dialog's layout, and makes the dialog visible.
* <p>
* If the dialog is modal, show() will not return until the
* dialog is no longer visible.
* <p>
* A Personal Profile or Personal Java implementation is not
* required to support multiple modal dialogs. In this case, if
* there is a previous modal dialog being shown, it can be hidden
* until this Dialog is made invisible via setVisible() or dispose().
* This must work recursively to allow for multiple nested modal dialogs.
* @see Component#setVisible
* @since JDK1.0
*/
public void show() {
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;
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.
if (Toolkit.getEventQueue().isDispatchThread()) {
EventDispatchThread dispatchThread =
(EventDispatchThread) Thread.currentThread();
dispatchThread.pumpEvents(new Conditional() {
public boolean evaluate() {
return keepBlocking && windowClosingException == null;
}
}
);
} else {
synchronized (getTreeLock()) {
while (keepBlocking && windowClosingException == null) {
try {
getTreeLock().wait();
} catch (InterruptedException e) {
break;
}
}
}
}
if (windowClosingException != null) {
windowClosingException.fillInStackTrace();
throw windowClosingException;
}
}
}
}
private void hideAndDisposeHandler() {
if (keepBlocking) {
synchronized (getTreeLock()) {
keepBlocking = false;
EventQueue.invokeLater(new Runnable() {
public void run() {}
}
);
getTreeLock().notifyAll();
}
}
}
/**
* Hides the Dialog and then causes show() to return if it is currently
* blocked.
*/
public void hide() {
super.hide();
hideAndDisposeHandler();
}
/**
* Disposes the Dialog and then causes show() to return if it is currently
* blocked.
*/
public void dispose() {
super.dispose();
hideAndDisposeHandler();
}
/**
* Indicates whether this dialog window is resizable.
* @return <code>true</code> if the user can resize the dialog;
* <code>false</code> otherwise.
* @see java.awt.Dialog#setResizable
* @since JDK1.0
*/
public boolean isResizable() {
return resizable;
}
/**
* Sets the Resizable property of the dialog.
* This method sets the resizable property of the dialog. A
* dilaog that is resizable may be resized by the user. In Personal
* Profile, this method may have no effect, it may be verified with
* the isResizable() method.
* @param resizable <code>true</code> if the user can
* resize this dialog; <code>false</code> otherwise.
* @see java.awt.Dialog#isResizable
* @since JDK1.0
*/
public synchronized void setResizable(boolean resizable) {
this.resizable = resizable;
DialogXWindow xwindow = (DialogXWindow) this.xwindow;
if (xwindow != null)
xwindow.setResizable(resizable);
}
/**
* Returns the parameter string representing the state of this
* dialog window. This string is useful for debugging.
* @return the parameter string of this dialog window.
* @since JDK1.0
*/
protected String paramString() {
String str = super.paramString() + (modal ? ",modal" : ",modeless");
if (title != null) {
str += ",title=" + title;
}
return str;
}
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException {
s.defaultReadObject();
setModal(this.modal);
}
}