/* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * ----------------------------- * DefaultPolarItemRenderer.java * ----------------------------- * (C) Copyright 2004-2008, by Solution Engineering, Inc. and * Contributors. * * Original Author: Daniel Bridenbecker, Solution Engineering, Inc.; * Contributor(s): David Gilbert (for Object Refinery Limited); * * Changes * ------- * 19-Jan-2004 : Version 1, contributed by DB with minor changes by DG (DG); * 15-Jul-2004 : Switched getX() with getXValue() and getY() with * getYValue() (DG); * 04-Oct-2004 : Renamed BooleanUtils --> BooleanUtilities (DG); * 20-Apr-2005 : Update for change to LegendItem class (DG); * ------------- JFREECHART 1.0.x --------------------------------------------- * 04-Aug-2006 : Implemented equals() and clone() (DG); * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG); * 14-Mar-2007 : Fixed clone() method (DG); * 04-May-2007 : Fixed lookup for series paint and stroke (DG); * 18-May-2007 : Set dataset for LegendItem (DG); * */ package org.jfree.chart.renderer; import java.awt.AlphaComposite; import java.awt.Composite; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Point; import java.awt.Polygon; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.Ellipse2D; import java.awt.geom.Rectangle2D; import java.util.Iterator; import java.util.List; import org.jfree.chart.LegendItem; import org.jfree.chart.axis.NumberTick; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.DrawingSupplier; import org.jfree.chart.plot.PlotRenderingInfo; import org.jfree.chart.plot.PolarPlot; import org.jfree.data.xy.XYDataset; import org.jfree.text.TextUtilities; import org.jfree.ui.TextAnchor; import org.jfree.util.BooleanList; import org.jfree.util.BooleanUtilities; /** * A renderer that can be used with the {@link PolarPlot} class. */ public class DefaultPolarItemRenderer extends AbstractRenderer implements PolarItemRenderer { /** The plot that the renderer is assigned to. */ private PolarPlot plot; /** Flags that control whether the renderer fills each series or not. */ private BooleanList seriesFilled; /** * Creates a new instance of DefaultPolarItemRenderer */ public DefaultPolarItemRenderer() { this.seriesFilled = new BooleanList(); } /** * Set the plot associated with this renderer. * * @param plot the plot. * * @see #getPlot() */ public void setPlot(PolarPlot plot) { this.plot = plot; } /** * Return the plot associated with this renderer. * * @return The plot. * * @see #setPlot(PolarPlot) */ public PolarPlot getPlot() { return this.plot; } /** * Returns the drawing supplier from the plot. * * @return The drawing supplier. */ public DrawingSupplier getDrawingSupplier() { DrawingSupplier result = null; PolarPlot p = getPlot(); if (p != null) { result = p.getDrawingSupplier(); } return result; } /** * Returns <code>true</code> if the renderer should fill the specified * series, and <code>false</code> otherwise. * * @param series the series index (zero-based). * * @return A boolean. */ public boolean isSeriesFilled(int series) { boolean result = false; Boolean b = this.seriesFilled.getBoolean(series); if (b != null) { result = b.booleanValue(); } return result; } /** * Sets a flag that controls whether or not a series is filled. * * @param series the series index. * @param filled the flag. */ public void setSeriesFilled(int series, boolean filled) { this.seriesFilled.setBoolean(series, BooleanUtilities.valueOf(filled)); } /** * Plots the data for a given series. * * @param g2 the drawing surface. * @param dataArea the data area. * @param info collects plot rendering info. * @param plot the plot. * @param dataset the dataset. * @param seriesIndex the series index. */ public void drawSeries(Graphics2D g2, Rectangle2D dataArea, PlotRenderingInfo info, PolarPlot plot, XYDataset dataset, int seriesIndex) { Polygon poly = new Polygon(); int numPoints = dataset.getItemCount(seriesIndex); for (int i = 0; i < numPoints; i++) { double theta = dataset.getXValue(seriesIndex, i); double radius = dataset.getYValue(seriesIndex, i); Point p = plot.translateValueThetaRadiusToJava2D(theta, radius, dataArea); poly.addPoint(p.x, p.y); } g2.setPaint(lookupSeriesPaint(seriesIndex)); g2.setStroke(lookupSeriesStroke(seriesIndex)); if (isSeriesFilled(seriesIndex)) { Composite savedComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f)); g2.fill(poly); g2.setComposite(savedComposite); } else { g2.draw(poly); } } /** * Draw the angular gridlines - the spokes. * * @param g2 the drawing surface. * @param plot the plot. * @param ticks the ticks. * @param dataArea the data area. */ public void drawAngularGridLines(Graphics2D g2, PolarPlot plot, List ticks, Rectangle2D dataArea) { g2.setFont(plot.getAngleLabelFont()); g2.setStroke(plot.getAngleGridlineStroke()); g2.setPaint(plot.getAngleGridlinePaint()); double axisMin = plot.getAxis().getLowerBound(); double maxRadius = plot.getMaxRadius(); Point center = plot.translateValueThetaRadiusToJava2D(axisMin, axisMin, dataArea); Iterator iterator = ticks.iterator(); while (iterator.hasNext()) { NumberTick tick = (NumberTick) iterator.next(); Point p = plot.translateValueThetaRadiusToJava2D( tick.getNumber().doubleValue(), maxRadius, dataArea); g2.setPaint(plot.getAngleGridlinePaint()); g2.drawLine(center.x, center.y, p.x, p.y); if (plot.isAngleLabelsVisible()) { int x = p.x; int y = p.y; g2.setPaint(plot.getAngleLabelPaint()); TextUtilities.drawAlignedString(tick.getText(), g2, x, y, TextAnchor.CENTER); } } } /** * Draw the radial gridlines - the rings. * * @param g2 the drawing surface. * @param plot the plot. * @param radialAxis the radial axis. * @param ticks the ticks. * @param dataArea the data area. */ public void drawRadialGridLines(Graphics2D g2, PolarPlot plot, ValueAxis radialAxis, List ticks, Rectangle2D dataArea) { g2.setFont(radialAxis.getTickLabelFont()); g2.setPaint(plot.getRadiusGridlinePaint()); g2.setStroke(plot.getRadiusGridlineStroke()); double axisMin = radialAxis.getLowerBound(); Point center = plot.translateValueThetaRadiusToJava2D(axisMin, axisMin, dataArea); Iterator iterator = ticks.iterator(); while (iterator.hasNext()) { NumberTick tick = (NumberTick) iterator.next(); Point p = plot.translateValueThetaRadiusToJava2D(90.0, tick.getNumber().doubleValue(), dataArea); int r = p.x - center.x; int upperLeftX = center.x - r; int upperLeftY = center.y - r; int d = 2 * r; Ellipse2D ring = new Ellipse2D.Double(upperLeftX, upperLeftY, d, d); g2.setPaint(plot.getRadiusGridlinePaint()); g2.draw(ring); } } /** * Return the legend for the given series. * * @param series the series index. * * @return The legend item. */ public LegendItem getLegendItem(int series) { LegendItem result = null; PolarPlot polarPlot = getPlot(); if (polarPlot != null) { XYDataset dataset = polarPlot.getDataset(); if (dataset != null) { String label = dataset.getSeriesKey(series).toString(); String description = label; Shape shape = lookupSeriesShape(series); Paint paint = lookupSeriesPaint(series); Paint outlinePaint = lookupSeriesOutlinePaint(series); Stroke outlineStroke = lookupSeriesOutlineStroke(series); result = new LegendItem(label, description, null, null, shape, paint, outlineStroke, outlinePaint); result.setDataset(dataset); } } return result; } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object (<code>null</code> not permitted). * * @return <code>true</code> if this renderer is equal to <code>obj</code>, * and <code>false</code> otherwise. */ public boolean equals(Object obj) { if (obj == null) { return false; } if (!(obj instanceof DefaultPolarItemRenderer)) { return false; } DefaultPolarItemRenderer that = (DefaultPolarItemRenderer) obj; if (!this.seriesFilled.equals(that.seriesFilled)) { return false; } return super.equals(obj); } /** * Returns a clone of the renderer. * * @return A clone. * * @throws CloneNotSupportedException if the renderer cannot be cloned. */ public Object clone() throws CloneNotSupportedException { DefaultPolarItemRenderer clone = (DefaultPolarItemRenderer) super.clone(); clone.seriesFilled = (BooleanList) this.seriesFilled.clone(); return clone; } }