Source for org.jfree.chart.renderer.DefaultPolarItemRenderer

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2007, 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:  * DefaultPolarItemRenderer.java
  29:  * -----------------------------
  30:  * (C) Copyright 2004, 2006, 2007, by Solution Engineering, Inc. and 
  31:  *     Contributors.
  32:  *
  33:  * Original Author:  Daniel Bridenbecker, Solution Engineering, Inc.;
  34:  * Contributor(s):   David Gilbert (for Object Refinery Limited);
  35:  *
  36:  * $Id: DefaultPolarItemRenderer.java,v 1.7.2.7 2007/03/15 12:05:07 mungady Exp $
  37:  *
  38:  * Changes
  39:  * -------
  40:  * 19-Jan-2004 : Version 1, contributed by DB with minor changes by DG (DG);
  41:  * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 
  42:  *               getYValue() (DG);
  43:  * 04-Oct-2004 : Renamed BooleanUtils --> BooleanUtilities (DG);
  44:  * 20-Apr-2005 : Update for change to LegendItem class (DG);
  45:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  46:  * 04-Aug-2006 : Implemented equals() and clone() (DG);
  47:  * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG);
  48:  * 14-Mar-2007 : Fixed clone() method (DG);
  49:  *
  50:  */
  51: 
  52: package org.jfree.chart.renderer;
  53: 
  54: import java.awt.AlphaComposite;
  55: import java.awt.Composite;
  56: import java.awt.Graphics2D;
  57: import java.awt.Paint;
  58: import java.awt.Point;
  59: import java.awt.Polygon;
  60: import java.awt.Shape;
  61: import java.awt.Stroke;
  62: import java.awt.geom.Ellipse2D;
  63: import java.awt.geom.Rectangle2D;
  64: import java.util.Iterator;
  65: import java.util.List;
  66: 
  67: import org.jfree.chart.LegendItem;
  68: import org.jfree.chart.axis.NumberTick;
  69: import org.jfree.chart.axis.ValueAxis;
  70: import org.jfree.chart.plot.DrawingSupplier;
  71: import org.jfree.chart.plot.PlotRenderingInfo;
  72: import org.jfree.chart.plot.PolarPlot;
  73: import org.jfree.data.xy.XYDataset;
  74: import org.jfree.text.TextUtilities;
  75: import org.jfree.ui.TextAnchor;
  76: import org.jfree.util.BooleanList;
  77: import org.jfree.util.BooleanUtilities;
  78: 
  79: /**
  80:  * A renderer that can be used with the {@link PolarPlot} class.
  81:  */
  82: public class DefaultPolarItemRenderer extends AbstractRenderer  
  83:                                       implements PolarItemRenderer {
  84:        
  85:     /** The plot that the renderer is assigned to. */
  86:     private PolarPlot plot;
  87: 
  88:     /** Flags that control whether the renderer fills each series or not. */
  89:     private BooleanList seriesFilled;
  90:    
  91:     /**
  92:      * Creates a new instance of DefaultPolarItemRenderer
  93:      */
  94:     public DefaultPolarItemRenderer() {
  95:         this.seriesFilled = new BooleanList();
  96:     }
  97:    
  98:     /**
  99:      * Set the plot associated with this renderer.
 100:      * 
 101:      * @param plot  the plot.
 102:      * 
 103:      * @see #getPlot()
 104:      */
 105:     public void setPlot(PolarPlot plot) {
 106:         this.plot = plot;
 107:     }
 108: 
 109:     /**
 110:      * Return the plot associated with this renderer.
 111:      * 
 112:      * @return The plot.
 113:      * 
 114:      * @see #setPlot(PolarPlot)
 115:      */
 116:     public PolarPlot getPlot() {
 117:         return this.plot;
 118:     }
 119: 
 120:     /** 
 121:      * Returns the drawing supplier from the plot.
 122:      *
 123:      * @return The drawing supplier.
 124:      */
 125:     public DrawingSupplier getDrawingSupplier() {
 126:         DrawingSupplier result = null;
 127:         PolarPlot p = getPlot();
 128:         if (p != null) {
 129:             result = p.getDrawingSupplier();
 130:         }
 131:         return result;
 132:     }
 133: 
 134:     /**
 135:      * Returns <code>true</code> if the renderer should fill the specified 
 136:      * series, and <code>false</code> otherwise.
 137:      * 
 138:      * @param series  the series index (zero-based).
 139:      * 
 140:      * @return A boolean.
 141:      */
 142:     public boolean isSeriesFilled(int series) {
 143:         boolean result = false;
 144:         Boolean b = this.seriesFilled.getBoolean(series);
 145:         if (b != null) {
 146:             result = b.booleanValue();
 147:         }
 148:         return result;
 149:     }
 150: 
 151:     /**
 152:      * Sets a flag that controls whether or not a series is filled.
 153:      * 
 154:      * @param series  the series index.
 155:      * @param filled  the flag.
 156:      */
 157:     public void setSeriesFilled(int series, boolean filled) {
 158:         this.seriesFilled.setBoolean(series, BooleanUtilities.valueOf(filled));
 159:     }
 160:     
 161:     /**
 162:      * Plots the data for a given series.
 163:      * 
 164:      * @param g2  the drawing surface.
 165:      * @param dataArea  the data area.
 166:      * @param info  collects plot rendering info.
 167:      * @param plot  the plot.
 168:      * @param dataset  the dataset.
 169:      * @param seriesIndex  the series index.
 170:      */
 171:     public void drawSeries(Graphics2D g2, 
 172:                            Rectangle2D dataArea, 
 173:                            PlotRenderingInfo info,
 174:                            PolarPlot plot,
 175:                            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, radius, 
 184:                     dataArea);
 185:             poly.addPoint(p.x, p.y);
 186:         }
 187:         g2.setPaint(getSeriesPaint(seriesIndex));
 188:         g2.setStroke(getSeriesStroke(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:         }
 196:         else {
 197:             g2.draw(poly);
 198:         }
 199:     }
 200:     
 201:     /**
 202:      * Draw the angular gridlines - the spokes.
 203:      * 
 204:      * @param g2  the drawing surface.
 205:      * @param plot  the plot.
 206:      * @param ticks  the ticks.
 207:      * @param dataArea  the data area.
 208:      */
 209:     public void drawAngularGridLines(Graphics2D g2, 
 210:                                      PolarPlot plot, 
 211:                                      List ticks,
 212:                                      Rectangle2D dataArea) {
 213:         
 214:         g2.setFont(plot.getAngleLabelFont());
 215:         g2.setStroke(plot.getAngleGridlineStroke());
 216:         g2.setPaint(plot.getAngleGridlinePaint());
 217:       
 218:         double axisMin = plot.getAxis().getLowerBound();
 219:         double maxRadius = plot.getMaxRadius();
 220: 
 221:         Point center = plot.translateValueThetaRadiusToJava2D(axisMin, axisMin,
 222:                 dataArea);
 223:         Iterator iterator = ticks.iterator();
 224:         while (iterator.hasNext()) {
 225:             NumberTick tick = (NumberTick) iterator.next();
 226:             Point p = plot.translateValueThetaRadiusToJava2D(
 227:                     tick.getNumber().doubleValue(), maxRadius, dataArea);
 228:             g2.setPaint(plot.getAngleGridlinePaint());
 229:             g2.drawLine(center.x, center.y, p.x, p.y);
 230:             if (plot.isAngleLabelsVisible()) {
 231:                 int x = p.x;
 232:                 int y = p.y;
 233:                 g2.setPaint(plot.getAngleLabelPaint());
 234:                 TextUtilities.drawAlignedString(tick.getText(), g2, x, y, 
 235:                         TextAnchor.CENTER);
 236:             }
 237:         }
 238:      }
 239: 
 240:     /**
 241:      * Draw the radial gridlines - the rings.
 242:      * 
 243:      * @param g2  the drawing surface.
 244:      * @param plot  the plot.
 245:      * @param radialAxis  the radial axis.
 246:      * @param ticks  the ticks.
 247:      * @param dataArea  the data area.
 248:      */
 249:     public void drawRadialGridLines(Graphics2D g2, 
 250:                                     PolarPlot plot,
 251:                                     ValueAxis radialAxis,
 252:                                     List ticks,
 253:                                     Rectangle2D dataArea) {
 254:         
 255:         g2.setFont(radialAxis.getTickLabelFont());
 256:         g2.setPaint(plot.getRadiusGridlinePaint());
 257:         g2.setStroke(plot.getRadiusGridlineStroke());
 258: 
 259:         double axisMin = radialAxis.getLowerBound();
 260:         Point center = plot.translateValueThetaRadiusToJava2D(axisMin, axisMin,
 261:                 dataArea);
 262:         
 263:         Iterator iterator = ticks.iterator();
 264:         while (iterator.hasNext()) {
 265:             NumberTick tick = (NumberTick) iterator.next();
 266:             Point p = plot.translateValueThetaRadiusToJava2D(90.0, 
 267:                     tick.getNumber().doubleValue(), dataArea);
 268:             int r = p.x - center.x;
 269:             int upperLeftX = center.x - r;
 270:             int upperLeftY = center.y - r;
 271:             int d = 2 * r;
 272:             Ellipse2D ring = new Ellipse2D.Double(upperLeftX, upperLeftY, d, d);
 273:             g2.setPaint(plot.getRadiusGridlinePaint());
 274:             g2.draw(ring);
 275:         }
 276:     }
 277: 
 278:     /**
 279:      * Return the legend for the given series.
 280:      * 
 281:      * @param series  the series index.
 282:      * 
 283:      * @return The legend item.
 284:      */
 285:     public LegendItem getLegendItem(int series) {
 286:         LegendItem result = null;
 287:         PolarPlot polarPlot = getPlot();
 288:         if (polarPlot != null) {
 289:             XYDataset dataset;
 290:             dataset = polarPlot.getDataset();
 291:             if (dataset != null) {
 292:                 String label = dataset.getSeriesKey(series).toString();
 293:                 String description = label;
 294:                 Shape shape = getSeriesShape(series);
 295:                 Paint paint = getSeriesPaint(series);
 296:                 Paint outlinePaint = getSeriesOutlinePaint(series);
 297:                 Stroke outlineStroke = getSeriesOutlineStroke(series);
 298:                 result = new LegendItem(label, description, null, null, 
 299:                         shape, paint, outlineStroke, outlinePaint);
 300:             }
 301:         }
 302:         return result;
 303:     }
 304: 
 305:     /**
 306:      * Tests this renderer for equality with an arbitrary object.
 307:      * 
 308:      * @param obj  the object (<code>null</code> not permitted).
 309:      * 
 310:      * @return <code>true</code> if this renderer is equal to <code>obj</code>,
 311:      *     and <code>false</code> otherwise.
 312:      */
 313:     public boolean equals(Object obj) {
 314:         if (obj == null) {
 315:             return false;
 316:         }
 317:         if (!(obj instanceof DefaultPolarItemRenderer)) {
 318:             return false;
 319:         }
 320:         DefaultPolarItemRenderer that = (DefaultPolarItemRenderer) obj;
 321:         if (!this.seriesFilled.equals(that.seriesFilled)) {
 322:             return false;
 323:         }
 324:         return super.equals(obj);
 325:     }
 326:     
 327:     /**
 328:      * Returns a clone of the renderer.
 329:      *
 330:      * @return A clone.
 331:      *
 332:      * @throws CloneNotSupportedException if the renderer cannot be cloned.
 333:      */
 334:     public Object clone() throws CloneNotSupportedException {
 335:         DefaultPolarItemRenderer clone 
 336:                 = (DefaultPolarItemRenderer) super.clone();
 337:         clone.seriesFilled = (BooleanList) this.seriesFilled.clone();
 338:         return clone;
 339:     }
 340: 
 341: }