KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > SplashScreen


1 /**
2  * @(#)SplashScreen.java 1.13 06/11/21
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package java.awt;
8
9 import java.io.IOException JavaDoc;
10 import java.awt.image.*;
11 import java.net.URL JavaDoc;
12 import java.net.URLConnection JavaDoc;
13 import java.io.File JavaDoc;
14
15
16 /**
17  * The splash screen can be created at application startup, before the
18  * Java Virtual Machine (JVM) starts. The splash screen is displayed as an
19  * undecorated window containing an image. You can use GIF, JPEG, and PNG files
20  * for the image. Animation (for GIF) and transparency (for GIF, PNG) are
21  * supported. The window is positioned at the center of the screen (the
22  * position on multi-monitor systems is not specified - it is platform and
23  * implementation dependent).
24  * The window is closed automatically as soon as the first window is displayed by
25  * Swing/AWT (may be also closed manually using the Java API, see below).
26  * <P>
27  * There are two ways to show the native splash screen:
28  * <P>
29  * <UL>
30  * <LI>If your application is run from the command line or from a shortcut,
31  * use the "-splash:" Java application launcher option to show a splash screen.
32  * <BR>
33  * For example:
34  * <PRE>
35  * java -splash:filename.gif Test
36  * </PRE>
37  * <LI>If your application is packaged in a jar file, you can use the
38  * "SplashScreen-Image" option in a manifest file to show a splash screen.
39  * Place the image in the jar archive and specify the path in the option.
40  * The path should not have a leading slash.
41  * <BR>
42  * For example, in the <code>manifest.mf</code> file:
43  * <PRE>
44  * Manifest-Version: 1.0
45  * Main-Class: Test
46  * SplashScreen-Image: filename.gif
47  * </PRE>
48  * The command line interface has higher precedence over the manifest
49  * setting.
50  * </UL>
51  * <p>
52  * The {@code SplashScreen} class provides the API for controlling the splash
53  * screen. This class may be used to close the splash screen, change the splash
54  * screen image, get the image position/size and paint in the splash screen. It
55  * cannot be used to create the splash screen; you should use the command line or manifest
56  * file option for that.
57  * <p>
58  * This class cannot be instantiated. Only a single instance of this class
59  * can exist, and it may be obtained using the {@link #getSplashScreen()}
60  * static method. In case the splash screen has not been created at
61  * application startup via the command line or manifest file option,
62  * the <code>getSplashScreen</code> method returns <code>null</code>.
63  *
64  * @author Oleg Semenov
65  * @since 1.6
66  */

67 public final class SplashScreen {
68
69     SplashScreen(long ptr) { // non-public constructor
70
splashPtr = ptr;
71         wasClosed = false;
72     }
73
74     /**
75      * Returns the {@code SplashScreen} object used for
76      * Java startup splash screen control.
77      *
78      * @throws UnsupportedOperationException if the splash screen feature is not
79      * supported by the current toolkit
80      * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
81      * returns true
82      * @return the {@link SplashScreen} instance, or <code>null</code> if there is
83      * none or it has already been closed
84      */

85     public static synchronized SplashScreen JavaDoc getSplashScreen() {
86         if (GraphicsEnvironment.isHeadless()) {
87             throw new HeadlessException JavaDoc();
88         }
89         // SplashScreen class is now a singleton
90
if (SplashScreen.theInstance == null) {
91             java.security.AccessController.doPrivileged(
92                     new sun.security.action.LoadLibraryAction("splashscreen"));
93             long ptr = _getInstance();
94             if (ptr == 0) {
95                 return null;
96             }
97             if (!_isVisible(ptr)) {
98                 return null;
99             }
100             SplashScreen.theInstance = new SplashScreen JavaDoc(ptr);
101         }
102         return (theInstance.isVisible() ? theInstance : null);
103     }
104
105     /**
106      * Changes the splash screen image. The new image is loaded from the
107      * specified URL; GIF, JPEG and PNG image formats are supported.
108      * The method returns after the image has finished loading and the window
109      * has been updated.
110      * The splash screen window is resized according to the size of
111      * the image and is centered on the screen.
112      *
113      * @param imageURL the non-<code>null</code> URL for the new
114      * splash screen image
115      * @throws NullPointerException if {@code imageURL} is <code>null</code>
116      * @throws IOException if there was an error while loading the image
117      * @throws IllegalStateException if the splash screen has already been
118      * closed
119      */

120     public void setImageURL(URL JavaDoc imageURL) throws NullPointerException JavaDoc, IOException JavaDoc, IllegalStateException JavaDoc {
121         checkVisible();
122         URLConnection JavaDoc connection = imageURL.openConnection();
123         connection.connect();
124         int length = connection.getContentLength();
125         java.io.InputStream JavaDoc stream = connection.getInputStream();
126         byte[] buf = new byte[length];
127         int off = 0;
128         while(true) {
129             // check for available data
130
int available = stream.available();
131             if (available <= 0) {
132                 // no data available... well, let's try reading one byte
133
// we'll see what happens then
134
available = 1;
135             }
136             // check for enough room in buffer, realloc if needed
137
// the buffer always grows in size 2x minimum
138
if (off + available > length) {
139                 length = off*2;
140                 if (off + available > length) {
141                     length = available+off;
142                 }
143                 byte[] oldBuf = buf;
144                 buf = new byte[length];
145                 System.arraycopy(oldBuf, 0, buf, 0, off);
146             }
147             // now read the data
148
int result = stream.read(buf, off, available);
149             if (result < 0) {
150                 break;
151             }
152             off += result;
153         }
154         synchronized(this) {
155             if (!_setImageData(splashPtr, buf)) {
156                 throw new IOException JavaDoc("Bad image format or i/o error when loading image");
157             }
158             this.imageURL = imageURL;
159         }
160     }
161
162     private void checkVisible() {
163         if (!isVisible()) {
164             throw new IllegalStateException JavaDoc("no splash screen available");
165         }
166     }
167     /**
168      * Returns the current splash screen image.
169      *
170      * @return URL for the current splash screen image file
171      * @throws IllegalStateException if the splash screen has already been closed
172      */

173     public synchronized URL JavaDoc getImageURL() throws IllegalStateException JavaDoc {
174         checkVisible();
175         if (imageURL == null) {
176             try {
177                 String JavaDoc fileName = _getImageFileName(splashPtr);
178                 String JavaDoc jarName = _getImageJarName(splashPtr);
179                 if (fileName != null) {
180                     if (jarName != null) {
181                         imageURL = new URL JavaDoc("jar:"+(new File JavaDoc(jarName).toURL().toString())+"!/"+fileName);
182                     } else {
183                         imageURL = new File JavaDoc(fileName).toURL();
184                     }
185                 }
186             }
187             catch(java.net.MalformedURLException JavaDoc e) {
188                 // we'll just return null in this case
189
}
190         }
191         return imageURL;
192     }
193
194     /**
195      * Returns the bounds of the splash screen window as a {@link Rectangle}.
196      * This may be useful if, for example, you want to replace the splash
197      * screen with your window at the same location.
198      * <p>
199      * You cannot control the size or position of the splash screen.
200      * The splash screen size is adjusted automatically when the image changes.
201      *
202      * @return a {@code Rectangle} containing the splash screen bounds
203      * @throws IllegalStateException if the splash screen has already been closed
204      */

205     public Rectangle JavaDoc getBounds() throws IllegalStateException JavaDoc {
206         checkVisible();
207         return _getBounds(splashPtr);
208     }
209
210     /**
211      * Returns the size of the splash screen window as a {@link Dimension}.
212      * This may be useful if, for example,
213      * you want to draw on the splash screen overlay surface.
214      * <p>
215      * You cannot control the size or position of the splash screen.
216      * The splash screen size is adjusted automatically when the image changes.
217      *
218      * @return a {@link Dimension} object indicating the splash screen size
219      * @throws IllegalStateException if the splash screen has already been closed
220      */

221     public Dimension JavaDoc getSize() throws IllegalStateException JavaDoc {
222         return getBounds().getSize();
223     }
224
225     /**
226      * Creates a graphics context (as a {@link Graphics2D} object) for the splash
227      * screen overlay image, which allows you to draw over the splash screen.
228      * Note that you do not draw on the main image but on the image that is
229      * displayed over the main image using alpha blending. Also note that drawing
230      * on the overlay image does not necessarily update the contents of splash
231      * screen window. You should call {@code update()} on the
232      * <code>SplashScreen</code> when you want the splash screen to be
233      * updated immediately.
234      *
235      * @return graphics context for the splash screen overlay surface
236      * @throws IllegalStateException if the splash screen has already been closed
237      */

238     public Graphics2D JavaDoc createGraphics() throws IllegalStateException JavaDoc {
239         if (image==null) {
240             Dimension JavaDoc dim = getSize();
241             image = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
242         }
243         return image.createGraphics();
244     }
245
246     /**
247      * Updates the splash window with current contents of the overlay image.
248      *
249      * @throws IllegalStateException if the overlay image does not exist;
250      * for example, if {@code createGraphics} has never been called,
251      * or if the splash screen has already been closed
252      */

253     public void update() throws IllegalStateException JavaDoc {
254         checkVisible();
255         if (image == null) {
256             throw new IllegalStateException JavaDoc("no overlay image available");
257         }
258         DataBuffer buf = image.getRaster().getDataBuffer();
259         if (!(buf instanceof DataBufferInt)) {
260             throw new AssertionError JavaDoc("Overlay image DataBuffer is of invalid type == "+buf.getClass().getName());
261         }
262         int numBanks = buf.getNumBanks();
263         if (numBanks!=1) {
264             throw new AssertionError JavaDoc("Invalid number of banks =="+numBanks+" in overlay image DataBuffer");
265         }
266         if (!(image.getSampleModel() instanceof SinglePixelPackedSampleModel)) {
267             throw new AssertionError JavaDoc("Overlay image has invalid sample model == "+image.getSampleModel().getClass().getName());
268         }
269         SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel)image.getSampleModel();
270         int scanlineStride = sm.getScanlineStride();
271         Rectangle JavaDoc rect = image.getRaster().getBounds();
272         int[] data = ((DataBufferInt)buf).getData();
273         _update(splashPtr, data, rect.x, rect.y, rect.width, rect.height, scanlineStride);
274     }
275
276     /**
277      * Hides the splash screen, closes the window, and releases all associated
278      * resources.
279      *
280      * @throws IllegalStateException if the splash screen has already been closed
281      */

282     public synchronized void close() throws IllegalStateException JavaDoc {
283         checkVisible();
284         _close(splashPtr);
285         image = null;
286         wasClosed = true;
287         // There should be resetting the theInstance to null to prevent memory
288
// leak. But it brings some more problems with the bug 6382748, so we
289
// let the limited leak to stay.
290
}
291
292
293     /**
294      * Determines whether the splash screen is visible. The splash screen may
295      * be hidden using {@link #close()}, it is also hidden automatically when
296      * the first AWT/Swing window is made visible.
297      *
298      * @return true if the splash screen is visible (has not been closed yet),
299      * false otherwise
300      */

301     public boolean isVisible() {
302         return !wasClosed && _isVisible(splashPtr);
303     }
304
305     private BufferedImage image; // overlay image
306

307     private long splashPtr; // pointer to native Splash structure
308
private boolean wasClosed;
309
310     private URL JavaDoc imageURL;
311
312     /**
313      * The instance reference for the singleton.
314      * (<code>null</code> if no instance exists yet.)
315      *
316      * @see #getSplashScreen
317      * @see #close
318      */

319     private static SplashScreen JavaDoc theInstance = null;
320
321     private native static void _update(long splashPtr, int[] data, int x, int y, int width, int height, int scanlineStride);
322     private native static boolean _isVisible(long splashPtr);
323     private native static Rectangle JavaDoc _getBounds(long splashPtr);
324     private native static long _getInstance();
325     private native static void _close(long splashPtr);
326     private native static String JavaDoc _getImageFileName(long splashPtr);
327     private native static String JavaDoc _getImageJarName(long SplashPtr);
328     private native static boolean _setImageData(long SplashPtr, byte[] data);
329
330 };
331
332
Popular Tags