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