graph.eventhandlers.MyEditingGraphMousePlugin.java Source code

Java tutorial

Introduction

Here is the source code for graph.eventhandlers.MyEditingGraphMousePlugin.java

Source

/*
 * Copyright (c) 2003, the JUNG Project and the Regents of the University of
 * California All rights reserved.
 * 
 * This software is open-source under the BSD license; see either "license.txt"
 * or http://jung.sourceforge.net/license.txt for a description.
 * 
 */
package graph.eventhandlers;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Point2D;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.swing.JOptionPane;

import org.apache.commons.lang3.tuple.Pair;

import biologicalElements.Elementdeclerations;
import biologicalElements.Pathway;
import biologicalObjects.edges.BiologicalEdgeAbstract;
import biologicalObjects.nodes.BiologicalNodeAbstract;
import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationServer.Paintable;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.AbstractGraphMousePlugin;
import edu.uci.ics.jung.visualization.util.ArrowFactory;
import graph.ContainerSingelton;
import graph.GraphContainer;
import graph.GraphInstance;
import graph.gui.EdgeDialog;
import graph.gui.PetriNetVertexDialog;
import graph.gui.VertexDialog;
import gui.MainWindowSingleton;
import petriNet.ContinuousTransition;
import petriNet.Place;
import petriNet.Transition;

/**
 * A plugin that can create vertices, undirected edges, and directed edges using
 * mouse gestures.
 * 
 * @author Tom Nelson - RABA Technologies
 * 
 */
public class MyEditingGraphMousePlugin extends AbstractGraphMousePlugin
        implements MouseListener, MouseMotionListener {

    // HashMap vertexLocations;
    private BiologicalNodeAbstract startVertex;
    //private Point2D down;

    private CubicCurve2D rawEdge = new CubicCurve2D.Float();
    private Shape edgeShape;
    private Shape rawArrowShape;
    private Shape arrowShape;
    private Paintable edgePaintable;
    private Paintable arrowPaintable;
    private boolean edgeIsDirected;
    private GraphContainer con = ContainerSingelton.getInstance();

    private GraphInstance graphInstance = new GraphInstance();
    private Pathway pw;

    public MyEditingGraphMousePlugin() {
        this(InputEvent.BUTTON1_MASK);
    }

    /**
     * create instance and prepare shapes for visual effects
     * 
     * @param modifiers
     */
    public MyEditingGraphMousePlugin(int modifiers) {
        super(modifiers);
        rawEdge.setCurve(0.0f, 0.0f, 0.33f, 100, .66f, -50, 1.0f, 0.0f);
        rawArrowShape = ArrowFactory.getNotchedArrow(20, 16, 8);
        edgePaintable = new EdgePaintable();
        arrowPaintable = new ArrowPaintable();
    }

    /**
     * sets the vertex locations. Needed to place new vertices
     * 
     * @param vertexLocations
     */
    // public void setVertexLocations(HashMap vertexLocations) {
    // this.vertexLocations = vertexLocations;
    // }

    /**
     * overrided to be more flexible, and pass events with key combinations. The
     * default responds to both ButtonOne and ButtonOne+Shift
     */
    @Override
    public boolean checkModifiers(MouseEvent e) {
        return (e.getModifiers() & modifiers) != 0;
    }

    /**
     * If the mouse is pressed in an empty area, create a new vertex there. If
     * the mouse is pressed on an existing vertex, prepare to create an edge
     * from that vertex to another
     */
    public void mousePressed(MouseEvent e) {
        pw = graphInstance.getPathway();
        if (checkModifiers(e)) {

            final VisualizationViewer<BiologicalNodeAbstract, BiologicalEdgeAbstract> vv = (VisualizationViewer<BiologicalNodeAbstract, BiologicalEdgeAbstract>) e
                    .getSource();
            // final Point2D p = vv.inverseViewTransform(e.getPoint());
            // System.out.println("Points: "+e.getPoint().getX()+", "+e.getPoint().getY());
            final Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(e.getPoint());
            // System.out.println(e.getPoint()+ " "+p);
            // System.out.println("Points: "+p.getX()+", "+p.getY());
            // final Point2D p = e.getPoint();
            GraphElementAccessor<BiologicalNodeAbstract, BiologicalEdgeAbstract> pickSupport = vv.getPickSupport();
            // System.out.println("Click: "+p);
            // System.out.println("regul: "+e.getPoint());

            Iterator<BiologicalNodeAbstract> it = pw.getGraph().getAllVertices().iterator();
            // while(it.hasNext()){
            // System.out.println(pw.getGraph().getVertexLocation(it.next()));
            // }
            // System.out.println(pw.getGraph().getAllEdges().size());
            // System.out.println(pickSupport.g);

            BiologicalNodeAbstract vertex = null;

            vertex = (BiologicalNodeAbstract) pickSupport.getVertex(vv.getGraphLayout(), e.getPoint().getX(),
                    e.getPoint().getY());
            // System.out.println(vertex);

            if (vertex != null) { // get ready to make an edge
                // System.out.println(vertex);
                startVertex = vertex;
                super.down = e.getPoint();
                transformEdgeShape(down, down);
                vv.addPostRenderPaintable(edgePaintable);
                if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0) {
                    edgeIsDirected = true;
                    transformArrowShape(down, e.getPoint());
                    vv.addPostRenderPaintable(arrowPaintable);
                }
            } else { // make a new vertex
                Graph<BiologicalNodeAbstract, BiologicalEdgeAbstract> graph = vv.getGraphLayout().getGraph();
                //            BiologicalNodeAbstract newVertex = new BiologicalNodeAbstract(
                //                  "label", "name");
                // vertexLocations.put(newVertex, p);

                Layout<BiologicalNodeAbstract, BiologicalEdgeAbstract> layout = vv.getGraphLayout();

                // System.out.println("size V: "+layout.getGraph().getVertices().size());
                // System.out.println("size E: "+layout.getGraph().getEdges().size());

                // graph.addVertex(newVertex);
                /*
                 * Object key = (((AggregateLayout)
                 * layout).getDelegate()).getBaseKey(); Object datum = new
                 * Coordinates(vv.inverseTransform( e.getPoint()).getX(),
                 * vv.inverseTransform( e.getPoint()).getY());
                 * newVertex.setUserDatum(key, datum, new CopyAction.Clone());
                 */

                for (Iterator<BiologicalNodeAbstract> iterator = graph.getVertices().iterator(); iterator
                        .hasNext();) {
                    layout.lock(iterator.next(), true);

                }

                if (con.isPetriView()) {
                    // System.out.println("is petri");

                    PetriNetVertexDialog dialog = new PetriNetVertexDialog(con.getPetriNetEditingMode());
                    BiologicalNodeAbstract bna = dialog.getAnswer(p);
                    // System.out.println();
                    if (bna != null) {
                        // BiologicalNodeAbstract ba = new
                        // BiologicalNodeAbstract(
                        // answers[0], "", newVertex);
                        // ba.setBiologicalElement(answers[1]);
                        // ba.setCompartment(answers[2]);
                        // graphInstance.getPathway().addElement(ba);
                        // graph.addVertex(newVertex);

                        // vv.getModel().restart();
                        //System.out.println("update");
                        if (pw instanceof BiologicalNodeAbstract) {
                            bna.setParentNode((BiologicalNodeAbstract) pw);
                        }
                        MainWindowSingleton.getInstance().updateElementTree();
                        MainWindowSingleton.getInstance().updatePathwayTree();
                        //MainWindowSingelton.getInstance().updateAllGuiElements();
                        //MainWindowSingelton.getInstance().updateOptionPanel();
                        // MainWindowSingelton.getInstance()
                        // .updateTheoryProperties();

                        // Pathway pw = graphInstance.getPathway();

                    }

                } else {
                    // System.out.println("not petri");
                    VertexDialog dialog = new VertexDialog();
                    String[] answers = dialog.getAnswer();
                    if (answers != null) {

                        // BiologicalNodeAbstract ba = new
                        // BiologicalNodeAbstract(
                        // answers[0], "");
                        String name = answers[0];
                        String label = answers[0];
                        String element = answers[1];
                        String compartment = answers[2];
                        //                  newVertex.setBiologicalElement(answers[1]);
                        //                  newVertex.setCompartment(answers[2]);
                        // graphInstance.getPathway().addElement(newVertex);
                        // graph.addVertex(newVertex);

                        BiologicalNodeAbstract newVertex = pw.addVertex(name, label, element, compartment, p);
                        if (pw instanceof BiologicalNodeAbstract) {
                            newVertex.setParentNode((BiologicalNodeAbstract) pw);
                        }
                        //pw.addVertex(newVertex, p);
                        if (graph.getVertices().size() > 1) {
                            // System.exit(0);
                        }

                        // pw.getGraph().setVertexLocation(newVertex, p);
                        // layout.setLocation(newVertex, p);
                        // vv.getModel().restart();
                        MainWindowSingleton.getInstance().updateElementTree();
                        // MainWindowSingelton.getInstance()
                        // .updateTheoryProperties();

                        for (Iterator<BiologicalNodeAbstract> iterator = graph.getVertices().iterator(); iterator
                                .hasNext();) {
                            layout.lock(iterator.next(), false);
                        }

                    }

                }
                if (pw instanceof BiologicalNodeAbstract) {

                }
            }
            vv.repaint();
        }
    }

    /**
     * If startVertex is non-null, and the mouse is released over an existing
     * vertex, create an undirected edge from startVertex to the vertex under
     * the mouse pointer. If shift was also pressed, create a directed edge
     * instead.
     */
    public void mouseReleased(MouseEvent e) {
        pw = graphInstance.getPathway();
        if (checkModifiers(e)) {
            final VisualizationViewer<BiologicalNodeAbstract, BiologicalEdgeAbstract> vv = (VisualizationViewer) e
                    .getSource();
            //final Point2D p = vv.getRenderContext().getMultiLayerTransformer()
            //      .inverseTransform(e.getPoint());
            //int v = vv.getPickedVertexState().getPicked().size();
            //int edge = vv.getPickedEdgeState().getPicked().size();
            GraphElementAccessor<BiologicalNodeAbstract, BiologicalEdgeAbstract> pickSupport = vv.getPickSupport();
            // if (v > 0) {
            // System.out.println("release");
            final BiologicalNodeAbstract vertex = (BiologicalNodeAbstract) pickSupport
                    .getVertex(vv.getGraphLayout(), e.getPoint().getX(), e.getPoint().getY());
            if (vertex != null && startVertex != null) {

                // Pathway pw = graphInstance.getPathway();

                BiologicalNodeAbstract start = startVertex;// (BiologicalNodeAbstract)
                // pw
                // .getNodeByVertexID(startVertex.toString());
                BiologicalNodeAbstract end = vertex;// (BiologicalNodeAbstract)
                // pw
                // .getNodeByVertexID(vertex.toString());

                if (pw.isPetriNet() && !((start instanceof Place && end instanceof Transition)
                        || (start instanceof Transition && end instanceof Place)))
                    JOptionPane.showMessageDialog(MainWindowSingleton.getInstance(),
                            "In a petri net only Transition->Place and Place->Transition Relations are allowed!",
                            "Unallowed Operation...", JOptionPane.ERROR_MESSAGE);

                else if ((start instanceof ContinuousTransition && end instanceof Place
                        && ((Place) end).isDiscrete())
                        || (end instanceof ContinuousTransition && start instanceof Place
                                && ((Place) start).isDiscrete()))
                    JOptionPane.showMessageDialog(MainWindowSingleton.getInstance(),
                            "Relations between discrete Places and Continoues Transitions are not possible!",
                            "Unallowed Operation...", JOptionPane.ERROR_MESSAGE);
                else {
                    // Graph graph = vv.getGraphLayout().getGraph();
                    EdgeDialog dialog = new EdgeDialog(startVertex, vertex);
                    Pair<String[], BiologicalNodeAbstract[]> answer = dialog.getAnswer();
                    String[] answers = answer.getLeft();
                    BiologicalNodeAbstract[] nodes = answer.getRight();

                    if (answers != null) {
                        if (answers[2] != null && answers[2].toLowerCase().contains("inhibi")
                                && !(startVertex instanceof Place && vertex instanceof Transition))
                            JOptionPane.showMessageDialog(MainWindowSingleton.getInstance(),
                                    "Inhibitory Edges are only possible from Place to Transition!",
                                    "Unallowed Operation...", JOptionPane.ERROR_MESSAGE);
                        else {
                            String name = answers[0];
                            String label = answers[0];
                            String element = answers[2];
                            if (answers[2].toLowerCase().contains("inhibi")) {
                                element = Elementdeclerations.pnInhibitionEdge;
                            }
                            boolean directed = false;
                            if (answers[1].equals("directed_edge")) {
                                directed = true;
                            }

                            Set<BiologicalNodeAbstract> parentBNAs = new HashSet<BiologicalNodeAbstract>();
                            parentBNAs.addAll(nodes[0].getAllParentNodes());
                            parentBNAs.addAll(nodes[1].getAllParentNodes());
                            BiologicalEdgeAbstract bea = pw.addEdge(label, name, nodes[0], nodes[1], element,
                                    directed);
                            if (nodes[0] == startVertex && nodes[1] == vertex) {
                                pw.addEdgeToView(bea, false);
                            } else {
                                BiologicalEdgeAbstract clone = bea.clone();
                                clone.setFrom(startVertex);
                                clone.setTo(vertex);
                                pw.addEdgeToView(clone, false);
                            }
                        }
                    }
                }
            }
            vv.repaint();
            startVertex = null;
            down = null;
            edgeIsDirected = false;
            vv.removePostRenderPaintable(edgePaintable);
            vv.removePostRenderPaintable(arrowPaintable);
        }
    }

    /**
     * If startVertex is non-null, stretch an edge shape between startVertex and
     * the mouse pointer to simulate edge creation
     */
    public void mouseDragged(MouseEvent e) {
        if (checkModifiers(e)) {
            if (startVertex != null) {
                transformEdgeShape(down, e.getPoint());
                if (edgeIsDirected) {
                    transformArrowShape(down, e.getPoint());
                }
            }
            VisualizationViewer<BiologicalNodeAbstract, BiologicalEdgeAbstract> vv = (VisualizationViewer<BiologicalNodeAbstract, BiologicalEdgeAbstract>) e
                    .getSource();
            vv.repaint();
        }
    }

    /**
     * code lifted from PluggableRenderer to move an edge shape into an
     * arbitrary position
     */
    private void transformEdgeShape(Point2D down, Point2D out) {
        float x1 = (float) down.getX();
        float y1 = (float) down.getY();
        float x2 = (float) out.getX();
        float y2 = (float) out.getY();

        AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);

        float dx = x2 - x1;
        float dy = y2 - y1;
        float thetaRadians = (float) Math.atan2(dy, dx);
        xform.rotate(thetaRadians);
        float dist = (float) Math.sqrt(dx * dx + dy * dy);
        xform.scale(dist / rawEdge.getBounds().getWidth(), 1.0);
        edgeShape = xform.createTransformedShape(rawEdge);
    }

    private void transformArrowShape(Point2D down, Point2D out) {
        float x1 = (float) down.getX();
        float y1 = (float) down.getY();
        float x2 = (float) out.getX();
        float y2 = (float) out.getY();

        AffineTransform xform = AffineTransform.getTranslateInstance(x2, y2);

        float dx = x2 - x1;
        float dy = y2 - y1;
        float thetaRadians = (float) Math.atan2(dy, dx);
        xform.rotate(thetaRadians);
        arrowShape = xform.createTransformedShape(rawArrowShape);
    }

    /**
     * Used for the edge creation visual effect during mouse drag
     */
    class EdgePaintable implements Paintable {

        public void paint(Graphics g) {
            if (edgeShape != null) {
                Color oldColor = g.getColor();
                g.setColor(Color.black);
                ((Graphics2D) g).draw(edgeShape);
                g.setColor(oldColor);
            }
        }

        public boolean useTransform() {
            return false;
        }
    }

    /**
     * Used for the directed edge creation visual effect during mouse drag
     */
    class ArrowPaintable implements Paintable {

        public void paint(Graphics g) {
            if (arrowShape != null) {
                Color oldColor = g.getColor();
                g.setColor(Color.black);
                ((Graphics2D) g).fill(arrowShape);
                g.setColor(oldColor);
            }
        }

        public boolean useTransform() {
            return false;
        }
    }

    public void mouseClicked(MouseEvent e) {
        // System.out.println("click: ");
        // System.out.println(e.getClickCount());
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mouseMoved(MouseEvent e) {
    }
}