1
36
37
40
41
42 import javax.swing.*;
43 import javax.swing.event.*;
44 import javax.swing.text.*;
45 import javax.swing.border.*;
46 import javax.swing.colorchooser.*;
47 import javax.swing.filechooser.*;
48 import javax.accessibility.*;
49
50 import java.awt.*;
51 import java.awt.font.*;
52 import java.awt.geom.*;
53 import java.awt.image.*;
54 import java.awt.event.*;
55
56
63 class BezierAnimationPanel extends JPanel implements Runnable {
64
65 Color backgroundColor = new Color(0, 0, 153);
66 Color outerColor = new Color(255, 255, 255);
67 Color gradientColorA = new Color(255, 0, 101);
68 Color gradientColorB = new Color(255, 255, 0);
69
70 boolean bgChanged = false;
71
72 GradientPaint gradient = null;
73
74 public final int NUMPTS = 6;
75
76 float animpts[] = new float[NUMPTS * 2];
77
78 float deltas[] = new float[NUMPTS * 2];
79
80 float staticpts[] = {
81 50.0f, 0.0f,
82 150.0f, 0.0f,
83 200.0f, 75.0f,
84 150.0f, 150.0f,
85 50.0f, 150.0f,
86 0.0f, 75.0f,
87 };
88
89 float movepts[] = new float[staticpts.length];
90
91 BufferedImage img;
92
93 Rectangle bounds = null;
94
95 Thread anim;
96
97
100 public BezierAnimationPanel() {
101 addHierarchyListener(
102 new HierarchyListener() {
103 public void hierarchyChanged(HierarchyEvent e) {
104 if(isShowing()) {
105 start();
106 } else {
107 stop();
108 }
109 }
110 }
111 );
112 setBackground(getBackgroundColor());
113 }
114
115 public boolean isOpaque() {
116 return true;
117 }
118
119 public Color getGradientColorA() {
120 return gradientColorA;
121 }
122
123 public void setGradientColorA(Color c) {
124 if(c != null) {
125 gradientColorA = c;
126 }
127 }
128
129 public Color getGradientColorB() {
130 return gradientColorB;
131 }
132
133 public void setGradientColorB(Color c) {
134 if(c != null) {
135 gradientColorB = c;
136 }
137 }
138
139 public Color getOuterColor() {
140 return outerColor;
141 }
142
143 public void setOuterColor(Color c) {
144 if(c != null) {
145 outerColor = c;
146 }
147 }
148
149 public Color getBackgroundColor() {
150 return backgroundColor;
151 }
152
153 public void setBackgroundColor(Color c) {
154 if(c != null) {
155 backgroundColor = c;
156 setBackground(c);
157 bgChanged = true;
158 }
159 }
160
161 public void start() {
162 Dimension size = getSize();
163 for (int i = 0; i < animpts.length; i += 2) {
164 animpts[i + 0] = (float) (Math.random() * size.width);
165 animpts[i + 1] = (float) (Math.random() * size.height);
166 deltas[i + 0] = (float) (Math.random() * 4.0 + 2.0);
167 deltas[i + 1] = (float) (Math.random() * 4.0 + 2.0);
168 if (animpts[i + 0] > size.width / 6.0f) {
169 deltas[i + 0] = -deltas[i + 0];
170 }
171 if (animpts[i + 1] > size.height / 6.0f) {
172 deltas[i + 1] = -deltas[i + 1];
173 }
174 }
175 anim = new Thread(this);
176 anim.setPriority(Thread.MIN_PRIORITY);
177 anim.start();
178 }
179
180 public synchronized void stop() {
181 anim = null;
182 notify();
183 }
184
185 public void animate(float[] pts, float[] deltas, int index, int limit) {
186 float newpt = pts[index] + deltas[index];
187 if (newpt <= 0) {
188 newpt = -newpt;
189 deltas[index] = (float) (Math.random() * 3.0 + 2.0);
190 } else if (newpt >= (float) limit) {
191 newpt = 2.0f * limit - newpt;
192 deltas[index] = - (float) (Math.random() * 3.0 + 2.0);
193 }
194 pts[index] = newpt;
195 }
196
197 public void run() {
198 Thread me = Thread.currentThread();
199 while (getSize().width <= 0) {
200 try {
201 anim.sleep(500);
202 } catch (InterruptedException e) {
203 return;
204 }
205 }
206
207 Graphics2D g2d = null;
208 Graphics2D BufferG2D = null;
209 Graphics2D ScreenG2D = null;
210 BasicStroke solid = new BasicStroke(9.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 9.0f);
211 GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO);
212 int rule = AlphaComposite.SRC_OVER;
213 AlphaComposite opaque = AlphaComposite.SrcOver;
214 AlphaComposite blend = AlphaComposite.getInstance(rule, 0.9f);
215 AlphaComposite set = AlphaComposite.Src;
216 int frame = 0;
217 int frametmp = 0;
218 Dimension oldSize = getSize();
219 Shape clippath = null;
220 while (anim == me) {
221 Dimension size = getSize();
222 if (size.width != oldSize.width || size.height != oldSize.height) {
223 img = null;
224 clippath = null;
225 if (BufferG2D != null) {
226 BufferG2D.dispose();
227 BufferG2D = null;
228 }
229 if (ScreenG2D != null) {
230 ScreenG2D.dispose();
231 ScreenG2D = null;
232 }
233 }
234 oldSize = size;
235
236 if (img == null) {
237 img = (BufferedImage) createImage(size.width, size.height);
238 }
239
240 if (BufferG2D == null) {
241 BufferG2D = img.createGraphics();
242 BufferG2D.setRenderingHint(RenderingHints.KEY_RENDERING,
243 RenderingHints.VALUE_RENDER_DEFAULT);
244 BufferG2D.setClip(clippath);
245 }
246 g2d = BufferG2D;
247
248 float[] ctrlpts;
249 for (int i = 0; i < animpts.length; i += 2) {
250 animate(animpts, deltas, i + 0, size.width);
251 animate(animpts, deltas, i + 1, size.height);
252 }
253 ctrlpts = animpts;
254 int len = ctrlpts.length;
255 gp.reset();
256 int dir = 0;
257 float prevx = ctrlpts[len - 2];
258 float prevy = ctrlpts[len - 1];
259 float curx = ctrlpts[0];
260 float cury = ctrlpts[1];
261 float midx = (curx + prevx) / 2.0f;
262 float midy = (cury + prevy) / 2.0f;
263 gp.moveTo(midx, midy);
264 for (int i = 2; i <= ctrlpts.length; i += 2) {
265 float x1 = (midx + curx) / 2.0f;
266 float y1 = (midy + cury) / 2.0f;
267 prevx = curx;
268 prevy = cury;
269 if (i < ctrlpts.length) {
270 curx = ctrlpts[i + 0];
271 cury = ctrlpts[i + 1];
272 } else {
273 curx = ctrlpts[0];
274 cury = ctrlpts[1];
275 }
276 midx = (curx + prevx) / 2.0f;
277 midy = (cury + prevy) / 2.0f;
278 float x2 = (prevx + midx) / 2.0f;
279 float y2 = (prevy + midy) / 2.0f;
280 gp.curveTo(x1, y1, x2, y2, midx, midy);
281 }
282 gp.closePath();
283
284 g2d.setComposite(set);
285 g2d.setBackground(backgroundColor);
286 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
287 RenderingHints.VALUE_ANTIALIAS_OFF);
288
289 if(bgChanged || bounds == null) {
290 bounds = new Rectangle(0, 0, getWidth(), getHeight());
291 bgChanged = false;
292 }
293 g2d.clearRect(0, 0, getWidth(), getHeight());
295
296 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
297 RenderingHints.VALUE_ANTIALIAS_ON);
298 g2d.setColor(outerColor);
299 g2d.setComposite(opaque);
300 g2d.setStroke(solid);
301 g2d.draw(gp);
302 g2d.setPaint(gradient);
303
304 if(!bgChanged) {
305 bounds = gp.getBounds();
306 } else {
307 bounds = new Rectangle(0, 0, getWidth(), getHeight());
308 bgChanged = false;
309 }
310 gradient = new GradientPaint(bounds.x, bounds.y, gradientColorA,
311 bounds.x + bounds.width, bounds.y + bounds.height,
312 gradientColorB, true);
313 g2d.setComposite(blend);
314 g2d.fill(gp);
315
316 if (g2d == BufferG2D) {
317 repaint();
318 }
319 ++frame;
320 Thread.yield();
321 }
322 if (g2d != null) {
323 g2d.dispose();
324 }
325 }
326
327 public void paint(Graphics g) {
328 synchronized (this) {
329 Graphics2D g2d = (Graphics2D) g;
330 if (img != null) {
331 int imgw = img.getWidth();
332 int imgh = img.getHeight();
333 g2d.setComposite(AlphaComposite.Src);
334 g2d.drawImage(img, null, 0, 0);
335 }
336 }
337 }
338 }
339