001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2020, 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-2020, by Object Refinery Limited and Contributors. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 */ 036 037package org.jfree.data.xy; 038 039import org.jfree.chart.util.PublicCloneable; 040import org.jfree.data.general.DatasetChangeEvent; 041import org.jfree.data.general.DatasetChangeListener; 042 043/** 044 * A dataset wrapper class that converts a standard {@link XYDataset} into an 045 * {@link IntervalXYDataset} suitable for use in creating XY bar charts. 046 */ 047public class XYBarDataset extends AbstractIntervalXYDataset 048 implements IntervalXYDataset, DatasetChangeListener, PublicCloneable { 049 050 /** The underlying dataset. */ 051 private XYDataset underlying; 052 053 /** The bar width. */ 054 private double barWidth; 055 056 /** 057 * Creates a new dataset. 058 * 059 * @param underlying the underlying dataset ({@code null} not 060 * permitted). 061 * @param barWidth the width of the bars. 062 */ 063 public XYBarDataset(XYDataset underlying, double barWidth) { 064 this.underlying = underlying; 065 this.underlying.addChangeListener(this); 066 this.barWidth = barWidth; 067 } 068 069 /** 070 * Returns the underlying dataset that was specified via the constructor. 071 * 072 * @return The underlying dataset (never {@code null}). 073 * 074 * @since 1.0.4 075 */ 076 public XYDataset getUnderlyingDataset() { 077 return this.underlying; 078 } 079 080 /** 081 * Returns the bar width. 082 * 083 * @return The bar width. 084 * 085 * @see #setBarWidth(double) 086 * @since 1.0.4 087 */ 088 public double getBarWidth() { 089 return this.barWidth; 090 } 091 092 /** 093 * Sets the bar width and sends a {@link DatasetChangeEvent} to all 094 * registered listeners. 095 * 096 * @param barWidth the bar width. 097 * 098 * @see #getBarWidth() 099 * @since 1.0.4 100 */ 101 public void setBarWidth(double barWidth) { 102 this.barWidth = barWidth; 103 notifyListeners(new DatasetChangeEvent(this, this)); 104 } 105 106 /** 107 * Returns the number of series in the dataset. 108 * 109 * @return The series count. 110 */ 111 @Override 112 public int getSeriesCount() { 113 return this.underlying.getSeriesCount(); 114 } 115 116 /** 117 * Returns the key for a series. 118 * 119 * @param series the series index (in the range {@code 0} to 120 * {@code getSeriesCount() - 1}). 121 * 122 * @return The series key. 123 */ 124 @Override 125 public Comparable getSeriesKey(int series) { 126 return this.underlying.getSeriesKey(series); 127 } 128 129 /** 130 * Returns the number of items in a series. 131 * 132 * @param series the series index (zero-based). 133 * 134 * @return The item count. 135 */ 136 @Override 137 public int getItemCount(int series) { 138 return this.underlying.getItemCount(series); 139 } 140 141 /** 142 * Returns the x-value for an item within a series. 143 * 144 * @param series the series index (zero-based). 145 * @param item the item index (zero-based). 146 * 147 * @return The x-value. 148 * 149 * @see #getXValue(int, int) 150 */ 151 @Override 152 public Number getX(int series, int item) { 153 return this.underlying.getX(series, item); 154 } 155 156 /** 157 * Returns the x-value (as a double primitive) for an item within a series. 158 * 159 * @param series the series index (zero-based). 160 * @param item the item index (zero-based). 161 * 162 * @return The value. 163 * 164 * @see #getX(int, int) 165 */ 166 @Override 167 public double getXValue(int series, int item) { 168 return this.underlying.getXValue(series, item); 169 } 170 171 /** 172 * Returns the y-value for an item within a series. 173 * 174 * @param series the series index (zero-based). 175 * @param item the item index (zero-based). 176 * 177 * @return The y-value (possibly {@code null}). 178 * 179 * @see #getYValue(int, int) 180 */ 181 @Override 182 public Number getY(int series, int item) { 183 return this.underlying.getY(series, item); 184 } 185 186 /** 187 * Returns the y-value (as a double primitive) for an item within a series. 188 * 189 * @param series the series index (zero-based). 190 * @param item the item index (zero-based). 191 * 192 * @return The value. 193 * 194 * @see #getY(int, int) 195 */ 196 @Override 197 public double getYValue(int series, int item) { 198 return this.underlying.getYValue(series, 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 value. 208 */ 209 @Override 210 public Number getStartX(int series, int item) { 211 Number result = null; 212 Number xnum = this.underlying.getX(series, item); 213 if (xnum != null) { 214 result = xnum.doubleValue() - this.barWidth / 2.0; 215 } 216 return result; 217 } 218 219 /** 220 * Returns the starting x-value (as a double primitive) for an item within 221 * a series. 222 * 223 * @param series the series index (zero-based). 224 * @param item the item index (zero-based). 225 * 226 * @return The value. 227 * 228 * @see #getXValue(int, int) 229 */ 230 @Override 231 public double getStartXValue(int series, int item) { 232 return getXValue(series, item) - this.barWidth / 2.0; 233 } 234 235 /** 236 * Returns the ending X value for the specified series and item. 237 * 238 * @param series the series index (zero-based). 239 * @param item the item index (zero-based). 240 * 241 * @return The value. 242 */ 243 @Override 244 public Number getEndX(int series, int item) { 245 Number result = null; 246 Number xnum = this.underlying.getX(series, item); 247 if (xnum != null) { 248 result = xnum.doubleValue() + this.barWidth / 2.0; 249 } 250 return result; 251 } 252 253 /** 254 * Returns the ending x-value (as a double primitive) for an item within 255 * a series. 256 * 257 * @param series the series index (zero-based). 258 * @param item the item index (zero-based). 259 * 260 * @return The value. 261 * 262 * @see #getXValue(int, int) 263 */ 264 @Override 265 public double getEndXValue(int series, int item) { 266 return getXValue(series, item) + this.barWidth / 2.0; 267 } 268 269 /** 270 * Returns the starting Y value for the specified series and item. 271 * 272 * @param series the series index (zero-based). 273 * @param item the item index (zero-based). 274 * 275 * @return The value. 276 */ 277 @Override 278 public Number getStartY(int series, int item) { 279 return this.underlying.getY(series, item); 280 } 281 282 /** 283 * Returns the starting y-value (as a double primitive) for an item within 284 * a series. 285 * 286 * @param series the series index (zero-based). 287 * @param item the item index (zero-based). 288 * 289 * @return The value. 290 * 291 * @see #getYValue(int, int) 292 */ 293 @Override 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 @Override 307 public Number getEndY(int series, int item) { 308 return this.underlying.getY(series, item); 309 } 310 311 /** 312 * Returns the ending y-value (as a double primitive) for an item within 313 * a series. 314 * 315 * @param series the series index (zero-based). 316 * @param item the item index (zero-based). 317 * 318 * @return The value. 319 * 320 * @see #getYValue(int, int) 321 */ 322 @Override 323 public double getEndYValue(int series, int item) { 324 return getYValue(series, item); 325 } 326 327 /** 328 * Receives notification of an dataset change event. 329 * 330 * @param event information about the event. 331 */ 332 @Override 333 public void datasetChanged(DatasetChangeEvent event) { 334 notifyListeners(event); 335 } 336 337 /** 338 * Tests this dataset for equality with an arbitrary object. 339 * 340 * @param obj the object ({@code null} permitted). 341 * 342 * @return A boolean. 343 */ 344 @Override 345 public boolean equals(Object obj) { 346 if (obj == this) { 347 return true; 348 } 349 if (!(obj instanceof XYBarDataset)) { 350 return false; 351 } 352 XYBarDataset that = (XYBarDataset) obj; 353 if (!this.underlying.equals(that.underlying)) { 354 return false; 355 } 356 if (this.barWidth != that.barWidth) { 357 return false; 358 } 359 return true; 360 } 361 362 /** 363 * Returns an independent copy of the dataset. Note that: 364 * <ul> 365 * <li>the underlying dataset is only cloned if it implements the 366 * {@link PublicCloneable} interface;</li> 367 * <li>the listeners registered with this dataset are not carried over to 368 * the cloned dataset.</li> 369 * </ul> 370 * 371 * @return An independent copy of the dataset. 372 * 373 * @throws CloneNotSupportedException if the dataset cannot be cloned for 374 * any reason. 375 */ 376 @Override 377 public Object clone() throws CloneNotSupportedException { 378 XYBarDataset clone = (XYBarDataset) super.clone(); 379 if (this.underlying instanceof PublicCloneable) { 380 PublicCloneable pc = (PublicCloneable) this.underlying; 381 clone.underlying = (XYDataset) pc.clone(); 382 } 383 return clone; 384 } 385 386}