Path: blob/master/src/demo/share/jfc/SwingSet2/BezierAnimationPanel.java
41152 views
/*1*2* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7*8* - Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10*11* - Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* - Neither the name of Oracle nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS20* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,21* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR22* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR23* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,24* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,25* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR26* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF27* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING28* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/313233import javax.swing.*;34import javax.swing.event.*;35import javax.swing.text.*;36import javax.swing.border.*;37import javax.swing.colorchooser.*;38import javax.swing.filechooser.*;39import javax.accessibility.*;4041import java.awt.*;42import java.awt.font.*;43import java.awt.geom.*;44import java.awt.image.*;45import java.lang.reflect.InvocationTargetException;46import java.awt.event.*;4748/**49* BezierAnimationPanel50*51* @author Jim Graham52* @author Jeff Dinkins (removed dynamic setting changes, made swing friendly)53*/54class BezierAnimationPanel extends JPanel implements Runnable {5556Color backgroundColor = new Color(0, 0, 153);57Color outerColor = new Color(255, 255, 255);58Color gradientColorA = new Color(255, 0, 101);59Color gradientColorB = new Color(255, 255, 0);6061boolean bgChanged = false;6263GradientPaint gradient = null;6465public final int NUMPTS = 6;6667float[] animpts = new float[NUMPTS * 2];6869float[] deltas = new float[NUMPTS * 2];7071float[] staticpts = {7250.0f, 0.0f,73150.0f, 0.0f,74200.0f, 75.0f,75150.0f, 150.0f,7650.0f, 150.0f,770.0f, 75.0f,78};7980float[] movepts = new float[staticpts.length];8182BufferedImage img;8384Rectangle bounds = null;8586Thread anim;8788private final Object lock = new Object();8990/**91* BezierAnimationPanel Constructor92*/93public BezierAnimationPanel() {94addHierarchyListener(95new HierarchyListener() {96public void hierarchyChanged(HierarchyEvent e) {97if(isShowing()) {98start();99} else {100stop();101}102}103}104);105setBackground(getBackgroundColor());106}107108public boolean isOpaque() {109return true;110}111112public Color getGradientColorA() {113return gradientColorA;114}115116public void setGradientColorA(Color c) {117if(c != null) {118gradientColorA = c;119}120}121122public Color getGradientColorB() {123return gradientColorB;124}125126public void setGradientColorB(Color c) {127if(c != null) {128gradientColorB = c;129}130}131132public Color getOuterColor() {133return outerColor;134}135136public void setOuterColor(Color c) {137if(c != null) {138outerColor = c;139}140}141142public Color getBackgroundColor() {143return backgroundColor;144}145146public void setBackgroundColor(Color c) {147if(c != null) {148backgroundColor = c;149setBackground(c);150bgChanged = true;151}152}153154public void start() {155Dimension size = getSize();156for (int i = 0; i < animpts.length; i += 2) {157animpts[i + 0] = (float) (Math.random() * size.width);158animpts[i + 1] = (float) (Math.random() * size.height);159deltas[i + 0] = (float) (Math.random() * 4.0 + 2.0);160deltas[i + 1] = (float) (Math.random() * 4.0 + 2.0);161if (animpts[i + 0] > size.width / 6.0f) {162deltas[i + 0] = -deltas[i + 0];163}164if (animpts[i + 1] > size.height / 6.0f) {165deltas[i + 1] = -deltas[i + 1];166}167}168anim = new Thread(this);169anim.setPriority(Thread.MIN_PRIORITY);170anim.start();171}172173public synchronized void stop() {174anim = null;175notify();176}177178public void animate(float[] pts, float[] deltas, int index, int limit) {179float newpt = pts[index] + deltas[index];180if (newpt <= 0) {181newpt = -newpt;182deltas[index] = (float) (Math.random() * 3.0 + 2.0);183} else if (newpt >= (float) limit) {184newpt = 2.0f * limit - newpt;185deltas[index] = - (float) (Math.random() * 3.0 + 2.0);186}187pts[index] = newpt;188}189190public void run() {191Thread me = Thread.currentThread();192while (getSize().width <= 0) {193try {194anim.sleep(500);195} catch (InterruptedException e) {196return;197}198}199200Graphics2D g2d = null;201Graphics2D BufferG2D = null;202Graphics2D ScreenG2D = null;203BasicStroke solid = new BasicStroke(9.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 9.0f);204GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO);205int rule = AlphaComposite.SRC_OVER;206AlphaComposite opaque = AlphaComposite.SrcOver;207AlphaComposite blend = AlphaComposite.getInstance(rule, 0.9f);208AlphaComposite set = AlphaComposite.Src;209int frame = 0;210int frametmp = 0;211Dimension oldSize = getSize();212Shape clippath = null;213while (anim == me) {214Dimension size = getSize();215if (size.width != oldSize.width || size.height != oldSize.height) {216img = null;217clippath = null;218if (BufferG2D != null) {219BufferG2D.dispose();220BufferG2D = null;221}222if (ScreenG2D != null) {223ScreenG2D.dispose();224ScreenG2D = null;225}226}227oldSize = size;228229if (img == null) {230img = (BufferedImage) createImage(size.width, size.height);231}232233if (BufferG2D == null) {234BufferG2D = img.createGraphics();235BufferG2D.setRenderingHint(RenderingHints.KEY_RENDERING,236RenderingHints.VALUE_RENDER_DEFAULT);237BufferG2D.setClip(clippath);238}239g2d = BufferG2D;240241float[] ctrlpts;242for (int i = 0; i < animpts.length; i += 2) {243animate(animpts, deltas, i + 0, size.width);244animate(animpts, deltas, i + 1, size.height);245}246ctrlpts = animpts;247int len = ctrlpts.length;248gp.reset();249int dir = 0;250float prevx = ctrlpts[len - 2];251float prevy = ctrlpts[len - 1];252float curx = ctrlpts[0];253float cury = ctrlpts[1];254float midx = (curx + prevx) / 2.0f;255float midy = (cury + prevy) / 2.0f;256gp.moveTo(midx, midy);257for (int i = 2; i <= ctrlpts.length; i += 2) {258float x1 = (midx + curx) / 2.0f;259float y1 = (midy + cury) / 2.0f;260prevx = curx;261prevy = cury;262if (i < ctrlpts.length) {263curx = ctrlpts[i + 0];264cury = ctrlpts[i + 1];265} else {266curx = ctrlpts[0];267cury = ctrlpts[1];268}269midx = (curx + prevx) / 2.0f;270midy = (cury + prevy) / 2.0f;271float x2 = (prevx + midx) / 2.0f;272float y2 = (prevy + midy) / 2.0f;273gp.curveTo(x1, y1, x2, y2, midx, midy);274}275gp.closePath();276277synchronized(lock) {278g2d.setComposite(set);279g2d.setBackground(backgroundColor);280g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,281RenderingHints.VALUE_ANTIALIAS_OFF);282283if(bgChanged || bounds == null) {284bounds = new Rectangle(0, 0, getWidth(), getHeight());285bgChanged = false;286}287288// g2d.clearRect(bounds.x-5, bounds.y-5, bounds.x + bounds.width + 5, bounds.y + bounds.height + 5);289g2d.clearRect(0, 0, getWidth(), getHeight());290291g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,292RenderingHints.VALUE_ANTIALIAS_ON);293g2d.setColor(outerColor);294g2d.setComposite(opaque);295g2d.setStroke(solid);296g2d.draw(gp);297g2d.setPaint(gradient);298299if(!bgChanged) {300bounds = gp.getBounds();301} else {302bounds = new Rectangle(0, 0, getWidth(), getHeight());303bgChanged = false;304}305gradient = new GradientPaint(bounds.x, bounds.y, gradientColorA,306bounds.x + bounds.width, bounds.y + bounds.height,307gradientColorB, true);308g2d.setComposite(blend);309g2d.fill(gp);310}311if (g2d == BufferG2D) {312try {313SwingUtilities.invokeAndWait(new Runnable() {314315@Override316public void run() {317repaint();318}319});320} catch (InvocationTargetException | InterruptedException e) {321e.printStackTrace();322}323}324++frame;325}326if (g2d != null) {327g2d.dispose();328}329}330331public void paint(Graphics g) {332synchronized (lock) {333Graphics2D g2d = (Graphics2D) g;334if (img != null) {335g2d.setComposite(AlphaComposite.Src);336g2d.drawImage(img, null, 0, 0);337}338}339}340}341342343