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