001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2013, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 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 050package org.jfree.data.xy; 051 052import org.jfree.data.general.DatasetChangeEvent; 053import org.jfree.data.general.DatasetChangeListener; 054import 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 */ 060public 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 @Override 125 public int getSeriesCount() { 126 return this.underlying.getSeriesCount(); 127 } 128 129 /** 130 * Returns the key for a series. 131 * 132 * @param series the series index (in the range <code>0</code> to 133 * <code>getSeriesCount() - 1</code>). 134 * 135 * @return The series key. 136 */ 137 @Override 138 public Comparable getSeriesKey(int series) { 139 return this.underlying.getSeriesKey(series); 140 } 141 142 /** 143 * Returns the number of items in a series. 144 * 145 * @param series the series index (zero-based). 146 * 147 * @return The item count. 148 */ 149 @Override 150 public int getItemCount(int series) { 151 return this.underlying.getItemCount(series); 152 } 153 154 /** 155 * Returns the x-value for an item within a series. 156 * 157 * @param series the series index (zero-based). 158 * @param item the item index (zero-based). 159 * 160 * @return The x-value. 161 * 162 * @see #getXValue(int, int) 163 */ 164 @Override 165 public Number getX(int series, int item) { 166 return this.underlying.getX(series, item); 167 } 168 169 /** 170 * Returns the x-value (as a double primitive) for an item within a series. 171 * 172 * @param series the series index (zero-based). 173 * @param item the item index (zero-based). 174 * 175 * @return The value. 176 * 177 * @see #getX(int, int) 178 */ 179 @Override 180 public double getXValue(int series, int item) { 181 return this.underlying.getXValue(series, item); 182 } 183 184 /** 185 * Returns the y-value for an item within a series. 186 * 187 * @param series the series index (zero-based). 188 * @param item the item index (zero-based). 189 * 190 * @return The y-value (possibly <code>null</code>). 191 * 192 * @see #getYValue(int, int) 193 */ 194 @Override 195 public Number getY(int series, int item) { 196 return this.underlying.getY(series, item); 197 } 198 199 /** 200 * Returns the y-value (as a double primitive) for an item within a series. 201 * 202 * @param series the series index (zero-based). 203 * @param item the item index (zero-based). 204 * 205 * @return The value. 206 * 207 * @see #getY(int, int) 208 */ 209 @Override 210 public double getYValue(int series, int item) { 211 return this.underlying.getYValue(series, item); 212 } 213 214 /** 215 * Returns the starting X value for the specified series and item. 216 * 217 * @param series the series index (zero-based). 218 * @param item the item index (zero-based). 219 * 220 * @return The value. 221 */ 222 @Override 223 public Number getStartX(int series, int item) { 224 Number result = null; 225 Number xnum = this.underlying.getX(series, item); 226 if (xnum != null) { 227 result = new Double(xnum.doubleValue() - this.barWidth / 2.0); 228 } 229 return result; 230 } 231 232 /** 233 * Returns the starting x-value (as a double primitive) for an item within 234 * a series. 235 * 236 * @param series the series index (zero-based). 237 * @param item the item index (zero-based). 238 * 239 * @return The value. 240 * 241 * @see #getXValue(int, int) 242 */ 243 @Override 244 public double getStartXValue(int series, int item) { 245 return getXValue(series, item) - this.barWidth / 2.0; 246 } 247 248 /** 249 * Returns the ending X value for the specified series and item. 250 * 251 * @param series the series index (zero-based). 252 * @param item the item index (zero-based). 253 * 254 * @return The value. 255 */ 256 @Override 257 public Number getEndX(int series, int item) { 258 Number result = null; 259 Number xnum = this.underlying.getX(series, item); 260 if (xnum != null) { 261 result = new Double(xnum.doubleValue() + this.barWidth / 2.0); 262 } 263 return result; 264 } 265 266 /** 267 * Returns the ending x-value (as a double primitive) for an item within 268 * a series. 269 * 270 * @param series the series index (zero-based). 271 * @param item the item index (zero-based). 272 * 273 * @return The value. 274 * 275 * @see #getXValue(int, int) 276 */ 277 @Override 278 public double getEndXValue(int series, int item) { 279 return getXValue(series, item) + this.barWidth / 2.0; 280 } 281 282 /** 283 * Returns the starting Y value for the specified series and item. 284 * 285 * @param series the series index (zero-based). 286 * @param item the item index (zero-based). 287 * 288 * @return The value. 289 */ 290 @Override 291 public Number getStartY(int series, int item) { 292 return this.underlying.getY(series, item); 293 } 294 295 /** 296 * Returns the starting y-value (as a double primitive) for an item within 297 * a series. 298 * 299 * @param series the series index (zero-based). 300 * @param item the item index (zero-based). 301 * 302 * @return The value. 303 * 304 * @see #getYValue(int, int) 305 */ 306 @Override 307 public double getStartYValue(int series, int item) { 308 return getYValue(series, item); 309 } 310 311 /** 312 * Returns the ending Y value for the specified series and item. 313 * 314 * @param series the series index (zero-based). 315 * @param item the item index (zero-based). 316 * 317 * @return The value. 318 */ 319 @Override 320 public Number getEndY(int series, int item) { 321 return this.underlying.getY(series, item); 322 } 323 324 /** 325 * Returns the ending y-value (as a double primitive) for an item within 326 * a series. 327 * 328 * @param series the series index (zero-based). 329 * @param item the item index (zero-based). 330 * 331 * @return The value. 332 * 333 * @see #getYValue(int, int) 334 */ 335 @Override 336 public double getEndYValue(int series, int item) { 337 return getYValue(series, item); 338 } 339 340 /** 341 * Receives notification of an dataset change event. 342 * 343 * @param event information about the event. 344 */ 345 @Override 346 public void datasetChanged(DatasetChangeEvent event) { 347 notifyListeners(event); 348 } 349 350 /** 351 * Tests this dataset for equality with an arbitrary object. 352 * 353 * @param obj the object (<code>null</code> permitted). 354 * 355 * @return A boolean. 356 */ 357 @Override 358 public boolean equals(Object obj) { 359 if (obj == this) { 360 return true; 361 } 362 if (!(obj instanceof XYBarDataset)) { 363 return false; 364 } 365 XYBarDataset that = (XYBarDataset) obj; 366 if (!this.underlying.equals(that.underlying)) { 367 return false; 368 } 369 if (this.barWidth != that.barWidth) { 370 return false; 371 } 372 return true; 373 } 374 375 /** 376 * Returns an independent copy of the dataset. Note that: 377 * <ul> 378 * <li>the underlying dataset is only cloned if it implements the 379 * {@link PublicCloneable} interface;</li> 380 * <li>the listeners registered with this dataset are not carried over to 381 * the cloned dataset.</li> 382 * </ul> 383 * 384 * @return An independent copy of the dataset. 385 * 386 * @throws CloneNotSupportedException if the dataset cannot be cloned for 387 * any reason. 388 */ 389 @Override 390 public Object clone() throws CloneNotSupportedException { 391 XYBarDataset clone = (XYBarDataset) super.clone(); 392 if (this.underlying instanceof PublicCloneable) { 393 PublicCloneable pc = (PublicCloneable) this.underlying; 394 clone.underlying = (XYDataset) pc.clone(); 395 } 396 return clone; 397 } 398 399}