1   /*
2    * Copyright (c) 2003 Sun Microsystems, Inc. All  Rights Reserved.
3    * 
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions
6    * are met:
7    * 
8    * -Redistributions of source code must retain the above copyright
9    *  notice, this list of conditions and the following disclaimer.
10   * 
11   * -Redistribution in binary form must reproduct the above copyright
12   *  notice, this list of conditions and the following disclaimer in
13   *  the documentation and/or other materials provided with the distribution.
14   * 
15   * Neither the name of Sun Microsystems, Inc. or the names of contributors
16   * may be used to endorse or promote products derived from this software
17   * without specific prior written permission.
18   * 
19   * This software is provided "AS IS," without a warranty of any kind. ALL
20   * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
21   * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
22   * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT
23   * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
24   * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
25   * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
26   * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
27   * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
28   * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
29   * IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
30   * 
31   * You acknowledge that Software is not designed, licensed or intended for
32   * use in the design, construction, operation or maintenance of any nuclear
33   * facility.
34   */
35  
36  /*
37   * @(#)BezierAnimationPanel.java    1.12 03/03/12
38   */
39  
40  
41  import javax.swing.*;
42  import javax.swing.event.*;
43  import javax.swing.text.*;
44  import javax.swing.border.*;
45  import javax.swing.colorchooser.*;
46  import javax.swing.filechooser.*;
47  import javax.accessibility.*;
48   
49  import java.awt.*;
50  import java.awt.font.*;
51  import java.awt.geom.*;
52  import java.awt.image.*;
53  import java.awt.event.*;
54  
55  /**
56   * BezierAnimationPanel
57   *
58   * @version 1.12 03/12/03
59   * @author Jim Graham
60   * @author Jeff Dinkins (removed dynamic setting changes, made swing friendly)
61   */
62  class BezierAnimationPanel extends JPanel implements Runnable {
63  
64      Color backgroundColor =  new Color(0,     0, 153);
65      Color outerColor      =  new Color(255, 255, 255);
66      Color gradientColorA  =  new Color(255,   0, 101);
67      Color gradientColorB  =  new Color(255, 255,   0);
68  
69      boolean bgChanged = false;
70  
71      GradientPaint gradient = null;
72      
73      public final int NUMPTS = 6;
74  
75      float animpts[] = new float[NUMPTS * 2];
76  
77      float deltas[] = new float[NUMPTS * 2];
78  
79      float staticpts[] = {
80       50.0f,   0.0f,
81      150.0f,   0.0f,
82      200.0f,  75.0f,
83      150.0f, 150.0f,
84       50.0f, 150.0f,
85        0.0f,  75.0f,
86      };
87  
88      float movepts[] = new float[staticpts.length];
89  
90      BufferedImage img;
91  
92      Rectangle bounds = null;
93  
94      Thread anim;
95  
96      /**
97       * BezierAnimationPanel Constructor
98       */
99      public BezierAnimationPanel() {
100     addHierarchyListener(
101         new HierarchyListener() {
102            public void hierarchyChanged(HierarchyEvent e) {
103            if(isShowing()) {
104                start();
105            } else {
106                stop();
107            }
108            }
109        }
110     );
111     setBackground(getBackgroundColor());
112     }
113 
114     public boolean isOpaque() {
115         return true;
116     }
117 
118     public Color getGradientColorA() {
119     return gradientColorA;
120     }
121 
122     public void setGradientColorA(Color c) {
123     if(c != null) {
124         gradientColorA = c;
125     }
126     }
127 
128     public Color getGradientColorB() {
129     return gradientColorB;
130     }
131 
132     public void setGradientColorB(Color c) {
133     if(c != null) {
134         gradientColorB = c;
135     }
136     }
137 
138     public Color getOuterColor() {
139     return outerColor;
140     }
141 
142     public void setOuterColor(Color c) {
143     if(c != null) {
144         outerColor = c;
145     }
146     }
147 
148     public Color getBackgroundColor() {
149     return backgroundColor;
150     }
151 
152     public void setBackgroundColor(Color c) {
153     if(c != null) {
154         backgroundColor = c;
155         setBackground(c);
156         bgChanged = true;
157     }
158     }
159 
160     public void start() {
161     Dimension size = getSize();
162     for (int i = 0; i < animpts.length; i += 2) {
163         animpts[i + 0] = (float) (Math.random() * size.width);
164         animpts[i + 1] = (float) (Math.random() * size.height);
165         deltas[i + 0] = (float) (Math.random() * 4.0 + 2.0);
166         deltas[i + 1] = (float) (Math.random() * 4.0 + 2.0);
167         if (animpts[i + 0] > size.width / 6.0f) {
168         deltas[i + 0] = -deltas[i + 0];
169         }
170         if (animpts[i + 1] > size.height / 6.0f) {
171         deltas[i + 1] = -deltas[i + 1];
172         }
173     }
174     anim = new Thread(this);
175     anim.setPriority(Thread.MIN_PRIORITY);
176     anim.start();
177     }
178 
179     public synchronized void stop() {
180     anim = null;
181     notify();
182     }
183 
184     public void animate(float[] pts, float[] deltas, int index, int limit) {
185     float newpt = pts[index] + deltas[index];
186     if (newpt <= 0) {
187         newpt = -newpt;
188         deltas[index] = (float) (Math.random() * 3.0 + 2.0);
189     } else if (newpt >= (float) limit) {
190         newpt = 2.0f * limit - newpt;
191         deltas[index] = - (float) (Math.random() * 3.0 + 2.0);
192     }
193     pts[index] = newpt;
194     }
195 
196     public void run() {
197     Thread me = Thread.currentThread();
198     while (getSize().width <= 0) {
199         try {
200         anim.sleep(500);
201         } catch (InterruptedException e) {
202         return;
203         }
204         }
205          
206     Graphics2D g2d = null;
207     Graphics2D BufferG2D = null;
208     Graphics2D ScreenG2D = null;
209     BasicStroke solid = new BasicStroke(9.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 9.0f);
210     GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO);
211     int rule = AlphaComposite.SRC_OVER;
212     AlphaComposite opaque = AlphaComposite.SrcOver;
213     AlphaComposite blend = AlphaComposite.getInstance(rule, 0.9f);
214     AlphaComposite set = AlphaComposite.Src;
215     int frame = 0;
216     int frametmp = 0;
217     Dimension oldSize = getSize();
218     Shape clippath = null;
219     while (anim == me) {
220         Dimension size = getSize();
221         if (size.width != oldSize.width || size.height != oldSize.height) {
222         img = null;
223         clippath = null;
224         if (BufferG2D != null) {
225             BufferG2D.dispose();
226             BufferG2D = null;
227         }
228         if (ScreenG2D != null) {
229             ScreenG2D.dispose();
230             ScreenG2D = null;
231         }
232         }
233         oldSize = size;
234 
235         if (img == null) {
236         img = (BufferedImage) createImage(size.width, size.height);
237         }
238 
239         if (BufferG2D == null) {
240         BufferG2D = img.createGraphics();
241         BufferG2D.setRenderingHint(RenderingHints.KEY_RENDERING,
242                        RenderingHints.VALUE_RENDER_DEFAULT);
243         BufferG2D.setClip(clippath);
244         }
245         g2d = BufferG2D;
246 
247         float[] ctrlpts;
248         for (int i = 0; i < animpts.length; i += 2) {
249         animate(animpts, deltas, i + 0, size.width);
250         animate(animpts, deltas, i + 1, size.height);
251         }
252         ctrlpts = animpts;
253         int len = ctrlpts.length;
254         gp.reset();
255         int dir = 0;
256         float prevx = ctrlpts[len - 2];
257         float prevy = ctrlpts[len - 1];
258         float curx = ctrlpts[0];
259         float cury = ctrlpts[1];
260         float midx = (curx + prevx) / 2.0f;
261         float midy = (cury + prevy) / 2.0f;
262         gp.moveTo(midx, midy);
263         for (int i = 2; i <= ctrlpts.length; i += 2) {
264         float x1 = (midx + curx) / 2.0f;
265         float y1 = (midy + cury) / 2.0f;
266         prevx = curx;
267         prevy = cury;
268         if (i < ctrlpts.length) {
269             curx = ctrlpts[i + 0];
270             cury = ctrlpts[i + 1];
271         } else {
272             curx = ctrlpts[0];
273             cury = ctrlpts[1];
274         }
275         midx = (curx + prevx) / 2.0f;
276         midy = (cury + prevy) / 2.0f;
277         float x2 = (prevx + midx) / 2.0f;
278         float y2 = (prevy + midy) / 2.0f;
279         gp.curveTo(x1, y1, x2, y2, midx, midy);
280         }
281         gp.closePath();
282 
283         g2d.setComposite(set);
284         g2d.setBackground(backgroundColor);
285         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
286                  RenderingHints.VALUE_ANTIALIAS_OFF);
287 
288         if(bgChanged || bounds == null) {
289         bounds = new Rectangle(0, 0, getWidth(), getHeight());
290         bgChanged = false;
291         }
292         // g2d.clearRect(bounds.x-5, bounds.y-5, bounds.x + bounds.width + 5, bounds.y + bounds.height + 5);
293         g2d.clearRect(0, 0, getWidth(), getHeight());
294 
295         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
296                  RenderingHints.VALUE_ANTIALIAS_ON);
297         g2d.setColor(outerColor);
298         g2d.setComposite(opaque);
299         g2d.setStroke(solid);
300         g2d.draw(gp);
301         g2d.setPaint(gradient);
302 
303         if(!bgChanged) {
304         bounds = gp.getBounds();
305         } else {
306         bounds = new Rectangle(0, 0, getWidth(), getHeight());
307         bgChanged = false;
308         }
309         gradient = new GradientPaint(bounds.x, bounds.y, gradientColorA,
310                      bounds.x + bounds.width, bounds.y + bounds.height,
311                      gradientColorB, true);
312         g2d.setComposite(blend);
313         g2d.fill(gp);
314 
315         if (g2d == BufferG2D) {
316         repaint();
317         }
318         ++frame;
319         Thread.yield();
320     }
321     if (g2d != null) {  
322         g2d.dispose();
323     }
324     }
325 
326     public void paint(Graphics g) {
327     synchronized (this) {
328        Graphics2D g2d = (Graphics2D) g;
329        if (img != null) {
330            int imgw = img.getWidth();
331            int imgh = img.getHeight();
332            g2d.setComposite(AlphaComposite.Src);
333            g2d.drawImage(img, null, 0, 0);
334        }
335         }
336     }
337 }
338