Example usage for org.jfree.chart ChartPanel getChartRenderingInfo

List of usage examples for org.jfree.chart ChartPanel getChartRenderingInfo

Introduction

In this page you can find the example usage for org.jfree.chart ChartPanel getChartRenderingInfo.

Prototype

public ChartRenderingInfo getChartRenderingInfo() 

Source Link

Document

Returns the chart rendering info from the most recent chart redraw.

Usage

From source file:net.sf.mzmine.chartbasics.ChartLogics.java

/**
 * calculates the correct height with multiple iterations Domain and Range axes need to share the
 * same unit (e.g. mm)/* w  ww .  j av  a  2s  .  co  m*/
 * 
 * @param myChart
 * @param copyToNewPanel
 * @param dataWidth width of data
 * @param axis for width calculation
 * @return
 */
public static double calcHeightToWidth(ChartPanel myChart, double chartWidth, double estimatedHeight,
        int iterations, boolean copyToNewPanel) {
    // if(myChart.getChartRenderingInfo()==null ||
    // myChart.getChartRenderingInfo().getChartArea()==null ||
    // myChart.getChartRenderingInfo().getChartArea().getWidth()==0)
    // result
    double height = estimatedHeight;
    double lastH = height;

    makeChartResizable(myChart);

    // paint on a ghost panel
    JPanel parent = (JPanel) myChart.getParent();
    JPanel p = copyToNewPanel ? new JPanel() : parent;
    if (copyToNewPanel)
        p.add(myChart, BorderLayout.CENTER);
    try {
        for (int i = 0; i < iterations; i++) {
            // paint on ghost panel with estimated height (if copy panel==true)
            myChart.setSize((int) chartWidth, (int) estimatedHeight);
            myChart.paintImmediately(myChart.getBounds());

            XYPlot plot = (XYPlot) myChart.getChart().getPlot();
            ChartRenderingInfo info = myChart.getChartRenderingInfo();
            Rectangle2D dataArea = info.getPlotInfo().getDataArea();
            Rectangle2D chartArea = info.getChartArea();

            // calc title space: will be added later to the right plot size
            double titleWidth = chartArea.getWidth() - dataArea.getWidth();
            double titleHeight = chartArea.getHeight() - dataArea.getHeight();

            // calc right plot size with axis dim.
            // real plot width is given by factor;
            double realPW = chartWidth - titleWidth;

            // ranges
            ValueAxis domainAxis = plot.getDomainAxis();
            org.jfree.data.Range x = domainAxis.getRange();
            ValueAxis rangeAxis = plot.getRangeAxis();
            org.jfree.data.Range y = rangeAxis.getRange();

            // real plot height can be calculated by
            double realPH = realPW / x.getLength() * y.getLength();

            // the real height
            height = realPH + titleHeight;

            // for next iteration
            estimatedHeight = height;
            if ((int) lastH == (int) height)
                break;
            else
                lastH = height;
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    if (copyToNewPanel) {
        // reset to frame
        p.removeAll();
        parent.add(myChart);
    }

    return height;
}

From source file:org.yccheok.jstock.gui.charting.ChartLayerUI.java

private TimeSeries getTimeSeries(int plotIndex, int seriesIndex) {
    final ChartPanel chartPanel = this.chartJDialog.getChartPanel();

    if (plotIndex >= chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotCount()) {
        /* Not ready yet. */
        return null;
    }/*from w ww  . java2  s  .  co  m*/

    if (plotIndex >= this.chartJDialog.getPlotSize()) {
        /* Not ready yet. */
        return null;
    }

    final XYDataset xyDataset = this.chartJDialog.getPlot(plotIndex).getDataset();
    if (xyDataset instanceof TimeSeriesCollection) {
        final TimeSeriesCollection timeSeriesCollection = (TimeSeriesCollection) xyDataset;
        if (seriesIndex >= timeSeriesCollection.getSeriesCount()) {
            return null;
        }
        return timeSeriesCollection.getSeries(seriesIndex);
    } else {
        // 0 is candlestick chart.
        if (plotIndex == 0 && seriesIndex == 0) {
            return null;
        }
        if (seriesIndex >= this.chartJDialog.getPlot(plotIndex).getDatasetCount()) {
            return null;
        }
        final XYDataset d = this.chartJDialog.getPlot(plotIndex).getDataset(seriesIndex);
        return ((TimeSeriesCollection) d).getSeries(0);
    }
}

From source file:org.yccheok.jstock.gui.charting.ChartLayerUI.java

private void updateTraceInfosIfPossible(int dataOffset) {
    // Do we have a valid mainTraceInfo?
    if (this.mainTraceInfo.point == null) {
        // Nope. Returns early.
        return;/*from w  w w .  j a  v a 2  s.co m*/
    }
    final int newDataIndex = dataOffset + this.mainTraceInfo.dataIndex;
    if (newDataIndex < 0) {
        // We try to offset beyond chart boundary. Returns early.
    }

    /* Try to get correct main chart area. */
    final ChartPanel chartPanel = this.chartJDialog.getChartPanel();
    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0)
            .getDataArea();

    final Point2D tmpPoint = this.getPoint(0, 0, newDataIndex);
    if (tmpPoint == null || _plotArea.contains(tmpPoint) == false) {
        return;
    }

    this.mainTraceInfo = TraceInfo.newInstance(tmpPoint, 0, 0, newDataIndex);
    this.updateTraceInfos();
}

From source file:org.yccheok.jstock.gui.charting.InvestmentFlowLayerUI.java

@Override
protected void paintLayer(Graphics2D g2, JXLayer<? extends V> layer) {
    super.paintLayer(g2, layer);

    final ChartPanel chartPanel = ((ChartPanel) layer.getView());

    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();

    this.drawArea.setRect(_plotArea);

    if (false == this.investmentFlowChartJDialog.isFinishLookUpPrice()) {
        this.drawBusyBox(g2, layer);
    }//ww  w  . j  av a  2s  .c  o m

    if (this.investPoint != null) {
        final int RADIUS = 8;
        final Object oldValueAntiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
        final Color oldColor = g2.getColor();

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(COLOR_RED);
        g2.fillOval((int) (this.investPoint.getX() - (RADIUS >> 1) + 0.5),
                (int) (this.investPoint.getY() - (RADIUS >> 1) + 0.5), RADIUS, RADIUS);
        g2.setColor(oldColor);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldValueAntiAlias);
        this.updateInvestInformationBox(g2);
    }

    if (this.ROIPoint != null) {
        final int RADIUS = 8;
        final Object oldValueAntiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
        final Color oldColor = g2.getColor();

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(COLOR_BLUE);
        g2.fillOval((int) (this.ROIPoint.getX() - (RADIUS >> 1) + 0.5),
                (int) (this.ROIPoint.getY() - (RADIUS >> 1) + 0.5), RADIUS, RADIUS);
        g2.setColor(oldColor);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldValueAntiAlias);
        this.updateROIInformationBox(g2);
    }

    this.solveConflict();

    if (this.investPoint != null) {
        this.drawInformationBox(g2, this.investmentFlowChartJDialog.getInvestActivities(this.investPointIndex),
                investRect, investParams, investValues,
                GUIBundle.getString("InvestmentFlowLayerUI_Total_Invest"), totalInvestValue,
                COLOR_RED_BACKGROUND, COLOR_RED_BORDER);
    }

    if (this.ROIPoint != null) {
        this.drawInformationBox(g2, this.investmentFlowChartJDialog.getROIActivities(this.ROIPointIndex),
                ROIRect, ROIParams, ROIValues, GUIBundle.getString("InvestmentFlowLayerUI_Total_Return"),
                totalROIValue, COLOR_BLUE_BACKGROUND, COLOR_BLUE_BORDER);
    }

    this.drawTitle(g2);
}

From source file:org.yccheok.jstock.gui.charting.ChartLayerUI.java

private Point2D.Double getPoint(int plotIndex, int seriesIndex, int dataIndex) {
    final TimeSeries timeSeries = this.getTimeSeries(plotIndex, seriesIndex);
    if (timeSeries == null) {
        // Possible this is candlestick?
        final XYPlot plot = this.chartJDialog.getPlot(plotIndex);
        if (plot.getDataset(seriesIndex) instanceof org.jfree.data.xy.DefaultHighLowDataset) {
            return this._getPointForCandlestick(plotIndex, seriesIndex, dataIndex);
        }/*from   w  w  w .java  2  s.  c  om*/
        return null;
    }

    if (dataIndex >= timeSeries.getItemCount()) {
        /* Not ready yet. */
        return null;
    }

    final ChartPanel chartPanel = this.chartJDialog.getChartPanel();
    final XYPlot plot = this.chartJDialog.getPlot(plotIndex);
    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();

    final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(dataIndex);
    final double xValue = timeSeriesDataItem.getPeriod().getFirstMillisecond();
    final double yValue = timeSeriesDataItem.getValue().doubleValue();
    final Rectangle2D plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(plotIndex)
            .getDataArea();
    final double xJava2D = domainAxis.valueToJava2D(xValue, plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, plotArea, rangeAxisEdge);
    // Use Double version, to avoid from losing precision.
    return new Point2D.Double(xJava2D, yJava2D);
}

From source file:org.yccheok.jstock.gui.charting.ChartLayerUI.java

private boolean _updateMainTraceInfoForCandlestick(Point2D point) {
    if (point == null) {
        return false;
    }/*from   ww w .ja  v a2 s.  co m*/

    final ChartPanel chartPanel = this.chartJDialog.getChartPanel();
    // Top most plot.
    final XYPlot plot = this.chartJDialog.getPlot();

    final org.jfree.data.xy.DefaultHighLowDataset defaultHighLowDataset = (org.jfree.data.xy.DefaultHighLowDataset) plot
            .getDataset();

    // I also not sure why. This is what are being done in Mouse Listener Demo 4.
    //
    // Don't use it. It will cause us to lose precision.
    //final Point2D p2 = chartPanel.translateScreenToJava2D((Point)point);

    /* Try to get correct main chart area. */
    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0)
            .getDataArea();

    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
    // Don't use it. It will cause us to lose precision.
    //final double coordinateX = domainAxis.java2DToValue(p2.getX(), _plotArea,
    //        domainAxisEdge);
    final double coordinateX = domainAxis.java2DToValue(point.getX(), _plotArea, domainAxisEdge);
    //double coordinateY = rangeAxis.java2DToValue(mousePoint2.getY(), plotArea,
    //        rangeAxisEdge);

    int low = 0;
    int high = defaultHighLowDataset.getItemCount(0) - 1;
    Date date = new Date((long) coordinateX);
    final long time = date.getTime();
    long bestDistance = Long.MAX_VALUE;
    int bestMid = 0;

    while (low <= high) {
        int mid = (low + high) >>> 1;

        final Date d = defaultHighLowDataset.getXDate(0, mid);
        final long search = d.getTime();
        final long cmp = search - time;

        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            bestDistance = 0;
            bestMid = mid;
            break;
        }

        final long abs_cmp = Math.abs(cmp);
        if (abs_cmp < bestDistance) {
            bestDistance = abs_cmp;
            bestMid = mid;
        }
    }

    final double xValue = defaultHighLowDataset.getXDate(0, bestMid).getTime();
    final double yValue = defaultHighLowDataset.getCloseValue(0, bestMid);
    final double xJava2D = domainAxis.valueToJava2D(xValue, _plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, _plotArea, rangeAxisEdge);

    final int tmpIndex = bestMid;
    // translateJava2DToScreen will internally convert Point2D.Double to Point.
    final Point2D tmpPoint = chartPanel.translateJava2DToScreen(new Point2D.Double(xJava2D, yJava2D));
    this.mainDrawArea.setRect(_plotArea);

    if (this.mainDrawArea.contains(tmpPoint)) {
        // 0 indicates main plot.
        this.mainTraceInfo = TraceInfo.newInstance(tmpPoint, 0, 0, tmpIndex);
        return true;
    }
    return false;
}

From source file:org.yccheok.jstock.gui.charting.ChartLayerUI.java

private Point2D.Double _getPointForCandlestick(int plotIndex, int seriesIndex, int dataIndex) {
    final ChartPanel chartPanel = this.chartJDialog.getChartPanel();
    final XYPlot plot = this.chartJDialog.getPlot(plotIndex);
    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();

    final org.jfree.data.xy.DefaultHighLowDataset defaultHighLowDataset = (org.jfree.data.xy.DefaultHighLowDataset) plot
            .getDataset(seriesIndex);//from   w  w  w  . ja v  a  2s .  c o  m

    if (dataIndex >= defaultHighLowDataset.getItemCount(0)) {
        /* Not ready yet. */
        return null;
    }

    final double xValue = defaultHighLowDataset.getXDate(0, dataIndex).getTime();
    final double yValue = defaultHighLowDataset.getCloseValue(0, dataIndex);
    final Rectangle2D plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(plotIndex)
            .getDataArea();
    final double xJava2D = domainAxis.valueToJava2D(xValue, plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, plotArea, rangeAxisEdge);
    // Use Double version, to avoid from losing precision.
    return new Point2D.Double(xJava2D, yJava2D);
}

From source file:org.yccheok.jstock.gui.charting.InvestmentFlowLayerUI.java

private boolean updateInvestPoint(Point2D _investPoint) {
    if (_investPoint == null) {
        return false;
    }//from   w w  w .j  av a  2  s .  c  om

    final ChartPanel chartPanel = this.investmentFlowChartJDialog.getChartPanel();
    final JFreeChart chart = chartPanel.getChart();
    final XYPlot plot = (XYPlot) chart.getPlot();
    final TimeSeriesCollection timeSeriesCollection = (TimeSeriesCollection) plot.getDataset();
    final TimeSeries timeSeries = timeSeriesCollection.getSeries(0);

    // I also not sure why. This is what are being done in Mouse Listener Demo 4.
    //
    // Don't use it. It will cause us to lose precision.
    //final Point2D p2 = chartPanel.translateScreenToJava2D((Point)_investPoint);

    /* Try to get correct main chart area. */
    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();

    /* Believe it? When there is another thread keep updateing time series data,
     * and keep calling setDirty, _plotArea can be 0 size sometimes. Ignore it.
     * Just assume we had processed it.
     */
    if (_plotArea.getWidth() == 0.0 && _plotArea.getHeight() == 0.0) {
        /* Cheat the caller. */
        return true;
    }

    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
    final double coordinateX = domainAxis.java2DToValue(_investPoint.getX(), _plotArea, domainAxisEdge);

    int low = 0;
    int high = timeSeries.getItemCount() - 1;
    Date date = new Date((long) coordinateX);
    final long time = date.getTime();
    long bestDistance = Long.MAX_VALUE;
    int bestMid = 0;

    while (low <= high) {
        int mid = (low + high) >>> 1;

        final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(mid);
        final Day day = (Day) timeSeriesDataItem.getPeriod();
        final long search = day.getFirstMillisecond();
        final long cmp = search - time;

        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            bestDistance = 0;
            bestMid = mid;
            break;
        }

        final long abs_cmp = Math.abs(cmp);
        if (abs_cmp < bestDistance) {
            bestDistance = abs_cmp;
            bestMid = mid;
        }
    }

    final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(bestMid);
    final double xValue = timeSeriesDataItem.getPeriod().getFirstMillisecond();
    final double yValue = timeSeriesDataItem.getValue().doubleValue();
    final double xJava2D = domainAxis.valueToJava2D(xValue, _plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, _plotArea, rangeAxisEdge);

    final int tmpIndex = bestMid;
    // Do not perform translation as this will cause precision losing.
    // We might experience unstable point. For example,
    //
    // this.investPoint is 700.9, there are 2 data points which are 700 and
    // 701.
    // During first updateInvestPoint(this.investPoint) call, data point 701
    // will be chosen, and this.investPoint has been truncated to 700.
    // During second updateInvestPoint(this.investPoint) call, data point 700
    // will be chosen. We may observe an unstable point swings between 700
    // and 701.
    //
    // translateJava2DToScreen will internally convert Point2D.Double to Point.
    //final Point2D tmpPoint = chartPanel.translateJava2DToScreen(new Point2D.Double(xJava2D, yJava2D));
    final Point2D tmpPoint = new Point2D.Double(xJava2D, yJava2D);
    this.drawArea.setRect(_plotArea);

    if (this.drawArea.contains(tmpPoint)) {
        this.investPointIndex = tmpIndex;
        this.investPoint = tmpPoint;
        return true;
    }
    return false;
}

From source file:org.yccheok.jstock.gui.charting.ChartLayerUI.java

private boolean updateMainTraceInfo(Point2D point) {
    if (point == null) {
        return false;
    }// w w  w. j  av  a  2s .  c o  m

    final ChartPanel chartPanel = this.chartJDialog.getChartPanel();
    // Top most plot.
    final XYPlot plot = this.chartJDialog.getPlot();

    if (plot.getDataset() instanceof org.jfree.data.xy.DefaultHighLowDataset) {
        return this._updateMainTraceInfoForCandlestick(point);
    }

    final TimeSeriesCollection timeSeriesCollection = (TimeSeriesCollection) plot.getDataset();
    // 0 are the main chart. 1, 2, 3... are TA.
    final TimeSeries timeSeries = timeSeriesCollection.getSeries(0);

    // I also not sure why. This is what are being done in Mouse Listener Demo 4.
    //
    // Don't use it. It will cause us to lose precision.
    //final Point2D p2 = chartPanel.translateScreenToJava2D((Point)point);

    /* Try to get correct main chart area. */
    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0)
            .getDataArea();

    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
    // Don't use it. It will cause us to lose precision.
    //final double coordinateX = domainAxis.java2DToValue(p2.getX(), _plotArea,
    //        domainAxisEdge);
    final double coordinateX = domainAxis.java2DToValue(point.getX(), _plotArea, domainAxisEdge);
    //double coordinateY = rangeAxis.java2DToValue(mousePoint2.getY(), plotArea,
    //        rangeAxisEdge);

    int low = 0;
    int high = timeSeries.getItemCount() - 1;
    Date date = new Date((long) coordinateX);
    final long time = date.getTime();
    long bestDistance = Long.MAX_VALUE;
    int bestMid = 0;

    while (low <= high) {
        int mid = (low + high) >>> 1;

        final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(mid);
        final Day day = (Day) timeSeriesDataItem.getPeriod();
        final long search = day.getFirstMillisecond();
        final long cmp = search - time;

        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            bestDistance = 0;
            bestMid = mid;
            break;
        }

        final long abs_cmp = Math.abs(cmp);
        if (abs_cmp < bestDistance) {
            bestDistance = abs_cmp;
            bestMid = mid;
        }
    }

    final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(bestMid);
    final double xValue = timeSeriesDataItem.getPeriod().getFirstMillisecond();
    final double yValue = timeSeriesDataItem.getValue().doubleValue();
    final double xJava2D = domainAxis.valueToJava2D(xValue, _plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, _plotArea, rangeAxisEdge);

    final int tmpIndex = bestMid;
    // translateJava2DToScreen will internally convert Point2D.Double to Point.
    final Point2D tmpPoint = chartPanel.translateJava2DToScreen(new Point2D.Double(xJava2D, yJava2D));
    this.mainDrawArea.setRect(_plotArea);

    if (this.mainDrawArea.contains(tmpPoint)) {
        // 0 indicates main plot.
        this.mainTraceInfo = TraceInfo.newInstance(tmpPoint, 0, 0, tmpIndex);
        return true;
    }
    return false;
}

From source file:org.yccheok.jstock.gui.charting.InvestmentFlowLayerUI.java

private boolean updateROIPoint(Point2D _ROIPoint) {
    if (_ROIPoint == null) {
        return false;
    }/*w w w  . ja  v a  2  s.c  o  m*/

    final ChartPanel chartPanel = this.investmentFlowChartJDialog.getChartPanel();
    final JFreeChart chart = chartPanel.getChart();
    final XYPlot plot = (XYPlot) chart.getPlot();
    // Dataset 0 are the invest information. 1 is the ROI information.
    final TimeSeriesCollection timeSeriesCollection = (TimeSeriesCollection) plot.getDataset(1);
    final TimeSeries timeSeries = timeSeriesCollection.getSeries(0);

    // I also not sure why. This is what are being done in Mouse Listener Demo 4.
    //
    // Don't use it. It will cause us to lose precision.
    //final Point2D p2 = chartPanel.translateScreenToJava2D((Point)_ROIPoint);

    /* Try to get correct main chart area. */
    final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();

    /* Believe it? When there is another thread keep updateing time series data,
     * and keep calling setDirty, _plotArea can be 0 size sometimes. Ignore it.
     * Just assume we had processed it.
     */
    if (_plotArea.getWidth() == 0.0 && _plotArea.getHeight() == 0.0) {
        /* Cheat the caller. */
        return true;
    }

    final ValueAxis domainAxis = plot.getDomainAxis();
    final RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
    final ValueAxis rangeAxis = plot.getRangeAxis();
    final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
    final double coordinateX = domainAxis.java2DToValue(_ROIPoint.getX(), _plotArea, domainAxisEdge);

    int low = 0;
    int high = timeSeries.getItemCount() - 1;
    Date date = new Date((long) coordinateX);
    final long time = date.getTime();
    long bestDistance = Long.MAX_VALUE;
    int bestMid = 0;

    while (low <= high) {
        int mid = (low + high) >>> 1;

        final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(mid);
        final Day day = (Day) timeSeriesDataItem.getPeriod();
        final long search = day.getFirstMillisecond();
        final long cmp = search - time;

        if (cmp < 0) {
            low = mid + 1;
        } else if (cmp > 0) {
            high = mid - 1;
        } else {
            bestDistance = 0;
            bestMid = mid;
            break;
        }

        final long abs_cmp = Math.abs(cmp);
        if (abs_cmp < bestDistance) {
            bestDistance = abs_cmp;
            bestMid = mid;
        }
    }

    final TimeSeriesDataItem timeSeriesDataItem = timeSeries.getDataItem(bestMid);
    final double xValue = timeSeriesDataItem.getPeriod().getFirstMillisecond();
    final double yValue = timeSeriesDataItem.getValue().doubleValue();
    final double xJava2D = domainAxis.valueToJava2D(xValue, _plotArea, domainAxisEdge);
    final double yJava2D = rangeAxis.valueToJava2D(yValue, _plotArea, rangeAxisEdge);

    final int tmpIndex = bestMid;
    // Do not perform translation as this will cause precision losing.
    // We might experience unstable point. For example,
    //
    // this.ROIPoint is 700.9, there are 2 data points which are 700 and
    // 701.
    // During first updateROIPoint(this.ROIPoint) call, data point 701
    // will be chosen, and this.ROIPoint has been truncated to 700.
    // During second updateROIPoint(this.ROIPoint) call, data point 700
    // will be chosen. We may observe an unstable point swings between 700
    // and 701.
    //
    // translateJava2DToScreen will internally convert Point2D.Double to Point.
    //final Point2D tmpPoint = chartPanel.translateJava2DToScreen(new Point2D.Double(xJava2D, yJava2D));
    final Point2D tmpPoint = new Point2D.Double(xJava2D, yJava2D);
    this.drawArea.setRect(_plotArea);

    if (this.drawArea.contains(tmpPoint)) {
        this.ROIPointIndex = tmpIndex;
        this.ROIPoint = tmpPoint;
        return true;
    }
    return false;
}