    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
    051package org.jfree.chart.block;
    052
    053import java.awt.Color;
    054import java.awt.Font;
    055import java.awt.Graphics2D;
    056import java.awt.Paint;
    057import java.awt.Shape;
    058import java.awt.geom.Point2D;
    059import java.awt.geom.Rectangle2D;
    060import java.io.IOException;
    061import java.io.ObjectInputStream;
    062import java.io.ObjectOutputStream;
    063
    064import org.jfree.chart.entity.ChartEntity;
    065import org.jfree.chart.entity.StandardEntityCollection;
    066import org.jfree.io.SerialUtilities;
    067import org.jfree.text.TextBlock;
    068import org.jfree.text.TextBlockAnchor;
    069import org.jfree.text.TextUtilities;
    070import org.jfree.ui.RectangleAnchor;
    071import org.jfree.ui.Size2D;
    072import org.jfree.util.ObjectUtilities;
    073import org.jfree.util.PaintUtilities;
    074import org.jfree.util.PublicCloneable;
    075
    076/**
    077 * A block containing a label.
    078 */
    079public 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}