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 }