| /* |
| * |
| * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Oracle nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| import javax.swing.*; |
| import javax.swing.event.*; |
| import javax.swing.text.*; |
| import javax.swing.border.*; |
| import javax.swing.colorchooser.*; |
| import javax.swing.filechooser.*; |
| import javax.accessibility.*; |
| |
| import java.awt.*; |
| import java.awt.font.*; |
| import java.awt.geom.*; |
| import java.awt.image.*; |
| import java.lang.reflect.InvocationTargetException; |
| import java.awt.event.*; |
| |
| /** |
| * BezierAnimationPanel |
| * |
| * @author Jim Graham |
| * @author Jeff Dinkins (removed dynamic setting changes, made swing friendly) |
| */ |
| class BezierAnimationPanel extends JPanel implements Runnable { |
| |
| Color backgroundColor = new Color(0, 0, 153); |
| Color outerColor = new Color(255, 255, 255); |
| Color gradientColorA = new Color(255, 0, 101); |
| Color gradientColorB = new Color(255, 255, 0); |
| |
| boolean bgChanged = false; |
| |
| GradientPaint gradient = null; |
| |
| public final int NUMPTS = 6; |
| |
| float animpts[] = new float[NUMPTS * 2]; |
| |
| float deltas[] = new float[NUMPTS * 2]; |
| |
| float staticpts[] = { |
| 50.0f, 0.0f, |
| 150.0f, 0.0f, |
| 200.0f, 75.0f, |
| 150.0f, 150.0f, |
| 50.0f, 150.0f, |
| 0.0f, 75.0f, |
| }; |
| |
| float movepts[] = new float[staticpts.length]; |
| |
| BufferedImage img; |
| |
| Rectangle bounds = null; |
| |
| Thread anim; |
| |
| private final Object lock = new Object(); |
| |
| /** |
| * BezierAnimationPanel Constructor |
| */ |
| public BezierAnimationPanel() { |
| addHierarchyListener( |
| new HierarchyListener() { |
| public void hierarchyChanged(HierarchyEvent e) { |
| if(isShowing()) { |
| start(); |
| } else { |
| stop(); |
| } |
| } |
| } |
| ); |
| setBackground(getBackgroundColor()); |
| } |
| |
| public boolean isOpaque() { |
| return true; |
| } |
| |
| public Color getGradientColorA() { |
| return gradientColorA; |
| } |
| |
| public void setGradientColorA(Color c) { |
| if(c != null) { |
| gradientColorA = c; |
| } |
| } |
| |
| public Color getGradientColorB() { |
| return gradientColorB; |
| } |
| |
| public void setGradientColorB(Color c) { |
| if(c != null) { |
| gradientColorB = c; |
| } |
| } |
| |
| public Color getOuterColor() { |
| return outerColor; |
| } |
| |
| public void setOuterColor(Color c) { |
| if(c != null) { |
| outerColor = c; |
| } |
| } |
| |
| public Color getBackgroundColor() { |
| return backgroundColor; |
| } |
| |
| public void setBackgroundColor(Color c) { |
| if(c != null) { |
| backgroundColor = c; |
| setBackground(c); |
| bgChanged = true; |
| } |
| } |
| |
| public void start() { |
| Dimension size = getSize(); |
| for (int i = 0; i < animpts.length; i += 2) { |
| animpts[i + 0] = (float) (Math.random() * size.width); |
| animpts[i + 1] = (float) (Math.random() * size.height); |
| deltas[i + 0] = (float) (Math.random() * 4.0 + 2.0); |
| deltas[i + 1] = (float) (Math.random() * 4.0 + 2.0); |
| if (animpts[i + 0] > size.width / 6.0f) { |
| deltas[i + 0] = -deltas[i + 0]; |
| } |
| if (animpts[i + 1] > size.height / 6.0f) { |
| deltas[i + 1] = -deltas[i + 1]; |
| } |
| } |
| anim = new Thread(this); |
| anim.setPriority(Thread.MIN_PRIORITY); |
| anim.start(); |
| } |
| |
| public synchronized void stop() { |
| anim = null; |
| notify(); |
| } |
| |
| public void animate(float[] pts, float[] deltas, int index, int limit) { |
| float newpt = pts[index] + deltas[index]; |
| if (newpt <= 0) { |
| newpt = -newpt; |
| deltas[index] = (float) (Math.random() * 3.0 + 2.0); |
| } else if (newpt >= (float) limit) { |
| newpt = 2.0f * limit - newpt; |
| deltas[index] = - (float) (Math.random() * 3.0 + 2.0); |
| } |
| pts[index] = newpt; |
| } |
| |
| public void run() { |
| Thread me = Thread.currentThread(); |
| while (getSize().width <= 0) { |
| try { |
| anim.sleep(500); |
| } catch (InterruptedException e) { |
| return; |
| } |
| } |
| |
| Graphics2D g2d = null; |
| Graphics2D BufferG2D = null; |
| Graphics2D ScreenG2D = null; |
| BasicStroke solid = new BasicStroke(9.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 9.0f); |
| GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO); |
| int rule = AlphaComposite.SRC_OVER; |
| AlphaComposite opaque = AlphaComposite.SrcOver; |
| AlphaComposite blend = AlphaComposite.getInstance(rule, 0.9f); |
| AlphaComposite set = AlphaComposite.Src; |
| int frame = 0; |
| int frametmp = 0; |
| Dimension oldSize = getSize(); |
| Shape clippath = null; |
| while (anim == me) { |
| Dimension size = getSize(); |
| if (size.width != oldSize.width || size.height != oldSize.height) { |
| img = null; |
| clippath = null; |
| if (BufferG2D != null) { |
| BufferG2D.dispose(); |
| BufferG2D = null; |
| } |
| if (ScreenG2D != null) { |
| ScreenG2D.dispose(); |
| ScreenG2D = null; |
| } |
| } |
| oldSize = size; |
| |
| if (img == null) { |
| img = (BufferedImage) createImage(size.width, size.height); |
| } |
| |
| if (BufferG2D == null) { |
| BufferG2D = img.createGraphics(); |
| BufferG2D.setRenderingHint(RenderingHints.KEY_RENDERING, |
| RenderingHints.VALUE_RENDER_DEFAULT); |
| BufferG2D.setClip(clippath); |
| } |
| g2d = BufferG2D; |
| |
| float[] ctrlpts; |
| for (int i = 0; i < animpts.length; i += 2) { |
| animate(animpts, deltas, i + 0, size.width); |
| animate(animpts, deltas, i + 1, size.height); |
| } |
| ctrlpts = animpts; |
| int len = ctrlpts.length; |
| gp.reset(); |
| int dir = 0; |
| float prevx = ctrlpts[len - 2]; |
| float prevy = ctrlpts[len - 1]; |
| float curx = ctrlpts[0]; |
| float cury = ctrlpts[1]; |
| float midx = (curx + prevx) / 2.0f; |
| float midy = (cury + prevy) / 2.0f; |
| gp.moveTo(midx, midy); |
| for (int i = 2; i <= ctrlpts.length; i += 2) { |
| float x1 = (midx + curx) / 2.0f; |
| float y1 = (midy + cury) / 2.0f; |
| prevx = curx; |
| prevy = cury; |
| if (i < ctrlpts.length) { |
| curx = ctrlpts[i + 0]; |
| cury = ctrlpts[i + 1]; |
| } else { |
| curx = ctrlpts[0]; |
| cury = ctrlpts[1]; |
| } |
| midx = (curx + prevx) / 2.0f; |
| midy = (cury + prevy) / 2.0f; |
| float x2 = (prevx + midx) / 2.0f; |
| float y2 = (prevy + midy) / 2.0f; |
| gp.curveTo(x1, y1, x2, y2, midx, midy); |
| } |
| gp.closePath(); |
| |
| synchronized(lock) { |
| g2d.setComposite(set); |
| g2d.setBackground(backgroundColor); |
| g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, |
| RenderingHints.VALUE_ANTIALIAS_OFF); |
| |
| if(bgChanged || bounds == null) { |
| bounds = new Rectangle(0, 0, getWidth(), getHeight()); |
| bgChanged = false; |
| } |
| |
| // g2d.clearRect(bounds.x-5, bounds.y-5, bounds.x + bounds.width + 5, bounds.y + bounds.height + 5); |
| g2d.clearRect(0, 0, getWidth(), getHeight()); |
| |
| g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, |
| RenderingHints.VALUE_ANTIALIAS_ON); |
| g2d.setColor(outerColor); |
| g2d.setComposite(opaque); |
| g2d.setStroke(solid); |
| g2d.draw(gp); |
| g2d.setPaint(gradient); |
| |
| if(!bgChanged) { |
| bounds = gp.getBounds(); |
| } else { |
| bounds = new Rectangle(0, 0, getWidth(), getHeight()); |
| bgChanged = false; |
| } |
| gradient = new GradientPaint(bounds.x, bounds.y, gradientColorA, |
| bounds.x + bounds.width, bounds.y + bounds.height, |
| gradientColorB, true); |
| g2d.setComposite(blend); |
| g2d.fill(gp); |
| } |
| if (g2d == BufferG2D) { |
| try { |
| SwingUtilities.invokeAndWait(new Runnable() { |
| |
| @Override |
| public void run() { |
| repaint(); |
| } |
| }); |
| } catch (InvocationTargetException | InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| ++frame; |
| } |
| if (g2d != null) { |
| g2d.dispose(); |
| } |
| } |
| |
| public void paint(Graphics g) { |
| synchronized (lock) { |
| Graphics2D g2d = (Graphics2D) g; |
| if (img != null) { |
| g2d.setComposite(AlphaComposite.Src); |
| g2d.drawImage(img, null, 0, 0); |
| } |
| } |
| } |
| } |