KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > text > TextBlock


1 /* ========================================================================
2  * JCommon : a free general purpose class library for the Java(tm) platform
3  * ========================================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jcommon/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * --------------
28  * TextBlock.java
29  * --------------
30  * (C) Copyright 2003, 2004, by Object Refinery Limited and Contributors.
31  *
32  * Original Author: David Gilbert (for Object Refinery Limited);
33  * Contributor(s): -;
34  *
35  * $Id: TextBlock.java,v 1.13 2005/10/18 13:17:16 mungady Exp $
36  *
37  * Changes
38  * -------
39  * 07-Nov-2003 : Version 1 (DG);
40  * 22-Dec-2003 : Added workaround for Java bug 4245442 (DG);
41  * 09-Jan-2004 : Added an extra draw() method for no rotation case (DG);
42  * 25-Feb-2004 : Added getLines() method (DG);
43  * 22-Mar-2004 : Added equals() method and implemented Serializable (DG);
44  * 24-Mar-2004 : Added 'paint' argument to addLine() method (DG);
45  * 01-Apr-2004 : Changed java.awt.geom.Dimension2D to org.jfree.ui.Size2D
46  * because of JDK bug 4976448 which persists on JDK 1.3.1 (DG);
47  * 04-Oct-2004 : Renamed ShapeUtils --> ShapeUtilities (DG);
48  *
49  */

50  
51 package org.jfree.text;
52
53 import java.awt.Font JavaDoc;
54 import java.awt.Graphics2D JavaDoc;
55 import java.awt.Paint JavaDoc;
56 import java.awt.Shape JavaDoc;
57 import java.awt.geom.Rectangle2D JavaDoc;
58 import java.io.Serializable JavaDoc;
59 import java.util.Collections JavaDoc;
60 import java.util.Iterator JavaDoc;
61 import java.util.List JavaDoc;
62
63 import org.jfree.ui.HorizontalAlignment;
64 import org.jfree.ui.Size2D;
65 import org.jfree.ui.TextAnchor;
66 import org.jfree.util.Log;
67 import org.jfree.util.LogContext;
68 import org.jfree.util.ShapeUtilities;
69
70 /**
71  * A list of {@link TextLine} objects that form a block of text.
72  *
73  * @see TextUtilities#createTextBlock(String, Font, Paint)
74  *
75  * @author David Gilbert
76  */

77 public class TextBlock implements Serializable JavaDoc {
78
79     /** For serialization. */
80     private static final long serialVersionUID = -4333175719424385526L;
81     
82     /** Storage for the lines of text. */
83     private List JavaDoc lines;
84     
85     /** The alignment of the lines. */
86     private HorizontalAlignment lineAlignment;
87     
88     /** Access to logging facilities. */
89     protected static final LogContext logger
90         = Log.createContext(TextBlock.class);
91
92     /**
93      * Creates a new empty text block.
94      */

95     public TextBlock() {
96         this.lines = new java.util.ArrayList JavaDoc();
97         this.lineAlignment = HorizontalAlignment.CENTER;
98     }
99     
100     /**
101      * Returns the alignment of the lines of text within the block.
102      *
103      * @return The alignment (never <code>null</code>).
104      */

105     public HorizontalAlignment getLineAlignment() {
106         return this.lineAlignment;
107     }
108     
109     /**
110      * Sets the alignment of the lines of text within the block.
111      *
112      * @param alignment the alignment (<code>null</code> not permitted).
113      */

114     public void setLineAlignment(HorizontalAlignment alignment) {
115         if (alignment == null) {
116             throw new IllegalArgumentException JavaDoc("Null 'alignment' argument.");
117         }
118         this.lineAlignment = alignment;
119     }
120     
121     /**
122      * Adds a line of text that will be displayed using the specified font.
123      *
124      * @param text the text.
125      * @param font the font.
126      * @param paint the paint.
127      */

128     public void addLine(final String JavaDoc text, final Font JavaDoc font, final Paint JavaDoc paint) {
129         addLine(new TextLine(text, font, paint));
130     }
131     
132     /**
133      * Adds a {@link TextLine} to the block.
134      *
135      * @param line the line.
136      */

137     public void addLine(final TextLine line) {
138         this.lines.add(line);
139     }
140     
141     /**
142      * Returns the last line in the block.
143      *
144      * @return The last line in the block.
145      */

146     public TextLine getLastLine() {
147         TextLine last = null;
148         final int index = this.lines.size() - 1;
149         if (index >= 0) {
150             last = (TextLine) this.lines.get(index);
151         }
152         return last;
153     }
154     
155     /**
156      * Returns an unmodifiable list containing the lines for the text block.
157      *
158      * @return A list of {@link TextLine} objects.
159      */

160     public List JavaDoc getLines() {
161         return Collections.unmodifiableList(this.lines);
162     }
163     
164     /**
165      * Returns the width and height of the text block.
166      *
167      * @param g2 the graphics device.
168      *
169      * @return The width and height.
170      */

171     public Size2D calculateDimensions(final Graphics2D JavaDoc g2) {
172         double width = 0.0;
173         double height = 0.0;
174         final Iterator JavaDoc iterator = this.lines.iterator();
175         while (iterator.hasNext()) {
176             final TextLine line = (TextLine) iterator.next();
177             final Size2D dimension = line.calculateDimensions(g2);
178             width = Math.max(width, dimension.getWidth());
179             height = height + dimension.getHeight();
180         }
181         if (logger.isDebugEnabled()) {
182             logger.debug("width = " + width + ", height = " + height);
183         }
184         return new Size2D(width, height);
185     }
186     
187     /**
188      * Returns the bounds of the text block.
189      *
190      * @param g2 the graphics device (<code>null</code> not permitted).
191      * @param anchorX the x-coordinate for the anchor point.
192      * @param anchorY the y-coordinate for the anchor point.
193      * @param anchor the text block anchor (<code>null</code> not permitted).
194      * @param rotateX the x-coordinate for the rotation point.
195      * @param rotateY the y-coordinate for the rotation point.
196      * @param angle the rotation angle.
197      *
198      * @return The bounds.
199      */

200     public Shape JavaDoc calculateBounds(final Graphics2D JavaDoc g2,
201                                  final float anchorX, final float anchorY,
202                                  final TextBlockAnchor anchor,
203                                  final float rotateX, final float rotateY,
204                                  final double angle) {
205         
206         final Size2D d = calculateDimensions(g2);
207         final float[] offsets = calculateOffsets(
208             anchor, d.getWidth(), d.getHeight()
209         );
210         final Rectangle2D JavaDoc bounds = new Rectangle2D.Double JavaDoc(
211             anchorX + offsets[0], anchorY + offsets[1],
212             d.getWidth(), d.getHeight()
213         );
214         final Shape JavaDoc rotatedBounds = ShapeUtilities.rotateShape(
215             bounds, angle, rotateX, rotateY
216         );
217         return rotatedBounds;
218         
219     }
220     
221     /**
222      * Draws the text block at a specific location.
223      *
224      * @param g2 the graphics device.
225      * @param x the x-coordinate for the anchor point.
226      * @param y the y-coordinate for the anchor point.
227      * @param anchor the anchor point.
228      */

229     public void draw(final Graphics2D JavaDoc g2, final float x, final float y,
230                      final TextBlockAnchor anchor) {
231         draw(g2, x, y, anchor, 0.0f, 0.0f, 0.0);
232     }
233     
234     /**
235      * Draws the text block, aligning it with the specified anchor point and
236      * rotating it about the specified rotation point.
237      *
238      * @param g2 the graphics device.
239      * @param anchorX the x-coordinate for the anchor point.
240      * @param anchorY the y-coordinate for the anchor point.
241      * @param anchor the point on the text block that is aligned to the
242      * anchor point.
243      * @param rotateX the x-coordinate for the rotation point.
244      * @param rotateY the x-coordinate for the rotation point.
245      * @param angle the rotation (in radians).
246      */

247     public void draw(final Graphics2D JavaDoc g2,
248                      final float anchorX, final float anchorY,
249                      final TextBlockAnchor anchor,
250                      final float rotateX, final float rotateY,
251                      final double angle) {
252     
253         final Size2D d = calculateDimensions(g2);
254         final float[] offsets = calculateOffsets(anchor, d.getWidth(),
255                 d.getHeight());
256         final Iterator JavaDoc iterator = this.lines.iterator();
257         float yCursor = 0.0f;
258         while (iterator.hasNext()) {
259             TextLine line = (TextLine) iterator.next();
260             Size2D dimension = line.calculateDimensions(g2);
261             float lineOffset = 0.0f;
262             if (this.lineAlignment == HorizontalAlignment.CENTER) {
263                 lineOffset = (float) (d.getWidth() - dimension.getWidth())
264                     / 2.0f;
265             }
266             else if (this.lineAlignment == HorizontalAlignment.RIGHT) {
267                 lineOffset = (float) (d.getWidth() - dimension.getWidth());
268             }
269             line.draw(
270                 g2, anchorX + offsets[0] + lineOffset, anchorY + offsets[1] + yCursor,
271                 TextAnchor.TOP_LEFT, rotateX, rotateY, angle
272             );
273             yCursor = yCursor + (float) dimension.getHeight();
274         }
275         
276     }
277  
278     /**
279      * Calculates the x and y offsets required to align the text block with the
280      * specified anchor point. This assumes that the top left of the text
281      * block is at (0.0, 0.0).
282      *
283      * @param anchor the anchor position.
284      * @param width the width of the text block.
285      * @param height the height of the text block.
286      *
287      * @return The offsets (float[0] = x offset, float[1] = y offset).
288      */

289     private float[] calculateOffsets(final TextBlockAnchor anchor,
290                                      final double width, final double height) {
291         final float[] result = new float[2];
292         float xAdj = 0.0f;
293         float yAdj = 0.0f;
294
295         if (anchor == TextBlockAnchor.TOP_CENTER
296                 || anchor == TextBlockAnchor.CENTER
297                 || anchor == TextBlockAnchor.BOTTOM_CENTER) {
298                     
299             xAdj = (float) -width / 2.0f;
300             
301         }
302         else if (anchor == TextBlockAnchor.TOP_RIGHT
303                 || anchor == TextBlockAnchor.CENTER_RIGHT
304                 || anchor == TextBlockAnchor.BOTTOM_RIGHT) {
305                     
306             xAdj = (float) -width;
307             
308         }
309
310         if (anchor == TextBlockAnchor.TOP_LEFT
311                 || anchor == TextBlockAnchor.TOP_CENTER
312                 || anchor == TextBlockAnchor.TOP_RIGHT) {
313                     
314             yAdj = 0.0f;
315             
316         }
317         else if (anchor == TextBlockAnchor.CENTER_LEFT
318                 || anchor == TextBlockAnchor.CENTER
319                 || anchor == TextBlockAnchor.CENTER_RIGHT) {
320                     
321             yAdj = (float) -height / 2.0f;
322             
323         }
324         else if (anchor == TextBlockAnchor.BOTTOM_LEFT
325                 || anchor == TextBlockAnchor.BOTTOM_CENTER
326                 || anchor == TextBlockAnchor.BOTTOM_RIGHT) {
327                     
328             yAdj = (float) -height;
329             
330         }
331         result[0] = xAdj;
332         result[1] = yAdj;
333         return result;
334     }
335     
336     /**
337      * Tests this object for equality with an arbitrary object.
338      *
339      * @param obj the object to test against (<code>null</code> permitted).
340      *
341      * @return A boolean.
342      */

343     public boolean equals(final Object JavaDoc obj) {
344         if (obj == this) {
345             return true;
346         }
347         if (obj instanceof TextBlock) {
348             final TextBlock block = (TextBlock) obj;
349             return this.lines.equals(block.lines);
350         }
351         return false;
352     }
353
354     /**
355      * Returns a hash code for this object.
356      *
357      * @return A hash code.
358      */

359     public int hashCode() {
360         return (this.lines != null ? this.lines.hashCode() : 0);
361     }
362 }
363
Popular Tags