001 /*
002 * $Id: WindowUtils.java,v 1.11 2006/04/20 00:20:41 gfx Exp $
003 *
004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020 */
021
022 package org.jdesktop.swingx.util;
023
024 import java.awt.Component;
025 import java.awt.Container;
026 import java.awt.Font;
027 import java.awt.GraphicsDevice;
028 import java.awt.GraphicsEnvironment;
029 import java.awt.GridBagConstraints;
030 import java.awt.Insets;
031 import java.awt.MouseInfo;
032 import java.awt.Point;
033 import java.awt.Rectangle;
034 import java.awt.Window;
035 import java.awt.event.ComponentAdapter;
036 import java.awt.event.ComponentListener;
037 import java.util.ArrayList;
038 import java.util.List;
039 import java.util.logging.Level;
040 import java.util.logging.Logger;
041 import javax.swing.JComponent;
042 import javax.swing.JDialog;
043 import javax.swing.JFrame;
044 import javax.swing.JInternalFrame;
045 import javax.swing.JOptionPane;
046 import javax.swing.RootPaneContainer;
047 import javax.swing.SwingUtilities;
048
049 /**
050 * Encapsulates various utilities for windows (ie: <code>Frame</code> and
051 * <code>Dialog</code> objects and descendants, in particular).
052 *
053 * @author Richard Bair
054 */
055 public final class WindowUtils {
056 private static final Logger LOG = Logger.getLogger(WindowUtils.class
057 .getName());
058
059 /**
060 * Hide the constructor - don't wan't anybody creating an instance of this
061 */
062 private WindowUtils() {
063 }
064
065 /**
066 * <p/>
067 * Returns the <code>Point</code> at which a window should be placed to
068 * center that window on the screen.
069 * </p>
070 * <p/>
071 * Some thought was taken as to whether to implement a method such as this,
072 * or to simply make a method that, given a window, will center it. It was
073 * decided that it is better to not alter an object within a method.
074 * </p>
075 *
076 * @param window The window to calculate the center point for. This object
077 * can not be null.
078 *
079 * @return the <code>Point</code> at which the window should be placed to
080 * center that window on the screen.
081 */
082 public static Point getPointForCentering(Window window) {
083 //assert window != null;
084 try {
085 Point mousePoint = MouseInfo.getPointerInfo().getLocation();
086 GraphicsDevice[] devices = GraphicsEnvironment
087 .getLocalGraphicsEnvironment().getScreenDevices();
088 for (GraphicsDevice device : devices) {
089 Rectangle bounds = device.getDefaultConfiguration().getBounds();
090 //check to see if the mouse cursor is within these bounds
091 if (mousePoint.x >= bounds.x && mousePoint.y >= bounds.y
092 && mousePoint.x <= (bounds.x + bounds.width)
093 && mousePoint.y <= (bounds.y + bounds.height)) {
094 //this is it
095 int screenWidth = bounds.width;
096 int screenHeight = bounds.height;
097 int width = window.getWidth();
098 int height = window.getHeight();
099 Point p = new Point(((screenWidth - width) / 2) + bounds.x,
100 ((screenHeight - height) / 2) + bounds
101 .y);
102 return p;
103 }
104 }
105 } catch (Exception e) {
106 LOG.log(Level.FINE, e.getLocalizedMessage() +
107 " - this can occur do to a Security exception in sandboxed apps");
108 }
109 return new Point(0, 0);
110 }
111
112 /**
113 * <p/>
114 * Returns the <code>Point</code> at which a window should be placed to
115 * center that window on the given desktop.
116 * </p>
117 * <p/>
118 * Some thought was taken as to whether to implement a method such as this,
119 * or to simply make a method that, given a window, will center it. It was
120 * decided that it is better to not alter an object within a method.
121 * </p>
122 *
123 * @param window The window (JInternalFrame) to calculate the center point
124 * for. This object can not be null.
125 *
126 * @return the <code>Point</code> at which the window should be placed to
127 * center that window on the given desktop
128 */
129 public static Point getPointForCentering(JInternalFrame window) {
130 try {
131 //assert window != null;
132 Point mousePoint = MouseInfo.getPointerInfo().getLocation();
133 GraphicsDevice[] devices = GraphicsEnvironment
134 .getLocalGraphicsEnvironment().getScreenDevices();
135 for (GraphicsDevice device : devices) {
136 Rectangle bounds = device.getDefaultConfiguration().getBounds();
137 //check to see if the mouse cursor is within these bounds
138 if (mousePoint.x >= bounds.x && mousePoint.y >= bounds.y
139 && mousePoint.x <= (bounds.x + bounds.width)
140 && mousePoint.y <= (bounds.y + bounds.height)) {
141 //this is it
142 int screenWidth = bounds.width;
143 int screenHeight = bounds.height;
144 int width = window.getWidth();
145 int height = window.getHeight();
146 Point p = new Point(((screenWidth - width) / 2) + bounds.x,
147 ((screenHeight - height) / 2) + bounds
148 .y);
149 return p;
150 }
151 }
152 } catch (Exception e) {
153 LOG.log(Level.FINE, e.getLocalizedMessage() +
154 " - this can occur do to a Security exception in sandboxed apps");
155 }
156 return new Point(0, 0);
157 }
158
159 /**
160 * <p/>
161 * Returns the <code>Point</code> at which a window should be placed in
162 * order to be staggered slightly from another "origin" window to
163 * ensure that the title areas of both windows remain visible to the user.
164 * </p>
165 *
166 * @param originWindow Window from which the staggered location will be calculated
167 *
168 * @return location staggered from the upper left location of the origin
169 * window
170 */
171 public static Point getPointForStaggering(Window originWindow) {
172 Point origin = originWindow.getLocation();
173 Insets insets = originWindow.getInsets();
174 origin.x += insets.top;
175 origin.y += insets.top;
176 return origin;
177 }
178
179 /**
180 * Utility method used to load a GridBagConstraints object (param gbc) with the
181 * data in the other parameters. This method saves code space over doing the
182 * assignments by hand, and also allows you to reuse the same GridBagConstraints
183 * object reducing temporary object creating (at the expense of a method call.
184 * Go figure).
185 */
186 public static void setConstraints(GridBagConstraints gbc, int gridx,
187 int gridy, int gridwidth, int gridheight,
188 double weightx, double weighty,
189 int anchor, int fill, int top, int left,
190 int bottom, int right) {
191 gbc.gridx = gridx;
192 gbc.gridy = gridy;
193 gbc.gridwidth = gridwidth;
194 gbc.gridheight = gridheight;
195 gbc.weightx = weightx;
196 gbc.weighty = weighty;
197 gbc.anchor = anchor;
198 gbc.fill = fill;
199 gbc.insets = new Insets(top, left, bottom, right);
200 }
201
202 /**
203 * Get a <code>Rectangle</code> object representing the given window's position and
204 * magnitude in space.
205 *
206 * @param win The window to get a Rectangle object for
207 *
208 * @return a Rectangle object. @see com.jgui.Rectangle
209 */
210 public static Rectangle getRectangle(Window win) {
211 Rectangle Rectangle = new Rectangle(win.getY(), win.getX(),
212 win.getWidth(), win.getHeight());
213 return Rectangle;
214 }
215
216 /**
217 * Get a <code>Rectangle</code> object representing the given JComponent's position and
218 * magnitude in space.
219 *
220 * @param comp The JComponent to get a Rectangle object for
221 *
222 * @return a Rectangle object. @see com.jgui.Rectangle
223 */
224 public static Rectangle getRectangle(JComponent comp) {
225 Rectangle Rectangle = new Rectangle(comp.getY(), comp.getX(),
226 comp.getWidth(), comp.getHeight());
227 return Rectangle;
228 }
229
230 /**
231 * Locates the RootPaneContainer for the given component
232 *
233 * @param c
234 *
235 * @return the RootPaneContainer to which the component belongs to
236 */
237 public static RootPaneContainer findRootPaneContainer(Component c) {
238 if (c == null) {
239 return null;
240 } else if (c instanceof RootPaneContainer) {
241 return (RootPaneContainer) c;
242 } else {
243 return findRootPaneContainer(c.getParent());
244 }
245 }
246
247 /**
248 * Locates the JFrame for the given component
249 *
250 * @param c
251 *
252 * @return the JFrame to which the component belongs to
253 */
254 public static JFrame findJFrame(Component c) {
255 if (c == null) {
256 return null;
257 } else if (c instanceof RootPaneContainer) {
258 return (JFrame) c;
259 } else {
260 return findJFrame(c.getParent());
261 }
262 }
263
264 /**
265 * Locates the JDialog for the given component
266 *
267 * @param c
268 *
269 * @return the JDialog to which the component belongs to
270 */
271 public static JDialog findJDialog(Component c) {
272 if (c == null) {
273 return null;
274 } else if (c instanceof JDialog) {
275 return (JDialog) c;
276 } else {
277 return findJDialog(c.getParent());
278 }
279 }
280
281 public static Window findWindow(Component c) {
282 if (c == null) {
283 return JOptionPane.getRootFrame();
284 } else if (c instanceof Window) {
285 return (Window) c;
286 } else {
287 return findWindow(c.getParent());
288 }
289 }
290
291 public static List<Component> getAllComponents(final Container c) {
292 Component[] comps = c.getComponents();
293 List<Component> compList = new ArrayList<Component>();
294 for (Component comp : comps) {
295 compList.add(comp);
296 if (comp instanceof Container) {
297 compList.addAll(getAllComponents((Container) comp));
298 }
299 }
300 return compList;
301 }
302
303 public static void setFontRecursively(Container c, Font font) {
304 for (Component comp : getAllComponents(c)) {
305 comp.setFont(font);
306 }
307 }
308
309 /**
310 * Installs/resets a ComponentListener to resize the
311 * given window to minWidth/Height if needed.
312 *
313 * @param window
314 * @param minWidth
315 * @param minHeight
316 */
317 public static void setMinimumSizeManager(Window window, int minWidth,
318 int minHeight) {
319 ComponentListener[] listeners = window.getComponentListeners();
320 ComponentListener listener = null;
321 for (ComponentListener l : listeners) {
322 if (l instanceof MinSizeComponentListener) {
323 listener = l;
324 break;
325 }
326 }
327 if (listener == null) {
328 window.addComponentListener(new MinSizeComponentListener(
329 window, minWidth, minHeight));
330 } else {
331 ((MinSizeComponentListener) listener).resetSizes(minWidth,
332 minHeight);
333 }
334 }
335
336 /**
337 * Resets window size to minSize if needed.
338 *
339 * @author Patrick Wright
340 */
341 public static class MinSizeComponentListener extends ComponentAdapter {
342 private Window window;
343 private int minHeight;
344 private int minWidth;
345
346 MinSizeComponentListener(Window frame, int minWidth, int minHeight) {
347 this.window = frame;
348 resetSizes(minWidth, minHeight);
349 }
350
351 public void resetSizes(int minWidth, int minHeight) {
352 this.minWidth = minWidth;
353 this.minHeight = minHeight;
354 adjustIfNeeded(window);
355 }
356
357 @Override
358 public void componentResized(java.awt.event.ComponentEvent evt) {
359 adjustIfNeeded((Window) evt.getComponent());
360 }
361
362 private void adjustIfNeeded(final Window window) {
363 boolean doSize = false;
364 int newWidth = window.getWidth();
365 int newHeight = window.getHeight();
366 if (newWidth < minWidth) {
367 newWidth = minWidth;
368 doSize = true;
369 }
370 if (newHeight < minHeight) {
371 newHeight = minHeight;
372 doSize = true;
373 }
374 if (doSize) {
375 final int w = newWidth;
376 final int h = newHeight;
377 SwingUtilities.invokeLater(new Runnable() {
378 public void run() {
379 window.setSize(w, h);
380 }
381 });
382 }
383 }
384 }
385 }