package org.jzy3d.chart.controllers.mouse.selection;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import org.jzy3d.chart.Chart;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.maths.IntegerCoord2d;
import org.jzy3d.plot3d.rendering.canvas.ICanvas;
import org.jzy3d.plot3d.rendering.scene.Scene;
import org.jzy3d.plot3d.rendering.view.AWTView;
import org.jzy3d.plot3d.rendering.view.AbstractViewportManager;
import org.jzy3d.plot3d.rendering.view.Camera;
import org.jzy3d.plot3d.rendering.view.Renderer2d;
import org.jzy3d.plot3d.rendering.view.View;

public abstract class AWTAbstractMouseSelector implements MouseListener, MouseMotionListener {
    public AWTAbstractMouseSelector() {
        in = new IntegerCoord2d(-1, -1);
        last = new IntegerCoord2d(-1, -1);
        out = new IntegerCoord2d(-1, -1);
    }

    public void dispose() {
        unregister();
    }

    public void register(Chart chart) {
        this.chart = chart;
        this.chart.getCanvas().addMouseController(this);
        final ICanvas c = chart.getCanvas();
        selectionRenderer = initRenderer2d(c);
        if (chart.getView() instanceof AWTView)
            ((AWTView) this.chart.getView()).addRenderer2d(selectionRenderer);
    }

    public void unregister() {
        if (chart != null) {
            chart.getCanvas().removeMouseController(this);
            if (chart.getView() instanceof AWTView)
                ((AWTView) this.chart.getView()).removeRenderer2d(selectionRenderer);
        }
    }

    protected Renderer2d initRenderer2d(final ICanvas c) {
        return new Renderer2d() {
            @Override
            public void paint(Graphics g) {
                drawSelection((Graphics2D) g, c.getRendererWidth(), c.getRendererHeight());
                updateLast();
            }
        };
    }

    /*****************************************/

    protected abstract void processSelection(Scene scene, View view, int width, int height);

    /**
     * Drawing occurs in the selection renderer which as the dimension of the
     * GL2 scene viewport. In other words, one should not expect to draw on the
     * entire canvas if the GL2 scene viewport only covers a slice of the
     * screen. As an example, the following piece of code will draw a border
     * around the GL2 scene:
     * 
     * g2d.drawRect(1, 1, chart.getCanvas().getRendererWidth()-2,
     * chart.getCanvas().getRendererHeight()-2);
     * 
     * @see {@link AbstractViewportManager} and {@link Camera}
     */
    protected abstract void drawSelection(Graphics2D g, int width, int height);

    public abstract void clearLastSelection();

    protected boolean matchRectangleSelection(IntegerCoord2d in, IntegerCoord2d out, Coord3d projection, int width, int height) {
        return matchRectangleSelection(in, out, projection.x, projection.y, width, height);
    }

    /**
     * @param in
     *            The mouse selection start point
     * @param out
     *            The mouse selection end point
     * @param px
     *            A projected point x value
     * @param py
     *            A projected point y value
     * @param width
     *            The canvas dimension
     * @param height
     *            The canvas dimension
     * @return true if the point (px,py) is inside the (in,out) mouse selection
     *         of a canvas having dimensions (width, height)
     */
    protected boolean matchRectangleSelection(IntegerCoord2d in, IntegerCoord2d out, float px, float py, int width, int height) {
        float flipYProjection = height - py;

        // 4|3
        // ---
        // 2|1
        if (in.y < out.y) {
            if (in.x < out.x) {
                // ("1");
                if (in.x <= px && px <= out.x && in.y <= flipYProjection && flipYProjection <= out.y)
                    return true;
            } else {
                // ("2");
                if (out.x <= px && px <= in.x && in.y <= flipYProjection && flipYProjection <= out.y)
                    return true;
            }

        } else {
            if (in.x < out.x) {
                // ("3");
                if (in.x <= px && px <= out.x && out.y <= flipYProjection && flipYProjection <= in.y)
                    return true;
            } else {
                // ("4");
                if (out.x <= px && px <= in.x && out.y <= flipYProjection && flipYProjection <= in.y) // buggy
                    return true;
            }
        }
        return false;
    }

    protected void drawRectangle(Graphics2D g2d, IntegerCoord2d in, IntegerCoord2d out) {
        g2d.setColor(java.awt.Color.RED);
        if (in.y < out.y) {
            if (in.x < out.x)
                g2d.drawRect(in.x, in.y, out.x - in.x, out.y - in.y);
            else
                g2d.drawRect(out.x, in.y, in.x - out.x, out.y - in.y);
        } else {
            if (in.x < out.x)
                g2d.drawRect(in.x, out.y, out.x - in.x, in.y - out.y);
            else
                g2d.drawRect(out.x, out.y, in.x - out.x, in.y - out.y);
        }
    }

    /*****************************************/

    protected void startSelection(MouseEvent e) {
        in = xy(e);
        last = xy(e);
        out = xy(e);
    }

    public IntegerCoord2d xy(MouseEvent e) {
        return new IntegerCoord2d(x(e), y(e));
    }
    
    public int x(MouseEvent e) {
        return e.getX();
    }

    public int y(MouseEvent e) {
        return e.getY();
    }

    protected void dragSelection(MouseEvent e) {
        out.x = x(e);
        out.y = y(e);
        chart.render();
    }

    protected void releaseSelection(MouseEvent e) {
        out.x = x(e);
        out.y = y(e);

        processSelection(chart.getScene(), chart.getView(), chart.getCanvas().getRendererWidth(), chart.getCanvas().getRendererHeight());
        chart.render(); // calls draw selection
    }

    protected void rollOver(MouseEvent e) {

    }

    protected void updateLast() {
        last.x = out.x;
        last.y = out.y;
    }

    /*****************************************/

    @Override
    public void mousePressed(MouseEvent e) {
        dragging = true;
        startSelection(e);
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (dragging)
            releaseSelection(e);
        dragging = false;
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (dragging)
            dragSelection(e);
        // else
        // rollOver(e);
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        rollOver(e);
    }

    /*****************************************/

    public void mouseWheelMoved(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    /*****************************************/

    protected Chart chart;
    protected boolean dragging = false;
    protected IntegerCoord2d in;
    protected IntegerCoord2d out;
    protected IntegerCoord2d last;

    protected Renderer2d selectionRenderer;
}

 

Ads help maintain this website.