001 /*
002 * Copyright 2002-2006 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.Image;
020 import java.awt.Toolkit;
021 import java.net.URL;
022
023 import javax.swing.JFrame;
024 import javax.swing.JOptionPane;
025
026 import org.apache.commons.logging.Log;
027 import org.apache.commons.logging.LogFactory;
028 import org.springframework.context.MessageSource;
029 import org.springframework.context.NoSuchMessageException;
030 import org.springframework.richclient.components.ShadowBorderFrame;
031 import org.springframework.richclient.util.WindowUtils;
032
033 /**
034 * An abstract helper implementation of the {@link SplashScreen} interface.
035 *
036 * <p>
037 * The splash screen produced by this class will be an undecorated, centered
038 * frame containing the component provided by {@link #createContentPane()},
039 * which is the only method that subclasses need to implement.
040 * </p>
041 *
042 * @author Peter De Bruycker
043 */
044 public abstract class AbstractSplashScreen implements SplashScreen {
045
046 /**
047 * The message resource key used to look up the splash screen's frame title.
048 */
049 public static final String SPLASH_TITLE_KEY = "splash.title";
050
051 private JFrame frame;
052
053 private MessageSource messageSource;
054
055 private String iconResourcePath;
056
057 private boolean shadowBorder;
058
059 protected final Log logger = LogFactory.getLog(getClass());
060
061 private boolean rootFrame = true;
062
063 /**
064 * Returns the location of the image to be used as the icon for the splash
065 * screen's frame. The splash screen produced by this class is undecorated,
066 * so the icon will only be visible in the frame's taskbar icon. If the
067 * given path starts with a '/', it is interpreted to be relative to the
068 * root of the runtime classpath. Otherwise it is interpreted to be relative
069 * to the subdirectory of the classpath root that corresponds to the package
070 * of this class.
071 *
072 * @return The location of the icon resource.
073 */
074 public String getIconResourcePath() {
075 return iconResourcePath;
076 }
077
078 /**
079 * Sets the location of the image to be used as the icon for the splash
080 * screen's frame. The splash screen produced by this class is undecorated,
081 * so the icon will only be visible in the frame's taskbar icon. If the
082 * given path starts with a '/', it is interpreted to be relative to the
083 * root of the runtime classpath. Otherwise it is interpreted to be relative
084 * to the subdirectory of the classpath root that corresponds to the package
085 * of this class.
086 *
087 * @param iconResourcePath The location of the icon resource.
088 */
089 public void setIconResourcePath(String iconResourcePath) {
090 this.iconResourcePath = iconResourcePath;
091 }
092
093 /**
094 * Returns the message source used to resolve localized messages.
095 *
096 * @return The message source, or null.
097 */
098 public MessageSource getMessageSource() {
099 return messageSource;
100 }
101
102 /**
103 * Sets the message source used to resolve localized messages.
104 *
105 * @param messageSource The message source.
106 */
107 public void setMessageSource(MessageSource messageSource) {
108 this.messageSource = messageSource;
109 }
110
111 public final void dispose() {
112
113 if (frame != null) {
114 frame.dispose();
115 frame = null;
116 }
117
118 }
119
120 /**
121 * Creates and displays an undecorated, centered splash screen containing
122 * the component provided by {@link #createContentPane()}. If this instance
123 * has been provided with a {@link MessageSource}, it will be used to
124 * retrieve the splash screen's frame title under the key
125 * {@value #SPLASH_TITLE_KEY}.
126 */
127 public final void splash() {
128 frame = shadowBorder ? new ShadowBorderFrame() : new JFrame();
129 if (isRootFrame())
130 JOptionPane.setRootFrame(frame);
131
132 frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
133 frame.setUndecorated(true);
134
135 frame.setTitle(loadFrameTitle());
136 frame.setIconImage(loadFrameIcon());
137
138 Component content = createContentPane();
139 if (content != null) {
140 frame.getContentPane().add(content);
141 }
142 frame.pack();
143 WindowUtils.centerOnScreen(frame);
144 frame.setVisible(true);
145 }
146
147 /**
148 * Loads the message under the key {@value #SPLASH_TITLE_KEY} if a
149 * {@link MessageSource} has been set on this instance.
150 *
151 * @return The message resource stored under the key
152 * {@value #SPLASH_TITLE_KEY}, or null if no message source has been set.
153 */
154 private String loadFrameTitle() {
155 try {
156 return messageSource == null ? null : messageSource.getMessage(SPLASH_TITLE_KEY, null, null);
157 }
158 catch (NoSuchMessageException e) {
159 return null;
160 }
161 }
162
163 private Image loadFrameIcon() {
164 if (iconResourcePath == null) {
165 return null;
166 }
167
168 URL url = this.getClass().getResource(iconResourcePath);
169 if (url == null) {
170 logger.warn("Unable to locate splash screen in classpath at: " + iconResourcePath);
171 return null;
172 }
173 return Toolkit.getDefaultToolkit().createImage(url);
174 }
175
176 /**
177 * Returns the component to be displayed in the splash screen's main frame.
178 * If the returned value is null the frame for the splash screen will still
179 * be created but will not have any content
180 *
181 * @return The content pane component. Can be null.
182 */
183 protected abstract Component createContentPane();
184
185 /**
186 * Returns whether the splash screen will be rendered with a shadow border.
187 * The shadow border will let the background show through.
188 *
189 * @return whether to show a shadow border or not
190 */
191 public boolean isShadowBorder() {
192 return shadowBorder;
193 }
194
195 /**
196 * Sets whether the splash screen will be rendered with a shadow border. If
197 * <code>true</code> a border will be shown.
198 *
199 * @param shadowBorder Show the shadow border or not
200 */
201 public void setShadowBorder(boolean shadowBorder) {
202 this.shadowBorder = shadowBorder;
203 }
204
205 /**
206 * The frame that is used to display this splashscreen can be used as
207 * rootFrame for other dialogs/windows that need a Frame before the
208 * applicationFrame is created. (eg login).
209 *
210 * @param rootFrame <code>true</code> if the created frame must be set as
211 * rootFrame. Defaults to <code>true</code>.
212 * @see JOptionPane#setRootFrame(java.awt.Frame)
213 */
214 public void setRootFrame(boolean rootFrame) {
215 this.rootFrame = rootFrame;
216 }
217
218 /**
219 * @return <code>true</code> if the created frame must be set as rootFrame.
220 */
221 public boolean isRootFrame() {
222 return this.rootFrame;
223 }
224 }