/*
 * @(#)Popup.java	1.17 03/12/19
 *
 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package javax.swing;
import java.awt.*;
import sun.awt.ModalExclude;
/**
 * Popups are used to display a Component to the user, typically
 * on top of all the other Components in a particular containment
 * hierarchy. Popups have a very small life cycle. Once you
 * have obtained a Popup, and hidden it (invoked the
 * hide method), you should no longer
 * invoke any methods on it. This allows the PopupFactory to cache
 * Popups for later use.
 * 
 * The general contract is that if you need to change the size of the
 * Component, or location of the Popup, you should
 * obtain a new Popup.
 * 
 * Popup does not descend from Component, rather
 * implementations of Popup are responsible for creating
 * and maintaining their own Components to render the
 * requested Component to the user.
 * 
 * You typically do not explicitly create an instance of Popup,
 * instead obtain one from a PopupFactory.
 *
 * @see PopupFactory
 *
 * @version 1.17 12/19/03
 * @since 1.4
 */
public class Popup {
    /**
     * The Component representing the Popup.
     */
    private Component component;
    /**
     * Creates a Popup for the Component owner
     * containing the Component contents. owner
     * is used to determine which Window the new
     * Popup will parent the Component the
     * Popup creates to.
     * A null owner implies there is no valid parent.
     * x and
     * y specify the preferred initial location to place
     * the Popup at. Based on screen size, or other paramaters,
     * the Popup may not display at x and
     * y.
     *
     * @param owner    Component mouse coordinates are relative to, may be null
     * @param contents Contents of the Popup
     * @param x        Initial x screen coordinate
     * @param y        Initial y screen coordinate
     * @exception IllegalArgumentException if contents is null
     */
    protected Popup(Component owner, Component contents, int x, int y) {
        this();
        if (contents == null) {
            throw new IllegalArgumentException("Contents must be non-null");
        }
        reset(owner, contents, x, y);
    }
    /**
     * Creates a Popup. This is provided for subclasses.
     */
    protected Popup() {
    }
    /**
     * Makes the Popup visible. If the Popup is
     * currently visible, this has no effect.
     */
    public void show() {
        Component component = getComponent();
        if (component != null) {
            component.show();
        }
    }
    /**
     * Hides and disposes of the Popup. Once a Popup
     * has been disposed you should no longer invoke methods on it. A
     * disposed Popup may be reclaimed and later used
     * based on the PopupFactory. As such, if you invoke methods
     * on a disposed Popup, indeterminate
     * behavior will result.
     */
    public void hide() {
        Component component = getComponent();
        if (component instanceof JWindow) {
            component.hide();
            ((JWindow)component).getContentPane().removeAll();
        }
        dispose();
    }
    /**
     * Frees any resources the Popup may be holding onto.
     */
    void dispose() {
        Component component = getComponent();
        if (component instanceof JWindow) {
            ((Window)component).dispose();
            component = null;
        }
    }
    /**
     * Resets the Popup to an initial state.
     */
    void reset(Component owner, Component contents, int ownerX, int ownerY) {
        if (getComponent() == null) {
            component = createComponent(owner);
        }
        Component c = getComponent();
        if (c instanceof JWindow) {
            JWindow component = (JWindow)getComponent();
            component.setLocation(ownerX, ownerY);
            component.getContentPane().add(contents, BorderLayout.CENTER);
            contents.invalidate();
            if(component.isVisible()) {
                // Do not call pack() if window is not visible to
                // avoid early native peer creation
                pack();
            }
        }
    }
    /**
     * Causes the Popup to be sized to fit the preferred size
     * of the Component it contains.
     */
    void pack() {
        Component component = getComponent();
        if (component instanceof Window) {
            ((Window)component).pack();
        }
    }
    /**
     * Returns the Window to use as the parent of the
     * Window created for the Popup. This creates
     * a new Frame each time it is invoked. Subclasses that wish
     * to support a different Window parent should override
     * this.
     */
    private Window getParentWindow(Component owner) {
        Window window = null;
        if (owner instanceof Window) {
            window = (Window)owner;
        }
        else if (owner != null) {
            window = SwingUtilities.getWindowAncestor(owner);
        }
        if (window == null) {
            window = new DefaultFrame();
        }
        return window;
    }
    /**
     * Creates the Component to use as the parent of the Popup.
     * The default implementation creates a Window, subclasses
     * should override.
     */
    Component createComponent(Component owner) {
        if (GraphicsEnvironment.isHeadless()) {
            // Generally not useful, bail.
            return null;
        }
        return new HeavyWeightWindow(getParentWindow(owner));
    }
    /**
     * Returns the Component returned from
     * createComponent that will hold the Popup.
     */
    Component getComponent() {
        return component;
    }
    /**
     * Component used to house window.
     */
    static class HeavyWeightWindow extends JWindow implements ModalExclude {
        HeavyWeightWindow(Window parent) {
            super(parent);
            setFocusableWindowState(false);
            setName("###overrideRedirect###");
        }
        public void update(Graphics g) {
            paint(g);
        }
	public void show() {
	    this.pack();
	    super.show();
	}
    }
    /**
     * Used if no valid Window ancestor of the supplied owner is found.
     * 
* PopupFactory uses this as a way to know when the Popup shouldn't * be cached based on the Window. */ static class DefaultFrame extends Frame { } }