001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2017, 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 * LabelBlock.java 029 * --------------- 030 * (C) Copyright 2004-2017, by Object Refinery Limited. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): Pierre-Marie Le Biot; 034 * 035 */ 036 037package org.jfree.chart.block; 038 039import java.awt.Color; 040import java.awt.Font; 041import java.awt.Graphics2D; 042import java.awt.Paint; 043import java.awt.Shape; 044import java.awt.geom.Point2D; 045import java.awt.geom.Rectangle2D; 046import java.io.IOException; 047import java.io.ObjectInputStream; 048import java.io.ObjectOutputStream; 049 050import org.jfree.chart.entity.ChartEntity; 051import org.jfree.chart.entity.StandardEntityCollection; 052import org.jfree.chart.text.TextBlock; 053import org.jfree.chart.text.TextBlockAnchor; 054import org.jfree.chart.text.TextUtils; 055import org.jfree.chart.ui.RectangleAnchor; 056import org.jfree.chart.ui.Size2D; 057import org.jfree.chart.util.ObjectUtils; 058import org.jfree.chart.util.PaintUtils; 059import org.jfree.chart.util.Args; 060import org.jfree.chart.util.PublicCloneable; 061import org.jfree.chart.util.SerialUtils; 062 063/** 064 * A block containing a label. 065 */ 066public class LabelBlock extends AbstractBlock 067 implements Block, PublicCloneable { 068 069 /** For serialization. */ 070 static final long serialVersionUID = 249626098864178017L; 071 072 /** 073 * The text for the label - retained in case the label needs 074 * regenerating (for example, to change the font). 075 */ 076 private String text; 077 078 /** The label. */ 079 private TextBlock label; 080 081 /** The font. */ 082 private Font font; 083 084 /** The tool tip text (can be {@code null}). */ 085 private String toolTipText; 086 087 /** The URL text (can be {@code null}). */ 088 private String urlText; 089 090 /** The default color. */ 091 public static final Paint DEFAULT_PAINT = Color.BLACK; 092 093 /** The paint. */ 094 private transient Paint paint; 095 096 /** 097 * The content alignment point. 098 * 099 * @since 1.0.13 100 */ 101 private TextBlockAnchor contentAlignmentPoint; 102 103 /** 104 * The anchor point for the text. 105 * 106 * @since 1.0.13 107 */ 108 private RectangleAnchor textAnchor; 109 110 /** 111 * Creates a new label block. 112 * 113 * @param label the label ({@code null} not permitted). 114 */ 115 public LabelBlock(String label) { 116 this(label, new Font("SansSerif", Font.PLAIN, 10), DEFAULT_PAINT); 117 } 118 119 /** 120 * Creates a new label block. 121 * 122 * @param text the text for the label ({@code null} not permitted). 123 * @param font the font ({@code null} not permitted). 124 */ 125 public LabelBlock(String text, Font font) { 126 this(text, font, DEFAULT_PAINT); 127 } 128 129 /** 130 * Creates a new label block. 131 * 132 * @param text the text for the label ({@code null} not permitted). 133 * @param font the font ({@code null} not permitted). 134 * @param paint the paint ({@code null} not permitted). 135 */ 136 public LabelBlock(String text, Font font, Paint paint) { 137 this.text = text; 138 this.paint = paint; 139 this.label = TextUtils.createTextBlock(text, font, this.paint); 140 this.font = font; 141 this.toolTipText = null; 142 this.urlText = null; 143 this.contentAlignmentPoint = TextBlockAnchor.CENTER; 144 this.textAnchor = RectangleAnchor.CENTER; 145 } 146 147 /** 148 * Returns the font. 149 * 150 * @return The font (never {@code null}). 151 * 152 * @see #setFont(Font) 153 */ 154 public Font getFont() { 155 return this.font; 156 } 157 158 /** 159 * Sets the font and regenerates the label. 160 * 161 * @param font the font ({@code null} not permitted). 162 * 163 * @see #getFont() 164 */ 165 public void setFont(Font font) { 166 Args.nullNotPermitted(font, "font"); 167 this.font = font; 168 this.label = TextUtils.createTextBlock(this.text, font, this.paint); 169 } 170 171 /** 172 * Returns the paint. 173 * 174 * @return The paint (never {@code null}). 175 * 176 * @see #setPaint(Paint) 177 */ 178 public Paint getPaint() { 179 return this.paint; 180 } 181 182 /** 183 * Sets the paint and regenerates the label. 184 * 185 * @param paint the paint ({@code null} not permitted). 186 * 187 * @see #getPaint() 188 */ 189 public void setPaint(Paint paint) { 190 Args.nullNotPermitted(paint, "paint"); 191 this.paint = paint; 192 this.label = TextUtils.createTextBlock(this.text, this.font, 193 this.paint); 194 } 195 196 /** 197 * Returns the tool tip text. 198 * 199 * @return The tool tip text (possibly {@code null}). 200 * 201 * @see #setToolTipText(String) 202 */ 203 public String getToolTipText() { 204 return this.toolTipText; 205 } 206 207 /** 208 * Sets the tool tip text. 209 * 210 * @param text the text ({@code null} permitted). 211 * 212 * @see #getToolTipText() 213 */ 214 public void setToolTipText(String text) { 215 this.toolTipText = text; 216 } 217 218 /** 219 * Returns the URL text. 220 * 221 * @return The URL text (possibly {@code null}). 222 * 223 * @see #setURLText(String) 224 */ 225 public String getURLText() { 226 return this.urlText; 227 } 228 229 /** 230 * Sets the URL text. 231 * 232 * @param text the text ({@code null} permitted). 233 * 234 * @see #getURLText() 235 */ 236 public void setURLText(String text) { 237 this.urlText = text; 238 } 239 240 /** 241 * Returns the content alignment point. 242 * 243 * @return The content alignment point (never {@code null}). 244 * 245 * @since 1.0.13 246 */ 247 public TextBlockAnchor getContentAlignmentPoint() { 248 return this.contentAlignmentPoint; 249 } 250 251 /** 252 * Sets the content alignment point. 253 * 254 * @param anchor the anchor used to determine the alignment point (never 255 * {@code null}). 256 * 257 * @since 1.0.13 258 */ 259 public void setContentAlignmentPoint(TextBlockAnchor anchor) { 260 Args.nullNotPermitted(anchor, "anchor"); 261 this.contentAlignmentPoint = anchor; 262 } 263 264 /** 265 * Returns the text anchor (never {@code null}). 266 * 267 * @return The text anchor. 268 * 269 * @since 1.0.13 270 */ 271 public RectangleAnchor getTextAnchor() { 272 return this.textAnchor; 273 } 274 275 /** 276 * Sets the text anchor. 277 * 278 * @param anchor the anchor ({@code null} not permitted). 279 * 280 * @since 1.0.13 281 */ 282 public void setTextAnchor(RectangleAnchor anchor) { 283 this.textAnchor = anchor; 284 } 285 286 /** 287 * Arranges the contents of the block, within the given constraints, and 288 * returns the block size. 289 * 290 * @param g2 the graphics device. 291 * @param constraint the constraint ({@code null} not permitted). 292 * 293 * @return The block size (in Java2D units, never {@code null}). 294 */ 295 @Override 296 public Size2D arrange(Graphics2D g2, RectangleConstraint constraint) { 297 g2.setFont(this.font); 298 Size2D s = this.label.calculateDimensions(g2); 299 return new Size2D(calculateTotalWidth(s.getWidth()), 300 calculateTotalHeight(s.getHeight())); 301 } 302 303 /** 304 * Draws the block. 305 * 306 * @param g2 the graphics device. 307 * @param area the area. 308 */ 309 @Override 310 public void draw(Graphics2D g2, Rectangle2D area) { 311 draw(g2, area, null); 312 } 313 314 /** 315 * Draws the block within the specified area. 316 * 317 * @param g2 the graphics device. 318 * @param area the area. 319 * @param params ignored ({@code null} permitted). 320 * 321 * @return Always {@code null}. 322 */ 323 @Override 324 public Object draw(Graphics2D g2, Rectangle2D area, Object params) { 325 area = trimMargin(area); 326 drawBorder(g2, area); 327 area = trimBorder(area); 328 area = trimPadding(area); 329 330 // check if we need to collect chart entities from the container 331 EntityBlockParams ebp = null; 332 StandardEntityCollection sec = null; 333 Shape entityArea = null; 334 if (params instanceof EntityBlockParams) { 335 ebp = (EntityBlockParams) params; 336 if (ebp.getGenerateEntities()) { 337 sec = new StandardEntityCollection(); 338 entityArea = (Shape) area.clone(); 339 } 340 } 341 g2.setPaint(this.paint); 342 g2.setFont(this.font); 343 Point2D pt = this.textAnchor.getAnchorPoint(area); 344 this.label.draw(g2, (float) pt.getX(), (float) pt.getY(), 345 this.contentAlignmentPoint); 346 BlockResult result = null; 347 if (ebp != null && sec != null) { 348 if (this.toolTipText != null || this.urlText != null) { 349 ChartEntity entity = new ChartEntity(entityArea, 350 this.toolTipText, this.urlText); 351 sec.add(entity); 352 result = new BlockResult(); 353 result.setEntityCollection(sec); 354 } 355 } 356 return result; 357 } 358 359 /** 360 * Tests this {@code LabelBlock} for equality with an arbitrary object. 361 * 362 * @param obj the object ({@code null} permitted). 363 * 364 * @return A boolean. 365 */ 366 @Override 367 public boolean equals(Object obj) { 368 if (!(obj instanceof LabelBlock)) { 369 return false; 370 } 371 LabelBlock that = (LabelBlock) obj; 372 if (!this.text.equals(that.text)) { 373 return false; 374 } 375 if (!this.font.equals(that.font)) { 376 return false; 377 } 378 if (!PaintUtils.equal(this.paint, that.paint)) { 379 return false; 380 } 381 if (!ObjectUtils.equal(this.toolTipText, that.toolTipText)) { 382 return false; 383 } 384 if (!ObjectUtils.equal(this.urlText, that.urlText)) { 385 return false; 386 } 387 if (!this.contentAlignmentPoint.equals(that.contentAlignmentPoint)) { 388 return false; 389 } 390 if (!this.textAnchor.equals(that.textAnchor)) { 391 return false; 392 } 393 return super.equals(obj); 394 } 395 396 /** 397 * Returns a clone of this {@code LabelBlock} instance. 398 * 399 * @return A clone. 400 * 401 * @throws CloneNotSupportedException if there is a problem cloning. 402 */ 403 @Override 404 public Object clone() throws CloneNotSupportedException { 405 return super.clone(); 406 } 407 408 /** 409 * Provides serialization support. 410 * 411 * @param stream the output stream. 412 * 413 * @throws IOException if there is an I/O error. 414 */ 415 private void writeObject(ObjectOutputStream stream) throws IOException { 416 stream.defaultWriteObject(); 417 SerialUtils.writePaint(this.paint, stream); 418 } 419 420 /** 421 * Provides serialization support. 422 * 423 * @param stream the input stream. 424 * 425 * @throws IOException if there is an I/O error. 426 * @throws ClassNotFoundException if there is a classpath problem. 427 */ 428 private void readObject(ObjectInputStream stream) 429 throws IOException, ClassNotFoundException { 430 stream.defaultReadObject(); 431 this.paint = SerialUtils.readPaint(stream); 432 } 433 434}