Cytoscape for Vaadin Flow / Graph / Network

Cytoscape Addon for Vaadin 14+ (based on npm)

This Vaadin addon wrappes https://js.cytoscape.org/ in a java component. It does not cover all features, but most of them an showcases how you can extent it on your own.

This addon uses currently to cytoscape extensions:

Links

Running the demo application

Using jetty:run or by running the de.xinblue.cytoscape.View class (in src/text/java) directly from your IDE.

Examples

public class View extends Div {
	
	
	private VerticalLayout dashboard=new VerticalLayout();
	private HorizontalLayout hl1=new HorizontalLayout();
	private Label output=new Label();
	private Label rawOutput=new Label();
	private VerticalLayout buttonLayout=new VerticalLayout();
	private VerticalLayout nodeList=new VerticalLayout();
	
	private void createDashboard() {
		    H1 headline=new H1("Cytoscape Vaadin Addon");
		    dashboard.add(headline);
		    Label headlineLabel=new Label("Use the mousewheel to zoom. Drag icons on the canvas to add nodes. Tap (left mosue down) on a node/edge to access the context menu. Click on the edge handle (blue dot on mouse over) to draw edges between nodes.");
		    dashboard.add(headlineLabel);

		    hl1.setWidth("100%");
			dashboard.add(hl1);
			dashboard.add(output);
			dashboard.add(rawOutput);
			
		    add(dashboard);

	}
	
	private void setOutput(String s) {
		output.setText(s);
	}
	
	private void setRawOutput(String s) {
		rawOutput.setText(s);
	}
	
	private void processContextMenu(Cytoscape cy,String s) {
		
		ObjectMapper mapper = new ObjectMapper();
        JsonNode actualObj;
		try {
			actualObj = mapper.readTree(s);
			if (actualObj.get("action").asText().equalsIgnoreCase("editnode") ) {
				setOutput("Contextmenu Edit Node");
			} else if (actualObj.get("action").asText().equalsIgnoreCase("deletenode") ) {
				setOutput("Contextmenu Delete Node");
				cy.deleteNode(actualObj.get("id").asText());
			} else if (actualObj.get("action").asText().equalsIgnoreCase("showedge") ) {
				setOutput("Contextmenu Edit Edge");
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		} 
	}
	
	
	private void createButtonLayout(Cytoscape cy) {
		    
		    
		    Button b1=new Button("Load graph");
		    b1.addClickListener( e -> {cy.loadGraph(cy.getDemoGraph2());});
		    buttonLayout.add(b1);
		    
		    Button b2=new Button("Export graph");
		    b2.addClickListener( e -> {cy.exportGraph().then(e2 -> {setOutput("Export Graph");setRawOutput(e2.toJson());});});
		    buttonLayout.add(b2);
		    
		    Button b3=new Button("Center graph");
		    b3.addClickListener( e -> {cy.centerGraph();});
		    buttonLayout.add(b3);
		    
		    Button b4=new Button("Get selected elements");
		    b4.addClickListener( e -> {cy.getSelectedElements().then(e2 -> {setOutput("Export Graph");setRawOutput(e2.toJson());});});
		    buttonLayout.add(b4);
		    
		    Button b5=new Button("Add predefined nodes and edges dynamically");
		    b5.addClickListener( e -> {
		    	
		    	Node node1=new Node();
				node1.getPosition().put("x", 100);
				node1.getPosition().put("y", 100);	
				node1.getData().put("id", "x1");
				node1.getData().put("myname", "martin");

		    	Node node2=new Node();
				node2.getPosition().put("x", 200);
				node2.getPosition().put("y", 200);	
				node2.getData().put("id", "x2");

				Edge edge1=new Edge();
				edge1.getData().put("id", "x1-x2");
				edge1.getData().put("source", "x1");
				edge1.getData().put("target", "x2");

				cy.addNode(node1).then(e1 -> cy.addNode(node2).then(e3 -> cy.addEdge(edge1)));
		    });
		    buttonLayout.add(b5);
		    
		    Button b6=new Button("Clear all");
		    b6.addClickListener( e -> {cy.deleteAll();});
		    buttonLayout.add(b6);
				
		    
		    Button b7=new Button("Delete selected nodes");
		    b7.addClickListener( e -> {
		    	cy.getSelectedElements().then(e2 -> {
		    		
					setOutput("Delete selected");setRawOutput(e2.toJson());
		    		String s=e2.toJson();
		    		try {
						JsonNode selectedObject = new ObjectMapper().readTree(s);
						Iterator<JsonNode> iterator = selectedObject.iterator();
					
						System.out.println("delete selected");
						while (iterator.hasNext()) {
							JsonNode js=iterator.next().at("/data/id");
							String id=js.asText();
							cy.deleteNode(id);
						}
					} catch (Exception e1) {
						e1.printStackTrace();
					}
		    	});
		    });
		    buttonLayout.add(b7);

		    Button b8=new Button("Set element data");
		    b8.addClickListener( e -> {cy.getSelectedElements().then(e2 -> {
		        	String s=e2.toJson();
		    		try {
						JsonNode selectedObject = new ObjectMapper().readTree(s);
						Iterator<JsonNode> iterator = selectedObject.iterator();
						while (iterator.hasNext()) {
							JsonNode js=iterator.next().at("/data/id");
							String id=js.asText();
							setOutput("Set data of element with id:");setRawOutput(id);
							cy.setElementData(id,"{\"myname\":\"martin\"}");
						}
					} catch (Exception e1) {
						e1.printStackTrace();
					}	
		    	});
		    });
		    buttonLayout.add(b8);

	}
	
	private void createNodeList(Cytoscape cy) {
		
		nodeList.setWidth("200px");
		Icon logo1 = new Icon(VaadinIcon.CIRCLE);
		logo1.setSize("100px");
		logo1.setColor("orange");
		
		Icon logo2 = new Icon(VaadinIcon.ELASTIC);
		logo2.setSize("100px");
		logo2.setColor("orange");
		
		nodeList.add(logo1);
		nodeList.add(logo2);
		
		//Make icons draggable
        DragSource<Icon> box1DragSource = DragSource.create(logo1);
        box1DragSource.setDragData("MyNode1");
        
        DragSource<Icon> box2DragSource = DragSource.create(logo2);
        box2DragSource.setDragData("MyNode2");
        
        box1DragSource.addDragStartListener( e -> cy.setDragObject("Node1"));
        box2DragSource.addDragStartListener( e -> cy.setDragObject("Node2"));
        
	}
	
	
	private void createDashBoardContent() {
		//Create Cytoscape Canvas
	    Cytoscape cy=new Cytoscape();
	    cy.setWidth("100%");
	    cy.setHeight("600px");   
	    cy.addClassName("cy");

	    //Add edge handling
	    cy.registerStandardEdgeHandling();

	    //Create context menu for nodes and edges. Tap on an edge or node (left mouse down for 1 second)
	    cy.createContextMenu("node",new String[]{"DeleteNode","EditNode"});
	    cy.createContextMenu("edge",new String[]{"ShowEdge"});
	    
	    cy.addActionListener(e -> {
	    	setRawOutput("ActionEvent: "+e.getMessage());
	    	processContextMenu(cy,e.getMessage());
	    	
	    });
	 
	    cy.registerEvent("mouseover", "node");
	    cy.addCustomEventListener(e -> {
			try {
				JsonNode event = new ObjectMapper().readTree(e.getMessage());
				setOutput("CustomEvent:");
				setRawOutput(e.getMessage());
				JsonNode ja=event.get("data");
				Iterator<JsonNode> iterator = ja.iterator();
				while (iterator.hasNext()) {
					JsonNode js=iterator.next().at("/data/id");
					String id=js.asText();
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
	    });
    
	    cy.addNodeHasBeenAddedEventListener(e -> {
	    	setOutput("NodeHasBeenAdded Event");
	    	setRawOutput(e.getMessage());
	    });
	    
	    cy.addEdgeHasBeenAddedEventListener(e -> {
	    	setOutput("EdgeHasBeenAdded Event");
	    	setRawOutput(e.getMessage());
	    });
	    
	    cy.addEdgeAddedEventListener(e -> {
	    	setOutput("EdgeAdded Event");
	    	setRawOutput(e.getMessage());
	    });
	    
	    
	    cy.addDragListener(e -> {
			try {
				JsonNode dragObject = new ObjectMapper().readTree(e.getMessage());
				Node node=new Node();
				node.getPosition().put("x", dragObject.get("dragXCoordinate").asInt());
				node.getPosition().put("y", dragObject.get("dragYCoordinate").asInt());	
				node.getData().put("type", dragObject.get("dragObject").asText());
				cy.addNode(node);
		    	setOutput("Drag Event");
		    	setRawOutput(e.getMessage());
		
			} catch (Exception ex) {
				ex.printStackTrace();
			}
        });
	    
	    DropTarget<Div> dropTarget = DropTarget.create(cy);
	       
        dropTarget.addDropListener(event -> {
            event.getDragData().ifPresent(data -> {
		    	setOutput("Drag target");
            });
        }); 
    

	    //Define an array of styles for different selectors	
	    GraphStyles gs=new GraphStyles();
	    
	    //Define the style for nodes
	    GeneralGraphStyles node=new GeneralGraphStyles.Builder().background_color("#c00").label("data(id)").build();
	    gs.addStyle("node", node);
	    
	    //Define the style for edges
	    GeneralGraphStyles edge=new GeneralGraphStyles.Builder().width("2").line_color("#00c").line_style("dotted").build();
	    gs.addStyle("edge", edge);
	    
	    //Define the style for selected nodes
	    GeneralGraphStyles node_selected=new GeneralGraphStyles.Builder().background_color("#0c0").build();
	    gs.addStyle("node:selected", node_selected);
	    
	    //Define the style for edgeHandling
	    GeneralGraphStyles eh_handle=new GeneralGraphStyles.Builder().background_color("#00C").width("8").height("8").text_opacity("0").build();
	    gs.addStyle(".eh-handle", eh_handle);
	    
	    //Set the styles
	    cy.loadStyle(gs.getJson(true));
    
        //Load demo graph
	    cy.loadGraph(cy.getDemoGraph2());
	    
	    createButtonLayout(cy);
	    createNodeList(cy);
	    hl1.add(buttonLayout,nodeList,cy);
	}
	
    public View() {
    	
    	createDashboard();
    	createDashBoardContent();
 	    
    }
    
  
}

Install

Link to this version
BetaReleased 13 October 2020MIT License
Framework Support
Vaadin platform 14+
Browser Compatibility
Install with
Release notes - Version 0.0.9

Added loadLayout Function to change the Layout and rearrange the elements