001: /*
002: * @(#)Dialog.java 1.62 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027: package java.awt;
028:
029: import java.awt.event.*;
030: import java.io.ObjectOutputStream;
031: import java.io.ObjectInputStream;
032: import java.io.IOException;
033:
034: /**
035: * A dialog component is a top level window, . It resembles a
036: * frame, but has fewer properties. It does not have an icon or
037: * a settable cursor. In PersonalJava and Personal Profile
038: * implementations, the display of the title is optional.
039: * <p>
040: * A modal dialog, when visible, prevents the user from interacting
041: * with AWT components. A modeless dialog behaves more like a Frame.
042: * A Personal Profile Implementation must support modal dialogs.
043: * Multiple (nested) Modal Dialogs may be implemented so that only
044: * a single dialog is visible at a time: when a new modal is shown,
045: * it must become visible, and when it is dismissed, the previous modal
046: * dialog must be shown.
047: * <p>
048: * Nonmodal dialogs are optional in a Personal Profile implementation.
049: * If they are not supported, an <em> UnsupportedOperationException </em> is
050: * thrown when the consturctor is called and the system property
051: * <em> java.awt.dialog.SupportsNonmodal </em> is set to "false".
052: * <p>
053: * The modality of a dialog cannot be changed after the dialog has been created.
054: * <h3>System Properties</h3>
055: * The following system properties will be set to either <code>"true"</code> or <code>"false"</code>
056: * indicating which optional dialog features are supported by the Personal
057: * Profile implementation:
058: * <li>java.awt.dialog.SupportsNonmodal
059: * <li>java.awt.dialog.SupportsMultipleModal
060: * <li>java.awt.dialog.SupportsResize
061: * <li>java.awt.dialog.SupportsTitle
062: * @see WindowEvent
063: * @see Window#addWindowListener
064: *
065: * @version 1.46, 03/12/01
066: * @author Sami Shaio
067: * @author Arthur van Hoff
068: * @since JDK1.0
069: */
070: public class Dialog extends Window {
071: boolean resizable = true;
072: /**
073: * Sets to true if the Dialog is modal. A modal
074: * Dialog grabs all the input to the parent frame from the user.
075: */
076: boolean modal;
077: /**
078: * The title of the Dialog.
079: */
080: String title;
081: private transient boolean keepBlocking = false;
082: private static final String base = "dialog";
083: private static int nameCounter = 0;
084: /*
085: * JDK 1.1 serialVersionUID
086: */
087: private static final long serialVersionUID = 5920926903803293709L;
088:
089: /**
090: * Creates a dialog.
091: * @param parent the non null parent of the dialog
092: * @see Component#setSize
093: * @see Component#setVisible
094: * @exception UnsupportedOperationException If the implementation does not support
095: * modeless dialogs.
096: * @exception IllegalArgumentException if the parent in null
097: * @since JDK1.0
098: */
099: public Dialog(Frame parent) {
100: this (parent, "", false);
101: }
102:
103: /**
104: * Creates a dialog.
105: * @param parent the non null parent of the dialog
106: * @param modal the modality of the dialog. If true the dialog is modal,
107: * otherwise it is modeless. If the implementation does not
108: * support modeless dialogs and modal is false, an
109: * <em>UnsupportedOperationException</em> should be thrown.
110: * @see Component#setSize
111: * @see Component#setVisible
112: * @exception UnsupportedOperationException If the implementation does not support
113: * modeless dialogs.
114: * @exception IllegalArgumentException if the parent in null
115: * @since JDK1.0
116: */
117: public Dialog(Frame parent, boolean modal) {
118: this (parent, "", modal);
119: }
120:
121: /**
122: * Creates a dialog.
123: * @param parent the non null parent of the dialog
124: * @param title the title of the dialog
125: * @see Component#setSize
126: * @see Component#setVisible
127: * @exception UnsupportedOperationException If the implementation does not support
128: * modeless dialogs.
129: * @exception IllegalArgumentException if the parent in null
130: * @since JDK1.0
131: */
132: public Dialog(Frame parent, String title) {
133: this (parent, title, false);
134: }
135:
136: /**
137: * Creates a dialog.
138: * @param parent the non null parent of the dialog
139: * @param title the title of the dialog
140: * @param modal the modality of the dialog. If true the dialog is modal,
141: * otherwise it is modeless. If the implementation does not
142: * support modeless dialogs and modal is false, an
143: * <em>UnsupportedOperationException</em> should be thrown.
144: * @see Component#setSize
145: * @see Component#setVisible
146: * @exception UnsupportedOperationException If the implementation does not support
147: * modeless dialogs.
148: * @exception IllegalArgumentException if the parent in null
149: * @since JDK1.0
150: */
151: public Dialog(Frame parent, String title, boolean modal) {
152: super (parent);
153: if (parent == null) {
154: throw new IllegalArgumentException("null parent frame");
155: }
156: this .title = title;
157: setModal(modal);
158: }
159:
160: /**
161: * Construct a name for this component. Called by getName() when the
162: * name is null.
163: */
164: String constructComponentName() {
165: return base + nameCounter++;
166: }
167:
168: /**
169: * Creates the dialog's peer. The peer allows us to change the appearance
170: * of the frame without changing its functionality.
171: * @since JDK1.0
172: */
173:
174: // public void addNotify() {
175: // synchronized (getTreeLock()) {
176: // if (peer == null) {
177: // peer = ((PeerBasedToolkit)getToolkit()).createDialog(this);
178: // }
179: // super.addNotify();
180: // }
181: // }
182: /**
183: * Indicates whether the dialog is modal.
184: * A modal dialog grabs all input from the user.
185: * @return <code>true</code> if this dialog window is modal;
186: * <code>false</code> otherwise.
187: * @see java.awt.Dialog#setModal
188: * @since JDK1.0
189: */
190: public boolean isModal() {
191: return modal;
192: }
193:
194: /**
195: * Specifies the modality of the dialog.
196: * This method sets the modal property as specified by modal. A
197: * Personal Profile implementation may optionally support non-modal
198: * dialogs or not allow the modal property to be changed after the
199: * dialog is created. isModal() may be called to verify the setting
200: * of the modal property.
201: * @param <code>modal</code> desired modality for the dialog
202: * @see java.awt.Dialog#isModal
203: * @since JDK1.1
204: */
205: public void setModal(boolean modal) {
206: this .modal = modal;
207: DialogXWindow xwindow = (DialogXWindow) this .xwindow;
208: if (xwindow != null)
209: xwindow.setModal(modal);
210: }
211:
212: /**
213: * Gets the title of the dialog.
214: * @return the title of this dialog window.
215: * @see java.awt.Dialog#setTitle
216: * @since JDK1.0
217: */
218: public String getTitle() {
219: return title;
220: }
221:
222: /**
223: * Sets the title of the Dialog.
224: * @param title the new title being given to the dialog
225: * @see #getTitle
226: * @since JDK1.0
227: */
228: public synchronized void setTitle(String title) {
229: this .title = title;
230: DialogXWindow xwindow = (DialogXWindow) this .xwindow;
231: if (xwindow != null)
232: xwindow.setTitle(title);
233: }
234:
235: ComponentXWindow createXWindow() {
236: return new DialogXWindow(this );
237: }
238:
239: /**
240: * @return true if we actually showed, false if we just called toFront()
241: */
242: private boolean conditionalShow() {
243: boolean retval;
244: synchronized (getTreeLock()) {
245: if (xwindow == null) {
246: addNotify();
247: }
248: validate();
249: if (visible) {
250: toFront();
251: retval = false;
252: } else {
253: visible = retval = true;
254: xwindow.map(); // now guaranteed never to block
255: // createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
256: // this, parent,
257: // HierarchyEvent.SHOWING_CHANGED);
258: }
259: if (retval
260: && (componentListener != null || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)) {
261: ComponentEvent e = new ComponentEvent(this ,
262: ComponentEvent.COMPONENT_SHOWN);
263: Toolkit.getEventQueue().postEvent(e);
264: }
265: }
266: if (retval && (state & OPENED) == 0) {
267: postWindowEvent(WindowEvent.WINDOW_OPENED);
268: state |= OPENED;
269: }
270: return retval;
271: }
272:
273: /**
274: * Makes this dialog visible and in front of all windows.
275: * This method calls the dialog's addNotify() method,
276: * validates the dialog's layout, and makes the dialog visible.
277: * <p>
278: * If the dialog is modal, show() will not return until the
279: * dialog is no longer visible.
280: * <p>
281: * A Personal Profile or Personal Java implementation is not
282: * required to support multiple modal dialogs. In this case, if
283: * there is a previous modal dialog being shown, it can be hidden
284: * until this Dialog is made invisible via setVisible() or dispose().
285: * This must work recursively to allow for multiple nested modal dialogs.
286: * @see Component#setVisible
287: * @since JDK1.0
288: */
289: public void show() {
290: if (!isModal()) {
291: conditionalShow();
292: } else {
293: // Set this variable before calling conditionalShow(). That
294: // way, if the Dialog is hidden right after being shown, we
295: // won't mistakenly block this thread.
296: keepBlocking = true;
297: if (conditionalShow()) {
298: // We have two mechanisms for blocking: 1. If we're on the
299: // EventDispatchThread, start a new event pump. 2. If we're
300: // on any other thread, call wait() on the treelock.
301:
302: if (Toolkit.getEventQueue().isDispatchThread()) {
303: EventDispatchThread dispatchThread = (EventDispatchThread) Thread
304: .currentThread();
305: dispatchThread.pumpEvents(new Conditional() {
306: public boolean evaluate() {
307: return keepBlocking
308: && windowClosingException == null;
309: }
310: });
311: } else {
312: synchronized (getTreeLock()) {
313: while (keepBlocking
314: && windowClosingException == null) {
315: try {
316: getTreeLock().wait();
317: } catch (InterruptedException e) {
318: break;
319: }
320: }
321: }
322: }
323: if (windowClosingException != null) {
324: windowClosingException.fillInStackTrace();
325: throw windowClosingException;
326: }
327: }
328: }
329: }
330:
331: private void hideAndDisposeHandler() {
332: if (keepBlocking) {
333: synchronized (getTreeLock()) {
334: keepBlocking = false;
335: EventQueue.invokeLater(new Runnable() {
336: public void run() {
337: }
338: });
339: getTreeLock().notifyAll();
340: }
341: }
342: }
343:
344: /**
345: * Hides the Dialog and then causes show() to return if it is currently
346: * blocked.
347: */
348: public void hide() {
349: super .hide();
350: hideAndDisposeHandler();
351: }
352:
353: /**
354: * Disposes the Dialog and then causes show() to return if it is currently
355: * blocked.
356: */
357: public void dispose() {
358: super .dispose();
359: hideAndDisposeHandler();
360: }
361:
362: /**
363: * Indicates whether this dialog window is resizable.
364: * @return <code>true</code> if the user can resize the dialog;
365: * <code>false</code> otherwise.
366: * @see java.awt.Dialog#setResizable
367: * @since JDK1.0
368: */
369: public boolean isResizable() {
370: return resizable;
371: }
372:
373: /**
374: * Sets the Resizable property of the dialog.
375: * This method sets the resizable property of the dialog. A
376: * dilaog that is resizable may be resized by the user. In Personal
377: * Profile, this method may have no effect, it may be verified with
378: * the isResizable() method.
379: * @param resizable <code>true</code> if the user can
380: * resize this dialog; <code>false</code> otherwise.
381: * @see java.awt.Dialog#isResizable
382: * @since JDK1.0
383: */
384: public synchronized void setResizable(boolean resizable) {
385: this .resizable = resizable;
386: DialogXWindow xwindow = (DialogXWindow) this .xwindow;
387: if (xwindow != null)
388: xwindow.setResizable(resizable);
389: }
390:
391: /**
392: * Returns the parameter string representing the state of this
393: * dialog window. This string is useful for debugging.
394: * @return the parameter string of this dialog window.
395: * @since JDK1.0
396: */
397: protected String paramString() {
398: String str = super .paramString()
399: + (modal ? ",modal" : ",modeless");
400: if (title != null) {
401: str += ",title=" + title;
402: }
403: return str;
404: }
405:
406: private void readObject(ObjectInputStream s)
407: throws ClassNotFoundException, IOException {
408: s.defaultReadObject();
409: setModal(this.modal);
410: }
411: }
|