1. /* ===========================================================
  2. * JFreeChart : a free chart 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/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 License
  20. * along with this library; if not, write to the Free Software Foundation,
  21. * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  22. *
  23. * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  24. * in the United States and other countries.]
  25. *
  26. * ---------------------
  27. * XYLineAnnotation.java
  28. * ---------------------
  29. * (C) Copyright 2003-2005, by Object Refinery Limited.
  30. *
  31. * Original Author: David Gilbert (for Object Refinery Limited);
  32. * Contributor(s): -;
  33. *
  34. * $Id: XYLineAnnotation.java,v 1.6 2005/02/28 16:12:29 mungady Exp $
  35. *
  36. * Changes:
  37. * --------
  38. * 02-Apr-2003 : Version 1 (DG);
  39. * 19-Aug-2003 : Added equals method, implemented Cloneable, and applied
  40. * serialization fixes (DG);
  41. * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
  42. * 14-Apr-2004 : Fixed draw() method to handle plot orientation correctly (DG);
  43. * 29-Sep-2004 : Added support for tool tips and URLS, now extends
  44. * AbstractXYAnnotation (DG);
  45. * 04-Oct-2004 : Renamed ShapeUtils --> ShapeUtilities (DG);
  46. *
  47. */
  48. package org.jfree.chart.annotations;
  49. import java.awt.BasicStroke;
  50. import java.awt.Color;
  51. import java.awt.Graphics2D;
  52. import java.awt.Paint;
  53. import java.awt.Stroke;
  54. import java.awt.geom.Line2D;
  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. import org.jfree.chart.axis.ValueAxis;
  61. import org.jfree.chart.plot.Plot;
  62. import org.jfree.chart.plot.PlotOrientation;
  63. import org.jfree.chart.plot.PlotRenderingInfo;
  64. import org.jfree.chart.plot.XYPlot;
  65. import org.jfree.io.SerialUtilities;
  66. import org.jfree.ui.RectangleEdge;
  67. import org.jfree.util.ObjectUtilities;
  68. import org.jfree.util.PublicCloneable;
  69. import org.jfree.util.ShapeUtilities;
  70. /**
  71. * A simple line annotation that can be placed on an {@link XYPlot}.
  72. */
  73. public class XYLineAnnotation extends AbstractXYAnnotation
  74. implements Cloneable, PublicCloneable,
  75. Serializable {
  76. /** The x-coordinate. */
  77. private double x1;
  78. /** The y-coordinate. */
  79. private double y1;
  80. /** The x-coordinate. */
  81. private double x2;
  82. /** The y-coordinate. */
  83. private double y2;
  84. /** The line stroke. */
  85. private transient Stroke stroke;
  86. /** The line color. */
  87. private transient Paint paint;
  88. /**
  89. * Creates a new annotation that draws a line from (x1, y1) to (x2, y2)
  90. * where the coordinates are measured in data space (that is, against the
  91. * plot's axes).
  92. *
  93. * @param x1 the x-coordinate for the start of the line.
  94. * @param y1 the y-coordinate for the start of the line.
  95. * @param x2 the x-coordinate for the end of the line.
  96. * @param y2 the y-coordinate for the end of the line.
  97. */
  98. public XYLineAnnotation(double x1, double y1, double x2, double y2) {
  99. this(x1, y1, x2, y2, new BasicStroke(1.0f), Color.black);
  100. }
  101. /**
  102. * Creates a new annotation that draws a line from (x1, y1) to (x2, y2)
  103. * where the coordinates are measured in data space (that is, against the
  104. * plot's axes).
  105. *
  106. * @param x1 the x-coordinate for the start of the line.
  107. * @param y1 the y-coordinate for the start of the line.
  108. * @param x2 the x-coordinate for the end of the line.
  109. * @param y2 the y-coordinate for the end of the line.
  110. * @param stroke the line stroke (<code>null</code> not permitted).
  111. * @param paint the line color (<code>null</code> not permitted).
  112. */
  113. public XYLineAnnotation(double x1, double y1, double x2, double y2,
  114. Stroke stroke, Paint paint) {
  115. if (stroke == null) {
  116. throw new IllegalArgumentException("Null 'stroke' argument.");
  117. }
  118. if (paint == null) {
  119. throw new IllegalArgumentException("Null 'paint' argument.");
  120. }
  121. this.x1 = x1;
  122. this.y1 = y1;
  123. this.x2 = x2;
  124. this.y2 = y2;
  125. this.stroke = stroke;
  126. this.paint = paint;
  127. }
  128. /**
  129. * Draws the annotation. This method is called by the {@link XYPlot}
  130. * class, you won't normally need to call it yourself.
  131. *
  132. * @param g2 the graphics device.
  133. * @param plot the plot.
  134. * @param dataArea the data area.
  135. * @param domainAxis the domain axis.
  136. * @param rangeAxis the range axis.
  137. * @param rendererIndex the renderer index.
  138. * @param info if supplied, this info object will be populated with
  139. * entity information.
  140. */
  141. public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea,
  142. ValueAxis domainAxis, ValueAxis rangeAxis,
  143. int rendererIndex,
  144. PlotRenderingInfo info) {
  145. PlotOrientation orientation = plot.getOrientation();
  146. RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
  147. plot.getDomainAxisLocation(), orientation
  148. );
  149. RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
  150. plot.getRangeAxisLocation(), orientation
  151. );
  152. float j2DX1 = 0.0f;
  153. float j2DX2 = 0.0f;
  154. float j2DY1 = 0.0f;
  155. float j2DY2 = 0.0f;
  156. if (orientation == PlotOrientation.VERTICAL) {
  157. j2DX1 = (float) domainAxis.valueToJava2D(
  158. this.x1, dataArea, domainEdge
  159. );
  160. j2DY1 = (float) rangeAxis.valueToJava2D(
  161. this.y1, dataArea, rangeEdge
  162. );
  163. j2DX2 = (float) domainAxis.valueToJava2D(
  164. this.x2, dataArea, domainEdge
  165. );
  166. j2DY2 = (float) rangeAxis.valueToJava2D(
  167. this.y2, dataArea, rangeEdge
  168. );
  169. }
  170. else if (orientation == PlotOrientation.HORIZONTAL) {
  171. j2DY1 = (float) domainAxis.valueToJava2D(
  172. this.x1, dataArea, domainEdge
  173. );
  174. j2DX1 = (float) rangeAxis.valueToJava2D(
  175. this.y1, dataArea, rangeEdge
  176. );
  177. j2DY2 = (float) domainAxis.valueToJava2D(
  178. this.x2, dataArea, domainEdge
  179. );
  180. j2DX2 = (float) rangeAxis.valueToJava2D(
  181. this.y2, dataArea, rangeEdge
  182. );
  183. }
  184. g2.setPaint(this.paint);
  185. g2.setStroke(this.stroke);
  186. Line2D line = new Line2D.Float(j2DX1, j2DY1, j2DX2, j2DY2);
  187. g2.draw(line);
  188. String toolTip = getToolTipText();
  189. String url = getURL();
  190. if (toolTip != null || url != null) {
  191. addEntity(
  192. info, ShapeUtilities.createLineRegion(line, 1.0f),
  193. rendererIndex, toolTip, url
  194. );
  195. }
  196. }
  197. /**
  198. * Tests this object for equality with an arbitrary object.
  199. *
  200. * @param obj the object to test against (<code>null</code> permitted).
  201. *
  202. * @return <code>true</code> or <code>false</code>.
  203. */
  204. public boolean equals(Object obj) {
  205. if (obj == this) {
  206. return true;
  207. }
  208. if (!super.equals(obj)) {
  209. return false;
  210. }
  211. if (!(obj instanceof XYLineAnnotation)) {
  212. return false;
  213. }
  214. XYLineAnnotation that = (XYLineAnnotation) obj;
  215. if (this.x1 != that.x1) {
  216. return false;
  217. }
  218. if (this.y1 != that.y1) {
  219. return false;
  220. }
  221. if (this.x2 != that.x2) {
  222. return false;
  223. }
  224. if (this.y2 != that.y2) {
  225. return false;
  226. }
  227. if (!ObjectUtilities.equal(this.paint, that.paint)) {
  228. return false;
  229. }
  230. if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
  231. return false;
  232. }
  233. // seems to be the same...
  234. return true;
  235. }
  236. /**
  237. * Returns a hash code.
  238. *
  239. * @return A hash code.
  240. */
  241. public int hashCode() {
  242. int result;
  243. long temp;
  244. temp = Double.doubleToLongBits(this.x1);
  245. result = (int) (temp ^ (temp >>> 32));
  246. temp = Double.doubleToLongBits(this.x2);
  247. result = 29 * result + (int) (temp ^ (temp >>> 32));
  248. temp = Double.doubleToLongBits(this.y1);
  249. result = 29 * result + (int) (temp ^ (temp >>> 32));
  250. temp = Double.doubleToLongBits(this.y2);
  251. result = 29 * result + (int) (temp ^ (temp >>> 32));
  252. return result;
  253. }
  254. /**
  255. * Returns a clone of the annotation.
  256. *
  257. * @return A clone.
  258. *
  259. * @throws CloneNotSupportedException if the annotation can't be cloned.
  260. */
  261. public Object clone() throws CloneNotSupportedException {
  262. return super.clone();
  263. }
  264. /**
  265. * Provides serialization support.
  266. *
  267. * @param stream the output stream.
  268. *
  269. * @throws IOException if there is an I/O error.
  270. */
  271. private void writeObject(ObjectOutputStream stream) throws IOException {
  272. stream.defaultWriteObject();
  273. SerialUtilities.writePaint(this.paint, stream);
  274. SerialUtilities.writeStroke(this.stroke, stream);
  275. }
  276. /**
  277. * Provides serialization support.
  278. *
  279. * @param stream the input stream.
  280. *
  281. * @throws IOException if there is an I/O error.
  282. * @throws ClassNotFoundException if there is a classpath problem.
  283. */
  284. private void readObject(ObjectInputStream stream)
  285. throws IOException, ClassNotFoundException {
  286. stream.defaultReadObject();
  287. this.paint = SerialUtilities.readPaint(stream);
  288. this.stroke = SerialUtilities.readStroke(stream);
  289. }
  290. }