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