Search code examples
javagraphstream

Collapsing nodes in Graphstream


Is there anyway I can collapse a certain number of nodes in a graph using graphstream? I have tried adding ui.hide attribute,but that is not what I want. Ideally I would want a + sign on the first node that is collapsed and then when I click on the + sign then the rest of the nodes should appear. Can anyone help me with this? TIA


Solution

  • Not exactly sure I got it right, but I guest you want to fold/unfold a tree, a bit like a package/file system view on a IDE (eclipse, netbean...).

    If I am right then there are some tricks that can help you do that in GraphStream.

    • The ui.hide attribute, as you mentioned, used on nodes and edges.
    • The layout.frozen attribute that blocks the layout algorithm on the selected node and allows you to control its position. You may want to set the position of the "folded" right at the clicked node's position in order to give the "folding" visual feeling.
    • The ui.class attribute that allows you to assign CSS classes to nodes, and thus give a particular style to node folded/unfolded nodes (e.g. add a "plus" sign icon).
    • In order to get notified when a node is clicked you need to retrieve a ProxyPipe from the viewer and listen to modifications coming from that viewer. especially the ui.clicked attribute that is automatically assigned to nodes that get clicked.

      ProxyPipe fromViewer = viewer.newViewerPipe();
      fromViewer.addSink(new SinkAdapter(){
          @Override
          public void nodeAttributeAdded(String sourceId, long timeId, String nodeId, String attribute, Object value) {
              if(attribute.equals("ui.clicked")){
                  // Being notified that a node was clicked...
              }
          }
      });
      
    • Finally, you have to decide which node to collapse. I guess a simple iterator rooted at the clicked node is what you need.

      // let n be the clicked node...
      Iterator<Node> it = n.getBreadthFirstIterator(true);
      while(it.hasNext()){
          Node m  =  it.next();
          for(Edge e : m.getLeavingEdgeSet()) {
              e.setAttribute("ui.hide");
          }
          if(n != m) {
              m.setAttribute("ui.hide");
          }
      }
      

    Then the Layout algorithm will be troublesome regarding nodes positions and stabilisation limits but that not really important.

    You'll find a working example in this gist where clicked nodes collapse their sub-trees :

    https://gist.github.com/pigne/2d4c0cbe8583f8a8f6b03309becaff3f

    Here is an example tree graph before collapsing sub-trees: Tree graph before collapsing sub-trees

    Same graph with node 13 and 15 collapsed after clicking: Same graph with node 13 and 15 collapsed