1 | /* |
---|
2 | * This program is free software; you can redistribute it and/or modify |
---|
3 | * it under the terms of the GNU General Public License as published by |
---|
4 | * the Free Software Foundation; either version 2 of the License, or |
---|
5 | * (at your option) any later version. |
---|
6 | * |
---|
7 | * This program is distributed in the hope that it will be useful, |
---|
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
10 | * GNU General Public License for more details. |
---|
11 | * |
---|
12 | * You should have received a copy of the GNU General Public License |
---|
13 | * along with this program; if not, write to the Free Software |
---|
14 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
15 | */ |
---|
16 | |
---|
17 | /* |
---|
18 | * @(#)SplashWindow.java 2.2 2005-04-03 |
---|
19 | * |
---|
20 | * Copyright (c) 2003-2005 Werner Randelshofer |
---|
21 | * Staldenmattweg 2, Immensee, CH-6405, Switzerland. |
---|
22 | * All rights reserved. |
---|
23 | * |
---|
24 | * This software is in the public domain. |
---|
25 | * |
---|
26 | */ |
---|
27 | |
---|
28 | package weka.gui; |
---|
29 | |
---|
30 | import java.awt.Dimension; |
---|
31 | import java.awt.EventQueue; |
---|
32 | import java.awt.Frame; |
---|
33 | import java.awt.Graphics; |
---|
34 | import java.awt.Image; |
---|
35 | import java.awt.MediaTracker; |
---|
36 | import java.awt.Toolkit; |
---|
37 | import java.awt.Window; |
---|
38 | import java.awt.event.MouseAdapter; |
---|
39 | import java.awt.event.MouseEvent; |
---|
40 | import java.net.URL; |
---|
41 | |
---|
42 | /** |
---|
43 | * A Splash window. |
---|
44 | * <p> |
---|
45 | * Usage: MyApplication is your application class. Create a Splasher class which |
---|
46 | * opens the splash window, invokes the main method of your Application class, |
---|
47 | * and disposes the splash window afterwards. |
---|
48 | * Please note that we want to keep the Splasher class and the SplashWindow class |
---|
49 | * as small as possible. The less code and the less classes must be loaded into |
---|
50 | * the JVM to open the splash screen, the faster it will appear. |
---|
51 | * <pre> |
---|
52 | * class Splasher { |
---|
53 | * public static void main(String[] args) { |
---|
54 | * SplashWindow.splash(Startup.class.getResource("splash.gif")); |
---|
55 | * MyApplication.main(args); |
---|
56 | * SplashWindow.disposeSplash(); |
---|
57 | * } |
---|
58 | * } |
---|
59 | * </pre> |
---|
60 | * |
---|
61 | * @author Werner Randelshofer |
---|
62 | * @author Mark Hall |
---|
63 | * @version $Revision: 1.3 $ |
---|
64 | */ |
---|
65 | public class SplashWindow |
---|
66 | extends Window { |
---|
67 | |
---|
68 | /** for serialization */ |
---|
69 | private static final long serialVersionUID = -2685134277041307795L; |
---|
70 | |
---|
71 | /** |
---|
72 | * The current instance of the splash window. |
---|
73 | * (Singleton design pattern). |
---|
74 | */ |
---|
75 | private static SplashWindow m_instance; |
---|
76 | |
---|
77 | /** |
---|
78 | * The splash image which is displayed on the splash window. |
---|
79 | */ |
---|
80 | private Image image; |
---|
81 | |
---|
82 | /** |
---|
83 | * This attribute indicates whether the method |
---|
84 | * paint(Graphics) has been called at least once since the |
---|
85 | * construction of this window.<br> |
---|
86 | * This attribute is used to notify method splash(Image) |
---|
87 | * that the window has been drawn at least once |
---|
88 | * by the AWT event dispatcher thread.<br> |
---|
89 | * This attribute acts like a latch. Once set to true, |
---|
90 | * it will never be changed back to false again. |
---|
91 | * |
---|
92 | * @see #paint |
---|
93 | * @see #splash |
---|
94 | */ |
---|
95 | private boolean paintCalled = false; |
---|
96 | |
---|
97 | /** |
---|
98 | * Creates a new instance. |
---|
99 | * @param parent the parent of the window. |
---|
100 | * @param image the splash image. |
---|
101 | */ |
---|
102 | private SplashWindow(Frame parent, Image image) { |
---|
103 | super(parent); |
---|
104 | this.image = image; |
---|
105 | |
---|
106 | // Load the image |
---|
107 | MediaTracker mt = new MediaTracker(this); |
---|
108 | mt.addImage(image,0); |
---|
109 | try { |
---|
110 | mt.waitForID(0); |
---|
111 | } catch(InterruptedException ie){ |
---|
112 | } |
---|
113 | |
---|
114 | // Center the window on the screen |
---|
115 | int imgWidth = image.getWidth(this); |
---|
116 | int imgHeight = image.getHeight(this); |
---|
117 | setSize(imgWidth, imgHeight); |
---|
118 | Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize(); |
---|
119 | setLocation( |
---|
120 | (screenDim.width - imgWidth) / 2, |
---|
121 | (screenDim.height - imgHeight) / 2 |
---|
122 | ); |
---|
123 | |
---|
124 | |
---|
125 | // Users shall be able to close the splash window by |
---|
126 | // clicking on its display area. This mouse listener |
---|
127 | // listens for mouse clicks and disposes the splash window. |
---|
128 | MouseAdapter disposeOnClick = new MouseAdapter() { |
---|
129 | public void mouseClicked(MouseEvent evt) { |
---|
130 | // Note: To avoid that method splash hangs, we |
---|
131 | // must set paintCalled to true and call notifyAll. |
---|
132 | // This is necessary because the mouse click may |
---|
133 | // occur before the contents of the window |
---|
134 | // has been painted. |
---|
135 | synchronized(SplashWindow.this) { |
---|
136 | SplashWindow.this.paintCalled = true; |
---|
137 | SplashWindow.this.notifyAll(); |
---|
138 | } |
---|
139 | dispose(); |
---|
140 | } |
---|
141 | }; |
---|
142 | addMouseListener(disposeOnClick); |
---|
143 | } |
---|
144 | |
---|
145 | /** |
---|
146 | * Updates the display area of the window. |
---|
147 | */ |
---|
148 | public void update(Graphics g) { |
---|
149 | // Note: Since the paint method is going to draw an |
---|
150 | // image that covers the complete area of the component we |
---|
151 | // do not fill the component with its background color |
---|
152 | // here. This avoids flickering. |
---|
153 | |
---|
154 | paint(g); |
---|
155 | } |
---|
156 | |
---|
157 | /** |
---|
158 | * Paints the image on the window. |
---|
159 | */ |
---|
160 | public void paint(Graphics g) { |
---|
161 | g.drawImage(image, 0, 0, this); |
---|
162 | // Notify method splash that the window |
---|
163 | // has been painted. |
---|
164 | // Note: To improve performance we do not enter |
---|
165 | // the synchronized block unless we have to. |
---|
166 | if (! paintCalled) { |
---|
167 | paintCalled = true; |
---|
168 | synchronized (this) { notifyAll(); } |
---|
169 | } |
---|
170 | } |
---|
171 | |
---|
172 | /** |
---|
173 | * Open's a splash window using the specified image. |
---|
174 | * @param image The splash image. |
---|
175 | */ |
---|
176 | public static void splash(Image image) { |
---|
177 | if (m_instance == null && image != null) { |
---|
178 | Frame f = new Frame(); |
---|
179 | |
---|
180 | // Create the splash image |
---|
181 | m_instance = new SplashWindow(f, image); |
---|
182 | |
---|
183 | // Show the window. |
---|
184 | m_instance.show(); |
---|
185 | |
---|
186 | // Note: To make sure the user gets a chance to see the |
---|
187 | // splash window we wait until its paint method has been |
---|
188 | // called at least once by the AWT event dispatcher thread. |
---|
189 | // If more than one processor is available, we don't wait, |
---|
190 | // and maximize CPU throughput instead. |
---|
191 | if (!EventQueue.isDispatchThread() |
---|
192 | && Runtime.getRuntime().availableProcessors() == 1) { |
---|
193 | synchronized (m_instance) { |
---|
194 | while (! m_instance.paintCalled) { |
---|
195 | try { m_instance.wait(); } catch (InterruptedException e) {} |
---|
196 | } |
---|
197 | } |
---|
198 | } |
---|
199 | } |
---|
200 | } |
---|
201 | |
---|
202 | /** |
---|
203 | * Open's a splash window using the specified image. |
---|
204 | * @param imageURL The url of the splash image. |
---|
205 | */ |
---|
206 | public static void splash(URL imageURL) { |
---|
207 | if (imageURL != null) { |
---|
208 | splash(Toolkit.getDefaultToolkit().createImage(imageURL)); |
---|
209 | } |
---|
210 | } |
---|
211 | |
---|
212 | /** |
---|
213 | * Closes the splash window. |
---|
214 | */ |
---|
215 | public static void disposeSplash() { |
---|
216 | if (m_instance != null) { |
---|
217 | m_instance.getOwner().dispose(); |
---|
218 | m_instance = null; |
---|
219 | } |
---|
220 | } |
---|
221 | |
---|
222 | /** |
---|
223 | * Invokes the named method of the provided class name. |
---|
224 | * @param className the name of the class |
---|
225 | * @param methodName the name of the method to invoke |
---|
226 | * @param args the command line arguments |
---|
227 | */ |
---|
228 | public static void invokeMethod(String className, String methodName, |
---|
229 | String [] args) { |
---|
230 | try { |
---|
231 | Class.forName(className) |
---|
232 | .getMethod(methodName, new Class[] {String[].class}) |
---|
233 | .invoke(null, new Object[] {args}); |
---|
234 | } catch (Exception e) { |
---|
235 | InternalError error = new InternalError("Failed to invoke method: " |
---|
236 | +methodName); |
---|
237 | error.initCause(e); |
---|
238 | throw error; |
---|
239 | } |
---|
240 | } |
---|
241 | |
---|
242 | /** |
---|
243 | * Invokes the main method of the provided class name. |
---|
244 | * @param className the name of the class |
---|
245 | * @param args the command line arguments |
---|
246 | */ |
---|
247 | public static void invokeMain(String className, String[] args) { |
---|
248 | try { |
---|
249 | Class.forName(className) |
---|
250 | .getMethod("main", new Class[] {String[].class}) |
---|
251 | .invoke(null, new Object[] {args}); |
---|
252 | } catch (Exception e) { |
---|
253 | InternalError error = new InternalError("Failed to invoke main method"); |
---|
254 | error.initCause(e); |
---|
255 | throw error; |
---|
256 | } |
---|
257 | } |
---|
258 | } |
---|