001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * ------------------- 028 * TextAnnotation.java 029 * ------------------- 030 * (C) Copyright 2002-2013, by Object Refinery Limited and Contributors. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): Peter Kolb (patch 2809117); 034 * Martin Hoeller; 035 * 036 * Changes: 037 * -------- 038 * 28-Aug-2002 : Version 1 (DG); 039 * 07-Nov-2002 : Fixed errors reported by Checkstyle, added accessor 040 * methods (DG); 041 * 13-Jan-2003 : Reviewed Javadocs (DG); 042 * 26-Mar-2003 : Implemented Serializable (DG); 043 * 02-Jun-2003 : Added anchor and rotation settings (DG); 044 * 19-Aug-2003 : Added equals() method and implemented Cloneable (DG); 045 * 29-Sep-2004 : Updated equals() method (DG); 046 * 06-Jun-2005 : Fixed equals() method to work with GradientPaint (DG); 047 * ------------- JFREECHART 1.0.x --------------------------------------------- 048 * 16-Jan-2007 : Added argument checks, fixed hashCode() method and updated 049 * API docs (DG); 050 * 24-Jun-2009 : Fire change events (see patch 2809117 by PK) (DG); 051 * 28-Oct-2011 : Added missing argument check, Bug #3428870 (MH); 052 * 01-Jul-2013 : Added missing AnnotationChangeEvent for setText() (DG); 053 * 054 */ 055 056package org.jfree.chart.annotations; 057 058import java.awt.Color; 059import java.awt.Font; 060import java.awt.Paint; 061import java.io.IOException; 062import java.io.ObjectInputStream; 063import java.io.ObjectOutputStream; 064import java.io.Serializable; 065 066import org.jfree.chart.HashUtilities; 067import org.jfree.chart.event.AnnotationChangeEvent; 068import org.jfree.chart.util.ParamChecks; 069import org.jfree.io.SerialUtilities; 070import org.jfree.ui.TextAnchor; 071import org.jfree.util.ObjectUtilities; 072import org.jfree.util.PaintUtilities; 073 074/** 075 * A base class for text annotations. This class records the content but not 076 * the location of the annotation. 077 */ 078public class TextAnnotation extends AbstractAnnotation implements Serializable { 079 080 /** For serialization. */ 081 private static final long serialVersionUID = 7008912287533127432L; 082 083 /** The default font. */ 084 public static final Font DEFAULT_FONT 085 = new Font("SansSerif", Font.PLAIN, 10); 086 087 /** The default paint. */ 088 public static final Paint DEFAULT_PAINT = Color.black; 089 090 /** The default text anchor. */ 091 public static final TextAnchor DEFAULT_TEXT_ANCHOR = TextAnchor.CENTER; 092 093 /** The default rotation anchor. */ 094 public static final TextAnchor DEFAULT_ROTATION_ANCHOR = TextAnchor.CENTER; 095 096 /** The default rotation angle. */ 097 public static final double DEFAULT_ROTATION_ANGLE = 0.0; 098 099 /** The text. */ 100 private String text; 101 102 /** The font. */ 103 private Font font; 104 105 /** The paint. */ 106 private transient Paint paint; 107 108 /** The text anchor. */ 109 private TextAnchor textAnchor; 110 111 /** The rotation anchor. */ 112 private TextAnchor rotationAnchor; 113 114 /** The rotation angle. */ 115 private double rotationAngle; 116 117 /** 118 * Creates a text annotation with default settings. 119 * 120 * @param text the text (<code>null</code> not permitted). 121 */ 122 protected TextAnnotation(String text) { 123 super(); 124 ParamChecks.nullNotPermitted(text, "text"); 125 this.text = text; 126 this.font = DEFAULT_FONT; 127 this.paint = DEFAULT_PAINT; 128 this.textAnchor = DEFAULT_TEXT_ANCHOR; 129 this.rotationAnchor = DEFAULT_ROTATION_ANCHOR; 130 this.rotationAngle = DEFAULT_ROTATION_ANGLE; 131 } 132 133 /** 134 * Returns the text for the annotation. 135 * 136 * @return The text (never <code>null</code>). 137 * 138 * @see #setText(String) 139 */ 140 public String getText() { 141 return this.text; 142 } 143 144 /** 145 * Sets the text for the annotation and sends an 146 * {@link AnnotationChangeEvent} to all registered listeners. 147 * 148 * @param text the text (<code>null</code> not permitted). 149 * 150 * @see #getText() 151 */ 152 public void setText(String text) { 153 ParamChecks.nullNotPermitted(text, "text"); 154 this.text = text; 155 fireAnnotationChanged(); 156 } 157 158 /** 159 * Returns the font for the annotation. 160 * 161 * @return The font (never <code>null</code>). 162 * 163 * @see #setFont(Font) 164 */ 165 public Font getFont() { 166 return this.font; 167 } 168 169 /** 170 * Sets the font for the annotation and sends an 171 * {@link AnnotationChangeEvent} to all registered listeners. 172 * 173 * @param font the font (<code>null</code> not permitted). 174 * 175 * @see #getFont() 176 */ 177 public void setFont(Font font) { 178 ParamChecks.nullNotPermitted(font, "font"); 179 this.font = font; 180 fireAnnotationChanged(); 181 } 182 183 /** 184 * Returns the paint for the annotation. 185 * 186 * @return The paint (never <code>null</code>). 187 * 188 * @see #setPaint(Paint) 189 */ 190 public Paint getPaint() { 191 return this.paint; 192 } 193 194 /** 195 * Sets the paint for the annotation and sends an 196 * {@link AnnotationChangeEvent} to all registered listeners. 197 * 198 * @param paint the paint (<code>null</code> not permitted). 199 * 200 * @see #getPaint() 201 */ 202 public void setPaint(Paint paint) { 203 ParamChecks.nullNotPermitted(paint, "paint"); 204 this.paint = paint; 205 fireAnnotationChanged(); 206 } 207 208 /** 209 * Returns the text anchor. 210 * 211 * @return The text anchor. 212 * 213 * @see #setTextAnchor(TextAnchor) 214 */ 215 public TextAnchor getTextAnchor() { 216 return this.textAnchor; 217 } 218 219 /** 220 * Sets the text anchor (the point on the text bounding rectangle that is 221 * aligned to the (x, y) coordinate of the annotation) and sends an 222 * {@link AnnotationChangeEvent} to all registered listeners. 223 * 224 * @param anchor the anchor point (<code>null</code> not permitted). 225 * 226 * @see #getTextAnchor() 227 */ 228 public void setTextAnchor(TextAnchor anchor) { 229 ParamChecks.nullNotPermitted(anchor, "anchor"); 230 this.textAnchor = anchor; 231 fireAnnotationChanged(); 232 } 233 234 /** 235 * Returns the rotation anchor. 236 * 237 * @return The rotation anchor point (never <code>null</code>). 238 * 239 * @see #setRotationAnchor(TextAnchor) 240 */ 241 public TextAnchor getRotationAnchor() { 242 return this.rotationAnchor; 243 } 244 245 /** 246 * Sets the rotation anchor point and sends an 247 * {@link AnnotationChangeEvent} to all registered listeners. 248 * 249 * @param anchor the anchor (<code>null</code> not permitted). 250 * 251 * @see #getRotationAnchor() 252 */ 253 public void setRotationAnchor(TextAnchor anchor) { 254 ParamChecks.nullNotPermitted(anchor, "anchor"); 255 this.rotationAnchor = anchor; 256 fireAnnotationChanged(); 257 } 258 259 /** 260 * Returns the rotation angle in radians. 261 * 262 * @return The rotation angle. 263 * 264 * @see #setRotationAngle(double) 265 */ 266 public double getRotationAngle() { 267 return this.rotationAngle; 268 } 269 270 /** 271 * Sets the rotation angle and sends an {@link AnnotationChangeEvent} to 272 * all registered listeners. The angle is measured clockwise in radians. 273 * 274 * @param angle the angle (in radians). 275 * 276 * @see #getRotationAngle() 277 */ 278 public void setRotationAngle(double angle) { 279 this.rotationAngle = angle; 280 fireAnnotationChanged(); 281 } 282 283 /** 284 * Tests this object for equality with an arbitrary object. 285 * 286 * @param obj the object (<code>null</code> permitted). 287 * 288 * @return <code>true</code> or <code>false</code>. 289 */ 290 @Override 291 public boolean equals(Object obj) { 292 if (obj == this) { 293 return true; 294 } 295 // now try to reject equality... 296 if (!(obj instanceof TextAnnotation)) { 297 return false; 298 } 299 TextAnnotation that = (TextAnnotation) obj; 300 if (!ObjectUtilities.equal(this.text, that.getText())) { 301 return false; 302 } 303 if (!ObjectUtilities.equal(this.font, that.getFont())) { 304 return false; 305 } 306 if (!PaintUtilities.equal(this.paint, that.getPaint())) { 307 return false; 308 } 309 if (!ObjectUtilities.equal(this.textAnchor, that.getTextAnchor())) { 310 return false; 311 } 312 if (!ObjectUtilities.equal(this.rotationAnchor, 313 that.getRotationAnchor())) { 314 return false; 315 } 316 if (this.rotationAngle != that.getRotationAngle()) { 317 return false; 318 } 319 320 // seem to be the same... 321 return true; 322 323 } 324 325 /** 326 * Returns a hash code for this instance. 327 * 328 * @return A hash code. 329 */ 330 @Override 331 public int hashCode() { 332 int result = 193; 333 result = 37 * result + this.font.hashCode(); 334 result = 37 * result + HashUtilities.hashCodeForPaint(this.paint); 335 result = 37 * result + this.rotationAnchor.hashCode(); 336 long temp = Double.doubleToLongBits(this.rotationAngle); 337 result = 37 * result + (int) (temp ^ (temp >>> 32)); 338 result = 37 * result + this.text.hashCode(); 339 result = 37 * result + this.textAnchor.hashCode(); 340 return result; 341 } 342 343 /** 344 * Provides serialization support. 345 * 346 * @param stream the output stream. 347 * 348 * @throws IOException if there is an I/O error. 349 */ 350 private void writeObject(ObjectOutputStream stream) throws IOException { 351 stream.defaultWriteObject(); 352 SerialUtilities.writePaint(this.paint, stream); 353 } 354 355 /** 356 * Provides serialization support. 357 * 358 * @param stream the input stream. 359 * 360 * @throws IOException if there is an I/O error. 361 * @throws ClassNotFoundException if there is a classpath problem. 362 */ 363 private void readObject(ObjectInputStream stream) 364 throws IOException, ClassNotFoundException { 365 stream.defaultReadObject(); 366 this.paint = SerialUtilities.readPaint(stream); 367 } 368 369}