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