    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     * TextAnnotation.java
    029     * -------------------
    030     * (C) Copyright 2002-2007, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: TextAnnotation.java,v 1.6.2.3 2007/01/16 09:43:46 mungady Exp $
    036     *
    037     * Changes:
    038     * --------
    039     * 28-Aug-2002 : Version 1 (DG);
    040     * 07-Nov-2002 : Fixed errors reported by Checkstyle, added accessor
    041     *               methods (DG);
    042     * 13-Jan-2003 : Reviewed Javadocs (DG);
    043     * 26-Mar-2003 : Implemented Serializable (DG);
    044     * 02-Jun-2003 : Added anchor and rotation settings (DG);
    045     * 19-Aug-2003 : Added equals() method and implemented Cloneable (DG);
    046     * 29-Sep-2004 : Updated equals() method (DG);
    047     * 06-Jun-2005 : Fixed equals() method to work with GradientPaint (DG);
    048     * ------------- JFREECHART 1.0.x ---------------------------------------------
    049     * 16-Jan-2007 : Added argument checks, fixed hashCode() method and updated
    050     *               API docs (DG);
    051     *
    052     */
    053
    054    package org.jfree.chart.annotations;
    055
    056    import java.awt.Color;
    057    import java.awt.Font;
    058    import java.awt.Paint;
    059    import java.io.IOException;
    060    import java.io.ObjectInputStream;
    061    import java.io.ObjectOutputStream;
    062    import java.io.Serializable;
    063
    064    import org.jfree.chart.HashUtilities;
    065    import org.jfree.io.SerialUtilities;
    066    import org.jfree.ui.TextAnchor;
    067    import org.jfree.util.ObjectUtilities;
    068    import org.jfree.util.PaintUtilities;
    069
    070    /**
    071     * A base class for text annotations.  This class records the content but not
    072     * the location of the annotation.
    073     */
    074    public class TextAnnotation implements Serializable {
    075
    076        /** For serialization. */
    077        private static final long serialVersionUID = 7008912287533127432L;
    078
    079        /** The default font. */
    080        public static final Font DEFAULT_FONT
    081            = new Font("SansSerif", Font.PLAIN, 10);
    082
    083        /** The default paint. */
    084        public static final Paint DEFAULT_PAINT = Color.black;
    085
    086        /** The default text anchor. */
    087        public static final TextAnchor DEFAULT_TEXT_ANCHOR = TextAnchor.CENTER;
    088
    089        /** The default rotation anchor. */
    090        public static final TextAnchor DEFAULT_ROTATION_ANCHOR = TextAnchor.CENTER;
    091
    092        /** The default rotation angle. */
    093        public static final double DEFAULT_ROTATION_ANGLE = 0.0;
    094
    095        /** The text. */
    096        private String text;
    097
    098        /** The font. */
    099        private Font font;
    100
    101        /** The paint. */
    102        private transient Paint paint;
    103
    104        /** The text anchor. */
    105        private TextAnchor textAnchor;
    106
    107        /** The rotation anchor. */
    108        private TextAnchor rotationAnchor;
    109
    110        /** The rotation angle. */
    111        private double rotationAngle;
    112
    113        /**
    114         * Creates a text annotation with default settings.
    115         *
    116         * @param text  the text (<code>null</code> not permitted).
    117         */
    118        protected TextAnnotation(String text) {
    119            if (text == null) {
    120                throw new IllegalArgumentException("Null 'text' argument.");
    121            }
    122            this.text = text;
    123            this.font = DEFAULT_FONT;
    124            this.paint = DEFAULT_PAINT;
    125            this.textAnchor = DEFAULT_TEXT_ANCHOR;
    126            this.rotationAnchor = DEFAULT_ROTATION_ANCHOR;
    127            this.rotationAngle = DEFAULT_ROTATION_ANGLE;
    128        }
    129
    130        /**
    131         * Returns the text for the annotation.
    132         *
    133         * @return The text (never <code>null</code>).
    134         *
    135         * @see #setText(String)
    136         */
    137        public String getText() {
    138            return this.text;
    139        }
    140
    141        /**
    142         * Sets the text for the annotation.
    143         *
    144         * @param text  the text (<code>null</code> not permitted).
    145         *
    146         * @see #getText()
    147         */
    148        public void setText(String text) {
    149            if (text == null) {
    150                throw new IllegalArgumentException("Null 'text' argument.");
    151            }
    152            this.text = text;
    153        }
    154
    155        /**
    156         * Returns the font for the annotation.
    157         *
    158         * @return The font (never <code>null</code>).
    159         *
    160         * @see #setFont(Font)
    161         */
    162        public Font getFont() {
    163            return this.font;
    164        }
    165
    166        /**
    167         * Sets the font for the annotation.
    168         *
    169         * @param font  the font (<code>null</code> not permitted).
    170         *
    171         * @see #getFont()
    172         */
    173        public void setFont(Font font) {
    174            if (font == null) {
    175                throw new IllegalArgumentException("Null 'font' argument.");
    176            }
    177            this.font = font;
    178        }
    179
    180        /**
    181         * Returns the paint for the annotation.
    182         *
    183         * @return The paint (never <code>null</code>).
    184         *
    185         * @see #setPaint(Paint)
    186         */
    187        public Paint getPaint() {
    188            return this.paint;
    189        }
    190
    191        /**
    192         * Sets the paint for the annotation.
    193         *
    194         * @param paint  the paint (<code>null</code> not permitted).
    195         *
    196         * @see #getPaint()
    197         */
    198        public void setPaint(Paint paint) {
    199            if (paint == null) {
    200                throw new IllegalArgumentException("Null 'paint' argument.");
    201            }
    202            this.paint = paint;
    203        }
    204
    205        /**
    206         * Returns the text anchor.
    207         *
    208         * @return The text anchor.
    209         *
    210         * @see #setTextAnchor(TextAnchor)
    211         */
    212        public TextAnchor getTextAnchor() {
    213            return this.textAnchor;
    214        }
    215
    216        /**
    217         * Sets the text anchor (the point on the text bounding rectangle that is
    218         * aligned to the (x, y) coordinate of the annotation).
    219         *
    220         * @param anchor  the anchor point (<code>null</code> not permitted).
    221         *
    222         * @see #getTextAnchor()
    223         */
    224        public void setTextAnchor(TextAnchor anchor) {
    225            if (anchor == null) {
    226                throw new IllegalArgumentException("Null 'anchor' argument.");
    227            }
    228            this.textAnchor = anchor;
    229        }
    230
    231        /**
    232         * Returns the rotation anchor.
    233         *
    234         * @return The rotation anchor point (never <code>null</code>).
    235         *
    236         * @see #setRotationAnchor(TextAnchor)
    237         */
    238        public TextAnchor getRotationAnchor() {
    239            return this.rotationAnchor;
    240        }
    241
    242        /**
    243         * Sets the rotation anchor point.
    244         *
    245         * @param anchor  the anchor (<code>null</code> not permitted).
    246         *
    247         * @see #getRotationAnchor()
    248         */
    249        public void setRotationAnchor(TextAnchor anchor) {
    250            this.rotationAnchor = anchor;
    251        }
    252
    253        /**
    254         * Returns the rotation angle in radians.
    255         *
    256         * @return The rotation angle.
    257         *
    258         * @see #setRotationAngle(double)
    259         */
    260        public double getRotationAngle() {
    261            return this.rotationAngle;
    262        }
    263
    264        /**
    265         * Sets the rotation angle.  The angle is measured clockwise in radians.
    266         *
    267         * @param angle  the angle (in radians).
    268         *
    269         * @see #getRotationAngle()
    270         */
    271        public void setRotationAngle(double angle) {
    272            this.rotationAngle = angle;
    273        }
    274
    275        /**
    276         * Tests this object for equality with an arbitrary object.
    277         *
    278         * @param obj  the object (<code>null</code> permitted).
    279         *
    280         * @return <code>true</code> or <code>false</code>.
    281         */
    282        public boolean equals(Object obj) {
    283            if (obj == this) {
    284                return true;
    285            }
    286            // now try to reject equality...
    287            if (!(obj instanceof TextAnnotation)) {
    288                return false;
    289            }
    290            TextAnnotation that = (TextAnnotation) obj;
    291            if (!ObjectUtilities.equal(this.text, that.getText())) {
    292                return false;
    293            }
    294            if (!ObjectUtilities.equal(this.font, that.getFont())) {
    295                return false;
    296            }
    297            if (!PaintUtilities.equal(this.paint, that.getPaint())) {
    298                return false;
    299            }
    300            if (!ObjectUtilities.equal(this.textAnchor, that.getTextAnchor())) {
    301                return false;
    302            }
    303            if (!ObjectUtilities.equal(this.rotationAnchor,
    304                    that.getRotationAnchor())) {
    305                return false;
    306            }
    307            if (this.rotationAngle != that.getRotationAngle()) {
    308                return false;
    309            }
    310
    311            // seem to be the same...
    312            return true;
    313
    314        }
    315
    316        /**
    317         * Returns a hash code for this instance.
    318         *
    319         * @return A hash code.
    320         */
    321        public int hashCode() {
    322            int result = 193;
    323            result = 37 * result + this.font.hashCode();
    324            result = 37 * result + HashUtilities.hashCodeForPaint(this.paint);
    325            result = 37 * result + this.rotationAnchor.hashCode();
    326            long temp = Double.doubleToLongBits(this.rotationAngle);
    327            result = 37 * result + (int) (temp ^ (temp >>> 32));
    328            result = 37 * result + this.text.hashCode();
    329            result = 37 * result + this.textAnchor.hashCode();
    330            return result;
    331        }
    332
    333        /**
    334         * Provides serialization support.
    335         *
    336         * @param stream  the output stream.
    337         *
    338         * @throws IOException if there is an I/O error.
    339         */
    340        private void writeObject(ObjectOutputStream stream) throws IOException {
    341            stream.defaultWriteObject();
    342            SerialUtilities.writePaint(this.paint, stream);
    343        }
    344
    345        /**
    346         * Provides serialization support.
    347         *
    348         * @param stream  the input stream.
    349         *
    350         * @throws IOException  if there is an I/O error.
    351         * @throws ClassNotFoundException  if there is a classpath problem.
    352         */
    353        private void readObject(ObjectInputStream stream)
    354            throws IOException, ClassNotFoundException {
    355            stream.defaultReadObject();
    356            this.paint = SerialUtilities.readPaint(stream);
    357        }
    358
    359    }