001 /*
002 * Copyright 2002-2007 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 org.springframework.richclient.application.splash;
017
018 import java.awt.Component;
019 import java.awt.Dimension;
020 import java.awt.Graphics;
021 import java.awt.Image;
022 import java.awt.MediaTracker;
023 import java.awt.Toolkit;
024 import java.io.IOException;
025 import java.net.URL;
026
027 import javax.swing.JPanel;
028
029 import org.apache.commons.logging.Log;
030 import org.apache.commons.logging.LogFactory;
031 import org.springframework.core.io.Resource;
032 import org.springframework.util.Assert;
033
034 /**
035 * A lightweight splash-screen for display when a GUI application is being
036 * initialized.
037 * <p>
038 * The splash screen renders an image in a Frame. It minimizes class loading so
039 * it is displayed immediately once the application is started.
040 *
041 * @author Keith Donald
042 * @author Jan Hoskens
043 */
044 public class SimpleSplashScreen extends AbstractSplashScreen {
045 private Image image;
046
047 private Resource imageResourcePath;
048
049 private static final Log logger = LogFactory.getLog(SimpleSplashScreen.class);
050
051 /**
052 * Creates a new uninitialized {@code SimpleSplashScreen}.
053 */
054 public SimpleSplashScreen() {
055 // do nothing
056 }
057
058 /**
059 * Creates a new {@code SimpleSplashScreen} that will display the image at
060 * the specified location.
061 *
062 * @param imageResourcePath The location of the image file to be displayed
063 * by this splash screen.
064 *
065 * @see #setImageResourcePath(String)
066 */
067 public SimpleSplashScreen(Resource imageResourcePath) {
068 setImageResourcePath(imageResourcePath);
069 }
070
071 /**
072 * Creates a new {@code SimpleSplashScreen} that will display the given
073 * image.
074 *
075 * @param image the image to splash.
076 *
077 * @throws IllegalArgumentException if {@code image} is null.
078 */
079 public SimpleSplashScreen(Image image) {
080 Assert.notNull(image, "The splash screen image is required");
081 this.image = image;
082 }
083
084 /**
085 * Sets the location of the image to be displayed by this splash screen. If
086 * the given path starts with a '/', it is interpreted to be relative to the
087 * root of the runtime classpath. Otherwise it is interpreted to be relative
088 * to the subdirectory of the classpath root that corresponds to the package
089 * of this class.
090 *
091 * @param path The path to the splash screen image.
092 */
093 public void setImageResourcePath(Resource path) {
094 Assert.notNull(path, "The splash screen image resource path is required");
095 this.imageResourcePath = path;
096 }
097
098 /**
099 * Load image from path.
100 *
101 * @param path Path to image.
102 * @return Image
103 * @throws IOException
104 *
105 * @throws NullPointerException if {@code path} is null.
106 */
107 private Image loadImage(Resource path) throws IOException {
108 URL url = path.getURL();
109 if (url == null) {
110 logger.warn("Unable to locate splash screen in classpath at: " + path);
111 return null;
112 }
113 return Toolkit.getDefaultToolkit().createImage(url);
114 }
115
116 protected Image getImage() {
117 if (image == null && imageResourcePath != null) {
118 try {
119 image = loadImage(imageResourcePath);
120 }
121 catch (IOException e) {
122 logger.error("Unable to load image from resource " + imageResourcePath, e);
123 }
124 }
125 return image;
126 }
127
128 /**
129 * Simple Canvas that paints an image.
130 */
131 public class ImageCanvas extends JPanel {
132 private static final long serialVersionUID = -5096223464173393949L;
133
134 private Image image;
135
136 /**
137 * Creates a new {@code ImageCanvas} with the specified image. The size
138 * of the canvas will be set to the size of the image.
139 *
140 * @param image The image to be displayed by the canvas.
141 *
142 * @throws NullPointerException if {@code image} is null.
143 */
144 public ImageCanvas(Image image) {
145 this.image = image;
146
147 loadImage();
148
149 Dimension size = new Dimension(image.getWidth(null), image.getHeight(null));
150
151 setSize(size);
152 setPreferredSize(size);
153 setMinimumSize(size);
154 }
155
156 private void loadImage() {
157 MediaTracker mediaTracker = new MediaTracker(this);
158 mediaTracker.addImage(image, 0);
159 try {
160 mediaTracker.waitForID(0);
161 }
162 catch (InterruptedException e) {
163 logger.warn("Interrupted while waiting for splash image to load.", e);
164 }
165 }
166
167 public void paintComponent(Graphics g) {
168 g.clearRect(0, 0, getWidth(), getHeight());
169 g.drawImage(image, 0, 0, this);
170 }
171 }
172
173 /**
174 * Returns a component that displays an image in a canvas.
175 */
176 protected Component createContentPane() {
177 Image image = getImage();
178 if (image != null) {
179 return new ImageCanvas(image);
180 }
181 return null;
182 }
183 }