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