    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    }