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 }