001/* JFrame.java -- 002 Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package javax.swing; 040 041import gnu.java.lang.CPStringBuilder; 042 043import java.awt.AWTEvent; 044import java.awt.BorderLayout; 045import java.awt.Component; 046import java.awt.Container; 047import java.awt.Dimension; 048import java.awt.Frame; 049import java.awt.Graphics; 050import java.awt.GraphicsConfiguration; 051import java.awt.LayoutManager; 052import java.awt.event.KeyEvent; 053import java.awt.event.WindowEvent; 054 055import javax.accessibility.Accessible; 056import 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 */ 070public 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}