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