Source for java.awt.Window

   1: /* Window.java --
   2:    Copyright (C) 1999, 2000, 2002, 2003, 2004, 2006  Free Software Foundation
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.awt;
  40: 
  41: import gnu.classpath.NotImplementedException;
  42: 
  43: import java.awt.event.ComponentEvent;
  44: import java.awt.event.FocusEvent;
  45: import java.awt.event.WindowAdapter;
  46: import java.awt.event.WindowEvent;
  47: import java.awt.event.WindowFocusListener;
  48: import java.awt.event.WindowListener;
  49: import java.awt.event.WindowStateListener;
  50: import java.awt.image.BufferStrategy;
  51: import java.awt.peer.WindowPeer;
  52: import java.lang.ref.Reference;
  53: import java.lang.ref.WeakReference;
  54: import java.util.EventListener;
  55: import java.util.Iterator;
  56: import java.util.Locale;
  57: import java.util.ResourceBundle;
  58: import java.util.Vector;
  59: 
  60: import javax.accessibility.Accessible;
  61: import javax.accessibility.AccessibleContext;
  62: import javax.accessibility.AccessibleRole;
  63: import javax.accessibility.AccessibleState;
  64: import javax.accessibility.AccessibleStateSet;
  65: 
  66: /**
  67:  * This class represents a top-level window with no decorations.
  68:  *
  69:  * @author Aaron M. Renn (arenn@urbanophile.com)
  70:  * @author Warren Levy  (warrenl@cygnus.com)
  71:  */
  72: public class Window extends Container implements Accessible
  73: {
  74:   private static final long serialVersionUID = 4497834738069338734L;
  75: 
  76:   // Serialized fields, from Sun's serialization spec.
  77:   private String warningString = null;
  78:   private int windowSerializedDataVersion = 0; // FIXME
  79:   /** @since 1.2 */
  80:   // private FocusManager focusMgr;  // FIXME: what is this?  
  81:   /** @since 1.2 */
  82:   private int state = 0;
  83:   /** @since 1.4 */
  84:   private boolean focusableWindowState = true;
  85: 
  86:   // A list of other top-level windows owned by this window.
  87:   private transient Vector ownedWindows = new Vector();
  88: 
  89:   private transient WindowListener windowListener;
  90:   private transient WindowFocusListener windowFocusListener;
  91:   private transient WindowStateListener windowStateListener;
  92:   private transient GraphicsConfiguration graphicsConfiguration;
  93: 
  94:   private transient boolean shown;
  95: 
  96:   // This is package-private to avoid an accessor method.
  97:   transient Component windowFocusOwner;
  98:   
  99:   /*
 100:    * The number used to generate the name returned by getName.
 101:    */
 102:   private static transient long next_window_number;
 103: 
 104:   protected class AccessibleAWTWindow extends AccessibleAWTContainer
 105:   {
 106:     private static final long serialVersionUID = 4215068635060671780L;
 107: 
 108:     public AccessibleRole getAccessibleRole()
 109:     {
 110:       return AccessibleRole.WINDOW;
 111:     }
 112:     
 113:     public AccessibleStateSet getAccessibleStateSet()
 114:     {
 115:       AccessibleStateSet states = super.getAccessibleStateSet();
 116:       if (isActive())
 117:         states.add(AccessibleState.ACTIVE);
 118:       return states;
 119:     }
 120:   }
 121: 
 122:   /** 
 123:    * This (package access) constructor is used by subclasses that want
 124:    * to build windows that do not have parents.  Eg. toplevel
 125:    * application frames.  Subclasses cannot call super(null), since
 126:    * null is an illegal argument.
 127:    */
 128:   Window()
 129:   {
 130:     visible = false;
 131:     // Windows are the only Containers that default to being focus
 132:     // cycle roots.
 133:     focusCycleRoot = true;
 134:     setLayout(new BorderLayout());
 135: 
 136:     addWindowFocusListener (new WindowAdapter ()
 137:       {
 138:         public void windowGainedFocus (WindowEvent event)
 139:         {
 140:           if (windowFocusOwner != null)
 141:             {
 142:               // FIXME: move this section and the other similar
 143:               // sections in Component into a separate method.
 144:               EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
 145:               synchronized (eq)
 146:                 {
 147:                   KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 148:                   Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
 149:                   if (currentFocusOwner != null)
 150:                     {
 151:                       eq.postEvent (new FocusEvent (currentFocusOwner, FocusEvent.FOCUS_LOST,
 152:                                                     false, windowFocusOwner));
 153:                       eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED,
 154:                                                     false, currentFocusOwner));
 155:                     }
 156:                   else
 157:                     eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED, false));
 158:                 }
 159:             }
 160:         }
 161:       });
 162:     
 163:     GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment();
 164:     graphicsConfiguration = g.getDefaultScreenDevice().getDefaultConfiguration();
 165:   }
 166: 
 167:   Window(GraphicsConfiguration gc)
 168:   {
 169:     this();
 170:     graphicsConfiguration = gc;
 171:   }
 172: 
 173:   /**
 174:    * Initializes a new instance of <code>Window</code> with the specified
 175:    * parent.  The window will initially be invisible.
 176:    *
 177:    * @param owner The owning <code>Frame</code> of this window.
 178:    *
 179:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
 180:    * is not from a screen device, or if owner is null; this exception is always
 181:    * thrown when GraphicsEnvironment.isHeadless returns true.
 182:    */
 183:   public Window(Frame owner)
 184:   {
 185:     this (owner, owner.getGraphicsConfiguration ());
 186:   }
 187: 
 188:   /**
 189:    * Initializes a new instance of <code>Window</code> with the specified
 190:    * parent.  The window will initially be invisible.   
 191:    *
 192:    * @exception IllegalArgumentException If the owner's GraphicsConfiguration
 193:    * is not from a screen device, or if owner is null; this exception is always
 194:    * thrown when GraphicsEnvironment.isHeadless returns true.
 195:    *
 196:    * @since 1.2
 197:    */
 198:   public Window(Window owner)
 199:   {
 200:     this (owner, owner.getGraphicsConfiguration ());
 201:   }
 202:   
 203:   /**
 204:    * Initializes a new instance of <code>Window</code> with the specified
 205:    * parent.  The window will initially be invisible.   
 206:    *
 207:    * @exception IllegalArgumentException If owner is null or if gc is not from a
 208:    * screen device; this exception is always thrown when
 209:    * GraphicsEnvironment.isHeadless returns true.
 210:    *
 211:    * @since 1.3
 212:    */
 213:   public Window(Window owner, GraphicsConfiguration gc)
 214:   {
 215:     this ();
 216: 
 217:     synchronized (getTreeLock())
 218:       {
 219:     if (owner == null)
 220:       throw new IllegalArgumentException ("owner must not be null");
 221: 
 222:     parent = owner;
 223:         owner.ownedWindows.add(new WeakReference(this));
 224:       }
 225: 
 226:     // FIXME: make this text visible in the window.
 227:     SecurityManager s = System.getSecurityManager();
 228:     if (s != null && ! s.checkTopLevelWindow(this))
 229:       warningString = System.getProperty("awt.appletWarning");
 230: 
 231:     if (gc != null
 232:         && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
 233:       throw new IllegalArgumentException ("gc must be from a screen device");
 234: 
 235:     if (gc == null)
 236:       graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
 237:                                                  .getDefaultScreenDevice()
 238:                                                  .getDefaultConfiguration();
 239:     else
 240:       graphicsConfiguration = gc;
 241:   }
 242: 
 243:   GraphicsConfiguration getGraphicsConfigurationImpl()
 244:   {
 245:     if (graphicsConfiguration != null)
 246:     return graphicsConfiguration;
 247: 
 248:     return super.getGraphicsConfigurationImpl();
 249:   }
 250: 
 251:   /**
 252:    * Creates the native peer for this window.
 253:    */
 254:   public void addNotify()
 255:   {
 256:     if (peer == null)
 257:       peer = getToolkit().createWindow(this);
 258:     super.addNotify();
 259:   }
 260: 
 261:   /**
 262:    * Relays out this window's child components at their preferred size.
 263:    *
 264:    * @specnote pack() doesn't appear to be called internally by show(), so
 265:    *             we duplicate some of the functionality.
 266:    */
 267:   public void pack()
 268:   {
 269:     if (parent != null && !parent.isDisplayable())
 270:       parent.addNotify();
 271:     if (peer == null)
 272:       addNotify();
 273: 
 274:     setSize(getPreferredSize());
 275: 
 276:     validate();
 277:   }
 278: 
 279:   /**
 280:    * Shows on-screen this window and any of its owned windows for whom
 281:    * isVisible returns true.
 282:    */
 283:   public void show()
 284:   {
 285:     synchronized (getTreeLock())
 286:       {
 287:         if (parent != null && ! parent.isDisplayable())
 288:           parent.addNotify();
 289:         if (peer == null)
 290:           addNotify();
 291: 
 292:         validate();
 293:         if (visible)
 294:           toFront();
 295:         else
 296:           {
 297:             super.show();
 298:             // Show visible owned windows.
 299:             Iterator e = ownedWindows.iterator();
 300:             while (e.hasNext())
 301:               {
 302:                 Window w = (Window) (((Reference) e.next()).get());
 303:                 if (w != null)
 304:                   {
 305:                     if (w.isVisible())
 306:                       w.getPeer().setVisible(true);
 307:                   }
 308:                 else
 309:                   // Remove null weak reference from ownedWindows.
 310:                   // Unfortunately this can't be done in the Window's
 311:                   // finalize method because there is no way to guarantee
 312:                   // synchronous access to ownedWindows there.
 313:                   e.remove();
 314:               }
 315:           }
 316:         KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
 317:         manager.setGlobalFocusedWindow(this);
 318: 
 319:         if (! shown)
 320:           {
 321:             FocusTraversalPolicy policy = getFocusTraversalPolicy();
 322:             Component initialFocusOwner = null;
 323: 
 324:             if (policy != null)
 325:               initialFocusOwner = policy.getInitialComponent(this);
 326: 
 327:             if (initialFocusOwner != null)
 328:               initialFocusOwner.requestFocusInWindow();
 329: 
 330:             shown = true;
 331:           }
 332:       }
 333:   }
 334: 
 335:   public void hide()
 336:   {
 337:     // Hide visible owned windows.
 338:     synchronized (getTreeLock ())
 339:       {
 340:     Iterator e = ownedWindows.iterator();
 341:     while(e.hasNext())
 342:       {
 343:         Window w = (Window)(((Reference) e.next()).get());
 344:         if (w != null)
 345:           {
 346:         if (w.isVisible() && w.getPeer() != null)
 347:           w.getPeer().setVisible(false);
 348:           }
 349:              else
 350:           e.remove();
 351:       }
 352:       }
 353:     super.hide();
 354:   }
 355: 
 356:   /**
 357:    * Destroys any resources associated with this window.  This includes
 358:    * all components in the window and all owned top-level windows.
 359:    */
 360:   public void dispose()
 361:   {
 362:     hide();
 363: 
 364:     synchronized (getTreeLock ())
 365:       {
 366:     Iterator e = ownedWindows.iterator();
 367:     while(e.hasNext())
 368:       {
 369:         Window w = (Window)(((Reference) e.next()).get());
 370:         if (w != null)
 371:           w.dispose();
 372:         else
 373:           // Remove null weak reference from ownedWindows.
 374:           e.remove();
 375:       }
 376: 
 377:     for (int i = 0; i < ncomponents; ++i)
 378:       component[i].removeNotify();
 379:     this.removeNotify();
 380: 
 381:         // Post a WINDOW_CLOSED event.
 382:         WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
 383:         getToolkit().getSystemEventQueue().postEvent(we);
 384:       }
 385:   }
 386: 
 387:   /**
 388:    * Sends this window to the back so that all other windows display in
 389:    * front of it.
 390:    */
 391:   public void toBack()
 392:   {
 393:     if (peer != null)
 394:       {
 395:     WindowPeer wp = (WindowPeer) peer;
 396:     wp.toBack();
 397:       }
 398:   }
 399: 
 400:   /**
 401:    * Brings this window to the front so that it displays in front of
 402:    * any other windows.
 403:    */
 404:   public void toFront()
 405:   {
 406:     if (peer != null)
 407:       {
 408:         WindowPeer wp = (WindowPeer) peer;
 409:         wp.toFront();
 410:       }
 411:   }
 412: 
 413:   /**
 414:    * Returns the toolkit used to create this window.
 415:    *
 416:    * @return The toolkit used to create this window.
 417:    *
 418:    * @specnote Unlike Component.getToolkit, this implementation always 
 419:    *           returns the value of Toolkit.getDefaultToolkit().
 420:    */
 421:   public Toolkit getToolkit()
 422:   {
 423:     return Toolkit.getDefaultToolkit();    
 424:   }
 425: 
 426:   /**
 427:    * Returns the warning string that will be displayed if this window is
 428:    * popped up by an unsecure applet or application.
 429:    *
 430:    * @return The unsecure window warning message.
 431:    */
 432:   public final String getWarningString()
 433:   {
 434:     return warningString;
 435:   }
 436: 
 437:   /**
 438:    * Returns the locale that this window is configured for.
 439:    *
 440:    * @return The locale this window is configured for.
 441:    */
 442:   public Locale getLocale()
 443:   {
 444:     return locale == null ? Locale.getDefault() : locale;
 445:   }
 446: 
 447:   /*
 448:   /** @since 1.2
 449:   public InputContext getInputContext()
 450:   {
 451:     // FIXME
 452:   }
 453:   */
 454: 
 455:   /**
 456:    * Sets the cursor for this window to the specifiec cursor.
 457:    *
 458:    * @param cursor The new cursor for this window.
 459:    */
 460:   public void setCursor(Cursor cursor)
 461:   {
 462:     super.setCursor(cursor);
 463:   }
 464: 
 465:   public Window getOwner()
 466:   {
 467:     return (Window) parent;
 468:   }
 469: 
 470:   /** @since 1.2 */
 471:   public Window[] getOwnedWindows()
 472:   {
 473:     Window [] trimmedList;
 474:     synchronized (getTreeLock ())
 475:       {
 476:     // Windows with non-null weak references in ownedWindows.
 477:     Window [] validList = new Window [ownedWindows.size()];
 478: 
 479:     Iterator e = ownedWindows.iterator();
 480:     int numValid = 0;
 481:     while (e.hasNext())
 482:       {
 483:         Window w = (Window)(((Reference) e.next()).get());
 484:         if (w != null)
 485:           validList[numValid++] = w;
 486:         else
 487:           // Remove null weak reference from ownedWindows.
 488:           e.remove();
 489:       }
 490: 
 491:     if (numValid != validList.length)
 492:       {
 493:         trimmedList = new Window [numValid];
 494:         System.arraycopy (validList, 0, trimmedList, 0, numValid);
 495:       }
 496:     else
 497:       trimmedList = validList;
 498:       }
 499:     return trimmedList;
 500:   }
 501: 
 502:   /**
 503:    * Adds the specified listener to the list of <code>WindowListeners</code>
 504:    * that will receive events for this window.
 505:    *
 506:    * @param listener The <code>WindowListener</code> to add.
 507:    */
 508:   public synchronized void addWindowListener(WindowListener listener)
 509:   {
 510:     windowListener = AWTEventMulticaster.add(windowListener, listener);
 511:   }
 512: 
 513:   /**
 514:    * Removes the specified listener from the list of
 515:    * <code>WindowListeners</code> that will receive events for this window.
 516:    *
 517:    * @param listener The <code>WindowListener</code> to remove.
 518:    */
 519:   public synchronized void removeWindowListener(WindowListener listener)
 520:   {
 521:     windowListener = AWTEventMulticaster.remove(windowListener, listener);
 522:   }
 523: 
 524:   /**
 525:    * Returns an array of all the window listeners registered on this window.
 526:    *
 527:    * @since 1.4
 528:    */
 529:   public synchronized WindowListener[] getWindowListeners()
 530:   {
 531:     return (WindowListener[])
 532:       AWTEventMulticaster.getListeners(windowListener,
 533:                                        WindowListener.class);
 534:   }
 535: 
 536:   /**
 537:    * Returns an array of all the window focus listeners registered on this
 538:    * window.
 539:    *
 540:    * @since 1.4
 541:    */
 542:   public synchronized WindowFocusListener[] getWindowFocusListeners()
 543:   {
 544:     return (WindowFocusListener[])
 545:       AWTEventMulticaster.getListeners(windowFocusListener,
 546:                                        WindowFocusListener.class);
 547:   }
 548:   
 549:   /**
 550:    * Returns an array of all the window state listeners registered on this
 551:    * window.
 552:    *
 553:    * @since 1.4
 554:    */
 555:   public synchronized WindowStateListener[] getWindowStateListeners()
 556:   {
 557:     return (WindowStateListener[])
 558:       AWTEventMulticaster.getListeners(windowStateListener,
 559:                                        WindowStateListener.class);
 560:   }
 561: 
 562:   /**
 563:    * Adds the specified listener to this window.
 564:    */
 565:   public void addWindowFocusListener (WindowFocusListener wfl)
 566:   {
 567:     windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
 568:   }
 569:   
 570:   /**
 571:    * Adds the specified listener to this window.
 572:    *
 573:    * @since 1.4
 574:    */
 575:   public void addWindowStateListener (WindowStateListener wsl)
 576:   {
 577:     windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);  
 578:   }
 579:   
 580:   /**
 581:    * Removes the specified listener from this window.
 582:    */
 583:   public void removeWindowFocusListener (WindowFocusListener wfl)
 584:   {
 585:     windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
 586:   }
 587:   
 588:   /**
 589:    * Removes the specified listener from this window.
 590:    *
 591:    * @since 1.4
 592:    */
 593:   public void removeWindowStateListener (WindowStateListener wsl)
 594:   {
 595:     windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
 596:   }
 597: 
 598:   /**
 599:    * Returns an array of all the objects currently registered as FooListeners
 600:    * upon this Window. FooListeners are registered using the addFooListener
 601:    * method.
 602:    *
 603:    * @exception ClassCastException If listenerType doesn't specify a class or
 604:    * interface that implements java.util.EventListener.
 605:    *
 606:    * @since 1.3
 607:    */
 608:   public EventListener[] getListeners(Class listenerType)
 609:   {
 610:     if (listenerType == WindowListener.class)
 611:       return getWindowListeners();
 612:     return super.getListeners(listenerType);
 613:   }
 614: 
 615:   void dispatchEventImpl(AWTEvent e)
 616:   {
 617:     // Make use of event id's in order to avoid multiple instanceof tests.
 618:     if (e.id <= WindowEvent.WINDOW_LAST 
 619:         && e.id >= WindowEvent.WINDOW_FIRST
 620:         && (windowListener != null
 621:         || windowFocusListener != null
 622:         || windowStateListener != null
 623:         || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
 624:       processEvent(e);
 625:     else 
 626:       {
 627:     if (peer != null && (e.id == ComponentEvent.COMPONENT_RESIZED
 628:         || e.id == ComponentEvent.COMPONENT_MOVED))
 629:             {
 630:         Rectangle bounds = peer.getBounds();
 631:         x = bounds.x;
 632:         y = bounds.y;
 633:         height = bounds.height;
 634:         width = bounds.width;
 635:         
 636:         if (e.id == ComponentEvent.COMPONENT_RESIZED)
 637:           {
 638:         invalidate();
 639:         validate();
 640:           }
 641:       }
 642:     super.dispatchEventImpl(e);
 643:       }
 644:   }
 645: 
 646:   /**
 647:    * Processes the specified event for this window.  If the event is an
 648:    * instance of <code>WindowEvent</code>, then
 649:    * <code>processWindowEvent()</code> is called to process the event,
 650:    * otherwise the superclass version of this method is invoked.
 651:    *
 652:    * @param evt The event to process.
 653:    */
 654:   protected void processEvent(AWTEvent evt)
 655:   {
 656:     if (evt instanceof WindowEvent)
 657:       processWindowEvent((WindowEvent) evt);
 658:     else
 659:       super.processEvent(evt);
 660:   }
 661: 
 662:   /**
 663:    * Dispatches this event to any listeners that are listening for
 664:    * <code>WindowEvents</code> on this window.  This method only gets
 665:    * invoked if it is enabled via <code>enableEvents()</code> or if
 666:    * a listener has been added.
 667:    *
 668:    * @param evt The event to process.
 669:    */
 670:   protected void processWindowEvent(WindowEvent evt)
 671:   {
 672:     int id = evt.getID();
 673: 
 674:     if (id == WindowEvent.WINDOW_GAINED_FOCUS
 675:     || id == WindowEvent.WINDOW_LOST_FOCUS)
 676:       processWindowFocusEvent (evt);
 677:     else if (id == WindowEvent.WINDOW_STATE_CHANGED)
 678:       processWindowStateEvent (evt);
 679:     else
 680:       {
 681:     if (windowListener != null)
 682:       {
 683:         switch (evt.getID())
 684:           {
 685:           case WindowEvent.WINDOW_ACTIVATED:
 686:         windowListener.windowActivated(evt);
 687:         break;
 688: 
 689:           case WindowEvent.WINDOW_CLOSED:
 690:         windowListener.windowClosed(evt);
 691:         break;
 692: 
 693:           case WindowEvent.WINDOW_CLOSING:
 694:         windowListener.windowClosing(evt);
 695:         break;
 696: 
 697:           case WindowEvent.WINDOW_DEACTIVATED:
 698:         windowListener.windowDeactivated(evt);
 699:         break;
 700: 
 701:           case WindowEvent.WINDOW_DEICONIFIED:
 702:         windowListener.windowDeiconified(evt);
 703:         break;
 704: 
 705:           case WindowEvent.WINDOW_ICONIFIED:
 706:         windowListener.windowIconified(evt);
 707:         break;
 708: 
 709:           case WindowEvent.WINDOW_OPENED:
 710:         windowListener.windowOpened(evt);
 711:         break;
 712: 
 713:           default:
 714:         break;
 715:           }
 716:       }
 717:       }
 718:   }
 719:   
 720:   /**
 721:    * Identifies if this window is active.  The active window is a Frame or
 722:    * Dialog that has focus or owns the active window.
 723:    *  
 724:    * @return true if active, else false.
 725:    * @since 1.4
 726:    */
 727:   public boolean isActive()
 728:   {
 729:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 730:     return manager.getActiveWindow() == this;
 731:   }
 732: 
 733:   /**
 734:    * Identifies if this window is focused.  A window is focused if it is the
 735:    * focus owner or it contains the focus owner.
 736:    * 
 737:    * @return true if focused, else false.
 738:    * @since 1.4
 739:    */
 740:   public boolean isFocused()
 741:   {
 742:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 743:     return manager.getFocusedWindow() == this;
 744:   }
 745:   
 746:   /**
 747:    * Returns the child window that has focus if this window is active.
 748:    * This method returns <code>null</code> if this window is not active
 749:    * or no children have focus.
 750:    *
 751:    * @return The component that has focus, or <code>null</code> if no
 752:    * component has focus.
 753:    */
 754:   public Component getFocusOwner ()
 755:   {
 756:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
 757: 
 758:     Window activeWindow = manager.getActiveWindow ();
 759: 
 760:     // The currently-focused Component belongs to the active Window.
 761:     if (activeWindow == this)
 762:       return manager.getFocusOwner ();
 763:     else
 764:       return null;
 765:   }
 766: 
 767:   /**
 768:    * Returns the child component of this window that would receive
 769:    * focus if this window were to become focused.  If the window
 770:    * already has the top-level focus, then this method returns the
 771:    * same component as getFocusOwner.  If no child component has
 772:    * requested focus within the window, then the initial focus owner
 773:    * is returned.  If this is a non-focusable window, this method
 774:    * returns null.
 775:    *
 776:    * @return the child component of this window that most recently had
 777:    * the focus, or <code>null</code>
 778:    * @since 1.4
 779:    */
 780:   public Component getMostRecentFocusOwner ()
 781:   {
 782:     return windowFocusOwner;
 783:   }
 784: 
 785:   /**
 786:    * Set the focus owner for this window.  This method is used to
 787:    * remember which component was focused when this window lost
 788:    * top-level focus, so that when it regains top-level focus the same
 789:    * child component can be refocused.
 790:    *
 791:    * @param windowFocusOwner the component in this window that owns
 792:    * the focus.
 793:    */
 794:   void setFocusOwner (Component windowFocusOwner)
 795:   {
 796:     this.windowFocusOwner = windowFocusOwner;
 797:   }
 798: 
 799:   /**
 800:    * Post a Java 1.0 event to the event queue.
 801:    *
 802:    * @param e The event to post.
 803:    *
 804:    * @deprecated
 805:    */
 806:   public boolean postEvent(Event e)
 807:   {
 808:     return handleEvent (e);
 809:   }
 810: 
 811:   /**
 812:    * Tests whether or not this window is visible on the screen.
 813:    *
 814:    * In contrast to the normal behaviour of Container, which is that
 815:    * a container is showing if its parent is visible and showing, a Window
 816:    * is even showing, if its parent (i.e. an invisible Frame) is not showing.
 817:    *
 818:    * @return <code>true</code> if this window is visible, <code>false</code>
 819:    * otherwise.
 820:    */
 821:   public boolean isShowing()
 822:   {
 823:     return isVisible();
 824:   }
 825: 
 826:   public void setLocationRelativeTo(Component c)
 827:   {
 828:     int x = 0;
 829:     int y = 0;
 830:     
 831:     if (c == null || !c.isShowing())
 832:       {
 833:         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
 834:         Point center = ge.getCenterPoint();
 835:         x = center.x - (width / 2);
 836:         y = center.y - (height / 2);
 837:       }
 838:     else
 839:       {
 840:         int cWidth = c.getWidth();
 841:         int cHeight = c.getHeight();
 842:         Dimension screenSize = getToolkit().getScreenSize();
 843: 
 844:         x = c.getLocationOnScreen().x;
 845:         y = c.getLocationOnScreen().y;
 846:         
 847:         // If bottom of component is cut off, window placed
 848:         // on the left or the right side of component
 849:         if ((y + cHeight) > screenSize.height)
 850:           {
 851:             // If the right side of the component is closer to the center
 852:             if ((screenSize.width / 2 - x) <= 0)
 853:               {
 854:                 if ((x - width) >= 0)
 855:                   x -= width;
 856:                 else
 857:                   x = 0;
 858:               }
 859:             else
 860:               {
 861:                 if ((x + cWidth + width) <= screenSize.width)
 862:                   x += cWidth;
 863:                 else
 864:                   x = screenSize.width - width;
 865:               }
 866: 
 867:             y = screenSize.height - height;
 868:           }
 869:         else if (cWidth > width || cHeight > height)
 870:           {
 871:             // If right side of component is cut off
 872:             if ((x + width) > screenSize.width)
 873:               x = screenSize.width - width;
 874:             // If left side of component is cut off
 875:             else if (x < 0)
 876:               x = 0;
 877:             else
 878:               x += (cWidth - width) / 2;
 879:             
 880:             y += (cHeight - height) / 2;
 881:           }
 882:         else
 883:           {
 884:             // If right side of component is cut off
 885:             if ((x + width) > screenSize.width)
 886:               x = screenSize.width - width;
 887:             // If left side of component is cut off
 888:             else if (x < 0 || (x - (width - cWidth) / 2) < 0)
 889:               x = 0;
 890:             else
 891:               x -= (width - cWidth) / 2;
 892: 
 893:             if ((y - (height - cHeight) / 2) > 0)
 894:               y -= (height - cHeight) / 2;
 895:             else
 896:               y = 0;
 897:           }
 898:       }
 899: 
 900:     setLocation(x, y);
 901:   }
 902: 
 903:   /**
 904:    * A BltBufferStrategy for windows.
 905:    */
 906:   private class WindowBltBufferStrategy extends BltBufferStrategy
 907:   {
 908:     /**
 909:      * Creates a block transfer strategy for this window.
 910:      *
 911:      * @param numBuffers the number of buffers in this strategy
 912:      * @param accelerated true if the buffer should be accelerated,
 913:      * false otherwise
 914:      */
 915:     WindowBltBufferStrategy(int numBuffers, boolean accelerated)
 916:     {
 917:       super(numBuffers,
 918:         new BufferCapabilities(new ImageCapabilities(accelerated),
 919:                    new ImageCapabilities(accelerated),
 920:                    BufferCapabilities.FlipContents.COPIED));
 921:     }
 922:   }
 923: 
 924:   /**
 925:    * A FlipBufferStrategy for windows.
 926:    */
 927:   private class WindowFlipBufferStrategy extends FlipBufferStrategy
 928:   {
 929:     /**
 930:      * Creates a flip buffer strategy for this window.
 931:      *
 932:      * @param numBuffers the number of buffers in this strategy
 933:      *
 934:      * @throws AWTException if the requested number of buffers is not
 935:      * supported
 936:      */
 937:     WindowFlipBufferStrategy(int numBuffers)
 938:       throws AWTException
 939:     {
 940:       super(numBuffers,
 941:         new BufferCapabilities(new ImageCapabilities(true),
 942:                    new ImageCapabilities(true),
 943:                    BufferCapabilities.FlipContents.COPIED));
 944:     }
 945:   }
 946: 
 947:   /**
 948:    * Creates a buffering strategy that manages how this window is
 949:    * repainted.  This method attempts to create the optimum strategy
 950:    * based on the desired number of buffers.  Hardware or software
 951:    * acceleration may be used.
 952:    *
 953:    * createBufferStrategy attempts different levels of optimization,
 954:    * but guarantees that some strategy with the requested number of
 955:    * buffers will be created even if it is not optimal.  First it
 956:    * attempts to create a page flipping strategy, then an accelerated
 957:    * blitting strategy, then an unaccelerated blitting strategy.
 958:    *
 959:    * Calling this method causes any existing buffer strategy to be
 960:    * destroyed.
 961:    *
 962:    * @param numBuffers the number of buffers in this strategy
 963:    *
 964:    * @throws IllegalArgumentException if requested number of buffers
 965:    * is less than one
 966:    * @throws IllegalStateException if this window is not displayable
 967:    *
 968:    * @since 1.4
 969:    */
 970:   public void createBufferStrategy(int numBuffers)
 971:   {
 972:     if (numBuffers < 1)
 973:       throw new IllegalArgumentException("Window.createBufferStrategy: number"
 974:                      + " of buffers is less than one");
 975: 
 976:     if (!isDisplayable())
 977:       throw new IllegalStateException("Window.createBufferStrategy: window is"
 978:                       + " not displayable");
 979: 
 980:     BufferStrategy newStrategy = null;
 981: 
 982:     // try a flipping strategy
 983:     try
 984:       {
 985:     newStrategy = new WindowFlipBufferStrategy(numBuffers);
 986:       }
 987:     catch (AWTException e)
 988:       {
 989:       }
 990: 
 991:     // fall back to an accelerated blitting strategy
 992:     if (newStrategy == null)
 993:       newStrategy = new WindowBltBufferStrategy(numBuffers, true);
 994: 
 995:     bufferStrategy = newStrategy;
 996:   }
 997: 
 998:   /**
 999:    * Creates a buffering strategy that manages how this window is
1000:    * repainted.  This method attempts to create a strategy based on
1001:    * the specified capabilities and throws an exception if the
1002:    * requested strategy is not supported.
1003:    *
1004:    * Calling this method causes any existing buffer strategy to be
1005:    * destroyed.
1006:    *
1007:    * @param numBuffers the number of buffers in this strategy
1008:    * @param caps the requested buffering capabilities
1009:    *
1010:    * @throws AWTException if the requested capabilities are not
1011:    * supported
1012:    * @throws IllegalArgumentException if requested number of buffers
1013:    * is less than one or if caps is null
1014:    *
1015:    * @since 1.4
1016:    */
1017:   public void createBufferStrategy(int numBuffers, BufferCapabilities caps)
1018:     throws AWTException
1019:   {
1020:     if (numBuffers < 1)
1021:       throw new IllegalArgumentException("Window.createBufferStrategy: number"
1022:                      + " of buffers is less than one");
1023: 
1024:     if (caps == null)
1025:       throw new IllegalArgumentException("Window.createBufferStrategy:"
1026:                      + " capabilities object is null");
1027: 
1028:     // a flipping strategy was requested
1029:     if (caps.isPageFlipping())
1030:       bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
1031:     else
1032:       bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
1033:   }
1034: 
1035:   /**
1036:    * Returns the buffer strategy used by the window.
1037:    *
1038:    * @return the buffer strategy.
1039:    * @since 1.4
1040:    */
1041:   public BufferStrategy getBufferStrategy()
1042:   {
1043:     return bufferStrategy;
1044:   }
1045: 
1046:   /**
1047:    * @since 1.2
1048:    *
1049:    * @deprecated
1050:    */
1051:   public void applyResourceBundle(ResourceBundle rb)
1052:     throws NotImplementedException
1053:   {
1054:     throw new Error ("Not implemented");
1055:   }
1056: 
1057:   /**
1058:    * @since 1.2
1059:    *
1060:    * @deprecated
1061:    */
1062:   public void applyResourceBundle(String rbName)
1063:   {
1064:     ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
1065:       ClassLoader.getSystemClassLoader());
1066:     if (rb != null)
1067:       applyResourceBundle(rb);    
1068:   }
1069: 
1070:   /**
1071:    * Gets the AccessibleContext associated with this <code>Window</code>.
1072:    * The context is created, if necessary.
1073:    *
1074:    * @return the associated context
1075:    */
1076:   public AccessibleContext getAccessibleContext()
1077:   {
1078:     /* Create the context if this is the first request */
1079:     if (accessibleContext == null)
1080:       accessibleContext = new AccessibleAWTWindow();
1081:     return accessibleContext;
1082:   }
1083: 
1084:   /** 
1085:    * Get graphics configuration.  The implementation for Window will
1086:    * not ask any parent containers, since Window is a toplevel
1087:    * window and not actually embedded in the parent component.
1088:    */
1089:   public GraphicsConfiguration getGraphicsConfiguration()
1090:   {
1091:     if (graphicsConfiguration != null) return graphicsConfiguration;
1092:     if (peer != null) return peer.getGraphicsConfiguration();
1093:     return null;
1094:   }
1095: 
1096:   protected void processWindowFocusEvent(WindowEvent event)
1097:   {
1098:     if (windowFocusListener != null)
1099:       {
1100:         switch (event.getID ())
1101:           {
1102:           case WindowEvent.WINDOW_GAINED_FOCUS:
1103:             windowFocusListener.windowGainedFocus (event);
1104:             break;
1105:             
1106:           case WindowEvent.WINDOW_LOST_FOCUS:
1107:             windowFocusListener.windowLostFocus (event);
1108:             break;
1109:             
1110:           default:
1111:             break;
1112:           }
1113:       }
1114:   }
1115:   
1116:   /**
1117:    * @since 1.4
1118:    */
1119:   protected void processWindowStateEvent(WindowEvent event)
1120:   {
1121:     if (windowStateListener != null
1122:         && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
1123:       windowStateListener.windowStateChanged (event);
1124:   }
1125: 
1126:   /**
1127:    * Returns whether this <code>Window</code> can get the focus or not.
1128:    *
1129:    * @since 1.4
1130:    */
1131:   public final boolean isFocusableWindow ()
1132:   {
1133:     if (getFocusableWindowState () == false)
1134:       return false;
1135: 
1136:     if (this instanceof Dialog
1137:         || this instanceof Frame)
1138:       return true;
1139: 
1140:     // FIXME: Implement more possible cases for returning true.
1141: 
1142:     return false;
1143:   }
1144:   
1145:   /**
1146:    * Returns the value of the focusableWindowState property.
1147:    * 
1148:    * @since 1.4
1149:    */
1150:   public boolean getFocusableWindowState ()
1151:   {
1152:     return focusableWindowState;
1153:   }
1154: 
1155:   /**
1156:    * Sets the value of the focusableWindowState property.
1157:    * 
1158:    * @since 1.4
1159:    */
1160:   public void setFocusableWindowState (boolean focusableWindowState)
1161:   {
1162:     this.focusableWindowState = focusableWindowState;
1163:   }
1164:   
1165:   /**
1166:    * Check whether this Container is a focus cycle root.
1167:    * Returns always <code>true</code> as Windows are the 
1168:    * root of the focus cycle.
1169:    *
1170:    * @return Always <code>true</code>.
1171:    *
1172:    * @since 1.4
1173:    */
1174:   public final boolean isFocusCycleRoot()
1175:   {
1176:     return true;
1177:   }
1178: 
1179:   /**
1180:    * Set whether or not this Container is the root of a focus
1181:    * traversal cycle. Windows are the root of the focus cycle
1182:    * and therefore this method does nothing.
1183:    * 
1184:    * @param focusCycleRoot ignored.
1185:    *
1186:    * @since 1.4
1187:    */
1188:   public final void setFocusCycleRoot(boolean focusCycleRoot)
1189:   {
1190:     // calls to the method are ignored
1191:   }
1192: 
1193:   /**
1194:    * Returns the root container that owns the focus cycle where this
1195:    * component resides. Windows have no ancestors and this method
1196:    * returns always <code>null</code>.
1197:    *
1198:    * @return Always <code>null</code>.
1199:    * @since 1.4
1200:    */
1201:   public final Container getFocusCycleRootAncestor()
1202:   {
1203:     return null;
1204:   }
1205: 
1206:   /**
1207:    * Generate a unique name for this window.
1208:    *
1209:    * @return A unique name for this window.
1210:    */
1211:   String generateName()
1212:   {
1213:     return "win" + getUniqueLong();
1214:   }
1215: 
1216:   private static synchronized long getUniqueLong()
1217:   {
1218:     return next_window_number++;
1219:   }
1220: }