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
161: .valueOf(filled));
162: }
163:
164: /**
165: * Plots the data for a given series.
166: *
167: * @param g2 the drawing surface.
168: * @param dataArea the data area.
169: * @param info collects plot rendering info.
170: * @param plot the plot.
171: * @param dataset the dataset.
172: * @param seriesIndex the series index.
173: */
174: public void drawSeries(Graphics2D g2, Rectangle2D dataArea,
175: PlotRenderingInfo info, PolarPlot plot, XYDataset dataset,
176: int seriesIndex) {
177:
178: Polygon poly = new Polygon();
179: int numPoints = dataset.getItemCount(seriesIndex);
180: for (int i = 0; i < numPoints; i++) {
181: double theta = dataset.getXValue(seriesIndex, i);
182: double radius = dataset.getYValue(seriesIndex, i);
183: Point p = plot.translateValueThetaRadiusToJava2D(theta,
184: radius, dataArea);
185: poly.addPoint(p.x, p.y);
186: }
187: g2.setPaint(lookupSeriesPaint(seriesIndex));
188: g2.setStroke(lookupSeriesStroke(seriesIndex));
189: if (isSeriesFilled(seriesIndex)) {
190: Composite savedComposite = g2.getComposite();
191: g2.setComposite(AlphaComposite.getInstance(
192: AlphaComposite.SRC_OVER, 0.5f));
193: g2.fill(poly);
194: g2.setComposite(savedComposite);
195: } else {
196: g2.draw(poly);
197: }
198: }
199:
200: /**
201: * Draw the angular gridlines - the spokes.
202: *
203: * @param g2 the drawing surface.
204: * @param plot the plot.
205: * @param ticks the ticks.
206: * @param dataArea the data area.
207: */
208: public void drawAngularGridLines(Graphics2D g2, PolarPlot plot,
209: List ticks, Rectangle2D dataArea) {
210:
211: g2.setFont(plot.getAngleLabelFont());
212: g2.setStroke(plot.getAngleGridlineStroke());
213: g2.setPaint(plot.getAngleGridlinePaint());
214:
215: double axisMin = plot.getAxis().getLowerBound();
216: double maxRadius = plot.getMaxRadius();
217:
218: Point center = plot.translateValueThetaRadiusToJava2D(axisMin,
219: axisMin, dataArea);
220: Iterator iterator = ticks.iterator();
221: while (iterator.hasNext()) {
222: NumberTick tick = (NumberTick) iterator.next();
223: Point p = plot.translateValueThetaRadiusToJava2D(tick
224: .getNumber().doubleValue(), maxRadius, dataArea);
225: g2.setPaint(plot.getAngleGridlinePaint());
226: g2.drawLine(center.x, center.y, p.x, p.y);
227: if (plot.isAngleLabelsVisible()) {
228: int x = p.x;
229: int y = p.y;
230: g2.setPaint(plot.getAngleLabelPaint());
231: TextUtilities.drawAlignedString(tick.getText(), g2, x,
232: y, TextAnchor.CENTER);
233: }
234: }
235: }
236:
237: /**
238: * Draw the radial gridlines - the rings.
239: *
240: * @param g2 the drawing surface.
241: * @param plot the plot.
242: * @param radialAxis the radial axis.
243: * @param ticks the ticks.
244: * @param dataArea the data area.
245: */
246: public void drawRadialGridLines(Graphics2D g2, PolarPlot plot,
247: ValueAxis radialAxis, List ticks, Rectangle2D dataArea) {
248:
249: g2.setFont(radialAxis.getTickLabelFont());
250: g2.setPaint(plot.getRadiusGridlinePaint());
251: g2.setStroke(plot.getRadiusGridlineStroke());
252:
253: double axisMin = radialAxis.getLowerBound();
254: Point center = plot.translateValueThetaRadiusToJava2D(axisMin,
255: axisMin, dataArea);
256:
257: Iterator iterator = ticks.iterator();
258: while (iterator.hasNext()) {
259: NumberTick tick = (NumberTick) iterator.next();
260: Point p = plot.translateValueThetaRadiusToJava2D(90.0, tick
261: .getNumber().doubleValue(), dataArea);
262: int r = p.x - center.x;
263: int upperLeftX = center.x - r;
264: int upperLeftY = center.y - r;
265: int d = 2 * r;
266: Ellipse2D ring = new Ellipse2D.Double(upperLeftX,
267: upperLeftY, d, d);
268: g2.setPaint(plot.getRadiusGridlinePaint());
269: g2.draw(ring);
270: }
271: }
272:
273: /**
274: * Return the legend for the given series.
275: *
276: * @param series the series index.
277: *
278: * @return The legend item.
279: */
280: public LegendItem getLegendItem(int series) {
281: LegendItem result = null;
282: PolarPlot polarPlot = getPlot();
283: if (polarPlot != null) {
284: XYDataset dataset = polarPlot.getDataset();
285: if (dataset != null) {
286: String label = dataset.getSeriesKey(series).toString();
287: String description = label;
288: Shape shape = lookupSeriesShape(series);
289: Paint paint = lookupSeriesPaint(series);
290: Paint outlinePaint = lookupSeriesOutlinePaint(series);
291: Stroke outlineStroke = lookupSeriesOutlineStroke(series);
292: result = new LegendItem(label, description, null, null,
293: shape, paint, outlineStroke, outlinePaint);
294: result.setDataset(dataset);
295: }
296: }
297: return result;
298: }
299:
300: /**
301: * Tests this renderer for equality with an arbitrary object.
302: *
303: * @param obj the object (<code>null</code> not permitted).
304: *
305: * @return <code>true</code> if this renderer is equal to <code>obj</code>,
306: * and <code>false</code> otherwise.
307: */
308: public boolean equals(Object obj) {
309: if (obj == null) {
310: return false;
311: }
312: if (!(obj instanceof DefaultPolarItemRenderer)) {
313: return false;
314: }
315: DefaultPolarItemRenderer that = (DefaultPolarItemRenderer) obj;
316: if (!this .seriesFilled.equals(that.seriesFilled)) {
317: return false;
318: }
319: return super .equals(obj);
320: }
321:
322: /**
323: * Returns a clone of the renderer.
324: *
325: * @return A clone.
326: *
327: * @throws CloneNotSupportedException if the renderer cannot be cloned.
328: */
329: public Object clone() throws CloneNotSupportedException {
330: DefaultPolarItemRenderer clone = (DefaultPolarItemRenderer) super
331: .clone();
332: clone.seriesFilled = (BooleanList) this.seriesFilled.clone();
333: return clone;
334: }
335:
336: }
|