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