1. /*
  2. * @(#)JApplet.java 1.65 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.applet.Applet;
  11. import java.beans.PropertyChangeListener;
  12. import java.util.Locale;
  13. import java.util.Vector;
  14. import java.io.Serializable;
  15. import javax.accessibility.*;
  16. /**
  17. * An extended version of <code>java.applet.Applet</code> that adds support for
  18. * the JFC/Swing component architecture.
  19. * You can find task-oriented documentation about using <code>JApplet</code>
  20. * in <em>The Java Tutorial</em>,
  21. * in the section
  22. * <a
  23. href="http://java.sun.com/docs/books/tutorial/uiswing/components/applet.html">How to Make Applets</a>.
  24. * <p>
  25. * The <code>JApplet</code> class is slightly incompatible with
  26. * <code>java.applet.Applet</code>. <code>JApplet</code> contains a
  27. * <code>JRootPane</code> as its only child. The <code>contentPane</code>
  28. * should be the parent of any children of the <code>JApplet</code>.
  29. * As a convenience <code>add</code> and its variants, <code>remove</code> and
  30. * <code>setLayout</code> have been overridden to forward to the
  31. * <code>contentPane</code> as necessary. This means you can write:
  32. * <pre>
  33. * applet.add(child);
  34. * </pre>
  35. *
  36. * And the child will be added to the <code>contentPane</code>.
  37. * The <code>contentPane</code> will always be non-<code>null</code>.
  38. * Attempting to set it to <code>null</code> will cause the
  39. * <code>JApplet</code> to throw an exception. The default
  40. * <code>contentPane</code> will have a <code>BorderLayout</code>
  41. * manager set on it.
  42. * Refer to {@link javax.swing.RootPaneContainer}
  43. * for details on adding, removing and setting the <code>LayoutManager</code>
  44. * of a <code>JApplet</code>.
  45. * <p>
  46. * Please see the <code>JRootPane</code> documentation for a
  47. * complete description of the <code>contentPane</code>, <code>glassPane</code>,
  48. * and <code>layeredPane</code> properties.
  49. * <p>
  50. * <strong>Warning:</strong>
  51. * Serialized objects of this class will not be compatible with
  52. * future Swing releases. The current serialization support is
  53. * appropriate for short term storage or RMI between applications running
  54. * the same version of Swing. As of 1.4, support for long term storage
  55. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  56. * has been added to the <code>java.beans</code> package.
  57. * Please see {@link java.beans.XMLEncoder}.
  58. *
  59. * @see javax.swing.RootPaneContainer
  60. * @beaninfo
  61. * attribute: isContainer true
  62. * attribute: containerDelegate getContentPane
  63. * description: Swing's Applet subclass.
  64. *
  65. * @version 1.65 12/19/03
  66. * @author Arnaud Weber
  67. */
  68. public class JApplet extends Applet implements Accessible, RootPaneContainer
  69. {
  70. /**
  71. * @see #getRootPane
  72. * @see #setRootPane
  73. */
  74. protected JRootPane rootPane;
  75. /**
  76. * If true then calls to <code>add</code> and <code>setLayout</code>
  77. * will be forwarded to the <code>contentPane</code>. This is initially
  78. * false, but is set to true when the <code>JApplet</code> is constructed.
  79. *
  80. * @see #isRootPaneCheckingEnabled
  81. * @see #setRootPaneCheckingEnabled
  82. * @see javax.swing.RootPaneContainer
  83. */
  84. protected boolean rootPaneCheckingEnabled = false;
  85. /**
  86. * Creates a swing applet instance.
  87. * <p>
  88. * This constructor sets the component's locale property to the value
  89. * returned by <code>JComponent.getDefaultLocale</code>.
  90. *
  91. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  92. * returns true.
  93. * @see java.awt.GraphicsEnvironment#isHeadless
  94. * @see JComponent#getDefaultLocale
  95. */
  96. public JApplet() throws HeadlessException {
  97. super();
  98. // Check the timerQ and restart if necessary.
  99. TimerQueue q = TimerQueue.sharedInstance();
  100. if(q != null) {
  101. synchronized(q) {
  102. if(!q.running)
  103. q.start();
  104. }
  105. }
  106. /* Workaround for bug 4155072. The shared double buffer image
  107. * may hang on to a reference to this applet; unfortunately
  108. * Image.getGraphics() will continue to call JApplet.getForeground()
  109. * and getBackground() even after this applet has been destroyed.
  110. * So we ensure that these properties are non-null here.
  111. */
  112. setForeground(Color.black);
  113. setBackground(Color.white);
  114. setLocale( JComponent.getDefaultLocale() );
  115. setLayout(new BorderLayout());
  116. setRootPane(createRootPane());
  117. setRootPaneCheckingEnabled(true);
  118. setFocusTraversalPolicyProvider(true);
  119. sun.awt.SunToolkit.checkAndSetPolicy(this, true);
  120. enableEvents(AWTEvent.KEY_EVENT_MASK);
  121. }
  122. /** Called by the constructor methods to create the default rootPane. */
  123. protected JRootPane createRootPane() {
  124. JRootPane rp = new JRootPane();
  125. // NOTE: this uses setOpaque vs LookAndFeel.installProperty as there
  126. // is NO reason for the RootPane not to be opaque. For painting to
  127. // work the contentPane must be opaque, therefor the RootPane can
  128. // also be opaque.
  129. rp.setOpaque(true);
  130. return rp;
  131. }
  132. /**
  133. * Just calls <code>paint(g)</code>. This method was overridden to
  134. * prevent an unnecessary call to clear the background.
  135. */
  136. public void update(Graphics g) {
  137. paint(g);
  138. }
  139. /**
  140. * Sets the menubar for this applet.
  141. * @param menuBar the menubar being placed in the applet
  142. *
  143. * @see #getJMenuBar
  144. *
  145. * @beaninfo
  146. * hidden: true
  147. * description: The menubar for accessing pulldown menus from this applet.
  148. */
  149. public void setJMenuBar(JMenuBar menuBar) {
  150. getRootPane().setMenuBar(menuBar);
  151. }
  152. /**
  153. * Returns the menubar set on this applet.
  154. *
  155. * @see #setJMenuBar
  156. */
  157. public JMenuBar getJMenuBar() {
  158. return getRootPane().getMenuBar();
  159. }
  160. /**
  161. * Returns whether calls to <code>add</code> and
  162. * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
  163. *
  164. * @return true if <code>add</code> and <code>setLayout</code>
  165. * are fowarded; false otherwise
  166. *
  167. * @see #addImpl
  168. * @see #setLayout
  169. * @see #setRootPaneCheckingEnabled
  170. * @see javax.swing.RootPaneContainer
  171. */
  172. protected boolean isRootPaneCheckingEnabled() {
  173. return rootPaneCheckingEnabled;
  174. }
  175. /**
  176. * Sets whether calls to <code>add</code> and
  177. * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
  178. *
  179. * @param enabled true if <code>add</code> and <code>setLayout</code>
  180. * are forwarded, false if they should operate directly on the
  181. * <code>JApplet</code>.
  182. *
  183. * @see #addImpl
  184. * @see #setLayout
  185. * @see #isRootPaneCheckingEnabled
  186. * @see javax.swing.RootPaneContainer
  187. * @beaninfo
  188. * hidden: true
  189. * description: Whether the add and setLayout methods are forwarded
  190. */
  191. protected void setRootPaneCheckingEnabled(boolean enabled) {
  192. rootPaneCheckingEnabled = enabled;
  193. }
  194. /**
  195. * Adds the specified child <code>Component</code>.
  196. * This method is overridden to conditionally forwad calls to the
  197. * <code>contentPane</code>.
  198. * By default, children are added to the <code>contentPane</code> instead
  199. * of the frame, refer to {@link javax.swing.RootPaneContainer} for
  200. * details.
  201. *
  202. * @param comp the component to be enhanced
  203. * @param constraints the constraints to be respected
  204. * @param index the index
  205. * @exception IllegalArgumentException if <code>index</code> is invalid
  206. * @exception IllegalArgumentException if adding the container's parent
  207. * to itself
  208. * @exception IllegalArgumentException if adding a window to a container
  209. *
  210. * @see #setRootPaneCheckingEnabled
  211. * @see javax.swing.RootPaneContainer
  212. */
  213. protected void addImpl(Component comp, Object constraints, int index)
  214. {
  215. if(isRootPaneCheckingEnabled()) {
  216. getContentPane().add(comp, constraints, index);
  217. }
  218. else {
  219. super.addImpl(comp, constraints, index);
  220. }
  221. }
  222. /**
  223. * Removes the specified component from the container. If
  224. * <code>comp</code> is not the <code>rootPane</code>, this will forward
  225. * the call to the <code>contentPane</code>. This will do nothing if
  226. * <code>comp</code> is not a child of the <code>JFrame</code> or
  227. * <code>contentPane</code>.
  228. *
  229. * @param comp the component to be removed
  230. * @throws NullPointerException if <code>comp</code> is null
  231. * @see #add
  232. * @see javax.swing.RootPaneContainer
  233. */
  234. public void remove(Component comp) {
  235. if (comp == rootPane) {
  236. super.remove(comp);
  237. } else {
  238. getContentPane().remove(comp);
  239. }
  240. }
  241. /**
  242. * Sets the <code>LayoutManager</code>.
  243. * Overridden to conditionally forward the call to the
  244. * <code>contentPane</code>.
  245. * Refer to {@link javax.swing.RootPaneContainer} for
  246. * more information.
  247. *
  248. * @param manager the <code>LayoutManager</code>
  249. * @see #setRootPaneCheckingEnabled
  250. * @see javax.swing.RootPaneContainer
  251. */
  252. public void setLayout(LayoutManager manager) {
  253. if(isRootPaneCheckingEnabled()) {
  254. getContentPane().setLayout(manager);
  255. }
  256. else {
  257. super.setLayout(manager);
  258. }
  259. }
  260. /**
  261. * Returns the rootPane object for this applet.
  262. *
  263. * @see #setRootPane
  264. * @see RootPaneContainer#getRootPane
  265. */
  266. public JRootPane getRootPane() {
  267. return rootPane;
  268. }
  269. /**
  270. * Sets the rootPane property. This method is called by the constructor.
  271. * @param root the rootPane object for this applet
  272. *
  273. * @see #getRootPane
  274. *
  275. * @beaninfo
  276. * hidden: true
  277. * description: the RootPane object for this applet.
  278. */
  279. protected void setRootPane(JRootPane root) {
  280. if(rootPane != null) {
  281. remove(rootPane);
  282. }
  283. rootPane = root;
  284. if(rootPane != null) {
  285. boolean checkingEnabled = isRootPaneCheckingEnabled();
  286. try {
  287. setRootPaneCheckingEnabled(false);
  288. add(rootPane, BorderLayout.CENTER);
  289. }
  290. finally {
  291. setRootPaneCheckingEnabled(checkingEnabled);
  292. }
  293. }
  294. }
  295. /**
  296. * Returns the contentPane object for this applet.
  297. *
  298. * @see #setContentPane
  299. * @see RootPaneContainer#getContentPane
  300. */
  301. public Container getContentPane() {
  302. return getRootPane().getContentPane();
  303. }
  304. /**
  305. * Sets the contentPane property. This method is called by the constructor.
  306. * @param contentPane the contentPane object for this applet
  307. *
  308. * @exception java.awt.IllegalComponentStateException (a runtime
  309. * exception) if the content pane parameter is null
  310. * @see #getContentPane
  311. * @see RootPaneContainer#setContentPane
  312. *
  313. * @beaninfo
  314. * hidden: true
  315. * description: The client area of the applet where child
  316. * components are normally inserted.
  317. */
  318. public void setContentPane(Container contentPane) {
  319. getRootPane().setContentPane(contentPane);
  320. }
  321. /**
  322. * Returns the layeredPane object for this applet.
  323. *
  324. * @exception java.awt.IllegalComponentStateException (a runtime
  325. * exception) if the layered pane parameter is null
  326. * @see #setLayeredPane
  327. * @see RootPaneContainer#getLayeredPane
  328. */
  329. public JLayeredPane getLayeredPane() {
  330. return getRootPane().getLayeredPane();
  331. }
  332. /**
  333. * Sets the layeredPane property. This method is called by the constructor.
  334. * @param layeredPane the layeredPane object for this applet
  335. *
  336. * @see #getLayeredPane
  337. * @see RootPaneContainer#setLayeredPane
  338. *
  339. * @beaninfo
  340. * hidden: true
  341. * description: The pane which holds the various applet layers.
  342. */
  343. public void setLayeredPane(JLayeredPane layeredPane) {
  344. getRootPane().setLayeredPane(layeredPane);
  345. }
  346. /**
  347. * Returns the glassPane object for this applet.
  348. *
  349. * @see #setGlassPane
  350. * @see RootPaneContainer#getGlassPane
  351. */
  352. public Component getGlassPane() {
  353. return getRootPane().getGlassPane();
  354. }
  355. /**
  356. * Sets the glassPane property.
  357. * This method is called by the constructor.
  358. * @param glassPane the glassPane object for this applet
  359. *
  360. * @see #getGlassPane
  361. * @see RootPaneContainer#setGlassPane
  362. *
  363. * @beaninfo
  364. * hidden: true
  365. * description: A transparent pane used for menu rendering.
  366. */
  367. public void setGlassPane(Component glassPane) {
  368. getRootPane().setGlassPane(glassPane);
  369. }
  370. /**
  371. * Returns a string representation of this JApplet. This method
  372. * is intended to be used only for debugging purposes, and the
  373. * content and format of the returned string may vary between
  374. * implementations. The returned string may be empty but may not
  375. * be <code>null</code>.
  376. *
  377. * @return a string representation of this JApplet.
  378. */
  379. protected String paramString() {
  380. String rootPaneString = (rootPane != null ?
  381. rootPane.toString() : "");
  382. String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ?
  383. "true" : "false");
  384. return super.paramString() +
  385. ",rootPane=" + rootPaneString +
  386. ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString;
  387. }
  388. /////////////////
  389. // Accessibility support
  390. ////////////////
  391. protected AccessibleContext accessibleContext = null;
  392. /**
  393. * Gets the AccessibleContext associated with this JApplet.
  394. * For JApplets, the AccessibleContext takes the form of an
  395. * AccessibleJApplet.
  396. * A new AccessibleJApplet instance is created if necessary.
  397. *
  398. * @return an AccessibleJApplet that serves as the
  399. * AccessibleContext of this JApplet
  400. */
  401. public AccessibleContext getAccessibleContext() {
  402. if (accessibleContext == null) {
  403. accessibleContext = new AccessibleJApplet();
  404. }
  405. return accessibleContext;
  406. }
  407. /**
  408. * This class implements accessibility support for the
  409. * <code>JApplet</code> class.
  410. */
  411. protected class AccessibleJApplet extends AccessibleApplet {
  412. // everything moved to new parent, AccessibleApplet
  413. }
  414. }