1 /* 2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing; 26 27 import java.awt.*; 28 import java.awt.event.*; 29 import java.applet.Applet; 30 import java.beans.PropertyChangeListener; 31 import java.util.Locale; 32 import java.util.Vector; 33 import java.io.Serializable; 34 import javax.accessibility.*; 35 36 /** 37 * An extended version of <code>java.applet.Applet</code> that adds support for 38 * the JFC/Swing component architecture. 39 * You can find task-oriented documentation about using <code>JApplet</code> 40 * in <em>The Java Tutorial</em>, 41 * in the section 42 * <a 43 href="http://java.sun.com/docs/books/tutorial/uiswing/components/applet.html">How to Make Applets</a>. 44 * <p> 45 * The <code>JApplet</code> class is slightly incompatible with 46 * <code>java.applet.Applet</code>. <code>JApplet</code> contains a 47 * <code>JRootPane</code> as its only child. The <code>contentPane</code> 48 * should be the parent of any children of the <code>JApplet</code>. 49 * As a convenience <code>add</code> and its variants, <code>remove</code> and 50 * <code>setLayout</code> have been overridden to forward to the 51 * <code>contentPane</code> as necessary. This means you can write: 52 * <pre> 53 * applet.add(child); 54 * </pre> 55 * 56 * And the child will be added to the <code>contentPane</code>. 57 * The <code>contentPane</code> will always be non-<code>null</code>. 58 * Attempting to set it to <code>null</code> will cause the 59 * <code>JApplet</code> to throw an exception. The default 60 * <code>contentPane</code> will have a <code>BorderLayout</code> 61 * manager set on it. 62 * Refer to {@link javax.swing.RootPaneContainer} 63 * for details on adding, removing and setting the <code>LayoutManager</code> 64 * of a <code>JApplet</code>. 65 * <p> 66 * Please see the <code>JRootPane</code> documentation for a 67 * complete description of the <code>contentPane</code>, <code>glassPane</code>, 68 * and <code>layeredPane</code> properties. 69 * <p> 70 * <strong>Warning:</strong> Swing is not thread safe. For more 71 * information see <a 72 * href="package-summary.html#threading">Swing's Threading 73 * Policy</a>. 74 * <p> 75 * <strong>Warning:</strong> 76 * Serialized objects of this class will not be compatible with 77 * future Swing releases. The current serialization support is 78 * appropriate for short term storage or RMI between applications running 79 * the same version of Swing. As of 1.4, support for long term storage 80 * of all JavaBeans<sup><font size="-2">TM</font></sup> 81 * has been added to the <code>java.beans</code> package. 82 * Please see {@link java.beans.XMLEncoder}. 83 * 84 * @see javax.swing.RootPaneContainer 85 * @beaninfo 86 * attribute: isContainer true 87 * attribute: containerDelegate getContentPane 88 * description: Swing's Applet subclass. 89 * 90 * @author Arnaud Weber 91 */ 92 public class JApplet extends Applet implements Accessible, 93 RootPaneContainer, 94 TransferHandler.HasGetTransferHandler 95 { 96 /** 97 * @see #getRootPane 98 * @see #setRootPane 99 */ 100 protected JRootPane rootPane; 101 102 /** 103 * If true then calls to <code>add</code> and <code>setLayout</code> 104 * will be forwarded to the <code>contentPane</code>. This is initially 105 * false, but is set to true when the <code>JApplet</code> is constructed. 106 * 107 * @see #isRootPaneCheckingEnabled 108 * @see #setRootPaneCheckingEnabled 109 * @see javax.swing.RootPaneContainer 110 */ 111 protected boolean rootPaneCheckingEnabled = false; 112 113 /** 114 * The <code>TransferHandler</code> for this applet. 115 */ 116 private TransferHandler transferHandler; 117 118 /** 119 * Creates a swing applet instance. 120 * <p> 121 * This constructor sets the component's locale property to the value 122 * returned by <code>JComponent.getDefaultLocale</code>. 123 * 124 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 125 * returns true. 126 * @see java.awt.GraphicsEnvironment#isHeadless 127 * @see JComponent#getDefaultLocale 128 */ 129 public JApplet() throws HeadlessException { 130 super(); 131 // Check the timerQ and restart if necessary. 132 TimerQueue q = TimerQueue.sharedInstance(); 133 if(q != null) { 134 q.startIfNeeded(); 135 } 136 137 /* Workaround for bug 4155072. The shared double buffer image 138 * may hang on to a reference to this applet; unfortunately 139 * Image.getGraphics() will continue to call JApplet.getForeground() 140 * and getBackground() even after this applet has been destroyed. 141 * So we ensure that these properties are non-null here. 142 */ 143 setForeground(Color.black); 144 setBackground(Color.white); 145 146 setLocale( JComponent.getDefaultLocale() ); 147 setLayout(new BorderLayout()); 148 setRootPane(createRootPane()); 149 setRootPaneCheckingEnabled(true); 150 151 setFocusTraversalPolicyProvider(true); 152 sun.awt.SunToolkit.checkAndSetPolicy(this); 153 154 enableEvents(AWTEvent.KEY_EVENT_MASK); 155 } 156 157 158 /** Called by the constructor methods to create the default rootPane. */ 159 protected JRootPane createRootPane() { 160 JRootPane rp = new JRootPane(); 161 // NOTE: this uses setOpaque vs LookAndFeel.installProperty as there 162 // is NO reason for the RootPane not to be opaque. For painting to 163 // work the contentPane must be opaque, therefor the RootPane can 164 // also be opaque. 165 rp.setOpaque(true); 166 return rp; 167 } 168 169 /** 170 * Sets the {@code transferHandler} property, which is a mechanism to 171 * support transfer of data into this component. Use {@code null} 172 * if the component does not support data transfer operations. 173 * <p> 174 * If the system property {@code suppressSwingDropSupport} is {@code false} 175 * (the default) and the current drop target on this component is either 176 * {@code null} or not a user-set drop target, this method will change the 177 * drop target as follows: If {@code newHandler} is {@code null} it will 178 * clear the drop target. If not {@code null} it will install a new 179 * {@code DropTarget}. 180 * <p> 181 * Note: When used with {@code JApplet}, {@code TransferHandler} only 182 * provides data import capability, as the data export related methods 183 * are currently typed to {@code JComponent}. 184 * <p> 185 * Please see 186 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/dnd.html"> 187 * How to Use Drag and Drop and Data Transfer</a>, a section in 188 * <em>The Java Tutorial</em>, for more information. 189 * 190 * @param newHandler the new {@code TransferHandler} 191 * 192 * @see TransferHandler 193 * @see #getTransferHandler 194 * @see java.awt.Component#setDropTarget 195 * @since 1.6 196 * 197 * @beaninfo 198 * bound: true 199 * hidden: true 200 * description: Mechanism for transfer of data into the component 201 */ 202 public void setTransferHandler(TransferHandler newHandler) { 203 TransferHandler oldHandler = transferHandler; 204 transferHandler = newHandler; 205 SwingUtilities.installSwingDropTargetAsNecessary(this, transferHandler); 206 firePropertyChange("transferHandler", oldHandler, newHandler); 207 } 208 209 /** 210 * Gets the <code>transferHandler</code> property. 211 * 212 * @return the value of the <code>transferHandler</code> property 213 * 214 * @see TransferHandler 215 * @see #setTransferHandler 216 * @since 1.6 217 */ 218 public TransferHandler getTransferHandler() { 219 return transferHandler; 220 } 221 222 /** 223 * Just calls <code>paint(g)</code>. This method was overridden to 224 * prevent an unnecessary call to clear the background. 225 */ 226 public void update(Graphics g) { 227 paint(g); 228 } 229 230 /** 231 * Sets the menubar for this applet. 232 * @param menuBar the menubar being placed in the applet 233 * 234 * @see #getJMenuBar 235 * 236 * @beaninfo 237 * hidden: true 238 * description: The menubar for accessing pulldown menus from this applet. 239 */ 240 public void setJMenuBar(JMenuBar menuBar) { 241 getRootPane().setMenuBar(menuBar); 242 } 243 244 /** 245 * Returns the menubar set on this applet. 246 * 247 * @see #setJMenuBar 248 */ 249 public JMenuBar getJMenuBar() { 250 return getRootPane().getMenuBar(); 251 } 252 253 254 /** 255 * Returns whether calls to <code>add</code> and 256 * <code>setLayout</code> are forwarded to the <code>contentPane</code>. 257 * 258 * @return true if <code>add</code> and <code>setLayout</code> 259 * are fowarded; false otherwise 260 * 261 * @see #addImpl 262 * @see #setLayout 263 * @see #setRootPaneCheckingEnabled 264 * @see javax.swing.RootPaneContainer 265 */ 266 protected boolean isRootPaneCheckingEnabled() { 267 return rootPaneCheckingEnabled; 268 } 269 270 271 /** 272 * Sets whether calls to <code>add</code> and 273 * <code>setLayout</code> are forwarded to the <code>contentPane</code>. 274 * 275 * @param enabled true if <code>add</code> and <code>setLayout</code> 276 * are forwarded, false if they should operate directly on the 277 * <code>JApplet</code>. 278 * 279 * @see #addImpl 280 * @see #setLayout 281 * @see #isRootPaneCheckingEnabled 282 * @see javax.swing.RootPaneContainer 283 * @beaninfo 284 * hidden: true 285 * description: Whether the add and setLayout methods are forwarded 286 */ 287 protected void setRootPaneCheckingEnabled(boolean enabled) { 288 rootPaneCheckingEnabled = enabled; 289 } 290 291 292 /** 293 * Adds the specified child <code>Component</code>. 294 * This method is overridden to conditionally forward calls to the 295 * <code>contentPane</code>. 296 * By default, children are added to the <code>contentPane</code> instead 297 * of the frame, refer to {@link javax.swing.RootPaneContainer} for 298 * details. 299 * 300 * @param comp the component to be enhanced 301 * @param constraints the constraints to be respected 302 * @param index the index 303 * @exception IllegalArgumentException if <code>index</code> is invalid 304 * @exception IllegalArgumentException if adding the container's parent 305 * to itself 306 * @exception IllegalArgumentException if adding a window to a container 307 * 308 * @see #setRootPaneCheckingEnabled 309 * @see javax.swing.RootPaneContainer 310 */ 311 protected void addImpl(Component comp, Object constraints, int index) 312 { 313 if(isRootPaneCheckingEnabled()) { 314 getContentPane().add(comp, constraints, index); 315 } 316 else { 317 super.addImpl(comp, constraints, index); 318 } 319 } 320 321 /** 322 * Removes the specified component from the container. If 323 * <code>comp</code> is not the <code>rootPane</code>, this will forward 324 * the call to the <code>contentPane</code>. This will do nothing if 325 * <code>comp</code> is not a child of the <code>JFrame</code> or 326 * <code>contentPane</code>. 327 * 328 * @param comp the component to be removed 329 * @throws NullPointerException if <code>comp</code> is null 330 * @see #add 331 * @see javax.swing.RootPaneContainer 332 */ 333 public void remove(Component comp) { 334 if (comp == rootPane) { 335 super.remove(comp); 336 } else { 337 getContentPane().remove(comp); 338 } 339 } 340 341 342 /** 343 * Sets the <code>LayoutManager</code>. 344 * Overridden to conditionally forward the call to the 345 * <code>contentPane</code>. 346 * Refer to {@link javax.swing.RootPaneContainer} for 347 * more information. 348 * 349 * @param manager the <code>LayoutManager</code> 350 * @see #setRootPaneCheckingEnabled 351 * @see javax.swing.RootPaneContainer 352 */ 353 public void setLayout(LayoutManager manager) { 354 if(isRootPaneCheckingEnabled()) { 355 getContentPane().setLayout(manager); 356 } 357 else { 358 super.setLayout(manager); 359 } 360 } 361 362 363 /** 364 * Returns the rootPane object for this applet. 365 * 366 * @see #setRootPane 367 * @see RootPaneContainer#getRootPane 368 */ 369 public JRootPane getRootPane() { 370 return rootPane; 371 } 372 373 374 /** 375 * Sets the rootPane property. This method is called by the constructor. 376 * @param root the rootPane object for this applet 377 * 378 * @see #getRootPane 379 * 380 * @beaninfo 381 * hidden: true 382 * description: the RootPane object for this applet. 383 */ 384 protected void setRootPane(JRootPane root) { 385 if(rootPane != null) { 386 remove(rootPane); 387 } 388 rootPane = root; 389 if(rootPane != null) { 390 boolean checkingEnabled = isRootPaneCheckingEnabled(); 391 try { 392 setRootPaneCheckingEnabled(false); 393 add(rootPane, BorderLayout.CENTER); 394 } 395 finally { 396 setRootPaneCheckingEnabled(checkingEnabled); 397 } 398 } 399 } 400 401 402 /** 403 * Returns the contentPane object for this applet. 404 * 405 * @see #setContentPane 406 * @see RootPaneContainer#getContentPane 407 */ 408 public Container getContentPane() { 409 return getRootPane().getContentPane(); 410 } 411 412 /** 413 * Sets the contentPane property. This method is called by the constructor. 414 * @param contentPane the contentPane object for this applet 415 * 416 * @exception java.awt.IllegalComponentStateException (a runtime 417 * exception) if the content pane parameter is null 418 * @see #getContentPane 419 * @see RootPaneContainer#setContentPane 420 * 421 * @beaninfo 422 * hidden: true 423 * description: The client area of the applet where child 424 * components are normally inserted. 425 */ 426 public void setContentPane(Container contentPane) { 427 getRootPane().setContentPane(contentPane); 428 } 429 430 /** 431 * Returns the layeredPane object for this applet. 432 * 433 * @exception java.awt.IllegalComponentStateException (a runtime 434 * exception) if the layered pane parameter is null 435 * @see #setLayeredPane 436 * @see RootPaneContainer#getLayeredPane 437 */ 438 public JLayeredPane getLayeredPane() { 439 return getRootPane().getLayeredPane(); 440 } 441 442 /** 443 * Sets the layeredPane property. This method is called by the constructor. 444 * @param layeredPane the layeredPane object for this applet 445 * 446 * @see #getLayeredPane 447 * @see RootPaneContainer#setLayeredPane 448 * 449 * @beaninfo 450 * hidden: true 451 * description: The pane which holds the various applet layers. 452 */ 453 public void setLayeredPane(JLayeredPane layeredPane) { 454 getRootPane().setLayeredPane(layeredPane); 455 } 456 457 /** 458 * Returns the glassPane object for this applet. 459 * 460 * @see #setGlassPane 461 * @see RootPaneContainer#getGlassPane 462 */ 463 public Component getGlassPane() { 464 return getRootPane().getGlassPane(); 465 } 466 467 /** 468 * Sets the glassPane property. 469 * This method is called by the constructor. 470 * @param glassPane the glassPane object for this applet 471 * 472 * @see #getGlassPane 473 * @see RootPaneContainer#setGlassPane 474 * 475 * @beaninfo 476 * hidden: true 477 * description: A transparent pane used for menu rendering. 478 */ 479 public void setGlassPane(Component glassPane) { 480 getRootPane().setGlassPane(glassPane); 481 } 482 483 /** 484 * {@inheritDoc} 485 * 486 * @since 1.6 487 */ 488 public Graphics getGraphics() { 489 JComponent.getGraphicsInvoked(this); 490 return super.getGraphics(); 491 } 492 493 /** 494 * Repaints the specified rectangle of this component within 495 * <code>time</code> milliseconds. Refer to <code>RepaintManager</code> 496 * for details on how the repaint is handled. 497 * 498 * @param time maximum time in milliseconds before update 499 * @param x the <i>x</i> coordinate 500 * @param y the <i>y</i> coordinate 501 * @param width the width 502 * @param height the height 503 * @see RepaintManager 504 * @since 1.6 505 */ 506 public void repaint(long time, int x, int y, int width, int height) { 507 if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) { 508 RepaintManager.currentManager(this).addDirtyRegion( 509 this, x, y, width, height); 510 } 511 else { 512 super.repaint(time, x, y, width, height); 513 } 514 } 515 516 /** 517 * Returns a string representation of this JApplet. This method 518 * is intended to be used only for debugging purposes, and the 519 * content and format of the returned string may vary between 520 * implementations. The returned string may be empty but may not 521 * be <code>null</code>. 522 * 523 * @return a string representation of this JApplet. 524 */ 525 protected String paramString() { 526 String rootPaneString = (rootPane != null ? 527 rootPane.toString() : ""); 528 String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ? 529 "true" : "false"); 530 531 return super.paramString() + 532 ",rootPane=" + rootPaneString + 533 ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString; 534 } 535 536 537 538 ///////////////// 539 // Accessibility support 540 //////////////// 541 542 protected AccessibleContext accessibleContext = null; 543 544 /** 545 * Gets the AccessibleContext associated with this JApplet. 546 * For JApplets, the AccessibleContext takes the form of an 547 * AccessibleJApplet. 548 * A new AccessibleJApplet instance is created if necessary. 549 * 550 * @return an AccessibleJApplet that serves as the 551 * AccessibleContext of this JApplet 552 */ 553 public AccessibleContext getAccessibleContext() { 554 if (accessibleContext == null) { 555 accessibleContext = new AccessibleJApplet(); 556 } 557 return accessibleContext; 558 } 559 560 /** 561 * This class implements accessibility support for the 562 * <code>JApplet</code> class. 563 */ 564 protected class AccessibleJApplet extends AccessibleApplet { 565 // everything moved to new parent, AccessibleApplet 566 } 567 }