    001/* ===========================================================
    002 * Orson Charts : a 3D chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C)opyright 2013-2016, by Object Refinery Limited.  All rights reserved.
    006 *
    007 * http://www.object-refinery.com/orsoncharts/index.html
    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 com.orsoncharts.table;
    034
    035import com.orsoncharts.TitleAnchor;
    036
    037import java.awt.Color;
    038import java.awt.GradientPaint;
    039import java.awt.Graphics2D;
    040import java.awt.Paint;
    041import java.awt.geom.Point2D;
    042import java.awt.geom.Rectangle2D;
    043import java.io.Serializable;
    044
    045import com.orsoncharts.util.Anchor2D;
    046import com.orsoncharts.util.ArgChecks;
    047import com.orsoncharts.util.ObjectUtils;
    048
    049/**
    050 * A {@link RectanglePainter} that can fill a rectangle with a gradient (the
    051 * gradient is generated using anchor points to fit any size rectangle on
    052 * demand).  Instances of this class are immutable.
    053 * <br><br>
    054 * NOTE: This class is serializable, but the serialization format is subject
    055 * to change in future releases and should not be relied upon for persisting
    056 * instances of this class.
    057 */
    058@SuppressWarnings("serial")
    059public final class GradientRectanglePainter implements RectanglePainter,
    060        Serializable {
    061
    062    /** The first color for the gradient. */
    063    private final Color color1;
    064
    065    /** The anchor point used to find the starting point for the gradient. */
    066    private final Anchor2D anchor1;
    067
    068    /** The first color for the gradient. */
    069    private final Color color2;
    070
    071    /** The anchor point used to find the ending point for the gradient. */
    072    private final Anchor2D anchor2;
    073
    074    /**
    075     * Creates a new instance.
    076     * <br><br>
    077     * NOTE:  some useful standard anchor points are defined in the
    078     * {@link TitleAnchor} class.
    079     *
    080     * @param color1  the first color for the gradient ({@code null} not
    081     *     permitted).
    082     * @param anchor1  the anchor point used to determine the starting point
    083     *     for the gradient ({@code null} not permitted).
    084     * @param color2  the second color for the gradient ({@code null} not
    085     *     permitted).
    086     * @param anchor2  the anchor point used to determine the ending point for
    087     *     the gradient ({@code null} not permitted).
    088     */
    089    public GradientRectanglePainter(Color color1, Anchor2D anchor1,
    090            Color color2, Anchor2D anchor2) {
    091        ArgChecks.nullNotPermitted(color1, "color1");
    092        ArgChecks.nullNotPermitted(anchor1, "anchor1");
    093        ArgChecks.nullNotPermitted(color2, "color2");
    094        ArgChecks.nullNotPermitted(anchor2, "anchor2");
    095        this.color1 = color1;
    096        this.anchor1 = anchor1;
    097        this.color2 = color2;
    098        this.anchor2 = anchor2;
    099    }
    100
    101    /**
    102     * Returns the first color for the gradient (as specified via the
    103     * constructor).  There is no setter method because instances of this class
    104     * are immutable.
    105     *
    106     * @return The first color for the gradient (never {@code null}).
    107     */
    108    public Color getColor1() {
    109        return this.color1;
    110    }
    111
    112    /**
    113     * Returns the anchor point used to find the starting point for the
    114     * gradient (as specified via the constructor).  There is no setter method
    115     * because instances of this class are immutable.
    116     *
    117     * @return The anchor point (never {@code null}).
    118     */
    119    public Anchor2D getAnchor1() {
    120        return this.anchor1;
    121    }
    122
    123    /**
    124     * Returns the second color for the gradient (as specified via the
    125     * constructor).  There is no setter method because instances of this class
    126     * are immutable.
    127     *
    128     * @return The second color for the gradient (never {@code null}).
    129     */
    130    public Color getColor2() {
    131        return this.color2;
    132    }
    133
    134    /**
    135     * Returns the anchor point used to find the ending point for the
    136     * gradient (as specified via the constructor).  There is no setter method
    137     * because instances of this class are immutable.
    138     *
    139     * @return The anchor point (never {@code null}).
    140     */
    141    public Anchor2D getAnchor2() {
    142        return this.anchor2;
    143    }
    144
    145    /**
    146     * Returns a {@code GradientPaint} instance with coordinates based
    147     * on the painter's anchor points and the supplied rectangle.
    148     *
    149     * @param area  the area ({@code null} not permitted).
    150     *
    151     * @return A gradient paint (never {@code null}).
    152     */
    153    private GradientPaint createTransformedGradient(Rectangle2D area) {
    154        // defer arg check
    155        Point2D pt1 = this.anchor1.getAnchorPoint(area);
    156        Point2D pt2 = this.anchor2.getAnchorPoint(area);
    157        return new GradientPaint(pt1, this.color1, pt2, this.color2);
    158    }
    159
    160    /**
    161     * Fills the specified {@code area} with a gradient paint created
    162     * using the colors and anchor points of this painter.
    163     *
    164     * @param g2  the graphics target ({@code null} not permitted).
    165     * @param area  the area to fill ({@code null} not permitted).
    166     */
    167    @Override
    168    public void fill(Graphics2D g2, Rectangle2D area) {
    169        Paint saved = g2.getPaint();
    170        g2.setPaint(createTransformedGradient(area));
    171        g2.fill(area);
    172        g2.setPaint(saved);
    173    }
    174
    175    /**
    176     * Tests this instance for equality with an arbitrary object.
    177     *
    178     * @param obj  the object ({@code null} not permitted).
    179     *
    180     * @return A boolean.
    181     */
    182    @Override
    183    public boolean equals(Object obj) {
    184        if (obj == this) {
    185            return true;
    186        }
    187        if (!(obj instanceof GradientRectanglePainter)) {
    188            return false;
    189        }
    190        GradientRectanglePainter that = (GradientRectanglePainter) obj;
    191        if (!this.color1.equals(that.color1)) {
    192            return false;
    193        }
    194        if (!this.anchor1.equals(that.anchor1)) {
    195            return false;
    196        }
    197        if (!this.color2.equals(that.color2)) {
    198            return false;
    199        }
    200        if (!this.anchor2.equals(that.anchor2)) {
    201            return false;
    202        }
    203        return true;
    204    }
    205
    206    @Override
    207    public int hashCode() {
    208        int hash = 5;
    209        hash = 67 * hash + ObjectUtils.hashCode(this.color1);
    210        hash = 67 * hash + ObjectUtils.hashCode(this.anchor1);
    211        hash = 67 * hash + ObjectUtils.hashCode(this.color2);
    212        hash = 67 * hash + ObjectUtils.hashCode(this.anchor2);
    213        return hash;
    214    }
    215
    216}