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