1 /* 2 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.peer.FramePeer; 28 import java.awt.event.*; 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.List; 32 import java.util.Vector; 33 import java.io.Serializable; 34 import java.io.ObjectOutputStream; 35 import java.io.ObjectInputStream; 36 import java.io.IOException; 37 import sun.awt.AppContext; 38 import sun.awt.SunToolkit; 39 import sun.awt.AWTAccessor; 40 import java.lang.ref.WeakReference; 41 import javax.accessibility.*; 42 43 /** 44 * A <code>Frame</code> is a top-level window with a title and a border. 45 * <p> 46 * The size of the frame includes any area designated for the 47 * border. The dimensions of the border area may be obtained 48 * using the <code>getInsets</code> method, however, since 49 * these dimensions are platform-dependent, a valid insets 50 * value cannot be obtained until the frame is made displayable 51 * by either calling <code>pack</code> or <code>show</code>. 52 * Since the border area is included in the overall size of the 53 * frame, the border effectively obscures a portion of the frame, 54 * constraining the area available for rendering and/or displaying 55 * subcomponents to the rectangle which has an upper-left corner 56 * location of <code>(insets.left, insets.top)</code>, and has a size of 57 * <code>width - (insets.left + insets.right)</code> by 58 * <code>height - (insets.top + insets.bottom)</code>. 59 * <p> 60 * The default layout for a frame is <code>BorderLayout</code>. 61 * <p> 62 * A frame may have its native decorations (i.e. <code>Frame</code> 63 * and <code>Titlebar</code>) turned off 64 * with <code>setUndecorated</code>. This can only be done while the frame 65 * is not {@link Component#isDisplayable() displayable}. 66 * <p> 67 * In a multi-screen environment, you can create a <code>Frame</code> 68 * on a different screen device by constructing the <code>Frame</code> 69 * with {@link #Frame(GraphicsConfiguration)} or 70 * {@link #Frame(String title, GraphicsConfiguration)}. The 71 * <code>GraphicsConfiguration</code> object is one of the 72 * <code>GraphicsConfiguration</code> objects of the target screen 73 * device. 74 * <p> 75 * In a virtual device multi-screen environment in which the desktop 76 * area could span multiple physical screen devices, the bounds of all 77 * configurations are relative to the virtual-coordinate system. The 78 * origin of the virtual-coordinate system is at the upper left-hand 79 * corner of the primary physical screen. Depending on the location 80 * of the primary screen in the virtual device, negative coordinates 81 * are possible, as shown in the following figure. 82 * <p> 83 * <img src="doc-files/MultiScreen.gif" 84 * alt="Diagram of virtual device encompassing three physical screens and one primary physical screen. The primary physical screen 85 * shows (0,0) coords while a different physical screen shows (-80,-100) coords." 86 * ALIGN=center HSPACE=10 VSPACE=7> 87 * <p> 88 * In such an environment, when calling <code>setLocation</code>, 89 * you must pass a virtual coordinate to this method. Similarly, 90 * calling <code>getLocationOnScreen</code> on a <code>Frame</code> 91 * returns virtual device coordinates. Call the <code>getBounds</code> 92 * method of a <code>GraphicsConfiguration</code> to find its origin in 93 * the virtual coordinate system. 94 * <p> 95 * The following code sets the 96 * location of the <code>Frame</code> at (10, 10) relative 97 * to the origin of the physical screen of the corresponding 98 * <code>GraphicsConfiguration</code>. If the bounds of the 99 * <code>GraphicsConfiguration</code> is not taken into account, the 100 * <code>Frame</code> location would be set at (10, 10) relative to the 101 * virtual-coordinate system and would appear on the primary physical 102 * screen, which might be different from the physical screen of the 103 * specified <code>GraphicsConfiguration</code>. 104 * 105 * <pre> 106 * Frame f = new Frame(GraphicsConfiguration gc); 107 * Rectangle bounds = gc.getBounds(); 108 * f.setLocation(10 + bounds.x, 10 + bounds.y); 109 * </pre> 110 * 111 * <p> 112 * Frames are capable of generating the following types of 113 * <code>WindowEvent</code>s: 114 * <ul> 115 * <li><code>WINDOW_OPENED</code> 116 * <li><code>WINDOW_CLOSING</code>: 117 * <br>If the program doesn't 118 * explicitly hide or dispose the window while processing 119 * this event, the window close operation is canceled. 120 * <li><code>WINDOW_CLOSED</code> 121 * <li><code>WINDOW_ICONIFIED</code> 122 * <li><code>WINDOW_DEICONIFIED</code> 123 * <li><code>WINDOW_ACTIVATED</code> 124 * <li><code>WINDOW_DEACTIVATED</code> 125 * <li><code>WINDOW_GAINED_FOCUS</code> 126 * <li><code>WINDOW_LOST_FOCUS</code> 127 * <li><code>WINDOW_STATE_CHANGED</code> 128 * </ul> 129 * 130 * @author Sami Shaio 131 * @see WindowEvent 132 * @see Window#addWindowListener 133 * @since JDK1.0 134 */ 135 public class Frame extends Window implements MenuContainer { 136 137 /* Note: These are being obsoleted; programs should use the Cursor class 138 * variables going forward. See Cursor and Component.setCursor. 139 */ 140 141 /** 142 * @deprecated replaced by <code>Cursor.DEFAULT_CURSOR</code>. 143 */ 144 @Deprecated 145 public static final int DEFAULT_CURSOR = Cursor.DEFAULT_CURSOR; 146 147 148 /** 149 * @deprecated replaced by <code>Cursor.CROSSHAIR_CURSOR</code>. 150 */ 151 @Deprecated 152 public static final int CROSSHAIR_CURSOR = Cursor.CROSSHAIR_CURSOR; 153 154 /** 155 * @deprecated replaced by <code>Cursor.TEXT_CURSOR</code>. 156 */ 157 @Deprecated 158 public static final int TEXT_CURSOR = Cursor.TEXT_CURSOR; 159 160 /** 161 * @deprecated replaced by <code>Cursor.WAIT_CURSOR</code>. 162 */ 163 @Deprecated 164 public static final int WAIT_CURSOR = Cursor.WAIT_CURSOR; 165 166 /** 167 * @deprecated replaced by <code>Cursor.SW_RESIZE_CURSOR</code>. 168 */ 169 @Deprecated 170 public static final int SW_RESIZE_CURSOR = Cursor.SW_RESIZE_CURSOR; 171 172 /** 173 * @deprecated replaced by <code>Cursor.SE_RESIZE_CURSOR</code>. 174 */ 175 @Deprecated 176 public static final int SE_RESIZE_CURSOR = Cursor.SE_RESIZE_CURSOR; 177 178 /** 179 * @deprecated replaced by <code>Cursor.NW_RESIZE_CURSOR</code>. 180 */ 181 @Deprecated 182 public static final int NW_RESIZE_CURSOR = Cursor.NW_RESIZE_CURSOR; 183 184 /** 185 * @deprecated replaced by <code>Cursor.NE_RESIZE_CURSOR</code>. 186 */ 187 @Deprecated 188 public static final int NE_RESIZE_CURSOR = Cursor.NE_RESIZE_CURSOR; 189 190 /** 191 * @deprecated replaced by <code>Cursor.N_RESIZE_CURSOR</code>. 192 */ 193 @Deprecated 194 public static final int N_RESIZE_CURSOR = Cursor.N_RESIZE_CURSOR; 195 196 /** 197 * @deprecated replaced by <code>Cursor.S_RESIZE_CURSOR</code>. 198 */ 199 @Deprecated 200 public static final int S_RESIZE_CURSOR = Cursor.S_RESIZE_CURSOR; 201 202 /** 203 * @deprecated replaced by <code>Cursor.W_RESIZE_CURSOR</code>. 204 */ 205 @Deprecated 206 public static final int W_RESIZE_CURSOR = Cursor.W_RESIZE_CURSOR; 207 208 /** 209 * @deprecated replaced by <code>Cursor.E_RESIZE_CURSOR</code>. 210 */ 211 @Deprecated 212 public static final int E_RESIZE_CURSOR = Cursor.E_RESIZE_CURSOR; 213 214 /** 215 * @deprecated replaced by <code>Cursor.HAND_CURSOR</code>. 216 */ 217 @Deprecated 218 public static final int HAND_CURSOR = Cursor.HAND_CURSOR; 219 220 /** 221 * @deprecated replaced by <code>Cursor.MOVE_CURSOR</code>. 222 */ 223 @Deprecated 224 public static final int MOVE_CURSOR = Cursor.MOVE_CURSOR; 225 226 227 /** 228 * Frame is in the "normal" state. This symbolic constant names a 229 * frame state with all state bits cleared. 230 * @see #setExtendedState(int) 231 * @see #getExtendedState 232 */ 233 public static final int NORMAL = 0; 234 235 /** 236 * This state bit indicates that frame is iconified. 237 * @see #setExtendedState(int) 238 * @see #getExtendedState 239 */ 240 public static final int ICONIFIED = 1; 241 242 /** 243 * This state bit indicates that frame is maximized in the 244 * horizontal direction. 245 * @see #setExtendedState(int) 246 * @see #getExtendedState 247 * @since 1.4 248 */ 249 public static final int MAXIMIZED_HORIZ = 2; 250 251 /** 252 * This state bit indicates that frame is maximized in the 253 * vertical direction. 254 * @see #setExtendedState(int) 255 * @see #getExtendedState 256 * @since 1.4 257 */ 258 public static final int MAXIMIZED_VERT = 4; 259 260 /** 261 * This state bit mask indicates that frame is fully maximized 262 * (that is both horizontally and vertically). It is just a 263 * convenience alias for 264 * <code>MAXIMIZED_VERT | MAXIMIZED_HORIZ</code>. 265 * 266 * <p>Note that the correct test for frame being fully maximized is 267 * <pre> 268 * (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH 269 * </pre> 270 * 271 * <p>To test is frame is maximized in <em>some</em> direction use 272 * <pre> 273 * (state & Frame.MAXIMIZED_BOTH) != 0 274 * </pre> 275 * 276 * @see #setExtendedState(int) 277 * @see #getExtendedState 278 * @since 1.4 279 */ 280 public static final int MAXIMIZED_BOTH = MAXIMIZED_VERT | MAXIMIZED_HORIZ; 281 282 /** 283 * Maximized bounds for this frame. 284 * @see #setMaximizedBounds(Rectangle) 285 * @see #getMaximizedBounds 286 * @serial 287 * @since 1.4 288 */ 289 Rectangle maximizedBounds; 290 291 292 /** 293 * This is the title of the frame. It can be changed 294 * at any time. <code>title</code> can be null and if 295 * this is the case the <code>title</code> = "". 296 * 297 * @serial 298 * @see #getTitle 299 * @see #setTitle(String) 300 */ 301 String title = "Untitled"; 302 303 /** 304 * The frames menubar. If <code>menuBar</code> = null 305 * the frame will not have a menubar. 306 * 307 * @serial 308 * @see #getMenuBar 309 * @see #setMenuBar(MenuBar) 310 */ 311 MenuBar menuBar; 312 313 /** 314 * This field indicates whether the frame is resizable. 315 * This property can be changed at any time. 316 * <code>resizable</code> will be true if the frame is 317 * resizable, otherwise it will be false. 318 * 319 * @serial 320 * @see #isResizable() 321 */ 322 boolean resizable = true; 323 324 /** 325 * This field indicates whether the frame is undecorated. 326 * This property can only be changed while the frame is not displayable. 327 * <code>undecorated</code> will be true if the frame is 328 * undecorated, otherwise it will be false. 329 * 330 * @serial 331 * @see #setUndecorated(boolean) 332 * @see #isUndecorated() 333 * @see Component#isDisplayable() 334 * @since 1.4 335 */ 336 boolean undecorated = false; 337 338 /** 339 * <code>mbManagement</code> is only used by the Motif implementation. 340 * 341 * @serial 342 */ 343 boolean mbManagement = false; /* used only by the Motif impl. */ 344 345 // XXX: uwe: abuse old field for now 346 // will need to take care of serialization 347 private int state = NORMAL; 348 349 /* 350 * The Windows owned by the Frame. 351 * Note: in 1.2 this has been superceded by Window.ownedWindowList 352 * 353 * @serial 354 * @see java.awt.Window#ownedWindowList 355 */ 356 Vector ownedWindows; 357 358 private static final String base = "frame"; 359 private static int nameCounter = 0; 360 361 /* 362 * JDK 1.1 serialVersionUID 363 */ 364 private static final long serialVersionUID = 2673458971256075116L; 365 366 static { 367 /* ensure that the necessary native libraries are loaded */ 368 Toolkit.loadLibraries(); 369 if (!GraphicsEnvironment.isHeadless()) { 370 initIDs(); 371 } 372 } 373 374 /** 375 * Constructs a new instance of <code>Frame</code> that is 376 * initially invisible. The title of the <code>Frame</code> 377 * is empty. 378 * @exception HeadlessException when 379 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 380 * @see java.awt.GraphicsEnvironment#isHeadless() 381 * @see Component#setSize 382 * @see Component#setVisible(boolean) 383 */ 384 public Frame() throws HeadlessException { 385 this(""); 386 } 387 388 /** 389 * Constructs a new, initially invisible {@code Frame} with the 390 * specified {@code GraphicsConfiguration}. 391 * 392 * @param gc the <code>GraphicsConfiguration</code> 393 * of the target screen device. If <code>gc</code> 394 * is <code>null</code>, the system default 395 * <code>GraphicsConfiguration</code> is assumed. 396 * @exception IllegalArgumentException if 397 * <code>gc</code> is not from a screen device. 398 * @exception HeadlessException when 399 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 400 * @see java.awt.GraphicsEnvironment#isHeadless() 401 * @since 1.3 402 */ 403 public Frame(GraphicsConfiguration gc) { 404 this("", gc); 405 } 406 407 /** 408 * Constructs a new, initially invisible <code>Frame</code> object 409 * with the specified title. 410 * @param title the title to be displayed in the frame's border. 411 * A <code>null</code> value 412 * is treated as an empty string, "". 413 * @exception HeadlessException when 414 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 415 * @see java.awt.GraphicsEnvironment#isHeadless() 416 * @see java.awt.Component#setSize 417 * @see java.awt.Component#setVisible(boolean) 418 * @see java.awt.GraphicsConfiguration#getBounds 419 */ 420 public Frame(String title) throws HeadlessException { 421 init(title, null); 422 } 423 424 /** 425 * Constructs a new, initially invisible <code>Frame</code> object 426 * with the specified title and a 427 * <code>GraphicsConfiguration</code>. 428 * @param title the title to be displayed in the frame's border. 429 * A <code>null</code> value 430 * is treated as an empty string, "". 431 * @param gc the <code>GraphicsConfiguration</code> 432 * of the target screen device. If <code>gc</code> is 433 * <code>null</code>, the system default 434 * <code>GraphicsConfiguration</code> is assumed. 435 * @exception IllegalArgumentException if <code>gc</code> 436 * is not from a screen device. 437 * @exception HeadlessException when 438 * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code> 439 * @see java.awt.GraphicsEnvironment#isHeadless() 440 * @see java.awt.Component#setSize 441 * @see java.awt.Component#setVisible(boolean) 442 * @see java.awt.GraphicsConfiguration#getBounds 443 * @since 1.3 444 */ 445 public Frame(String title, GraphicsConfiguration gc) { 446 super(gc); 447 init(title, gc); 448 } 449 450 private void init(String title, GraphicsConfiguration gc) { 451 this.title = title; 452 SunToolkit.checkAndSetPolicy(this, false); 453 } 454 455 /** 456 * Construct a name for this component. Called by getName() when the 457 * name is null. 458 */ 459 String constructComponentName() { 460 synchronized (Frame.class) { 461 return base + nameCounter++; 462 } 463 } 464 465 /** 466 * Makes this Frame displayable by connecting it to 467 * a native screen resource. Making a frame displayable will 468 * cause any of its children to be made displayable. 469 * This method is called internally by the toolkit and should 470 * not be called directly by programs. 471 * @see Component#isDisplayable 472 * @see #removeNotify 473 */ 474 public void addNotify() { 475 synchronized (getTreeLock()) { 476 if (peer == null) { 477 peer = getToolkit().createFrame(this); 478 } 479 FramePeer p = (FramePeer)peer; 480 MenuBar menuBar = this.menuBar; 481 if (menuBar != null) { 482 mbManagement = true; 483 menuBar.addNotify(); 484 p.setMenuBar(menuBar); 485 } 486 p.setMaximizedBounds(maximizedBounds); 487 super.addNotify(); 488 } 489 } 490 491 /** 492 * Gets the title of the frame. The title is displayed in the 493 * frame's border. 494 * @return the title of this frame, or an empty string ("") 495 * if this frame doesn't have a title. 496 * @see #setTitle(String) 497 */ 498 public String getTitle() { 499 return title; 500 } 501 502 /** 503 * Sets the title for this frame to the specified string. 504 * @param title the title to be displayed in the frame's border. 505 * A <code>null</code> value 506 * is treated as an empty string, "". 507 * @see #getTitle 508 */ 509 public void setTitle(String title) { 510 String oldTitle = this.title; 511 if (title == null) { 512 title = ""; 513 } 514 515 516 synchronized(this) { 517 this.title = title; 518 FramePeer peer = (FramePeer)this.peer; 519 if (peer != null) { 520 peer.setTitle(title); 521 } 522 } 523 firePropertyChange("title", oldTitle, title); 524 } 525 526 /** 527 * Returns the image to be displayed as the icon for this frame. 528 * <p> 529 * This method is obsolete and kept for backward compatibility 530 * only. Use {@link Window#getIconImages Window.getIconImages()} instead. 531 * <p> 532 * If a list of several images was specified as a Window's icon, 533 * this method will return the first item of the list. 534 * 535 * @return the icon image for this frame, or <code>null</code> 536 * if this frame doesn't have an icon image. 537 * @see #setIconImage(Image) 538 * @see Window#getIconImages() 539 * @see Window#setIconImages 540 */ 541 public Image getIconImage() { 542 java.util.List<Image> icons = this.icons; 543 if (icons != null) { 544 if (icons.size() > 0) { 545 return icons.get(0); 546 } 547 } 548 return null; 549 } 550 551 /** 552 * {@inheritDoc} 553 */ 554 public void setIconImage(Image image) { 555 super.setIconImage(image); 556 } 557 558 /** 559 * Gets the menu bar for this frame. 560 * @return the menu bar for this frame, or <code>null</code> 561 * if this frame doesn't have a menu bar. 562 * @see #setMenuBar(MenuBar) 563 */ 564 public MenuBar getMenuBar() { 565 return menuBar; 566 } 567 568 /** 569 * Sets the menu bar for this frame to the specified menu bar. 570 * @param mb the menu bar being set. 571 * If this parameter is <code>null</code> then any 572 * existing menu bar on this frame is removed. 573 * @see #getMenuBar 574 */ 575 public void setMenuBar(MenuBar mb) { 576 synchronized (getTreeLock()) { 577 if (menuBar == mb) { 578 return; 579 } 580 if ((mb != null) && (mb.parent != null)) { 581 mb.parent.remove(mb); 582 } 583 if (menuBar != null) { 584 remove(menuBar); 585 } 586 menuBar = mb; 587 if (menuBar != null) { 588 menuBar.parent = this; 589 590 FramePeer peer = (FramePeer)this.peer; 591 if (peer != null) { 592 mbManagement = true; 593 menuBar.addNotify(); 594 invalidateIfValid(); 595 peer.setMenuBar(menuBar); 596 } 597 } 598 } 599 } 600 601 /** 602 * Indicates whether this frame is resizable by the user. 603 * By default, all frames are initially resizable. 604 * @return <code>true</code> if the user can resize this frame; 605 * <code>false</code> otherwise. 606 * @see java.awt.Frame#setResizable(boolean) 607 */ 608 public boolean isResizable() { 609 return resizable; 610 } 611 612 /** 613 * Sets whether this frame is resizable by the user. 614 * @param resizable <code>true</code> if this frame is resizable; 615 * <code>false</code> otherwise. 616 * @see java.awt.Frame#isResizable 617 */ 618 public void setResizable(boolean resizable) { 619 boolean oldResizable = this.resizable; 620 boolean testvalid = false; 621 622 synchronized (this) { 623 this.resizable = resizable; 624 FramePeer peer = (FramePeer)this.peer; 625 if (peer != null) { 626 peer.setResizable(resizable); 627 testvalid = true; 628 } 629 } 630 631 // On some platforms, changing the resizable state affects 632 // the insets of the Frame. If we could, we'd call invalidate() 633 // from the peer, but we need to guarantee that we're not holding 634 // the Frame lock when we call invalidate(). 635 if (testvalid) { 636 invalidateIfValid(); 637 } 638 firePropertyChange("resizable", oldResizable, resizable); 639 } 640 641 642 /** 643 * Sets the state of this frame (obsolete). 644 * <p> 645 * In older versions of JDK a frame state could only be NORMAL or 646 * ICONIFIED. Since JDK 1.4 set of supported frame states is 647 * expanded and frame state is represented as a bitwise mask. 648 * <p> 649 * For compatibility with applications developed 650 * earlier this method still accepts 651 * {@code Frame.NORMAL} and 652 * {@code Frame.ICONIFIED} only. The iconic 653 * state of the frame is only changed, other aspects 654 * of frame state are not affected by this method. If 655 * the state passed to this method is neither {@code 656 * Frame.NORMAL} nor {@code Frame.ICONIFIED} the 657 * method performs no actions at all. 658 * <p>Note that if the state is not supported on a 659 * given platform, neither the state nor the return 660 * value of the {@link #getState} method will be 661 * changed. The application may determine whether a 662 * specific state is supported via the {@link 663 * java.awt.Toolkit#isFrameStateSupported} method. 664 * <p><b>If the frame is currently visible on the 665 * screen</b> (the {@link #isShowing} method returns 666 * {@code true}), the developer should examine the 667 * return value of the {@link 668 * java.awt.event.WindowEvent#getNewState} method of 669 * the {@code WindowEvent} received through the 670 * {@link java.awt.event.WindowStateListener} to 671 * determine that the state has actually been 672 * changed. 673 * <p><b>If the frame is not visible on the 674 * screen</b>, the events may or may not be 675 * generated. In this case the developer may assume 676 * that the state changes immediately after this 677 * method returns. Later, when the {@code 678 * setVisible(true)} method is invoked, the frame 679 * will attempt to apply this state. Receiving any 680 * {@link 681 * java.awt.event.WindowEvent#WINDOW_STATE_CHANGED} 682 * events is not guaranteed in this case also. 683 * 684 * @param state either <code>Frame.NORMAL</code> or 685 * <code>Frame.ICONIFIED</code>. 686 * @see #setExtendedState(int) 687 * @see java.awt.Window#addWindowStateListener 688 */ 689 public synchronized void setState(int state) { 690 int current = getExtendedState(); 691 if (state == ICONIFIED && (current & ICONIFIED) == 0) { 692 setExtendedState(current | ICONIFIED); 693 } 694 else if (state == NORMAL && (current & ICONIFIED) != 0) { 695 setExtendedState(current & ~ICONIFIED); 696 } 697 } 698 699 /** 700 * Sets the state of this frame. The state is 701 * represented as a bitwise mask. 702 * <ul> 703 * <li><code>NORMAL</code> 704 * <br>Indicates that no state bits are set. 705 * <li><code>ICONIFIED</code> 706 * <li><code>MAXIMIZED_HORIZ</code> 707 * <li><code>MAXIMIZED_VERT</code> 708 * <li><code>MAXIMIZED_BOTH</code> 709 * <br>Concatenates <code>MAXIMIZED_HORIZ</code> 710 * and <code>MAXIMIZED_VERT</code>. 711 * </ul> 712 * <p>Note that if the state is not supported on a 713 * given platform, neither the state nor the return 714 * value of the {@link #getExtendedState} method will 715 * be changed. The application may determine whether 716 * a specific state is supported via the {@link 717 * java.awt.Toolkit#isFrameStateSupported} method. 718 * <p><b>If the frame is currently visible on the 719 * screen</b> (the {@link #isShowing} method returns 720 * {@code true}), the developer should examine the 721 * return value of the {@link 722 * java.awt.event.WindowEvent#getNewState} method of 723 * the {@code WindowEvent} received through the 724 * {@link java.awt.event.WindowStateListener} to 725 * determine that the state has actually been 726 * changed. 727 * <p><b>If the frame is not visible on the 728 * screen</b>, the events may or may not be 729 * generated. In this case the developer may assume 730 * that the state changes immediately after this 731 * method returns. Later, when the {@code 732 * setVisible(true)} method is invoked, the frame 733 * will attempt to apply this state. Receiving any 734 * {@link 735 * java.awt.event.WindowEvent#WINDOW_STATE_CHANGED} 736 * events is not guaranteed in this case also. 737 * 738 * @param state a bitwise mask of frame state constants 739 * @since 1.4 740 * @see java.awt.Window#addWindowStateListener 741 */ 742 public void setExtendedState(int state) { 743 if ( !isFrameStateSupported( state ) ) { 744 return; 745 } 746 synchronized (getObjectLock()) { 747 this.state = state; 748 } 749 // peer.setState must be called outside of object lock 750 // synchronization block to avoid possible deadlock 751 FramePeer peer = (FramePeer)this.peer; 752 if (peer != null) { 753 peer.setState(state); 754 } 755 } 756 private boolean isFrameStateSupported(int state) { 757 if( !getToolkit().isFrameStateSupported( state ) ) { 758 // * Toolkit.isFrameStateSupported returns always false 759 // on compound state even if all parts are supported; 760 // * if part of state is not supported, state is not supported; 761 // * MAXIMIZED_BOTH is not a compound state. 762 if( ((state & ICONIFIED) != 0) && 763 !getToolkit().isFrameStateSupported( ICONIFIED )) { 764 return false; 765 }else { 766 state &= ~ICONIFIED; 767 } 768 return getToolkit().isFrameStateSupported( state ); 769 } 770 return true; 771 } 772 773 /** 774 * Gets the state of this frame (obsolete). 775 * <p> 776 * In older versions of JDK a frame state could only be NORMAL or 777 * ICONIFIED. Since JDK 1.4 set of supported frame states is 778 * expanded and frame state is represented as a bitwise mask. 779 * <p> 780 * For compatibility with old programs this method still returns 781 * <code>Frame.NORMAL</code> and <code>Frame.ICONIFIED</code> but 782 * it only reports the iconic state of the frame, other aspects of 783 * frame state are not reported by this method. 784 * 785 * @return <code>Frame.NORMAL</code> or <code>Frame.ICONIFIED</code>. 786 * @see #setState(int) 787 * @see #getExtendedState 788 */ 789 public synchronized int getState() { 790 return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL; 791 } 792 793 794 /** 795 * Gets the state of this frame. The state is 796 * represented as a bitwise mask. 797 * <ul> 798 * <li><code>NORMAL</code> 799 * <br>Indicates that no state bits are set. 800 * <li><code>ICONIFIED</code> 801 * <li><code>MAXIMIZED_HORIZ</code> 802 * <li><code>MAXIMIZED_VERT</code> 803 * <li><code>MAXIMIZED_BOTH</code> 804 * <br>Concatenates <code>MAXIMIZED_HORIZ</code> 805 * and <code>MAXIMIZED_VERT</code>. 806 * </ul> 807 * 808 * @return a bitwise mask of frame state constants 809 * @see #setExtendedState(int) 810 * @since 1.4 811 */ 812 public int getExtendedState() { 813 synchronized (getObjectLock()) { 814 return state; 815 } 816 } 817 818 static { 819 AWTAccessor.setFrameAccessor( 820 new AWTAccessor.FrameAccessor() { 821 public void setExtendedState(Frame frame, int state) { 822 synchronized(frame.getObjectLock()) { 823 frame.state = state; 824 } 825 } 826 public int getExtendedState(Frame frame) { 827 synchronized(frame.getObjectLock()) { 828 return frame.state; 829 } 830 } 831 public Rectangle getMaximizedBounds(Frame frame) { 832 synchronized(frame.getObjectLock()) { 833 return frame.maximizedBounds; 834 } 835 } 836 } 837 ); 838 } 839 840 /** 841 * Sets the maximized bounds for this frame. 842 * <p> 843 * When a frame is in maximized state the system supplies some 844 * defaults bounds. This method allows some or all of those 845 * system supplied values to be overridden. 846 * <p> 847 * If <code>bounds</code> is <code>null</code>, accept bounds 848 * supplied by the system. If non-<code>null</code> you can 849 * override some of the system supplied values while accepting 850 * others by setting those fields you want to accept from system 851 * to <code>Integer.MAX_VALUE</code>. 852 * <p> 853 * Note, the given maximized bounds are used as a hint for the native 854 * system, because the underlying platform may not support setting the 855 * location and/or size of the maximized windows. If that is the case, the 856 * provided values do not affect the appearance of the frame in the 857 * maximized state. 858 * 859 * @param bounds bounds for the maximized state 860 * @see #getMaximizedBounds() 861 * @since 1.4 862 */ 863 public void setMaximizedBounds(Rectangle bounds) { 864 synchronized(getObjectLock()) { 865 this.maximizedBounds = bounds; 866 } 867 FramePeer peer = (FramePeer)this.peer; 868 if (peer != null) { 869 peer.setMaximizedBounds(bounds); 870 } 871 } 872 873 /** 874 * Gets maximized bounds for this frame. 875 * Some fields may contain <code>Integer.MAX_VALUE</code> to indicate 876 * that system supplied values for this field must be used. 877 * 878 * @return maximized bounds for this frame; may be <code>null</code> 879 * @see #setMaximizedBounds(Rectangle) 880 * @since 1.4 881 */ 882 public Rectangle getMaximizedBounds() { 883 synchronized(getObjectLock()) { 884 return maximizedBounds; 885 } 886 } 887 888 889 /** 890 * Disables or enables decorations for this frame. 891 * <p> 892 * This method can only be called while the frame is not displayable. To 893 * make this frame decorated, it must be opaque and have the default shape, 894 * otherwise the {@code IllegalComponentStateException} will be thrown. 895 * Refer to {@link Window#setShape}, {@link Window#setOpacity} and {@link 896 * Window#setBackground} for details 897 * 898 * @param undecorated {@code true} if no frame decorations are to be 899 * enabled; {@code false} if frame decorations are to be enabled 900 * 901 * @throws IllegalComponentStateException if the frame is displayable 902 * @throws IllegalComponentStateException if {@code undecorated} is 903 * {@code false}, and this frame does not have the default shape 904 * @throws IllegalComponentStateException if {@code undecorated} is 905 * {@code false}, and this frame opacity is less than {@code 1.0f} 906 * @throws IllegalComponentStateException if {@code undecorated} is 907 * {@code false}, and the alpha value of this frame background 908 * color is less than {@code 1.0f} 909 * 910 * @see #isUndecorated 911 * @see Component#isDisplayable 912 * @see Window#getShape 913 * @see Window#getOpacity 914 * @see Window#getBackground 915 * @see javax.swing.JFrame#setDefaultLookAndFeelDecorated(boolean) 916 * 917 * @since 1.4 918 */ 919 public void setUndecorated(boolean undecorated) { 920 /* Make sure we don't run in the middle of peer creation.*/ 921 synchronized (getTreeLock()) { 922 if (isDisplayable()) { 923 throw new IllegalComponentStateException("The frame is displayable."); 924 } 925 if (!undecorated) { 926 if (getOpacity() < 1.0f) { 927 throw new IllegalComponentStateException("The frame is not opaque"); 928 } 929 if (getShape() != null) { 930 throw new IllegalComponentStateException("The frame does not have a default shape"); 931 } 932 Color bg = getBackground(); 933 if ((bg != null) && (bg.getAlpha() < 255)) { 934 throw new IllegalComponentStateException("The frame background color is not opaque"); 935 } 936 } 937 this.undecorated = undecorated; 938 } 939 } 940 941 /** 942 * Indicates whether this frame is undecorated. 943 * By default, all frames are initially decorated. 944 * @return <code>true</code> if frame is undecorated; 945 * <code>false</code> otherwise. 946 * @see java.awt.Frame#setUndecorated(boolean) 947 * @since 1.4 948 */ 949 public boolean isUndecorated() { 950 return undecorated; 951 } 952 953 /** 954 * {@inheritDoc} 955 */ 956 @Override 957 public void setOpacity(float opacity) { 958 synchronized (getTreeLock()) { 959 if ((opacity < 1.0f) && !isUndecorated()) { 960 throw new IllegalComponentStateException("The frame is decorated"); 961 } 962 super.setOpacity(opacity); 963 } 964 } 965 966 /** 967 * {@inheritDoc} 968 */ 969 @Override 970 public void setShape(Shape shape) { 971 synchronized (getTreeLock()) { 972 if ((shape != null) && !isUndecorated()) { 973 throw new IllegalComponentStateException("The frame is decorated"); 974 } 975 super.setShape(shape); 976 } 977 } 978 979 /** 980 * {@inheritDoc} 981 */ 982 @Override 983 public void setBackground(Color bgColor) { 984 synchronized (getTreeLock()) { 985 if ((bgColor != null) && (bgColor.getAlpha() < 255) && !isUndecorated()) { 986 throw new IllegalComponentStateException("The frame is decorated"); 987 } 988 super.setBackground(bgColor); 989 } 990 } 991 992 /** 993 * Removes the specified menu bar from this frame. 994 * @param m the menu component to remove. 995 * If <code>m</code> is <code>null</code>, then 996 * no action is taken 997 */ 998 public void remove(MenuComponent m) { 999 if (m == null) { 1000 return; 1001 } 1002 synchronized (getTreeLock()) { 1003 if (m == menuBar) { 1004 menuBar = null; 1005 FramePeer peer = (FramePeer)this.peer; 1006 if (peer != null) { 1007 mbManagement = true; 1008 invalidateIfValid(); 1009 peer.setMenuBar(null); 1010 m.removeNotify(); 1011 } 1012 m.parent = null; 1013 } else { 1014 super.remove(m); 1015 } 1016 } 1017 } 1018 1019 /** 1020 * Makes this Frame undisplayable by removing its connection 1021 * to its native screen resource. Making a Frame undisplayable 1022 * will cause any of its children to be made undisplayable. 1023 * This method is called by the toolkit internally and should 1024 * not be called directly by programs. 1025 * @see Component#isDisplayable 1026 * @see #addNotify 1027 */ 1028 public void removeNotify() { 1029 synchronized (getTreeLock()) { 1030 FramePeer peer = (FramePeer)this.peer; 1031 if (peer != null) { 1032 // get the latest Frame state before disposing 1033 getState(); 1034 1035 if (menuBar != null) { 1036 mbManagement = true; 1037 peer.setMenuBar(null); 1038 menuBar.removeNotify(); 1039 } 1040 } 1041 super.removeNotify(); 1042 } 1043 } 1044 1045 void postProcessKeyEvent(KeyEvent e) { 1046 if (menuBar != null && menuBar.handleShortcut(e)) { 1047 e.consume(); 1048 return; 1049 } 1050 super.postProcessKeyEvent(e); 1051 } 1052 1053 /** 1054 * Returns a string representing the state of this <code>Frame</code>. 1055 * This method is intended to be used only for debugging purposes, and the 1056 * content and format of the returned string may vary between 1057 * implementations. The returned string may be empty but may not be 1058 * <code>null</code>. 1059 * 1060 * @return the parameter string of this frame 1061 */ 1062 protected String paramString() { 1063 String str = super.paramString(); 1064 if (title != null) { 1065 str += ",title=" + title; 1066 } 1067 if (resizable) { 1068 str += ",resizable"; 1069 } 1070 int state = getExtendedState(); 1071 if (state == NORMAL) { 1072 str += ",normal"; 1073 } 1074 else { 1075 if ((state & ICONIFIED) != 0) { 1076 str += ",iconified"; 1077 } 1078 if ((state & MAXIMIZED_BOTH) == MAXIMIZED_BOTH) { 1079 str += ",maximized"; 1080 } 1081 else if ((state & MAXIMIZED_HORIZ) != 0) { 1082 str += ",maximized_horiz"; 1083 } 1084 else if ((state & MAXIMIZED_VERT) != 0) { 1085 str += ",maximized_vert"; 1086 } 1087 } 1088 return str; 1089 } 1090 1091 /** 1092 * @deprecated As of JDK version 1.1, 1093 * replaced by <code>Component.setCursor(Cursor)</code>. 1094 */ 1095 @Deprecated 1096 public void setCursor(int cursorType) { 1097 if (cursorType < DEFAULT_CURSOR || cursorType > MOVE_CURSOR) { 1098 throw new IllegalArgumentException("illegal cursor type"); 1099 } 1100 setCursor(Cursor.getPredefinedCursor(cursorType)); 1101 } 1102 1103 /** 1104 * @deprecated As of JDK version 1.1, 1105 * replaced by <code>Component.getCursor()</code>. 1106 */ 1107 @Deprecated 1108 public int getCursorType() { 1109 return (getCursor().getType()); 1110 } 1111 1112 /** 1113 * Returns an array of all {@code Frame}s created by this application. 1114 * If called from an applet, the array includes only the {@code Frame}s 1115 * accessible by that applet. 1116 * <p> 1117 * <b>Warning:</b> this method may return system created frames, such 1118 * as a shared, hidden frame which is used by Swing. Applications 1119 * should not assume the existence of these frames, nor should an 1120 * application assume anything about these frames such as component 1121 * positions, <code>LayoutManager</code>s or serialization. 1122 * <p> 1123 * <b>Note</b>: To obtain a list of all ownerless windows, including 1124 * ownerless {@code Dialog}s (introduced in release 1.6), use {@link 1125 * Window#getOwnerlessWindows Window.getOwnerlessWindows}. 1126 * 1127 * @see Window#getWindows() 1128 * @see Window#getOwnerlessWindows 1129 * 1130 * @since 1.2 1131 */ 1132 public static Frame[] getFrames() { 1133 Window[] allWindows = Window.getWindows(); 1134 1135 int frameCount = 0; 1136 for (Window w : allWindows) { 1137 if (w instanceof Frame) { 1138 frameCount++; 1139 } 1140 } 1141 1142 Frame[] frames = new Frame[frameCount]; 1143 int c = 0; 1144 for (Window w : allWindows) { 1145 if (w instanceof Frame) { 1146 frames[c++] = (Frame)w; 1147 } 1148 } 1149 1150 return frames; 1151 } 1152 1153 /* Serialization support. If there's a MenuBar we restore 1154 * its (transient) parent field here. Likewise for top level 1155 * windows that are "owned" by this frame. 1156 */ 1157 1158 /** 1159 * <code>Frame</code>'s Serialized Data Version. 1160 * 1161 * @serial 1162 */ 1163 private int frameSerializedDataVersion = 1; 1164 1165 /** 1166 * Writes default serializable fields to stream. Writes 1167 * an optional serializable icon <code>Image</code>, which is 1168 * available as of 1.4. 1169 * 1170 * @param s the <code>ObjectOutputStream</code> to write 1171 * @serialData an optional icon <code>Image</code> 1172 * @see java.awt.Image 1173 * @see #getIconImage 1174 * @see #setIconImage(Image) 1175 * @see #readObject(ObjectInputStream) 1176 */ 1177 private void writeObject(ObjectOutputStream s) 1178 throws IOException 1179 { 1180 s.defaultWriteObject(); 1181 if (icons != null && icons.size() > 0) { 1182 Image icon1 = icons.get(0); 1183 if (icon1 instanceof Serializable) { 1184 s.writeObject(icon1); 1185 return; 1186 } 1187 } 1188 s.writeObject(null); 1189 } 1190 1191 /** 1192 * Reads the <code>ObjectInputStream</code>. Tries 1193 * to read an icon <code>Image</code>, which is optional 1194 * data available as of 1.4. If an icon <code>Image</code> 1195 * is not available, but anything other than an EOF 1196 * is detected, an <code>OptionalDataException</code> 1197 * will be thrown. 1198 * Unrecognized keys or values will be ignored. 1199 * 1200 * @param s the <code>ObjectInputStream</code> to read 1201 * @exception java.io.OptionalDataException if an icon <code>Image</code> 1202 * is not available, but anything other than an EOF 1203 * is detected 1204 * @exception HeadlessException if 1205 * <code>GraphicsEnvironment.isHeadless</code> returns 1206 * <code>true</code> 1207 * @see java.awt.GraphicsEnvironment#isHeadless() 1208 * @see java.awt.Image 1209 * @see #getIconImage 1210 * @see #setIconImage(Image) 1211 * @see #writeObject(ObjectOutputStream) 1212 */ 1213 private void readObject(ObjectInputStream s) 1214 throws ClassNotFoundException, IOException, HeadlessException 1215 { 1216 // HeadlessException is thrown by Window's readObject 1217 s.defaultReadObject(); 1218 try { 1219 Image icon = (Image) s.readObject(); 1220 if (icons == null) { 1221 icons = new ArrayList<Image>(); 1222 icons.add(icon); 1223 } 1224 } catch (java.io.OptionalDataException e) { 1225 // pre-1.4 instances will not have this optional data. 1226 // 1.6 and later instances serialize icons in the Window class 1227 // e.eof will be true to indicate that there is no more 1228 // data available for this object. 1229 1230 // If e.eof is not true, throw the exception as it 1231 // might have been caused by unrelated reasons. 1232 if (!e.eof) { 1233 throw (e); 1234 } 1235 } 1236 1237 if (menuBar != null) 1238 menuBar.parent = this; 1239 1240 // Ensure 1.1 serialized Frames can read & hook-up 1241 // owned windows properly 1242 // 1243 if (ownedWindows != null) { 1244 for (int i = 0; i < ownedWindows.size(); i++) { 1245 connectOwnedWindow((Window) ownedWindows.elementAt(i)); 1246 } 1247 ownedWindows = null; 1248 } 1249 } 1250 1251 /** 1252 * Initialize JNI field and method IDs 1253 */ 1254 private static native void initIDs(); 1255 1256 /* 1257 * --- Accessibility Support --- 1258 * 1259 */ 1260 1261 /** 1262 * Gets the AccessibleContext associated with this Frame. 1263 * For frames, the AccessibleContext takes the form of an 1264 * AccessibleAWTFrame. 1265 * A new AccessibleAWTFrame instance is created if necessary. 1266 * 1267 * @return an AccessibleAWTFrame that serves as the 1268 * AccessibleContext of this Frame 1269 * @since 1.3 1270 */ 1271 public AccessibleContext getAccessibleContext() { 1272 if (accessibleContext == null) { 1273 accessibleContext = new AccessibleAWTFrame(); 1274 } 1275 return accessibleContext; 1276 } 1277 1278 /** 1279 * This class implements accessibility support for the 1280 * <code>Frame</code> class. It provides an implementation of the 1281 * Java Accessibility API appropriate to frame user-interface elements. 1282 * @since 1.3 1283 */ 1284 protected class AccessibleAWTFrame extends AccessibleAWTWindow 1285 { 1286 /* 1287 * JDK 1.3 serialVersionUID 1288 */ 1289 private static final long serialVersionUID = -6172960752956030250L; 1290 1291 /** 1292 * Get the role of this object. 1293 * 1294 * @return an instance of AccessibleRole describing the role of the 1295 * object 1296 * @see AccessibleRole 1297 */ 1298 public AccessibleRole getAccessibleRole() { 1299 return AccessibleRole.FRAME; 1300 } 1301 1302 /** 1303 * Get the state of this object. 1304 * 1305 * @return an instance of AccessibleStateSet containing the current 1306 * state set of the object 1307 * @see AccessibleState 1308 */ 1309 public AccessibleStateSet getAccessibleStateSet() { 1310 AccessibleStateSet states = super.getAccessibleStateSet(); 1311 if (getFocusOwner() != null) { 1312 states.add(AccessibleState.ACTIVE); 1313 } 1314 if (isResizable()) { 1315 states.add(AccessibleState.RESIZABLE); 1316 } 1317 return states; 1318 } 1319 1320 1321 } // inner class AccessibleAWTFrame 1322 1323 }