Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2008, 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: * AbstractXYItemLabelGenerator.java 29: * --------------------------------- 30: * (C) Copyright 2004-2008, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * Changes 36: * ------- 37: * 27-Feb-2004 : Version 1 (DG); 38: * 12-May-2004 : Moved default tool tip format to 39: * StandardXYToolTipGenerator (DG); 40: * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 41: * getYValue() (DG); 42: * 08-Oct-2004 : Modified createItemArray() method to handle null values (DG); 43: * 10-Jan-2005 : Updated createItemArray() to use x, y primitives if 44: * possible (DG); 45: * ------------- JFREECHART 1.0.x -------------------------------------------- 46: * 26-Jan-2006 : Minor API doc update (DG); 47: * 25-Jan-2007 : Added new constructor and fixed bug in clone() method (DG); 48: * 16-Oct-2007 : Removed redundant code (DG); 49: * 23-Nov-2007 : Implemented hashCode() (DG); 50: * 26-May-2008 : Added accessor methods for nullYString and updated equals() 51: * method (DG); 52: * 53: */ 54: 55: package org.jfree.chart.labels; 56: 57: import java.io.Serializable; 58: import java.text.DateFormat; 59: import java.text.MessageFormat; 60: import java.text.NumberFormat; 61: import java.util.Date; 62: 63: import org.jfree.chart.HashUtilities; 64: import org.jfree.data.xy.XYDataset; 65: import org.jfree.util.ObjectUtilities; 66: 67: /** 68: * A base class for creating item label generators. 69: */ 70: public class AbstractXYItemLabelGenerator implements Cloneable, Serializable { 71: 72: /** For serialization. */ 73: private static final long serialVersionUID = 5869744396278660636L; 74: 75: /** The item label format string. */ 76: private String formatString; 77: 78: /** A number formatter for the x value. */ 79: private NumberFormat xFormat; 80: 81: /** A date formatter for the x value. */ 82: private DateFormat xDateFormat; 83: 84: /** A formatter for the y value. */ 85: private NumberFormat yFormat; 86: 87: /** A date formatter for the y value. */ 88: private DateFormat yDateFormat; 89: 90: /** The string used to represent 'null' for the y-value. */ 91: private String nullYString = "null"; 92: 93: /** 94: * Creates an item label generator using default number formatters. 95: */ 96: protected AbstractXYItemLabelGenerator() { 97: this("{2}", NumberFormat.getNumberInstance(), 98: NumberFormat.getNumberInstance()); 99: } 100: 101: /** 102: * Creates an item label generator using the specified number formatters. 103: * 104: * @param formatString the item label format string (<code>null</code> 105: * not permitted). 106: * @param xFormat the format object for the x values (<code>null</code> 107: * not permitted). 108: * @param yFormat the format object for the y values (<code>null</code> 109: * not permitted). 110: */ 111: protected AbstractXYItemLabelGenerator(String formatString, 112: NumberFormat xFormat, 113: NumberFormat yFormat) { 114: 115: if (formatString == null) { 116: throw new IllegalArgumentException("Null 'formatString' argument."); 117: } 118: if (xFormat == null) { 119: throw new IllegalArgumentException("Null 'xFormat' argument."); 120: } 121: if (yFormat == null) { 122: throw new IllegalArgumentException("Null 'yFormat' argument."); 123: } 124: this.formatString = formatString; 125: this.xFormat = xFormat; 126: this.yFormat = yFormat; 127: 128: } 129: 130: /** 131: * Creates an item label generator using the specified number formatters. 132: * 133: * @param formatString the item label format string (<code>null</code> 134: * not permitted). 135: * @param xFormat the format object for the x values (<code>null</code> 136: * permitted). 137: * @param yFormat the format object for the y values (<code>null</code> 138: * not permitted). 139: */ 140: protected AbstractXYItemLabelGenerator(String formatString, 141: DateFormat xFormat, 142: NumberFormat yFormat) { 143: 144: this(formatString, NumberFormat.getInstance(), yFormat); 145: this.xDateFormat = xFormat; 146: 147: } 148: 149: /** 150: * Creates an item label generator using the specified formatters (a 151: * number formatter for the x-values and a date formatter for the 152: * y-values). 153: * 154: * @param formatString the item label format string (<code>null</code> 155: * not permitted). 156: * @param xFormat the format object for the x values (<code>null</code> 157: * permitted). 158: * @param yFormat the format object for the y values (<code>null</code> 159: * not permitted). 160: * 161: * @since 1.0.4 162: */ 163: protected AbstractXYItemLabelGenerator(String formatString, 164: NumberFormat xFormat, DateFormat yFormat) { 165: 166: this(formatString, xFormat, NumberFormat.getInstance()); 167: this.yDateFormat = yFormat; 168: } 169: 170: /** 171: * Creates an item label generator using the specified number formatters. 172: * 173: * @param formatString the item label format string (<code>null</code> 174: * not permitted). 175: * @param xFormat the format object for the x values (<code>null</code> 176: * permitted). 177: * @param yFormat the format object for the y values (<code>null</code> 178: * not permitted). 179: */ 180: protected AbstractXYItemLabelGenerator(String formatString, 181: DateFormat xFormat, 182: DateFormat yFormat) { 183: 184: this(formatString, NumberFormat.getInstance(), 185: NumberFormat.getInstance()); 186: this.xDateFormat = xFormat; 187: this.yDateFormat = yFormat; 188: 189: } 190: 191: /** 192: * Returns the format string (this controls the overall structure of the 193: * label). 194: * 195: * @return The format string (never <code>null</code>). 196: */ 197: public String getFormatString() { 198: return this.formatString; 199: } 200: 201: /** 202: * Returns the number formatter for the x-values. 203: * 204: * @return The number formatter (possibly <code>null</code>). 205: */ 206: public NumberFormat getXFormat() { 207: return this.xFormat; 208: } 209: 210: /** 211: * Returns the date formatter for the x-values. 212: * 213: * @return The date formatter (possibly <code>null</code>). 214: */ 215: public DateFormat getXDateFormat() { 216: return this.xDateFormat; 217: } 218: 219: /** 220: * Returns the number formatter for the y-values. 221: * 222: * @return The number formatter (possibly <code>null</code>). 223: */ 224: public NumberFormat getYFormat() { 225: return this.yFormat; 226: } 227: 228: /** 229: * Returns the date formatter for the y-values. 230: * 231: * @return The date formatter (possibly <code>null</code>). 232: */ 233: public DateFormat getYDateFormat() { 234: return this.yDateFormat; 235: } 236: 237: /** 238: * Generates a label string for an item in the dataset. 239: * 240: * @param dataset the dataset (<code>null</code> not permitted). 241: * @param series the series (zero-based index). 242: * @param item the item (zero-based index). 243: * 244: * @return The label (possibly <code>null</code>). 245: */ 246: public String generateLabelString(XYDataset dataset, int series, int item) { 247: String result = null; 248: Object[] items = createItemArray(dataset, series, item); 249: result = MessageFormat.format(this.formatString, items); 250: return result; 251: } 252: 253: /** 254: * Returns the string representing a null value. 255: * 256: * @return The string representing a null value. 257: * 258: * @since 1.0.10 259: */ 260: public String getNullYString() { 261: return this.nullYString; 262: } 263: 264: /** 265: * Creates the array of items that can be passed to the 266: * {@link MessageFormat} class for creating labels. 267: * 268: * @param dataset the dataset (<code>null</code> not permitted). 269: * @param series the series (zero-based index). 270: * @param item the item (zero-based index). 271: * 272: * @return An array of three items from the dataset formatted as 273: * <code>String</code> objects (never <code>null</code>). 274: */ 275: protected Object[] createItemArray(XYDataset dataset, int series, 276: int item) { 277: Object[] result = new Object[3]; 278: result[0] = dataset.getSeriesKey(series).toString(); 279: 280: double x = dataset.getXValue(series, item); 281: if (this.xDateFormat != null) { 282: result[1] = this.xDateFormat.format(new Date((long) x)); 283: } 284: else { 285: result[1] = this.xFormat.format(x); 286: } 287: 288: double y = dataset.getYValue(series, item); 289: if (Double.isNaN(y) && dataset.getY(series, item) == null) { 290: result[2] = this.nullYString; 291: } 292: else { 293: if (this.yDateFormat != null) { 294: result[2] = this.yDateFormat.format(new Date((long) y)); 295: } 296: else { 297: result[2] = this.yFormat.format(y); 298: } 299: } 300: return result; 301: } 302: 303: /** 304: * Tests this object for equality with an arbitrary object. 305: * 306: * @param obj the other object (<code>null</code> permitted). 307: * 308: * @return A boolean. 309: */ 310: public boolean equals(Object obj) { 311: if (obj == this) { 312: return true; 313: } 314: if (!(obj instanceof AbstractXYItemLabelGenerator)) { 315: return false; 316: } 317: AbstractXYItemLabelGenerator that = (AbstractXYItemLabelGenerator) obj; 318: if (!this.formatString.equals(that.formatString)) { 319: return false; 320: } 321: if (!ObjectUtilities.equal(this.xFormat, that.xFormat)) { 322: return false; 323: } 324: if (!ObjectUtilities.equal(this.xDateFormat, that.xDateFormat)) { 325: return false; 326: } 327: if (!ObjectUtilities.equal(this.yFormat, that.yFormat)) { 328: return false; 329: } 330: if (!ObjectUtilities.equal(this.yDateFormat, that.yDateFormat)) { 331: return false; 332: } 333: if (!this.nullYString.equals(that.nullYString)) { 334: return false; 335: } 336: return true; 337: } 338: 339: /** 340: * Returns a hash code for this instance. 341: * 342: * @return A hash code. 343: */ 344: public int hashCode() { 345: int result = 127; 346: result = HashUtilities.hashCode(result, this.formatString); 347: result = HashUtilities.hashCode(result, this.xFormat); 348: result = HashUtilities.hashCode(result, this.xDateFormat); 349: result = HashUtilities.hashCode(result, this.yFormat); 350: result = HashUtilities.hashCode(result, this.yDateFormat); 351: return result; 352: } 353: 354: /** 355: * Returns an independent copy of the generator. 356: * 357: * @return A clone. 358: * 359: * @throws CloneNotSupportedException if cloning is not supported. 360: */ 361: public Object clone() throws CloneNotSupportedException { 362: AbstractXYItemLabelGenerator clone 363: = (AbstractXYItemLabelGenerator) super.clone(); 364: if (this.xFormat != null) { 365: clone.xFormat = (NumberFormat) this.xFormat.clone(); 366: } 367: if (this.yFormat != null) { 368: clone.yFormat = (NumberFormat) this.yFormat.clone(); 369: } 370: if (this.xDateFormat != null) { 371: clone.xDateFormat = (DateFormat) this.xDateFormat.clone(); 372: } 373: if (this.yDateFormat != null) { 374: clone.yDateFormat = (DateFormat) this.yDateFormat.clone(); 375: } 376: return clone; 377: } 378: 379: }