001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2013, 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-2013, 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 * 02-Jul-2013 : Use ParamChecks (DG);
049 *
050 */
051
052package org.jfree.chart.block;
053
054import java.awt.Color;
055import java.awt.Font;
056import java.awt.Graphics2D;
057import java.awt.Paint;
058import java.awt.Shape;
059import java.awt.geom.Point2D;
060import java.awt.geom.Rectangle2D;
061import java.io.IOException;
062import java.io.ObjectInputStream;
063import java.io.ObjectOutputStream;
064
065import org.jfree.chart.entity.ChartEntity;
066import org.jfree.chart.entity.StandardEntityCollection;
067import org.jfree.chart.util.ParamChecks;
068import org.jfree.io.SerialUtilities;
069import org.jfree.text.TextBlock;
070import org.jfree.text.TextBlockAnchor;
071import org.jfree.text.TextUtilities;
072import org.jfree.ui.RectangleAnchor;
073import org.jfree.ui.Size2D;
074import org.jfree.util.ObjectUtilities;
075import org.jfree.util.PaintUtilities;
076import org.jfree.util.PublicCloneable;
077
078/**
079 * A block containing a label.
080 */
081public class LabelBlock extends AbstractBlock
082        implements Block, PublicCloneable {
083
084    /** For serialization. */
085    static final long serialVersionUID = 249626098864178017L;
086
087    /**
088     * The text for the label - retained in case the label needs
089     * regenerating (for example, to change the font).
090     */
091    private String text;
092
093    /** The label. */
094    private TextBlock label;
095
096    /** The font. */
097    private Font font;
098
099    /** The tool tip text (can be <code>null</code>). */
100    private String toolTipText;
101
102    /** The URL text (can be <code>null</code>). */
103    private String urlText;
104
105    /** The default color. */
106    public static final Paint DEFAULT_PAINT = Color.black;
107
108    /** The paint. */
109    private transient Paint paint;
110
111    /**
112     * The content alignment point.
113     *
114     * @since 1.0.13
115     */
116    private TextBlockAnchor contentAlignmentPoint;
117
118    /**
119     * The anchor point for the text.
120     *
121     * @since 1.0.13
122     */
123    private RectangleAnchor textAnchor;
124
125    /**
126     * Creates a new label block.
127     *
128     * @param label  the label (<code>null</code> not permitted).
129     */
130    public LabelBlock(String label) {
131        this(label, new Font("SansSerif", Font.PLAIN, 10), DEFAULT_PAINT);
132    }
133
134    /**
135     * Creates a new label block.
136     *
137     * @param text  the text for the label (<code>null</code> not permitted).
138     * @param font  the font (<code>null</code> not permitted).
139     */
140    public LabelBlock(String text, Font font) {
141        this(text, font, DEFAULT_PAINT);
142    }
143
144    /**
145     * Creates a new label block.
146     *
147     * @param text  the text for the label (<code>null</code> not permitted).
148     * @param font  the font (<code>null</code> not permitted).
149     * @param paint the paint (<code>null</code> not permitted).
150     */
151    public LabelBlock(String text, Font font, Paint paint) {
152        this.text = text;
153        this.paint = paint;
154        this.label = TextUtilities.createTextBlock(text, font, this.paint);
155        this.font = font;
156        this.toolTipText = null;
157        this.urlText = null;
158        this.contentAlignmentPoint = TextBlockAnchor.CENTER;
159        this.textAnchor = RectangleAnchor.CENTER;
160    }
161
162    /**
163     * Returns the font.
164     *
165     * @return The font (never <code>null</code>).
166     *
167     * @see #setFont(Font)
168     */
169    public Font getFont() {
170        return this.font;
171    }
172
173    /**
174     * Sets the font and regenerates the label.
175     *
176     * @param font  the font (<code>null</code> not permitted).
177     *
178     * @see #getFont()
179     */
180    public void setFont(Font font) {
181        ParamChecks.nullNotPermitted(font, "font");
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        ParamChecks.nullNotPermitted(paint, "paint");
206        this.paint = paint;
207        this.label = TextUtilities.createTextBlock(this.text, this.font,
208                this.paint);
209    }
210
211    /**
212     * Returns the tool tip text.
213     *
214     * @return The tool tip text (possibly <code>null</code>).
215     *
216     * @see #setToolTipText(String)
217     */
218    public String getToolTipText() {
219        return this.toolTipText;
220    }
221
222    /**
223     * Sets the tool tip text.
224     *
225     * @param text  the text (<code>null</code> permitted).
226     *
227     * @see #getToolTipText()
228     */
229    public void setToolTipText(String text) {
230        this.toolTipText = text;
231    }
232
233    /**
234     * Returns the URL text.
235     *
236     * @return The URL text (possibly <code>null</code>).
237     *
238     * @see #setURLText(String)
239     */
240    public String getURLText() {
241        return this.urlText;
242    }
243
244    /**
245     * Sets the URL text.
246     *
247     * @param text  the text (<code>null</code> permitted).
248     *
249     * @see #getURLText()
250     */
251    public void setURLText(String text) {
252        this.urlText = text;
253    }
254
255    /**
256     * Returns the content alignment point.
257     *
258     * @return The content alignment point (never <code>null</code>).
259     *
260     * @since 1.0.13
261     */
262    public TextBlockAnchor getContentAlignmentPoint() {
263        return this.contentAlignmentPoint;
264    }
265
266    /**
267     * Sets the content alignment point.
268     *
269     * @param anchor  the anchor used to determine the alignment point (never
270     *         <code>null</code>).
271     *
272     * @since 1.0.13
273     */
274    public void setContentAlignmentPoint(TextBlockAnchor anchor) {
275        ParamChecks.nullNotPermitted(anchor, "anchor");
276        this.contentAlignmentPoint = anchor;
277    }
278
279    /**
280     * Returns the text anchor (never <code>null</code>).
281     *
282     * @return The text anchor.
283     *
284     * @since 1.0.13
285     */
286    public RectangleAnchor getTextAnchor() {
287        return this.textAnchor;
288    }
289
290    /**
291     * Sets the text anchor.
292     *
293     * @param anchor  the anchor (<code>null</code> not permitted).
294     *
295     * @since 1.0.13
296     */
297    public void setTextAnchor(RectangleAnchor anchor) {
298        this.textAnchor = anchor;
299    }
300
301    /**
302     * Arranges the contents of the block, within the given constraints, and
303     * returns the block size.
304     *
305     * @param g2  the graphics device.
306     * @param constraint  the constraint (<code>null</code> not permitted).
307     *
308     * @return The block size (in Java2D units, never <code>null</code>).
309     */
310    @Override
311    public Size2D arrange(Graphics2D g2, RectangleConstraint constraint) {
312        g2.setFont(this.font);
313        Size2D s = this.label.calculateDimensions(g2);
314        return new Size2D(calculateTotalWidth(s.getWidth()),
315                calculateTotalHeight(s.getHeight()));
316    }
317
318    /**
319     * Draws the block.
320     *
321     * @param g2  the graphics device.
322     * @param area  the area.
323     */
324    @Override
325    public void draw(Graphics2D g2, Rectangle2D area) {
326        draw(g2, area, null);
327    }
328
329    /**
330     * Draws the block within the specified area.
331     *
332     * @param g2  the graphics device.
333     * @param area  the area.
334     * @param params  ignored (<code>null</code> permitted).
335     *
336     * @return Always <code>null</code>.
337     */
338    @Override
339    public Object draw(Graphics2D g2, Rectangle2D area, Object params) {
340        area = trimMargin(area);
341        drawBorder(g2, area);
342        area = trimBorder(area);
343        area = trimPadding(area);
344
345        // check if we need to collect chart entities from the container
346        EntityBlockParams ebp = null;
347        StandardEntityCollection sec = null;
348        Shape entityArea = null;
349        if (params instanceof EntityBlockParams) {
350            ebp = (EntityBlockParams) params;
351            if (ebp.getGenerateEntities()) {
352                sec = new StandardEntityCollection();
353                entityArea = (Shape) area.clone();
354            }
355        }
356        g2.setPaint(this.paint);
357        g2.setFont(this.font);
358        Point2D pt = RectangleAnchor.coordinates(area, this.textAnchor);
359        this.label.draw(g2, (float) pt.getX(), (float) pt.getY(),
360                this.contentAlignmentPoint);
361        BlockResult result = null;
362        if (ebp != null && sec != null) {
363            if (this.toolTipText != null || this.urlText != null) {
364                ChartEntity entity = new ChartEntity(entityArea,
365                        this.toolTipText, this.urlText);
366                sec.add(entity);
367                result = new BlockResult();
368                result.setEntityCollection(sec);
369            }
370        }
371        return result;
372    }
373
374    /**
375     * Tests this <code>LabelBlock</code> for equality with an arbitrary
376     * object.
377     *
378     * @param obj  the object (<code>null</code> permitted).
379     *
380     * @return A boolean.
381     */
382    @Override
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    @Override
420    public Object clone() throws CloneNotSupportedException {
421        return super.clone();
422    }
423
424    /**
425     * Provides serialization support.
426     *
427     * @param stream  the output stream.
428     *
429     * @throws IOException if there is an I/O error.
430     */
431    private void writeObject(ObjectOutputStream stream) throws IOException {
432        stream.defaultWriteObject();
433        SerialUtilities.writePaint(this.paint, stream);
434    }
435
436    /**
437     * Provides serialization support.
438     *
439     * @param stream  the input stream.
440     *
441     * @throws IOException  if there is an I/O error.
442     * @throws ClassNotFoundException  if there is a classpath problem.
443     */
444    private void readObject(ObjectInputStream stream)
445        throws IOException, ClassNotFoundException {
446        stream.defaultReadObject();
447        this.paint = SerialUtilities.readPaint(stream);
448    }
449
450}