001    /* Popup.java --
002       Copyright (C) 2003 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing;
040    
041    import java.awt.Component;
042    import java.awt.FlowLayout;
043    import java.awt.Point;
044    import 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     */
058    public 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    }