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 */
25package javax.swing;
26
27import java.awt.*;
28import java.awt.event.*;
29import java.beans.JavaBean;
30import java.beans.BeanProperty;
31
32import javax.accessibility.*;
33
34/**
35 * A <code>JWindow</code> is a container that can be displayed anywhere on the
36 * user's desktop. It does not have the title bar, window-management buttons,
37 * or other trimmings associated with a <code>JFrame</code>, but it is still a
38 * "first-class citizen" of the user's desktop, and can exist anywhere
39 * on it.
40 * <p>
41 * The <code>JWindow</code> component contains a <code>JRootPane</code>
42 * as its only child.  The <code>contentPane</code> should be the parent
43 * of any children of the <code>JWindow</code>.
44 * As a convenience, the {@code add}, {@code remove}, and {@code setLayout}
45 * methods of this class are overridden, so that they delegate calls
46 * to the corresponding methods of the {@code ContentPane}.
47 * For example, you can add a child component to a window as follows:
48 * <pre>
49 *       window.add(child);
50 * </pre>
51 * And the child will be added to the contentPane.
52 * The <code>contentPane</code> will always be non-<code>null</code>.
53 * Attempting to set it to <code>null</code> will cause the <code>JWindow</code>
54 * to throw an exception. The default <code>contentPane</code> will have a
55 * <code>BorderLayout</code> manager set on it.
56 * Refer to {@link javax.swing.RootPaneContainer}
57 * for details on adding, removing and setting the <code>LayoutManager</code>
58 * of a <code>JWindow</code>.
59 * <p>
60 * Please see the {@link JRootPane} documentation for a complete description of
61 * the <code>contentPane</code>, <code>glassPane</code>, and
62 * <code>layeredPane</code> components.
63 * <p>
64 * In a multi-screen environment, you can create a <code>JWindow</code>
65 * on a different screen device.  See {@link java.awt.Window} for more
66 * information.
67 * <p>
68 * <strong>Warning:</strong> Swing is not thread safe. For more
69 * information see <a
70 * href="package-summary.html#threading">Swing's Threading
71 * Policy</a>.
72 * <p>
73 * <strong>Warning:</strong>
74 * Serialized objects of this class will not be compatible with
75 * future Swing releases. The current serialization support is
76 * appropriate for short term storage or RMI between applications running
77 * the same version of Swing.  As of 1.4, support for long term storage
78 * of all JavaBeans&trade;
79 * has been added to the <code>java.beans</code> package.
80 * Please see {@link java.beans.XMLEncoder}.
81 *
82 * @see JRootPane
83 *
84 * @author David Kloba
85 * @since 1.2
86 */
87@JavaBean(defaultProperty = "accessibleContext", description = "A toplevel window which has no system border or controls.")
88@SwingContainer(delegate = "getContentPane")
89@SuppressWarnings("serial")
90public class JWindow extends Window implements Accessible,
91                                               RootPaneContainer,
92                               TransferHandler.HasGetTransferHandler
93{
94    /**
95     * The <code>JRootPane</code> instance that manages the
96     * <code>contentPane</code>
97     * and optional <code>menuBar</code> for this frame, as well as the
98     * <code>glassPane</code>.
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>JWindow</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 window.
118     */
119    private TransferHandler transferHandler;
120
121    /**
122     * Creates a window with no specified owner. This window will not be
123     * focusable.
124     * <p>
125     * This constructor sets the component's locale property to the value
126     * returned by <code>JComponent.getDefaultLocale</code>.
127     *
128     * @throws HeadlessException if
129     *         <code>GraphicsEnvironment.isHeadless()</code> returns true.
130     * @see java.awt.GraphicsEnvironment#isHeadless
131     * @see #isFocusableWindow
132     * @see JComponent#getDefaultLocale
133     */
134    public JWindow() {
135        this((Frame)null);
136    }
137
138    /**
139     * Creates a window with the specified <code>GraphicsConfiguration</code>
140     * of a screen device. This window will not be focusable.
141     * <p>
142     * This constructor sets the component's locale property to the value
143     * returned by <code>JComponent.getDefaultLocale</code>.
144     *
145     * @param gc the <code>GraphicsConfiguration</code> that is used
146     *          to construct the new window with; if gc is <code>null</code>,
147     *          the system default <code>GraphicsConfiguration</code>
148     *          is assumed
149     * @throws HeadlessException If
150     *         <code>GraphicsEnvironment.isHeadless()</code> returns true.
151     * @throws IllegalArgumentException if <code>gc</code> is not from
152     *         a screen device.
153     *
154     * @see java.awt.GraphicsEnvironment#isHeadless
155     * @see #isFocusableWindow
156     * @see JComponent#getDefaultLocale
157     *
158     * @since  1.3
159     */
160    public JWindow(GraphicsConfiguration gc) {
161        this(null, gc);
162        super.setFocusableWindowState(false);
163    }
164
165    /**
166     * Creates a window with the specified owner frame.
167     * If <code>owner</code> is <code>null</code>, the shared owner
168     * will be used and this window will not be focusable. Also,
169     * this window will not be focusable unless its owner is showing
170     * on the screen.
171     * <p>
172     * This constructor sets the component's locale property to the value
173     * returned by <code>JComponent.getDefaultLocale</code>.
174     *
175     * @param owner the frame from which the window is displayed
176     * @throws HeadlessException if GraphicsEnvironment.isHeadless()
177     *            returns true.
178     * @see java.awt.GraphicsEnvironment#isHeadless
179     * @see #isFocusableWindow
180     * @see JComponent#getDefaultLocale
181     */
182    public JWindow(Frame owner) {
183        super(owner == null? SwingUtilities.getSharedOwnerFrame() : owner);
184        if (owner == null) {
185            WindowListener ownerShutdownListener =
186                    SwingUtilities.getSharedOwnerFrameShutdownListener();
187            addWindowListener(ownerShutdownListener);
188        }
189        windowInit();
190    }
191
192    /**
193     * Creates a window with the specified owner window. This window
194     * will not be focusable unless its owner is showing on the screen.
195     * If <code>owner</code> is <code>null</code>, the shared owner
196     * will be used and this window will not be focusable.
197     * <p>
198     * This constructor sets the component's locale property to the value
199     * returned by <code>JComponent.getDefaultLocale</code>.
200     *
201     * @param owner the window from which the window is displayed
202     * @throws HeadlessException if
203     *         <code>GraphicsEnvironment.isHeadless()</code> returns true.
204     * @see java.awt.GraphicsEnvironment#isHeadless
205     * @see #isFocusableWindow
206     * @see JComponent#getDefaultLocale
207     */
208    public JWindow(Window owner) {
209        super(owner == null ? (Window)SwingUtilities.getSharedOwnerFrame() :
210              owner);
211        if (owner == null) {
212            WindowListener ownerShutdownListener =
213                    SwingUtilities.getSharedOwnerFrameShutdownListener();
214            addWindowListener(ownerShutdownListener);
215        }
216        windowInit();
217    }
218
219    /**
220     * Creates a window with the specified owner window and
221     * <code>GraphicsConfiguration</code> of a screen device. If
222     * <code>owner</code> is <code>null</code>, the shared owner will be used
223     * and this window will not be focusable.
224     * <p>
225     * This constructor sets the component's locale property to the value
226     * returned by <code>JComponent.getDefaultLocale</code>.
227     *
228     * @param owner the window from which the window is displayed
229     * @param gc the <code>GraphicsConfiguration</code> that is used
230     *          to construct the new window with; if gc is <code>null</code>,
231     *          the system default <code>GraphicsConfiguration</code>
232     *          is assumed, unless <code>owner</code> is also null, in which
233     *          case the <code>GraphicsConfiguration</code> from the
234     *          shared owner frame will be used.
235     * @throws HeadlessException if
236     *         <code>GraphicsEnvironment.isHeadless()</code> returns true.
237     * @throws IllegalArgumentException if <code>gc</code> is not from
238     *         a screen device.
239     *
240     * @see java.awt.GraphicsEnvironment#isHeadless
241     * @see #isFocusableWindow
242     * @see JComponent#getDefaultLocale
243     *
244     * @since  1.3
245     */
246    public JWindow(Window owner, GraphicsConfiguration gc) {
247        super(owner == null ? (Window)SwingUtilities.getSharedOwnerFrame() :
248              owner, gc);
249        if (owner == null) {
250            WindowListener ownerShutdownListener =
251                    SwingUtilities.getSharedOwnerFrameShutdownListener();
252            addWindowListener(ownerShutdownListener);
253        }
254        windowInit();
255    }
256
257    /**
258     * Called by the constructors to init the <code>JWindow</code> properly.
259     */
260    protected void windowInit() {
261        setLocale( JComponent.getDefaultLocale() );
262        setRootPane(createRootPane());
263        setRootPaneCheckingEnabled(true);
264        sun.awt.SunToolkit.checkAndSetPolicy(this);
265    }
266
267    /**
268     * Called by the constructor methods to create the default
269     * <code>rootPane</code>.
270     *
271     * @return a new {@code JRootPane}
272     */
273    protected JRootPane createRootPane() {
274        JRootPane rp = new JRootPane();
275        // NOTE: this uses setOpaque vs LookAndFeel.installProperty as there
276        // is NO reason for the RootPane not to be opaque. For painting to
277        // work the contentPane must be opaque, therefor the RootPane can
278        // also be opaque.
279        rp.setOpaque(true);
280        return rp;
281    }
282
283    /**
284     * Returns whether calls to <code>add</code> and
285     * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
286     *
287     * @return true if <code>add</code> and <code>setLayout</code>
288     *         are forwarded; false otherwise
289     *
290     * @see #addImpl
291     * @see #setLayout
292     * @see #setRootPaneCheckingEnabled
293     * @see javax.swing.RootPaneContainer
294     */
295    protected boolean isRootPaneCheckingEnabled() {
296        return rootPaneCheckingEnabled;
297    }
298
299    /**
300     * Sets the {@code transferHandler} property, which is a mechanism to
301     * support transfer of data into this component. Use {@code null}
302     * if the component does not support data transfer operations.
303     * <p>
304     * If the system property {@code suppressSwingDropSupport} is {@code false}
305     * (the default) and the current drop target on this component is either
306     * {@code null} or not a user-set drop target, this method will change the
307     * drop target as follows: If {@code newHandler} is {@code null} it will
308     * clear the drop target. If not {@code null} it will install a new
309     * {@code DropTarget}.
310     * <p>
311     * Note: When used with {@code JWindow}, {@code TransferHandler} only
312     * provides data import capability, as the data export related methods
313     * are currently typed to {@code JComponent}.
314     * <p>
315     * Please see
316     * <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
317     * How to Use Drag and Drop and Data Transfer</a>, a section in
318     * <em>The Java Tutorial</em>, for more information.
319     *
320     * @param newHandler the new {@code TransferHandler}
321     *
322     * @see TransferHandler
323     * @see #getTransferHandler
324     * @see java.awt.Component#setDropTarget
325     * @since 1.6
326     */
327    @BeanProperty(hidden = true, description
328            = "Mechanism for transfer of data into the component")
329    public void setTransferHandler(TransferHandler newHandler) {
330        TransferHandler oldHandler = transferHandler;
331        transferHandler = newHandler;
332        SwingUtilities.installSwingDropTargetAsNecessary(this, transferHandler);
333        firePropertyChange("transferHandler", oldHandler, newHandler);
334    }
335
336    /**
337     * Gets the <code>transferHandler</code> property.
338     *
339     * @return the value of the <code>transferHandler</code> property
340     *
341     * @see TransferHandler
342     * @see #setTransferHandler
343     * @since 1.6
344     */
345    public TransferHandler getTransferHandler() {
346        return transferHandler;
347    }
348
349    /**
350     * Calls <code>paint(g)</code>.  This method was overridden to
351     * prevent an unnecessary call to clear the background.
352     *
353     * @param g  the <code>Graphics</code> context in which to paint
354     */
355    public void update(Graphics g) {
356        paint(g);
357    }
358
359    /**
360     * Sets whether calls to <code>add</code> and
361     * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
362     *
363     * @param enabled  true if <code>add</code> and <code>setLayout</code>
364     *        are forwarded, false if they should operate directly on the
365     *        <code>JWindow</code>.
366     *
367     * @see #addImpl
368     * @see #setLayout
369     * @see #isRootPaneCheckingEnabled
370     * @see javax.swing.RootPaneContainer
371     */
372    @BeanProperty(hidden = true, description
373            = "Whether the add and setLayout methods are forwarded")
374    protected void setRootPaneCheckingEnabled(boolean enabled) {
375        rootPaneCheckingEnabled = enabled;
376    }
377
378
379    /**
380     * Adds the specified child <code>Component</code>.
381     * This method is overridden to conditionally forward calls to the
382     * <code>contentPane</code>.
383     * By default, children are added to the <code>contentPane</code> instead
384     * of the frame, refer to {@link javax.swing.RootPaneContainer} for
385     * details.
386     *
387     * @param comp the component to be enhanced
388     * @param constraints the constraints to be respected
389     * @param index the index
390     * @exception IllegalArgumentException if <code>index</code> is invalid
391     * @exception IllegalArgumentException if adding the container's parent
392     *                  to itself
393     * @exception IllegalArgumentException if adding a window to a container
394     *
395     * @see #setRootPaneCheckingEnabled
396     * @see javax.swing.RootPaneContainer
397     */
398    protected void addImpl(Component comp, Object constraints, int index)
399    {
400        if(isRootPaneCheckingEnabled()) {
401            getContentPane().add(comp, constraints, index);
402        }
403        else {
404            super.addImpl(comp, constraints, index);
405        }
406    }
407
408    /**
409     * Removes the specified component from the container. If
410     * <code>comp</code> is not the <code>rootPane</code>, this will forward
411     * the call to the <code>contentPane</code>. This will do nothing if
412     * <code>comp</code> is not a child of the <code>JWindow</code> or
413     * <code>contentPane</code>.
414     *
415     * @param comp the component to be removed
416     * @throws NullPointerException if <code>comp</code> is null
417     * @see #add
418     * @see javax.swing.RootPaneContainer
419     */
420    public void remove(Component comp) {
421        if (comp == rootPane) {
422            super.remove(comp);
423        } else {
424            getContentPane().remove(comp);
425        }
426    }
427
428
429    /**
430     * Sets the <code>LayoutManager</code>.
431     * Overridden to conditionally forward the call to the
432     * <code>contentPane</code>.
433     * Refer to {@link javax.swing.RootPaneContainer} for
434     * more information.
435     *
436     * @param manager the <code>LayoutManager</code>
437     * @see #setRootPaneCheckingEnabled
438     * @see javax.swing.RootPaneContainer
439     */
440    public void setLayout(LayoutManager manager) {
441        if(isRootPaneCheckingEnabled()) {
442            getContentPane().setLayout(manager);
443        }
444        else {
445            super.setLayout(manager);
446        }
447    }
448
449
450    /**
451     * Returns the <code>rootPane</code> object for this window.
452     * @return the <code>rootPane</code> property for this window
453     *
454     * @see #setRootPane
455     * @see RootPaneContainer#getRootPane
456     */
457    @BeanProperty(bound = false, hidden = true, description
458            = "the RootPane object for this window.")
459    public JRootPane getRootPane() {
460        return rootPane;
461    }
462
463
464    /**
465     * Sets the new <code>rootPane</code> object for this window.
466     * This method is called by the constructor.
467     *
468     * @param root the new <code>rootPane</code> property
469     * @see #getRootPane
470     */
471    protected void setRootPane(JRootPane root) {
472        if(rootPane != null) {
473            remove(rootPane);
474        }
475        rootPane = root;
476        if(rootPane != null) {
477            boolean checkingEnabled = isRootPaneCheckingEnabled();
478            try {
479                setRootPaneCheckingEnabled(false);
480                add(rootPane, BorderLayout.CENTER);
481            }
482            finally {
483                setRootPaneCheckingEnabled(checkingEnabled);
484            }
485        }
486    }
487
488
489    /**
490     * Returns the <code>Container</code> which is the <code>contentPane</code>
491     * for this window.
492     *
493     * @return the <code>contentPane</code> property
494     * @see #setContentPane
495     * @see RootPaneContainer#getContentPane
496     */
497    public Container getContentPane() {
498        return getRootPane().getContentPane();
499    }
500
501    /**
502     * Sets the <code>contentPane</code> property for this window.
503     * This method is called by the constructor.
504     *
505     * @param contentPane the new <code>contentPane</code>
506     *
507     * @exception IllegalComponentStateException (a runtime
508     *            exception) if the content pane parameter is <code>null</code>
509     * @see #getContentPane
510     * @see RootPaneContainer#setContentPane
511     */
512    @BeanProperty(bound = false, hidden = true, description
513            = "The client area of the window where child components are normally inserted.")
514    public void setContentPane(Container contentPane) {
515        getRootPane().setContentPane(contentPane);
516    }
517
518    /**
519     * Returns the <code>layeredPane</code> object for this window.
520     *
521     * @return the <code>layeredPane</code> property
522     * @see #setLayeredPane
523     * @see RootPaneContainer#getLayeredPane
524     */
525    public JLayeredPane getLayeredPane() {
526        return getRootPane().getLayeredPane();
527    }
528
529    /**
530     * Sets the <code>layeredPane</code> property.
531     * This method is called by the constructor.
532     *
533     * @param layeredPane the new <code>layeredPane</code> object
534     *
535     * @exception IllegalComponentStateException (a runtime
536     *            exception) if the content pane parameter is <code>null</code>
537     * @see #getLayeredPane
538     * @see RootPaneContainer#setLayeredPane
539     */
540    @BeanProperty(bound = false, hidden = true, description
541            = "The pane which holds the various window layers.")
542    public void setLayeredPane(JLayeredPane layeredPane) {
543        getRootPane().setLayeredPane(layeredPane);
544    }
545
546    /**
547     * Returns the <code>glassPane Component</code> for this window.
548     *
549     * @return the <code>glassPane</code> property
550     * @see #setGlassPane
551     * @see RootPaneContainer#getGlassPane
552     */
553    public Component getGlassPane() {
554        return getRootPane().getGlassPane();
555    }
556
557    /**
558     * Sets the <code>glassPane</code> property.
559     * This method is called by the constructor.
560     * @param glassPane the <code>glassPane</code> object for this window
561     *
562     * @see #getGlassPane
563     * @see RootPaneContainer#setGlassPane
564     */
565    @BeanProperty(bound = false, hidden = true, description
566            = "A transparent pane used for menu rendering.")
567    public void setGlassPane(Component glassPane) {
568        getRootPane().setGlassPane(glassPane);
569    }
570
571    /**
572     * {@inheritDoc}
573     *
574     * @since 1.6
575     */
576    @BeanProperty(bound = false)
577    public Graphics getGraphics() {
578        JComponent.getGraphicsInvoked(this);
579        return super.getGraphics();
580    }
581
582    /**
583     * Repaints the specified rectangle of this component within
584     * <code>time</code> milliseconds.  Refer to <code>RepaintManager</code>
585     * for details on how the repaint is handled.
586     *
587     * @param     time   maximum time in milliseconds before update
588     * @param     x    the <i>x</i> coordinate
589     * @param     y    the <i>y</i> coordinate
590     * @param     width    the width
591     * @param     height   the height
592     * @see       RepaintManager
593     * @since     1.6
594     */
595    public void repaint(long time, int x, int y, int width, int height) {
596        if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {
597            RepaintManager.currentManager(this).addDirtyRegion(
598                              this, x, y, width, height);
599        }
600        else {
601            super.repaint(time, x, y, width, height);
602        }
603    }
604
605    /**
606     * Returns a string representation of this <code>JWindow</code>.
607     * This method
608     * is intended to be used only for debugging purposes, and the
609     * content and format of the returned string may vary between
610     * implementations. The returned string may be empty but may not
611     * be <code>null</code>.
612     *
613     * @return  a string representation of this <code>JWindow</code>
614     */
615    protected String paramString() {
616        String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ?
617                                                "true" : "false");
618
619        return super.paramString() +
620        ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString;
621    }
622
623
624/////////////////
625// Accessibility support
626////////////////
627
628    /** The accessible context property. */
629    protected AccessibleContext accessibleContext = null;
630
631    /**
632     * Gets the AccessibleContext associated with this JWindow.
633     * For JWindows, the AccessibleContext takes the form of an
634     * AccessibleJWindow.
635     * A new AccessibleJWindow instance is created if necessary.
636     *
637     * @return an AccessibleJWindow that serves as the
638     *         AccessibleContext of this JWindow
639     */
640    public AccessibleContext getAccessibleContext() {
641        if (accessibleContext == null) {
642            accessibleContext = new AccessibleJWindow();
643        }
644        return accessibleContext;
645    }
646
647
648    /**
649     * This class implements accessibility support for the
650     * <code>JWindow</code> class.  It provides an implementation of the
651     * Java Accessibility API appropriate to window user-interface
652     * elements.
653     */
654    @SuppressWarnings("serial")
655    protected class AccessibleJWindow extends AccessibleAWTWindow {
656        // everything is in the new parent, AccessibleAWTWindow
657    }
658
659}
660