001/* 002 * Copyright (c) 2003-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-10-28 21:01:43 +0000 (Wed, 28 Oct 2015) $' 007 * '$Revision: 34134 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.gui; 031 032import java.awt.BorderLayout; 033import java.awt.Color; 034import java.awt.Dimension; 035import java.awt.Font; 036import java.awt.FontMetrics; 037import java.awt.Frame; 038import java.awt.Graphics; 039import java.awt.Image; 040import java.awt.MediaTracker; 041import java.awt.Toolkit; 042import java.awt.event.MouseAdapter; 043import java.awt.event.MouseEvent; 044import java.net.URL; 045 046import javax.swing.JLabel; 047import javax.swing.JPanel; 048import javax.swing.JWindow; 049import javax.swing.SwingUtilities; 050 051import org.kepler.build.modules.ModuleTree; 052import org.kepler.configuration.ConfigurationManager; 053import org.kepler.configuration.ConfigurationProperty; 054import org.kepler.util.StatusListener; 055import org.kepler.util.StatusNotifier; 056 057/** 058 * A Splash window. 059 * <p> 060 * 061 * Usage: MyApplication is your application class. Create a Splasher class which 062 * opens the splash window, invokes the main method of your Application class, 063 * and disposes the splash window afterwards. Please note that we want to keep 064 * the Splasher class and the SplashWindow class as small as possible. The less 065 * code and the less classes must be loaded into the JVM to open the splash 066 * screen, the faster it will appear. 067 * 068 * <pre> 069 * class Splasher { 070 * public static void main(String[] args) { 071 * SplashWindow.splash(Startup.class.getResource("splash.gif")); 072 * MyApplication.main(args); 073 * SplashWindow.disposeSplash(); 074 * } 075 * } 076 * </pre> 077 * 078 * @author Werner Randelshofer 079 * @version 2.1 2005-04-03 Revised. 080 */ 081public class SplashWindow extends JWindow implements StatusListener { 082 /** 083 * The current instance of the splash window. (Singleton design pattern). 084 */ 085 private static SplashWindow instance; 086 087 /** 088 * The splash image which is displayed on the splash window. 089 */ 090 private Image image; 091 092 /** 093 * The version number to be displayed in the window. 094 */ 095 private String version; 096 private String versionLabel; 097 098 /** The status message to be displayed on the splash window. */ 099 private String _statusMessage = ""; 100 101 /** The version font. */ 102 private Font _versionFont; 103 104 /** The version color. */ 105 private Color _versionColor; 106 107 /** The status message font. */ 108 private Font _statusFont; 109 110 /** The status message color. */ 111 private Color _statusColor; 112 113 /** The color of the progress bar. */ 114 private Color _progressBarColor; 115 116 /** 117 * Creates a new instance. 118 * 119 * @param parent 120 * the parent of the window. 121 * @param image 122 * the splash image. 123 */ 124 private SplashWindow(Frame parent, Image image) { 125 super(parent); 126 this.image = image; 127 128 // Load the image 129 MediaTracker mt = new MediaTracker(this); 130 mt.addImage(image, 0); 131 132 try { 133 mt.waitForID(0); 134 } catch (InterruptedException ie) { 135 // Ignored 136 } 137 138 // Center the window on the screen 139 int imgWidth = image.getWidth(this); 140 int imgHeight = image.getHeight(this); 141 setSize(imgWidth, imgHeight); 142 143 Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize(); 144 setLocation((screenDim.width - imgWidth) / 2, 145 (screenDim.height - imgHeight) / 2); 146 147 // Users shall be able to close the splash window by 148 // clicking on its display area. This mouse listener 149 // listens for mouse clicks and disposes the splash window. 150 MouseAdapter disposeOnClick = new MouseAdapter() { 151 @Override 152 public void mouseClicked(MouseEvent evt) { 153 dispose(); 154 } 155 }; 156 addMouseListener(disposeOnClick); 157 158 ConfigurationProperty commonProperty = ConfigurationManager 159 .getInstance().getProperty( 160 ConfigurationManager.getModule("common")); 161 162 versionLabel = commonProperty.getProperty("splash.versionLabel") 163 .getValue(); 164 version = commonProperty.getProperty("kepler.version").getValue(); 165 166 _versionFont = new Font("SanSerif", Font.BOLD, 24); 167 // set the color to match the "Kepler" in the image. 168 _versionColor = new Color(28, 115, 84); 169 170 _statusFont = new Font("Dialog", Font.BOLD, 12); 171 _statusColor = Color.BLACK; 172 173 _progressBarColor = _versionColor; 174 175 JPanel content = (JPanel)getContentPane(); 176 content.add(_splashLabel, BorderLayout.CENTER); 177 } 178 179 180 /** 181 * Updates the display area of the window. 182 */ 183 /* 184 @Override 185 public void update(Graphics g) { 186 // Note: Since the paint method is going to draw an 187 // image that covers the complete area of the component we 188 // do not fill the component with its background color 189 // here. This avoids flickering. 190 paint(g); 191 } 192 */ 193 194 private class SplashJLabel extends JLabel { 195 196 /** 197 * Paints the image on the window. 198 */ 199 @Override 200 public void paintComponent(Graphics g) { 201 super.paintComponent(g); 202 203 g.drawImage(image, 0, 0, this); 204 Font saveFont = g.getFont(); 205 Color saveColor = g.getColor(); 206 207 // draw the version string 208 g.setFont(_versionFont); 209 g.setColor(_versionColor); 210 211 int imgWidth = image.getWidth(this); 212 String versionString = versionLabel + " " + version; 213 int x = getHorizontalStartPosition(versionString, imgWidth, g); 214 g.drawString(versionString, x, VERSION_Y); 215 216 // draw the status string 217 g.setFont(_statusFont); 218 g.setColor(_statusColor); 219 x = getHorizontalStartPosition(_statusMessage, imgWidth, g); 220 g.drawString(_statusMessage, x, STATUS_Y); 221 222 g.setColor(_progressBarColor); 223 double percent = (double) _progress / MAX_STEPS; 224 int maxWidth = imgWidth - 46; 225 int width = (int) (maxWidth * percent); 226 if(width > maxWidth) { 227 width = maxWidth; 228 } 229 g.fillRoundRect((imgWidth - width) / 2, PROGRESS_BAR_Y, width, 5, 5, 5); 230 231 g.setFont(saveFont); 232 g.setColor(saveColor); 233 } 234 } 235 236 /** 237 * Calculate the x position at which to start drawing a string to center it 238 * within a given width. 239 * 240 * @param s 241 * the string to be centered 242 * @param w 243 * the width over which the string should be centered 244 * @param g 245 * the graphics context used to draw the string 246 * @return the x position to start drawing the string 247 */ 248 int getHorizontalStartPosition(String s, int width, Graphics g) { 249 FontMetrics fm = g.getFontMetrics(); 250 int xpos = (width - fm.stringWidth(s)) / 2; 251 return xpos; 252 } 253 254 /** 255 * Open's a splash window using the specified image. 256 * 257 * @param image 258 * The splash image. 259 */ 260 public static void splash(Image image) { 261 splash(image, false); 262 } 263 264 /** 265 * 266 */ 267 public static void splash(Image image, boolean reset) { 268 if (reset) { 269 instance = null; 270 } 271 if (instance == null && image != null) { 272 Frame f = new Frame(); 273 274 // Create the splash image 275 instance = new SplashWindow(f, image); 276 277 // Show the window. 278 instance.setVisible(true); 279 280 // listen for startup messages. 281 StatusNotifier.addStatusListener(instance); 282 } 283 } 284 285 /** 286 * Opens a splash window using the specified image. 287 * 288 * @param imageURL 289 * The url of the splash image. 290 */ 291 public static void splash(URL imageURL) { 292 splash(imageURL, false); 293 } 294 295 /** 296 * splash the url. if reset is true, allow the splash to be shown more than 297 * once 298 */ 299 public static void splash(URL imageURL, boolean reset) { 300 if (imageURL != null) { 301 splash(Toolkit.getDefaultToolkit().createImage(imageURL), reset); 302 } 303 } 304 305 /** 306 * Closes the splash window. 307 */ 308 public static void disposeSplash() { 309 if (instance != null) { 310 instance.getOwner().dispose(); 311 instance = null; 312 } 313 } 314 315 /** Update the status text and progress bar. */ 316 @Override 317 public void log(String message) { 318 319 _statusMessage = message; 320 _progress++; 321 322 if(SwingUtilities.isEventDispatchThread()) { 323 _splashLabel.paintImmediately(_splashLabel.getBounds()); 324 } else { 325 _splashLabel.repaint(); 326 } 327 } 328 329 /** The label containing the image, version text, and status. */ 330 private JLabel _splashLabel = new SplashJLabel(); 331 332 /** The number of steps completed during initialization. */ 333 private int _progress = 0; 334 335 /** Maximum number of steps for the progress bar. 336 * This is a rough estimate... 337 */ 338 private static final int MAX_STEPS = 5 + ModuleTree.instance().getModuleList().size() / 2; 339 340 /** Version height offset. */ 341 private static final int VERSION_Y = 200; 342 343 /** Status message height offset. */ 344 private static final int STATUS_Y = VERSION_Y + 40; 345 346 /** Progress bar height offset. */ 347 private static final int PROGRESS_BAR_Y = STATUS_Y + 10; 348 349 350}