001 /* JFrame.java --
002 Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.swing;
040
041 import gnu.java.lang.CPStringBuilder;
042
043 import java.awt.AWTEvent;
044 import java.awt.BorderLayout;
045 import java.awt.Component;
046 import java.awt.Container;
047 import java.awt.Dimension;
048 import java.awt.Frame;
049 import java.awt.Graphics;
050 import java.awt.GraphicsConfiguration;
051 import java.awt.LayoutManager;
052 import java.awt.event.KeyEvent;
053 import java.awt.event.WindowEvent;
054
055 import javax.accessibility.Accessible;
056 import javax.accessibility.AccessibleContext;
057
058 /**
059 * A window that supports window decorations (titlebar and borders).
060 * This is an extension of {@link java.awt.Frame} that provides support
061 * for the Swing architecture. Most importantly it contains a {@link JRootPane}
062 * as it's only top-level child, that manages the content pane, the menu and
063 * a glass pane.
064 *
065 * Also, unlike <code>java.awt.Frame</code>s, JFrames support the
066 * Swing Pluggable Look & Feel architecture.
067 *
068 * @author Ronald Veldema (rveldema@cs.vu.nl)
069 */
070 public class JFrame extends Frame
071 implements WindowConstants, RootPaneContainer, Accessible
072 {
073 /**
074 * Provides accessibility support for <code>JFrame</code>s.
075 */
076 protected class AccessibleJFrame extends Frame.AccessibleAWTFrame
077 {
078 /**
079 * Creates a new instance of <code>AccessibleJFrame</code>.
080 */
081 protected AccessibleJFrame()
082 {
083 super();
084 // Nothing to do here.
085 }
086 }
087
088 /**
089 * A flag for {@link #setDefaultCloseOperation(int)}, indicating that the
090 * application should be exited, when this <code>JFrame</code> is closed.
091 * Note that in version 1.4, the equivalent constant has been added to
092 * {@link WindowConstants}.
093 *
094 * @since 1.3
095 */
096 public static final int EXIT_ON_CLOSE = 3;
097
098 private static final long serialVersionUID = -3362141868504252139L;
099 private static boolean defaultLookAndFeelDecorated;
100 private int closeAction = HIDE_ON_CLOSE;
101 protected AccessibleContext accessibleContext;
102 protected JRootPane rootPane;
103
104 /**
105 * @specnote rootPaneCheckingEnabled is false to comply with J2SE 5.0
106 */
107 protected boolean rootPaneCheckingEnabled = false;
108
109 /**
110 * Creates a new frame with an empty string for the title.
111 */
112 public JFrame()
113 {
114 super("");
115 frameInit();
116 }
117
118 /**
119 * Creates a new <code>JFrame</code> with the specified title.
120 *
121 * @param title the frame title (<code>null</code> permitted).
122 */
123 public JFrame(String title)
124 {
125 super(title);
126 frameInit();
127 }
128
129 /**
130 * Creates a new JFrame in the specified {@link GraphicsConfiguration}
131 * and with an empty title.
132 *
133 * @param gc the <code>GraphicsConfiguration</code> that is used for
134 * the new <code>JFrame</code>
135 *
136 * @see Frame#Frame(GraphicsConfiguration)
137 */
138 public JFrame(GraphicsConfiguration gc)
139 {
140 super(gc);
141 frameInit();
142 }
143
144 /**
145 * Creates a new JFrame in the specified {@link GraphicsConfiguration}
146 * and with the specified title.
147 *
148 * @param title the title for the new <code>JFrame</code>
149 * @param gc the <code>GraphicsConfiguration</code> that is used for
150 * the new <code>JFrame</code>
151 *
152 * @see Frame#Frame(String, GraphicsConfiguration)
153 */
154 public JFrame(String title, GraphicsConfiguration gc)
155 {
156 super(title, gc);
157 frameInit();
158 }
159
160 protected void frameInit()
161 {
162 // We need to explicitly enable events here so that our processKeyEvent()
163 // and processWindowEvent() gets called.
164 enableEvents(AWTEvent.WINDOW_EVENT_MASK | AWTEvent.KEY_EVENT_MASK);
165
166 super.setLayout(new BorderLayout());
167 setBackground(UIManager.getDefaults().getColor("control"));
168 enableEvents(AWTEvent.WINDOW_EVENT_MASK);
169 getRootPane(); // will do set/create
170
171 // Setup the defaultLookAndFeelDecoration if requested.
172 if (isDefaultLookAndFeelDecorated()
173 && UIManager.getLookAndFeel().getSupportsWindowDecorations())
174 {
175 setUndecorated(true);
176 getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
177 }
178
179 // We're now done the init stage.
180 setRootPaneCheckingEnabled(true);
181 }
182
183 public Dimension getPreferredSize()
184 {
185 return super.getPreferredSize();
186 }
187
188 public JMenuBar getJMenuBar()
189 {
190 return getRootPane().getJMenuBar();
191 }
192
193 public void setJMenuBar(JMenuBar menubar)
194 {
195 getRootPane().setJMenuBar(menubar);
196 }
197
198 public void setLayout(LayoutManager manager)
199 {
200 // Check if we're in initialization stage. If so, call super.setLayout
201 // otherwise, valid calls go to the content pane.
202 if (isRootPaneCheckingEnabled())
203 getContentPane().setLayout(manager);
204 else
205 super.setLayout(manager);
206 }
207
208 public void setLayeredPane(JLayeredPane layeredPane)
209 {
210 getRootPane().setLayeredPane(layeredPane);
211 }
212
213 public JLayeredPane getLayeredPane()
214 {
215 return getRootPane().getLayeredPane();
216 }
217
218 public JRootPane getRootPane()
219 {
220 if (rootPane == null)
221 setRootPane(createRootPane());
222 return rootPane;
223 }
224
225 protected void setRootPane(JRootPane root)
226 {
227 if (rootPane != null)
228 remove(rootPane);
229
230 rootPane = root;
231 add(rootPane, BorderLayout.CENTER);
232 }
233
234 protected JRootPane createRootPane()
235 {
236 return new JRootPane();
237 }
238
239 public Container getContentPane()
240 {
241 return getRootPane().getContentPane();
242 }
243
244 public void setContentPane(Container contentPane)
245 {
246 getRootPane().setContentPane(contentPane);
247 }
248
249 public Component getGlassPane()
250 {
251 return getRootPane().getGlassPane();
252 }
253
254 public void setGlassPane(Component glassPane)
255 {
256 getRootPane().setGlassPane(glassPane);
257 }
258
259 protected void addImpl(Component comp, Object constraints, int index)
260 {
261 // If we're adding in the initialization stage use super.add.
262 // Otherwise pass the add onto the content pane.
263 if (isRootPaneCheckingEnabled() && comp != rootPane)
264 getContentPane().add(comp,constraints,index);
265 else
266 super.addImpl(comp, constraints, index);
267 }
268
269 public void remove(Component comp)
270 {
271 // If we're removing the root pane, use super.remove. Otherwise
272 // pass it on to the content pane instead.
273 if (comp==rootPane)
274 super.remove(rootPane);
275 else
276 getContentPane().remove(comp);
277 }
278
279 protected boolean isRootPaneCheckingEnabled()
280 {
281 return rootPaneCheckingEnabled;
282 }
283
284 protected void setRootPaneCheckingEnabled(boolean enabled)
285 {
286 rootPaneCheckingEnabled = enabled;
287 }
288
289 public void update(Graphics g)
290 {
291 paint(g);
292 }
293
294 protected void processKeyEvent(KeyEvent e)
295 {
296 super.processKeyEvent(e);
297 }
298
299 public static void setDefaultLookAndFeelDecorated(boolean decorated)
300 {
301 defaultLookAndFeelDecorated = decorated;
302 }
303
304 public static boolean isDefaultLookAndFeelDecorated()
305 {
306 return defaultLookAndFeelDecorated;
307 }
308
309 /**
310 * Returns the object that provides accessibility features for this
311 * <code>JFrame</code>.
312 *
313 * @return The accessible context (an instance of {@link AccessibleJFrame}).
314 */
315 public AccessibleContext getAccessibleContext()
316 {
317 if (accessibleContext == null)
318 accessibleContext = new AccessibleJFrame();
319 return accessibleContext;
320 }
321
322 /**
323 * Returns a code for the default operation when the frame is closed. The
324 * default value is {@link WindowConstants#HIDE_ON_CLOSE}.
325 *
326 * @return One of: {@link WindowConstants#DO_NOTHING_ON_CLOSE},
327 * {@link WindowConstants#HIDE_ON_CLOSE},
328 * {@link WindowConstants#DISPOSE_ON_CLOSE}, {@link #EXIT_ON_CLOSE}.
329 *
330 * @see #setDefaultCloseOperation(int)
331 */
332 public int getDefaultCloseOperation()
333 {
334 return closeAction;
335 }
336
337 /**
338 * Returns a string describing the attributes for the <code>JFrame</code>,
339 * for use in debugging. The return value is guaranteed to be
340 * non-<code>null</code>, but the format may vary between implementations.
341 *
342 * @return A string describing the attributes of the <code>JFrame</code>.
343 */
344 protected String paramString()
345 {
346 CPStringBuilder sb = new CPStringBuilder(super.paramString());
347 sb.append(",defaultCloseOperation=");
348 sb.append(SwingUtilities.convertWindowConstantToString(
349 getDefaultCloseOperation()));
350 sb.append(",rootPane=");
351 if (rootPane != null)
352 sb.append(rootPane);
353 sb.append(",rootPaneCheckingEnabled=").append(rootPaneCheckingEnabled);
354 return sb.toString();
355 }
356
357 protected void processWindowEvent(WindowEvent e)
358 {
359 super.processWindowEvent(e);
360 if (e.getID() == WindowEvent.WINDOW_CLOSING)
361 {
362 switch (closeAction)
363 {
364 case EXIT_ON_CLOSE:
365 System.exit(0);
366 break;
367 case DISPOSE_ON_CLOSE:
368 dispose();
369 break;
370 case HIDE_ON_CLOSE:
371 setVisible(false);
372 break;
373 case DO_NOTHING_ON_CLOSE:
374 break;
375 }
376 }
377 }
378
379 /**
380 * Sets the default operation that is performed when this frame is closed.
381 * The default is <code>HIDE_ON_CLOSE</code>. When
382 * <code>EXIT_ON_CLOSE</code> is specified this method calls
383 * <code>SecurityManager.checkExit(0)</code> which might throw a
384 * <code>SecurityException</code>.
385 *
386 * @param operation a code for the operation (one of:
387 * {@link WindowConstants#DO_NOTHING_ON_CLOSE},
388 * {@link WindowConstants#HIDE_ON_CLOSE},
389 * {@link WindowConstants#DISPOSE_ON_CLOSE} and
390 * {@link WindowConstants#EXIT_ON_CLOSE}).
391 *
392 * @throws IllegalArgumentException if <code>operation</code> is not one of
393 * the specified codes.
394 *
395 * @see #getDefaultCloseOperation()
396 */
397 public void setDefaultCloseOperation(int operation)
398 {
399 SecurityManager sm = System.getSecurityManager();
400 if (sm != null && operation == EXIT_ON_CLOSE)
401 sm.checkExit(0);
402
403 if (operation != EXIT_ON_CLOSE && operation != DISPOSE_ON_CLOSE
404 && operation != HIDE_ON_CLOSE && operation != DO_NOTHING_ON_CLOSE)
405 throw new IllegalArgumentException("operation must be EXIT_ON_CLOSE, "
406 + "HIDE_ON_CLOSE, DISPOSE_ON_CLOSE, or DO_NOTHING_ON_CLOSE");
407
408 closeAction = operation;
409 }
410 }