    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2011, 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     * LabelBlock.java
    029     * ---------------
    030     * (C) Copyright 2004-2009, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   Pierre-Marie Le Biot;
    034     *
    035     * Changes:
    036     * --------
    037     * 22-Oct-2004 : Version 1 (DG);
    038     * 19-Apr-2005 : Added optional tooltip and URL text items,
    039     *               draw() method now returns entities if
    040     *               requested (DG);
    041     * 13-May-2005 : Added methods to set the font (DG);
    042     * 01-Sep-2005 : Added paint management (PMLB);
    043     *               Implemented equals() and clone() (PublicCloneable) (DG);
    044     * ------------- JFREECHART 1.0.x ---------------------------------------------
    045     * 20-Jul-2006 : Fixed entity area in draw() method (DG);
    046     * 16-Mar-2007 : Fixed serialization when using GradientPaint (DG);
    047     * 10-Feb-2009 : Added alignment fields (DG);
    048     *
    049     */
    050
    051    package org.jfree.chart.block;
    052
    053    import java.awt.Color;
    054    import java.awt.Font;
    055    import java.awt.Graphics2D;
    056    import java.awt.Paint;
    057    import java.awt.Shape;
    058    import java.awt.geom.Point2D;
    059    import java.awt.geom.Rectangle2D;
    060    import java.io.IOException;
    061    import java.io.ObjectInputStream;
    062    import java.io.ObjectOutputStream;
    063
    064    import org.jfree.chart.entity.ChartEntity;
    065    import org.jfree.chart.entity.StandardEntityCollection;
    066    import org.jfree.io.SerialUtilities;
    067    import org.jfree.text.TextBlock;
    068    import org.jfree.text.TextBlockAnchor;
    069    import org.jfree.text.TextUtilities;
    070    import org.jfree.ui.RectangleAnchor;
    071    import org.jfree.ui.Size2D;
    072    import org.jfree.util.ObjectUtilities;
    073    import org.jfree.util.PaintUtilities;
    074    import org.jfree.util.PublicCloneable;
    075
    076    /**
    077     * A block containing a label.
    078     */
    079    public class LabelBlock extends AbstractBlock
    080            implements Block, PublicCloneable {
    081
    082        /** For serialization. */
    083        static final long serialVersionUID = 249626098864178017L;
    084
    085        /**
    086         * The text for the label - retained in case the label needs
    087         * regenerating (for example, to change the font).
    088         */
    089        private String text;
    090
    091        /** The label. */
    092        private TextBlock label;
    093
    094        /** The font. */
    095        private Font font;
    096
    097        /** The tool tip text (can be <code>null</code>). */
    098        private String toolTipText;
    099
    100        /** The URL text (can be <code>null</code>). */
    101        private String urlText;
    102
    103        /** The default color. */
    104        public static final Paint DEFAULT_PAINT = Color.black;
    105
    106        /** The paint. */
    107        private transient Paint paint;
    108
    109        /**
    110         * The content alignment point.
    111         *
    112         * @since 1.0.13
    113         */
    114        private TextBlockAnchor contentAlignmentPoint;
    115
    116        /**
    117         * The anchor point for the text.
    118         *
    119         * @since 1.0.13
    120         */
    121        private RectangleAnchor textAnchor;
    122
    123        /**
    124         * Creates a new label block.
    125         *
    126         * @param label  the label (<code>null</code> not permitted).
    127         */
    128        public LabelBlock(String label) {
    129            this(label, new Font("SansSerif", Font.PLAIN, 10), DEFAULT_PAINT);
    130        }
    131
    132        /**
    133         * Creates a new label block.
    134         *
    135         * @param text  the text for the label (<code>null</code> not permitted).
    136         * @param font  the font (<code>null</code> not permitted).
    137         */
    138        public LabelBlock(String text, Font font) {
    139            this(text, font, DEFAULT_PAINT);
    140        }
    141
    142        /**
    143         * Creates a new label block.
    144         *
    145         * @param text  the text for the label (<code>null</code> not permitted).
    146         * @param font  the font (<code>null</code> not permitted).
    147         * @param paint the paint (<code>null</code> not permitted).
    148         */
    149        public LabelBlock(String text, Font font, Paint paint) {
    150            this.text = text;
    151            this.paint = paint;
    152            this.label = TextUtilities.createTextBlock(text, font, this.paint);
    153            this.font = font;
    154            this.toolTipText = null;
    155            this.urlText = null;
    156            this.contentAlignmentPoint = TextBlockAnchor.CENTER;
    157            this.textAnchor = RectangleAnchor.CENTER;
    158        }
    159
    160        /**
    161         * Returns the font.
    162         *
    163         * @return The font (never <code>null</code>).
    164         *
    165         * @see #setFont(Font)
    166         */
    167        public Font getFont() {
    168            return this.font;
    169        }
    170
    171        /**
    172         * Sets the font and regenerates the label.
    173         *
    174         * @param font  the font (<code>null</code> not permitted).
    175         *
    176         * @see #getFont()
    177         */
    178        public void setFont(Font font) {
    179            if (font == null) {
    180                throw new IllegalArgumentException("Null 'font' argument.");
    181            }
    182            this.font = font;
    183            this.label = TextUtilities.createTextBlock(this.text, font, this.paint);
    184        }
    185
    186        /**
    187         * Returns the paint.
    188         *
    189         * @return The paint (never <code>null</code>).
    190         *
    191         * @see #setPaint(Paint)
    192         */
    193        public Paint getPaint() {
    194            return this.paint;
    195        }
    196
    197        /**
    198         * Sets the paint and regenerates the label.
    199         *
    200         * @param paint  the paint (<code>null</code> not permitted).
    201         *
    202         * @see #getPaint()
    203         */
    204        public void setPaint(Paint paint) {
    205            if (paint == null) {
    206                throw new IllegalArgumentException("Null 'paint' argument.");
    207            }
    208            this.paint = paint;
    209            this.label = TextUtilities.createTextBlock(this.text, this.font,
    210                    this.paint);
    211        }
    212
    213        /**
    214         * Returns the tool tip text.
    215         *
    216         * @return The tool tip text (possibly <code>null</code>).
    217         *
    218         * @see #setToolTipText(String)
    219         */
    220        public String getToolTipText() {
    221            return this.toolTipText;
    222        }
    223
    224        /**
    225         * Sets the tool tip text.
    226         *
    227         * @param text  the text (<code>null</code> permitted).
    228         *
    229         * @see #getToolTipText()
    230         */
    231        public void setToolTipText(String text) {
    232            this.toolTipText = text;
    233        }
    234
    235        /**
    236         * Returns the URL text.
    237         *
    238         * @return The URL text (possibly <code>null</code>).
    239         *
    240         * @see #setURLText(String)
    241         */
    242        public String getURLText() {
    243            return this.urlText;
    244        }
    245
    246        /**
    247         * Sets the URL text.
    248         *
    249         * @param text  the text (<code>null</code> permitted).
    250         *
    251         * @see #getURLText()
    252         */
    253        public void setURLText(String text) {
    254            this.urlText = text;
    255        }
    256
    257        /**
    258         * Returns the content alignment point.
    259         *
    260         * @return The content alignment point (never <code>null</code>).
    261         *
    262         * @since 1.0.13
    263         */
    264        public TextBlockAnchor getContentAlignmentPoint() {
    265            return this.contentAlignmentPoint;
    266        }
    267
    268        /**
    269         * Sets the content alignment point.
    270         *
    271         * @param anchor  the anchor used to determine the alignment point (never
    272         *         <code>null</code>).
    273         *
    274         * @since 1.0.13
    275         */
    276        public void setContentAlignmentPoint(TextBlockAnchor anchor) {
    277            if (anchor == null) {
    278                throw new IllegalArgumentException("Null 'anchor' argument.");
    279            }
    280            this.contentAlignmentPoint = anchor;
    281        }
    282
    283        /**
    284         * Returns the text anchor (never <code>null</code>).
    285         *
    286         * @return The text anchor.
    287         *
    288         * @since 1.0.13
    289         */
    290        public RectangleAnchor getTextAnchor() {
    291            return this.textAnchor;
    292        }
    293
    294        /**
    295         * Sets the text anchor.
    296         *
    297         * @param anchor  the anchor (<code>null</code> not permitted).
    298         *
    299         * @since 1.0.13
    300         */
    301        public void setTextAnchor(RectangleAnchor anchor) {
    302            this.textAnchor = anchor;
    303        }
    304
    305        /**
    306         * Arranges the contents of the block, within the given constraints, and
    307         * returns the block size.
    308         *
    309         * @param g2  the graphics device.
    310         * @param constraint  the constraint (<code>null</code> not permitted).
    311         *
    312         * @return The block size (in Java2D units, never <code>null</code>).
    313         */
    314        public Size2D arrange(Graphics2D g2, RectangleConstraint constraint) {
    315            g2.setFont(this.font);
    316            Size2D s = this.label.calculateDimensions(g2);
    317            return new Size2D(calculateTotalWidth(s.getWidth()),
    318                    calculateTotalHeight(s.getHeight()));
    319        }
    320
    321        /**
    322         * Draws the block.
    323         *
    324         * @param g2  the graphics device.
    325         * @param area  the area.
    326         */
    327        public void draw(Graphics2D g2, Rectangle2D area) {
    328            draw(g2, area, null);
    329        }
    330
    331        /**
    332         * Draws the block within the specified area.
    333         *
    334         * @param g2  the graphics device.
    335         * @param area  the area.
    336         * @param params  ignored (<code>null</code> permitted).
    337         *
    338         * @return Always <code>null</code>.
    339         */
    340        public Object draw(Graphics2D g2, Rectangle2D area, Object params) {
    341            area = trimMargin(area);
    342            drawBorder(g2, area);
    343            area = trimBorder(area);
    344            area = trimPadding(area);
    345
    346            // check if we need to collect chart entities from the container
    347            EntityBlockParams ebp = null;
    348            StandardEntityCollection sec = null;
    349            Shape entityArea = null;
    350            if (params instanceof EntityBlockParams) {
    351                ebp = (EntityBlockParams) params;
    352                if (ebp.getGenerateEntities()) {
    353                    sec = new StandardEntityCollection();
    354                    entityArea = (Shape) area.clone();
    355                }
    356            }
    357            g2.setPaint(this.paint);
    358            g2.setFont(this.font);
    359            Point2D pt = RectangleAnchor.coordinates(area, this.textAnchor);
    360            this.label.draw(g2, (float) pt.getX(), (float) pt.getY(),
    361                    this.contentAlignmentPoint);
    362            BlockResult result = null;
    363            if (ebp != null && sec != null) {
    364                if (this.toolTipText != null || this.urlText != null) {
    365                    ChartEntity entity = new ChartEntity(entityArea,
    366                            this.toolTipText, this.urlText);
    367                    sec.add(entity);
    368                    result = new BlockResult();
    369                    result.setEntityCollection(sec);
    370                }
    371            }
    372            return result;
    373        }
    374
    375        /**
    376         * Tests this <code>LabelBlock</code> for equality with an arbitrary
    377         * object.
    378         *
    379         * @param obj  the object (<code>null</code> permitted).
    380         *
    381         * @return A boolean.
    382         */
    383        public boolean equals(Object obj) {
    384            if (!(obj instanceof LabelBlock)) {
    385                return false;
    386            }
    387            LabelBlock that = (LabelBlock) obj;
    388            if (!this.text.equals(that.text)) {
    389                return false;
    390            }
    391            if (!this.font.equals(that.font)) {
    392                return false;
    393            }
    394            if (!PaintUtilities.equal(this.paint, that.paint)) {
    395                return false;
    396            }
    397            if (!ObjectUtilities.equal(this.toolTipText, that.toolTipText)) {
    398                return false;
    399            }
    400            if (!ObjectUtilities.equal(this.urlText, that.urlText)) {
    401                return false;
    402            }
    403            if (!this.contentAlignmentPoint.equals(that.contentAlignmentPoint)) {
    404                return false;
    405            }
    406            if (!this.textAnchor.equals(that.textAnchor)) {
    407                return false;
    408            }
    409            return super.equals(obj);
    410        }
    411
    412        /**
    413         * Returns a clone of this <code>LabelBlock</code> instance.
    414         *
    415         * @return A clone.
    416         *
    417         * @throws CloneNotSupportedException if there is a problem cloning.
    418         */
    419        public Object clone() throws CloneNotSupportedException {
    420            return super.clone();
    421        }
    422
    423        /**
    424         * Provides serialization support.
    425         *
    426         * @param stream  the output stream.
    427         *
    428         * @throws IOException if there is an I/O error.
    429         */
    430        private void writeObject(ObjectOutputStream stream) throws IOException {
    431            stream.defaultWriteObject();
    432            SerialUtilities.writePaint(this.paint, stream);
    433        }
    434
    435        /**
    436         * Provides serialization support.
    437         *
    438         * @param stream  the input stream.
    439         *
    440         * @throws IOException  if there is an I/O error.
    441         * @throws ClassNotFoundException  if there is a classpath problem.
    442         */
    443        private void readObject(ObjectInputStream stream)
    444            throws IOException, ClassNotFoundException {
    445            stream.defaultReadObject();
    446            this.paint = SerialUtilities.readPaint(stream);
    447        }
    448
    449    }