001/* Popup.java --
002   Copyright (C) 2003 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.swing;
040
041import java.awt.Component;
042import java.awt.FlowLayout;
043import java.awt.Point;
044import java.awt.Rectangle;
045
046
047/**
048 * Manages a popup window that displays a Component on top of
049 * everything else.
050 *
051 * <p>To obtain an instance of <code>Popup</code>, use the
052 * {@link javax.swing.PopupFactory}.
053 *
054 * @since 1.4
055 *
056 * @author Sascha Brawer (brawer@dandelis.ch)
057 */
058public class Popup
059{
060  /**
061   * Constructs a new <code>Popup</code> given its owner,
062   * contents and the screen position where the popup
063   * will appear.
064   *
065   * @param owner the Component to which <code>x</code> and
066   *        <code>y</code> are relative, or <code>null</code> for
067   *        placing the popup relative to the origin of the screen.
068   *
069   * @param contents the contents that will be displayed inside
070   *        the <code>Popup</code>.
071   *
072   * @param x the horizontal position where the Popup will appear.
073   *
074   * @param y the vertical position where the Popup will appear.
075   *
076   * @throws IllegalArgumentException if <code>contents</code>
077   *         is <code>null</code>.
078   */
079  protected Popup(Component owner, Component contents,
080                  int x, int y)
081  {
082    if (contents == null)
083      throw new IllegalArgumentException();
084
085    // The real stuff happens in the implementation of subclasses,
086    // for instance JWindowPopup.
087  }
088  
089  
090  /**
091   * Constructs a new <code>Popup</code>.
092   */
093  protected Popup()
094  {
095    // Nothing to do here.
096  }
097
098
099  /**
100   * Displays the <code>Popup</code> on the screen.  Nothing happens
101   * if it is currently shown.
102   */
103  public void show()
104  {
105    // Implemented by subclasses, for instance JWindowPopup.
106  }
107
108
109  /**
110   * Removes the <code>Popup</code> from the screen.  Nothing happens
111   * if it is currently hidden.
112   */
113  public void hide()
114  {
115    // Implemented by subclasses, for instance JWindowPopup.
116  }
117
118
119  /**
120   * A <code>Popup</code> that uses a <code>JWindow</code> for
121   * displaying its contents.
122   *
123   * @see PopupFactory#getPopup
124   *
125   * @author Sascha Brawer (brawer@dandelis.ch)
126   */
127  static class JWindowPopup
128    extends Popup
129  {
130    /**
131     * The <code>JWindow</code> used for displaying the contents
132     * of the popup.
133     */
134    JWindow window;
135
136    private Component contents;
137
138    /**
139     * Constructs a new <code>JWindowPopup</code> given its owner,
140     * contents and the screen position where the popup
141     * will appear.
142     *
143     * @param owner the Component to which <code>x</code> and
144     *        <code>y</code> are relative, or <code>null</code> for
145     *        placing the popup relative to the origin of the screen.
146     *
147     * @param contents the contents that will be displayed inside
148     *        the <code>Popup</code>.
149     *
150     * @param x the horizontal position where the Popup will appear.
151     *
152     * @param y the vertical position where the Popup will appear.
153     *
154     * @throws IllegalArgumentException if <code>contents</code>
155     *         is <code>null</code>.
156     */
157    public JWindowPopup(Component owner, Component contents,
158                        int x, int y)
159    {
160      /* Checks whether contents is null. */
161      super(owner, contents, x, y);
162
163      this.contents = contents;
164      window = new JWindow(SwingUtilities.getWindowAncestor(owner));
165      window.getContentPane().add(contents);
166      window.setLocation(x, y);
167      window.setFocusableWindowState(false);
168    }
169
170
171    /**
172     * Displays the popup's <code>JWindow</code> on the screen.
173     * Nothing happens if it is already visible.
174     */
175    public void show()
176    {
177      window.setSize(contents.getSize());
178      window.show();
179    }
180    
181    
182    /**
183     * Removes the popup's <code>JWindow</code> from the
184     * screen.  Nothing happens if it is currently not visible.
185     */
186    public void hide()
187    {
188      /* Calling dispose() instead of hide() will conserve native
189       * system resources, for example memory in an X11 server.
190       * They will automatically be re-allocated by a call to
191       * show().
192       */
193      window.dispose();
194    }
195  }
196
197  /**
198   * A popup that displays itself within the JLayeredPane of a JRootPane of
199   * the containment hierarchy of the owner component.
200   *
201   * @author Roman Kennke (kennke@aicas.com)
202   */
203  static class LightweightPopup extends Popup
204  {
205    /**
206     * The owner component for this popup.
207     */
208    Component owner;
209
210    /**
211     * The contents that should be shown.
212     */
213    Component contents;
214
215    /**
216     * The X location in screen coordinates.
217     */
218    int x;
219
220    /**
221     * The Y location in screen coordinates.
222     */
223    int y;
224
225    /**
226     * The panel that holds the content.
227     */
228    private JPanel panel;
229    
230    /**
231     * The layered pane of the owner.
232     */
233    private JLayeredPane layeredPane;
234    
235    /**
236     * Constructs a new <code>LightweightPopup</code> given its owner,
237     * contents and the screen position where the popup
238     * will appear.
239     *
240     * @param owner the component that should own the popup window; this
241     *        provides the JRootPane in which we place the popup window
242     *
243     * @param contents the contents that will be displayed inside
244     *        the <code>Popup</code>.
245     *
246     * @param x the horizontal position where the Popup will appear in screen
247     *        coordinates
248     *
249     * @param y the vertical position where the Popup will appear in screen
250     *        coordinates
251     *
252     * @throws IllegalArgumentException if <code>contents</code>
253     *         is <code>null</code>.
254     */
255    public LightweightPopup(Component owner, Component  contents, int x, int y)
256    {
257      super(owner, contents, x, y);
258      this.owner = owner;
259      this.contents = contents;
260      this.x = x;
261      this.y = y;
262      
263      JRootPane rootPane = SwingUtilities.getRootPane(owner);
264      JLayeredPane layeredPane = rootPane.getLayeredPane();
265      this.layeredPane = layeredPane;
266    }
267
268    /**
269     * Places the popup within the JLayeredPane of the owner component and
270     * makes it visible.
271     */
272    public void show()
273    {
274      // We insert a JPanel between the layered pane and the contents so we
275      // can fiddle with the setLocation() method without disturbing a
276      // JPopupMenu (which overrides setLocation in an unusual manner).
277      if (panel == null)
278        {
279          panel = new JPanel();
280          panel.setLayout(new FlowLayout(0, 0, 0));
281        }
282      
283      panel.add(contents);
284      panel.setSize(contents.getSize());
285      Point layeredPaneLoc = layeredPane.getLocationOnScreen();
286      panel.setLocation(x - layeredPaneLoc.x, y - layeredPaneLoc.y);
287      layeredPane.add(panel, JLayeredPane.POPUP_LAYER, 0);
288      panel.repaint();
289    }
290
291    /**
292     * Removes the popup from the JLayeredPane thus making it invisible.
293     */
294    public void hide()
295    {
296      Rectangle bounds = panel.getBounds();
297      layeredPane.remove(panel);
298      layeredPane.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
299    }
300  }
301}