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. * CategoryTextAnnotation.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: CategoryTextAnnotation.java,v 1.4 2005/02/28 16:11:12 mungady Exp $
  35. *
  36. * Changes:
  37. * --------
  38. * 02-Apr-2003 : Version 1 (DG);
  39. * 02-Jul-2003 : Added new text alignment and rotation options (DG);
  40. * 04-Jul-2003 : Added a category anchor option (DG);
  41. * 19-Aug-2003 : Added equals(...) method and implemented Cloneable (DG);
  42. * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
  43. * 30-Sep-2004 : Moved drawRotatedString() from RefineryUtilities
  44. * --> TextUtilities (DG);
  45. *
  46. */
  47. package org.jfree.chart.annotations;
  48. import java.awt.Graphics2D;
  49. import java.awt.geom.Rectangle2D;
  50. import java.io.Serializable;
  51. import org.jfree.chart.axis.CategoryAnchor;
  52. import org.jfree.chart.axis.CategoryAxis;
  53. import org.jfree.chart.axis.ValueAxis;
  54. import org.jfree.chart.plot.CategoryPlot;
  55. import org.jfree.chart.plot.Plot;
  56. import org.jfree.chart.plot.PlotOrientation;
  57. import org.jfree.data.category.CategoryDataset;
  58. import org.jfree.text.TextUtilities;
  59. import org.jfree.ui.RectangleEdge;
  60. /**
  61. * A text annotation that can be placed on a
  62. * {@link org.jfree.chart.plot.CategoryPlot}.
  63. */
  64. public class CategoryTextAnnotation extends TextAnnotation
  65. implements CategoryAnnotation,
  66. Cloneable, Serializable {
  67. /** The category. */
  68. private Comparable category;
  69. /** The category anchor (START, MIDDLE, or END). */
  70. private CategoryAnchor categoryAnchor;
  71. /** The value. */
  72. private double value;
  73. /**
  74. * Creates a new annotation to be displayed at the given location.
  75. *
  76. * @param text the text (<code>null</code> not permitted).
  77. * @param category the category (<code>null</code> not permitted).
  78. * @param value the value.
  79. */
  80. public CategoryTextAnnotation(String text, Comparable category,
  81. double value) {
  82. super(text);
  83. if (category == null) {
  84. throw new IllegalArgumentException("Null 'category' argument.");
  85. }
  86. this.category = category;
  87. this.value = value;
  88. this.categoryAnchor = CategoryAnchor.MIDDLE;
  89. }
  90. /**
  91. * Returns the category.
  92. *
  93. * @return The category (never <code>null</code>).
  94. */
  95. public Comparable getCategory() {
  96. return this.category;
  97. }
  98. /**
  99. * Sets the category that the annotation attaches to.
  100. *
  101. * @param category the category (<code>null</code> not permitted).
  102. */
  103. public void setCategory(Comparable category) {
  104. if (category == null) {
  105. throw new IllegalArgumentException("Null 'category' argument.");
  106. }
  107. this.category = category;
  108. }
  109. /**
  110. * Returns the category anchor point.
  111. *
  112. * @return The category anchor point.
  113. */
  114. public CategoryAnchor getCategoryAnchor() {
  115. return this.categoryAnchor;
  116. }
  117. /**
  118. * Sets the category anchor point.
  119. *
  120. * @param anchor the anchor point (<code>null</code> not permitted).
  121. */
  122. public void setCategoryAnchor(CategoryAnchor anchor) {
  123. if (anchor == null) {
  124. throw new IllegalArgumentException("Null 'anchor' argument.");
  125. }
  126. this.categoryAnchor = anchor;
  127. }
  128. /**
  129. * Returns the value that the annotation attaches to.
  130. *
  131. * @return The value.
  132. */
  133. public double getValue() {
  134. return this.value;
  135. }
  136. /**
  137. * Sets the value.
  138. *
  139. * @param value the value.
  140. */
  141. public void setValue(double value) {
  142. this.value = value;
  143. }
  144. /**
  145. * Draws the annotation.
  146. *
  147. * @param g2 the graphics device.
  148. * @param plot the plot.
  149. * @param dataArea the data area.
  150. * @param domainAxis the domain axis.
  151. * @param rangeAxis the range axis.
  152. */
  153. public void draw(Graphics2D g2, CategoryPlot plot, Rectangle2D dataArea,
  154. CategoryAxis domainAxis, ValueAxis rangeAxis) {
  155. CategoryDataset dataset = plot.getDataset();
  156. int catIndex = dataset.getColumnIndex(this.category);
  157. int catCount = dataset.getColumnCount();
  158. float anchorX = 0.0f;
  159. float anchorY = 0.0f;
  160. PlotOrientation orientation = plot.getOrientation();
  161. RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
  162. plot.getDomainAxisLocation(), orientation
  163. );
  164. RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
  165. plot.getRangeAxisLocation(), orientation
  166. );
  167. if (orientation == PlotOrientation.HORIZONTAL) {
  168. anchorY = (float) domainAxis.getCategoryJava2DCoordinate(
  169. this.categoryAnchor, catIndex, catCount, dataArea, domainEdge
  170. );
  171. anchorX = (float) rangeAxis.valueToJava2D(
  172. this.value, dataArea, rangeEdge
  173. );
  174. }
  175. else if (orientation == PlotOrientation.VERTICAL) {
  176. anchorX = (float) domainAxis.getCategoryJava2DCoordinate(
  177. this.categoryAnchor, catIndex, catCount, dataArea, domainEdge
  178. );
  179. anchorY = (float) rangeAxis.valueToJava2D(
  180. this.value, dataArea, rangeEdge
  181. );
  182. }
  183. g2.setFont(getFont());
  184. g2.setPaint(getPaint());
  185. TextUtilities.drawRotatedString(
  186. getText(),
  187. g2,
  188. anchorX,
  189. anchorY,
  190. getTextAnchor(),
  191. getRotationAngle(),
  192. getRotationAnchor()
  193. );
  194. }
  195. /**
  196. * Tests this object for equality with another.
  197. *
  198. * @param obj the object (<code>null</code> permitted).
  199. *
  200. * @return <code>true</code> or <code>false</code>.
  201. */
  202. public boolean equals(Object obj) {
  203. if (obj == this) {
  204. return true;
  205. }
  206. if (!(obj instanceof CategoryTextAnnotation)) {
  207. return false;
  208. }
  209. CategoryTextAnnotation that = (CategoryTextAnnotation) obj;
  210. if (!super.equals(obj)) {
  211. return false;
  212. }
  213. if (!this.category.equals(that.getCategory())) {
  214. return false;
  215. }
  216. if (!this.categoryAnchor.equals(that.getCategoryAnchor())) {
  217. return false;
  218. }
  219. if (this.value != that.getValue()) {
  220. return false;
  221. }
  222. return true;
  223. }
  224. /**
  225. * Returns a clone of the annotation.
  226. *
  227. * @return A clone.
  228. *
  229. * @throws CloneNotSupportedException this class will not throw this
  230. * exception, but subclasses (if any) might.
  231. */
  232. public Object clone() throws CloneNotSupportedException {
  233. return super.clone();
  234. }
  235. }