/*
* @(#)Frame.java 1.106 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
/*
* Warning :
* Two versions of this file exist in this workspace.
* One for Personal Basis, and one for Personal Profile.
* Don't edit the wrong one !!!
*/
package java.awt;
import sun.awt.peer.FramePeer;
import sun.awt.PeerBasedToolkit;
import java.awt.event.*;
import sun.awt.AppContext;
import java.util.Vector;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
/**
* A Frame is a top-level window with a title and a border.
* <p>
* The size of the frame includes any area designated for the
* border. The dimensions of the border area can be obtained
* using the <code>getInsets</code> method, however, since
* these dimensions are platform-dependent, a valid insets
* value cannot be obtained until the frame is made displayable
* by either calling <code>pack</code> or <code>show</code>.
* Since the border area is included in the overall size of the
* frame, the border effectively obscures a portion of the frame,
* constraining the area available for rendering and/or displaying
* subcomponents to the rectangle which has an upper-left corner
* location of <code>(insets.left, insets.top)</code>, and has a size of
* <code>width - (insets.left + insets.right)</code> by
* <code>height - (insets.top + insets.bottom)</code>.
* <p>
* The default layout for a frame is BorderLayout.
* <p>
* In a multi-screen environment, you can create a <code>Frame</code>
* on a different screen device by constructing the <code>Frame</code>
* with {@link #Frame(GraphicsConfiguration)} or
* {@link #Frame(String title, GraphicsConfiguration)}. The
* <code>GraphicsConfiguration</code> object is one of the
* <code>GraphicsConfiguration</code> objects of the target screen
* device.
* <p>
* In a virtual device multi-screen environment in which the desktop
* area could span multiple physical screen devices, the bounds of all
* configurations are relative to the virtual-coordinate system. The
* origin of the virtual-coordinate system is at the upper left-hand
* corner of the primary physical screen. Depending on the location
* of the primary screen in the virtual device, negative coordinates
* are possible, as shown in the following figure.
* <p>
* <img src="doc-files/MultiScreen.gif">
* <ALIGN=center HSPACE=10 VSPACE=7>
* <p>
* In such an environment, when calling <code>setLocation</code>,
* you must pass a virtual coordinate to this method. Similarly,
* calling <code>getLocationOnScreen</code> on a <code>Frame</code>
* returns virtual device coordinates. Call the <code>getBounds</code>
* method of a <code>GraphicsConfiguration</code> to find its origin in
* the virtual coordinate system.
* <p>
* The following code sets the
* location of the <code>Frame</code> at (10, 10) relative
* to the origin of the physical screen of the corresponding
* <code>GraphicsConfiguration</code>. If the bounds of the
* <code>GraphicsConfiguration</code> is not taken into account, the
* <code>Frame</code> location would be set at (10, 10) relative to the
* virtual-coordinate system and would appear on the primary physical
* screen, which might be different from the physical screen of the
* specified <code>GraphicsConfiguration</code>.
*
* <pre>
* Frame f = new Frame(GraphicsConfiguration gc);
* Rectangle bounds = gc.getBounds();
* f.setLocation(10 + bounds.x, 10 + bounds.y);
* </pre>
*
* <p>
* Frames are capable of generating the following types of window events:
* WindowOpened, WindowClosing, WindowClosed, WindowIconified,
* WindowDeiconified, WindowActivated, WindowDeactivated.
*
* <p>
* <a name="restrictions">
* <h4>Restrictions</h4>
* <em>
* Implementations of Frame in Personal Profile exhibit
* certain restrictions, specifically:
* <ul>
* <li> An implementation need not support more than a single Frame size.
* In such a case:
* <ol>
* <li> Attempts to change the size of the Frame will fail silently.
* <li> When the Frame is made visible, its size will be changed to
* reflect the size supported by the implementation. If the supported size
* is different than the requested size, a resize event will be generated.
* </ol>
* See:
* <ul>
* <li> {@link #setSize(int, int)}
* <li> {@link #setSize(Dimension)}
* <li> {@link #setBounds(int, int, int, int)}
* <li> {@link #setBounds(Rectangle)}
* </ul>
* <li> An implementation may prohibit resizing of Frames by a user. In
* such a case, attempts to make any Frame resizable will fail silently.
* See:
* <ul>
* <li> {@link #setResizable(boolean)}
* </ul>
* <li> An implementation need not support more than a single Frame
* location. In such a case, attempts to change the location of any
* Frame will fail silently. See:
* <ul>
* <li> {@link #setLocation(int, int)}
* <li> {@link #setLocation(Point)}
* <li> {@link #setBounds(int, int, int, int)}
* <li> {@link #setBounds(Rectangle)}
* </ul>
* <li> An implementation may prohibit iconification. In
* such a case, attempts to iconify any Frame will fail silently.
* See:
* <ul>
* <li> {@link #setState}
* </ul>
* <li> An implementation need not support a visible title on Frames.
* In such a case, the methods {@link #setTitle} and {@link #getTitle}
* on all Frames behave as normal, but no title is visible to the user.
* See:
* <ul>
* <li> {@link #Frame(String)}
* <li> {@link #Frame(String, GraphicsConfiguration)}
* <li> {@link #setTitle}
* </ul>
* </ul>
* </em>
*
* @version 1.98, 08/19/02
* @author Sami Shaio
* @see WindowEvent
* @see Window#addWindowListener
* @since JDK1.0
*/
public class Frame extends Window implements MenuContainer {
/* Note: These are being obsoleted; programs should use the Cursor class
* variables going forward. See Cursor and Component.setCursor.
*/
/**
* @deprecated replaced by <code>Cursor.DEFAULT_CURSOR</code>.
*/
public static final int DEFAULT_CURSOR = Cursor.DEFAULT_CURSOR;
/**
*@deprecated replaced by <code>Cursor.CROSSHAIR_CURSOR</code>.
*/
public static final int CROSSHAIR_CURSOR = Cursor.CROSSHAIR_CURSOR;
/**
* @deprecated replaced by <code>Cursor.TEXT_CURSOR</code>
*/
public static final int TEXT_CURSOR = Cursor.TEXT_CURSOR;
/**
* @deprecated replaced by <code>Cursor.WAIT_CURSOR</code>.
*/
public static final int WAIT_CURSOR = Cursor.WAIT_CURSOR;
/**
* @deprecated replaced by <code>Cursor.SW_RESIZE_CURSOR</code>.
*/
public static final int SW_RESIZE_CURSOR = Cursor.SW_RESIZE_CURSOR;
/**
* @deprecated replaced by <code>Cursor.SE_RESIZE_CURSOR</code>.
*/
public static final int SE_RESIZE_CURSOR = Cursor.SE_RESIZE_CURSOR;
/**
* @deprecated replaced by <code>Cursor.NW_RESIZE_CURSOR</code>.
*/
public static final int NW_RESIZE_CURSOR = Cursor.NW_RESIZE_CURSOR;
/**
* @deprecated replaced by <code>Cursor.NE_RESIZE_CURSOR</code>.
*/
public static final int NE_RESIZE_CURSOR = Cursor.NE_RESIZE_CURSOR;
/**
* @deprecated replaced by <code>Cursor.N_RESIZE_CURSOR</code>.
*/
public static final int N_RESIZE_CURSOR = Cursor.N_RESIZE_CURSOR;
/**
* @deprecated replaced by <code>Cursor.S_RESIZE_CURSOR</code>.
*/
public static final int S_RESIZE_CURSOR = Cursor.S_RESIZE_CURSOR;
/**
* @deprecated replaced by <code>Cursor.W_RESIZE_CURSOR</code>.
*/
public static final int W_RESIZE_CURSOR = Cursor.W_RESIZE_CURSOR;
/**
** @deprecated replaced by <code>Cursor.E_RESIZE_CURSOR</code>.
*/
public static final int E_RESIZE_CURSOR = Cursor.E_RESIZE_CURSOR;
/**
* @deprecated replaced by <code>Cursor.HAND_CURSOR</code>.
*/
public static final int HAND_CURSOR = Cursor.HAND_CURSOR;
/**
* @deprecated replaced by <code>Cursor.MOVE_CURSOR</code>.
*/
public static final int MOVE_CURSOR = Cursor.MOVE_CURSOR;
public static final int NORMAL = 0;
public static final int ICONIFIED = 1;
/**
* This is the title of the frame. It can be changed
* at any time. <code>title</code> can be null and if
* this is the case the <code>title</code> = "".
*
* @serial
* @see getTitle()
* @see setTitle()
*/
String title = "Untitled";
/**
* <code>icon</code> is the graphical way we can
* represent the frame.
* <code>icon</code> can be null, but obviously if
* you try to set the icon image <code>icon</code>
* cannot be null.
*
* @serial
* @see getIconImage()
* @see setIconImage()
*/
Image icon;
/**
* The frames menubar. If <code>menuBar</code> = null
* the frame will not have a menubar.
*
* @serial
* @see getMenuBar()
* @see setMenuBar()
*/
MenuBar menuBar;
/**
* This field indicates whether the the frame is resizable
* This property can be changed at any time.
* <code>resizable</code> will be true if the frame is
* resizable, otherwise it will be false.
*
* @serial
* @see isResizable()
*/
boolean resizable = true;
/**
* This field indicates whether the frame is undecorated.
* This property can only be changed while the frame is not displayable.
* <code>undecorated</code> will be true if the frame is
* undecorated, otherwise it will be false.
*
* @serial
* @see #setUndecorated(boolean)
* @see #isUndecorated()
* @see Component#isDisplayable()
* @since 1.4
*/
boolean undecorated = false;
/**
* Defines the current state of the Frame.
*/
private int state = NORMAL;
boolean mbManagement = false; /* used only by the Motif impl. */
private static final String base = "frame";
private static int nameCounter = 0;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 2673458971256075116L;
/**
* Constructs a new instance of <code>Frame</code> that is
* initially invisible. The title of the <code>Frame</code>
* is empty.
* @see Component#setSize
* @see Component#setVisible
*/
public Frame() {
this("", (GraphicsConfiguration) null);
}
/**
* Create a <code>Frame</code> with the specified
* <code>GraphicsConfiguration</code> of
* a screen device.
* @param gc the <code>GraphicsConfiguration</code>
* of the target screen device. If <code>gc</code>
* is <code>null</code>, the system default
* <code>GraphicsConfiguration</code> is assumed.
* @exception IllegalArgumentException if
* <code>gc</code> is not from a screen device.
* @since 1.3
*/
public Frame(GraphicsConfiguration gc) {
this("", gc);
}
/**
* Constructs a new, initially invisible <code>Frame</code> object
* with the specified title.
* <p>
* <em>Note: This operation is subject to
* <a href="#restrictions">restriction</a>
* in Personal Profile.</em>
*
* @param title the title to be displayed in the frame's border.
* A <code>null</code> value
* is treated as an empty string, "".
* @exception IllegalArgumentException if gc is not from
* a screen device.
* @see java.awt.Component#setSize
* @see java.awt.Component#setVisible
* @see java.awt.GraphicsConfiguration#getBounds
*/
public Frame(String title) {
this(title, (GraphicsConfiguration) null);
}
/**
* Constructs a new, initially invisible <code>Frame</code> object
* with the specified title and a
* <code>GraphicsConfiguration</code>.
* <p>
* <em>Note: This operation is subject to
* <a href="#restrictions">restriction</a>
* in Personal Profile.</em>
*
* @param title the title to be displayed in the frame's border.
* A <code>null</code> value
* is treated as an empty string, "".
* @param gc the <code>GraphicsConfiguration</code>
* of the target screen device. If <code>gc</code> is
* <code>null</code>, the system default
* <code>GraphicsConfiguration</code> is assumed.
* @exception IllegalArgumentException if <code>gc</code>
* is not from a screen device.
* @see java.awt.Component#setSize
* @see java.awt.Component#setVisible
* @see java.awt.GraphicsConfiguration#getBounds
*/
public Frame(String title, GraphicsConfiguration gc) {
super(gc);
this.title = title;
visible = false;
setLayout(new BorderLayout());
// 6275164
setFocusTraversalPolicy(KeyboardFocusManager.
getCurrentKeyboardFocusManager().
getDefaultFocusTraversalPolicy()
);
}
/**
* Construct a name for this component. Called by getName() when the
* name is null.
*/
String constructComponentName() {
return base + nameCounter++;
}
/**
* Creates the Frame's peer. The peer allows us to change the look
* of the Frame without changing its functionality.
* @since JDK1.0
*/
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = ((PeerBasedToolkit) getToolkit()).createFrame(this);
MenuBar menuBar = this.menuBar;
if (menuBar != null) {
menuBar.addNotify();
((FramePeer) peer).setMenuBar(menuBar);
}
super.addNotify();
}
}
/**
* Gets the title of the frame. The title is displayed in the
* frame's border.
* @return the title of this frame, or an empty string ("")
* if this frame doesn't have a title.
* @see java.awt.Frame#setTitle
*/
public String getTitle() {
return title;
}
/**
* Sets the title for this frame to the specified string.
* <p>
* <em>Note: This operation is subject to
* <a href="#restrictions">restriction</a>
* in Personal Profile.</em>
*
* @param title the title to be displayed in the frame's border
* @param title the title to be displayed in the frame's border.
* A <code>null</code> value
* is treated as an empty string, "".
* @see java.awt.Frame#getTitle
*/
public synchronized void setTitle(String title) {
this.title = (title == null) ? "" : title;
FramePeer peer = (FramePeer) this.peer;
if (peer != null) {
peer.setTitle(this.title);
}
}
/**
* Gets the image to be displayed in the minimized icon
* for this frame.
* @return the icon image for this frame, or <code>null</code>
* if this frame doesn't have an icon image.
* @see java.awt.Frame#setIconImage
*/
public Image getIconImage() {
return icon;
}
/**
* Sets the image to displayed in the minimized icon for this frame.
* Not all platforms support the concept of minimizing a window.
* @param image the icon image to be displayed.
* If this parameter is <code>null</code> then the
* icon image is set to the default image, which may vary
* with platform.
* @see java.awt.Frame#getIconImage
*/
public synchronized void setIconImage(Image image) {
this.icon = image;
FramePeer peer = (FramePeer) this.peer;
if (peer != null) {
peer.setIconImage(image);
}
}
/**
* Gets the menu bar for this frame.
* @return the menu bar for this frame, or <code>null</code>
* if this frame doesn't have a menu bar.
* @see java.awt.Frame#setMenuBar
*/
public MenuBar getMenuBar() {
return menuBar;
}
/**
* Sets the menu bar for this frame to the specified menu bar.
* @param mb the menu bar being set.
* If this parameter is <code>null</code> then any
* existing menu bar on this frame is removed.
* @see java.awt.Frame#getMenuBar
*/
public void setMenuBar(MenuBar mb) {
synchronized (getTreeLock()) {
if (menuBar == mb) {
return;
}
if ((mb != null) && (mb.parent != null)) {
mb.parent.remove(mb);
}
if (menuBar != null) {
remove(menuBar);
}
menuBar = mb;
if (menuBar != null) {
menuBar.parent = this;
FramePeer peer = (FramePeer) this.peer;
if (peer != null) {
mbManagement = true;
menuBar.addNotify();
peer.setMenuBar(menuBar);
}
}
invalidate();
}
}
/**
* Indicates whether this frame is resizable by the user.
* By default, all frames are initially resizable.
* @return <code>true</code> if the user can resize this frame;
* <code>false</code> otherwise.
* @see java.awt.Frame#setResizable
*/
public boolean isResizable() {
return resizable;
}
/**
* Sets whether this frame is resizable by the user.
* <p>
* <em>Note: This operation is subject to
* <a href="#restrictions">restriction</a>
* in Personal Profile.</em>
*
* @param resizable <code>true</code> if this frame is resizable;
* <code>false</code> otherwise.
* @see java.awt.Frame#isResizable
*/
public synchronized void setResizable(boolean resizable) {
this.resizable = resizable;
FramePeer peer = (FramePeer) this.peer;
if (peer != null) {
peer.setResizable(resizable);
}
}
/**
* Removes the specified menu bar from this frame.
* @param m the menu component to remove.
* If this parameter is <code>null</code> then a
* NullPointerException is thrown and no action
* is taken.
*/
public void remove(MenuComponent m) {
synchronized (getTreeLock()) {
if (m == menuBar) {
menuBar = null;
FramePeer peer = (FramePeer) this.peer;
if (peer != null) {
mbManagement = true;
peer.setMenuBar(null);
m.removeNotify();
}
m.parent = null;
} else {
super.remove(m);
}
}
}
/**
* Makes this Frame undisplayable by removing its connection
* to its native screen resource. Making a Frame undisplayable
* will cause any of its children to be made undisplayable.
* This method is called by the toolkit internally and should
* not be called directly by programs.
* @see Component#isDisplayable
* @see #addNotify
*/
public void removeNotify() {
synchronized (getTreeLock()) {
FramePeer peer = (FramePeer)this.peer;
if (peer != null) {
// get the latest Frame state before disposing
getState();
if (menuBar != null) {
mbManagement = true;
peer.setMenuBar(null);
menuBar.removeNotify();
}
}
super.removeNotify();
}
}
/**
* Disposes of the Frame. This method must
* be called to release the resources that
* are used for the frame. All components
* contained by the frame and all windows
* owned by the frame will also be destroyed.
* @since JDK1.0
*/
public void dispose() { // synch removed.
synchronized (getTreeLock()) {
if (ownedWindows != null) {
int ownedWindowCount = ownedWindows.size();
Window ownedWindowCopy[] = new Window[ownedWindowCount];
ownedWindows.copyInto(ownedWindowCopy);
for (int i = 0; i < ownedWindowCount; i++) {
ownedWindowCopy[i].dispose();
}
}
// Bug : 5012737
// J2SE 1.4.2 does not override Window.dispose() method, so
// it does not remove the menubar if set. Mimicing the same
// behavior.
// if (menuBar != null) {
// remove(menuBar);
// menuBar = null;
// }
// Bug : 5012737
}
super.dispose();
}
void postProcessKeyEvent(KeyEvent e) {
if (menuBar != null && menuBar.handleShortcut(e)) {
e.consume();
return;
}
super.postProcessKeyEvent(e);
}
/**
* Removes the specified menu bar from this frame.
* @param m the menu component to remove.
* If this parameter is <code>null</code> then a
* NullPointerException is thrown and no action
* is taken.
*/
protected String paramString() {
String str = super.paramString();
if (resizable) {
str += ",resizable";
}
if (title != null) {
str += ",title=" + title;
}
return str;
}
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>Component.setCursor(Cursor)</code>.
*/
public synchronized void setCursor(int cursorType) {
if (cursorType < DEFAULT_CURSOR || cursorType > MOVE_CURSOR) {
throw new IllegalArgumentException("illegal cursor type");
}
setCursor(Cursor.getPredefinedCursor(cursorType));
}
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>Component.getCursor()</code>.
*/
public int getCursorType() {
return (getCursor().getType());
}
/**
* Gets the state of this frame.
* @return <code>Frame.ICONIFIED</code> if frame in iconic state;
* <code>Frame.NORMAL</code> if frame is in normal state.
* @see java.awt.Frame#setState
*/
public synchronized int getState() {
FramePeer peer = (FramePeer) this.peer;
if (peer != null) {
state = peer.getState();
}
return state;
}
/**
* Sets the state of this frame.
* <p>
* <em>Note: This operation is subject to
* <a href="#restrictions">restriction</a>
* in Personal Profile.</em>
*
* @param state <code>Frame.ICONIFIED</code> if this frame is in
* iconic state; <code>Frame.NORMAL</code> if this frame is
* in normal state.
* @see java.awt.Frame#getState
*/
public synchronized void setState(int state) {
if (state == ICONIFIED || state == NORMAL) {
this.state = state;
FramePeer peer = (FramePeer) this.peer;
if (peer != null) {
peer.setState(state);
}
}
}
/**
* Disables or enables decorations for this frame.
* This method can only be called while the frame is not displayable.
* @param undecorated <code>true</code> if no frame decorations are
* to be enabled;
* <code>false</code> if frame decorations are to be enabled.
* @throws <code>IllegalComponentStateException</code> if the frame
* is displayable.
* @see #isUndecorated
* @see Component#isDisplayable
* @see javax.swing.JFrame#setDefaultLookAndFeelDecorated(boolean)
* @since 1.4
*/
public void setUndecorated(boolean undecorated) {
/* Make sure we don't run in the middle of peer creation.*/
synchronized (getTreeLock()) {
if (isDisplayable()) {
throw new IllegalComponentStateException("The frame is displayable.");
}
this.undecorated = undecorated;
}
}
/**
* Indicates whether this frame is undecorated.
* By default, all frames are initially decorated.
* @return <code>true</code> if frame is undecorated;
* <code>false</code> otherwise.
* @see java.awt.Frame#setUndecorated(boolean)
* @since 1.4
*/
public boolean isUndecorated() {
return undecorated;
}
/* Serialization support. If there's a MenuBar we restore
* its (transient) parent field here. Likewise for top level
* windows that are "owned" by this frame.
*/
/**
* Frame Serialized Data Version.
*
* @serial
*/
private int frameSerializedDataVersion = 1;
/**
* Writes default serializable fields to stream. Writes
* a list of serializable ItemListener(s) as optional data.
* The non-serializable ItemListner(s) are detected and
* no attempt is made to serialize them.
*
* @serialData Null terminated sequence of 0 or more pairs.
* The pair consists of a String and Object.
* The String indicates the type of object and
* is one of the following :
* itemListenerK indicating and ItemListener object.
*
* @see java.awt.Component.itemListenerK
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
s.defaultWriteObject();
}
/**
* Read the ObjectInputStream and if it isnt null
* add a listener to receive item events fired
* by the Frame.
* Unrecognised keys or values will be Ignored.
* @see removeActionListener()
* @see addActionListener()
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException {
s.defaultReadObject();
if (menuBar != null)
menuBar.parent = this;
if (ownedWindows != null) {
for (int i = 0; i < ownedWindows.size(); i++) {
Window child = (Window) (ownedWindows.elementAt(i));
child.parent = this;
}
}
}
}