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 }