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