Frames | No Frames |
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: }