
// PlotFunctionEx.java
// https://stackoverflow.com/questions/20097308/java-how-to-receive-point-coordinates-after-mouse-button-release-jfreechart
// Modified by Andrew Davison, ad@coe.psu.ac.th, Nov 2022

/*  Plot the function y = 3x^2 for x = -20 to 20,
    generating 20 data points.

    When the mouse is clicked anywhere in the chart, its coordinate
    relative to the XY plot origin is printed.

    If the mouse is clicked on a graph point (large red squares)
    then its coordinate is printed.

    Usage:
      > compile PlotFunctionEx.java
      > run PlotFunctionEx
*/

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

import org.jfree.chart.*;
import org.jfree.chart.entity.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.ui.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.chart.util.*;

import org.jfree.data.function.*;
import org.jfree.data.general.*;
import org.jfree.data.xy.*;


public class PlotFunctionEx extends JFrame
{
  // global so can be used in getChartCoord()
  private JFreeChart chart; 
  private ChartPanel chartPanel;
 

  public PlotFunctionEx()
  {
    super("Parabola Demo");

    XYDataset ds = createDataset();
    chart = createChart(ds);

    chartPanel = new ChartPanel(chart);
    chartPanel.addChartMouseListener(new ChartMouseListener() 
    {
      public void chartMouseClicked(ChartMouseEvent ev) 
      {  reportCoords(ev); }

      public void chartMouseMoved(ChartMouseEvent ev) { }
    });

    setContentPane(chartPanel);

    // pack()
    setSize(800, 400);
    setResizable(false);
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setVisible(true);
  }  // end of PlotFunctionEx()



  private XYDataset createDataset()
  {
    // create y = a0 + a1*x + a2*x^2 + ... + an*x^n
    double[] coefs = {0.0, 0.0, 3.0};
    Function2D fn = new PolynomialFunction2D(coefs);
       /*   also LineFunction2D, NormalDistributionFunction2D, 
                 PowerFunction2D
       */
    XYDataset ds = DatasetUtils.sampleFunction2D(
              fn, -20.0, 20.0, 20, "y = 3x^2 {-20...20}");
                 // start, end, no. of samples
    return ds;
  } /* createDataset */



  private JFreeChart createChart(XYDataset ds)
  {
    JFreeChart chart = ChartFactory.createXYLineChart(
                                   "Parabola", "X", "Y", ds);

    XYPlot plot = (XYPlot) chart.getPlot();

    XYLineAndShapeRenderer rend = 
           (XYLineAndShapeRenderer) plot.getRenderer();
    rend.setDefaultShapesVisible(true);   // make coords visible
    // enlarge points, so easy to click upon
    rend.setSeriesShape(0, 
              ShapeUtils.createTranslatedShape(
                       new Rectangle(12, 12), -6, -6));

    return chart;
  } /* createChart */


  private void reportCoords(ChartMouseEvent ev) 
  /* when the mouse is clicked, print the chart coordinate
     and the plot coordinate if the mouse is on it
  */
  {
    Point2D.Double pt = getChartCoord(ev);
    System.out.printf("Cicked on chart at (%.2f, %.2f)\n", pt.x, pt.y);

    // get the plot coordinate
    ChartEntity ce = ev.getEntity();
    if (ce instanceof XYItemEntity) {
      XYItemEntity e = (XYItemEntity) ce;
      XYDataset ds = e.getDataset();
      int seriesIdx = e.getSeriesIndex();
      int i = e.getItem();
      System.out.printf("Clicked on graph point: (%.2f, %.2f)\n",
                       ds.getX(seriesIdx, i), 
                       ds.getY(seriesIdx, i));
    }
  }  // end of reportCoords()


  private Point2D.Double getChartCoord(ChartMouseEvent ev)
  // https://stackoverflow.com/questions/1512112/jfreechart-get-mouse-coordinates
  {
    Point mousePt = ev.getTrigger().getPoint();  // use mouse event
    Point2D panelPt = chartPanel.translateScreenToJava2D(mousePt);

    Rectangle2D plotArea = chartPanel.getScreenDataArea();
    XYPlot plot = (XYPlot) chart.getPlot(); 

    ValueAxis xAxis = plot.getDomainAxis();
    RectangleEdge xEdge = plot.getDomainAxisEdge();
    double xChart = xAxis.java2DToValue(panelPt.getX(), plotArea, xEdge);
              // from JPanel back to chart coordinates

    ValueAxis yAxis = plot.getRangeAxis();
    RectangleEdge yEdge = plot.getRangeAxisEdge();
    double yChart = yAxis.java2DToValue(panelPt.getY(), plotArea, yEdge);

    return new Point2D.Double(xChart, yChart);
  }  // end of getChartCoord()

  // -------------------------------------

  public static void main(String[] args)
  {   new PlotFunctionEx();  } 


}  // end of PlotFunctionEx class
