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: * CategoryTableXYDataset.java 29: * --------------------------- 30: * (C) Copyright 2004, 2005, by Andreas Schroeder and Contributors. 31: * 32: * Original Author: Andreas Schroeder; 33: * Contributor(s): David Gilbert (for Object Refinery Limited); 34: * 35: * $Id: CategoryTableXYDataset.java,v 1.7.2.2 2005/10/25 21:36:51 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 31-Mar-2004 : Version 1 (AS); 40: * 05-May-2004 : Now extends AbstractIntervalXYDataset (DG); 41: * 15-Jul-2004 : Switched interval access method names (DG); 42: * 18-Aug-2004 : Moved from org.jfree.data --> org.jfree.data.xy (DG); 43: * 17-Nov-2004 : Updates required by changes to DomainInfo interface (DG); 44: * 11-Jan-2005 : Removed deprecated code in preparation for 1.0.0 release (DG); 45: * 05-Oct-2005 : Made the interval delegate a dataset change listener (DG); 46: * 47: */ 48: 49: package org.jfree.data.xy; 50: 51: import org.jfree.data.DefaultKeyedValues2D; 52: import org.jfree.data.DomainInfo; 53: import org.jfree.data.Range; 54: import org.jfree.data.general.DatasetChangeEvent; 55: import org.jfree.data.general.DatasetUtilities; 56: 57: /** 58: * An implementation variant of the {@link TableXYDataset} where every series 59: * shares the same x-values (required for generating stacked area charts). 60: * This implementation uses a {@link DefaultKeyedValues2D} Object as backend 61: * implementation and is hence more "category oriented" than the {@link 62: * DefaultTableXYDataset} implementation. 63: * <p> 64: * This implementation provides no means to remove data items yet. 65: * This is due to the lack of such facility in the DefaultKeyedValues2D class. 66: * <p> 67: * This class also implements the {@link IntervalXYDataset} interface, but this 68: * implementation is provisional. 69: * 70: * @author Andreas Schroeder 71: */ 72: public class CategoryTableXYDataset extends AbstractIntervalXYDataset 73: implements TableXYDataset, 74: IntervalXYDataset, 75: DomainInfo { 76: 77: /** 78: * The backing data structure. 79: */ 80: private DefaultKeyedValues2D values; 81: 82: /** A delegate for controlling the interval width. */ 83: private IntervalXYDelegate intervalDelegate; 84: 85: /** 86: * Creates a new empty CategoryTableXYDataset. 87: */ 88: public CategoryTableXYDataset() { 89: this.values = new DefaultKeyedValues2D(true); 90: this.intervalDelegate = new IntervalXYDelegate(this); 91: addChangeListener(this.intervalDelegate); 92: } 93: 94: /** 95: * Adds a data item to this dataset and sends a {@link DatasetChangeEvent} 96: * to all registered listeners. 97: * 98: * @param x the x value. 99: * @param y the y value. 100: * @param seriesName the name of the series to add the data item. 101: */ 102: public void add(double x, double y, String seriesName) { 103: add(new Double(x), new Double(y), seriesName, true); 104: } 105: 106: /** 107: * Adds a data item to this dataset and, if requested, sends a 108: * {@link DatasetChangeEvent} to all registered listeners. 109: * 110: * @param x the x value. 111: * @param y the y value. 112: * @param seriesName the name of the series to add the data item. 113: * @param notify notify listeners? 114: */ 115: public void add(Number x, Number y, String seriesName, boolean notify) { 116: this.values.addValue(y, (Comparable) x, seriesName); 117: if (notify) { 118: fireDatasetChanged(); 119: } 120: } 121: 122: /** 123: * Removes a value from the dataset. 124: * 125: * @param x the x-value. 126: * @param seriesName the series name. 127: */ 128: public void remove(double x, String seriesName) { 129: remove(new Double(x), seriesName, true); 130: } 131: 132: /** 133: * Removes an item from the dataset. 134: * 135: * @param x the x-value. 136: * @param seriesName the series name. 137: * @param notify notify listeners? 138: */ 139: public void remove(Number x, String seriesName, boolean notify) { 140: this.values.removeValue((Comparable) x, seriesName); 141: if (notify) { 142: fireDatasetChanged(); 143: } 144: } 145: 146: 147: /** 148: * Returns the number of series in the collection. 149: * 150: * @return The series count. 151: */ 152: public int getSeriesCount() { 153: return this.values.getColumnCount(); 154: } 155: 156: /** 157: * Returns the key for a series. 158: * 159: * @param series the series index (zero-based). 160: * 161: * @return The key for a series. 162: */ 163: public Comparable getSeriesKey(int series) { 164: return this.values.getColumnKey(series); 165: } 166: 167: /** 168: * Returns the number of x values in the dataset. 169: * 170: * @return The item count. 171: */ 172: public int getItemCount() { 173: return this.values.getRowCount(); 174: } 175: 176: /** 177: * Returns the number of items in the specified series. 178: * Returns the same as {@link CategoryTableXYDataset#getItemCount()}. 179: * 180: * @param series the series index (zero-based). 181: * 182: * @return The item count. 183: */ 184: public int getItemCount(int series) { 185: return getItemCount(); // all series have the same number of items in 186: // this dataset 187: } 188: 189: /** 190: * Returns the x-value for the specified series and item. 191: * 192: * @param series the series index (zero-based). 193: * @param item the item index (zero-based). 194: * 195: * @return The value. 196: */ 197: public Number getX(int series, int item) { 198: return (Number) this.values.getRowKey(item); 199: } 200: 201: /** 202: * Returns the starting X value for the specified series and item. 203: * 204: * @param series the series index (zero-based). 205: * @param item the item index (zero-based). 206: * 207: * @return The starting X value. 208: */ 209: public Number getStartX(int series, int item) { 210: return this.intervalDelegate.getStartX(series, item); 211: } 212: 213: /** 214: * Returns the ending X value for the specified series and item. 215: * 216: * @param series the series index (zero-based). 217: * @param item the item index (zero-based). 218: * 219: * @return The ending X value. 220: */ 221: public Number getEndX(int series, int item) { 222: return this.intervalDelegate.getEndX(series, item); 223: } 224: 225: /** 226: * Returns the y-value for the specified series and item. 227: * 228: * @param series the series index (zero-based). 229: * @param item the item index (zero-based). 230: * 231: * @return The y value (possibly <code>null</code>). 232: */ 233: public Number getY(int series, int item) { 234: return this.values.getValue(item, series); 235: } 236: 237: /** 238: * Returns the starting Y value for the specified series and item. 239: * 240: * @param series the series index (zero-based). 241: * @param item the item index (zero-based). 242: * 243: * @return The starting Y value. 244: */ 245: public Number getStartY(int series, int item) { 246: return getY(series, item); 247: } 248: 249: /** 250: * Returns the ending Y value for the specified series and item. 251: * 252: * @param series the series index (zero-based). 253: * @param item the item index (zero-based). 254: * 255: * @return The ending Y value. 256: */ 257: public Number getEndY(int series, int item) { 258: return getY(series, item); 259: } 260: 261: /** 262: * Returns the minimum x-value in the dataset. 263: * 264: * @param includeInterval a flag that determines whether or not the 265: * x-interval is taken into account. 266: * 267: * @return The minimum value. 268: */ 269: public double getDomainLowerBound(boolean includeInterval) { 270: return this.intervalDelegate.getDomainLowerBound(includeInterval); 271: } 272: 273: /** 274: * Returns the maximum x-value in the dataset. 275: * 276: * @param includeInterval a flag that determines whether or not the 277: * x-interval is taken into account. 278: * 279: * @return The maximum value. 280: */ 281: public double getDomainUpperBound(boolean includeInterval) { 282: return this.intervalDelegate.getDomainUpperBound(includeInterval); 283: } 284: 285: /** 286: * Returns the range of the values in this dataset's domain. 287: * 288: * @param includeInterval a flag that determines whether or not the 289: * x-interval is taken into account. 290: * 291: * @return The range. 292: */ 293: public Range getDomainBounds(boolean includeInterval) { 294: if (includeInterval) { 295: return this.intervalDelegate.getDomainBounds(includeInterval); 296: } 297: else { 298: return DatasetUtilities.iterateDomainBounds(this, includeInterval); 299: } 300: } 301: 302: /** 303: * Returns the interval position factor. 304: * 305: * @return The interval position factor. 306: */ 307: public double getIntervalPositionFactor() { 308: return this.intervalDelegate.getIntervalPositionFactor(); 309: } 310: 311: /** 312: * Sets the interval position factor. Must be between 0.0 and 1.0 inclusive. 313: * If the factor is 0.5, the gap is in the middle of the x values. If it 314: * is lesser than 0.5, the gap is farther to the left and if greater than 315: * 0.5 it gets farther to the right. 316: * 317: * @param d the new interval position factor. 318: */ 319: public void setIntervalPositionFactor(double d) { 320: this.intervalDelegate.setIntervalPositionFactor(d); 321: fireDatasetChanged(); 322: } 323: 324: /** 325: * Returns the full interval width. 326: * 327: * @return The interval width to use. 328: */ 329: public double getIntervalWidth() { 330: return this.intervalDelegate.getIntervalWidth(); 331: } 332: 333: /** 334: * Sets the interval width to a fixed value, and sends a 335: * {@link DatasetChangeEvent} to all registered listeners. 336: * 337: * @param d the new interval width (must be > 0). 338: */ 339: public void setIntervalWidth(double d) { 340: this.intervalDelegate.setFixedIntervalWidth(d); 341: fireDatasetChanged(); 342: } 343: 344: /** 345: * Returns whether the interval width is automatically calculated or not. 346: * 347: * @return whether the width is automatically calculated or not. 348: */ 349: public boolean isAutoWidth() { 350: return this.intervalDelegate.isAutoWidth(); 351: } 352: 353: /** 354: * Sets the flag that indicates whether the interval width is automatically 355: * calculated or not. 356: * 357: * @param b the flag. 358: */ 359: public void setAutoWidth(boolean b) { 360: this.intervalDelegate.setAutoWidth(b); 361: fireDatasetChanged(); 362: } 363: 364: /** 365: * Tests this dataset for equality with an arbitrary object. 366: * 367: * @param obj the object (<code>null</code> permitted). 368: * 369: * @return A boolean. 370: */ 371: public boolean equals(Object obj) { 372: if (!(obj instanceof CategoryTableXYDataset)) { 373: return false; 374: } 375: CategoryTableXYDataset that = (CategoryTableXYDataset) obj; 376: if (!this.intervalDelegate.equals(that.intervalDelegate)) { 377: return false; 378: } 379: if (!this.values.equals(that.values)) { 380: return false; 381: } 382: return true; 383: } 384: 385: }