001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2005, 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, by Solution Engineering, Inc. and Contributors. 031 * 032 * Original Author: Daniel Bridenbecker, Solution Engineering, Inc.; 033 * Contributor(s): David Gilbert (for Object Refinery Limited); 034 * 035 * $Id: DefaultPolarItemRenderer.java,v 1.7.2.3 2005/11/28 12:06:35 mungady Exp $ 036 * 037 * Changes 038 * ------- 039 * 19-Jan-2004 : Version 1, contributed by DB with minor changes by DG (DG); 040 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 041 * getYValue() (DG); 042 * 04-Oct-2004 : Renamed BooleanUtils --> BooleanUtilities (DG); 043 * 20-Apr-2005 : Update for change to LegendItem class (DG); 044 * 045 */ 046 047 package org.jfree.chart.renderer; 048 049 import java.awt.AlphaComposite; 050 import java.awt.Composite; 051 import java.awt.Graphics2D; 052 import java.awt.Paint; 053 import java.awt.Point; 054 import java.awt.Polygon; 055 import java.awt.Shape; 056 import java.awt.Stroke; 057 import java.awt.geom.Ellipse2D; 058 import java.awt.geom.Rectangle2D; 059 import java.util.Iterator; 060 import java.util.List; 061 062 import org.jfree.chart.LegendItem; 063 import org.jfree.chart.axis.NumberTick; 064 import org.jfree.chart.axis.ValueAxis; 065 import org.jfree.chart.plot.DrawingSupplier; 066 import org.jfree.chart.plot.PlotRenderingInfo; 067 import org.jfree.chart.plot.PolarPlot; 068 import org.jfree.data.xy.XYDataset; 069 import org.jfree.text.TextUtilities; 070 import org.jfree.ui.TextAnchor; 071 import org.jfree.util.BooleanList; 072 import org.jfree.util.BooleanUtilities; 073 074 /** 075 * A renderer that can be used with the {@link PolarPlot} class. 076 * 077 * @author Daniel Bridenbecker, Solution Engineering, Inc. 078 */ 079 public class DefaultPolarItemRenderer extends AbstractRenderer 080 implements PolarItemRenderer { 081 082 /** The plot that the renderer is assigned to. */ 083 private PolarPlot plot; 084 085 /** Flags that control whether the renderer fills each series or not. */ 086 private BooleanList seriesFilled; 087 088 /** 089 * Creates a new instance of DefaultPolarItemRenderer 090 */ 091 public DefaultPolarItemRenderer() { 092 this.seriesFilled = new BooleanList(); 093 } 094 095 // -------------------------------- 096 // --- AbstractRenderer Methods --- 097 // -------------------------------- 098 099 /** 100 * Returns the drawing supplier from the plot. 101 * 102 * @return The drawing supplier. 103 */ 104 public DrawingSupplier getDrawingSupplier() { 105 DrawingSupplier result = null; 106 PolarPlot p = getPlot(); 107 if (p != null) { 108 result = p.getDrawingSupplier(); 109 } 110 return result; 111 } 112 113 // ---------------------- 114 // --- Public Methods --- 115 // ---------------------- 116 /** 117 * Set the plot associated with this renderer. 118 * 119 * @param plot the plot. 120 */ 121 public void setPlot(PolarPlot plot) { 122 this.plot = plot; 123 } 124 125 /** 126 * Return the plot associated with this renderer. 127 * 128 * @return The plot. 129 */ 130 public PolarPlot getPlot() { 131 return this.plot; 132 } 133 134 /** 135 * Plots the data for a given series. 136 * 137 * @param g2 the drawing surface. 138 * @param dataArea the data area. 139 * @param info collects plot rendering info. 140 * @param plot the plot. 141 * @param dataset the dataset. 142 * @param seriesIndex the series index. 143 */ 144 public void drawSeries(Graphics2D g2, 145 Rectangle2D dataArea, 146 PlotRenderingInfo info, 147 PolarPlot plot, 148 XYDataset dataset, 149 int seriesIndex) { 150 151 Polygon poly = new Polygon(); 152 int numPoints = dataset.getItemCount(seriesIndex); 153 for (int i = 0; i < numPoints; i++) { 154 double theta = dataset.getXValue(seriesIndex, i); 155 double radius = dataset.getYValue(seriesIndex, i); 156 Point p = plot.translateValueThetaRadiusToJava2D( 157 theta, radius, dataArea 158 ); 159 poly.addPoint(p.x, p.y); 160 } 161 g2.setPaint(getSeriesPaint(seriesIndex)); 162 g2.setStroke(getSeriesStroke(seriesIndex)); 163 if (isSeriesFilled(seriesIndex)) { 164 Composite savedComposite = g2.getComposite(); 165 g2.setComposite( 166 AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f) 167 ); 168 g2.fill(poly); 169 g2.setComposite(savedComposite); 170 } 171 else { 172 g2.draw(poly); 173 } 174 } 175 176 /** 177 * Returns <code>true</code> if the renderer should fill the specified 178 * series, and <code>false</code> otherwise. 179 * 180 * @param series the series index (zero-based). 181 * 182 * @return A boolean. 183 */ 184 public boolean isSeriesFilled(int series) { 185 boolean result = false; 186 Boolean b = this.seriesFilled.getBoolean(series); 187 if (b != null) { 188 result = b.booleanValue(); 189 } 190 return result; 191 } 192 193 /** 194 * Sets a flag that controls whether or not a series is filled. 195 * 196 * @param series the series index. 197 * @param filled the flag. 198 */ 199 public void setSeriesFilled(int series, boolean filled) { 200 this.seriesFilled.setBoolean(series, BooleanUtilities.valueOf(filled)); 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( 224 axisMin, axisMin, dataArea 225 ); 226 Iterator iterator = ticks.iterator(); 227 while (iterator.hasNext()) { 228 NumberTick tick = (NumberTick) iterator.next(); 229 Point p = plot.translateValueThetaRadiusToJava2D( 230 tick.getNumber().doubleValue(), maxRadius, dataArea 231 ); 232 g2.setPaint(plot.getAngleGridlinePaint()); 233 g2.drawLine(center.x, center.y, p.x, p.y); 234 if (plot.isAngleLabelsVisible()) { 235 int x = p.x; 236 int y = p.y; 237 g2.setPaint(plot.getAngleLabelPaint()); 238 TextUtilities.drawAlignedString( 239 tick.getText(), g2, x, y, TextAnchor.CENTER 240 ); 241 } 242 } 243 } 244 245 /** 246 * Draw the radial gridlines - the rings. 247 * 248 * @param g2 the drawing surface. 249 * @param plot the plot. 250 * @param radialAxis the radial axis. 251 * @param ticks the ticks. 252 * @param dataArea the data area. 253 */ 254 public void drawRadialGridLines(Graphics2D g2, 255 PolarPlot plot, 256 ValueAxis radialAxis, 257 List ticks, 258 Rectangle2D dataArea) { 259 260 g2.setFont(radialAxis.getTickLabelFont()); 261 g2.setPaint(plot.getRadiusGridlinePaint()); 262 g2.setStroke(plot.getRadiusGridlineStroke()); 263 264 double axisMin = radialAxis.getLowerBound(); 265 Point center = plot.translateValueThetaRadiusToJava2D( 266 axisMin, axisMin, dataArea 267 ); 268 269 Iterator iterator = ticks.iterator(); 270 while (iterator.hasNext()) { 271 NumberTick tick = (NumberTick) iterator.next(); 272 Point p = plot.translateValueThetaRadiusToJava2D( 273 90.0, tick.getNumber().doubleValue(), dataArea 274 ); 275 int r = p.x - center.x; 276 int upperLeftX = center.x - r; 277 int upperLeftY = center.y - r; 278 int d = 2 * r; 279 Ellipse2D ring = new Ellipse2D.Double(upperLeftX, upperLeftY, d, d); 280 g2.setPaint(plot.getRadiusGridlinePaint()); 281 g2.draw(ring); 282 } 283 } 284 285 /** 286 * Return the legend for the given series. 287 * 288 * @param series the series index. 289 * 290 * @return The legend item. 291 */ 292 public LegendItem getLegendItem(int series) { 293 LegendItem result = null; 294 PolarPlot polarPlot = getPlot(); 295 if (polarPlot != null) { 296 XYDataset dataset; 297 dataset = polarPlot.getDataset(); 298 if (dataset != null) { 299 String label = dataset.getSeriesKey(series).toString(); 300 String description = label; 301 Shape shape = getSeriesShape(series); 302 Paint paint = getSeriesPaint(series); 303 Paint outlinePaint = getSeriesOutlinePaint(series); 304 Stroke outlineStroke = getSeriesOutlineStroke(series); 305 result = new LegendItem(label, description, null, null, 306 shape, paint, outlineStroke, outlinePaint); 307 } 308 } 309 return result; 310 } 311 312 }