Source for java.awt.Dialog

   1: /* Dialog.java -- An AWT dialog box
   2:  Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006  
   3:  Free Software Foundation, Inc.
   4: 
   5:  This file is part of GNU Classpath.
   6: 
   7:  GNU Classpath is free software; you can redistribute it and/or modify
   8:  it under the terms of the GNU General Public License as published by
   9:  the Free Software Foundation; either version 2, or (at your option)
  10:  any later version.
  11: 
  12:  GNU Classpath is distributed in the hope that it will be useful, but
  13:  WITHOUT ANY WARRANTY; without even the implied warranty of
  14:  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15:  General Public License for more details.
  16: 
  17:  You should have received a copy of the GNU General Public License
  18:  along with GNU Classpath; see the file COPYING.  If not, write to the
  19:  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20:  02110-1301 USA.
  21: 
  22:  Linking this library statically or dynamically with other modules is
  23:  making a combined work based on this library.  Thus, the terms and
  24:  conditions of the GNU General Public License cover the whole
  25:  combination.
  26: 
  27:  As a special exception, the copyright holders of this library give you
  28:  permission to link this library with independent modules to produce an
  29:  executable, regardless of the license terms of these independent
  30:  modules, and to copy and distribute the resulting executable under
  31:  terms of your choice, provided that you also meet, for each linked
  32:  independent module, the terms and conditions of the license of that
  33:  module.  An independent module is a module which is not derived from
  34:  or based on this library.  If you modify this library, you may extend
  35:  this exception to your version of the library, but you are not
  36:  obligated to do so.  If you do not wish to do so, delete this
  37:  exception statement from your version. */
  38: 
  39: 
  40: package java.awt;
  41: 
  42: import java.awt.peer.DialogPeer;
  43: 
  44: import javax.accessibility.AccessibleContext;
  45: import javax.accessibility.AccessibleRole;
  46: import javax.accessibility.AccessibleState;
  47: import javax.accessibility.AccessibleStateSet;
  48: 
  49: /**
  50:  * <code>Dialog</code> provides a top-level window normally used to receive 
  51:  * user input in applications.
  52:  * <p>
  53:  * A dialog always has another top-level window as owner and is only visible
  54:  * if this owner is visible to the user. The default layout of dialogs is the 
  55:  * <code>BorderLayout</code>. Dialogs can be modal (blocks user input to other
  56:  * components) or non-modal (user input in other components are allowed).
  57:  * </p> 
  58:  * 
  59:  * @author Aaron M. Renn (arenn@urbanophile.com)
  60:  * @author Tom Tromey (tromey@redhat.com)
  61:  */
  62: public class Dialog extends Window
  63: {
  64:   // Serialization constant
  65:   private static final long serialVersionUID = 5920926903803293709L;
  66: 
  67:   /**
  68:    * @serial Indicates whether or not this dialog box is modal.
  69:    */
  70:   private boolean modal;
  71: 
  72:   /**
  73:    * @serial Indicates whether or not this dialog box is resizable.
  74:    */
  75:   private boolean resizable = true;
  76: 
  77:   /**
  78:    * @serial The title string for this dialog box, which can be
  79:    *         <code>null</code>.
  80:    */
  81:   private String title;
  82: 
  83:   /**
  84:    * This field indicates whether the dialog is undecorated or not.
  85:    */
  86:   private boolean undecorated = false;
  87: 
  88:   /**
  89:    * Indicates that we are blocked for modality in show
  90:    */
  91:   private boolean blocked = false;
  92: 
  93:   /**
  94:    * Secondary EventQueue to handle AWT events while we are blocked for 
  95:    * modality in show.
  96:    */
  97:   private EventQueue eq2 = null;
  98: 
  99:   /**
 100:    * The number used to generate the name returned by getName.
 101:    */
 102:   private static transient long next_dialog_number;
 103: 
 104:   /**
 105:    * Initializes a new instance of <code>Dialog</code> with the specified
 106:    * parent, that is resizable and not modal, and which has no title.
 107:    * 
 108:    * @param parent The parent frame of this dialog box.
 109:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration 
 110:    * is not from a screen device, or if owner is null. This exception is 
 111:    * always thrown when GraphicsEnvironment.isHeadless() returns true.
 112:    */
 113:   public Dialog(Frame parent)
 114:   {
 115:     this(parent, "", false);
 116:   }
 117: 
 118:   /**
 119:    * Initializes a new instance of <code>Dialog</code> with the specified
 120:    * parent and modality, that is resizable and which has no title.
 121:    * 
 122:    * @param parent The parent frame of this dialog box.
 123:    * @param modal <code>true</code> if this dialog box is modal,
 124:    * <code>false</code> otherwise.
 125:    * 
 126:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
 127:    * is not from a screen device, or if owner is null. This exception is 
 128:    * always thrown when GraphicsEnvironment.isHeadless() returns true.
 129:    */
 130:   public Dialog(Frame parent, boolean modal)
 131:   {
 132:     this(parent, "", modal);
 133:   }
 134: 
 135:   /**
 136:    * Initializes a new instance of <code>Dialog</code> with the specified
 137:    * parent, that is resizable and not modal, and which has the specified 
 138:    * title.
 139:    * 
 140:    * @param parent The parent frame of this dialog box.
 141:    * @param title The title string for this dialog box.
 142:    * 
 143:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
 144:    * is not from a screen device, or if owner is null. This exceptionnis 
 145:    * always thrown when GraphicsEnvironment.isHeadless() returns true.
 146:    */
 147:   public Dialog(Frame parent, String title)
 148:   {
 149:     this(parent, title, false);
 150:   }
 151: 
 152:   /**
 153:    * Initializes a new instance of <code>Dialog</code> with the specified,
 154:    * parent, title, and modality, that is resizable.
 155:    * 
 156:    * @param parent The parent frame of this dialog box.
 157:    * @param title The title string for this dialog box.
 158:    * @param modal <code>true</code> if this dialog box is modal,
 159:    * <code>false</code> otherwise.
 160:    *          
 161:    * @exception IllegalArgumentException If owner is null or
 162:    *              GraphicsEnvironment.isHeadless() returns true.
 163:    */
 164:   public Dialog(Frame parent, String title, boolean modal)
 165:   {
 166:     this(parent, title, modal, parent.getGraphicsConfiguration());
 167:   }
 168: 
 169:   /**
 170:    * Initializes a new instance of <code>Dialog</code> with the specified,
 171:    * parent, title, modality and <code>GraphicsConfiguration</code>, that is
 172:    * resizable.
 173:    * 
 174:    * @param parent The parent frame of this dialog box.
 175:    * @param title The title string for this dialog box.
 176:    * @param modal <code>true</code> if this dialog box is modal,
 177:    * <code>false</code> otherwise.
 178:    * @param gc The <code>GraphicsConfiguration</code> object to use. If 
 179:    * <code>null</code> the <code>GraphicsConfiguration</code> of the target 
 180:    * frame is used.
 181:    * 
 182:    * @exception IllegalArgumentException If owner is null, the
 183:    *              GraphicsConfiguration is not a screen device or
 184:    *              GraphicsEnvironment.isHeadless() returns true.
 185:    * @since 1.4
 186:    */
 187:   public Dialog(Frame parent, String title, boolean modal,
 188:                 GraphicsConfiguration gc)
 189:   {
 190:     super(parent, (gc == null) ? parent.getGraphicsConfiguration() : gc);
 191: 
 192:     // A null title is equivalent to an empty title
 193:     this.title = (title != null) ? title : "";
 194:     this.modal = modal;
 195:     visible = false;
 196: 
 197:     setLayout(new BorderLayout());
 198:     setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 199:   }
 200: 
 201:   /**
 202:    * Initializes a new instance of <code>Dialog</code> with the specified,
 203:    * parent, that is resizable.
 204:    * 
 205:    * @param owner The parent frame of this dialog box.
 206:    * 
 207:    * @exception IllegalArgumentException If parent is null. This exception is
 208:    * always thrown when GraphicsEnvironment.isHeadless() returns true.
 209:    * 
 210:    * @since 1.2
 211:    */
 212:   public Dialog(Dialog owner)
 213:   {
 214:     this(owner, "", false, owner.getGraphicsConfiguration());
 215:   }
 216: 
 217:   /**
 218:    * Initializes a new instance of <code>Dialog</code> with the specified,
 219:    * parent and title, that is resizable.
 220:    * 
 221:    * @param owner The parent frame of this dialog box.
 222:    * @param title The title string for this dialog box.
 223:    * 
 224:    * @exception IllegalArgumentException If parent is null. This exception is
 225:    *              always thrown when GraphicsEnvironment.isHeadless() returns
 226:    *              true.
 227:    * @since 1.2
 228:    */
 229:   public Dialog(Dialog owner, String title)
 230:   {
 231:     this(owner, title, false, owner.getGraphicsConfiguration());
 232:   }
 233: 
 234:   /**
 235:    * Initializes a new instance of <code>Dialog</code> with the specified,
 236:    * parent, title and modality, that is resizable.
 237:    * 
 238:    * @param owner The parent frame of this dialog box.
 239:    * @param title The title string for this dialog box.
 240:    * @param modal <code>true</code> if this dialog box is modal,
 241:    * <code>false</code> otherwise.
 242:    * 
 243:    * @exception IllegalArgumentException If parent is null. This exception is
 244:    * always thrown when GraphicsEnvironment.isHeadless() returns true.
 245:    * @since 1.2
 246:    */
 247:   public Dialog(Dialog owner, String title, boolean modal)
 248:   {
 249:     this(owner, title, modal, owner.getGraphicsConfiguration());
 250:   }
 251: 
 252:   /**
 253:    * Initializes a new instance of <code>Dialog</code> with the specified,
 254:    * parent, title, modality and <code>GraphicsConfiguration</code>, that is
 255:    * resizable.
 256:    * 
 257:    * @param parent The parent frame of this dialog box.
 258:    * @param title The title string for this dialog box.
 259:    * @param modal <code>true</code> if this dialog box is modal,
 260:    * <code>false</code> otherwise.
 261:    * @param gc The <code>GraphicsConfiguration</code> object to use. If 
 262:    * <code>null</code> the <code>GraphicsConfiguration</code> of the target 
 263:    * frame is used.
 264:    * 
 265:    * @exception IllegalArgumentException If parent is null, the
 266:    * GraphicsConfiguration is not a screen device or 
 267:    * GraphicsEnvironment.isHeadless() returns true.
 268:    * 
 269:    * @since 1.4
 270:    */
 271:   public Dialog(Dialog parent, String title, boolean modal,
 272:                 GraphicsConfiguration gc)
 273:   {
 274:     super(parent, (gc == null) ? parent.getGraphicsConfiguration() : gc);
 275: 
 276:     // A null title is equivalent to an empty title
 277:     this.title = (title != null) ? title : "";
 278:     this.modal = modal;
 279:     visible = false;
 280: 
 281:     setLayout(new BorderLayout());
 282:     setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 283:   }
 284: 
 285:   /**
 286:    * Returns the title of this dialog box.
 287:    * 
 288:    * @return The title of this dialog box.
 289:    */
 290:   public String getTitle()
 291:   {
 292:     return title;
 293:   }
 294: 
 295:   /**
 296:    * Sets the title of this dialog box to the specified string.
 297:    * 
 298:    * @param title the new title. If <code>null</code> an empty
 299:    * title will be set.
 300:    */
 301:   public synchronized void setTitle(String title)
 302:   {
 303:     // A null title is equivalent to an empty title
 304:     this.title = (title != null) ? title : "";
 305: 
 306:     if (peer != null)
 307:       {
 308:         DialogPeer d = (DialogPeer) peer;
 309:         d.setTitle(title);
 310:       }
 311:   }
 312: 
 313:   /**
 314:    * Tests whether or not this dialog box is modal.
 315:    * 
 316:    * @return <code>true</code> if this dialog box is modal, <code>false</code>
 317:    * otherwise.
 318:    */
 319:   public boolean isModal()
 320:   {
 321:     return modal;
 322:   }
 323: 
 324:   /**
 325:    * Changes the modality of this dialog box. This can only be done before the
 326:    * peer is created.
 327:    * 
 328:    * @param modal <code>true</code> to make this dialog box modal,
 329:    * <code>false</code> to make it non-modal. 
 330:    */
 331:   public void setModal(boolean modal)
 332:   {
 333:     this.modal = modal;
 334:   }
 335: 
 336:   /**
 337:    * Tests whether or not this dialog box is resizable.
 338:    * 
 339:    * @return <code>true</code> if this dialog is resizable,
 340:    * <code>false</code> otherwise.
 341:    */
 342:   public boolean isResizable()
 343:   {
 344:     return resizable;
 345:   }
 346: 
 347:   /**
 348:    * Changes the resizability of this dialog box.
 349:    * 
 350:    * @param resizable <code>true</code> to make this dialog resizable,
 351:    * <code>false</code> to make it non-resizable.
 352:    */
 353:   public synchronized void setResizable(boolean resizable)
 354:   {
 355:     this.resizable = resizable;
 356:     if (peer != null)
 357:       {
 358:         DialogPeer d = (DialogPeer) peer;
 359:         d.setResizable(resizable);
 360:       }
 361:   }
 362: 
 363:   /**
 364:    * Creates this object's native peer.
 365:    */
 366:   public synchronized void addNotify()
 367:   {
 368:     if (peer == null)
 369:       peer = getToolkit().createDialog(this);
 370:     super.addNotify();
 371:   }
 372: 
 373:   /**
 374:    * Makes this dialog visible and brings it to the front. If the dialog is
 375:    * modal and is not already visible, this call will not return until the
 376:    * dialog is hidden by someone calling hide or dispose. If this is the event
 377:    * dispatching thread we must ensure that another event thread runs while the
 378:    * one which invoked this method is blocked.
 379:    * 
 380:    * @deprecated Use {@link Component#setVisible(boolean)} instead.
 381:    */
 382:   public synchronized void show()
 383:   {
 384:     super.show();
 385: 
 386:     if (isModal())
 387:       {
 388:         // If already shown (and blocked) just return
 389:         if (blocked)
 390:           return;
 391: 
 392:         /*
 393:          * If show is called in the dispatch thread for a modal dialog it will
 394:          * block so we must run another thread so the events keep being
 395:          * dispatched.
 396:          */
 397:         if (EventQueue.isDispatchThread())
 398:           {
 399:             EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
 400:             eq2 = new EventQueue();
 401:             eq.push(eq2);
 402:           }
 403: 
 404:         try
 405:           {
 406:             blocked = true;
 407:             wait();
 408:             blocked = false;
 409:           }
 410:         catch (InterruptedException e)
 411:           {
 412:             blocked = false;
 413:           }
 414: 
 415:         if (eq2 != null)
 416:           {
 417:             eq2.pop();
 418:             eq2 = null;
 419:           }
 420:       }
 421:   }
 422: 
 423:   /**
 424:    * Hides the Dialog and then causes show() to return if it is currently
 425:    * blocked.
 426:    * 
 427:    * @deprecated Use {@link Component#setVisible(boolean)} instead.
 428:    */
 429:   public synchronized void hide()
 430:   {
 431:     if (blocked)
 432:       {
 433:         notifyAll();
 434:       }
 435: 
 436:     super.hide();
 437:   }
 438: 
 439:   /**
 440:    * Disposes the Dialog and then causes show() to return if it is currently
 441:    * blocked.
 442:    */
 443:   public synchronized void dispose()
 444:   {
 445:     if (blocked)
 446:       {
 447:         notifyAll();
 448:       }
 449: 
 450:     super.dispose();
 451:   }
 452: 
 453:   /**
 454:    * Returns a debugging string for this component.
 455:    * 
 456:    * @return A debugging string for this component.
 457:    */
 458:   protected String paramString()
 459:   {
 460:     return "title+" + title + ",modal=" + modal + ",resizable=" + resizable
 461:             + "," + super.paramString();
 462:   }
 463: 
 464:   /**
 465:    * Returns whether this frame is undecorated or not.
 466:    * 
 467:    * @return <code>true</code> if this dialog is undecorated,
 468:    * <code>false</code> otherwise.
 469:    * 
 470:    * @since 1.4
 471:    */
 472:   public boolean isUndecorated()
 473:   {
 474:     return undecorated;
 475:   }
 476: 
 477:   /**
 478:    * Disables or enables decorations for this frame. This method can only be
 479:    * called while the frame is not displayable.
 480:    * 
 481:    * @param undecorated <code>true</code> to disable dialog decorations,
 482:    * <code>false</code> otherwise.
 483:    * 
 484:    * @exception IllegalComponentStateException If this frame is displayable.
 485:    * @since 1.4
 486:    */
 487:   public void setUndecorated(boolean undecorated)
 488:   {
 489:     if (isDisplayable())
 490:       throw new IllegalComponentStateException();
 491: 
 492:     this.undecorated = undecorated;
 493:   }
 494: 
 495:   /**
 496:    * Accessibility support for <code>Dialog</code>.
 497:    */
 498:   protected class AccessibleAWTDialog
 499:       extends AccessibleAWTWindow
 500:   {
 501:     private static final long serialVersionUID = 4837230331833941201L;
 502: 
 503:     /**
 504:      * Gets the role of this object.
 505:      * @return AccessibleRole.DIALOG 
 506:      */
 507:     public AccessibleRole getAccessibleRole()
 508:     {
 509:       return AccessibleRole.DIALOG;
 510:     }
 511: 
 512:     /**
 513:      * Gets the state set of this object.
 514:      * @return The current state of this dialog.
 515:      */
 516:     public AccessibleStateSet getAccessibleStateSet()
 517:     {
 518:       AccessibleStateSet states = super.getAccessibleStateSet();
 519:       if (isResizable())
 520:         states.add(AccessibleState.RESIZABLE);
 521:       if (isModal())
 522:         states.add(AccessibleState.MODAL);
 523:       return states;
 524:     }
 525:   }
 526: 
 527:   /**
 528:    * Gets the AccessibleContext associated with this <code>Dialog</code>. The
 529:    * context is created, if necessary.
 530:    * 
 531:    * @return the associated context
 532:    */
 533:   public AccessibleContext getAccessibleContext()
 534:   {
 535:     /* Create the context if this is the first request */
 536:     if (accessibleContext == null)
 537:       accessibleContext = new AccessibleAWTDialog();
 538:     return accessibleContext;
 539:   }
 540:   
 541:   /**
 542:    * Generate a unique name for this <code>Dialog</code>.
 543:    *
 544:    * @return A unique name for this <code>Dialog</code>.
 545:    */
 546:   String generateName()
 547:   {
 548:     return "dialog" + getUniqueLong();
 549:   }
 550: 
 551:   private static synchronized long getUniqueLong()
 552:   {
 553:     return next_dialog_number++;
 554:   }
 555: }