1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package proguard.gui.splash; 22 23 import proguard.gui.SwingUtil; 24 25 import javax.swing.*; 26 import java.awt.*; 27 import java.awt.event.*; 28 import java.lang.reflect.InvocationTargetException; 29 30 /** 31 * This JPanel renders an animated Sprite. 32 * 33 * @author Eric Lafortune 34 */ 35 public class SplashPanel extends JPanel 36 { 37 private final MyAnimator animator = new MyAnimator(); 38 private final MyRepainter repainter = new MyRepainter(); 39 40 private final Sprite sprite; 41 private final double sleepFactor; 42 43 private long startTime = Long.MAX_VALUE; 44 private final long stopTime; 45 46 private volatile Thread animationThread; 47 48 49 /** 50 * Creates a new SplashPanel with the given Sprite, which will be animated 51 * indefinitely. 52 * @param sprite the Sprite that will be animated. 53 * @param processorLoad the fraction of processing time to be spend on 54 * animating the Sprite (between 0 and 1). 55 */ SplashPanel(Sprite sprite, double processorLoad)56 public SplashPanel(Sprite sprite, double processorLoad) 57 { 58 this(sprite, processorLoad, (long)Integer.MAX_VALUE); 59 } 60 61 62 /** 63 * Creates a new SplashPanel with the given Sprite, which will be animated 64 * for a limited period of time. 65 * @param sprite the Sprite that will be animated. 66 * @param processorLoad the fraction of processing time to be spend on 67 * animating the Sprite (between 0 and 1). 68 * @param stopTime the number of milliseconds after which the 69 * animation will be stopped automatically. 70 */ SplashPanel(Sprite sprite, double processorLoad, long stopTime)71 public SplashPanel(Sprite sprite, double processorLoad, long stopTime) 72 { 73 this.sprite = sprite; 74 this.sleepFactor = (1.0-processorLoad) / processorLoad; 75 this.stopTime = stopTime; 76 77 // Restart the animation on a mouse click. 78 addMouseListener(new MouseAdapter() 79 { 80 public void mouseClicked(MouseEvent e) 81 { 82 SplashPanel.this.start(); 83 } 84 }); 85 } 86 87 88 /** 89 * Starts the animation. 90 */ start()91 public void start() 92 { 93 // Go to the beginning of the animation. 94 startTime = System.currentTimeMillis(); 95 96 // Make sure we have an animation thread running. 97 if (animationThread == null) 98 { 99 animationThread = new Thread(animator); 100 animationThread.start(); 101 } 102 } 103 104 105 /** 106 * Stops the animation. 107 */ stop()108 public void stop() 109 { 110 // Go to the end of the animation. 111 startTime = 0L; 112 113 // Let the animation thread stop itself. 114 animationThread = null; 115 116 // Repaint the SplashPanel one last time. 117 try 118 { 119 SwingUtil.invokeAndWait(repainter); 120 } 121 catch (InterruptedException ex) 122 { 123 // Nothing. 124 } 125 catch (InvocationTargetException ex) 126 { 127 // Nothing. 128 } 129 } 130 131 132 // Implementation for JPanel. 133 paintComponent(Graphics graphics)134 public void paintComponent(Graphics graphics) 135 { 136 super.paintComponent(graphics); 137 138 sprite.paint(graphics, System.currentTimeMillis() - startTime); 139 } 140 141 142 /** 143 * This Runnable makes sure its SplashPanel gets repainted regularly, 144 * depending on the targeted processor load. 145 */ 146 private class MyAnimator implements Runnable 147 { run()148 public void run() 149 { 150 try 151 { 152 while (animationThread != null) 153 { 154 // Check if we should stop the animation. 155 long time = System.currentTimeMillis(); 156 if (time > startTime + stopTime) 157 { 158 animationThread = null; 159 } 160 161 // Do a repaint and time it. 162 SwingUtil.invokeAndWait(repainter); 163 164 // Sleep for a proportional while. 165 long repaintTime = System.currentTimeMillis() - time; 166 long sleepTime = (long)(sleepFactor * repaintTime); 167 if (sleepTime < 10L) 168 { 169 sleepTime = 10L; 170 } 171 172 Thread.sleep(sleepTime); 173 } 174 } 175 catch (InterruptedException ex) 176 { 177 // Nothing. 178 } 179 catch (InvocationTargetException ex) 180 { 181 // Nothing. 182 } 183 } 184 } 185 186 187 /** 188 * This Runnable repaints its SplashPanel. 189 */ 190 private class MyRepainter implements Runnable 191 { run()192 public void run() 193 { 194 SplashPanel.this.repaint(); 195 } 196 } 197 198 199 /** 200 * A main method for testing the splash panel. 201 */ main(String[] args)202 public static void main(String[] args) 203 { 204 JFrame frame = new JFrame(); 205 frame.setTitle("Animation"); 206 frame.setSize(800, 600); 207 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 208 Dimension frameSize = frame.getSize(); 209 frame.setLocation((screenSize.width - frameSize.width) / 2, 210 (screenSize.height - frameSize.height) / 2); 211 212 Sprite sprite = 213 new ClipSprite( 214 new ConstantColor(Color.white), 215 new ConstantColor(Color.lightGray), 216 new CircleSprite(true, 217 new LinearInt(200, 600, new SineTiming(2345L, 0L)), 218 new LinearInt(200, 400, new SineTiming(3210L, 0L)), 219 new ConstantInt(150)), 220 new ColorSprite(new ConstantColor(Color.gray), 221 new FontSprite(new ConstantFont(new Font("sansserif", Font.BOLD, 90)), 222 new TextSprite(new ConstantString("ProGuard"), 223 new ConstantInt(200), 224 new ConstantInt(300))))); 225 226 SplashPanel panel = new SplashPanel(sprite, 0.5); 227 panel.setBackground(Color.white); 228 229 frame.getContentPane().add(panel); 230 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 231 frame.setVisible(true); 232 233 panel.start(); 234 } 235 } 236