package com.onaro.util.chart;
import ilog.views.chart.*;
import ilog.views.chart.data.*;
import ilog.views.chart.interactor.*;
import java.awt.geom.*;
import java.util.*;
public class AutoYZoomInteractor extends IlvChartZoomInteractor {
private static final long serialVersionUID = 1L;
/**
* limits the zoom to show at least this number of data points
*/
public static final int MIN_POINTS_IN_RANGE = 5;
/**
* Initializes a new AutoYZoomInteractor
.
* By default, unzooming operations are disabled.
*/
public AutoYZoomInteractor() {
setYZoomAllowed(false);
}
/**
* Performs the zoom. The y-range is automatically computed according to the
* data displayed within the specied x-range.
*/
protected void doIt() {
//get the data window that the user dragged
IlvDataWindow w = getZoomedDataWindow();
//makes sure that at least MIN_POINTS_IN_RANGE points are in the viewed range
if (moreThanMinPointInRange(w, getChart())) {
//performa the zoom, and fix the y axis to scale to the maz viewed value
performAnimatedZoom(getChart(), getYAxisIndex(), w.xRange, getAnimationStep());
}
}
public static boolean moreThanMinPointInRange(IlvDataWindow w, IlvChart chart) {
Set points = new HashSet();
IlvDataSet[] dataSets = chart.getDataSource().getDataSets();
for (IlvDataSet dataSet : dataSets) {
IlvDataPoints dataPoints = dataSet.getDataInside(w, 0, false);
if (dataPoints != null) {
for (int i = 0; i < dataPoints.size(); i++) {
points.add(new Point2D.Double(dataPoints.getX(i), dataPoints.getY(i)));
}
}
}
return points.size() >= MIN_POINTS_IN_RANGE;
}
public static void performAnimatedZoom(IlvChart chart, int yAxisIdx,
IlvDataWindow w,
int zoomSteps) {
if (zoomSteps < 1) {
chart.zoom(w, yAxisIdx);
return;
}
IlvAxis xAxis = chart.getXAxis();
IlvAxis yAxis = chart.getYAxis(yAxisIdx);
IlvDataInterval xRange = xAxis.getVisibleRange();
IlvDataInterval yRange = yAxis.getVisibleRange();
IlvDataInterval newXRange = w.xRange;
IlvDataInterval newYRange = w.yRange;
chart.getChartArea().setDirectRedrawEnabled(true);
xAxis.setAdjusting(true);
yAxis.setAdjusting(true);
int steps = zoomSteps + 1;
double deltaXMin = (newXRange.min - xRange.min) / steps;
double deltaXMax = (newXRange.max - xRange.max) / steps;
double deltaYMin = (newYRange.min - yRange.min) / steps;
double deltaYMax = (newYRange.max - yRange.max) / steps;
final IlvDataWindow dw = new IlvDataWindow(xRange, yRange);
for (int i = 0; i < steps; ++i) {
dw.xRange.setMin(dw.getXMin() + deltaXMin);
dw.xRange.setMax(dw.getXMax() + deltaXMax);
dw.yRange.setMin(dw.getYMin() + deltaYMin);
dw.yRange.setMax(dw.getYMax() + deltaYMax);
chart.zoom(dw, yAxisIdx);
}
chart.getChartArea().setDirectRedrawEnabled(false);
chart.zoom(w, yAxisIdx);
xAxis.setAdjusting(false);
yAxis.setAdjusting(false);
}
/**
* Performs an animated zoom.
*
* @param chart The considered chart.
* @param yAxisIdx The index of the considered y-axis.
* @param xRange The new visible range for the x-axis.
* @param zoomSteps The number of animation steps.
*/
public void performAnimatedZoom(IlvChart chart, int yAxisIdx,
IlvDataInterval xRange,
int zoomSteps) {
IlvDataWindow w = new IlvDataWindow(xRange, getYDataRange(chart, yAxisIdx, xRange));
performAnimatedZoom(chart, yAxisIdx, w, zoomSteps);
}
/**
* Computes the y-range corresponding to the specified x-range.
* The returned range is such that it contains all the data displayed
* within the specified x-range.
*
* @param chart The considered chart.
* @param yAxisIdx The index of the considered y-axis.
* @param xRange The visible range for the x-axis.
* @return The y-range, such that it contains all the data displayed
* within the specified x-range.
*/
public static IlvDataInterval getYDataRange(IlvChart chart,
int yAxisIdx,
IlvDataInterval xRange) {
IlvDataInterval res = new IlvDataInterval();
Iterator iter = chart.getRendererIterator();
IlvDataInterval tmpRange = null;
while (iter.hasNext()) {
IlvChartRenderer r = iter.next();
if (!r.isViewable() || r.getYAxisIdx() != yAxisIdx) continue;
tmpRange = r.getYRange(xRange, tmpRange);
res.add(tmpRange);
}
IlvDefaultStepsDefinition.adjustRange(res);
//even if the range shows values higher than 0, show from zero
res.setMin(0.0);
return res;
}
}