1. /*
  2. * @(#)JApplet.java 1.39 01/11/29
  3. *
  4. * Copyright 2002 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 java.applet.Applet that adds support for
  18. * interposing input and painting behavior in front of the applets
  19. * children (see glassPane), support for special children that
  20. * are managed by a LayeredPane (see rootPane) and for Swing MenuBars.
  21. * <p>
  22. * The JApplet class is slightly incompatible with java.applet.Applet.
  23. * JApplet contains a JRootPane as it's only child.
  24. * The <b>contentPane</b> should be the parent of any children of the JApplet.
  25. * This is different than java.applet.Applet, e.g. to add a child to
  26. * an an java.applet.Applet you'd write:
  27. * <pre>
  28. * applet.add(child);
  29. * </pre>
  30. * However using JApplet you need to add the child to the JApplet's contentPane
  31. * instead:
  32. * <pre>
  33. * applet.getContentPane().add(child);
  34. * </pre>
  35. * The same is true for setting LayoutManagers, removing components,
  36. * listing children, etc. All these methods should normally be sent to
  37. * the contentPane() instead of the JApplet itself. The contentPane() will
  38. * always be non-null. Attempting to set it to null will cause the JApplet
  39. * to throw an exception. The default contentPane() will have a BorderLayout
  40. * manager set on it.
  41. * <p>
  42. * Please see the JRootPane documentation for a complete description of
  43. * the contentPane, glassPane, and layeredPane properties.
  44. * <p>
  45. * For the keyboard keys used by this component in the standard Look and
  46. * Feel (L&F) renditions, see the
  47. * <a href="doc-files/Key-Index.html#JApplet">JApplet</a> key assignments.
  48. * <p>
  49. * Both Netscape Communicator and Internet Explorer 4.0 unconditionally
  50. * print an error message to the Java console when an applet attempts
  51. * to access the AWT system event queue. Swing applets do this once,
  52. * to check if access is permitted. To prevent the warning message in
  53. * a production applet one can set a client property called
  54. * "defeatSystemEventQueueCheck" on the JApplets RootPane to any
  55. * non null value, e.g:
  56. * <pre>
  57. * JRootPane rp = myJApplet.getRootPane();
  58. * rp.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
  59. * </pre>
  60. * We hope that future versions of the browsers will not have this
  61. * limitation and we'll be able to retire this hack.
  62. * <p>
  63. * <strong>Warning:</strong>
  64. * Serialized objects of this class will not be compatible with
  65. * future Swing releases. The current serialization support is appropriate
  66. * for short term storage or RMI between applications running the same
  67. * version of Swing. A future release of Swing will provide support for
  68. * long term persistence.
  69. *
  70. * @beaninfo
  71. * attribute: isContainer true
  72. * attribute: containerDelegate getContentPane
  73. * description: Swing's Applet subclass.
  74. *
  75. * @version 1.39 11/29/01
  76. * @author Arnaud Weber
  77. */
  78. public class JApplet extends Applet implements Accessible, RootPaneContainer
  79. {
  80. /**
  81. * @see #getRootPane
  82. * @see #setRootPane
  83. */
  84. protected JRootPane rootPane;
  85. /**
  86. * @see #isRootPaneCheckingEnabled
  87. * @see #setRootPaneCheckingEnabled
  88. */
  89. protected boolean rootPaneCheckingEnabled = false;
  90. /**
  91. * Creates a swing applet instance.
  92. */
  93. public JApplet() {
  94. super();
  95. // Check the timerQ and restart if necessary.
  96. TimerQueue q = TimerQueue.sharedInstance();
  97. if(q != null) {
  98. synchronized(q) {
  99. if(!q.running)
  100. q.start();
  101. }
  102. }
  103. /* Workaround for bug 4155072. The shared double buffer image
  104. * may hang on to a reference to this applet; unfortunately
  105. * Image.getGraphics() will continue to call JApplet.getForeground()
  106. * and getBackground() even after this applet has been destroyed.
  107. * So we ensure that these properties are non-null here.
  108. */
  109. setForeground(Color.black);
  110. setBackground(Color.white);
  111. setLayout(new BorderLayout());
  112. setRootPane(createRootPane());
  113. setRootPaneCheckingEnabled(true);
  114. }
  115. /** Called by the constructor methods to create the default rootPane. */
  116. protected JRootPane createRootPane() {
  117. return new JRootPane();
  118. }
  119. protected void processKeyEvent(KeyEvent e) {
  120. super.processKeyEvent(e);
  121. if(!e.isConsumed()) {
  122. JComponent.processKeyBindingsForAllComponents(e,this,e.getID() == KeyEvent.KEY_PRESSED);
  123. }
  124. }
  125. /**
  126. * Just calls <code>paint(g)</code>. This method was overridden to
  127. * prevent an unneccessary call to clear the background.
  128. */
  129. public void update(Graphics g) {
  130. paint(g);
  131. }
  132. /**
  133. * Sets the menubar for this applet.
  134. * @param menubar the menubar being placed in the applet
  135. *
  136. * @see #getJMenuBar
  137. *
  138. * @beaninfo
  139. * hidden: true
  140. * description: The menubar for accessing pulldown menus from this applet.
  141. */
  142. public void setJMenuBar(JMenuBar menuBar) {
  143. getRootPane().setMenuBar(menuBar);
  144. }
  145. /**
  146. * Returns the menubar set on this applet.
  147. *
  148. * @see #setJMenuBar
  149. */
  150. public JMenuBar getJMenuBar() {
  151. return getRootPane().getMenuBar();
  152. }
  153. /**
  154. * @return true if add and setLayout should be checked
  155. * @see #addImpl
  156. * @see #setLayout
  157. * @see #setRootPaneCheckingEnabled
  158. */
  159. protected boolean isRootPaneCheckingEnabled() {
  160. return rootPaneCheckingEnabled;
  161. }
  162. /**
  163. * If true then calls to add() and setLayout() will cause an exception
  164. * to be thrown.
  165. *
  166. * @see #addImpl
  167. * @see #setLayout
  168. * @see #isRootPaneCheckingEnabled
  169. */
  170. protected void setRootPaneCheckingEnabled(boolean enabled) {
  171. rootPaneCheckingEnabled = enabled;
  172. }
  173. /**
  174. * Create an runtime exception with a message like:
  175. * <pre>
  176. * "Do not use JApplet.add() use JApplet.getContentPane().add() instead"
  177. * </pre>
  178. */
  179. private Error createRootPaneException(String op) {
  180. String type = getClass().getName();
  181. return new Error(
  182. "Do not use " + type + "." + op + "() use "
  183. + type + ".getContentPane()." + op + "() instead");
  184. }
  185. /**
  186. * By default, children may not be added directly to a this component,
  187. * they must be added to its contentPane instead. For example:
  188. * <pre>
  189. * thiComponent.getContentPane().add(child)
  190. * </pre>
  191. * An attempt to add to directly to this component will cause an
  192. * runtime exception to be thrown. Subclasses can disable this
  193. * behavior.
  194. *
  195. * @see #setRootPaneCheckingEnabled
  196. * @exception Error if called with rootPaneChecking true
  197. */
  198. protected void addImpl(Component comp, Object constraints, int index)
  199. {
  200. if(isRootPaneCheckingEnabled()) {
  201. throw createRootPaneException("add");
  202. }
  203. else {
  204. super.addImpl(comp, constraints, index);
  205. }
  206. }
  207. /**
  208. * Removes the specified component from this container.
  209. * @param comp the component to be removed
  210. * @see #add
  211. */
  212. public void remove(Component comp) {
  213. if (comp == rootPane) {
  214. super.remove(comp);
  215. } else {
  216. // Client mistake, but we need to handle it to avoid a
  217. // common object leak in client applications.
  218. getContentPane().remove(comp);
  219. }
  220. }
  221. /**
  222. * By default the layout of this component may not be set,
  223. * the layout of its contentPane should be set instead.
  224. * For example:
  225. * <pre>
  226. * thiComponent.getContentPane().setLayout(new BorderLayout())
  227. * </pre>
  228. * An attempt to set the layout of this component will cause an
  229. * runtime exception to be thrown. Subclasses can disable this
  230. * behavior.
  231. *
  232. * @see #setRootPaneCheckingEnabled
  233. * @exception Error if called with rootPaneChecking true
  234. */
  235. public void setLayout(LayoutManager manager) {
  236. if(isRootPaneCheckingEnabled()) {
  237. throw createRootPaneException("setLayout");
  238. }
  239. else {
  240. super.setLayout(manager);
  241. }
  242. }
  243. /**
  244. * Returns the rootPane object for this applet.
  245. *
  246. * @see #setRootPane
  247. * @see RootPaneContainer#getRootPane
  248. */
  249. public JRootPane getRootPane() {
  250. return rootPane;
  251. }
  252. /**
  253. * Sets the rootPane property. This method is called by the constructor.
  254. * @param root the rootPane object for this applet
  255. *
  256. * @see #getRootPane
  257. *
  258. * @beaninfo
  259. * hidden: true
  260. * description: the RootPane object for this applet.
  261. */
  262. protected void setRootPane(JRootPane root) {
  263. if(rootPane != null) {
  264. remove(rootPane);
  265. }
  266. rootPane = root;
  267. if(rootPane != null) {
  268. boolean checkingEnabled = isRootPaneCheckingEnabled();
  269. try {
  270. setRootPaneCheckingEnabled(false);
  271. add(rootPane, BorderLayout.CENTER);
  272. }
  273. finally {
  274. setRootPaneCheckingEnabled(checkingEnabled);
  275. }
  276. }
  277. }
  278. /**
  279. * Returns the contentPane object for this applet.
  280. *
  281. * @see #setContentPane
  282. * @see RootPaneContainer#getContentPane
  283. */
  284. public Container getContentPane() {
  285. return getRootPane().getContentPane();
  286. }
  287. /**
  288. * Sets the contentPane property. This method is called by the constructor.
  289. * @param contentPane the contentPane object for this applet
  290. *
  291. * @exception java.awt.IllegalComponentStateException (a runtime
  292. * exception) if the content pane parameter is null
  293. * @see #getContentPane
  294. * @see RootPaneContainer#setContentPane
  295. *
  296. * @beaninfo
  297. * hidden: true
  298. * description: The client area of the applet where child
  299. * components are normally inserted.
  300. */
  301. public void setContentPane(Container contentPane) {
  302. getRootPane().setContentPane(contentPane);
  303. }
  304. /**
  305. * Returns the layeredPane object for this applet.
  306. *
  307. * @exception java.awt.IllegalComponentStateException (a runtime
  308. * exception) if the layered pane parameter is null
  309. * @see #setLayeredPane
  310. * @see RootPaneContainer#getLayeredPane
  311. */
  312. public JLayeredPane getLayeredPane() {
  313. return getRootPane().getLayeredPane();
  314. }
  315. /**
  316. * Sets the layeredPane property. This method is called by the constructor.
  317. * @param layeredPane the layeredPane object for this applet
  318. *
  319. * @see #getLayeredPane
  320. * @see RootPaneContainer#setLayeredPane
  321. *
  322. * @beaninfo
  323. * hidden: true
  324. * description: The pane which holds the various applet layers.
  325. */
  326. public void setLayeredPane(JLayeredPane layeredPane) {
  327. getRootPane().setLayeredPane(layeredPane);
  328. }
  329. /**
  330. * Returns the glassPane object for this applet.
  331. *
  332. * @see #setGlassPane
  333. * @see RootPaneContainer#getGlassPane
  334. */
  335. public Component getGlassPane() {
  336. return getRootPane().getGlassPane();
  337. }
  338. /**
  339. * Sets the glassPane property.
  340. * This method is called by the constructor.
  341. * @param glassPane the glassPane object for this applet
  342. *
  343. * @see #getGlassPane
  344. * @see RootPaneContainer#setGlassPane
  345. *
  346. * @beaninfo
  347. * hidden: true
  348. * description: A transparent pane used for menu rendering.
  349. */
  350. public void setGlassPane(Component glassPane) {
  351. getRootPane().setGlassPane(glassPane);
  352. }
  353. /**
  354. * Returns a string representation of this JApplet. This method
  355. * is intended to be used only for debugging purposes, and the
  356. * content and format of the returned string may vary between
  357. * implementations. The returned string may be empty but may not
  358. * be <code>null</code>.
  359. *
  360. * @return a string representation of this JApplet.
  361. */
  362. protected String paramString() {
  363. String rootPaneString = (rootPane != null ?
  364. rootPane.toString() : "");
  365. String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ?
  366. "true" : "false");
  367. return super.paramString() +
  368. ",rootPane=" + rootPaneString +
  369. ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString;
  370. }
  371. /////////////////
  372. // Accessibility support
  373. ////////////////
  374. protected AccessibleContext accessibleContext = null;
  375. /**
  376. * Get the AccessibleContext associated with this JApplet
  377. *
  378. * @return the AccessibleContext of this JApplet
  379. */
  380. public AccessibleContext getAccessibleContext() {
  381. if (accessibleContext == null) {
  382. accessibleContext = new AccessibleJApplet();
  383. }
  384. return accessibleContext;
  385. }
  386. protected class AccessibleJApplet extends AccessibleContext
  387. implements Serializable, AccessibleComponent {
  388. // AccessibleContext methods
  389. //
  390. /**
  391. * Get the role of this object.
  392. *
  393. * @return an instance of AccessibleRole describing the role of the
  394. * object
  395. * @see AccessibleRole
  396. */
  397. public AccessibleRole getAccessibleRole() {
  398. return AccessibleRole.FRAME;
  399. }
  400. /**
  401. * Get the state of this object.
  402. *
  403. * @return an instance of AccessibleStateSet containing the current
  404. * state set of the object
  405. * @see AccessibleState
  406. */
  407. public AccessibleStateSet getAccessibleStateSet() {
  408. AccessibleStateSet states = SwingUtilities.getAccessibleStateSet(JApplet.this);
  409. states.add(AccessibleState.ACTIVE);
  410. return states;
  411. }
  412. /**
  413. * Get the Accessible parent of this object. If the parent of this
  414. * object implements Accessible, this method should simply return
  415. * getParent().
  416. *
  417. * @return the Accessible parent of this object -- can be null if this
  418. * object does not have an Accessible parent
  419. */
  420. public Accessible getAccessibleParent() {
  421. if (accessibleParent != null) {
  422. return accessibleParent;
  423. } else {
  424. Container parent = getParent();
  425. if (parent instanceof Accessible) {
  426. return (Accessible) parent;
  427. }
  428. }
  429. return null;
  430. }
  431. /**
  432. * Get the index of this object in its accessible parent.
  433. *
  434. * @return the index of this object in its parent; -1 if this
  435. * object does not have an accessible parent.
  436. * @see #getAccessibleParent
  437. */
  438. public int getAccessibleIndexInParent() {
  439. return SwingUtilities.getAccessibleIndexInParent(JApplet.this);
  440. }
  441. /**
  442. * Returns the number of accessible children in the object. If all
  443. * of the children of this object implement Accessible, than this
  444. * method should return the number of children of this object.
  445. *
  446. * @return the number of accessible children in the object.
  447. */
  448. public int getAccessibleChildrenCount() {
  449. return SwingUtilities.getAccessibleChildrenCount(JApplet.this);
  450. }
  451. /**
  452. * Return the nth Accessible child of the object.
  453. *
  454. * @param i zero-based index of child
  455. * @return the nth Accessible child of the object
  456. */
  457. public Accessible getAccessibleChild(int i) {
  458. return SwingUtilities.getAccessibleChild(JApplet.this,i);
  459. }
  460. /**
  461. * Return the locale of this object.
  462. *
  463. * @return the locale of this object
  464. */
  465. public Locale getLocale() {
  466. return JApplet.this.getLocale();
  467. }
  468. /**
  469. * Get the AccessibleComponent associated with this object if one
  470. * exists. Otherwise return null.
  471. */
  472. public AccessibleComponent getAccessibleComponent() {
  473. return this;
  474. }
  475. // AccessibleComponent methods
  476. //
  477. /**
  478. * Get the background color of this object.
  479. *
  480. * @return the background color, if supported, of the object;
  481. * otherwise, null
  482. */
  483. public Color getBackground() {
  484. return JApplet.this.getBackground();
  485. }
  486. /**
  487. * Set the background color of this object.
  488. *
  489. * @param c the new Color for the background
  490. */
  491. public void setBackground(Color c) {
  492. JApplet.this.setBackground(c);
  493. }
  494. /**
  495. * Get the foreground color of this object.
  496. *
  497. * @return the foreground color, if supported, of the object;
  498. * otherwise, null
  499. */
  500. public Color getForeground() {
  501. return JApplet.this.getForeground();
  502. }
  503. /**
  504. * Set the foreground color of this object.
  505. *
  506. * @param c the new Color for the foreground
  507. */
  508. public void setForeground(Color c) {
  509. JApplet.this.setForeground(c);
  510. }
  511. /**
  512. * Get the Cursor of this object.
  513. *
  514. * @return the Cursor, if supported, of the object; otherwise, null
  515. */
  516. public Cursor getCursor() {
  517. return JApplet.this.getCursor();
  518. }
  519. /**
  520. * Set the Cursor of this object.
  521. *
  522. * @param c the new Cursor for the object
  523. */
  524. public void setCursor(Cursor cursor) {
  525. JApplet.this.setCursor(cursor);
  526. }
  527. /**
  528. * Get the Font of this object.
  529. *
  530. * @return the Font,if supported, for the object; otherwise, null
  531. */
  532. public Font getFont() {
  533. return JApplet.this.getFont();
  534. }
  535. /**
  536. * Set the Font of this object.
  537. *
  538. * @param f the new Font for the object
  539. */
  540. public void setFont(Font f) {
  541. JApplet.this.setFont(f);
  542. }
  543. /**
  544. * Get the FontMetrics of this object.
  545. *
  546. * @param f the Font
  547. * @return the FontMetrics, if supported, the object; otherwise, null
  548. * @see #getFont
  549. */
  550. public FontMetrics getFontMetrics(Font f) {
  551. return JApplet.this.getFontMetrics(f);
  552. }
  553. /**
  554. * Determine if the object is enabled.
  555. *
  556. * @return true if object is enabled; otherwise, false
  557. */
  558. public boolean isEnabled() {
  559. return JApplet.this.isEnabled();
  560. }
  561. /**
  562. * Set the enabled state of the object.
  563. *
  564. * @param b if true, enables this object; otherwise, disables it
  565. */
  566. public void setEnabled(boolean b) {
  567. JApplet.this.setEnabled(b);
  568. }
  569. /**
  570. * Determine if the object is visible. Note: this means that the
  571. * object intends to be visible; however, it may not in fact be
  572. * showing on the screen because one of the objects that this object
  573. * is contained by is not visible. To determine if an object is
  574. * showing on the screen, use isShowing().
  575. *
  576. * @return true if object is visible; otherwise, false
  577. */
  578. public boolean isVisible() {
  579. return JApplet.this.isVisible();
  580. }
  581. /**
  582. * Set the visible state of the object.
  583. *
  584. * @param b if true, shows this object; otherwise, hides it
  585. */
  586. public void setVisible(boolean b) {
  587. JApplet.this.setVisible(b);
  588. }
  589. /**
  590. * Determine if the object is showing. This is determined by checking
  591. * the visibility of the object and ancestors of the object. Note:
  592. * this will return true even if the object is obscured by another
  593. * (for example, it happens to be underneath a menu that was pulled
  594. * down).
  595. *
  596. * @return true if object is showing; otherwise, false
  597. */
  598. public boolean isShowing() {
  599. return JApplet.this.isShowing();
  600. }
  601. /**
  602. * Checks whether the specified point is within this object's bounds,
  603. * where the point's x and y coordinates are defined to be relative to
  604. * the coordinate system of the object.
  605. *
  606. * @param p the Point relative to the coordinate system of the object
  607. * @return true if object contains Point; otherwise false
  608. */
  609. public boolean contains(Point p) {
  610. return JApplet.this.contains(p);
  611. }
  612. /**
  613. * Returns the location of the object on the screen.
  614. *
  615. * @return location of object on screen -- can be null if this object
  616. * is not on the screen
  617. */
  618. public Point getLocationOnScreen() {
  619. return JApplet.this.getLocationOnScreen();
  620. }
  621. /**
  622. * Gets the location of the object relative to the parent in the form
  623. * of a point specifying the object's top-left corner in the screen's
  624. * coordinate space.
  625. *
  626. * @return An instance of Point representing the top-left corner of
  627. * the objects's bounds in the coordinate space of the screen; null if
  628. * this object or its parent are not on the screen
  629. */
  630. public Point getLocation() {
  631. return JApplet.this.getLocation();
  632. }
  633. /**
  634. * Sets the location of the object relative to the parent.
  635. */
  636. public void setLocation(Point p) {
  637. JApplet.this.setLocation(p);
  638. }
  639. /**
  640. * Gets the bounds of this object in the form of a Rectangle object.
  641. * The bounds specify this object's width, height, and location
  642. * relative to its parent.
  643. *
  644. * @return A rectangle indicating this component's bounds; null if
  645. * this object is not on the screen.
  646. */
  647. public Rectangle getBounds() {
  648. return JApplet.this.getBounds();
  649. }
  650. /**
  651. * Sets the bounds of this object in the form of a Rectangle object.
  652. * The bounds specify this object's width, height, and location
  653. * relative to its parent.
  654. *
  655. * @param A rectangle indicating this component's bounds
  656. */
  657. public void setBounds(Rectangle r) {
  658. JApplet.this.setBounds(r);
  659. }
  660. /**
  661. * Returns the size of this object in the form of a Dimension object.
  662. * The height field of the Dimension object contains this objects's
  663. * height, and the width field of the Dimension object contains this
  664. * object's width.
  665. *
  666. * @return A Dimension object that indicates the size of this
  667. * component; null if this object is not on the screen
  668. */
  669. public Dimension getSize() {
  670. return JApplet.this.getSize();
  671. }
  672. /**
  673. * Resizes this object so that it has width width and height.
  674. *
  675. * @param d - The dimension specifying the new size of the object.
  676. */
  677. public void setSize(Dimension d) {
  678. JApplet.this.setSize(d);
  679. }
  680. /**
  681. * Returns the Accessible child, if one exists, contained at the local
  682. * coordinate Point.
  683. *
  684. * @param p The point defining the top-left corner of the Accessible,
  685. * given in the coordinate space of the object's parent.
  686. * @return the Accessible, if it exists, at the specified location;
  687. * else null
  688. */
  689. public Accessible getAccessibleAt(Point p) {
  690. return SwingUtilities.getAccessibleAt(JApplet.this,p);
  691. }
  692. /**
  693. * Returns whether this object can accept focus or not.
  694. *
  695. * @return true if object can accept focus; otherwise false
  696. */
  697. public boolean isFocusTraversable() {
  698. return JApplet.this.isFocusTraversable();
  699. }
  700. /**
  701. * Requests focus for this object.
  702. */
  703. public void requestFocus() {
  704. JApplet.this.requestFocus();
  705. }
  706. /**
  707. * Adds the specified focus listener to receive focus events from this
  708. * component.
  709. *
  710. * @param l the focus listener
  711. */
  712. public void addFocusListener(FocusListener l) {
  713. JApplet.this.addFocusListener(l);
  714. }
  715. /**
  716. * Removes the specified focus listener so it no longer receives focus
  717. * events from this component.
  718. *
  719. * @param l the focus listener
  720. */
  721. public void removeFocusListener(FocusListener l) {
  722. JApplet.this.removeFocusListener(l);
  723. }
  724. } // inner class AccessibleJApplet
  725. }