• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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