001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-present, by David Gilbert 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 * MeterNeedle.java 029 * ---------------- 030 * (C) Copyright 2002-present, by the Australian Antarctic Division and 031 * Contributors. 032 * 033 * Original Author: Bryan Scott (for the Australian Antarctic Division); 034 * Contributor(s): David Gilbert; 035 * Nicolas Brodu (for Astrium and EADS Corporate Research 036 * Center); 037 */ 038 039package org.jfree.chart.needle; 040 041import java.awt.BasicStroke; 042import java.awt.Color; 043import java.awt.Graphics2D; 044import java.awt.Paint; 045import java.awt.Shape; 046import java.awt.Stroke; 047import java.awt.geom.AffineTransform; 048import java.awt.geom.Point2D; 049import java.awt.geom.Rectangle2D; 050import java.io.IOException; 051import java.io.ObjectInputStream; 052import java.io.ObjectOutputStream; 053import java.io.Serializable; 054import java.util.Objects; 055 056import org.jfree.chart.HashUtils; 057import org.jfree.chart.util.PaintUtils; 058import org.jfree.chart.util.SerialUtils; 059 060/** 061 * The base class used to represent the needle on a 062 * {@link org.jfree.chart.plot.CompassPlot}. 063 */ 064public abstract class MeterNeedle implements Serializable { 065 066 /** For serialization. */ 067 private static final long serialVersionUID = 5203064851510951052L; 068 069 /** The outline paint. */ 070 private transient Paint outlinePaint = Color.BLACK; 071 072 /** The outline stroke. */ 073 private transient Stroke outlineStroke = new BasicStroke(2); 074 075 /** The fill paint. */ 076 private transient Paint fillPaint = null; 077 078 /** The highlight paint. */ 079 private transient Paint highlightPaint = null; 080 081 /** The size. */ 082 private int size = 5; 083 084 /** Scalar to apply to locate the rotation x point. */ 085 private double rotateX = 0.5; 086 087 /** Scalar to apply to locate the rotation y point. */ 088 private double rotateY = 0.5; 089 090 /** A transform. */ 091 protected static AffineTransform transform = new AffineTransform(); 092 093 /** 094 * Creates a new needle. 095 */ 096 public MeterNeedle() { 097 this(null, null, null); 098 } 099 100 /** 101 * Creates a new needle. 102 * 103 * @param outline the outline paint ({@code null} permitted). 104 * @param fill the fill paint ({@code null} permitted). 105 * @param highlight the highlight paint ({@code null} permitted). 106 */ 107 public MeterNeedle(Paint outline, Paint fill, Paint highlight) { 108 this.fillPaint = fill; 109 this.highlightPaint = highlight; 110 this.outlinePaint = outline; 111 } 112 113 /** 114 * Returns the outline paint. 115 * 116 * @return The outline paint. 117 */ 118 public Paint getOutlinePaint() { 119 return this.outlinePaint; 120 } 121 122 /** 123 * Sets the outline paint. 124 * 125 * @param p the new paint. 126 */ 127 public void setOutlinePaint(Paint p) { 128 if (p != null) { 129 this.outlinePaint = p; 130 } 131 } 132 133 /** 134 * Returns the outline stroke. 135 * 136 * @return The outline stroke. 137 */ 138 public Stroke getOutlineStroke() { 139 return this.outlineStroke; 140 } 141 142 /** 143 * Sets the outline stroke. 144 * 145 * @param s the new stroke. 146 */ 147 public void setOutlineStroke(Stroke s) { 148 if (s != null) { 149 this.outlineStroke = s; 150 } 151 } 152 153 /** 154 * Returns the fill paint. 155 * 156 * @return The fill paint. 157 */ 158 public Paint getFillPaint() { 159 return this.fillPaint; 160 } 161 162 /** 163 * Sets the fill paint. 164 * 165 * @param p the fill paint. 166 */ 167 public void setFillPaint(Paint p) { 168 if (p != null) { 169 this.fillPaint = p; 170 } 171 } 172 173 /** 174 * Returns the highlight paint. 175 * 176 * @return The highlight paint. 177 */ 178 public Paint getHighlightPaint() { 179 return this.highlightPaint; 180 } 181 182 /** 183 * Sets the highlight paint. 184 * 185 * @param p the highlight paint. 186 */ 187 public void setHighlightPaint(Paint p) { 188 if (p != null) { 189 this.highlightPaint = p; 190 } 191 } 192 193 /** 194 * Returns the scalar used for determining the rotation x value. 195 * 196 * @return The x rotate scalar. 197 */ 198 public double getRotateX() { 199 return this.rotateX; 200 } 201 202 /** 203 * Sets the rotateX value. 204 * 205 * @param x the new value. 206 */ 207 public void setRotateX(double x) { 208 this.rotateX = x; 209 } 210 211 /** 212 * Sets the rotateY value. 213 * 214 * @param y the new value. 215 */ 216 public void setRotateY(double y) { 217 this.rotateY = y; 218 } 219 220 /** 221 * Returns the scalar used for determining the rotation y value. 222 * 223 * @return The y rotate scalar. 224 */ 225 public double getRotateY() { 226 return this.rotateY; 227 } 228 229 /** 230 * Draws the needle. 231 * 232 * @param g2 the graphics device. 233 * @param plotArea the plot area. 234 */ 235 public void draw(Graphics2D g2, Rectangle2D plotArea) { 236 draw(g2, plotArea, 0); 237 } 238 239 /** 240 * Draws the needle. 241 * 242 * @param g2 the graphics device. 243 * @param plotArea the plot area. 244 * @param angle the angle. 245 */ 246 public void draw(Graphics2D g2, Rectangle2D plotArea, double angle) { 247 Point2D.Double pt = new Point2D.Double(); 248 pt.setLocation(plotArea.getMinX() + this.rotateX * plotArea.getWidth(), 249 plotArea.getMinY() + this.rotateY * plotArea.getHeight()); 250 draw(g2, plotArea, pt, angle); 251 } 252 253 /** 254 * Draws the needle. 255 * 256 * @param g2 the graphics device. 257 * @param plotArea the plot area. 258 * @param rotate the rotation point. 259 * @param angle the angle. 260 */ 261 public void draw(Graphics2D g2, Rectangle2D plotArea, Point2D rotate, 262 double angle) { 263 264 Paint savePaint = g2.getColor(); 265 Stroke saveStroke = g2.getStroke(); 266 267 drawNeedle(g2, plotArea, rotate, Math.toRadians(angle)); 268 269 g2.setStroke(saveStroke); 270 g2.setPaint(savePaint); 271 } 272 273 /** 274 * Draws the needle. 275 * 276 * @param g2 the graphics device. 277 * @param plotArea the plot area. 278 * @param rotate the rotation point. 279 * @param angle the angle. 280 */ 281 protected abstract void drawNeedle(Graphics2D g2, Rectangle2D plotArea, 282 Point2D rotate, double angle); 283 284 /** 285 * Displays a shape. 286 * 287 * @param g2 the graphics device. 288 * @param shape the shape. 289 */ 290 protected void defaultDisplay(Graphics2D g2, Shape shape) { 291 if (this.fillPaint != null) { 292 g2.setPaint(this.fillPaint); 293 g2.fill(shape); 294 } 295 296 if (this.outlinePaint != null) { 297 g2.setStroke(this.outlineStroke); 298 g2.setPaint(this.outlinePaint); 299 g2.draw(shape); 300 } 301 } 302 303 /** 304 * Returns the size. 305 * 306 * @return The size. 307 */ 308 public int getSize() { 309 return this.size; 310 } 311 312 /** 313 * Sets the size. 314 * 315 * @param pixels the new size. 316 */ 317 public void setSize(int pixels) { 318 this.size = pixels; 319 } 320 321 /** 322 * Returns the transform. 323 * 324 * @return The transform. 325 */ 326 public AffineTransform getTransform() { 327 return MeterNeedle.transform; 328 } 329 330 /** 331 * Tests another object for equality with this object. 332 * 333 * @param obj the object to test ({@code null} permitted). 334 * 335 * @return A boolean. 336 */ 337 @Override 338 public boolean equals(Object obj) { 339 if (obj == this) { 340 return true; 341 } 342 if (!(obj instanceof MeterNeedle)) { 343 return false; 344 } 345 MeterNeedle that = (MeterNeedle) obj; 346 if (!PaintUtils.equal(this.outlinePaint, that.outlinePaint)) { 347 return false; 348 } 349 if (!Objects.equals(this.outlineStroke, that.outlineStroke)) { 350 return false; 351 } 352 if (!PaintUtils.equal(this.fillPaint, that.fillPaint)) { 353 return false; 354 } 355 if (!PaintUtils.equal(this.highlightPaint, that.highlightPaint)) { 356 return false; 357 } 358 if (this.size != that.size) { 359 return false; 360 } 361 if (this.rotateX != that.rotateX) { 362 return false; 363 } 364 if (this.rotateY != that.rotateY) { 365 return false; 366 } 367 return true; 368 } 369 370 /** 371 * Returns a hash code for this instance. 372 * 373 * @return A hash code. 374 */ 375 @Override 376 public int hashCode() { 377 int result = HashUtils.hashCode(193, this.fillPaint); 378 result = HashUtils.hashCode(result, this.highlightPaint); 379 result = HashUtils.hashCode(result, this.outlinePaint); 380 result = HashUtils.hashCode(result, this.outlineStroke); 381 result = HashUtils.hashCode(result, this.rotateX); 382 result = HashUtils.hashCode(result, this.rotateY); 383 result = HashUtils.hashCode(result, this.size); 384 return result; 385 } 386 387 /** 388 * Provides serialization support. 389 * 390 * @param stream the output stream. 391 * 392 * @throws IOException if there is an I/O error. 393 */ 394 private void writeObject(ObjectOutputStream stream) throws IOException { 395 stream.defaultWriteObject(); 396 SerialUtils.writeStroke(this.outlineStroke, stream); 397 SerialUtils.writePaint(this.outlinePaint, stream); 398 SerialUtils.writePaint(this.fillPaint, stream); 399 SerialUtils.writePaint(this.highlightPaint, stream); 400 } 401 402 /** 403 * Provides serialization support. 404 * 405 * @param stream the input stream. 406 * 407 * @throws IOException if there is an I/O error. 408 * @throws ClassNotFoundException if there is a classpath problem. 409 */ 410 private void readObject(ObjectInputStream stream) 411 throws IOException, ClassNotFoundException { 412 stream.defaultReadObject(); 413 this.outlineStroke = SerialUtils.readStroke(stream); 414 this.outlinePaint = SerialUtils.readPaint(stream); 415 this.fillPaint = SerialUtils.readPaint(stream); 416 this.highlightPaint = SerialUtils.readPaint(stream); 417 } 418 419}