/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2011, 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.
*
* [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.]
*
* -----------------------------
* DefaultPolarItemRenderer.java
* -----------------------------
* (C) Copyright 2004-2011, by Solution Engineering, Inc. and
* Contributors.
*
* Original Author: Daniel Bridenbecker, Solution Engineering, Inc.;
* Contributor(s): David Gilbert (for Object Refinery Limited);
* Martin Hoeller (patch 2850344);
*
* 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);
* 03-Sep-2009 : Applied patch 2850344 by Martin Hoeller (DG);
* 27-Nov-2009 : Updated for modification to PolarItemRenderer interface (DG);
* 03-Oct-2011 : Fixed potential NPE in equals() (MH);
* 03-Oct-2011 : Added flag to connectFirstAndLastPoint (MH);
* 03-Oct-2011 : Added tooltip and URL generator support (MH);
* 03-Oct-2011 : Added some configuration options for the legend (MH);
* 03-Oct-2011 : Added support for PolarPlot's angleOffset and direction (MH);
* 16-Oct-2011 : Fixed serialization problems with fillComposite (MH);
*/
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.Shape;
import java.awt.Stroke;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
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.entity.EntityCollection;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.event.RendererChangeEvent;
import org.jfree.chart.labels.XYSeriesLabelGenerator;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.DrawingSupplier;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.renderer.xy.AbstractXYItemRenderer;
import org.jfree.chart.urls.XYURLGenerator;
import org.jfree.data.xy.XYDataset;
import org.jfree.io.SerialUtilities;
import org.jfree.text.TextUtilities;
import org.jfree.util.BooleanList;
import org.jfree.util.BooleanUtilities;
import org.jfree.util.ObjectList;
import org.jfree.util.ObjectUtilities;
import org.jfree.util.PublicCloneable;
import org.jfree.util.ShapeUtilities;
/**
* 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;
/**
* Flag that controls whether an outline is drawn for filled series or
* not.
*
* @since 1.0.14
*/
private boolean drawOutlineWhenFilled;
/**
* The composite to use when filling series.
*
* @since 1.0.14
*/
private transient Composite fillComposite;
/**
* A flag that controls whether the fill paint is used for filling
* shapes.
*
* @since 1.0.14
*/
private boolean useFillPaint;
/**
* The shape that is used to represent a line in the legend.
*
* @since 1.0.14
*/
private transient Shape legendLine;
/**
* Flag that controls whether item shapes are visible or not.
*
* @since 1.0.14
*/
private boolean shapesVisible;
/**
* Flag that controls if the first and last point of the dataset should be
* connected or not.
*
* @since 1.0.14
*/
private boolean connectFirstAndLastPoint;
/**
* A list of tool tip generators (one per series).
*
* @since 1.0.14
*/
private ObjectList toolTipGeneratorList;
/**
* The base tool tip generator.
*
* @since 1.0.14
*/
private XYToolTipGenerator baseToolTipGenerator;
/**
* The URL text generator.
*
* @since 1.0.14
*/
private XYURLGenerator urlGenerator;
/**
* The legend item tool tip generator.
*
* @since 1.0.14
*/
private XYSeriesLabelGenerator legendItemToolTipGenerator;
/**
* The legend item URL generator.
*
* @since 1.0.14
*/
private XYSeriesLabelGenerator legendItemURLGenerator;
/**
* Creates a new instance of DefaultPolarItemRenderer
*/
public DefaultPolarItemRenderer() {
this.seriesFilled = new BooleanList();
this.drawOutlineWhenFilled = true;
this.fillComposite = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, 0.3f);
this.useFillPaint = false; // use item paint for fills by default
this.legendLine = new Line2D.Double(-7.0, 0.0, 7.0, 0.0);
this.shapesVisible = true;
this.connectFirstAndLastPoint = true;
this.toolTipGeneratorList = new ObjectList();
this.urlGenerator = null;
this.legendItemToolTipGenerator = null;
this.legendItemURLGenerator = null;
}
/**
* 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 <code>true</code> if the renderer will draw an outline around
* a filled polygon, <code>false</code> otherwise.
*
* @return A boolean.
*
* @since 1.0.14
*/
public boolean getDrawOutlineWhenFilled() {
return this.drawOutlineWhenFilled;
}
/**
* Set the flag that controls whether the outline around a filled
* polygon will be drawn or not and sends a {@link RendererChangeEvent}
* to all registered listeners.
*
* @param drawOutlineWhenFilled the flag.
*
* @since 1.0.14
*/
public void setDrawOutlineWhenFilled(boolean drawOutlineWhenFilled) {
this.drawOutlineWhenFilled = drawOutlineWhenFilled;
fireChangeEvent();
}
/**
* Get the composite that is used for filling.
*
* @return The composite (never <code>null</code>).
*
* @since 1.0.14
*/
public Composite getFillComposite() {
return this.fillComposite;
}
/**
* Set the composite which will be used for filling polygons and sends a
* {@link RendererChangeEvent} to all registered listeners.
*
* @param composite the composite to use (<code>null</code> not
* permitted).
*
* @since 1.0.14
*/
public void setFillComposite(Composite composite) {
if (composite == null) {
throw new IllegalArgumentException("Null 'composite' argument.");
}
this.fillComposite = composite;
fireChangeEvent();
}
/**
* Returns <code>true</code> if a shape will be drawn for every item, or
* <code>false</code> if not.
*
* @return A boolean.
*
* @since 1.0.14
*/
public boolean getShapesVisible() {
return this.shapesVisible;
}
/**
* Set the flag that controls whether a shape will be drawn for every
* item, or not and sends a {@link RendererChangeEvent} to all registered
* listeners.
*
* @param visible the flag.
*
* @since 1.0.14
*/
public void setShapesVisible(boolean visible) {
this.shapesVisible = visible;
fireChangeEvent();
}
/**
* Returns <code>true</code> if first and last point of a series will be
* connected, <code>false</code> otherwise.
*
* @return The current status of the flag.
*
* @since 1.0.14
*/
public boolean getConnectFirstAndLastPoint() {
return this.connectFirstAndLastPoint;
}
/**
* Set the flag that controls whether the first and last point of a series
* will be connected or not and sends a {@link RendererChangeEvent} to all
* registered listeners.
*
* @param connect the flag.
*
* @since 1.0.14
*/
public void setConnectFirstAndLastPoint(boolean connect)
{
this.connectFirstAndLastPoint = connect;
fireChangeEvent();
}
/**
* 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));
}
/**
* Returns <code>true</code> if the renderer should use the fill paint
* setting to fill shapes, and <code>false</code> if it should just
* use the regular paint.
*
* @return A boolean.
*
* @see #setUseFillPaint(boolean)
* @since 1.0.14
*/
public boolean getUseFillPaint() {
return this.useFillPaint;
}
/**
* Sets the flag that controls whether the fill paint is used to fill
* shapes, and sends a {@link RendererChangeEvent} to all
* registered listeners.
*
* @param flag the flag.
*
* @see #getUseFillPaint()
* @since 1.0.14
*/
public void setUseFillPaint(boolean flag) {
this.useFillPaint = flag;
fireChangeEvent();
}
/**
* Returns the shape used to represent a line in the legend.
*
* @return The legend line (never <code>null</code>).
*
* @see #setLegendLine(Shape)
*/
public Shape getLegendLine() {
return this.legendLine;
}
/**
* Sets the shape used as a line in each legend item and sends a
* {@link RendererChangeEvent} to all registered listeners.
*
* @param line the line (<code>null</code> not permitted).
*
* @see #getLegendLine()
*/
public void setLegendLine(Shape line) {
if (line == null) {
throw new IllegalArgumentException("Null 'line' argument.");
}
this.legendLine = line;
fireChangeEvent();
}
/**
* Adds an entity to the collection.
*
* @param entities the entity collection being populated.
* @param area the entity area (if <code>null</code> a default will be
* used).
* @param dataset the dataset.
* @param series the series.
* @param item the item.
* @param entityX the entity's center x-coordinate in user space (only
* used if <code>area</code> is <code>null</code>).
* @param entityY the entity's center y-coordinate in user space (only
* used if <code>area</code> is <code>null</code>).
*/
// this method was copied from AbstractXYItemRenderer on 03-Oct-2011
protected void addEntity(EntityCollection entities, Shape area,
XYDataset dataset, int series, int item,
double entityX, double entityY) {
if (!getItemCreateEntity(series, item)) {
return;
}
Shape hotspot = area;
if (hotspot == null) {
double r = getDefaultEntityRadius();
double w = r * 2;
if (getPlot().getOrientation() == PlotOrientation.VERTICAL) {
hotspot = new Ellipse2D.Double(entityX - r, entityY - r, w, w);
}
else {
hotspot = new Ellipse2D.Double(entityY - r, entityX - r, w, w);
}
}
String tip = null;
XYToolTipGenerator generator = getToolTipGenerator(series, item);
if (generator != null) {
tip = generator.generateToolTip(dataset, series, item);
}
String url = null;
if (getURLGenerator() != null) {
url = getURLGenerator().generateURL(dataset, series, item);
}
XYItemEntity entity = new XYItemEntity(hotspot, dataset, series, item,
tip, url);
entities.add(entity);
}
/**
* 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) {
GeneralPath poly = null;
ValueAxis axis = plot.getAxisForDataset(plot.indexOf(dataset));
final 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.translateToJava2D(theta, radius, axis, dataArea);
if (poly == null) {
poly = new GeneralPath();
poly.moveTo(p.x, p.y);
}
else {
poly.lineTo(p.x, p.y);
}
}
if (getConnectFirstAndLastPoint()) {
poly.closePath();
}
g2.setPaint(lookupSeriesPaint(seriesIndex));
g2.setStroke(lookupSeriesStroke(seriesIndex));
if (isSeriesFilled(seriesIndex)) {
Composite savedComposite = g2.getComposite();
g2.setComposite(this.fillComposite);
g2.fill(poly);
g2.setComposite(savedComposite);
if (this.drawOutlineWhenFilled) {
// draw the outline of the filled polygon
g2.setPaint(lookupSeriesOutlinePaint(seriesIndex));
g2.draw(poly);
}
}
else {
// just the lines, no filling
g2.draw(poly);
}
// draw the item shapes
if (this.shapesVisible) {
// setup for collecting optional entity info...
EntityCollection entities = null;
if (info != null) {
entities = info.getOwner().getEntityCollection();
}
PathIterator pi = poly.getPathIterator(null);
int i = 0;
while (!pi.isDone()) {
final float[] coords = new float[6];
final int segType = pi.currentSegment(coords);
pi.next();
if (segType != PathIterator.SEG_LINETO &&
segType != PathIterator.SEG_MOVETO)
continue;
final int x = Math.round(coords[0]);
final int y = Math.round(coords[1]);
final Shape shape = ShapeUtilities.createTranslatedShape(
getItemShape(seriesIndex, i++), x, y);
Paint paint;
if (useFillPaint)
paint = lookupSeriesFillPaint(seriesIndex);
else
paint = lookupSeriesPaint(seriesIndex);
g2.setPaint(paint);
g2.fill(shape);
if (isSeriesFilled(seriesIndex) && this.drawOutlineWhenFilled) {
g2.setPaint(lookupSeriesOutlinePaint(seriesIndex));
g2.setStroke(lookupSeriesOutlineStroke(seriesIndex));
g2.draw(shape);
}
// add an entity for the item, but only if it falls within the
// data area...
if (entities != null &&
AbstractXYItemRenderer.isPointInRect(dataArea, x, y)) {
addEntity(entities, shape, dataset, seriesIndex, i-1, x, y);
}
}
}
}
/**
* 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.getAxis().getUpperBound();
Point center = plot.translateValueThetaRadiusToJava2D(axisMin, axisMin,
dataArea);
Iterator iterator = ticks.iterator();
while (iterator.hasNext()) {
NumberTick tick = (NumberTick) iterator.next();
double tickVal = tick.getNumber().doubleValue();
Point p = plot.translateValueThetaRadiusToJava2D(
tickVal, 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,
tick.getTextAnchor());
}
}
}
/**
* 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();
double angleDegrees = plot.isCounterClockwise() ? plot.getAngleOffset() : -plot.getAngleOffset();
Point p = plot.translateValueThetaRadiusToJava2D(angleDegrees,
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 plot = getPlot();
if (plot == null) {
return null;
}
XYDataset dataset = plot.getDataset(plot.getIndexOf(this));
if (dataset == null) {
return null;
}
String toolTipText = null;
if (getLegendItemToolTipGenerator() != null) {
toolTipText = getLegendItemToolTipGenerator().generateLabel(
dataset, series);
}
String urlText = null;
if (getLegendItemURLGenerator() != null) {
urlText = getLegendItemURLGenerator().generateLabel(dataset,
series);
}
String label = dataset.getSeriesKey(series).toString();
String description = label;
Shape shape = lookupSeriesShape(series);
Paint paint;
if (this.useFillPaint) {
paint = lookupSeriesFillPaint(series);
}
else {
paint = lookupSeriesPaint(series);
}
Stroke stroke = lookupSeriesStroke(series);
Paint outlinePaint = lookupSeriesOutlinePaint(series);
Stroke outlineStroke = lookupSeriesOutlineStroke(series);
boolean shapeOutlined = isSeriesFilled(series)
&& this.drawOutlineWhenFilled;
result = new LegendItem(label, description, toolTipText, urlText,
getShapesVisible(), shape, /* shapeFilled=*/ true, paint,
shapeOutlined, outlinePaint, outlineStroke,
/* lineVisible= */ true, this.legendLine, stroke, paint);
result.setToolTipText(toolTipText);
result.setURLText(urlText);
result.setDataset(dataset);
return result;
}
/**
* @since 1.0.14
*/
public XYToolTipGenerator getToolTipGenerator(int series, int item)
{
XYToolTipGenerator generator
= (XYToolTipGenerator) this.toolTipGeneratorList.get(series);
if (generator == null) {
generator = this.baseToolTipGenerator;
}
return generator;
}
/**
* @since 1.0.14
*/
public XYToolTipGenerator getSeriesToolTipGenerator(int series)
{
return (XYToolTipGenerator) this.toolTipGeneratorList.get(series);
}
/**
* @since 1.0.14
*/
public void setSeriesToolTipGenerator(int series,
XYToolTipGenerator generator)
{
this.toolTipGeneratorList.set(series, generator);
fireChangeEvent();
}
/**
* @since 1.0.14
*/
public XYToolTipGenerator getBaseToolTipGenerator()
{
return this.baseToolTipGenerator;
}
/**
* @since 1.0.14
*/
public void setBaseToolTipGenerator(XYToolTipGenerator generator)
{
this.baseToolTipGenerator = generator;
fireChangeEvent();
}
/**
* @since 1.0.14
*/
public XYURLGenerator getURLGenerator()
{
return this.urlGenerator;
}
/**
* @since 1.0.14
*/
public void setURLGenerator(XYURLGenerator urlGenerator)
{
this.urlGenerator = urlGenerator;
fireChangeEvent();
}
/**
* Returns the legend item tool tip generator.
*
* @return The tool tip generator (possibly <code>null</code>).
*
* @see #setLegendItemToolTipGenerator(XYSeriesLabelGenerator)
* @since 1.0.14
*/
public XYSeriesLabelGenerator getLegendItemToolTipGenerator() {
return this.legendItemToolTipGenerator;
}
/**
* Sets the legend item tool tip generator and sends a
* {@link RendererChangeEvent} to all registered listeners.
*
* @param generator the generator (<code>null</code> permitted).
*
* @see #getLegendItemToolTipGenerator()
* @since 1.0.14
*/
public void setLegendItemToolTipGenerator(
XYSeriesLabelGenerator generator) {
this.legendItemToolTipGenerator = generator;
fireChangeEvent();
}
/**
* Returns the legend item URL generator.
*
* @return The URL generator (possibly <code>null</code>).
*
* @see #setLegendItemURLGenerator(XYSeriesLabelGenerator)
* @since 1.0.14
*/
public XYSeriesLabelGenerator getLegendItemURLGenerator() {
return this.legendItemURLGenerator;
}
/**
* Sets the legend item URL generator and sends a
* {@link RendererChangeEvent} to all registered listeners.
*
* @param generator the generator (<code>null</code> permitted).
*
* @see #getLegendItemURLGenerator()
* @since 1.0.14
*/
public void setLegendItemURLGenerator(XYSeriesLabelGenerator generator) {
this.legendItemURLGenerator = generator;
fireChangeEvent();
}
/**
* 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;
}
if (this.drawOutlineWhenFilled != that.drawOutlineWhenFilled) {
return false;
}
if (!ObjectUtilities.equal(this.fillComposite, that.fillComposite)) {
return false;
}
if (this.useFillPaint != that.useFillPaint) {
return false;
}
if (!ShapeUtilities.equal(this.legendLine, that.legendLine)) {
return false;
}
if (this.shapesVisible != that.shapesVisible) {
return false;
}
if (this.connectFirstAndLastPoint != that.connectFirstAndLastPoint) {
return false;
}
if (!this.toolTipGeneratorList.equals(that.toolTipGeneratorList)) {
return false;
}
if (!ObjectUtilities.equal(this.baseToolTipGenerator,
that.baseToolTipGenerator)) {
return false;
}
if (!ObjectUtilities.equal(this.urlGenerator, that.urlGenerator)) {
return false;
}
if (!ObjectUtilities.equal(this.legendItemToolTipGenerator,
that.legendItemToolTipGenerator)) {
return false;
}
if (!ObjectUtilities.equal(this.legendItemURLGenerator,
that.legendItemURLGenerator)) {
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();
if (this.legendLine != null) {
clone.legendLine = ShapeUtilities.clone(this.legendLine);
}
clone.seriesFilled = (BooleanList) this.seriesFilled.clone();
clone.toolTipGeneratorList
= (ObjectList) this.toolTipGeneratorList.clone();
if (clone.baseToolTipGenerator instanceof PublicCloneable) {
clone.baseToolTipGenerator = (XYToolTipGenerator)
ObjectUtilities.clone(this.baseToolTipGenerator);
}
if (clone.urlGenerator instanceof PublicCloneable) {
clone.urlGenerator = (XYURLGenerator)
ObjectUtilities.clone(this.urlGenerator);
}
if (clone.legendItemToolTipGenerator instanceof PublicCloneable) {
clone.legendItemToolTipGenerator = (XYSeriesLabelGenerator)
ObjectUtilities.clone(this.legendItemToolTipGenerator);
}
if (clone.legendItemURLGenerator instanceof PublicCloneable) {
clone.legendItemURLGenerator = (XYSeriesLabelGenerator)
ObjectUtilities.clone(this.legendItemURLGenerator);
}
return clone;
}
/**
* Provides serialization support.
*
* @param stream the input stream.
*
* @throws IOException if there is an I/O error.
* @throws ClassNotFoundException if there is a classpath problem.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
this.legendLine = SerialUtilities.readShape(stream);
this.fillComposite = SerialUtilities.readComposite(stream);
}
/**
* Provides serialization support.
*
* @param stream the output stream.
*
* @throws IOException if there is an I/O error.
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
SerialUtilities.writeShape(this.legendLine, stream);
SerialUtilities.writeComposite(this.fillComposite, stream);
}
}
|