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 }