001: // This class originally taken from
002: // http://www.randelshofer.ch/oop/javasplash/javasplash.html
003: /*
004: * @(#)SplashWindow.java 2.2 2005-04-03
005: *
006: * Copyright (c) 2003-2005 Werner Randelshofer
007: * Staldenmattweg 2, Immensee, CH-6405, Switzerland.
008: * All rights reserved.
009: *
010: * This software is in the public domain.
011: */
012: package org.java.plugin.boot;
013:
014: import java.awt.Dimension;
015: import java.awt.EventQueue;
016: import java.awt.Frame;
017: import java.awt.Graphics;
018: import java.awt.Image;
019: import java.awt.MediaTracker;
020: import java.awt.Toolkit;
021: import java.awt.Window;
022: import java.awt.event.MouseAdapter;
023: import java.awt.event.MouseEvent;
024: import java.net.URL;
025:
026: /**
027: * A Splash window.
028: * <p>
029: * Usage: MyApplication is your application class. Create a Splasher class which
030: * opens the splash window, invokes the main method of your Application class,
031: * and disposes the splash window afterwards.
032: * Please note that we want to keep the Splasher class and the SplashWindow class
033: * as small as possible. The less code and the less classes must be loaded into
034: * the JVM to open the splash screen, the faster it will appear.
035: * <pre>
036: * class Splasher {
037: * public static void main(String[] args) {
038: * SplashWindow.splash(Startup.class.getResource("splash.gif"));
039: * MyApplication.main(args);
040: * SplashWindow.disposeSplash();
041: * }
042: * }
043: * </pre>
044: *
045: * @author Werner Randelshofer
046: * @version 2.1 2005-04-03 Revised.
047: * @version $Id$
048: */
049: final class SplashWindow extends Window {
050: private static final long serialVersionUID = 7264517933349367876L;
051:
052: /**
053: * The current instance of the splash window.
054: * (Singleton design pattern).
055: */
056: private static SplashWindow instance;
057:
058: /**
059: * The splash image which is displayed on the splash window.
060: */
061: private Image image;
062:
063: /**
064: * This attribute indicates whether the method
065: * paint(Graphics) has been called at least once since the
066: * construction of this window.<br>
067: * This attribute is used to notify method splash(Image)
068: * that the window has been drawn at least once
069: * by the AWT event dispatcher thread.<br>
070: * This attribute acts like a latch. Once set to true,
071: * it will never be changed back to false again.
072: *
073: * @see #paint(Graphics)
074: * @see #splash(URL)
075: */
076: boolean paintCalled = false;
077:
078: /**
079: * Creates a new instance.
080: * @param parent the parent of the window.
081: * @param image the splash image.
082: */
083: private SplashWindow(final Frame parent, final Image anImage) {
084: super (parent);
085: image = anImage;
086:
087: // Load the image
088: MediaTracker mt = new MediaTracker(this );
089: mt.addImage(image, 0);
090: try {
091: mt.waitForID(0);
092: } catch (InterruptedException ie) {
093: // ignore
094: }
095:
096: // Center the window on the screen
097: int imgWidth = image.getWidth(this );
098: int imgHeight = image.getHeight(this );
099: setSize(imgWidth, imgHeight);
100: Dimension screenDim = Toolkit.getDefaultToolkit()
101: .getScreenSize();
102: setLocation((screenDim.width - imgWidth) / 2,
103: (screenDim.height - imgHeight) / 2);
104:
105: // Users shall be able to close the splash window by
106: // clicking on its display area. This mouse listener
107: // listens for mouse clicks and disposes the splash window.
108: MouseAdapter disposeOnClick = new MouseAdapter() {
109: @Override
110: public void mouseClicked(final MouseEvent evt) {
111: // Note: To avoid that method splash hangs, we
112: // must set paintCalled to true and call notifyAll.
113: // This is necessary because the mouse click may
114: // occur before the contents of the window
115: // has been painted.
116: synchronized (SplashWindow.this ) {
117: SplashWindow.this .paintCalled = true;
118: SplashWindow.this .notifyAll();
119: }
120: dispose();
121: }
122: };
123: addMouseListener(disposeOnClick);
124: }
125:
126: /**
127: * @see java.awt.Component#update(java.awt.Graphics)
128: */
129: @Override
130: public void update(final Graphics g) {
131: // Note: Since the paint method is going to draw an
132: // image that covers the complete area of the component we
133: // do not fill the component with its background color
134: // here. This avoids flickering.
135: paint(g);
136: }
137:
138: /**
139: * @see java.awt.Component#paint(java.awt.Graphics)
140: */
141: @Override
142: public void paint(final Graphics g) {
143: g.drawImage(image, 0, 0, this );
144:
145: // Notify method splash that the window
146: // has been painted.
147: // Note: To improve performance we do not enter
148: // the synchronized block unless we have to.
149: if (!paintCalled) {
150: paintCalled = true;
151: synchronized (this ) {
152: notifyAll();
153: }
154: }
155: }
156:
157: /**
158: * Open's a splash window using the specified image.
159: * @param image The splash image.
160: */
161: private static void splash(final Image image) {
162: if (instance == null && image != null) {
163: Frame f = new Frame();
164:
165: // Create the splash image
166: instance = new SplashWindow(f, image);
167:
168: // Show the window.
169: instance.setVisible(true);
170:
171: // Note: To make sure the user gets a chance to see the
172: // splash window we wait until its paint method has been
173: // called at least once by the AWT event dispatcher thread.
174: // If more than one processor is available, we don't wait,
175: // and maximize CPU throughput instead.
176: if (!EventQueue.isDispatchThread()
177: && Runtime.getRuntime().availableProcessors() == 1) {
178: synchronized (instance) {
179: while (!instance.paintCalled) {
180: try {
181: instance.wait();
182: } catch (InterruptedException ie) {
183: // ignore
184: }
185: }
186: }
187: }
188: }
189: }
190:
191: /**
192: * Open's a splash window using the specified image.
193: * @param imageURL The url of the splash image.
194: */
195: static void splash(final URL imageURL) {
196: if (imageURL != null) {
197: splash(Toolkit.getDefaultToolkit().createImage(imageURL));
198: }
199: }
200:
201: /**
202: * Closes the splash window.
203: */
204: static void disposeSplash() {
205: if (instance != null) {
206: instance.getOwner().dispose();
207: instance = null;
208: }
209: }
210: }
|