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