1 /* =========================================================== 2 * JFreeChart : a free chart library for the Java(tm) platform 3 * =========================================================== 4 * 5 * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors. 6 * 7 * Project Info: http://www.jfree.org/jfreechart/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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 25 * Other names may be trademarks of their respective owners.] 26 * 27 * -------------------- 28 * XYBoxAnnotation.java 29 * -------------------- 30 * (C) Copyright 2005-2013, by Object Refinery Limited and Contributors. 31 * 32 * Original Author: David Gilbert (for Object Refinery Limited); 33 * Contributor(s): Peter Kolb (see patch 2809117); 34 * 35 * Changes: 36 * -------- 37 * 19-Jan-2005 : Version 1 (DG); 38 * 06-Jun-2005 : Fixed equals() method to handle GradientPaint (DG); 39 * 40 */ 41 42 package org.jfree.chart.annotations; 43 44 import java.awt.BasicStroke; 45 import java.awt.Color; 46 import java.awt.Graphics2D; 47 import java.awt.Paint; 48 import java.awt.Stroke; 49 import java.awt.geom.Rectangle2D; 50 import java.io.IOException; 51 import java.io.ObjectInputStream; 52 import java.io.ObjectOutputStream; 53 import java.io.Serializable; 54 55 import org.jfree.chart.axis.ValueAxis; 56 import org.jfree.chart.plot.Plot; 57 import org.jfree.chart.plot.PlotOrientation; 58 import org.jfree.chart.plot.PlotRenderingInfo; 59 import org.jfree.chart.plot.XYPlot; 60 import org.jfree.io.SerialUtilities; 61 import org.jfree.ui.RectangleEdge; 62 import org.jfree.util.ObjectUtilities; 63 import org.jfree.util.PaintUtilities; 64 import org.jfree.util.PublicCloneable; 65 66 /** 67 * A box annotation that can be placed on an {@link XYPlot}. The 68 * box coordinates are specified in data space. 69 */ 70 public class XYBoxAnnotation extends AbstractXYAnnotation 71 implements Cloneable, PublicCloneable, Serializable { 72 73 /** For serialization. */ 74 private static final long serialVersionUID = 6764703772526757457L; 75 76 /** The lower x-coordinate. */ 77 private double x0; 78 79 /** The lower y-coordinate. */ 80 private double y0; 81 82 /** The upper x-coordinate. */ 83 private double x1; 84 85 /** The upper y-coordinate. */ 86 private double y1; 87 88 /** The stroke used to draw the box outline. */ 89 private transient Stroke stroke; 90 91 /** The paint used to draw the box outline. */ 92 private transient Paint outlinePaint; 93 94 /** The paint used to fill the box. */ 95 private transient Paint fillPaint; 96 97 /** 98 * Creates a new annotation (where, by default, the box is drawn 99 * with a black outline). 100 * 101 * @param x0 the lower x-coordinate of the box (in data space). 102 * @param y0 the lower y-coordinate of the box (in data space). 103 * @param x1 the upper x-coordinate of the box (in data space). 104 * @param y1 the upper y-coordinate of the box (in data space). 105 */ XYBoxAnnotation(double x0, double y0, double x1, double y1)106 public XYBoxAnnotation(double x0, double y0, double x1, double y1) { 107 this(x0, y0, x1, y1, new BasicStroke(1.0f), Color.black); 108 } 109 110 /** 111 * Creates a new annotation where the box is drawn as an outline using 112 * the specified <code>stroke</code> and <code>outlinePaint</code>. 113 * 114 * @param x0 the lower x-coordinate of the box (in data space). 115 * @param y0 the lower y-coordinate of the box (in data space). 116 * @param x1 the upper x-coordinate of the box (in data space). 117 * @param y1 the upper y-coordinate of the box (in data space). 118 * @param stroke the shape stroke (<code>null</code> permitted). 119 * @param outlinePaint the shape color (<code>null</code> permitted). 120 */ XYBoxAnnotation(double x0, double y0, double x1, double y1, Stroke stroke, Paint outlinePaint)121 public XYBoxAnnotation(double x0, double y0, double x1, double y1, 122 Stroke stroke, Paint outlinePaint) { 123 this(x0, y0, x1, y1, stroke, outlinePaint, null); 124 } 125 126 /** 127 * Creates a new annotation. 128 * 129 * @param x0 the lower x-coordinate of the box (in data space). 130 * @param y0 the lower y-coordinate of the box (in data space). 131 * @param x1 the upper x-coordinate of the box (in data space). 132 * @param y1 the upper y-coordinate of the box (in data space). 133 * @param stroke the shape stroke (<code>null</code> permitted). 134 * @param outlinePaint the shape color (<code>null</code> permitted). 135 * @param fillPaint the paint used to fill the shape (<code>null</code> 136 * permitted). 137 */ XYBoxAnnotation(double x0, double y0, double x1, double y1, Stroke stroke, Paint outlinePaint, Paint fillPaint)138 public XYBoxAnnotation(double x0, double y0, double x1, double y1, 139 Stroke stroke, Paint outlinePaint, Paint fillPaint) { 140 super(); 141 this.x0 = x0; 142 this.y0 = y0; 143 this.x1 = x1; 144 this.y1 = y1; 145 this.stroke = stroke; 146 this.outlinePaint = outlinePaint; 147 this.fillPaint = fillPaint; 148 } 149 150 /** 151 * Draws the annotation. This method is usually called by the 152 * {@link XYPlot} class, you shouldn't need to call it directly. 153 * 154 * @param g2 the graphics device. 155 * @param plot the plot. 156 * @param dataArea the data area. 157 * @param domainAxis the domain axis. 158 * @param rangeAxis the range axis. 159 * @param rendererIndex the renderer index. 160 * @param info the plot rendering info. 161 */ 162 @Override draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, int rendererIndex, PlotRenderingInfo info)163 public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, 164 ValueAxis domainAxis, ValueAxis rangeAxis, 165 int rendererIndex, PlotRenderingInfo info) { 166 167 PlotOrientation orientation = plot.getOrientation(); 168 RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( 169 plot.getDomainAxisLocation(), orientation); 170 RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation( 171 plot.getRangeAxisLocation(), orientation); 172 173 double transX0 = domainAxis.valueToJava2D(this.x0, dataArea, 174 domainEdge); 175 double transY0 = rangeAxis.valueToJava2D(this.y0, dataArea, rangeEdge); 176 double transX1 = domainAxis.valueToJava2D(this.x1, dataArea, 177 domainEdge); 178 double transY1 = rangeAxis.valueToJava2D(this.y1, dataArea, rangeEdge); 179 180 Rectangle2D box = null; 181 if (orientation == PlotOrientation.HORIZONTAL) { 182 box = new Rectangle2D.Double(transY0, transX1, transY1 - transY0, 183 transX0 - transX1); 184 } 185 else if (orientation == PlotOrientation.VERTICAL) { 186 box = new Rectangle2D.Double(transX0, transY1, transX1 - transX0, 187 transY0 - transY1); 188 } 189 190 if (this.fillPaint != null) { 191 g2.setPaint(this.fillPaint); 192 g2.fill(box); 193 } 194 195 if (this.stroke != null && this.outlinePaint != null) { 196 g2.setPaint(this.outlinePaint); 197 g2.setStroke(this.stroke); 198 g2.draw(box); 199 } 200 addEntity(info, box, rendererIndex, getToolTipText(), getURL()); 201 202 } 203 204 /** 205 * Tests this annotation for equality with an arbitrary object. 206 * 207 * @param obj the object (<code>null</code> permitted). 208 * 209 * @return A boolean. 210 */ 211 @Override equals(Object obj)212 public boolean equals(Object obj) { 213 if (obj == this) { 214 return true; 215 } 216 // now try to reject equality 217 if (!super.equals(obj)) { 218 return false; 219 } 220 if (!(obj instanceof XYBoxAnnotation)) { 221 return false; 222 } 223 XYBoxAnnotation that = (XYBoxAnnotation) obj; 224 if (!(this.x0 == that.x0)) { 225 return false; 226 } 227 if (!(this.y0 == that.y0)) { 228 return false; 229 } 230 if (!(this.x1 == that.x1)) { 231 return false; 232 } 233 if (!(this.y1 == that.y1)) { 234 return false; 235 } 236 if (!ObjectUtilities.equal(this.stroke, that.stroke)) { 237 return false; 238 } 239 if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) { 240 return false; 241 } 242 if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) { 243 return false; 244 } 245 // seem to be the same 246 return true; 247 } 248 249 /** 250 * Returns a hash code. 251 * 252 * @return A hash code. 253 */ 254 @Override hashCode()255 public int hashCode() { 256 int result; 257 long temp; 258 temp = Double.doubleToLongBits(this.x0); 259 result = (int) (temp ^ (temp >>> 32)); 260 temp = Double.doubleToLongBits(this.x1); 261 result = 29 * result + (int) (temp ^ (temp >>> 32)); 262 temp = Double.doubleToLongBits(this.y0); 263 result = 29 * result + (int) (temp ^ (temp >>> 32)); 264 temp = Double.doubleToLongBits(this.y1); 265 result = 29 * result + (int) (temp ^ (temp >>> 32)); 266 return result; 267 } 268 269 /** 270 * Returns a clone. 271 * 272 * @return A clone. 273 * 274 * @throws CloneNotSupportedException not thrown by this class, but may be 275 * by subclasses. 276 */ 277 @Override clone()278 public Object clone() throws CloneNotSupportedException { 279 return super.clone(); 280 } 281 282 /** 283 * Provides serialization support. 284 * 285 * @param stream the output stream (<code>null</code> not permitted). 286 * 287 * @throws IOException if there is an I/O error. 288 */ writeObject(ObjectOutputStream stream)289 private void writeObject(ObjectOutputStream stream) throws IOException { 290 stream.defaultWriteObject(); 291 SerialUtilities.writeStroke(this.stroke, stream); 292 SerialUtilities.writePaint(this.outlinePaint, stream); 293 SerialUtilities.writePaint(this.fillPaint, stream); 294 } 295 296 /** 297 * Provides serialization support. 298 * 299 * @param stream the input stream (<code>null</code> not permitted). 300 * 301 * @throws IOException if there is an I/O error. 302 * @throws ClassNotFoundException if there is a classpath problem. 303 */ readObject(ObjectInputStream stream)304 private void readObject(ObjectInputStream stream) 305 throws IOException, ClassNotFoundException { 306 307 stream.defaultReadObject(); 308 this.stroke = SerialUtilities.readStroke(stream); 309 this.outlinePaint = SerialUtilities.readPaint(stream); 310 this.fillPaint = SerialUtilities.readPaint(stream); 311 } 312 313 } 314