001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-present, by David Gilbert and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * -------------------
028 * DialBackground.java
029 * -------------------
030 * (C) Copyright 2006-present, by David Gilbert.
031 *
032 * Original Author:  David Gilbert;
033 * Contributor(s):   -;
034 *
035 */
036
037package org.jfree.chart.plot.dial;
038
039import java.awt.Color;
040import java.awt.GradientPaint;
041import java.awt.Graphics2D;
042import java.awt.Paint;
043import java.awt.geom.Rectangle2D;
044import java.io.IOException;
045import java.io.ObjectInputStream;
046import java.io.ObjectOutputStream;
047import java.io.Serializable;
048
049import org.jfree.chart.HashUtils;
050import org.jfree.chart.ui.GradientPaintTransformer;
051import org.jfree.chart.ui.StandardGradientPaintTransformer;
052import org.jfree.chart.util.PaintUtils;
053import org.jfree.chart.util.Args;
054import org.jfree.chart.util.PublicCloneable;
055import org.jfree.chart.util.SerialUtils;
056
057/**
058 * A regular dial layer that can be used to draw the background for a dial.
059 */
060public class DialBackground extends AbstractDialLayer implements DialLayer,
061        Cloneable, PublicCloneable, Serializable {
062
063    /** For serialization. */
064    static final long serialVersionUID = -9019069533317612375L;
065
066    /**
067     * The background paint.  This field is transient because serialization
068     * requires special handling.
069     */
070    private transient Paint paint;
071
072    /**
073     * The transformer used when the background paint is an instance of
074     * {@code GradientPaint}.
075     */
076    private GradientPaintTransformer gradientPaintTransformer;
077
078    /**
079     * Creates a new instance of {@code DialBackground}.  The
080     * default background paint is {@code Color.WHITE}.
081     */
082    public DialBackground() {
083        this(Color.WHITE);
084    }
085
086    /**
087     * Creates a new instance of {@code DialBackground}.
088     *
089     * @param paint  the paint ({@code null} not permitted).
090     *
091     * @throws IllegalArgumentException if {@code Paint} is
092     *     {@code null}.
093     */
094    public DialBackground(Paint paint) {
095        Args.nullNotPermitted(paint, "paint");
096        this.paint = paint;
097        this.gradientPaintTransformer = new StandardGradientPaintTransformer();
098    }
099
100    /**
101     * Returns the paint used to fill the background.
102     *
103     * @return The paint (never {@code null}).
104     *
105     * @see #setPaint(Paint)
106     */
107    public Paint getPaint() {
108        return this.paint;
109    }
110
111    /**
112     * Sets the paint for the dial background and sends a
113     * {@link DialLayerChangeEvent} to all registered listeners.
114     *
115     * @param paint  the paint ({@code null} not permitted).
116     *
117     * @see #getPaint()
118     */
119    public void setPaint(Paint paint) {
120        Args.nullNotPermitted(paint, "paint");
121        this.paint = paint;
122        notifyListeners(new DialLayerChangeEvent(this));
123    }
124
125    /**
126     * Returns the transformer used to adjust the coordinates of any
127     * {@code GradientPaint} instance used for the background paint.
128     *
129     * @return The transformer (never {@code null}).
130     *
131     * @see #setGradientPaintTransformer(GradientPaintTransformer)
132     */
133    public GradientPaintTransformer getGradientPaintTransformer() {
134        return this.gradientPaintTransformer;
135    }
136
137    /**
138     * Sets the transformer used to adjust the coordinates of any
139     * {@code GradientPaint} instance used for the background paint, and
140     * sends a {@link DialLayerChangeEvent} to all registered listeners.
141     *
142     * @param t  the transformer ({@code null} not permitted).
143     *
144     * @see #getGradientPaintTransformer()
145     */
146    public void setGradientPaintTransformer(GradientPaintTransformer t) {
147        Args.nullNotPermitted(t, "t");
148        this.gradientPaintTransformer = t;
149        notifyListeners(new DialLayerChangeEvent(this));
150    }
151
152    /**
153     * Returns {@code true} to indicate that this layer should be
154     * clipped within the dial window.
155     *
156     * @return {@code true}.
157     */
158    @Override
159    public boolean isClippedToWindow() {
160        return true;
161    }
162
163    /**
164     * Draws the background to the specified graphics device.  If the dial
165     * frame specifies a window, the clipping region will already have been
166     * set to this window before this method is called.
167     *
168     * @param g2  the graphics device ({@code null} not permitted).
169     * @param plot  the plot (ignored here).
170     * @param frame  the dial frame (ignored here).
171     * @param view  the view rectangle ({@code null} not permitted).
172     */
173    @Override
174    public void draw(Graphics2D g2, DialPlot plot, Rectangle2D frame,
175            Rectangle2D view) {
176
177        Paint p = this.paint;
178        if (p instanceof GradientPaint) {
179            p = this.gradientPaintTransformer.transform((GradientPaint) p,
180                    view);
181        }
182        g2.setPaint(p);
183        g2.fill(view);
184    }
185
186    /**
187     * Tests this instance for equality with an arbitrary object.
188     *
189     * @param obj  the object ({@code null} permitted).
190     *
191     * @return A boolean.
192     */
193    @Override
194    public boolean equals(Object obj) {
195        if (obj == this) {
196            return true;
197        }
198        if (!(obj instanceof DialBackground)) {
199            return false;
200        }
201        DialBackground that = (DialBackground) obj;
202        if (!PaintUtils.equal(this.paint, that.paint)) {
203            return false;
204        }
205        if (!this.gradientPaintTransformer.equals(
206                that.gradientPaintTransformer)) {
207            return false;
208        }
209        return super.equals(obj);
210    }
211
212    /**
213     * Returns a hash code for this instance.
214     *
215     * @return The hash code.
216     */
217    @Override
218    public int hashCode() {
219        int result = 193;
220        result = 37 * result + HashUtils.hashCodeForPaint(this.paint);
221        result = 37 * result + this.gradientPaintTransformer.hashCode();
222        return result;
223    }
224
225    /**
226     * Returns a clone of this instance.
227     *
228     * @return The clone.
229     *
230     * @throws CloneNotSupportedException if some attribute of this instance
231     *     cannot be cloned.
232     */
233    @Override
234    public Object clone() throws CloneNotSupportedException {
235        return super.clone();
236    }
237
238    /**
239     * Provides serialization support.
240     *
241     * @param stream  the output stream.
242     *
243     * @throws IOException  if there is an I/O error.
244     */
245    private void writeObject(ObjectOutputStream stream) throws IOException {
246        stream.defaultWriteObject();
247        SerialUtils.writePaint(this.paint, stream);
248    }
249
250    /**
251     * Provides serialization support.
252     *
253     * @param stream  the input stream.
254     *
255     * @throws IOException  if there is an I/O error.
256     * @throws ClassNotFoundException  if there is a classpath problem.
257     */
258    private void readObject(ObjectInputStream stream)
259            throws IOException, ClassNotFoundException {
260        stream.defaultReadObject();
261        this.paint = SerialUtils.readPaint(stream);
262    }
263
264}