001 /*
002 * $Id: WindowUtils.java 3352 2009-05-25 16:37:52Z kschaefe $
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.GraphicsConfiguration;
027 import java.awt.GraphicsDevice;
028 import java.awt.GraphicsEnvironment;
029 import java.awt.Insets;
030 import java.awt.MouseInfo;
031 import java.awt.Point;
032 import java.awt.Rectangle;
033 import java.awt.Toolkit;
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
042 import javax.swing.JInternalFrame;
043 import javax.swing.JOptionPane;
044 import javax.swing.SwingUtilities;
045
046 /**
047 * Encapsulates various utilities for windows (ie: <code>Frame</code> and
048 * <code>Dialog</code> objects and descendants, in particular).
049 *
050 * @author Richard Bair
051 */
052 public final class WindowUtils {
053 private static final Logger LOG = Logger.getLogger(WindowUtils.class
054 .getName());
055
056 /**
057 * Hide the constructor - don't wan't anybody creating an instance of this
058 */
059 private WindowUtils() {
060 }
061
062 /**
063 * <p>
064 * Returns the <code>Point</code> at which a window should be placed to
065 * center that window on the screen.
066 * </p>
067 * <p>
068 * Some thought was taken as to whether to implement a method such as this,
069 * or to simply make a method that, given a window, will center it. It was
070 * decided that it is better to not alter an object within a method.
071 * </p>
072 *
073 * @param window The window to calculate the center point for. This object
074 * can not be null.
075 *
076 * @return the <code>Point</code> at which the window should be placed to
077 * center that window on the screen.
078 */
079 public static Point getPointForCentering(Window window) {
080 Rectangle usableBounds = getUsableDeviceBounds(window);
081 int screenWidth = usableBounds.width;
082 int screenHeight = usableBounds.height;
083 int width = window.getWidth();
084 int height = window.getHeight();
085
086 return new Point(((screenWidth - width) / 2) + usableBounds.x,
087 ((screenHeight - height) / 2) + usableBounds.y);
088 }
089
090 private static Rectangle getUsableDeviceBounds(Window window) {
091 Window owner = window.getOwner();
092 GraphicsConfiguration gc = null;
093
094 if (owner == null) {
095 gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
096 .getDefaultScreenDevice().getDefaultConfiguration();
097 } else {
098 gc = owner.getGraphicsConfiguration();
099 }
100
101 Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
102 Rectangle bounds = gc.getBounds();
103 bounds.x += insets.left;
104 bounds.y += insets.top;
105 bounds.width -= (insets.left + insets.right);
106 bounds.height -= (insets.top + insets.bottom);
107
108 return bounds;
109 }
110
111 /**
112 * <p/>
113 * Returns the <code>Point</code> at which a window should be placed to
114 * center that window on the given desktop.
115 * </p>
116 * <p/>
117 * Some thought was taken as to whether to implement a method such as this,
118 * or to simply make a method that, given a window, will center it. It was
119 * decided that it is better to not alter an object within a method.
120 * </p>
121 *
122 * @param window The window (JInternalFrame) to calculate the center point
123 * for. This object can not be null.
124 *
125 * @return the <code>Point</code> at which the window should be placed to
126 * center that window on the given desktop
127 */
128 public static Point getPointForCentering(JInternalFrame window) {
129 try {
130 //assert window != null;
131 Point mousePoint = MouseInfo.getPointerInfo().getLocation();
132 GraphicsDevice[] devices = GraphicsEnvironment
133 .getLocalGraphicsEnvironment().getScreenDevices();
134 for (GraphicsDevice device : devices) {
135 Rectangle bounds = device.getDefaultConfiguration().getBounds();
136 //check to see if the mouse cursor is within these bounds
137 if (mousePoint.x >= bounds.x && mousePoint.y >= bounds.y
138 && mousePoint.x <= (bounds.x + bounds.width)
139 && mousePoint.y <= (bounds.y + bounds.height)) {
140 //this is it
141 int screenWidth = bounds.width;
142 int screenHeight = bounds.height;
143 int width = window.getWidth();
144 int height = window.getHeight();
145 return new Point(((screenWidth - width) / 2) + bounds.x,
146 ((screenHeight - height) / 2) + bounds
147 .y);
148 }
149 }
150 } catch (Exception e) {
151 LOG.log(Level.FINE, e.getLocalizedMessage() +
152 " - this can occur do to a Security exception in sandboxed apps");
153 }
154 return new Point(0, 0);
155 }
156
157 /**
158 * <p/>
159 * Returns the <code>Point</code> at which a window should be placed in
160 * order to be staggered slightly from another "origin" window to
161 * ensure that the title areas of both windows remain visible to the user.
162 * </p>
163 *
164 * @param originWindow Window from which the staggered location will be calculated
165 *
166 * @return location staggered from the upper left location of the origin
167 * window
168 */
169 public static Point getPointForStaggering(Window originWindow) {
170 Point origin = originWindow.getLocation();
171 Insets insets = originWindow.getInsets();
172 origin.x += insets.top;
173 origin.y += insets.top;
174 return origin;
175 }
176
177 public static Window findWindow(Component c) {
178 if (c == null) {
179 return JOptionPane.getRootFrame();
180 } else if (c instanceof Window) {
181 return (Window) c;
182 } else {
183 return findWindow(c.getParent());
184 }
185 }
186
187 public static List<Component> getAllComponents(final Container c) {
188 Component[] comps = c.getComponents();
189 List<Component> compList = new ArrayList<Component>();
190 for (Component comp : comps) {
191 compList.add(comp);
192 if (comp instanceof Container) {
193 compList.addAll(getAllComponents((Container) comp));
194 }
195 }
196 return compList;
197 }
198
199 /**
200 * Installs/resets a ComponentListener to resize the
201 * given window to minWidth/Height if needed.
202 *
203 * @param window
204 * @param minWidth
205 * @param minHeight
206 */
207 public static void setMinimumSizeManager(Window window, int minWidth,
208 int minHeight) {
209 ComponentListener[] listeners = window.getComponentListeners();
210 ComponentListener listener = null;
211 for (ComponentListener l : listeners) {
212 if (l instanceof MinSizeComponentListener) {
213 listener = l;
214 break;
215 }
216 }
217 if (listener == null) {
218 window.addComponentListener(new MinSizeComponentListener(
219 window, minWidth, minHeight));
220 } else {
221 ((MinSizeComponentListener) listener).resetSizes(minWidth,
222 minHeight);
223 }
224 }
225
226 /**
227 * Resets window size to minSize if needed.
228 *
229 * @author Patrick Wright
230 */
231 public static class MinSizeComponentListener extends ComponentAdapter {
232 private Window window;
233 private int minHeight;
234 private int minWidth;
235
236 MinSizeComponentListener(Window frame, int minWidth, int minHeight) {
237 this.window = frame;
238 resetSizes(minWidth, minHeight);
239 }
240
241 public void resetSizes(int minWidth, int minHeight) {
242 this.minWidth = minWidth;
243 this.minHeight = minHeight;
244 adjustIfNeeded(window);
245 }
246
247 @Override
248 public void componentResized(java.awt.event.ComponentEvent evt) {
249 adjustIfNeeded((Window) evt.getComponent());
250 }
251
252 private void adjustIfNeeded(final Window window) {
253 boolean doSize = false;
254 int newWidth = window.getWidth();
255 int newHeight = window.getHeight();
256 if (newWidth < minWidth) {
257 newWidth = minWidth;
258 doSize = true;
259 }
260 if (newHeight < minHeight) {
261 newHeight = minHeight;
262 doSize = true;
263 }
264 if (doSize) {
265 final int w = newWidth;
266 final int h = newHeight;
267 SwingUtilities.invokeLater(new Runnable() {
268 public void run() {
269 window.setSize(w, h);
270 }
271 });
272 }
273 }
274 }
275 }