claczny / VizBin

Repository of our application for human-augmented binning
27 stars 14 forks source link

Integration of JFreeChart #5

Closed claczny closed 9 years ago

claczny commented 9 years ago

JFreeChart appears to be solving many of the other issues (e.g, https://github.com/claczny/VizBin/issues/3 or https://github.com/claczny/VizBin/issues/1). Here is our first attempt to use a scatter plot in combination with the ability to draw a polygon:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
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;
import org.jfree.ui.RectangleEdge;
// NEW
import org.jfree.chart.annotations.XYPolygonAnnotation;
import org.jfree.chart.axis.ValueAxis;

import java.util.ArrayList; 

public class MouseMarkerDemo extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public MouseMarkerDemo(String title) {
        super(title);
        JPanel chartPanel = createDemoPanel();
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        setContentPane(chartPanel);
    }

    private final static class  MouseMarker extends MouseAdapter{
        private ArrayList<Double> edges = new ArrayList<Double>();
        private XYPolygonAnnotation a1;
        private final XYPlot plot;
        private final JFreeChart chart;
        private final ChartPanel panel;

        public MouseMarker(ChartPanel panel) {
            this.panel = panel;
            this.chart = panel.getChart();
            this.plot = chart.getXYPlot();
            this.plot.setDomainGridlinesVisible(false);
            this.plot.setRangeGridlinesVisible(false);
            this.plot.setBackgroundPaint(Color.white);

        }

        private void clearMarker(){
            if( a1 != null)
            {
                plot.removeAnnotation(a1);
            }
        }
        private void updateMarker(){
            Stroke stroke1 = new BasicStroke(2.0f);
            if (a1 != null)
            {
                plot.removeAnnotation(a1);
            }
            Double[] edgesArr = new Double[edges.size()];
            edgesArr = edges.toArray(edgesArr);
            double[] tempArray = new double[edges.size()];
            int i = 0;
            for(Double d : edges) {
              tempArray[i] = (double) d;
              i++;
            }
            a1 = new XYPolygonAnnotation(tempArray, stroke1, Color.red, new Color(200, 200, 200, 130));
            plot.addAnnotation(a1);
        }

        public void mouseClicked(MouseEvent e) {
            if(SwingUtilities.isMiddleMouseButton(e)){
                int selectedValue = JOptionPane.showConfirmDialog(null,"Click 'Yes' to export current selection.\nClick 'No' to continue selecting.\nClick 'Cancel' to discard current selection.", "What to do with current selection?", JOptionPane.YES_NO_CANCEL_OPTION);
                switch(selectedValue)
                {
                case JOptionPane.YES_OPTION:    System.out.println("YES");
                                    break;
                case JOptionPane.NO_OPTION: System.out.println("NO");
                                break;
                default:    edges.clear();
                            clearMarker();
                            break;
                }
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if(SwingUtilities.isLeftMouseButton(e)){
                // Motivated by http://www.jfree.org/phpBB2/viewtopic.php?p=54140
                int mouseX = e.getX();
                int mouseY = e.getY();
                // DEBUG
                //System.out.println("x = " + mouseX + ", y = " + mouseY);       
                Point2D p = panel.translateScreenToJava2D(
                        new Point(mouseX, mouseY));
                XYPlot plot = (XYPlot) chart.getPlot();
                ChartRenderingInfo info = panel.getChartRenderingInfo();
                Rectangle2D dataArea = info.getPlotInfo().getDataArea();

                ValueAxis domainAxis = plot.getDomainAxis();
                RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
                ValueAxis rangeAxis = plot.getRangeAxis();
                RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
                double chartX = domainAxis.java2DToValue(p.getX(), dataArea,
                        domainAxisEdge);
                double chartY = rangeAxis.java2DToValue(p.getY(), dataArea,
                        rangeAxisEdge);
                // DEBUG
                //System.out.println("Chart: x = " + chartX + ", y = " + chartY);
                edges.add(chartX);
                edges.add(chartY);

                System.out.println(edges.size());
                updateMarker();
            }
        }
    }

    private static XYDataset createDataset() {
        XYSeriesCollection dataset = new XYSeriesCollection();
        /** A constant for the number of items in the sample dataset. */
        int COUNT = 5000;

        XYSeries dataXYSeries = new XYSeries("Data");
        for (int i = 0; i < COUNT; i++) {
            float x = (float) i;
            float y = (float) Math.random() * COUNT;
            dataXYSeries.add(x, y);
        }
        dataset.addSeries(dataXYSeries);
        return dataset;

    }

    private static JFreeChart createChart(XYDataset dataset) {

        JFreeChart chart = ChartFactory.createScatterPlot(
            "Mouse Marker",
            "X",
            "Y",
            dataset,
            PlotOrientation.VERTICAL,
            true,
            true,
            false
        );
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setDomainPannable(true);
        plot.setRangePannable(true);
        XYLineAndShapeRenderer renderer
                = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setBaseShapesVisible(true);
        renderer.setBaseShapesFilled(true);
        return chart;
    }

    public static JPanel createDemoPanel() {
        final JFreeChart chart = createChart(createDataset());
        final ChartPanel panel = new ChartPanel(chart);
        panel.setRangeZoomable(true);
        panel.setDomainZoomable(true);
        panel.setMouseWheelEnabled(true);
        panel.addMouseListener(new MouseMarker(panel));
        return panel;
    }

    public static void main(String[] args) {
        MouseMarkerDemo demo = new MouseMarkerDemo("JFreeChart: MouseMarkerDemo.java");
        demo.pack();
        demo.setVisible(true);
    }

}

And the resulting plot looks like this bla

Since the edges of the polygon seem to have the right coordinates relative to the actual points, it should be feasible to integrate it with our current solution for selection points contained within a polygon.

claczny commented 9 years ago

Sadly, this seems to be pretty slow when drawing >= 50k points. An alternative would be FastScatterPlot which is even fast for >=500k points, but the appearance is not nice, s.a. http://jakob.digidop.net/blog/?p=292 -> "The fast scatter plot is easily created but cannot change the data item shape size and color, it is always 1×1 pixel. The data format is a 2d float array".

claczny commented 9 years ago

An example of using FastScatterPlot with 500k points:


/* ===========================================================
 * JFreeChart : a free chart library for the Java(tm) platform
 * ===========================================================
 *
 * (C) Copyright 2000-2004, by Object Refinery Limited and Contributors.
 *
 * Project Info:  http://www.jfree.org/jfreechart/index.html
 *
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 *
 * ------------------------
 * FastScatterPlotDemo.java
 * ------------------------
 * (C) Copyright 2002-2004, by Object Refinery Limited and Contributors.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   -;
 *
 * $Id: FastScatterPlotDemo.java,v 1.13 2004/04/26 19:11:54 taqua Exp $
 *
 * Changes (from 29-Oct-2002)
 * --------------------------
 * 29-Oct-2002 : Added standard header and Javadocs (DG);
 * 12-Nov-2003 : Enabled zooming (DG);
 *
 */

//package org.jfree.chart.demo;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Paint;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Rectangle2D;

import javax.swing.JOptionPane;

import org.jfree.chart.ChartColor;
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.entity.ChartEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.plot.DefaultDrawingSupplier;
import org.jfree.chart.plot.FastScatterPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.util.ShapeUtilities;

/**
 * A demo of the fast scatter plot.
 *
 */
public class FastScatterPlotDemo extends ApplicationFrame {

    /** A constant for the number of items in the sample dataset. */
    private static final int COUNT = 500000;

    /** The data. */
    private float[][] data = new float[2][COUNT];

    private final static class ThisMouseListener implements ChartMouseListener{

        @Override
        public void chartMouseClicked(ChartMouseEvent event) {
            int x = event.getTrigger().getX();
            int y = event.getTrigger().getY();

            System.out.println("X :" + x + " Y : " + y);

            ChartEntity entity = event.getEntity();
            if(entity != null && (entity instanceof XYItemEntity)){
                XYItemEntity item = (XYItemEntity)entity;
            }
            new JOptionPane().showMessageDialog(null, "Hello", "Mouse Clicked event", JOptionPane.OK_OPTION);
        }

        @Override
        public void chartMouseMoved(ChartMouseEvent arg0) {
            // TODO Auto-generated method stub

        }
    } 

    /**
     * Creates a new fast scatter plot demo.
     *
     * @param title  the frame title.
     */
    public FastScatterPlotDemo(final String title) {

        super(title);
        populateData();
        final NumberAxis domainAxis = new NumberAxis("X");
        domainAxis.setAutoRangeIncludesZero(false);
        domainAxis.setTickMarksVisible(false);
        domainAxis.setTickLabelsVisible(false);

        final NumberAxis rangeAxis = new NumberAxis("Y");
        rangeAxis.setAutoRangeIncludesZero(false);
        rangeAxis.setTickMarksVisible(false);
        rangeAxis.setTickLabelsVisible(false);
        final FastScatterPlot plot = new FastScatterPlot(this.data, domainAxis, rangeAxis);
        plot.setDomainGridlinesVisible(false);
        plot.setRangeGridlinesVisible(false);
        //XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer( );
        //renderer.setSeriesPaint( 0 , Color.BLUE );
        //Shape cross = ShapeUtilities.createDiagonalCross(3, 1);
        //Shape[] shape_arr = new Shape[1];
        //shape_arr[0] = cross;

        /*
        Paint[] paintSequence;
        paintSequence =  new Paint[] {
                Color.BLUE};

        final Shape[] shapes = new Shape[1];
        int[] xpoints;
        int[] ypoints;

        // right-pointing triangle
        xpoints = new int[] {-100, 10, -100};
        ypoints = new int[] {-100, 0, 100};
        shapes[0] = new Polygon(xpoints, ypoints, 3);

        DefaultDrawingSupplier def_draw_supplier = new DefaultDrawingSupplier(paintSequence,
                DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
                shapes) ;
        */
        //plot.setDrawingSupplier(new ChartDrawingSupplier(), true);

        final Paint[] paintArray;
        // create default colors but modify some colors that are hard to see
        paintArray = ChartColor.createDefaultPaintArray();
        paintArray[0] = Color.GREEN;

        final JFreeChart chart = new JFreeChart("", plot);
        plot.setDrawingSupplier(new DefaultDrawingSupplier(
                paintArray,
                DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE));

        //        chart.setLegend(null);

        // force aliasing of the rendered content..
        chart.getRenderingHints().put
            (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        final ChartPanel panel = new ChartPanel(chart, true);
        panel.setPreferredSize(new java.awt.Dimension(500, 500));
        panel.setMouseWheelEnabled(true);

        panel.setMinimumDrawHeight(10);
        panel.setMaximumDrawHeight(2000);
        panel.setMinimumDrawWidth(20);
        panel.setMaximumDrawWidth(2000);

        setContentPane(panel);

    }

    // ****************************************************************************
    // * JFREECHART DEVELOPER GUIDE                                               *
    // * The JFreeChart Developer Guide, written by David Gilbert, is available   *
    // * to purchase from Object Refinery Limited:                                *
    // *                                                                          *
    // * http://www.object-refinery.com/jfreechart/guide.html                     *
    // *                                                                          *
    // * Sales are used to provide funding for the JFreeChart project - please    * 
    // * support us so that we can continue developing free software.             *
    // ****************************************************************************

    /**
     * Populates the data array with random values.
     */
    private void populateData() {

        for (int i = 0; i < this.data[0].length; i++) {
            final float x = (float) i + 100000;
            this.data[0][i] = x;
            this.data[1][i] = 100000 + (float) Math.random() * COUNT;
        }

    }

    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(final String[] args) {

        final FastScatterPlotDemo demo = new FastScatterPlotDemo("Fast Scatter Plot Demo");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

    }

}
claczny commented 9 years ago

ExtendedFastScatterPlot to plot easily around 500k points with decent rendering performance and allowing different sizes, colors, and shapes to be used. Not sure if "picking" is possible, i.e., to click and place polygon edges for selections of points. The MouseListener seems to work since the mouse wheel can be used for zooming as well as mouseDragged to select a particular zooming region.

//package jfreeexample;

import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;

import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.FastScatterPlot;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.ui.RectangleEdge;

public class ExtendedFastScatterPlot extends FastScatterPlot {

   /**
    *
    */
   private static final long    serialVersionUID    = 1L;

   int[] sizes;
   Paint[] colors;
   int[] shapes;

   public ExtendedFastScatterPlot(float[][] data, NumberAxis domainAxis, NumberAxis rangeAxis, int[] sizes, Paint[] colors, int[] shapes) {
       super(data,domainAxis,rangeAxis);
       this.sizes = sizes;
       this.colors = colors;
       this.shapes = shapes;
   }

   @Override
   public void render(Graphics2D g2, Rectangle2D dataArea, PlotRenderingInfo info, CrosshairState crosshairState) {
       //g2.setPaint(Color.BLUE);

       if (this.getData() != null) {
           for (int i = 0; i < this.getData()[0].length; i++) {
               float x = this.getData()[0][i];
               float y = this.getData()[1][i];
               int size = this.sizes[i];
               int transX = (int) this.getDomainAxis().valueToJava2D(x, dataArea, RectangleEdge.BOTTOM);
               int transY = (int) this.getRangeAxis().valueToJava2D(y, dataArea, RectangleEdge.LEFT);
               g2.setPaint(this.colors[i]);
               switch( this.shapes[i] )
               {
                case 0: g2.fillRect(transX, transY, size, size);
                        break;
                case 1: g2.fillOval(transX, transY, size, size);
                        break;
                default:int[] xSin = {transX-size, transX, transX+size};
                        int[] ySin = {transY, transY-size, transY};
                        g2.fillPolygon(xSin, ySin, xSin.length);
                        break;
               }
           }
       }
   }
}

And an associated demo FastScatterPlotDemo

import java.awt.Color;
import java.awt.Paint;
import java.awt.RenderingHints;

import javax.swing.JOptionPane;

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.entity.ChartEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.plot.FastScatterPlot;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

/**
 * A demo of the fast scatter plot.
 *
 */
public class FastScatterPlotDemo extends ApplicationFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    /** A constant for the number of items in the sample dataset. */
    private static final int COUNT = 200000;

    /** The data. */
    private float[][] data = new float[2][COUNT];

    /** The sizes */
    int[] sizes = new int[COUNT];
    Paint[] colors = new Paint[COUNT];
    int[] shapes = new int[COUNT];

    private final static class ThisMouseListener implements ChartMouseListener {

        @Override
        public void chartMouseClicked(ChartMouseEvent event) {
            int x = event.getTrigger().getX();
            int y = event.getTrigger().getY();

            System.out.println("X :" + x + " Y : " + y);

            ChartEntity entity = event.getEntity();
            if (entity != null && (entity instanceof XYItemEntity)) {
                XYItemEntity item = (XYItemEntity) entity;
            }
            new JOptionPane().showMessageDialog(null, "Hello",
                    "Mouse Clicked event", JOptionPane.OK_OPTION);
        }

        @Override
        public void chartMouseMoved(ChartMouseEvent arg0) {
            // TODO Auto-generated method stub

        }
    }

    /**
     * Creates a new fast scatter plot demo.
     *
     * @param title
     *            the frame title.
     */
    public FastScatterPlotDemo(final String title) {

        super(title);
        populateData();
        final NumberAxis domainAxis = new NumberAxis("X");
        domainAxis.setAutoRangeIncludesZero(false);
        domainAxis.setTickMarksVisible(false);
        domainAxis.setTickLabelsVisible(false);

        final NumberAxis rangeAxis = new NumberAxis("Y");
        rangeAxis.setAutoRangeIncludesZero(false);
        rangeAxis.setTickMarksVisible(false);
        rangeAxis.setTickLabelsVisible(false);

        final FastScatterPlot plot = new ExtendedFastScatterPlot(this.data, domainAxis, rangeAxis,
                this.sizes, this.colors, this.shapes);
        plot.setDomainGridlinesVisible(false);
        plot.setRangeGridlinesVisible(false);
        final JFreeChart chart = new JFreeChart("", plot);

        // force aliasing of the rendered content..
        chart.getRenderingHints().put(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        final ChartPanel panel = new ChartPanel(chart, true);
        panel.setPreferredSize(new java.awt.Dimension(800, 800));
        panel.setMouseWheelEnabled(true);

        panel.setMinimumDrawHeight(10);
        panel.setMaximumDrawHeight(2000);
        panel.setMinimumDrawWidth(20);
        panel.setMaximumDrawWidth(2000);

        setContentPane(panel);

    }

    /**
     * Populates the data array with random values.
     */
    private void populateData() {
        for (int i = 0; i < this.data[0].length; i++) {
            final float x = (float) i + 100000;
            this.data[0][i] = x;
            this.data[1][i] = 100000 + (float) Math.random() * COUNT;
            this.sizes[i] = (int) Math.ceil(Math.log(i/1000));
            // Substitute the following with something nicer, i.e., an enum or such.
            int shape_choice = (i % 3);
            switch( shape_choice )
            {
            case 0: this.colors[i] = Color.BLACK;
                    this.shapes[i] = 0;
                    break;
            case 1: this.colors[i] = Color.BLUE;
                    this.shapes[i] = 1;
                    break;
            default: this.colors[i] = Color.RED;
                    this.shapes[i] = 2;
            }
        }
    }

    /**
     * Starting point for the demonstration application.
     *
     * @param args
     *            ignored.
     */
    public static void main(final String[] args) {
        final FastScatterPlotDemo demo = new FastScatterPlotDemo(
                "Fast Scatter Plot Demo");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}
claczny commented 9 years ago

Just tried to use addAnnotation() and removeAnnotation() as done with the XYPlot at the top. Not to much of a surprise, this did NOT work since ExtendedFastScatterPlot is NOT derived from XYPlot for performance reasons. Probably the selection polygon has then to be drawn similar to how it is done now in VizBin. This is not bad news per se, since the functionality to add/remove polygon edges is actually quite a nice feature and seems not readily supported by XYPolygonAnnotation.

However, the open question is HOW to draw the polygon into the current visualization and HOW to preserve the zooming functionality, i.e., the polygon must "follow" when zooming...

claczny commented 9 years ago
    private final static class  MouseMarker extends MouseAdapter{
        private ArrayList<Double> edges = new ArrayList<Double>();
        private XYPolygonAnnotation a1;
        private final FastScatterPlot plot;
        private final JFreeChart chart;
        private final ChartPanel panel;

        public MouseMarker(ChartPanel panel) {
            this.panel = panel;
            this.chart = panel.getChart();
            this.plot = (FastScatterPlot) chart.getPlot();
            //this.plot.setDomainGridlinesVisible(false);
            //this.plot.setRangeGridlinesVisible(false);
            this.plot.setBackgroundPaint(Color.white);

        }

        /*
        private void clearMarker(){
            if( a1 != null)
            {
                plot.removeAnnotation(a1);
            }
        }
        private void updateMarker(){
            Stroke stroke1 = new BasicStroke(2.0f);
            if (a1 != null)
            {
                plot.removeAnnotation(a1);
            }
            Double[] edgesArr = new Double[edges.size()];
            edgesArr = edges.toArray(edgesArr);
            double[] tempArray = new double[edges.size()];
            int i = 0;
            for(Double d : edges) {
              tempArray[i] = (double) d;
              i++;
            }
            a1 = new XYPolygonAnnotation(tempArray, stroke1, Color.red, new Color(200, 200, 200, 130));
            plot.addAnnotation(a1);
        }
        */

        private void printEdges(){
            System.out.println("Edges size: " + edges.size());
            for (int i = 0; i < edges.size(); ){
                Double x = edges.get(i);
                ++i;
                Double y = edges.get(i);
                ++i;
                System.out.println("(" + x + "," + y + ")");
            }
        }

        public void mouseClicked(MouseEvent e) {
            // Put edges of the polygon for selecting a set of points in 2D
            if(SwingUtilities.isLeftMouseButton(e)){
                // Motivated by http://www.jfree.org/phpBB2/viewtopic.php?p=54140
                int mouseX = e.getX();
                int mouseY = e.getY();
                // DEBUG
                //System.out.println("x = " + mouseX + ", y = " + mouseY);       
                Point2D p = panel.translateScreenToJava2D(
                        new Point(mouseX, mouseY));
                FastScatterPlot plot = (FastScatterPlot) chart.getPlot();
                ChartRenderingInfo info = panel.getChartRenderingInfo();
                Rectangle2D dataArea = info.getPlotInfo().getDataArea();

                ValueAxis domainAxis = plot.getDomainAxis();
                //RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
                ValueAxis rangeAxis = plot.getRangeAxis();
                //RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
                double chartX = domainAxis.java2DToValue(p.getX(), dataArea,
                        RectangleEdge.BOTTOM);
                double chartY = rangeAxis.java2DToValue(p.getY(), dataArea,
                        RectangleEdge.LEFT);
                // DEBUG
                System.out.println("Mouse: x = " + mouseX + ", y = " + mouseY);
                System.out.println("Chart: x = " + chartX + ", y = " + chartY);
                edges.add(chartX);
                edges.add(chartY);

                // DEBUG
                //System.out.println(edges.size());
                //updateMarker();
            }
            // Open Export-Menu
            if(SwingUtilities.isMiddleMouseButton(e)){
                int selectedValue = JOptionPane.showConfirmDialog(null,"Click 'Yes' to export current selection.\nClick 'No' to continue selecting.\nClick 'Cancel' to discard current selection.", "What to do with current selection?", JOptionPane.YES_NO_CANCEL_OPTION);
                switch(selectedValue)
                {
                case JOptionPane.YES_OPTION:    System.out.println("YES");
                                                printEdges();
                                    break;
                case JOptionPane.NO_OPTION: System.out.println("NO");
                                break;
                default:    edges.clear();
                            //clearMarker();
                            break;
                }
            }
        }
    }
claczny commented 9 years ago

Integrated in 49a22b9d8b6e0e117aece33b1852568807c03afa.