Home | History | Annotate | Download | only in splash
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 Eric Lafortune (eric (at) 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      */
     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      */
     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      */
     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      */
    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 
    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     {
    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     {
    192         public void run()
    193         {
    194             SplashPanel.this.repaint();
    195         }
    196     }
    197 
    198 
    199     /**
    200      * A main method for testing the splash panel.
    201      */
    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