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