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