001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * ----------------- 028 * XYBarDataset.java 029 * ----------------- 030 * (C) Copyright 2004-2008, by Object Refinery Limited and Contributors. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * Changes 036 * ------- 037 * 02-Mar-2004 : Version 1 (DG); 038 * 05-May-2004 : Now extends AbstractIntervalXYDataset (DG); 039 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 040 * getYValue() (DG); 041 * ------------- JFREECHART 1.0.x --------------------------------------------- 042 * 25-Jan-2007 : Added some accessor methods, plus new equals() and clone() 043 * overrides (DG); 044 * 30-Jan-2007 : Added method overrides to prevent unnecessary object 045 * creation (DG); 046 * 22-Apr-2008 : Implemented PublicCloneable (DG); 047 * 048 */ 049 050 package org.jfree.data.xy; 051 052 import org.jfree.data.general.DatasetChangeEvent; 053 import org.jfree.data.general.DatasetChangeListener; 054 import org.jfree.util.PublicCloneable; 055 056 /** 057 * A dataset wrapper class that converts a standard {@link XYDataset} into an 058 * {@link IntervalXYDataset} suitable for use in creating XY bar charts. 059 */ 060 public class XYBarDataset extends AbstractIntervalXYDataset 061 implements IntervalXYDataset, DatasetChangeListener, PublicCloneable { 062 063 /** The underlying dataset. */ 064 private XYDataset underlying; 065 066 /** The bar width. */ 067 private double barWidth; 068 069 /** 070 * Creates a new dataset. 071 * 072 * @param underlying the underlying dataset (<code>null</code> not 073 * permitted). 074 * @param barWidth the width of the bars. 075 */ 076 public XYBarDataset(XYDataset underlying, double barWidth) { 077 this.underlying = underlying; 078 this.underlying.addChangeListener(this); 079 this.barWidth = barWidth; 080 } 081 082 /** 083 * Returns the underlying dataset that was specified via the constructor. 084 * 085 * @return The underlying dataset (never <code>null</code>). 086 * 087 * @since 1.0.4 088 */ 089 public XYDataset getUnderlyingDataset() { 090 return this.underlying; 091 } 092 093 /** 094 * Returns the bar width. 095 * 096 * @return The bar width. 097 * 098 * @see #setBarWidth(double) 099 * @since 1.0.4 100 */ 101 public double getBarWidth() { 102 return this.barWidth; 103 } 104 105 /** 106 * Sets the bar width and sends a {@link DatasetChangeEvent} to all 107 * registered listeners. 108 * 109 * @param barWidth the bar width. 110 * 111 * @see #getBarWidth() 112 * @since 1.0.4 113 */ 114 public void setBarWidth(double barWidth) { 115 this.barWidth = barWidth; 116 notifyListeners(new DatasetChangeEvent(this, this)); 117 } 118 119 /** 120 * Returns the number of series in the dataset. 121 * 122 * @return The series count. 123 */ 124 public int getSeriesCount() { 125 return this.underlying.getSeriesCount(); 126 } 127 128 /** 129 * Returns the key for a series. 130 * 131 * @param series the series index (in the range <code>0</code> to 132 * <code>getSeriesCount() - 1</code>). 133 * 134 * @return The series key. 135 */ 136 public Comparable getSeriesKey(int series) { 137 return this.underlying.getSeriesKey(series); 138 } 139 140 /** 141 * Returns the number of items in a series. 142 * 143 * @param series the series index (zero-based). 144 * 145 * @return The item count. 146 */ 147 public int getItemCount(int series) { 148 return this.underlying.getItemCount(series); 149 } 150 151 /** 152 * Returns the x-value for an item within a series. 153 * 154 * @param series the series index (zero-based). 155 * @param item the item index (zero-based). 156 * 157 * @return The x-value. 158 * 159 * @see #getXValue(int, int) 160 */ 161 public Number getX(int series, int item) { 162 return this.underlying.getX(series, item); 163 } 164 165 /** 166 * Returns the x-value (as a double primitive) for an item within a series. 167 * 168 * @param series the series index (zero-based). 169 * @param item the item index (zero-based). 170 * 171 * @return The value. 172 * 173 * @see #getX(int, int) 174 */ 175 public double getXValue(int series, int item) { 176 return this.underlying.getXValue(series, item); 177 } 178 179 /** 180 * Returns the y-value for an item within a series. 181 * 182 * @param series the series index (zero-based). 183 * @param item the item index (zero-based). 184 * 185 * @return The y-value (possibly <code>null</code>). 186 * 187 * @see #getYValue(int, int) 188 */ 189 public Number getY(int series, int item) { 190 return this.underlying.getY(series, item); 191 } 192 193 /** 194 * Returns the y-value (as a double primitive) for an item within a series. 195 * 196 * @param series the series index (zero-based). 197 * @param item the item index (zero-based). 198 * 199 * @return The value. 200 * 201 * @see #getY(int, int) 202 */ 203 public double getYValue(int series, int item) { 204 return this.underlying.getYValue(series, item); 205 } 206 207 /** 208 * Returns the starting X value for the specified series and item. 209 * 210 * @param series the series index (zero-based). 211 * @param item the item index (zero-based). 212 * 213 * @return The value. 214 */ 215 public Number getStartX(int series, int item) { 216 Number result = null; 217 Number xnum = this.underlying.getX(series, item); 218 if (xnum != null) { 219 result = new Double(xnum.doubleValue() - this.barWidth / 2.0); 220 } 221 return result; 222 } 223 224 /** 225 * Returns the starting x-value (as a double primitive) for an item within 226 * a series. 227 * 228 * @param series the series index (zero-based). 229 * @param item the item index (zero-based). 230 * 231 * @return The value. 232 * 233 * @see #getXValue(int, int) 234 */ 235 public double getStartXValue(int series, int item) { 236 return getXValue(series, item) - this.barWidth / 2.0; 237 } 238 239 /** 240 * Returns the ending X value for the specified series and item. 241 * 242 * @param series the series index (zero-based). 243 * @param item the item index (zero-based). 244 * 245 * @return The value. 246 */ 247 public Number getEndX(int series, int item) { 248 Number result = null; 249 Number xnum = this.underlying.getX(series, item); 250 if (xnum != null) { 251 result = new Double(xnum.doubleValue() + this.barWidth / 2.0); 252 } 253 return result; 254 } 255 256 /** 257 * Returns the ending x-value (as a double primitive) for an item within 258 * a series. 259 * 260 * @param series the series index (zero-based). 261 * @param item the item index (zero-based). 262 * 263 * @return The value. 264 * 265 * @see #getXValue(int, int) 266 */ 267 public double getEndXValue(int series, int item) { 268 return getXValue(series, item) + this.barWidth / 2.0; 269 } 270 271 /** 272 * Returns the starting Y value for the specified series and item. 273 * 274 * @param series the series index (zero-based). 275 * @param item the item index (zero-based). 276 * 277 * @return The value. 278 */ 279 public Number getStartY(int series, int item) { 280 return this.underlying.getY(series, item); 281 } 282 283 /** 284 * Returns the starting y-value (as a double primitive) for an item within 285 * a series. 286 * 287 * @param series the series index (zero-based). 288 * @param item the item index (zero-based). 289 * 290 * @return The value. 291 * 292 * @see #getYValue(int, int) 293 */ 294 public double getStartYValue(int series, int item) { 295 return getYValue(series, item); 296 } 297 298 /** 299 * Returns the ending Y value for the specified series and item. 300 * 301 * @param series the series index (zero-based). 302 * @param item the item index (zero-based). 303 * 304 * @return The value. 305 */ 306 public Number getEndY(int series, int item) { 307 return this.underlying.getY(series, item); 308 } 309 310 /** 311 * Returns the ending y-value (as a double primitive) for an item within 312 * a series. 313 * 314 * @param series the series index (zero-based). 315 * @param item the item index (zero-based). 316 * 317 * @return The value. 318 * 319 * @see #getYValue(int, int) 320 */ 321 public double getEndYValue(int series, int item) { 322 return getYValue(series, item); 323 } 324 325 /** 326 * Receives notification of an dataset change event. 327 * 328 * @param event information about the event. 329 */ 330 public void datasetChanged(DatasetChangeEvent event) { 331 notifyListeners(event); 332 } 333 334 /** 335 * Tests this dataset for equality with an arbitrary object. 336 * 337 * @param obj the object (<code>null</code> permitted). 338 * 339 * @return A boolean. 340 */ 341 public boolean equals(Object obj) { 342 if (obj == this) { 343 return true; 344 } 345 if (!(obj instanceof XYBarDataset)) { 346 return false; 347 } 348 XYBarDataset that = (XYBarDataset) obj; 349 if (!this.underlying.equals(that.underlying)) { 350 return false; 351 } 352 if (this.barWidth != that.barWidth) { 353 return false; 354 } 355 return true; 356 } 357 358 /** 359 * Returns an independent copy of the dataset. Note that: 360 * <ul> 361 * <li>the underlying dataset is only cloned if it implements the 362 * {@link PublicCloneable} interface;</li> 363 * <li>the listeners registered with this dataset are not carried over to 364 * the cloned dataset.</li> 365 * </ul> 366 * 367 * @return An independent copy of the dataset. 368 * 369 * @throws CloneNotSupportedException if the dataset cannot be cloned for 370 * any reason. 371 */ 372 public Object clone() throws CloneNotSupportedException { 373 XYBarDataset clone = (XYBarDataset) super.clone(); 374 if (this.underlying instanceof PublicCloneable) { 375 PublicCloneable pc = (PublicCloneable) this.underlying; 376 clone.underlying = (XYDataset) pc.clone(); 377 } 378 return clone; 379 } 380 381 }