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 * $Id: XYBarDataset.java,v 1.4.2.4 2007/01/30 15:02:33 mungady Exp $
036 *
037 * Changes
038 * -------
039 * 02-Mar-2004 : Version 1 (DG);
040 * 05-May-2004 : Now extends AbstractIntervalXYDataset (DG);
041 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
042 * getYValue() (DG);
043 * ------------- JFREECHART 1.0.x ---------------------------------------------
044 * 25-Jan-2007 : Added some accessor methods, plus new equals() and clone()
045 * overrides (DG);
046 * 30-Jan-2007 : Added method overrides to prevent unnecessary object
047 * creation (DG);
048 *
049 */
050
051 package org.jfree.data.xy;
052
053 import org.jfree.data.general.DatasetChangeEvent;
054 import org.jfree.data.general.DatasetChangeListener;
055 import org.jfree.util.PublicCloneable;
056
057 /**
058 * A dataset wrapper class that converts a standard {@link XYDataset} into an
059 * {@link IntervalXYDataset} suitable for use in creating XY bar charts.
060 */
061 public class XYBarDataset extends AbstractIntervalXYDataset
062 implements IntervalXYDataset, DatasetChangeListener {
063
064 /** The underlying dataset. */
065 private XYDataset underlying;
066
067 /** The bar width. */
068 private double barWidth;
069
070 /**
071 * Creates a new dataset.
072 *
073 * @param underlying the underlying dataset (<code>null</code> not
074 * permitted).
075 * @param barWidth the width of the bars.
076 */
077 public XYBarDataset(XYDataset underlying, double barWidth) {
078 this.underlying = underlying;
079 this.underlying.addChangeListener(this);
080 this.barWidth = barWidth;
081 }
082
083 /**
084 * Returns the underlying dataset that was specified via the constructor.
085 *
086 * @return The underlying dataset (never <code>null</code>).
087 *
088 * @since 1.0.4
089 */
090 public XYDataset getUnderlyingDataset() {
091 return this.underlying;
092 }
093
094 /**
095 * Returns the bar width.
096 *
097 * @return The bar width.
098 *
099 * @see #setBarWidth(double)
100 * @since 1.0.4
101 */
102 public double getBarWidth() {
103 return this.barWidth;
104 }
105
106 /**
107 * Sets the bar width and sends a {@link DatasetChangeEvent} to all
108 * registered listeners.
109 *
110 * @param barWidth the bar width.
111 *
112 * @see #getBarWidth()
113 * @since 1.0.4
114 */
115 public void setBarWidth(double barWidth) {
116 this.barWidth = barWidth;
117 notifyListeners(new DatasetChangeEvent(this, this));
118 }
119
120 /**
121 * Returns the number of series in the dataset.
122 *
123 * @return The series count.
124 */
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 public Comparable getSeriesKey(int series) {
138 return this.underlying.getSeriesKey(series);
139 }
140
141 /**
142 * Returns the number of items in a series.
143 *
144 * @param series the series index (zero-based).
145 *
146 * @return The item count.
147 */
148 public int getItemCount(int series) {
149 return this.underlying.getItemCount(series);
150 }
151
152 /**
153 * Returns the x-value for an item within a series.
154 *
155 * @param series the series index (zero-based).
156 * @param item the item index (zero-based).
157 *
158 * @return The x-value.
159 *
160 * @see #getXValue(int, int)
161 */
162 public Number getX(int series, int item) {
163 return this.underlying.getX(series, item);
164 }
165
166 /**
167 * Returns the x-value (as a double primitive) for an item within a series.
168 *
169 * @param series the series index (zero-based).
170 * @param item the item index (zero-based).
171 *
172 * @return The value.
173 *
174 * @see #getX(int, int)
175 */
176 public double getXValue(int series, int item) {
177 return this.underlying.getXValue(series, item);
178 }
179
180 /**
181 * Returns the y-value for an item within a series.
182 *
183 * @param series the series index (zero-based).
184 * @param item the item index (zero-based).
185 *
186 * @return The y-value (possibly <code>null</code>).
187 *
188 * @see #getYValue(int, int)
189 */
190 public Number getY(int series, int item) {
191 return this.underlying.getY(series, item);
192 }
193
194 /**
195 * Returns the y-value (as a double primitive) for an item within a series.
196 *
197 * @param series the series index (zero-based).
198 * @param item the item index (zero-based).
199 *
200 * @return The value.
201 *
202 * @see #getY(int, int)
203 */
204 public double getYValue(int series, int item) {
205 return this.underlying.getYValue(series, item);
206 }
207
208 /**
209 * Returns the starting X value for the specified series and item.
210 *
211 * @param series the series index (zero-based).
212 * @param item the item index (zero-based).
213 *
214 * @return The value.
215 */
216 public Number getStartX(int series, int item) {
217 Number result = null;
218 Number xnum = this.underlying.getX(series, item);
219 if (xnum != null) {
220 result = new Double(xnum.doubleValue() - this.barWidth / 2.0);
221 }
222 return result;
223 }
224
225 /**
226 * Returns the starting x-value (as a double primitive) for an item within
227 * a series.
228 *
229 * @param series the series index (zero-based).
230 * @param item the item index (zero-based).
231 *
232 * @return The value.
233 *
234 * @see #getXValue(int, int)
235 */
236 public double getStartXValue(int series, int item) {
237 return getXValue(series, item) - this.barWidth / 2.0;
238 }
239
240 /**
241 * Returns the ending X value for the specified series and item.
242 *
243 * @param series the series index (zero-based).
244 * @param item the item index (zero-based).
245 *
246 * @return The value.
247 */
248 public Number getEndX(int series, int item) {
249 Number result = null;
250 Number xnum = this.underlying.getX(series, item);
251 if (xnum != null) {
252 result = new Double(xnum.doubleValue() + this.barWidth / 2.0);
253 }
254 return result;
255 }
256
257 /**
258 * Returns the ending x-value (as a double primitive) for an item within
259 * a series.
260 *
261 * @param series the series index (zero-based).
262 * @param item the item index (zero-based).
263 *
264 * @return The value.
265 *
266 * @see #getXValue(int, int)
267 */
268 public double getEndXValue(int series, int item) {
269 return getXValue(series, item) + this.barWidth / 2.0;
270 }
271
272 /**
273 * Returns the starting Y value for the specified series and item.
274 *
275 * @param series the series index (zero-based).
276 * @param item the item index (zero-based).
277 *
278 * @return The value.
279 */
280 public Number getStartY(int series, int item) {
281 return this.underlying.getY(series, item);
282 }
283
284 /**
285 * Returns the starting y-value (as a double primitive) for an item within
286 * a series.
287 *
288 * @param series the series index (zero-based).
289 * @param item the item index (zero-based).
290 *
291 * @return The value.
292 *
293 * @see #getYValue(int, int)
294 */
295 public double getStartYValue(int series, int item) {
296 return getYValue(series, item);
297 }
298
299 /**
300 * Returns the ending Y value for the specified series and item.
301 *
302 * @param series the series index (zero-based).
303 * @param item the item index (zero-based).
304 *
305 * @return The value.
306 */
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 public double getEndYValue(int series, int item) {
323 return getYValue(series, item);
324 }
325
326 /**
327 * Receives notification of an dataset change event.
328 *
329 * @param event information about the event.
330 */
331 public void datasetChanged(DatasetChangeEvent event) {
332 this.notifyListeners(event);
333 }
334
335 /**
336 * Tests this dataset for equality with an arbitrary object.
337 *
338 * @param obj the object (<code>null</code> permitted).
339 *
340 * @return A boolean.
341 */
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 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 public Object clone() throws CloneNotSupportedException {
374 XYBarDataset clone = (XYBarDataset) super.clone();
375 if (this.underlying instanceof PublicCloneable) {
376 clone.underlying
377 = (XYDataset) ((PublicCloneable) this.underlying).clone();
378 }
379 return clone;
380 }
381
382 }