Source for org.jfree.text.TextBox

   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:  * TextBox.java
  29:  * ------------
  30:  * (C) Copyright 2004, by Object Refinery Limited and Contributors.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: TextBox.java,v 1.12 2005/11/16 15:58:41 taqua Exp $
  36:  *
  37:  * Changes
  38:  * -------
  39:  * 09-Mar-2004 : Version 1 (DG);
  40:  * 22-Mar-2004 : Added equals() method and implemented Serializable (DG);
  41:  * 09-Nov-2004 : Renamed getAdjustedHeight() --> calculateExtendedHeight() in 
  42:  *               Spacer class (DG);
  43:  * 22-Feb-2005 : Replaced Spacer with RectangleInsets (DG);
  44:  *
  45:  */
  46: 
  47: package org.jfree.text;
  48: 
  49: import java.awt.BasicStroke;
  50: import java.awt.Color;
  51: import java.awt.Font;
  52: import java.awt.Graphics2D;
  53: import java.awt.Paint;
  54: import java.awt.Stroke;
  55: import java.awt.geom.Rectangle2D;
  56: import java.io.IOException;
  57: import java.io.ObjectInputStream;
  58: import java.io.ObjectOutputStream;
  59: import java.io.Serializable;
  60: 
  61: import org.jfree.io.SerialUtilities;
  62: import org.jfree.ui.RectangleAnchor;
  63: import org.jfree.ui.RectangleInsets;
  64: import org.jfree.ui.Size2D;
  65: import org.jfree.util.ObjectUtilities;
  66: 
  67: /**
  68:  * A box containing a text block.
  69:  *
  70:  * @author David Gilbert
  71:  */
  72: public class TextBox implements Serializable {
  73:     
  74:     /** For serialization. */
  75:     private static final long serialVersionUID = 3360220213180203706L;
  76:     
  77:     /** The outline paint. */
  78:     private transient Paint outlinePaint;
  79:     
  80:     /** The outline stroke. */
  81:     private transient Stroke outlineStroke;
  82:     
  83:     /** The interior space. */
  84:     private RectangleInsets interiorGap;
  85:     
  86:     /** The background paint. */
  87:     private transient Paint backgroundPaint;
  88:     
  89:     /** The shadow paint. */
  90:     private transient Paint shadowPaint;
  91:     
  92:     /** The shadow x-offset. */
  93:     private double shadowXOffset = 2.0;
  94:     
  95:     /** The shadow y-offset. */
  96:     private double shadowYOffset = 2.0;
  97:     
  98:     /** The text block. */
  99:     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: }