001 /* ========================================================================
002 * JCommon : a free general purpose class library for the Java(tm) platform
003 * ========================================================================
004 *
005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jcommon/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 * TextBox.java
029 * ------------
030 * (C) Copyright 2004, by Object Refinery Limited and Contributors.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * $Id: TextBox.java,v 1.12 2005/11/16 15:58:41 taqua Exp $
036 *
037 * Changes
038 * -------
039 * 09-Mar-2004 : Version 1 (DG);
040 * 22-Mar-2004 : Added equals() method and implemented Serializable (DG);
041 * 09-Nov-2004 : Renamed getAdjustedHeight() --> calculateExtendedHeight() in
042 * Spacer class (DG);
043 * 22-Feb-2005 : Replaced Spacer with RectangleInsets (DG);
044 *
045 */
046
047 package org.jfree.text;
048
049 import java.awt.BasicStroke;
050 import java.awt.Color;
051 import java.awt.Font;
052 import java.awt.Graphics2D;
053 import java.awt.Paint;
054 import java.awt.Stroke;
055 import java.awt.geom.Rectangle2D;
056 import java.io.IOException;
057 import java.io.ObjectInputStream;
058 import java.io.ObjectOutputStream;
059 import java.io.Serializable;
060
061 import org.jfree.io.SerialUtilities;
062 import org.jfree.ui.RectangleAnchor;
063 import org.jfree.ui.RectangleInsets;
064 import org.jfree.ui.Size2D;
065 import org.jfree.util.ObjectUtilities;
066
067 /**
068 * A box containing a text block.
069 *
070 * @author David Gilbert
071 */
072 public class TextBox implements Serializable {
073
074 /** For serialization. */
075 private static final long serialVersionUID = 3360220213180203706L;
076
077 /** The outline paint. */
078 private transient Paint outlinePaint;
079
080 /** The outline stroke. */
081 private transient Stroke outlineStroke;
082
083 /** The interior space. */
084 private RectangleInsets interiorGap;
085
086 /** The background paint. */
087 private transient Paint backgroundPaint;
088
089 /** The shadow paint. */
090 private transient Paint shadowPaint;
091
092 /** The shadow x-offset. */
093 private double shadowXOffset = 2.0;
094
095 /** The shadow y-offset. */
096 private double shadowYOffset = 2.0;
097
098 /** The text block. */
099 private TextBlock textBlock;
100
101 /**
102 * Creates an empty text box.
103 */
104 public TextBox() {
105 this((TextBlock) null);
106 }
107
108 /**
109 * Creates a text box.
110 *
111 * @param text the text.
112 */
113 public TextBox(final String text) {
114 this((TextBlock) null);
115 if (text != null) {
116 this.textBlock = new TextBlock();
117 this.textBlock.addLine(
118 text, new Font("SansSerif", Font.PLAIN, 10),
119 Color.black
120 );
121 }
122 }
123
124 /**
125 * Creates a new text box.
126 *
127 * @param block the text block.
128 */
129 public TextBox(final TextBlock block) {
130 this.outlinePaint = Color.black;
131 this.outlineStroke = new BasicStroke(1.0f);
132 this.interiorGap = new RectangleInsets(1.0, 3.0, 1.0, 3.0);
133 this.backgroundPaint = new Color(255, 255, 192);
134 this.shadowPaint = Color.gray;
135 this.shadowXOffset = 2.0;
136 this.shadowYOffset = 2.0;
137 this.textBlock = block;
138 }
139
140 /**
141 * Returns the outline paint.
142 *
143 * @return The outline paint.
144 */
145 public Paint getOutlinePaint() {
146 return this.outlinePaint;
147 }
148
149 /**
150 * Sets the outline paint.
151 *
152 * @param paint the paint.
153 */
154 public void setOutlinePaint(final Paint paint) {
155 this.outlinePaint = paint;
156 }
157
158 /**
159 * Returns the outline stroke.
160 *
161 * @return The outline stroke.
162 */
163 public Stroke getOutlineStroke() {
164 return this.outlineStroke;
165 }
166
167 /**
168 * Sets the outline stroke.
169 *
170 * @param stroke the stroke.
171 */
172 public void setOutlineStroke(final Stroke stroke) {
173 this.outlineStroke = stroke;
174 }
175
176 /**
177 * Returns the interior gap.
178 *
179 * @return The interior gap.
180 */
181 public RectangleInsets getInteriorGap() {
182 return this.interiorGap;
183 }
184
185 /**
186 * Sets the interior gap.
187 *
188 * @param gap the gap.
189 */
190 public void setInteriorGap(final RectangleInsets gap) {
191 this.interiorGap = gap;
192 }
193
194 /**
195 * Returns the background paint.
196 *
197 * @return The background paint.
198 */
199 public Paint getBackgroundPaint() {
200 return this.backgroundPaint;
201 }
202
203 /**
204 * Sets the background paint.
205 *
206 * @param paint the paint.
207 */
208 public void setBackgroundPaint(final Paint paint) {
209 this.backgroundPaint = paint;
210 }
211
212 /**
213 * Returns the shadow paint.
214 *
215 * @return The shadow paint.
216 */
217 public Paint getShadowPaint() {
218 return this.shadowPaint;
219 }
220
221 /**
222 * Sets the shadow paint.
223 *
224 * @param paint the paint.
225 */
226 public void setShadowPaint(final Paint paint) {
227 this.shadowPaint = paint;
228 }
229
230 /**
231 * Returns the x-offset for the shadow effect.
232 *
233 * @return The offset.
234 */
235 public double getShadowXOffset() {
236 return this.shadowXOffset;
237 }
238
239 /**
240 * Sets the x-offset for the shadow effect.
241 *
242 * @param offset the offset (in Java2D units).
243 */
244 public void setShadowXOffset(final double offset) {
245 this.shadowXOffset = offset;
246 }
247
248 /**
249 * Returns the y-offset for the shadow effect.
250 *
251 * @return The offset.
252 */
253 public double getShadowYOffset() {
254 return this.shadowYOffset;
255 }
256
257 /**
258 * Sets the y-offset for the shadow effect.
259 *
260 * @param offset the offset (in Java2D units).
261 */
262 public void setShadowYOffset(final double offset) {
263 this.shadowYOffset = offset;
264 }
265
266 /**
267 * Returns the text block.
268 *
269 * @return The text block.
270 */
271 public TextBlock getTextBlock() {
272 return this.textBlock;
273 }
274
275 /**
276 * Sets the text block.
277 *
278 * @param block the block.
279 */
280 public void setTextBlock(final TextBlock block) {
281 this.textBlock = block;
282 }
283
284 /**
285 * Draws the text box.
286 *
287 * @param g2 the graphics device.
288 * @param x the x-coordinate.
289 * @param y the y-coordinate.
290 * @param anchor the anchor point.
291 */
292 public void draw(final Graphics2D g2,
293 final float x, final float y,
294 final RectangleAnchor anchor) {
295 final Size2D d1 = this.textBlock.calculateDimensions(g2);
296 final double w = this.interiorGap.extendWidth(d1.getWidth());
297 final double h = this.interiorGap.extendHeight(d1.getHeight());
298 final Size2D d2 = new Size2D(w, h);
299 final Rectangle2D bounds
300 = RectangleAnchor.createRectangle(d2, x, y, anchor);
301
302 if (this.shadowPaint != null) {
303 final Rectangle2D shadow = new Rectangle2D.Double(
304 bounds.getX() + this.shadowXOffset,
305 bounds.getY() + this.shadowYOffset,
306 bounds.getWidth(), bounds.getHeight()
307 );
308 g2.setPaint(this.shadowPaint);
309 g2.fill(shadow);
310 }
311 if (this.backgroundPaint != null) {
312 g2.setPaint(this.backgroundPaint);
313 g2.fill(bounds);
314 }
315
316 if (this.outlinePaint != null && this.outlineStroke != null) {
317 g2.setPaint(this.outlinePaint);
318 g2.setStroke(this.outlineStroke);
319 g2.draw(bounds);
320 }
321
322 this.textBlock.draw(
323 g2, (float) bounds.getCenterX(), (float) bounds.getCenterY(),
324 TextBlockAnchor.CENTER
325 );
326
327 }
328
329 /**
330 * Returns the height of the text box.
331 *
332 * @param g2 the graphics device.
333 *
334 * @return The height (in Java2D units).
335 */
336 public double getHeight(final Graphics2D g2) {
337 final Size2D d = this.textBlock.calculateDimensions(g2);
338 return this.interiorGap.extendHeight(d.getHeight());
339 }
340
341 /**
342 * Tests this object for equality with an arbitrary object.
343 *
344 * @param obj the object to test against (<code>null</code> permitted).
345 *
346 * @return A boolean.
347 */
348 public boolean equals(final Object obj) {
349 if (obj == this) {
350 return true;
351 }
352 if (!(obj instanceof TextBox)) {
353 return false;
354 }
355 final TextBox that = (TextBox) obj;
356 if (!ObjectUtilities.equal(this.outlinePaint, that.outlinePaint)) {
357 return false;
358 }
359 if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
360 return false;
361 }
362 if (!ObjectUtilities.equal(this.interiorGap, that.interiorGap)) {
363 return false;
364 }
365 if (!ObjectUtilities.equal(this.backgroundPaint,
366 that.backgroundPaint)) {
367 return false;
368 }
369 if (!ObjectUtilities.equal(this.shadowPaint, that.shadowPaint)) {
370 return false;
371 }
372 if (this.shadowXOffset != that.shadowXOffset) {
373 return false;
374 }
375 if (this.shadowYOffset != that.shadowYOffset) {
376 return false;
377 }
378 if (!ObjectUtilities.equal(this.textBlock, that.textBlock)) {
379 return false;
380 }
381
382 return true;
383 }
384
385 /**
386 * Returns a hash code for this object.
387 *
388 * @return A hash code.
389 */
390 public int hashCode() {
391 int result;
392 long temp;
393 result = (this.outlinePaint != null ? this.outlinePaint.hashCode() : 0);
394 result = 29 * result + (this.outlineStroke != null
395 ? this.outlineStroke.hashCode() : 0);
396 result = 29 * result + (this.interiorGap != null
397 ? this.interiorGap.hashCode() : 0);
398 result = 29 * result + (this.backgroundPaint != null
399 ? this.backgroundPaint.hashCode() : 0);
400 result = 29 * result + (this.shadowPaint != null
401 ? this.shadowPaint.hashCode() : 0);
402 temp = this.shadowXOffset != +0.0d
403 ? Double.doubleToLongBits(this.shadowXOffset) : 0L;
404 result = 29 * result + (int) (temp ^ (temp >>> 32));
405 temp = this.shadowYOffset != +0.0d
406 ? Double.doubleToLongBits(this.shadowYOffset) : 0L;
407 result = 29 * result + (int) (temp ^ (temp >>> 32));
408 result = 29 * result + (this.textBlock != null
409 ? this.textBlock.hashCode() : 0);
410 return result;
411 }
412
413 /**
414 * Provides serialization support.
415 *
416 * @param stream the output stream.
417 *
418 * @throws IOException if there is an I/O error.
419 */
420 private void writeObject(final ObjectOutputStream stream)
421 throws IOException {
422 stream.defaultWriteObject();
423 SerialUtilities.writePaint(this.outlinePaint, stream);
424 SerialUtilities.writeStroke(this.outlineStroke, stream);
425 SerialUtilities.writePaint(this.backgroundPaint, stream);
426 SerialUtilities.writePaint(this.shadowPaint, stream);
427 }
428
429 /**
430 * Provides serialization support.
431 *
432 * @param stream the input stream.
433 *
434 * @throws IOException if there is an I/O error.
435 * @throws ClassNotFoundException if there is a classpath problem.
436 */
437 private void readObject(final ObjectInputStream stream)
438 throws IOException, ClassNotFoundException {
439 stream.defaultReadObject();
440 this.outlinePaint = SerialUtilities.readPaint(stream);
441 this.outlineStroke = SerialUtilities.readStroke(stream);
442 this.backgroundPaint = SerialUtilities.readPaint(stream);
443 this.shadowPaint = SerialUtilities.readPaint(stream);
444 }
445
446
447 }