    001/* ===========================================================
    002 * Orson Charts : a 3D chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C)opyright 2013-2022, by David Gilbert.  All rights reserved.
    006 *
    007 * https://github.com/jfree/orson-charts
    008 *
    009 * This program is free software: you can redistribute it and/or modify
    010 * it under the terms of the GNU General Public License as published by
    011 * the Free Software Foundation, either version 3 of the License, or
    012 * (at your option) any later version.
    013 *
    014 * This program is distributed in the hope that it will be useful,
    015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    017 * GNU General Public License for more details.
    018 *
    019 * You should have received a copy of the GNU General Public License
    020 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    021 *
    022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    023 * Other names may be trademarks of their respective owners.]
    024 *
    025 * If you do not wish to be bound by the terms of the GPL, an alternative
    026 * commercial license can be purchased.  For details, please see visit the
    027 * Orson Charts home page:
    028 *
    029 * http://www.object-refinery.com/orsoncharts/index.html
    030 *
    031 */
    032
    033package org.jfree.chart3d.table;
    034
    035import java.awt.Color;
    036import java.awt.GradientPaint;
    037import java.awt.Graphics2D;
    038import java.awt.Paint;
    039import java.awt.geom.Point2D;
    040import java.awt.geom.Rectangle2D;
    041import java.io.Serializable;
    042
    043import org.jfree.chart3d.TitleAnchor;
    044import org.jfree.chart3d.graphics2d.Anchor2D;
    045import org.jfree.chart3d.internal.Args;
    046import org.jfree.chart3d.internal.ObjectUtils;
    047
    048/**
    049 * A {@link RectanglePainter} that can fill a rectangle with a gradient (the
    050 * gradient is generated using anchor points to fit any size rectangle on
    051 * demand).  Instances of this class are immutable.
    052 * <br><br>
    053 * NOTE: This class is serializable, but the serialization format is subject
    054 * to change in future releases and should not be relied upon for persisting
    055 * instances of this class.
    056 */
    057@SuppressWarnings("serial")
    058public final class GradientRectanglePainter implements RectanglePainter,
    059        Serializable {
    060
    061    /** The first color for the gradient. */
    062    private final Color color1;
    063
    064    /** The anchor point used to find the starting point for the gradient. */
    065    private final Anchor2D anchor1;
    066
    067    /** The first color for the gradient. */
    068    private final Color color2;
    069
    070    /** The anchor point used to find the ending point for the gradient. */
    071    private final Anchor2D anchor2;
    072
    073    /**
    074     * Creates a new instance.
    075     * <br><br>
    076     * NOTE:  some useful standard anchor points are defined in the
    077     * {@link TitleAnchor} class.
    078     *
    079     * @param color1  the first color for the gradient ({@code null} not
    080     *     permitted).
    081     * @param anchor1  the anchor point used to determine the starting point
    082     *     for the gradient ({@code null} not permitted).
    083     * @param color2  the second color for the gradient ({@code null} not
    084     *     permitted).
    085     * @param anchor2  the anchor point used to determine the ending point for
    086     *     the gradient ({@code null} not permitted).
    087     */
    088    public GradientRectanglePainter(Color color1, Anchor2D anchor1,
    089            Color color2, Anchor2D anchor2) {
    090        Args.nullNotPermitted(color1, "color1");
    091        Args.nullNotPermitted(anchor1, "anchor1");
    092        Args.nullNotPermitted(color2, "color2");
    093        Args.nullNotPermitted(anchor2, "anchor2");
    094        this.color1 = color1;
    095        this.anchor1 = anchor1;
    096        this.color2 = color2;
    097        this.anchor2 = anchor2;
    098    }
    099
    100    /**
    101     * Returns the first color for the gradient (as specified via the
    102     * constructor).  There is no setter method because instances of this class
    103     * are immutable.
    104     *
    105     * @return The first color for the gradient (never {@code null}).
    106     */
    107    public Color getColor1() {
    108        return this.color1;
    109    }
    110
    111    /**
    112     * Returns the anchor point used to find the starting point for the
    113     * gradient (as specified via the constructor).  There is no setter method
    114     * because instances of this class are immutable.
    115     *
    116     * @return The anchor point (never {@code null}).
    117     */
    118    public Anchor2D getAnchor1() {
    119        return this.anchor1;
    120    }
    121
    122    /**
    123     * Returns the second color for the gradient (as specified via the
    124     * constructor).  There is no setter method because instances of this class
    125     * are immutable.
    126     *
    127     * @return The second color for the gradient (never {@code null}).
    128     */
    129    public Color getColor2() {
    130        return this.color2;
    131    }
    132
    133    /**
    134     * Returns the anchor point used to find the ending point for the
    135     * gradient (as specified via the constructor).  There is no setter method
    136     * because instances of this class are immutable.
    137     *
    138     * @return The anchor point (never {@code null}).
    139     */
    140    public Anchor2D getAnchor2() {
    141        return this.anchor2;
    142    }
    143
    144    /**
    145     * Returns a {@code GradientPaint} instance with coordinates based
    146     * on the painter's anchor points and the supplied rectangle.
    147     *
    148     * @param area  the area ({@code null} not permitted).
    149     *
    150     * @return A gradient paint (never {@code null}).
    151     */
    152    private GradientPaint createTransformedGradient(Rectangle2D area) {
    153        // defer arg check
    154        Point2D pt1 = this.anchor1.getAnchorPoint(area);
    155        Point2D pt2 = this.anchor2.getAnchorPoint(area);
    156        return new GradientPaint(pt1, this.color1, pt2, this.color2);
    157    }
    158
    159    /**
    160     * Fills the specified {@code area} with a gradient paint created
    161     * using the colors and anchor points of this painter.
    162     *
    163     * @param g2  the graphics target ({@code null} not permitted).
    164     * @param area  the area to fill ({@code null} not permitted).
    165     */
    166    @Override
    167    public void fill(Graphics2D g2, Rectangle2D area) {
    168        Paint saved = g2.getPaint();
    169        g2.setPaint(createTransformedGradient(area));
    170        g2.fill(area);
    171        g2.setPaint(saved);
    172    }
    173
    174    /**
    175     * Tests this instance for equality with an arbitrary object.
    176     *
    177     * @param obj  the object ({@code null} not permitted).
    178     *
    179     * @return A boolean.
    180     */
    181    @Override
    182    public boolean equals(Object obj) {
    183        if (obj == this) {
    184            return true;
    185        }
    186        if (!(obj instanceof GradientRectanglePainter)) {
    187            return false;
    188        }
    189        GradientRectanglePainter that = (GradientRectanglePainter) obj;
    190        if (!this.color1.equals(that.color1)) {
    191            return false;
    192        }
    193        if (!this.anchor1.equals(that.anchor1)) {
    194            return false;
    195        }
    196        if (!this.color2.equals(that.color2)) {
    197            return false;
    198        }
    199        if (!this.anchor2.equals(that.anchor2)) {
    200            return false;
    201        }
    202        return true;
    203    }
    204
    205    @Override
    206    public int hashCode() {
    207        int hash = 5;
    208        hash = 67 * hash + ObjectUtils.hashCode(this.color1);
    209        hash = 67 * hash + ObjectUtils.hashCode(this.anchor1);
    210        hash = 67 * hash + ObjectUtils.hashCode(this.color2);
    211        hash = 67 * hash + ObjectUtils.hashCode(this.anchor2);
    212        return hash;
    213    }
    214
    215}