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