001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.gui.splash;
022:
023: import javax.swing.*;
024: import java.awt.*;
025: import java.awt.event.*;
026: import java.lang.reflect.InvocationTargetException;
027:
028: /**
029: * This JPanel renders an animated Sprite.
030: *
031: * @author Eric Lafortune
032: */
033: public class SplashPanel extends JPanel {
034: private final MyAnimator animator = new MyAnimator();
035: private final MyRepainter repainter = new MyRepainter();
036:
037: private final Sprite sprite;
038: private final double sleepFactor;
039:
040: private long startTime = Long.MAX_VALUE;
041: private final long stopTime;
042:
043: private volatile Thread animationThread;
044:
045: /**
046: * Creates a new SplashPanel with the given Sprite, which will be animated
047: * indefinitely.
048: * @param sprite the Sprite that will be animated.
049: * @param processorLoad the fraction of processing time to be spend on
050: * animating the Sprite (between 0 and 1).
051: */
052: public SplashPanel(Sprite sprite, double processorLoad) {
053: this (sprite, processorLoad, (long) Integer.MAX_VALUE);
054: }
055:
056: /**
057: * Creates a new SplashPanel with the given Sprite, which will be animated
058: * for a limited period of time.
059: * @param sprite the Sprite that will be animated.
060: * @param processorLoad the fraction of processing time to be spend on
061: * animating the Sprite (between 0 and 1).
062: * @param stopTime the number of milliseconds after which the
063: * animation will be stopped automatically.
064: */
065: public SplashPanel(Sprite sprite, double processorLoad,
066: long stopTime) {
067: this .sprite = sprite;
068: this .sleepFactor = (1.0 - processorLoad) / processorLoad;
069: this .stopTime = stopTime;
070:
071: // Restart the animation on a mouse click.
072: addMouseListener(new MouseAdapter() {
073: public void mouseClicked(MouseEvent e) {
074: SplashPanel.this .start();
075: }
076: });
077: }
078:
079: /**
080: * Starts the animation.
081: */
082: public void start() {
083: // Go to the beginning of the animation.
084: startTime = System.currentTimeMillis();
085:
086: // Make sure we have an animation thread running.
087: if (animationThread == null) {
088: animationThread = new Thread(animator);
089: animationThread.start();
090: }
091: }
092:
093: /**
094: * Stops the animation.
095: */
096: public void stop() {
097: // Go to the end of the animation.
098: startTime = 0L;
099:
100: // Let the animation thread stop itself.
101: animationThread = null;
102:
103: // Repaint the SplashPanel one last time.
104: try {
105: SwingUtilities.invokeAndWait(repainter);
106: } catch (InterruptedException ex) {
107: // Nothing.
108: } catch (InvocationTargetException ex) {
109: // Nothing.
110: }
111: }
112:
113: // Implementation for JPanel.
114:
115: public void paintComponent(Graphics graphics) {
116: super .paintComponent(graphics);
117:
118: sprite.paint(graphics, System.currentTimeMillis() - startTime);
119: }
120:
121: /**
122: * This Runnable makes sure its SplashPanel gets repainted regularly,
123: * depending on the targeted processor load.
124: */
125: private class MyAnimator implements Runnable {
126: public void run() {
127: try {
128: while (animationThread != null) {
129: // Check if we should stop the animation.
130: long time = System.currentTimeMillis();
131: if (time > startTime + stopTime) {
132: animationThread = null;
133: }
134:
135: // Do a repaint and time it.
136: SwingUtilities.invokeAndWait(repainter);
137:
138: // Sleep for a proportional while.
139: long repaintTime = System.currentTimeMillis()
140: - time;
141: long sleepTime = (long) (sleepFactor * repaintTime);
142: if (sleepTime < 10L) {
143: sleepTime = 10L;
144: }
145:
146: Thread.sleep(sleepTime);
147: }
148: } catch (InterruptedException ex) {
149: // Nothing.
150: } catch (InvocationTargetException ex) {
151: // Nothing.
152: }
153: }
154: }
155:
156: /**
157: * This Runnable repaints its SplashPanel.
158: */
159: private class MyRepainter implements Runnable {
160: public void run() {
161: SplashPanel.this .repaint();
162: }
163: }
164:
165: /**
166: * A main method for testing the splash panel.
167: */
168: public static void main(String[] args) {
169: JFrame frame = new JFrame();
170: frame.setTitle("Animation");
171: frame.setSize(800, 600);
172: Dimension screenSize = Toolkit.getDefaultToolkit()
173: .getScreenSize();
174: Dimension frameSize = frame.getSize();
175: frame.setLocation((screenSize.width - frameSize.width) / 2,
176: (screenSize.height - frameSize.height) / 2);
177:
178: Sprite sprite = new ClipSprite(new ConstantColor(Color.white),
179: new ConstantColor(Color.lightGray), new CircleSprite(
180: true, new LinearInt(200, 600, new SineTiming(
181: 2345L, 0L)), new LinearInt(200, 400,
182: new SineTiming(3210L, 0L)),
183: new ConstantInt(150)), new ColorSprite(
184: new ConstantColor(Color.gray), new FontSprite(
185: new ConstantFont(new Font("sansserif",
186: Font.BOLD, 90)),
187: new TextSprite(new ConstantString(
188: "ProGuard"), new ConstantInt(
189: 200), new ConstantInt(300)))));
190:
191: SplashPanel panel = new SplashPanel(sprite, 0.5);
192: panel.setBackground(Color.white);
193:
194: frame.getContentPane().add(panel);
195: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
196: frame.setVisible(true);
197:
198: panel.start();
199: }
200: }
|