001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2013, by Object Refinery Limited 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 * MeterNeedle.java
029 * ----------------
030 * (C) Copyright 2002-2008, by the Australian Antarctic Division and
031 *                          Contributors.
032 *
033 * Original Author:  Bryan Scott (for the Australian Antarctic Division);
034 * Contributor(s):   David Gilbert (for Object Refinery Limited);
035 *                   Nicolas Brodu (for Astrium and EADS Corporate Research
036 *                   Center);
037 *
038 * Changes:
039 * --------
040 * 25-Sep-2002 : Version 1, contributed by Bryan Scott (DG);
041 * 07-Nov-2002 : Fixed errors reported by Checkstyle (DG);
042 * 01-Sep-2003 : Implemented Serialization (NB);
043 * 16-Mar-2004 : Changed transform from private to protected (BRS);
044 * 08-Jun-2005 : Fixed equals() method to handle GradientPaint (DG);
045 * 22-Nov-2007 : Implemented hashCode() (DG);
046 *
047 */
048
049package org.jfree.chart.needle;
050
051import java.awt.BasicStroke;
052import java.awt.Color;
053import java.awt.Graphics2D;
054import java.awt.Paint;
055import java.awt.Shape;
056import java.awt.Stroke;
057import java.awt.geom.AffineTransform;
058import java.awt.geom.Point2D;
059import java.awt.geom.Rectangle2D;
060import java.io.IOException;
061import java.io.ObjectInputStream;
062import java.io.ObjectOutputStream;
063import java.io.Serializable;
064
065import org.jfree.chart.HashUtilities;
066import org.jfree.io.SerialUtilities;
067import org.jfree.util.ObjectUtilities;
068import org.jfree.util.PaintUtilities;
069
070/**
071 * The base class used to represent the needle on a
072 * {@link org.jfree.chart.plot.CompassPlot}.
073 */
074public abstract class MeterNeedle implements Serializable {
075
076    /** For serialization. */
077    private static final long serialVersionUID = 5203064851510951052L;
078
079    /** The outline paint. */
080    private transient Paint outlinePaint = Color.black;
081
082    /** The outline stroke. */
083    private transient Stroke outlineStroke = new BasicStroke(2);
084
085    /** The fill paint. */
086    private transient Paint fillPaint = null;
087
088    /** The highlight paint. */
089    private transient Paint highlightPaint = null;
090
091    /** The size. */
092    private int size = 5;
093
094    /** Scalar to aply to locate the rotation x point. */
095    private double rotateX = 0.5;
096
097    /** Scalar to aply to locate the rotation y point. */
098    private double rotateY = 0.5;
099
100    /** A transform. */
101    protected static AffineTransform transform = new AffineTransform();
102
103    /**
104     * Creates a new needle.
105     */
106    public MeterNeedle() {
107        this(null, null, null);
108    }
109
110    /**
111     * Creates a new needle.
112     *
113     * @param outline  the outline paint (<code>null</code> permitted).
114     * @param fill  the fill paint (<code>null</code> permitted).
115     * @param highlight  the highlight paint (<code>null</code> permitted).
116     */
117    public MeterNeedle(Paint outline, Paint fill, Paint highlight) {
118        this.fillPaint = fill;
119        this.highlightPaint = highlight;
120        this.outlinePaint = outline;
121    }
122
123    /**
124     * Returns the outline paint.
125     *
126     * @return The outline paint.
127     */
128    public Paint getOutlinePaint() {
129        return this.outlinePaint;
130    }
131
132    /**
133     * Sets the outline paint.
134     *
135     * @param p  the new paint.
136     */
137    public void setOutlinePaint(Paint p) {
138        if (p != null) {
139            this.outlinePaint = p;
140        }
141    }
142
143    /**
144     * Returns the outline stroke.
145     *
146     * @return The outline stroke.
147     */
148    public Stroke getOutlineStroke() {
149        return this.outlineStroke;
150    }
151
152    /**
153     * Sets the outline stroke.
154     *
155     * @param s  the new stroke.
156     */
157    public void setOutlineStroke(Stroke s) {
158        if (s != null) {
159            this.outlineStroke = s;
160        }
161    }
162
163    /**
164     * Returns the fill paint.
165     *
166     * @return The fill paint.
167     */
168    public Paint getFillPaint() {
169        return this.fillPaint;
170    }
171
172    /**
173     * Sets the fill paint.
174     *
175     * @param p  the fill paint.
176     */
177    public void setFillPaint(Paint p) {
178        if (p != null) {
179            this.fillPaint = p;
180        }
181    }
182
183    /**
184     * Returns the highlight paint.
185     *
186     * @return The highlight paint.
187     */
188    public Paint getHighlightPaint() {
189        return this.highlightPaint;
190    }
191
192    /**
193     * Sets the highlight paint.
194     *
195     * @param p  the highlight paint.
196     */
197    public void setHighlightPaint(Paint p) {
198        if (p != null) {
199            this.highlightPaint = p;
200        }
201    }
202
203    /**
204     * Returns the scalar used for determining the rotation x value.
205     *
206     * @return The x rotate scalar.
207     */
208    public double getRotateX() {
209        return this.rotateX;
210    }
211
212    /**
213     * Sets the rotateX value.
214     *
215     * @param x  the new value.
216     */
217    public void setRotateX(double x) {
218        this.rotateX = x;
219    }
220
221    /**
222     * Sets the rotateY value.
223     *
224     * @param y  the new value.
225     */
226    public void setRotateY(double y) {
227        this.rotateY = y;
228    }
229
230    /**
231     * Returns the scalar used for determining the rotation y value.
232     *
233     * @return The y rotate scalar.
234     */
235    public double getRotateY() {
236        return this.rotateY;
237    }
238
239    /**
240     * Draws the needle.
241     *
242     * @param g2  the graphics device.
243     * @param plotArea  the plot area.
244     */
245    public void draw(Graphics2D g2, Rectangle2D plotArea) {
246        draw(g2, plotArea, 0);
247    }
248
249    /**
250     * Draws the needle.
251     *
252     * @param g2  the graphics device.
253     * @param plotArea  the plot area.
254     * @param angle  the angle.
255     */
256    public void draw(Graphics2D g2, Rectangle2D plotArea, double angle) {
257
258        Point2D.Double pt = new Point2D.Double();
259        pt.setLocation(
260            plotArea.getMinX() + this.rotateX * plotArea.getWidth(),
261            plotArea.getMinY() + this.rotateY * plotArea.getHeight()
262        );
263        draw(g2, plotArea, pt, angle);
264
265    }
266
267    /**
268     * Draws the needle.
269     *
270     * @param g2  the graphics device.
271     * @param plotArea  the plot area.
272     * @param rotate  the rotation point.
273     * @param angle  the angle.
274     */
275    public void draw(Graphics2D g2, Rectangle2D plotArea, Point2D rotate,
276                     double angle) {
277
278        Paint savePaint = g2.getColor();
279        Stroke saveStroke = g2.getStroke();
280
281        drawNeedle(g2, plotArea, rotate, Math.toRadians(angle));
282
283        g2.setStroke(saveStroke);
284        g2.setPaint(savePaint);
285
286    }
287
288    /**
289     * Draws the needle.
290     *
291     * @param g2  the graphics device.
292     * @param plotArea  the plot area.
293     * @param rotate  the rotation point.
294     * @param angle  the angle.
295     */
296    protected abstract void drawNeedle(Graphics2D g2,
297                                       Rectangle2D plotArea, Point2D rotate,
298                                       double angle);
299
300    /**
301     * Displays a shape.
302     *
303     * @param g2  the graphics device.
304     * @param shape  the shape.
305     */
306    protected void defaultDisplay(Graphics2D g2, Shape shape) {
307
308        if (this.fillPaint != null) {
309            g2.setPaint(this.fillPaint);
310            g2.fill(shape);
311        }
312
313        if (this.outlinePaint != null) {
314            g2.setStroke(this.outlineStroke);
315            g2.setPaint(this.outlinePaint);
316            g2.draw(shape);
317        }
318
319    }
320
321    /**
322     * Returns the size.
323     *
324     * @return The size.
325     */
326    public int getSize() {
327        return this.size;
328    }
329
330    /**
331     * Sets the size.
332     *
333     * @param pixels  the new size.
334     */
335    public void setSize(int pixels) {
336        this.size = pixels;
337    }
338
339    /**
340     * Returns the transform.
341     *
342     * @return The transform.
343     */
344    public AffineTransform getTransform() {
345        return MeterNeedle.transform;
346    }
347
348    /**
349     * Tests another object for equality with this object.
350     *
351     * @param obj the object to test (<code>null</code> permitted).
352     *
353     * @return A boolean.
354     */
355    @Override
356    public boolean equals(Object obj) {
357        if (obj == this) {
358            return true;
359        }
360        if (!(obj instanceof MeterNeedle)) {
361            return false;
362        }
363        MeterNeedle that = (MeterNeedle) obj;
364        if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
365            return false;
366        }
367        if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
368            return false;
369        }
370        if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) {
371            return false;
372        }
373        if (!PaintUtilities.equal(this.highlightPaint, that.highlightPaint)) {
374            return false;
375        }
376        if (this.size != that.size) {
377            return false;
378        }
379        if (this.rotateX != that.rotateX) {
380            return false;
381        }
382        if (this.rotateY != that.rotateY) {
383            return false;
384        }
385        return true;
386    }
387
388    /**
389     * Returns a hash code for this instance.
390     *
391     * @return A hash code.
392     */
393    @Override
394    public int hashCode() {
395        int result = HashUtilities.hashCode(193, this.fillPaint);
396        result = HashUtilities.hashCode(result, this.highlightPaint);
397        result = HashUtilities.hashCode(result, this.outlinePaint);
398        result = HashUtilities.hashCode(result, this.outlineStroke);
399        result = HashUtilities.hashCode(result, this.rotateX);
400        result = HashUtilities.hashCode(result, this.rotateY);
401        result = HashUtilities.hashCode(result, this.size);
402        return result;
403    }
404
405    /**
406     * Provides serialization support.
407     *
408     * @param stream  the output stream.
409     *
410     * @throws IOException  if there is an I/O error.
411     */
412    private void writeObject(ObjectOutputStream stream) throws IOException {
413        stream.defaultWriteObject();
414        SerialUtilities.writeStroke(this.outlineStroke, stream);
415        SerialUtilities.writePaint(this.outlinePaint, stream);
416        SerialUtilities.writePaint(this.fillPaint, stream);
417        SerialUtilities.writePaint(this.highlightPaint, stream);
418    }
419
420    /**
421     * Provides serialization support.
422     *
423     * @param stream  the input stream.
424     *
425     * @throws IOException  if there is an I/O error.
426     * @throws ClassNotFoundException  if there is a classpath problem.
427     */
428    private void readObject(ObjectInputStream stream)
429        throws IOException, ClassNotFoundException {
430        stream.defaultReadObject();
431        this.outlineStroke = SerialUtilities.readStroke(stream);
432        this.outlinePaint = SerialUtilities.readPaint(stream);
433        this.fillPaint = SerialUtilities.readPaint(stream);
434        this.highlightPaint = SerialUtilities.readPaint(stream);
435    }
436
437}