| 
001 /*002  * Copyright 2008-2015 the original author or authors.
 003  *
 004  * Licensed under the Apache License, Version 2.0 (the "License");
 005  * you may not use this file except in compliance with the License.
 006  * You may obtain a copy of the License at
 007  *
 008  *     http://www.apache.org/licenses/LICENSE-2.0
 009  *
 010  * Unless required by applicable law or agreed to in writing, software
 011  * distributed under the License is distributed on an "AS IS" BASIS,
 012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 013  * See the License for the specific language governing permissions and
 014  * limitations under the License.
 015  */
 016 package griffon.swing.support;
 017
 018 import griffon.core.GriffonApplication;
 019
 020 import javax.annotation.Nonnull;
 021 import javax.annotation.Nullable;
 022 import javax.swing.JDesktopPane;
 023 import javax.swing.JFrame;
 024 import javax.swing.JInternalFrame;
 025 import javax.swing.WindowConstants;
 026 import java.awt.Component;
 027 import java.awt.Container;
 028 import java.awt.Dimension;
 029 import java.awt.Graphics;
 030 import java.awt.GraphicsConfiguration;
 031 import java.awt.GraphicsDevice;
 032 import java.awt.GraphicsEnvironment;
 033 import java.awt.Image;
 034 import java.awt.Point;
 035 import java.awt.Toolkit;
 036 import java.awt.Window;
 037 import java.awt.image.BufferedImage;
 038 import java.util.Map;
 039
 040 import static griffon.util.GriffonClassUtils.setPropertiesNoException;
 041 import static griffon.util.GriffonNameUtils.isBlank;
 042 import static griffon.util.GriffonNameUtils.requireNonBlank;
 043 import static java.util.Objects.requireNonNull;
 044
 045 /**
 046  * Additional utilities for Swing based applications.
 047  *
 048  * @author Andres Almiray
 049  * @since 2.0.0
 050  */
 051 public class SwingUtils {
 052     private static final String ERROR_WINDOW_NULL = "Argument 'window' must not be null";
 053
 054     /**
 055      * Centers a Window on the screen<p>
 056      * Sets the window on the top left corner if the window's
 057      * dimensions are bigger than the screen's.
 058      *
 059      * @param window a Window object
 060      */
 061     public static void centerOnScreen(@Nonnull Window window) {
 062         requireNonNull(window, ERROR_WINDOW_NULL);
 063
 064         Point center = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
 065         Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
 066
 067         double w = Math.min(window.getWidth(), screen.width);
 068         double h = Math.min(window.getHeight(), screen.height);
 069         int x = (int) (center.x - (w / 2));
 070         int y = (int) (center.y - (h / 2));
 071
 072         Point corner = new Point(
 073             (x >= 0 ? x : 0),
 074             (y >= 0 ? y : 0)
 075         );
 076
 077         window.setLocation(corner);
 078     }
 079
 080     /**
 081      * Centers a JInternalFrame on the screen<p>
 082      * Sets the internal frame on the top left corner if the frame's
 083      * dimensions are bigger than the desktop's.
 084      *
 085      * @param internalFrame a JInternalFrame object
 086      */
 087     public static void centerOnScreen(@Nonnull JInternalFrame internalFrame) {
 088         requireNonNull(internalFrame, "Argument 'internalFrame' must not be null");
 089
 090         JDesktopPane desktop = internalFrame.getDesktopPane();
 091         if (desktop == null) return;
 092         Dimension screen = desktop.getSize();
 093         Point center = new Point(screen.width / 2, screen.height / 2);
 094
 095         double w = Math.min(internalFrame.getWidth(), screen.width);
 096         double h = Math.min(internalFrame.getHeight(), screen.height);
 097         int x = (int) (center.x - (w / 2));
 098         int y = (int) (center.y - (h / 2));
 099
 100         Point corner = new Point(
 101             (x >= 0 ? x : 0),
 102             (y >= 0 ? y : 0)
 103         );
 104
 105         internalFrame.setLocation(corner);
 106     }
 107
 108     /**
 109      * Returns the window's current opacity value.
 110      *
 111      * @param window the window on which the opacity will be queried
 112      * @return the window's opacity value
 113      */
 114     public static float getWindowOpacity(@Nonnull Window window) {
 115         requireNonNull(window, ERROR_WINDOW_NULL);
 116         return window.getOpacity();
 117     }
 118
 119     /**
 120      * Sets the value for the window's opacity.
 121      *
 122      * @param window  the window on which the opacity will be set
 123      * @param opacity the new opacity value
 124      */
 125     public static void setWindowOpacity(@Nonnull Window window, float opacity) {
 126         requireNonNull(window, ERROR_WINDOW_NULL);
 127         window.setOpacity(opacity);
 128     }
 129
 130     /**
 131      * Searches a component by name in a particular component hierarchy.<p>
 132      * A component must have a value for its <tt>name</tt> property if it's
 133      * to be found with this method.<br/>
 134      * This method performs a depth-first search.
 135      *
 136      * @param name the value of the component's <tt>name</tt> property
 137      * @param root the root of the component hierarchy from where searching
 138      *             searching should start
 139      * @return the component reference if found, null otherwise
 140      */
 141     @Nullable
 142     public static Component findComponentByName(@Nonnull String name, @Nonnull Container root) {
 143         requireNonNull(root, "Argument 'root' must not be null");
 144         requireNonBlank(name, "Argument 'name' must not be blank");
 145         if (name.equals(root.getName())) {
 146             return root;
 147         }
 148
 149         for (Component comp : root.getComponents()) {
 150             if (name.equals(comp.getName())) {
 151                 return comp;
 152             }
 153             if (comp instanceof Container) {
 154                 Component found = findComponentByName(name, (Container) comp);
 155                 if (found != null) {
 156                     return found;
 157                 }
 158             }
 159         }
 160         return null;
 161     }
 162
 163     /**
 164      * Takes a snapshot of the target component.
 165      *
 166      * @param component the component to draw
 167      * @return a Graphics compatible image of the component
 168      */
 169     @Nonnull
 170     public static Image takeSnapshot(@Nonnull Component component) {
 171         return takeSnapshot(component, false);
 172     }
 173
 174     /**
 175      * Takes a snapshot of the target component.
 176      *
 177      * @param component the component to draw
 178      * @param usePrint  whether <tt>print()</tt> or <tt>paint()</tt> is used to grab the snapshot
 179      * @return a Graphics compatible image of the component
 180      */
 181     @Nonnull
 182     public static Image takeSnapshot(@Nonnull Component component, boolean usePrint) {
 183         requireNonNull(component, "Argument 'component' must not be null");
 184
 185         BufferedImage image = null;
 186         GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
 187         GraphicsDevice gd = genv.getDefaultScreenDevice();
 188         GraphicsConfiguration gc = gd.getDefaultConfiguration();
 189
 190         if (gc.getColorModel().hasAlpha()) {
 191             image = gc.createCompatibleImage(
 192                 (int) component.getSize().getWidth(),
 193                 (int) component.getSize().getHeight());
 194         } else {
 195             image = new BufferedImage(
 196                 (int) component.getSize().getWidth(),
 197                 (int) component.getSize().getHeight(),
 198                 BufferedImage.TYPE_INT_ARGB);
 199         }
 200
 201         Graphics g = image.getGraphics();
 202         if (usePrint) {
 203             component.print(g);
 204         } else {
 205             component.paint(g);
 206         }
 207         g.dispose();
 208
 209         return image;
 210     }
 211
 212     private static Class<?> loadClass(String className) {
 213         try {
 214             return Class.forName(className);
 215         } catch (ClassNotFoundException e) {
 216             throw new IllegalArgumentException(e);
 217         }
 218     }
 219
 220     /**
 221      * Creates a Window based on the application's configuration.<p>
 222      * Class lookup order is<ol>
 223      * <li>value in app.config.application.frameClass</li>
 224      * <li>'org.jdesktop.swingx.JXFrame' if SwingX is in the classpath</li>
 225      * <li>'javax.swing.JFrame'</li>
 226      *
 227      *
 228      * @param application the current running application
 229      * @param attributes window attributes
 230      * @return a newly instantiated window according to the application's
 231      *         preferences
 232      */
 233     @Nonnull
 234     public static Window createApplicationFrame(@Nonnull GriffonApplication application, @Nonnull Map<String, Object> attributes) {
 235         requireNonNull(application, "Argument 'application' must not be null");
 236         JFrame frame = null;
 237         // try config specified first
 238         String frameClass = application.getConfiguration().getAsString("application.frameClass", JFrame.class.getName());
 239         if (!isBlank(frameClass)) {
 240             try {
 241                 ClassLoader cl = SwingUtils.class.getClassLoader();
 242                 if (cl != null) {
 243                     frame = (JFrame) cl.loadClass(frameClass).newInstance();
 244                 } else {
 245                     frame = (JFrame) Class.forName(frameClass).newInstance();
 246                 }
 247             } catch (Throwable ignored) {
 248                 // ignore
 249             }
 250         }
 251         if (frame == null) {
 252             // JXFrame, it's nice.  Try it!
 253             try {
 254                 ClassLoader cl = SwingUtils.class.getClassLoader();
 255                 if (cl != null) {
 256                     frame = (JFrame) cl.loadClass("org.jdesktop.swingx.JXFrame").newInstance();
 257                 } else {
 258                     frame = (JFrame) Class.forName("org.jdesktop.swingx.JXFrame").newInstance();
 259                 }
 260             } catch (Throwable ignored) {
 261                 // ignore
 262             }
 263             // this will work for sure
 264             if (frame == null) {
 265                 frame = new JFrame();
 266             }
 267
 268             // do some standard tweaking
 269             frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
 270         }
 271
 272         setPropertiesNoException(frame, attributes);
 273
 274         return frame;
 275     }
 276 }
 |