Source for java.awt.Frame

   1: /* Frame.java -- AWT toplevel window
   2:    Copyright (C) 1999, 2000, 2002, 2004, 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.FramePeer;
  43: import java.lang.ref.Reference;
  44: import java.lang.ref.ReferenceQueue;
  45: import java.lang.ref.WeakReference;
  46: import java.util.ArrayList;
  47: import java.util.Vector;
  48: 
  49: import javax.accessibility.AccessibleContext;
  50: import javax.accessibility.AccessibleRole;
  51: import javax.accessibility.AccessibleState;
  52: import javax.accessibility.AccessibleStateSet;
  53: 
  54: /**
  55:   * This class is a top-level window with a title bar and window
  56:   * decorations.
  57:   *
  58:   * @author Aaron M. Renn (arenn@urbanophile.com)
  59:   */
  60: public class Frame extends Window implements MenuContainer
  61: {
  62: 
  63:   /**
  64:    * Constant for the default cursor.
  65:    *
  66:    * @deprecated Replaced by <code>Cursor.DEFAULT_CURSOR</code> instead.
  67:    */
  68:   public static final int DEFAULT_CURSOR = Cursor.DEFAULT_CURSOR;
  69: 
  70:   /**
  71:    * Constant for a cross-hair cursor.
  72:    *
  73:    * @deprecated Use <code>Cursor.CROSSHAIR_CURSOR</code> instead.
  74:    */
  75:   public static final int CROSSHAIR_CURSOR = Cursor.CROSSHAIR_CURSOR;
  76: 
  77:   /**
  78:    * Constant for a cursor over a text field.
  79:    *
  80:    * @deprecated Use <code>Cursor.TEXT_CURSOR</code> instead.
  81:    */
  82:   public static final int TEXT_CURSOR = Cursor.TEXT_CURSOR;
  83: 
  84:   /**
  85:    * Constant for a cursor to display while waiting for an action to complete.
  86:    *
  87:    * @deprecated Use <code>Cursor.WAIT_CURSOR</code>.
  88:    */
  89:   public static final int WAIT_CURSOR = Cursor.WAIT_CURSOR;
  90: 
  91:   /**
  92:    * Cursor used over SW corner of window decorations.
  93:    *
  94:    * @deprecated Use <code>Cursor.SW_RESIZE_CURSOR</code> instead.
  95:    */
  96:   public static final int SW_RESIZE_CURSOR = Cursor.SW_RESIZE_CURSOR;
  97: 
  98:   /**
  99:    * Cursor used over SE corner of window decorations.
 100:    * @deprecated Use <code>Cursor.SE_RESIZE_CURSOR</code> instead.
 101:    */
 102:   public static final int SE_RESIZE_CURSOR = Cursor.SE_RESIZE_CURSOR;
 103: 
 104:   /**
 105:    * Cursor used over NW corner of window decorations.
 106:    *
 107:    * @deprecated Use <code>Cursor.NW_RESIZE_CURSOR</code> instead.
 108:    */
 109:   public static final int NW_RESIZE_CURSOR = Cursor.NW_RESIZE_CURSOR;
 110: 
 111:   /**
 112:    * Cursor used over NE corner of window decorations.
 113:    *
 114:    * @deprecated Use <code>Cursor.NE_RESIZE_CURSOR</code> instead.
 115:    */
 116:   public static final int NE_RESIZE_CURSOR = Cursor.NE_RESIZE_CURSOR;
 117: 
 118:   /**
 119:    * Cursor used over N edge of window decorations.
 120:    *
 121:    * @deprecated Use <code>Cursor.N_RESIZE_CURSOR</code> instead.
 122:    */
 123:   public static final int N_RESIZE_CURSOR = Cursor.N_RESIZE_CURSOR;
 124: 
 125:   /**
 126:    * Cursor used over S edge of window decorations.
 127:    *
 128:    * @deprecated Use <code>Cursor.S_RESIZE_CURSOR</code> instead.
 129:    */
 130:   public static final int S_RESIZE_CURSOR = Cursor.S_RESIZE_CURSOR;
 131: 
 132:   /**
 133:    * Cursor used over E edge of window decorations.
 134:    *
 135:    * @deprecated Use <code>Cursor.E_RESIZE_CURSOR</code> instead.
 136:    */
 137:   public static final int E_RESIZE_CURSOR = Cursor.E_RESIZE_CURSOR;
 138: 
 139:   /**
 140:    * Cursor used over W edge of window decorations.
 141:    *
 142:    * @deprecated Use <code>Cursor.W_RESIZE_CURSOR</code> instead.
 143:    */
 144:   public static final int W_RESIZE_CURSOR = Cursor.W_RESIZE_CURSOR;
 145: 
 146:   /**
 147:    * Constant for a hand cursor.
 148:    *
 149:    * @deprecated Use <code>Cursor.HAND_CURSOR</code> instead.
 150:    */
 151:   public static final int HAND_CURSOR = Cursor.HAND_CURSOR;
 152: 
 153:   /**
 154:    * Constant for a cursor used during window move operations.
 155:    *
 156:    * @deprecated Use <code>Cursor.MOVE_CURSOR</code> instead.
 157:    */
 158:   public static final int MOVE_CURSOR = Cursor.MOVE_CURSOR;
 159: 
 160:   public static final int ICONIFIED = 1;
 161:   public static final int MAXIMIZED_BOTH = 6;
 162:   public static final int MAXIMIZED_HORIZ = 2;
 163:   public static final int MAXIMIZED_VERT = 4;
 164:   public static final int NORMAL = 0;
 165: 
 166: //Serialization version constant
 167:   private static final long serialVersionUID = 2673458971256075116L;
 168: 
 169:   /**
 170:    * @serial The version of the class data being serialized
 171:    * FIXME: what is this value?
 172:    */
 173:   private int frameSerializedDataVersion;
 174: 
 175:   /**
 176:    * @serial Image used as the icon when this frame is minimized.
 177:    */
 178:   private Image icon;
 179: 
 180:   /**
 181:    * @serial Constant used by the JDK Motif peer set.  Not used in
 182:    * this implementation.
 183:    */
 184:   private boolean mbManagement;
 185: 
 186:   /**
 187:    * @serial The menu bar for this frame.
 188:    */
 189:   private MenuBar menuBar;
 190: 
 191:   /**
 192:    * @serial A list of other top-level windows owned by this window.
 193:    */
 194:   Vector ownedWindows = new Vector();
 195: 
 196:   /**
 197:    * @serial Indicates whether or not this frame is resizable.
 198:    */
 199:   private boolean resizable = true;
 200: 
 201:   /**
 202:    * @serial The state of this frame.
 203:    * // FIXME: What are the values here?
 204:    * This is package-private to avoid an accessor method.
 205:    */
 206:   int state;
 207: 
 208:   /**
 209:    * @serial The title of the frame.
 210:    */
 211:   private String title = "";
 212: 
 213:   /**
 214:    * Maximized bounds for this frame.
 215:    */
 216:   private Rectangle maximizedBounds;
 217: 
 218:   /**
 219:    * This field indicates whether the frame is undecorated or not.
 220:    */
 221:   private boolean undecorated = false;
 222: 
 223:   /*
 224:    * The number used to generate the name returned by getName.
 225:    */
 226:   private static transient long next_frame_number;
 227: 
 228:   /**
 229:    * Initializes a new instance of <code>Frame</code> that is not visible
 230:    * and has no title.
 231:    */
 232:   public Frame()
 233:   {
 234:     this("");
 235:     noteFrame(this);
 236:   }
 237: 
 238:   /**
 239:    * Initializes a new instance of <code>Frame</code> that is not visible
 240:    * and has the specified title.
 241:    *
 242:    * @param title the title of this frame
 243:    */
 244:   public Frame(String title)
 245:   {
 246:     super();
 247:     this.title = title;
 248:     // Top-level frames are initially invisible.
 249:     visible = false;
 250:     noteFrame(this);
 251:   }
 252: 
 253:   public Frame(GraphicsConfiguration gc)
 254:   {
 255:     super(gc);
 256:     visible = false;
 257:     noteFrame(this);
 258:   }
 259: 
 260:   public Frame(String title, GraphicsConfiguration gc)
 261:   {
 262:     super(gc);
 263:     setTitle(title);
 264:     visible = false;
 265:     noteFrame(this);
 266:   }
 267: 
 268:   /**
 269:    * Returns this frame's title string.
 270:    *
 271:    * @return this frame's title string
 272:    */
 273:   public String getTitle()
 274:   {
 275:     return title;
 276:   }
 277: 
 278:   /**
 279:    * Sets this frame's title to the specified value.
 280:    *
 281:    * @param title the new frame title
 282:    */
 283:   public synchronized void setTitle(String title)
 284:   {
 285:     this.title = title;
 286:     if (peer != null)
 287:       ((FramePeer) peer).setTitle(title);
 288:   }
 289: 
 290:   /**
 291:    * Returns this frame's icon.
 292:    *
 293:    * @return this frame's icon, or <code>null</code> if this frame does not
 294:    *         have an icon
 295:    */
 296:   public Image getIconImage()
 297:   {
 298:     return icon;
 299:   }
 300: 
 301:   /**
 302:    * Sets this frame's icon to the specified value.
 303:    *
 304:    * @icon the new icon for this frame
 305:    */
 306:   public synchronized void setIconImage(Image icon)
 307:   {
 308:     this.icon = icon;
 309:     if (peer != null)
 310:       ((FramePeer) peer).setIconImage(icon);
 311:   }
 312: 
 313:   /**
 314:    * Returns this frame's menu bar.
 315:    *
 316:    * @return this frame's menu bar, or <code>null</code> if this frame
 317:    *         does not have a menu bar
 318:    */
 319:   public MenuBar getMenuBar()
 320:   {
 321:     return menuBar;
 322:   }
 323: 
 324:   /**
 325:    * Sets this frame's menu bar. Removes any existing menu bar. If the
 326:    * given menu bar is part of another frame it will be removed from
 327:    * that frame.
 328:    *
 329:    * @param menuBar the new menu bar for this frame
 330:    */
 331:   public synchronized void setMenuBar(MenuBar menuBar)
 332:   {
 333:     if (this.menuBar != null)
 334:       remove(this.menuBar);
 335: 
 336:     this.menuBar = menuBar;
 337:     if (menuBar != null)
 338:       {
 339:     MenuContainer parent = menuBar.getParent();
 340:     if (parent != null)
 341:       parent.remove(menuBar);
 342:     menuBar.setParent(this);
 343: 
 344:         // Create local copy for thread safety.
 345:         FramePeer p = (FramePeer) peer;
 346:         if (p != null)
 347:           {
 348:             if (menuBar != null)
 349:               menuBar.addNotify();
 350:             if (valid)
 351:               invalidate();
 352:             p.setMenuBar(menuBar);
 353:           }
 354:       }
 355:   }
 356: 
 357:   /**
 358:    * Tests whether or not this frame is resizable.  This will be 
 359:    * <code>true</code> by default.
 360:    *
 361:    * @return <code>true</code> if this frame is resizable, <code>false</code>
 362:    *         otherwise
 363:    */
 364:   public boolean isResizable()
 365:   {
 366:     return resizable;
 367:   }
 368: 
 369:   /**
 370:    * Sets the resizability of this frame to the specified value.
 371:    *
 372:    * @param resizable <code>true</code> to make the frame resizable,
 373:    * <code>false</code> to make it non-resizable
 374:    */
 375:   public synchronized void setResizable(boolean resizable)
 376:   {
 377:     this.resizable = resizable;
 378:     if (peer != null)
 379:       ((FramePeer) peer).setResizable(resizable);
 380:   }
 381: 
 382:   /**
 383:    * Returns the cursor type of the cursor for this window.  This will
 384:    * be one of the constants in this class.
 385:    *
 386:    * @return the cursor type for this frame
 387:    *
 388:    * @deprecated Use <code>Component.getCursor()</code> instead.
 389:    */
 390:   public int getCursorType()
 391:   {
 392:     return getCursor().getType();
 393:   }
 394: 
 395:   /**
 396:    * Sets the cursor for this window to the specified type.  The specified
 397:    * type should be one of the constants in this class.
 398:    *
 399:    * @param type the cursor type
 400:    *
 401:    * @deprecated Use <code>Component.setCursor(Cursor)</code> instead.
 402:    */
 403:   public void setCursor(int type)
 404:   {
 405:     setCursor(new Cursor(type));
 406:   }
 407: 
 408:   /**
 409:    * Removes the specified menu component from this frame. If it is
 410:    * the current MenuBar it is removed from the frame. If it is a
 411:    * Popup it is removed from this component. If it is any other menu
 412:    * component it is ignored.
 413:    *
 414:    * @param menu the menu component to remove
 415:    */
 416:   public void remove(MenuComponent menu)
 417:   {
 418:     if (menu == menuBar)
 419:       {
 420:     if (menuBar != null)
 421:       {
 422:         if (peer != null)
 423:           {
 424:         ((FramePeer) peer).setMenuBar(null);
 425:         menuBar.removeNotify();
 426:           }
 427:         menuBar.setParent(null);
 428:       }
 429:     menuBar = null;
 430:       }
 431:     else
 432:       super.remove(menu);
 433:   }
 434: 
 435:   public void addNotify()
 436:   {
 437:     if (menuBar != null)
 438:       menuBar.addNotify();
 439:     if (peer == null)
 440:       peer = getToolkit ().createFrame (this);
 441: 
 442:     super.addNotify();
 443:   }
 444: 
 445:   public void removeNotify()
 446:   {
 447:     if (menuBar != null)
 448:       menuBar.removeNotify();
 449:     super.removeNotify();
 450:   }
 451: 
 452:   /**
 453:    * Returns a debugging string describing this window.
 454:    *
 455:    * @return a debugging string describing this window
 456:    */
 457:   protected String paramString()
 458:   {
 459:     String title = getTitle();
 460: 
 461:     String resizable = "";
 462:     if (isResizable ())
 463:       resizable = ",resizable";
 464: 
 465:     String state = "";
 466:     switch (getState ())
 467:       {
 468:       case NORMAL:
 469:         state = ",normal";
 470:         break;
 471:       case ICONIFIED:
 472:         state = ",iconified";
 473:         break;
 474:       case MAXIMIZED_BOTH:
 475:         state = ",maximized-both";
 476:         break;
 477:       case MAXIMIZED_HORIZ:
 478:         state = ",maximized-horiz";
 479:         break;
 480:       case MAXIMIZED_VERT:
 481:         state = ",maximized-vert";
 482:         break;
 483:       }
 484: 
 485:     return super.paramString () + ",title=" + title + resizable + state;
 486:   }
 487: 
 488:   /**
 489:    * The list of active frames. GC'ed frames get removed in noteFrame().
 490:    */
 491:   private static ArrayList<WeakReference<Frame>> weakFrames =
 492:     new ArrayList<WeakReference<Frame>>();
 493: 
 494:   /**
 495:    * The death queue for all frames.
 496:    */ 
 497:   private static ReferenceQueue weakFramesQueue =
 498:     new ReferenceQueue<Frame>();
 499: 
 500:   private static void noteFrame(Frame f)
 501:   {
 502:     synchronized (weakFrames)
 503:       {
 504:         // Remove GCed frames from the list.
 505:         Reference ref = weakFramesQueue.poll();
 506:         while (ref != null)
 507:           {
 508:             weakFrames.remove(ref);
 509:             ref = weakFramesQueue.poll();
 510:           }
 511:         // Add new frame.
 512:         weakFrames.add(new WeakReference<Frame>(f));
 513:       }
 514:   }
 515: 
 516:   /**
 517:    * Returns <code>true</code> when there are any displayable frames,
 518:    * <code>false</code> otherwise.
 519:    *
 520:    * @return <code>true</code> when there are any displayable frames,
 521:    *         <code>false</code> otherwise
 522:    */
 523:   static boolean hasDisplayableFrames()
 524:   {
 525:     synchronized (weakFrames)
 526:       {
 527:         for (WeakReference<Frame> r : Frame.weakFrames)
 528:           {
 529:             Frame f = (Frame) r.get();
 530:             if (f != null && f.isDisplayable())
 531:               return true;
 532:           }
 533:       }
 534:     return false;
 535:   }
 536: 
 537:   public static Frame[] getFrames()
 538:   {
 539:     synchronized (weakFrames)
 540:       {
 541:         ArrayList<Frame> existingFrames = new ArrayList<Frame>();
 542:         for (WeakReference<Frame> ref : weakFrames)
 543:           {
 544:             Frame f = ref.get();
 545:             if (f != null)
 546:               {
 547:                 existingFrames.add(f);
 548:               }
 549:           }
 550:         Frame[] frames = new Frame[existingFrames.size()];
 551:         frames = existingFrames.toArray(frames);
 552:         return frames;
 553:       }
 554:   }
 555: 
 556:   public void setState(int state)
 557:   {
 558:     int current_state = getExtendedState ();
 559: 
 560:     if (state == NORMAL
 561:         && (current_state & ICONIFIED) != 0)
 562:       setExtendedState(current_state | ICONIFIED);
 563:     
 564:     if (state == ICONIFIED
 565:         && (current_state & ~ICONIFIED) == 0)
 566:       setExtendedState(current_state & ~ICONIFIED);
 567:   }
 568: 
 569:   public int getState()
 570:   {
 571:     return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
 572:   }
 573: 
 574:   /**
 575:    * @since 1.4
 576:    */
 577:   public void setExtendedState(int state)
 578:   {
 579:     if (getToolkit().isFrameStateSupported(state))
 580:       {
 581:         this.state = state;
 582:         FramePeer p = (FramePeer) peer;
 583:         if (p != null)
 584:           p.setState(state);
 585:       }
 586:   }
 587: 
 588:   /**
 589:    * @since 1.4
 590:    */
 591:   public int getExtendedState()
 592:   {
 593:     FramePeer p = (FramePeer) peer;
 594:     if (p != null)
 595:       state = p.getState();
 596:     return state;
 597:   }
 598: 
 599:   /**
 600:    * @since 1.4
 601:    */
 602:   public void setMaximizedBounds(Rectangle maximizedBounds)
 603:   {
 604:     this.maximizedBounds = maximizedBounds;
 605:   }
 606: 
 607:   /**
 608:    * Returns the maximized bounds of this frame.
 609:    *
 610:    * @return the maximized rectangle, may be null
 611:    *
 612:    * @since 1.4
 613:    */
 614:   public Rectangle getMaximizedBounds()
 615:   {
 616:     return maximizedBounds;
 617:   }
 618: 
 619:   /**
 620:    * Returns whether this frame is undecorated or not.
 621:    * 
 622:    * @since 1.4
 623:    */
 624:   public boolean isUndecorated()
 625:   {
 626:     return undecorated;
 627:   }
 628: 
 629:   /**
 630:    * Disables or enables decorations for this frame. This method can only be
 631:    * called while the frame is not displayable.
 632:    * 
 633:    * @throws IllegalComponentStateException if this frame is displayable
 634:    * 
 635:    * @since 1.4
 636:    */
 637:   public void setUndecorated(boolean undecorated)
 638:   {
 639:     if (isDisplayable())
 640:       throw new IllegalComponentStateException();
 641: 
 642:     this.undecorated = undecorated;
 643:   }
 644: 
 645:   /**
 646:    * Generate a unique name for this frame.
 647:    *
 648:    * @return a unique name for this frame
 649:    */
 650:   String generateName()
 651:   {
 652:     return "frame" + getUniqueLong();
 653:   }
 654: 
 655:   private static synchronized long getUniqueLong()
 656:   {
 657:     return next_frame_number++;
 658:   }
 659:   
 660:   /**
 661:    * Accessibility support for <code>Frame</code>.
 662:    */
 663:   protected class AccessibleAWTFrame extends AccessibleAWTWindow
 664:   {
 665:     private static final long serialVersionUID = -6172960752956030250L;
 666: 
 667:     /**
 668:      * Gets the role of this object.
 669:      * @return AccessibleRole.FRAME
 670:      */
 671:     public AccessibleRole getAccessibleRole()
 672:     {
 673:       return AccessibleRole.FRAME;
 674:     }
 675:     
 676:     /**
 677:      * Gets the state set of this object.
 678:      * @return The current state of this frame.
 679:      */
 680:     public AccessibleStateSet getAccessibleStateSet()
 681:     {
 682:       AccessibleStateSet states = super.getAccessibleStateSet();
 683:       if (isResizable())
 684:         states.add(AccessibleState.RESIZABLE);
 685:       if ((state & ICONIFIED) != 0)
 686:         states.add(AccessibleState.ICONIFIED);
 687:       return states;
 688:     }
 689:   }
 690:   
 691:   /**
 692:    * Gets the AccessibleContext associated with this <code>Frame</code>.
 693:    * The context is created, if necessary.
 694:    *
 695:    * @return the associated context
 696:    */
 697:   public AccessibleContext getAccessibleContext()
 698:   {
 699:     // Create the context if this is the first request.
 700:     if (accessibleContext == null)
 701:       accessibleContext = new AccessibleAWTFrame();
 702:     return accessibleContext;
 703:   }
 704: }