/**
*
* The MIT License
*
* Copyright (c) 2011 the original author or authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.googlecode.charts4j;
import static com.googlecode.charts4j.collect.Preconditions.checkArgument;
import static com.googlecode.charts4j.collect.Preconditions.checkNotNull;
import java.util.List;
import com.googlecode.charts4j.collect.ImmutableList;
import com.googlecode.charts4j.collect.Lists;
/**
* Plot implementation class. This class must always remain package private. It
* is constructed via the {@link Plots} static factory class.
*
* @author Julien Chastang (julien.c.chastang at gmail dot com)
*
*/
final class PlotImpl implements BarChartPlot, Line, RadarPlot, ScatterPlotData, XYLine {
/** X data series for this plot. **/
private final Data xData;
/** Y data series for this plot. **/
private final Data yData;
/** List of marked points for this plot. **/
private final List<MarkedPoints> markedPointsList = Lists.newLinkedList();
/** List of markers to be added to all point on this plot. **/
private final List<Marker> markers = Lists.newLinkedList();
/** Individual colors for bars in bar chart. **/
private final List<BarColor> barColors = Lists.newLinkedList();
/** Color of this plot. **/
private Color color;
/** Legend for this plot. **/
private String legend;
/** Point sizes for this scatter plot. **/
private Data pointSizes;
/** Fill area color for this plot. **/
private Color fillAreaColor;
/** Zero line if this is a bar chart. */
private double zeroLine = Data.MIN_VALUE;
/** Dataline for this bar chart. */
private DataLine dataLine;
/** The line style for this plot. */
private LineStyle lineStyle;
/** The priority for this plot. **/
private Priority priority;
/**
* Construct a plot with x and y data.
*
* @param xdata
* x data series
* @param ydata
* y data series
*/
PlotImpl(final Data xdata, final Data ydata) {
this.xData = xdata;
this.yData = ydata;
}
/**
* Construct a plot with y data. Y data is evenly spread on x axis.
*
* @param data
* y data series
*/
PlotImpl(final Data data) {
this.yData = data;
//Below, the * / 100 is to prevent ill-conditioned math.
int inc = 0;
if (data.getSize() > 1) {
inc = ((int)Data.MAX_VALUE) * 100 / (data.getSize() - 1);
}
final List<Number> xVals = Lists.newLinkedList();
double x = Data.MIN_VALUE;
for (int i = (int) Data.MIN_VALUE; i < data.getSize(); i++) {
xVals.add(x / 100);
x = x + inc;
}
this.xData = Data.newData(xVals);
}
/**
* Copy constructor.
*
* @param plotImpl
* object to be copied.
*/
private PlotImpl(final PlotImpl plotImpl) {
xData = plotImpl.xData;
yData = plotImpl.yData;
markedPointsList.addAll(plotImpl.markedPointsList);
barColors.addAll(plotImpl.barColors);
markers.addAll(plotImpl.markers);
color = plotImpl.color;
legend = plotImpl.legend;
pointSizes = plotImpl.pointSizes;
fillAreaColor = plotImpl.fillAreaColor;
zeroLine = plotImpl.zeroLine;
dataLine = plotImpl.dataLine;
lineStyle = plotImpl.lineStyle;
priority = plotImpl.priority;
}
public Plot klone() {
return new PlotImpl(this);
}
/**
* Get the Y series data.
*
* @return the y series data.
*/
Data getData() {
return yData;
}
/**
* Get the X series data.
*
* @return the x series data.
*/
Data getXData() {
return xData;
}
/**
* Get the Y series data.
*
* @return the y series data.
*/
Data getYData() {
return yData;
}
/**
* Get the legend for this plot.
*
*
* @return the legend as a string.
*/
String getLegend() {
return legend;
}
/**
* {@inheritDoc}
*/
public void setLegend(final String legend) {
checkNotNull(legend, "legend cannot be null");
this.legend = legend;
}
/**
* Get the color of this plot.
*
* @return the color of this plot. Could return null.
*/
Color getColor() {
return color;
}
/**
* {@inheritDoc}
*/
public void setColor(final Color color) {
checkNotNull(color, "color cannot be null");
this.color = color;
}
/**
* Get the individually colored bars in a bar chart.
*
* @return a list of individually colored bars.
*/
public ImmutableList<BarColor> getBarColors() {
return Lists.copyOf(barColors);
}
/**
* {@inheritDoc}
*/
public void setColor(final Color color, final int index) {
checkNotNull(color, "color cannot be null");
checkArgument(index >= 0, "index must be >= 0");
checkArgument(index < yData.getSize(), "index out of bounds");
barColors.add(new BarColor(color,index));
}
/**
* Get the fill area color for this plot.
*
* @return the fill area for this plot. Could be null.
*/
Color getFillAreaColor() {
return fillAreaColor;
}
/**
* {@inheritDoc}
*/
public void setFillAreaColor(final Color color) {
checkNotNull(color, "color cannot be null");
this.fillAreaColor = color;
}
/**
* Get the list of marked points for this plot.
*
* @return an immutable list of marked points.
*/
ImmutableList<MarkedPoints> getMarkedPointsList() {
return Lists.copyOf(markedPointsList);
}
/**
* Get the list of markers for this plot.
*
* @return an immutable list of markers.
*/
ImmutableList<Marker> getMarkers() {
return Lists.copyOf(markers);
}
/**
* {@inheritDoc}
*/
public void addShapeMarker(final Shape shape, final Color color, final int size, final int index) {
checkNotNull(shape, "shape cannot be null");
checkNotNull(color, "color cannot be null");
checkArgument(index >= 0, "index must be >= 0");
checkArgument(index < yData.getSize(), "index is out of bounds");
markedPointsList.add(new MarkedPoints(Markers.newShapeMarker(shape, color, size), index));
}
/**
* {@inheritDoc}
*/
public void addTextMarker(final String text, final Color color, final int size, final int index) {
checkNotNull(text, "text cannot be null");
checkNotNull(color, "color cannot be null");
checkArgument(index >= 0, "index must be >= 0");
checkArgument(index < yData.getSize(), "index is out of bounds");
markedPointsList.add(new MarkedPoints(Markers.newTextMarker(text, color, size), index));
}
/**
* {@inheritDoc}
*/
public void addShapeMarkers(final Shape shape, final Color color, final int size) {
checkNotNull(shape, "shape cannot be null");
checkNotNull(color, "color cannot be null");
markers.add(Markers.newShapeMarker(shape, color, size));
}
/**
* {@inheritDoc}
*/
public void addMarker(final Marker marker, final int index) {
checkNotNull(marker, "marker cannot be null");
checkArgument(index >= 0, "index must be >= 0");
markedPointsList.add(new MarkedPoints(marker, index));
}
/**
* {@inheritDoc}
*/
public void addMarkers(final Marker marker) {
checkNotNull(marker, "marker cannot be null");
markers.add(marker);
}
/**
* {@inheritDoc}
*/
public void addMarkers(final Marker marker, final int startIndex, final int endIndex, final int n) {
checkNotNull(marker, "marker cannot be null");
checkArgument(startIndex >= 0, "start index must be >= 0");
checkArgument(endIndex > 0, "end index must be > 0");
checkArgument(endIndex > startIndex, "end index must be > start index");
checkArgument(n > 0, "n must be > 0");
markedPointsList.add(new MarkedPoints(marker, startIndex, endIndex, n));
}
/**
* {@inheritDoc}
*/
public void addMarkers(final Marker marker, final int n) {
addMarkers(marker, 0, yData.getSize(), n);
}
/**
* {@inheritDoc}
*/
public void addMarkers(final Marker marker, final int startIndex, final int endIndex) {
addMarkers(marker, startIndex, endIndex, 1);
}
/**
* {@inheritDoc}
*/
public void setDataLine(final int dataLineSize, final Color color, final Priority priority) {
checkNotNull(color, "color cannot be null");
checkNotNull(priority, "priority cannot be null");
checkArgument(dataLineSize >= 0, "data line size must be >= 0");
dataLine = new DataLine(dataLineSize, color, priority);
}
/**
* Get the data line for bar charts.
*
* @return the data line for bar charts.
*/
DataLine getDataLine() {
return dataLine;
}
/**
* Get the zero line for bar charts.
*
* @return the zero line for bar charts.
*/
double getZeroLine() {
return zeroLine;
}
/**
* {@inheritDoc}
*/
public void setZeroLine(final double zeroLine) {
checkArgument(zeroLine >= Data.MIN_VALUE && zeroLine <= Data.MAX_VALUE, "Zero line must be between " + Data.MIN_VALUE + " and " + Data.MAX_VALUE);
this.zeroLine = zeroLine;
}
/**
* {@inheritDoc}
*/
public void setPriority(final Priority priority) {
checkNotNull(priority, "priority cannot be null");
this.priority = priority;
}
/**
* {@inheritDoc}
*/
public void setLineStyle(final LineStyle lineStyle) {
checkNotNull(lineStyle, "line style cannot be null");
this.lineStyle = lineStyle;
}
/**
* Get the line style for this plot.
*
* @return the line style for this plot.
*/
LineStyle getLineStyle() {
return lineStyle;
}
/**
* {@inheritDoc}
*/
public void setPointSizes(final Data pointSizes) {
checkNotNull(pointSizes, "point sizes cannot be null");
this.pointSizes = pointSizes;
}
/**
* Get the point sizes for scatter plots.
*
* @return the point sizes for scatter plots.
*/
Data getPointSizes() {
return pointSizes;
}
/**
* Get the priority for this plot.
*
* @return the priority for this plot
*/
Priority getPriority() {
return priority;
}
}