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 * DefaultPolarItemRenderer.java
029 * -----------------------------
030 * (C) Copyright 2004, 2006, 2007, by Solution Engineering, Inc. and
031 * Contributors.
032 *
033 * Original Author: Daniel Bridenbecker, Solution Engineering, Inc.;
034 * Contributor(s): David Gilbert (for Object Refinery Limited);
035 *
036 * $Id: DefaultPolarItemRenderer.java,v 1.7.2.9 2007/05/18 10:28:24 mungady Exp $
037 *
038 * Changes
039 * -------
040 * 19-Jan-2004 : Version 1, contributed by DB with minor changes by DG (DG);
041 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
042 * getYValue() (DG);
043 * 04-Oct-2004 : Renamed BooleanUtils --> BooleanUtilities (DG);
044 * 20-Apr-2005 : Update for change to LegendItem class (DG);
045 * ------------- JFREECHART 1.0.x ---------------------------------------------
046 * 04-Aug-2006 : Implemented equals() and clone() (DG);
047 * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG);
048 * 14-Mar-2007 : Fixed clone() method (DG);
049 * 04-May-2007 : Fixed lookup for series paint and stroke (DG);
050 * 18-May-2007 : Set dataset for LegendItem (DG);
051 *
052 */
053
054 package org.jfree.chart.renderer;
055
056 import java.awt.AlphaComposite;
057 import java.awt.Composite;
058 import java.awt.Graphics2D;
059 import java.awt.Paint;
060 import java.awt.Point;
061 import java.awt.Polygon;
062 import java.awt.Shape;
063 import java.awt.Stroke;
064 import java.awt.geom.Ellipse2D;
065 import java.awt.geom.Rectangle2D;
066 import java.util.Iterator;
067 import java.util.List;
068
069 import org.jfree.chart.LegendItem;
070 import org.jfree.chart.axis.NumberTick;
071 import org.jfree.chart.axis.ValueAxis;
072 import org.jfree.chart.plot.DrawingSupplier;
073 import org.jfree.chart.plot.PlotRenderingInfo;
074 import org.jfree.chart.plot.PolarPlot;
075 import org.jfree.data.xy.XYDataset;
076 import org.jfree.text.TextUtilities;
077 import org.jfree.ui.TextAnchor;
078 import org.jfree.util.BooleanList;
079 import org.jfree.util.BooleanUtilities;
080
081 /**
082 * A renderer that can be used with the {@link PolarPlot} class.
083 */
084 public class DefaultPolarItemRenderer extends AbstractRenderer
085 implements PolarItemRenderer {
086
087 /** The plot that the renderer is assigned to. */
088 private PolarPlot plot;
089
090 /** Flags that control whether the renderer fills each series or not. */
091 private BooleanList seriesFilled;
092
093 /**
094 * Creates a new instance of DefaultPolarItemRenderer
095 */
096 public DefaultPolarItemRenderer() {
097 this.seriesFilled = new BooleanList();
098 }
099
100 /**
101 * Set the plot associated with this renderer.
102 *
103 * @param plot the plot.
104 *
105 * @see #getPlot()
106 */
107 public void setPlot(PolarPlot plot) {
108 this.plot = plot;
109 }
110
111 /**
112 * Return the plot associated with this renderer.
113 *
114 * @return The plot.
115 *
116 * @see #setPlot(PolarPlot)
117 */
118 public PolarPlot getPlot() {
119 return this.plot;
120 }
121
122 /**
123 * Returns the drawing supplier from the plot.
124 *
125 * @return The drawing supplier.
126 */
127 public DrawingSupplier getDrawingSupplier() {
128 DrawingSupplier result = null;
129 PolarPlot p = getPlot();
130 if (p != null) {
131 result = p.getDrawingSupplier();
132 }
133 return result;
134 }
135
136 /**
137 * Returns <code>true</code> if the renderer should fill the specified
138 * series, and <code>false</code> otherwise.
139 *
140 * @param series the series index (zero-based).
141 *
142 * @return A boolean.
143 */
144 public boolean isSeriesFilled(int series) {
145 boolean result = false;
146 Boolean b = this.seriesFilled.getBoolean(series);
147 if (b != null) {
148 result = b.booleanValue();
149 }
150 return result;
151 }
152
153 /**
154 * Sets a flag that controls whether or not a series is filled.
155 *
156 * @param series the series index.
157 * @param filled the flag.
158 */
159 public void setSeriesFilled(int series, boolean filled) {
160 this.seriesFilled.setBoolean(series, BooleanUtilities.valueOf(filled));
161 }
162
163 /**
164 * Plots the data for a given series.
165 *
166 * @param g2 the drawing surface.
167 * @param dataArea the data area.
168 * @param info collects plot rendering info.
169 * @param plot the plot.
170 * @param dataset the dataset.
171 * @param seriesIndex the series index.
172 */
173 public void drawSeries(Graphics2D g2,
174 Rectangle2D dataArea,
175 PlotRenderingInfo info,
176 PolarPlot plot,
177 XYDataset dataset,
178 int seriesIndex) {
179
180 Polygon poly = new Polygon();
181 int numPoints = dataset.getItemCount(seriesIndex);
182 for (int i = 0; i < numPoints; i++) {
183 double theta = dataset.getXValue(seriesIndex, i);
184 double radius = dataset.getYValue(seriesIndex, i);
185 Point p = plot.translateValueThetaRadiusToJava2D(theta, radius,
186 dataArea);
187 poly.addPoint(p.x, p.y);
188 }
189 g2.setPaint(lookupSeriesPaint(seriesIndex));
190 g2.setStroke(lookupSeriesStroke(seriesIndex));
191 if (isSeriesFilled(seriesIndex)) {
192 Composite savedComposite = g2.getComposite();
193 g2.setComposite(AlphaComposite.getInstance(
194 AlphaComposite.SRC_OVER, 0.5f));
195 g2.fill(poly);
196 g2.setComposite(savedComposite);
197 }
198 else {
199 g2.draw(poly);
200 }
201 }
202
203 /**
204 * Draw the angular gridlines - the spokes.
205 *
206 * @param g2 the drawing surface.
207 * @param plot the plot.
208 * @param ticks the ticks.
209 * @param dataArea the data area.
210 */
211 public void drawAngularGridLines(Graphics2D g2,
212 PolarPlot plot,
213 List ticks,
214 Rectangle2D dataArea) {
215
216 g2.setFont(plot.getAngleLabelFont());
217 g2.setStroke(plot.getAngleGridlineStroke());
218 g2.setPaint(plot.getAngleGridlinePaint());
219
220 double axisMin = plot.getAxis().getLowerBound();
221 double maxRadius = plot.getMaxRadius();
222
223 Point center = plot.translateValueThetaRadiusToJava2D(axisMin, axisMin,
224 dataArea);
225 Iterator iterator = ticks.iterator();
226 while (iterator.hasNext()) {
227 NumberTick tick = (NumberTick) iterator.next();
228 Point p = plot.translateValueThetaRadiusToJava2D(
229 tick.getNumber().doubleValue(), maxRadius, dataArea);
230 g2.setPaint(plot.getAngleGridlinePaint());
231 g2.drawLine(center.x, center.y, p.x, p.y);
232 if (plot.isAngleLabelsVisible()) {
233 int x = p.x;
234 int y = p.y;
235 g2.setPaint(plot.getAngleLabelPaint());
236 TextUtilities.drawAlignedString(tick.getText(), g2, x, y,
237 TextAnchor.CENTER);
238 }
239 }
240 }
241
242 /**
243 * Draw the radial gridlines - the rings.
244 *
245 * @param g2 the drawing surface.
246 * @param plot the plot.
247 * @param radialAxis the radial axis.
248 * @param ticks the ticks.
249 * @param dataArea the data area.
250 */
251 public void drawRadialGridLines(Graphics2D g2,
252 PolarPlot plot,
253 ValueAxis radialAxis,
254 List ticks,
255 Rectangle2D dataArea) {
256
257 g2.setFont(radialAxis.getTickLabelFont());
258 g2.setPaint(plot.getRadiusGridlinePaint());
259 g2.setStroke(plot.getRadiusGridlineStroke());
260
261 double axisMin = radialAxis.getLowerBound();
262 Point center = plot.translateValueThetaRadiusToJava2D(axisMin, axisMin,
263 dataArea);
264
265 Iterator iterator = ticks.iterator();
266 while (iterator.hasNext()) {
267 NumberTick tick = (NumberTick) iterator.next();
268 Point p = plot.translateValueThetaRadiusToJava2D(90.0,
269 tick.getNumber().doubleValue(), dataArea);
270 int r = p.x - center.x;
271 int upperLeftX = center.x - r;
272 int upperLeftY = center.y - r;
273 int d = 2 * r;
274 Ellipse2D ring = new Ellipse2D.Double(upperLeftX, upperLeftY, d, d);
275 g2.setPaint(plot.getRadiusGridlinePaint());
276 g2.draw(ring);
277 }
278 }
279
280 /**
281 * Return the legend for the given series.
282 *
283 * @param series the series index.
284 *
285 * @return The legend item.
286 */
287 public LegendItem getLegendItem(int series) {
288 LegendItem result = null;
289 PolarPlot polarPlot = getPlot();
290 if (polarPlot != null) {
291 XYDataset dataset = polarPlot.getDataset();
292 if (dataset != null) {
293 String label = dataset.getSeriesKey(series).toString();
294 String description = label;
295 Shape shape = lookupSeriesShape(series);
296 Paint paint = lookupSeriesPaint(series);
297 Paint outlinePaint = lookupSeriesOutlinePaint(series);
298 Stroke outlineStroke = lookupSeriesOutlineStroke(series);
299 result = new LegendItem(label, description, null, null,
300 shape, paint, outlineStroke, outlinePaint);
301 result.setDataset(dataset);
302 }
303 }
304 return result;
305 }
306
307 /**
308 * Tests this renderer for equality with an arbitrary object.
309 *
310 * @param obj the object (<code>null</code> not permitted).
311 *
312 * @return <code>true</code> if this renderer is equal to <code>obj</code>,
313 * and <code>false</code> otherwise.
314 */
315 public boolean equals(Object obj) {
316 if (obj == null) {
317 return false;
318 }
319 if (!(obj instanceof DefaultPolarItemRenderer)) {
320 return false;
321 }
322 DefaultPolarItemRenderer that = (DefaultPolarItemRenderer) obj;
323 if (!this.seriesFilled.equals(that.seriesFilled)) {
324 return false;
325 }
326 return super.equals(obj);
327 }
328
329 /**
330 * Returns a clone of the renderer.
331 *
332 * @return A clone.
333 *
334 * @throws CloneNotSupportedException if the renderer cannot be cloned.
335 */
336 public Object clone() throws CloneNotSupportedException {
337 DefaultPolarItemRenderer clone
338 = (DefaultPolarItemRenderer) super.clone();
339 clone.seriesFilled = (BooleanList) this.seriesFilled.clone();
340 return clone;
341 }
342
343 }