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; } }