package pl.edu.fuw.fid.signalanalysis.dtf;
import java.awt.geom.Rectangle2D;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.labels.XYSeriesLabelGenerator;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* Panel displaying plot of AR criteria value vs selected model order.
* Allows user to select feasible model order and notifies given listener object
* about the selection.
*
* @author ptr@mimuw.edu.pl
*/
public class DtfOrderCriteriaPanel extends ChartPanel {
private DtfOrderSelectionListener listener;
private static JFreeChart createChart(final XYSeriesWithLegend[] criteria) {
final XYSeriesCollection dataset = new XYSeriesCollection();
for (XYSeries serie : criteria) {
dataset.addSeries(serie);
}
final JFreeChart chart = ChartFactory.createXYLineChart("Model order selection", "model order", "criterion value", dataset, PlotOrientation.VERTICAL, true, false, false);
final XYPlot plot = chart.getXYPlot();
((NumberAxis) plot.getDomainAxis()).setTickUnit(new NumberTickUnit(1.0));
final XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
renderer.setLegendItemToolTipGenerator(new XYSeriesLabelGenerator() {
@Override
public String generateLabel(XYDataset xyd, int i) {
return (i>=0 && i<criteria.length) ? criteria[i].getLegend() : "";
}
});
for (int i=0; i<dataset.getSeriesCount(); ++i) {
renderer.setSeriesShapesVisible(i, true);
renderer.setSeriesShapesFilled(i, true);
}
return chart;
}
public static DtfOrderCriteriaPanel create(int maxOrder, XYSeriesWithLegend[] criteria) {
return new DtfOrderCriteriaPanel(maxOrder, createChart(criteria));
}
public DtfOrderCriteriaPanel(final int maxOrder, JFreeChart chart) {
super(chart);
if (maxOrder <= 0) {
throw new IllegalArgumentException("maxOrder=" + maxOrder);
}
final XYPlot plot = chart.getXYPlot();
setDomainZoomable(false);
setRangeZoomable(false);
addChartMouseListener(new ChartMouseListener() {
@Override
public void chartMouseMoved(ChartMouseEvent cme) {
// nothing here
}
@Override
public void chartMouseClicked(ChartMouseEvent cme) {
int x = cme.getTrigger().getX();
Rectangle2D plotArea = getScreenDataArea();
// convert position in pixels to actual value on X axis
double value = plot.getDomainAxis().java2DToValue(x, plotArea, plot.getDomainAxisEdge());
int selectedOrder = (int) Math.round(value);
if (selectedOrder > 0 && selectedOrder <= maxOrder) {
// display selected model order
plot.clearDomainMarkers();
plot.addDomainMarker(new ValueMarker(selectedOrder));
// user-defined callback on model order change
DtfOrderSelectionListener call = listener;
if (call != null) {
call.modelOrderSelected(selectedOrder);
}
}
}
});
}
void setListener(DtfOrderSelectionListener listener) {
this.listener = listener;
}
}