Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2007, 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: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 25: * in the United States and other countries.] 26: * 27: * ---------------- 28: * ChartEntity.java 29: * ---------------- 30: * (C) Copyright 2002-2007, by Object Refinery Limited and Contributors. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): Richard Atkinson; 34: * Xavier Poinsard; 35: * Robert Fuller; 36: * 37: * $Id: ChartEntity.java,v 1.8.2.2 2007/02/06 11:28:53 mungady Exp $ 38: * 39: * Changes: 40: * -------- 41: * 23-May-2002 : Version 1 (DG); 42: * 12-Jun-2002 : Added Javadoc comments (DG); 43: * 26-Jun-2002 : Added methods for image maps (DG); 44: * 05-Aug-2002 : Added constructor and accessors for URL support in image maps 45: * Added getImageMapAreaTag() - previously in subclasses (RA); 46: * 05-Sep-2002 : Added getImageMapAreaTag(boolean) to support OverLIB for 47: * tooltips http://www.bosrup.com/web/overlib (RA); 48: * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG); 49: * 08-Oct-2002 : Changed getImageMapAreaTag to use title instead of alt 50: * attribute so HTML image maps now work in Mozilla and Opera as 51: * well as Internet Explorer (RA); 52: * 13-Mar-2003 : Change getImageMapAreaTag to only return a tag when there is a 53: * tooltip or URL, as suggested by Xavier Poinsard (see Feature 54: * Request 688079) (DG); 55: * 12-Aug-2003 : Added support for custom image maps using 56: * ToolTipTagFragmentGenerator and URLTagFragmentGenerator (RA); 57: * 02-Sep-2003 : Incorporated fix (791901) submitted by Robert Fuller (DG); 58: * 19-May-2004 : Added equals() method and implemented Cloneable and 59: * Serializable (DG); 60: * 29-Sep-2004 : Implemented PublicCloneable (DG); 61: * 13-Jan-2005 : Fixed for compliance with XHTML 1.0 (DG); 62: * 18-Apr-2005 : Use StringBuffer (DG); 63: * 20-Apr-2005 : Added toString() implementation (DG); 64: * ------------- JFREECHART 1.0.x --------------------------------------------- 65: * 06-Feb-2007 : API doc update (DG); 66: * 67: */ 68: 69: package org.jfree.chart.entity; 70: 71: import java.awt.Shape; 72: import java.awt.geom.PathIterator; 73: import java.awt.geom.Rectangle2D; 74: import java.io.IOException; 75: import java.io.ObjectInputStream; 76: import java.io.ObjectOutputStream; 77: import java.io.Serializable; 78: 79: import org.jfree.chart.imagemap.ToolTipTagFragmentGenerator; 80: import org.jfree.chart.imagemap.URLTagFragmentGenerator; 81: import org.jfree.io.SerialUtilities; 82: import org.jfree.util.ObjectUtilities; 83: import org.jfree.util.PublicCloneable; 84: 85: /** 86: * A class that captures information about some component of a chart (a bar, 87: * line etc). 88: */ 89: public class ChartEntity implements Cloneable, PublicCloneable, Serializable { 90: 91: /** For serialization. */ 92: private static final long serialVersionUID = -4445994133561919083L; 93: 94: /** The area occupied by the entity (in Java 2D space). */ 95: private transient Shape area; 96: 97: /** The tool tip text for the entity. */ 98: private String toolTipText; 99: 100: /** The URL text for the entity. */ 101: private String urlText; 102: 103: /** 104: * Creates a new chart entity. 105: * 106: * @param area the area (<code>null</code> not permitted). 107: */ 108: public ChartEntity(Shape area) { 109: // defer argument checks... 110: this(area, null); 111: } 112: 113: /** 114: * Creates a new chart entity. 115: * 116: * @param area the area (<code>null</code> not permitted). 117: * @param toolTipText the tool tip text (<code>null</code> permitted). 118: */ 119: public ChartEntity(Shape area, String toolTipText) { 120: // defer argument checks... 121: this(area, toolTipText, null); 122: } 123: 124: /** 125: * Creates a new entity. 126: * 127: * @param area the area (<code>null</code> not permitted). 128: * @param toolTipText the tool tip text (<code>null</code> permitted). 129: * @param urlText the URL text for HTML image maps (<code>null</code> 130: * permitted). 131: */ 132: public ChartEntity(Shape area, String toolTipText, String urlText) { 133: if (area == null) { 134: throw new IllegalArgumentException("Null 'area' argument."); 135: } 136: this.area = area; 137: this.toolTipText = toolTipText; 138: this.urlText = urlText; 139: } 140: 141: /** 142: * Returns the area occupied by the entity (in Java 2D space). 143: * 144: * @return The area (never <code>null</code>). 145: */ 146: public Shape getArea() { 147: return this.area; 148: } 149: 150: /** 151: * Sets the area for the entity. 152: * <P> 153: * This class conveys information about chart entities back to a client. 154: * Setting this area doesn't change the entity (which has already been 155: * drawn). 156: * 157: * @param area the area (<code>null</code> not permitted). 158: */ 159: public void setArea(Shape area) { 160: if (area == null) { 161: throw new IllegalArgumentException("Null 'area' argument."); 162: } 163: this.area = area; 164: } 165: 166: /** 167: * Returns the tool tip text for the entity. 168: * 169: * @return The tool tip text (possibly <code>null</code>). 170: */ 171: public String getToolTipText() { 172: return this.toolTipText; 173: } 174: 175: /** 176: * Sets the tool tip text. 177: * 178: * @param text the text (<code>null</code> permitted). 179: */ 180: public void setToolTipText(String text) { 181: this.toolTipText = text; 182: } 183: 184: /** 185: * Returns the URL text for the entity. 186: * 187: * @return The URL text (possibly <code>null</code>). 188: */ 189: public String getURLText() { 190: return this.urlText; 191: } 192: 193: /** 194: * Sets the URL text. 195: * 196: * @param text the text (<code>null</code> permitted). 197: */ 198: public void setURLText(String text) { 199: this.urlText = text; 200: } 201: 202: /** 203: * Returns a string describing the entity area. This string is intended 204: * for use in an AREA tag when generating an image map. 205: * 206: * @return The shape type (never <code>null</code>). 207: */ 208: public String getShapeType() { 209: if (this.area instanceof Rectangle2D) { 210: return "rect"; 211: } 212: else { 213: return "poly"; 214: } 215: } 216: 217: /** 218: * Returns the shape coordinates as a string. 219: * 220: * @return The shape coordinates (never <code>null</code>). 221: */ 222: public String getShapeCoords() { 223: if (this.area instanceof Rectangle2D) { 224: return getRectCoords((Rectangle2D) this.area); 225: } 226: else { 227: return getPolyCoords(this.area); 228: } 229: } 230: 231: /** 232: * Returns a string containing the coordinates (x1, y1, x2, y2) for a given 233: * rectangle. This string is intended for use in an image map. 234: * 235: * @param rectangle the rectangle (<code>null</code> not permitted). 236: * 237: * @return Upper left and lower right corner of a rectangle. 238: */ 239: private String getRectCoords(Rectangle2D rectangle) { 240: if (rectangle == null) { 241: throw new IllegalArgumentException("Null 'rectangle' argument."); 242: } 243: int x1 = (int) rectangle.getX(); 244: int y1 = (int) rectangle.getY(); 245: int x2 = x1 + (int) rectangle.getWidth(); 246: int y2 = y1 + (int) rectangle.getHeight(); 247: // fix by rfuller 248: if (x2 == x1) { 249: x2++; 250: } 251: if (y2 == y1) { 252: y2++; 253: } 254: // end fix by rfuller 255: return x1 + "," + y1 + "," + x2 + "," + y2; 256: } 257: 258: /** 259: * Returns a string containing the coordinates for a given shape. This 260: * string is intended for use in an image map. 261: * 262: * @param shape the shape (<code>null</code> not permitted). 263: * 264: * @return The coordinates for a given shape as string. 265: */ 266: private String getPolyCoords(Shape shape) { 267: if (shape == null) { 268: throw new IllegalArgumentException("Null 'shape' argument."); 269: } 270: StringBuffer result = new StringBuffer(); 271: boolean first = true; 272: float[] coords = new float[6]; 273: PathIterator pi = shape.getPathIterator(null, 1.0); 274: while (!pi.isDone()) { 275: pi.currentSegment(coords); 276: if (first) { 277: first = false; 278: result.append((int) coords[0]); 279: result.append(",").append((int) coords[1]); 280: } 281: else { 282: result.append(","); 283: result.append((int) coords[0]); 284: result.append(","); 285: result.append((int) coords[1]); 286: } 287: pi.next(); 288: } 289: return result.toString(); 290: } 291: 292: /** 293: * Returns an HTML image map tag for this entity. The returned fragment 294: * should be <code>XHTML 1.0</code> compliant. 295: * 296: * @param toolTipTagFragmentGenerator a generator for the HTML fragment 297: * that will contain the tooltip text (<code>null</code> not permitted 298: * if this entity contains tooltip information). 299: * @param urlTagFragmentGenerator a generator for the HTML fragment that 300: * will contain the URL reference (<code>null</code> not permitted if 301: * this entity has a URL). 302: * 303: * @return The HTML tag. 304: */ 305: public String getImageMapAreaTag( 306: ToolTipTagFragmentGenerator toolTipTagFragmentGenerator, 307: URLTagFragmentGenerator urlTagFragmentGenerator) { 308: 309: StringBuffer tag = new StringBuffer(); 310: boolean hasURL = (this.urlText == null ? false 311: : !this.urlText.equals("")); 312: boolean hasToolTip = (this.toolTipText == null ? false 313: : !this.toolTipText.equals("")); 314: if (hasURL || hasToolTip) { 315: tag.append("<area shape=\"" + getShapeType() + "\"" + " coords=\"" 316: + getShapeCoords() + "\""); 317: if (hasToolTip) { 318: tag.append(toolTipTagFragmentGenerator.generateToolTipFragment( 319: this.toolTipText)); 320: } 321: if (hasURL) { 322: tag.append(urlTagFragmentGenerator.generateURLFragment( 323: this.urlText)); 324: } 325: // if there is a tool tip, we expect it to generate the title and 326: // alt values, so we only add an empty alt if there is no tooltip 327: if (!hasToolTip) { 328: tag.append(" alt=\"\""); 329: } 330: tag.append("/>"); 331: } 332: return tag.toString(); 333: } 334: 335: /** 336: * Returns a string representation of the chart entity, useful for 337: * debugging. 338: * 339: * @return A string. 340: */ 341: public String toString() { 342: StringBuffer buf = new StringBuffer("ChartEntity: "); 343: buf.append("tooltip = "); 344: buf.append(this.toolTipText); 345: return buf.toString(); 346: } 347: 348: /** 349: * Tests the entity for equality with an arbitrary object. 350: * 351: * @param obj the object to test against (<code>null</code> permitted). 352: * 353: * @return A boolean. 354: */ 355: public boolean equals(Object obj) { 356: if (obj == this) { 357: return true; 358: } 359: if (obj instanceof ChartEntity) { 360: ChartEntity that = (ChartEntity) obj; 361: if (!this.area.equals(that.area)) { 362: return false; 363: } 364: if (!ObjectUtilities.equal(this.toolTipText, that.toolTipText)) { 365: return false; 366: } 367: if (!ObjectUtilities.equal(this.urlText, that.urlText)) { 368: return false; 369: } 370: return true; 371: } 372: return false; 373: } 374: 375: /** 376: * Returns a clone of the entity. 377: * 378: * @return A clone. 379: * 380: * @throws CloneNotSupportedException if there is a problem cloning the 381: * entity. 382: */ 383: public Object clone() throws CloneNotSupportedException { 384: return super.clone(); 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: SerialUtilities.writeShape(this.area, stream); 397: } 398: 399: /** 400: * Provides serialization support. 401: * 402: * @param stream the input stream. 403: * 404: * @throws IOException if there is an I/O error. 405: * @throws ClassNotFoundException if there is a classpath problem. 406: */ 407: private void readObject(ObjectInputStream stream) 408: throws IOException, ClassNotFoundException { 409: stream.defaultReadObject(); 410: this.area = SerialUtilities.readShape(stream); 411: } 412: 413: }