/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.util.media.chart;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import sim.util.gui.*;
// From JFreeChart
import org.jfree.data.xy.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.data.general.*;
// from iText (www.lowagie.com/iText/)
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
/* // looks like we'll have to move to these soon
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
*/
/**
TimeSeriesChartGenerator is a ChartGenerator which displays a time-series chart using the JFreeChart library.
The generator uses the XYSeriesCollection as its dataset, and thus holds some N XYSeriesDataset objects, each
representing a time series displayed on the chart. You add series to the generator with the <tt>addSeries</tt>
method.
<p>TimeSeriesChartGenerator creates attributes components in the form of TimeSeriesAttributes, which work with
the generator to properly update the chart to reflect changes the user has made to its display.
*/
public class TimeSeriesChartGenerator extends XYChartGenerator
{
public void clearAllSeries()
{
SeriesAttributes[] c = getSeriesAttributes();
for (int i = 0; i < c.length; i++)
{
((TimeSeriesAttributes)(c[i])).clear();
}
}
public void removeSeries(int index)
{
super.removeSeries(index);
XYSeriesCollection xysc = (XYSeriesCollection) getSeriesDataset();
xysc.removeSeries(index);
}
public void moveSeries(int index, boolean up)
{
super.moveSeries(index, up);
if ((index > 0 && up) || (index < getSeriesCount() - 1 && !up)) // it's not the first or the last given the move
{
XYSeriesCollection xysc = (XYSeriesCollection) getSeriesDataset();
// this requires removing everything from the dataset and resinserting, duh
ArrayList items = new ArrayList(xysc.getSeries());
xysc.removeAllSeries();
int delta = up? -1:1;
// now rearrange
items.add(index + delta, items.remove(index));
// rebuild the dataset
for(int i = 0; i < items.size(); i++)
xysc.addSeries(((XYSeries)(items.get(i))));
}
}
/** Adds a series, plus a (possibly null) SeriesChangeListener which will receive a <i>single</i>
event if/when the series is deleted from the chart by the user. The series should have a key
in the form of a String. Returns the series attributes. */
public SeriesAttributes addSeries( final XYSeries series, final SeriesChangeListener stopper)
{
XYSeriesCollection xysc = (XYSeriesCollection) getSeriesDataset();
int i = xysc.getSeriesCount();
series.setKey(new ChartGenerator.UniqueString(series.getKey()));
xysc.addSeries(series);
TimeSeriesAttributes csa = new TimeSeriesAttributes(this, series, i, stopper);
seriesAttributes.add(csa);
revalidate();
return csa;
}
protected void buildChart()
{
XYSeriesCollection collection = new XYSeriesCollection();
chart = ChartFactory.createXYLineChart("Untitled Chart","Untitled X Axis","Untitled Y Axis", collection,
PlotOrientation.VERTICAL, false, true, false);
((XYLineAndShapeRenderer)(((XYPlot)(chart.getPlot())).getRenderer())).setDrawSeriesLineAsPath(true);
chart.setAntiAlias(true);
//chartPanel = new ScrollableChartPanel(chart, true);
chartPanel = buildChartPanel(chart);
setChartPanel(chartPanel);
// chartHolder.getViewport().setView(chartPanel);
// this must come last because the chart must exist for us to set its dataset
setSeriesDataset(collection);
}
JCheckBox useCullingCheckBox;
NumberTextField maxPointsPerSeriesTextField;
DataCuller dataCuller;
public DataCuller getDataCuller() {return dataCuller;}
public void setDataCuller(DataCuller dataCuller) {this.dataCuller = dataCuller;}
public TimeSeriesChartGenerator()
{
super();
LabelledList globalAttribList = (LabelledList) (((DisclosurePanel)getGlobalAttribute(-2)).getDisclosedComponent());
useCullingCheckBox = new JCheckBox();
globalAttribList.add(new JLabel("Cull Data"), useCullingCheckBox);
maxPointsPerSeriesTextField = new NumberTextField(1000)
{
public double newValue(final double val)
{
int max = (int)val;
if(val<2)
return (int)getValue();
dataCuller = new MinGapDataCuller(max);
return max;
}
};
useCullingCheckBox.setSelected(true);
globalAttribList.add(new JLabel("... Over"),maxPointsPerSeriesTextField);
maxPointsPerSeriesTextField.setToolTipText("The maximum number of data points in a series before data culling gets triggered.");
dataCuller = new MinGapDataCuller((int)maxPointsPerSeriesTextField.getValue());
useCullingCheckBox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
if(useCullingCheckBox.isSelected())
{
maxPointsPerSeriesTextField.setEnabled(true);
int maxPoints = (int)maxPointsPerSeriesTextField.getValue();
dataCuller = new MinGapDataCuller(maxPoints);
}
else
{
maxPointsPerSeriesTextField.setEnabled(false);
dataCuller = null;
}
}
});
}
}