Frames | No Frames |
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 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-2005, 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.1 2005/10/25 20:41:59 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: * 65: */ 66: 67: package org.jfree.chart.entity; 68: 69: import java.awt.Shape; 70: import java.awt.geom.PathIterator; 71: import java.awt.geom.Rectangle2D; 72: import java.io.IOException; 73: import java.io.ObjectInputStream; 74: import java.io.ObjectOutputStream; 75: import java.io.Serializable; 76: 77: import org.jfree.chart.imagemap.ToolTipTagFragmentGenerator; 78: import org.jfree.chart.imagemap.URLTagFragmentGenerator; 79: import org.jfree.io.SerialUtilities; 80: import org.jfree.util.ObjectUtilities; 81: import org.jfree.util.PublicCloneable; 82: 83: /** 84: * A class that captures information about some component of a chart (a bar, 85: * line etc). 86: */ 87: public class ChartEntity implements Cloneable, PublicCloneable, Serializable { 88: 89: /** For serialization. */ 90: private static final long serialVersionUID = -4445994133561919083L; 91: 92: /** The area occupied by the entity (in Java 2D space). */ 93: private transient Shape area; 94: 95: /** The tool tip text for the entity. */ 96: private String toolTipText; 97: 98: /** The URL text for the entity. */ 99: private String urlText; 100: 101: /** 102: * Creates a new chart entity. 103: * 104: * @param area the area (<code>null</code> not permitted). 105: */ 106: public ChartEntity(Shape area) { 107: // defer argument checks... 108: this(area, null); 109: } 110: 111: /** 112: * Creates a new chart entity. 113: * 114: * @param area the area (<code>null</code> not permitted). 115: * @param toolTipText the tool tip text (<code>null</code> permitted). 116: */ 117: public ChartEntity(Shape area, String toolTipText) { 118: // defer argument checks... 119: this(area, toolTipText, null); 120: } 121: 122: /** 123: * Creates a new entity. 124: * 125: * @param area the area (<code>null</code> not permitted). 126: * @param toolTipText the tool tip text (<code>null</code> permitted). 127: * @param urlText the URL text for HTML image maps (<code>null</code> 128: * permitted). 129: */ 130: public ChartEntity(Shape area, String toolTipText, String urlText) { 131: if (area == null) { 132: throw new IllegalArgumentException("Null 'area' argument."); 133: } 134: this.area = area; 135: this.toolTipText = toolTipText; 136: this.urlText = urlText; 137: } 138: 139: /** 140: * Returns the area occupied by the entity (in Java 2D space). 141: * 142: * @return The area (never <code>null</code>). 143: */ 144: public Shape getArea() { 145: return this.area; 146: } 147: 148: /** 149: * Sets the area for the entity. 150: * <P> 151: * This class conveys information about chart entities back to a client. 152: * Setting this area doesn't change the entity (which has already been 153: * drawn). 154: * 155: * @param area the area (<code>null</code> not permitted). 156: */ 157: public void setArea(Shape area) { 158: if (area == null) { 159: throw new IllegalArgumentException("Null 'area' argument."); 160: } 161: this.area = area; 162: } 163: 164: /** 165: * Returns the tool tip text for the entity. 166: * 167: * @return The tool tip text (possibly <code>null</code>). 168: */ 169: public String getToolTipText() { 170: return this.toolTipText; 171: } 172: 173: /** 174: * Sets the tool tip text. 175: * 176: * @param text the text (<code>null</code> permitted). 177: */ 178: public void setToolTipText(String text) { 179: this.toolTipText = text; 180: } 181: 182: /** 183: * Returns the URL text for the entity. 184: * 185: * @return The URL text (possibly <code>null</code>). 186: */ 187: public String getURLText() { 188: return this.urlText; 189: } 190: 191: /** 192: * Sets the URL text. 193: * 194: * @param text the text (<code>null</code> permitted). 195: */ 196: public void setURLText(String text) { 197: this.urlText = text; 198: } 199: 200: /** 201: * Returns a string describing the entity area. This string is intended 202: * for use in an AREA tag when generating an image map. 203: * 204: * @return The shape type (never <code>null</code>). 205: */ 206: public String getShapeType() { 207: if (this.area instanceof Rectangle2D) { 208: return "rect"; 209: } 210: else { 211: return "poly"; 212: } 213: } 214: 215: /** 216: * Returns the shape coordinates as a string. 217: * 218: * @return The shape coordinates (never <code>null</code>). 219: */ 220: public String getShapeCoords() { 221: if (this.area instanceof Rectangle2D) { 222: return getRectCoords((Rectangle2D) this.area); 223: } 224: else { 225: return getPolyCoords(this.area); 226: } 227: } 228: 229: /** 230: * Returns a string containing the coordinates (x1, y1, x2, y2) for a given 231: * rectangle. This string is intended for use in an image map. 232: * 233: * @param rectangle the rectangle (<code>null</code> not permitted). 234: * 235: * @return Upper left and lower right corner of a rectangle. 236: */ 237: private String getRectCoords(Rectangle2D rectangle) { 238: if (rectangle == null) { 239: throw new IllegalArgumentException("Null 'rectangle' argument."); 240: } 241: int x1 = (int) rectangle.getX(); 242: int y1 = (int) rectangle.getY(); 243: int x2 = x1 + (int) rectangle.getWidth(); 244: int y2 = y1 + (int) rectangle.getHeight(); 245: // fix by rfuller 246: if (x2 == x1) { 247: x2++; 248: } 249: if (y2 == y1) { 250: y2++; 251: } 252: // end fix by rfuller 253: return x1 + "," + y1 + "," + x2 + "," + y2; 254: } 255: 256: /** 257: * Returns a string containing the coordinates for a given shape. This 258: * string is intended for use in an image map. 259: * 260: * @param shape the shape (<code>null</code> not permitted). 261: * 262: * @return The coordinates for a given shape as string. 263: */ 264: private String getPolyCoords(Shape shape) { 265: if (shape == null) { 266: throw new IllegalArgumentException("Null 'shape' argument."); 267: } 268: StringBuffer result = new StringBuffer(); 269: boolean first = true; 270: float[] coords = new float[6]; 271: PathIterator pi = shape.getPathIterator(null, 1.0); 272: while (!pi.isDone()) { 273: pi.currentSegment(coords); 274: if (first) { 275: first = false; 276: result.append((int) coords[0]); 277: result.append(",").append((int) coords[1]); 278: } 279: else { 280: result.append(","); 281: result.append((int) coords[0]); 282: result.append(","); 283: result.append((int) coords[1]); 284: } 285: pi.next(); 286: } 287: return result.toString(); 288: } 289: 290: /** 291: * Returns an HTML image map tag for this entity. The returned fragment 292: * should be <code>XHTML 1.0</code> compliant. 293: * 294: * @param toolTipTagFragmentGenerator the generator for tooltip fragment. 295: * @param urlTagFragmentGenerator the generator for the URL fragment. 296: * 297: * @return The HTML tag. 298: */ 299: public String getImageMapAreaTag( 300: ToolTipTagFragmentGenerator toolTipTagFragmentGenerator, 301: URLTagFragmentGenerator urlTagFragmentGenerator) { 302: 303: StringBuffer tag = new StringBuffer(); 304: boolean hasURL 305: = (this.urlText == null ? false : !this.urlText.equals("")); 306: boolean hasToolTip 307: = (this.toolTipText == null ? false : !this.toolTipText.equals("")); 308: if (hasURL || hasToolTip) { 309: tag.append( 310: "<area shape=\"" + getShapeType() + "\"" + " coords=\"" 311: + getShapeCoords() + "\"" 312: ); 313: if (hasToolTip) { 314: tag.append(toolTipTagFragmentGenerator.generateToolTipFragment( 315: this.toolTipText 316: )); 317: } 318: if (hasURL) { 319: tag.append( 320: urlTagFragmentGenerator.generateURLFragment(this.urlText) 321: ); 322: } 323: // if there is a tool tip, we expect it to generate the title and 324: // alt values, so we only add an empty alt if there is no tooltip 325: if (!hasToolTip) { 326: tag.append(" alt=\"\""); 327: } 328: tag.append("/>"); 329: } 330: return tag.toString(); 331: } 332: 333: /** 334: * Returns a string representation of the chart entity, useful for 335: * debugging. 336: * 337: * @return A string. 338: */ 339: public String toString() { 340: StringBuffer buf = new StringBuffer("ChartEntity: "); 341: buf.append("tooltip = "); 342: buf.append(this.toolTipText); 343: return buf.toString(); 344: } 345: 346: /** 347: * Tests the entity for equality with an arbitrary object. 348: * 349: * @param obj the object to test against (<code>null</code> permitted). 350: * 351: * @return A boolean. 352: */ 353: public boolean equals(Object obj) { 354: if (obj == this) { 355: return true; 356: } 357: if (obj instanceof ChartEntity) { 358: ChartEntity that = (ChartEntity) obj; 359: if (!this.area.equals(that.area)) { 360: return false; 361: } 362: if (!ObjectUtilities.equal(this.toolTipText, that.toolTipText)) { 363: return false; 364: } 365: if (!ObjectUtilities.equal(this.urlText, that.urlText)) { 366: return false; 367: } 368: return true; 369: } 370: return false; 371: } 372: 373: /** 374: * Returns a clone of the entity. 375: * 376: * @return A clone. 377: * 378: * @throws CloneNotSupportedException if there is a problem cloning the 379: * entity. 380: */ 381: public Object clone() throws CloneNotSupportedException { 382: return super.clone(); 383: } 384: 385: /** 386: * Provides serialization support. 387: * 388: * @param stream the output stream. 389: * 390: * @throws IOException if there is an I/O error. 391: */ 392: private void writeObject(ObjectOutputStream stream) throws IOException { 393: stream.defaultWriteObject(); 394: SerialUtilities.writeShape(this.area, stream); 395: } 396: 397: /** 398: * Provides serialization support. 399: * 400: * @param stream the input stream. 401: * 402: * @throws IOException if there is an I/O error. 403: * @throws ClassNotFoundException if there is a classpath problem. 404: */ 405: private void readObject(ObjectInputStream stream) 406: throws IOException, ClassNotFoundException { 407: stream.defaultReadObject(); 408: this.area = SerialUtilities.readShape(stream); 409: } 410: 411: }