Search code examples
javamouseeventgraphstream

Retrieving node/edge with mouse events


I'm following the official GraphStream tutorial, and as the title suggest - I'm trying to get node's by clicking on it.

this is my code so far:

import org.graphstream.graph.*;
import org.graphstream.graph.implementations.*;
    
public static void main(String args[]) {
    Graph graph = new MultiGraph("Tutorial 1");
    graph.setStrict(false);
    graph.setAutoCreate( true );

    graph.addNode("A").setAttribute("xy", 1, 1);
    graph.addNode("B").setAttribute("xy", 5, 5);
    graph.addNode("C").setAttribute("xy", 1, 8);

    graph.addEdge("AB", "A", "B");
    graph.addEdge("BC", "B", "C");
    graph.addEdge("CA", "C", "A");

    Viewer viewer = graph.display();
    viewer.disableAutoLayout();
}

Is there an efficient way to do it?


Solution

  • So here is the solution I have found:

    First I've written a new MouseManager to override the default one, and I've used the function findNodeOrSpriteAt(int x, int y) to "catch" the clicked node:

    public class CustomMouseManager implements MouseManager {
    
        protected View view;
        protected GraphicGraph graph;
    
        @Override
        public void init(GraphicGraph graph, View view) {
            this.graph = graph;
            this.view = view;
            view.addMouseListener(this);
            view.addMouseMotionListener(this);
        }
    
        @Override
        public void release() {
            view.removeMouseListener(this);
            view.removeMouseMotionListener(this);
        }
    
        @Override
        public void mouseClicked(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
    
            GraphicElement node = view.findNodeOrSpriteAt(x, y);
    
            if(node != null){
                System.out.println("Node " + node.getId() + ": (" + x + "," + y + ")");
            }
        }
        // here you should implement the rest of the MouseManager's methods (mouseDragged, mouseReleased, etc.)
    

    After that, I've added the new custom MouseManager to my Viewer with setMouseManager()

    public static void main(String args[]) {
        Graph graph = new MultiGraph("Tutorial 1");
        graph.setStrict(false);
        graph.setAutoCreate( true );
    
        graph.addNode("A").setAttribute("xy", 1, 1);
        graph.addNode("B").setAttribute("xy", 5, 5);
        graph.addNode("C").setAttribute("xy", 1, 8);
    
        graph.addEdge("AB", "A", "B");
        graph.addEdge("BC", "B", "C");
        graph.addEdge("CA", "C", "A");
    
        Viewer viewer = graph.display();
        viewer.disableAutoLayout();
        viewer.getDefaultView().setMouseManager(new MyMouseManager());
    }
    

    this code works for nodes but I'm still not sure what is the correct way to get an edge by clicking on it.

    However, a naive solution might be to get the mouse-click's coordinates and then iterate the nodes and check if those coordinates are between 2 nodes.

    another (faster) solution is - attaching sprites to the edges:

    Sprite s1;
    s1.attachToEdge("AB");
    

    By doing this, one can retrieve the edge's sprite with the function findNodeOrSpriteAt(int x, int y) that I've used to retrieve nodes.