KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > experimental > chart > renderer > xy > XYBlockRenderer


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * --------------------
28  * XYBlockRenderer.java
29  * --------------------
30  * (C) Copyright 2006, by Object Refinery Limited.
31  *
32  * Original Author: David Gilbert (for Object Refinery Limited);
33  * Contributor(s): -;
34  *
35  * $Id: XYBlockRenderer.java,v 1.1.2.1 2006/10/12 09:30:49 mungady Exp $
36  *
37  * Changes
38  * -------
39  * 05-Jul-2006 : Version 1 (DG);
40  *
41  */

42
43 package org.jfree.experimental.chart.renderer.xy;
44
45 import java.awt.BasicStroke JavaDoc;
46 import java.awt.Graphics2D JavaDoc;
47 import java.awt.Paint JavaDoc;
48 import java.awt.geom.Rectangle2D JavaDoc;
49 import java.io.Serializable JavaDoc;
50
51 import org.jfree.chart.axis.ValueAxis;
52 import org.jfree.chart.event.RendererChangeEvent;
53 import org.jfree.chart.plot.CrosshairState;
54 import org.jfree.chart.plot.PlotOrientation;
55 import org.jfree.chart.plot.PlotRenderingInfo;
56 import org.jfree.chart.plot.XYPlot;
57 import org.jfree.chart.renderer.xy.AbstractXYItemRenderer;
58 import org.jfree.chart.renderer.xy.XYItemRenderer;
59 import org.jfree.chart.renderer.xy.XYItemRendererState;
60 import org.jfree.data.Range;
61 import org.jfree.data.general.DatasetUtilities;
62 import org.jfree.data.xy.XYDataset;
63 import org.jfree.data.xy.XYZDataset;
64 import org.jfree.experimental.chart.renderer.LookupPaintScale;
65 import org.jfree.experimental.chart.renderer.PaintScale;
66 import org.jfree.ui.RectangleAnchor;
67
68 /**
69  * A renderer that represents data from an {@link XYZDataset} by drawing a
70  * color block at each (x, y) point, where the color is a function of the
71  * z-value from the dataset.
72  *
73  * WARNING: THIS CLASS IS NOT PART OF THE STANDARD JFREECHART API AND IS
74  * SUBJECT TO ALTERATION OR REMOVAL. DO NOT RELY ON THIS CLASS FOR
75  * PRODUCTION USE. Please experiment with this code and provide feedback.
76  */

77 public class XYBlockRenderer extends AbstractXYItemRenderer
78         implements XYItemRenderer, Cloneable JavaDoc, Serializable JavaDoc {
79
80     /**
81      * The block width (defaults to 1.0).
82      */

83     private double blockWidth = 1.0;
84     
85     /**
86      * The block height (defaults to 1.0).
87      */

88     private double blockHeight = 1.0;
89     
90     /**
91      * The anchor point used to align each block to its (x, y) location. The
92      * default value is <code>RectangleAnchor.CENTER</code>.
93      */

94     private RectangleAnchor blockAnchor = RectangleAnchor.CENTER;
95     
96     private double xOffset;
97     
98     private double yOffset;
99     
100     private PaintScale paintScale;
101     
102     /**
103      * Creates a new <code>XYBlockRenderer</code> instance with default
104      * attributes.
105      */

106     public XYBlockRenderer() {
107         updateOffsets();
108         this.paintScale = new LookupPaintScale();
109     }
110     
111     /**
112      * Returns the block width, in data/axis units.
113      *
114      * @return The block width.
115      *
116      * @see #setBlockWidth(double)
117      */

118     public double getBlockWidth() {
119         return this.blockWidth;
120     }
121     
122     /**
123      * Sets the width of the blocks used to represent each data item.
124      *
125      * @param width the new width, in data/axis units (must be > 0.0).
126      *
127      * @see #getBlockWidth()
128      */

129     public void setBlockWidth(double width) {
130         if (width <= 0.0) {
131             throw new IllegalArgumentException JavaDoc(
132                     "The 'width' argument must be > 0.0");
133         }
134         this.blockWidth = width;
135         updateOffsets();
136         this.notifyListeners(new RendererChangeEvent(this));
137     }
138     
139     /**
140      * Returns the block height, in data/axis units.
141      *
142      * @return The block height.
143      *
144      * @see #setBlockHeight(double)
145      */

146     public double getBlockHeight() {
147         return this.blockHeight;
148     }
149     
150     /**
151      * Sets the height of the blocks used to represent each data item.
152      *
153      * @param height the new height, in data/axis units (must be > 0.0).
154      *
155      * @see #getBlockHeight()
156      */

157     public void setBlockHeight(double height) {
158         if (height <= 0.0) {
159             throw new IllegalArgumentException JavaDoc(
160                     "The 'height' argument must be > 0.0");
161         }
162         this.blockHeight = height;
163         updateOffsets();
164         this.notifyListeners(new RendererChangeEvent(this));
165     }
166     
167     /**
168      * Returns the anchor point used to align a block at its (x, y) location.
169      * The default values is {@link RectangleAnchor#CENTER}.
170      *
171      * @return The anchor point (never <code>null</code>).
172      *
173      * @see #setBlockAnchor(RectangleAnchor)
174      */

175     public RectangleAnchor getBlockAnchor() {
176         return this.blockAnchor;
177     }
178     
179     /**
180      * Sets the anchor point used to align a block at its (x, y) location and
181      * sends a {@link RendererChangeEvent} to all registered listeners.
182      *
183      * @param anchor the anchor.
184      *
185      * @see #getBlockAnchor()
186      */

187     public void setBlockAnchor(RectangleAnchor anchor) {
188         if (anchor == null) {
189             throw new IllegalArgumentException JavaDoc("Null 'anchor' argument.");
190         }
191         if (this.blockAnchor.equals(anchor)) {
192             return; // no change
193
}
194         this.blockAnchor = anchor;
195         updateOffsets();
196         notifyListeners(new RendererChangeEvent(this));
197     }
198     
199     /**
200      * Sets the paint scale used by the renderer.
201      *
202      * @param scale the scale (<code>null</code> not permitted).
203      */

204     public void setPaintScale(PaintScale scale) {
205         if (scale == null) {
206             throw new IllegalArgumentException JavaDoc("Null 'scale' argument.");
207         }
208         this.paintScale = scale;
209         notifyListeners(new RendererChangeEvent(this));
210     }
211     
212     /**
213      * Updates the offsets to take into account the block width, height and
214      * anchor.
215      */

216     private void updateOffsets() {
217         if (this.blockAnchor.equals(RectangleAnchor.BOTTOM_LEFT)) {
218             xOffset = 0.0;
219             yOffset = 0.0;
220         }
221         else if (this.blockAnchor.equals(RectangleAnchor.BOTTOM)) {
222             xOffset = -this.blockWidth / 2.0;
223             yOffset = 0.0;
224         }
225         else if (this.blockAnchor.equals(RectangleAnchor.BOTTOM_RIGHT)) {
226             xOffset = -this.blockWidth;
227             yOffset = 0.0;
228         }
229         else if (this.blockAnchor.equals(RectangleAnchor.LEFT)) {
230             xOffset = 0.0;
231             yOffset = -this.blockHeight / 2.0;
232         }
233         else if (this.blockAnchor.equals(RectangleAnchor.CENTER)) {
234             xOffset = -this.blockWidth / 2.0;
235             yOffset = -this.blockHeight / 2.0;
236         }
237         else if (this.blockAnchor.equals(RectangleAnchor.RIGHT)) {
238             xOffset = -this.blockWidth;
239             yOffset = -this.blockHeight / 2.0;
240         }
241         else if (this.blockAnchor.equals(RectangleAnchor.TOP_LEFT)) {
242             xOffset = 0.0;
243             yOffset = -this.blockHeight;
244         }
245         else if (this.blockAnchor.equals(RectangleAnchor.TOP)) {
246             xOffset = -this.blockWidth / 2.0;
247             yOffset = -this.blockHeight;
248         }
249         else if (this.blockAnchor.equals(RectangleAnchor.TOP_RIGHT)) {
250             xOffset = -this.blockWidth;
251             yOffset = -this.blockHeight;
252         }
253     }
254     
255     /**
256      * Returns the lower and upper bounds (range) of the x-values in the
257      * specified dataset.
258      *
259      * @param dataset the dataset (<code>null</code> permitted).
260      *
261      * @return The range (<code>null</code> if the dataset is <code>null</code>
262      * or empty).
263      */

264     public Range findDomainBounds(XYDataset dataset) {
265         if (dataset != null) {
266             Range r = DatasetUtilities.findDomainBounds(dataset, false);
267             return new Range(r.getLowerBound() + xOffset, r.getUpperBound()
268                     + blockWidth + xOffset);
269         }
270         else {
271             return null;
272         }
273     }
274
275     /**
276      * Returns the range of values the renderer requires to display all the
277      * items from the specified dataset.
278      *
279      * @param dataset the dataset (<code>null</code> permitted).
280      *
281      * @return The range (<code>null</code> if the dataset is <code>null</code>
282      * or empty).
283      */

284     public Range findRangeBounds(XYDataset dataset) {
285         if (dataset != null) {
286             Range r = DatasetUtilities.findRangeBounds(dataset, false);
287             return new Range(r.getLowerBound() + yOffset, r.getUpperBound()
288                     + blockHeight + yOffset);
289         }
290         else {
291             return null;
292         }
293     }
294     
295     /**
296      * Draws the block representing the specified item.
297      *
298      * @param g2 the graphics device.
299      * @param state the state.
300      * @param dataArea the data area.
301      * @param info the plot rendering info.
302      * @param plot the plot.
303      * @param domainAxis the x-axis.
304      * @param rangeAxis the y-axis.
305      * @param dataset the dataset.
306      * @param series the series index.
307      * @param item the item index.
308      * @param crosshairState the crosshair state.
309      * @param pass the pass index.
310      */

311     public void drawItem(Graphics2D JavaDoc g2, XYItemRendererState state,
312             Rectangle2D JavaDoc dataArea, PlotRenderingInfo info, XYPlot plot,
313             ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset,
314             int series, int item, CrosshairState crosshairState, int pass) {
315         
316         double x = dataset.getXValue(series, item);
317         double y = dataset.getYValue(series, item);
318         double z = 0.0;
319         if (dataset instanceof XYZDataset) {
320             z = ((XYZDataset) dataset).getZValue(series, item);
321         }
322         Paint JavaDoc p = this.paintScale.getPaint(z);
323         double xx0 = domainAxis.valueToJava2D(x + this.xOffset, dataArea,
324                 plot.getDomainAxisEdge());
325         double yy0 = rangeAxis.valueToJava2D(y + this.yOffset, dataArea,
326                 plot.getRangeAxisEdge());
327         double xx1 = domainAxis.valueToJava2D(x + this.blockWidth
328                 + this.xOffset, dataArea, plot.getDomainAxisEdge());
329         double yy1 = rangeAxis.valueToJava2D(y + this.blockHeight
330                 + this.yOffset, dataArea, plot.getRangeAxisEdge());
331         Rectangle2D JavaDoc block;
332         PlotOrientation orientation = plot.getOrientation();
333         if (orientation.equals(PlotOrientation.HORIZONTAL)) {
334             block = new Rectangle2D.Double JavaDoc(Math.min(yy0, yy1),
335                     Math.min(xx0, xx1), Math.abs(yy1 - yy0),
336                     Math.abs(xx0 - xx1));
337         }
338         else {
339             block = new Rectangle2D.Double JavaDoc(Math.min(xx0, xx1),
340                     Math.min(yy0, yy1), Math.abs(xx1 - xx0),
341                     Math.abs(yy1 - yy0));
342         }
343         g2.setPaint(p);
344         g2.fill(block);
345         g2.setStroke(new BasicStroke JavaDoc(1.0f));
346         g2.draw(block);
347     }
348     
349     /**
350      * Tests this <code>XYBlockRenderer</code> for equality with an arbitrary
351      * object. This method returns <code>true</code> if and only if:
352      * <ul>
353      * <li><code>obj</code> is an instance of <code>XYBlockRenderer</code> (not
354      * <code>null</code>);</li>
355      * <li><code>obj</code> has the same field values as this
356      * <code>XYBlockRenderer</code>;</li>
357      * </ul>
358      *
359      * @param obj the object (<code>null</code> permitted).
360      *
361      * @return A boolean.
362      */

363     public boolean equals(Object JavaDoc obj) {
364         if (obj == this) {
365             return true;
366         }
367         if (!(obj instanceof XYBlockRenderer)) {
368             return false;
369         }
370         XYBlockRenderer that = (XYBlockRenderer) obj;
371         if (this.blockHeight != that.blockHeight) {
372             return false;
373         }
374         if (this.blockWidth != that.blockWidth) {
375             return false;
376         }
377         if (!this.blockAnchor.equals(that.blockAnchor)) {
378             return false;
379         }
380         if (!this.paintScale.equals(that.paintScale)) {
381             return false;
382         }
383         return super.equals(obj);
384     }
385     
386     /**
387      * Returns a clone of this renderer.
388      *
389      * @return A clone of this renderer.
390      *
391      * @throws CloneNotSupportedException if there is a problem creating the
392      * clone.
393      */

394     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
395         return super.clone();
396     }
397
398 }
399
Popular Tags