src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/GradAnim.java
author prr
Mon, 14 May 2018 08:58:32 -0700
changeset 50146 0bb0e464ee76
child 52252 de9486d74a74
permissions -rw-r--r--
8198991: Move Java2D demo to the open repository Reviewed-by: serb, jeff

/*
 *
 * Copyright (c) 2007, 2011, 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.
 */
package java2d.demos.Paint;


import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.Paint;
import java.awt.RadialGradientPaint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java2d.AnimatingControlsSurface;
import java2d.CustomControls;
import javax.swing.JComboBox;


/**
 * GradientPaint animation.
 */
@SuppressWarnings("serial")
public class GradAnim extends AnimatingControlsSurface {

    private static final int BASIC_GRADIENT = 0;
    private static final int LINEAR_GRADIENT = 1;
    private static final int RADIAL_GRADIENT = 2;
    private static final int FOCUS_GRADIENT = 3;
    private static final int MAX_HUE = 256 * 6;
    private animval x1, y1, x2, y2;
    private int hue = (int) (Math.random() * MAX_HUE);
    private int gradientType;

    public GradAnim() {
        setBackground(Color.white);
        setControls(new Component[] { new DemoControls(this) });
        x1 = new animval(0, 300, 2, 10);
        y1 = new animval(0, 300, 2, 10);
        x2 = new animval(0, 300, 2, 10);
        y2 = new animval(0, 300, 2, 10);
        gradientType = BASIC_GRADIENT;
    }

    @Override
    public void reset(int w, int h) {
        x1.newlimits(0, w);
        y1.newlimits(0, h);
        x2.newlimits(0, w);
        y2.newlimits(0, h);
    }

    @Override
    public void step(int w, int h) {
        x1.anim();
        y1.anim();
        x2.anim();
        y2.anim();
        hue = (hue + (int) (Math.random() * 10)) % MAX_HUE;
    }

    public static Color getColor(int hue) {
        int leg = (hue / 256) % 6;
        int step = (hue % 256) * 2;
        int falling = (step < 256) ? 255 : 511 - step;
        int rising = (step < 256) ? step : 255;
        int r, g, b;
        r = g = b = 0;
        switch (leg) {
            case 0:
                r = 255;
                break;
            case 1:
                r = falling;
                g = rising;
                break;
            case 2:
                g = 255;
                break;
            case 3:
                g = falling;
                b = rising;
                break;
            case 4:
                b = 255;
                break;
            case 5:
                b = falling;
                r = rising;
                break;
        }
        return new Color(r, g, b);
    }

    @Override
    public void render(int w, int h, Graphics2D g2) {
        float fx1 = x1.getFlt();
        float fy1 = y1.getFlt();
        float fx2 = x2.getFlt();
        float fy2 = y2.getFlt();

        if ((fx1 == fx2) && (fy1 == fy2)) {
            // just to prevent the points from being coincident
            fx2++;
            fy2++;
        }

        Color c1 = getColor(hue);
        Color c2 = getColor(hue + 256 * 3);
        Paint gp;

        switch (gradientType) {
            case BASIC_GRADIENT:
            default:
                gp = new GradientPaint(fx1, fy1, c1,
                        fx2, fy2, c2,
                        true);
                break;
            case LINEAR_GRADIENT: {
                float[] fractions = new float[] { 0.0f, 0.2f, 1.0f };
                Color c3 = getColor(hue + 256 * 2);
                Color[] colors = new Color[] { c1, c2, c3 };
                gp = new LinearGradientPaint(fx1, fy1,
                        fx2, fy2,
                        fractions, colors,
                        CycleMethod.REFLECT);
            }
            break;

            case RADIAL_GRADIENT: {
                float[] fractions = { 0.0f, 0.2f, 0.8f, 1.0f };
                Color c3 = getColor(hue + 256 * 2);
                Color c4 = getColor(hue + 256 * 4);
                Color[] colors = new Color[] { c1, c2, c3, c4 };
                float radius = (float) Point2D.distance(fx1, fy1, fx2, fy2);
                gp = new RadialGradientPaint(fx1, fy1, radius,
                        fractions, colors,
                        CycleMethod.REFLECT);
            }
            break;

            case FOCUS_GRADIENT: {
                float[] fractions = { 0.0f, 0.2f, 0.8f, 1.0f };
                Color c3 = getColor(hue + 256 * 4);
                Color c4 = getColor(hue + 256 * 2);
                Color[] colors = new Color[] { c1, c2, c3, c4 };
                float radius = (float) Point2D.distance(fx1, fy1, fx2, fy2);
                float max = Math.max(w, h);
                // This function will map the smallest radius to
                // max/10 when the points are next to each other,
                // max when the points are max distance apart,
                // and >max when they are further apart (in which
                // case the focus clipping code in RGP will clip
                // the focus to be inside the radius).
                radius = max * (((radius / max) * 0.9f) + 0.1f);
                gp = new RadialGradientPaint(fx2, fy2, radius,
                        fx1, fy1,
                        fractions, colors,
                        CycleMethod.REPEAT);
            }
            break;
        }
        g2.setPaint(gp);
        g2.fillRect(0, 0, w, h);
        g2.setColor(Color.yellow);
        g2.drawLine(x1.getInt(), y1.getInt(), x2.getInt(), y2.getInt());
    }


    public final class animval {

        float curval;
        float lowval;
        float highval;
        float currate;
        float lowrate;
        float highrate;

        public animval(int lowval, int highval,
                int lowrate, int highrate) {
            this.lowval = lowval;
            this.highval = highval;
            this.lowrate = lowrate;
            this.highrate = highrate;
            this.curval = randval(lowval, highval);
            this.currate = randval(lowrate, highrate);
        }

        public float randval(float low, float high) {
            return (float) (low + Math.random() * (high - low));
        }

        public float getFlt() {
            return curval;
        }

        public int getInt() {
            return (int) curval;
        }

        public void anim() {
            curval += currate;
            clip();
        }

        public void clip() {
            if (curval > highval) {
                curval = highval - (curval - highval);
                if (curval < lowval) {
                    curval = highval;
                }
                currate = -randval(lowrate, highrate);
            } else if (curval < lowval) {
                curval = lowval + (lowval - curval);
                if (curval > highval) {
                    curval = lowval;
                }
                currate = randval(lowrate, highrate);
            }
        }

        public void newlimits(int lowval, int highval) {
            this.lowval = lowval;
            this.highval = highval;
            clip();
        }
    }

    public static void main(String argv[]) {
        createDemoFrame(new GradAnim());
    }


    class DemoControls extends CustomControls implements ActionListener {

        GradAnim demo;
        JComboBox combo;

        @SuppressWarnings("LeakingThisInConstructor")
        public DemoControls(GradAnim demo) {
            super(demo.name);
            this.demo = demo;
            combo = new JComboBox();
            combo.addActionListener(this);
            combo.addItem("2-color GradientPaint");
            combo.addItem("3-color LinearGradientPaint");
            combo.addItem("4-color RadialGradientPaint");
            combo.addItem("4-color RadialGradientPaint with focus");
            combo.setSelectedIndex(0);
            add(combo);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            int index = combo.getSelectedIndex();
            if (index >= 0) {
                demo.gradientType = index;
            }
            if (!demo.animating.running()) {
                demo.repaint();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 41);
        }

        @Override
        @SuppressWarnings("SleepWhileHoldingLock")
        public void run() {
            Thread me = Thread.currentThread();
            while (thread == me) {
                for (int i = 0; i < combo.getItemCount(); i++) {
                    combo.setSelectedIndex(i);
                    try {
                        Thread.sleep(4444);
                    } catch (InterruptedException e) {
                        return;
                    }
                }
            }
            thread = null;
        }
    }
}