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 */ Frame()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 */ Frame(String title)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 Frame(GraphicsConfiguration gc)253 public Frame(GraphicsConfiguration gc) 254 { 255 super(gc); 256 visible = false; 257 noteFrame(this); 258 } 259 Frame(String title, GraphicsConfiguration gc)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 */ getTitle()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 */ setTitle(String title)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 */ getIconImage()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 */ setIconImage(Image icon)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 */ getMenuBar()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 */ setMenuBar(MenuBar menuBar)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 */ isResizable()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 */ setResizable(boolean resizable)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 */ getCursorType()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 */ setCursor(int type)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 */ remove(MenuComponent menu)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 addNotify()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 removeNotify()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 */ paramString()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 noteFrame(Frame f)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 */ hasDisplayableFrames()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 getFrames()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 setState(int state)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 getState()569 public int getState() 570 { 571 return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL; 572 } 573 574 /** 575 * @since 1.4 576 */ setExtendedState(int state)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 */ getExtendedState()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 */ setMaximizedBounds(Rectangle maximizedBounds)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 */ getMaximizedBounds()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 */ isUndecorated()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 */ setUndecorated(boolean undecorated)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 */ generateName()650 String generateName() 651 { 652 return "frame" + getUniqueLong(); 653 } 654 getUniqueLong()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 */ getAccessibleRole()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 */ getAccessibleStateSet()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 */ getAccessibleContext()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 } 705