How to draw graphviz graphs with Nitrogen

I built an initial version of a new control which allows to draw graphviz graphs with Nitrogen and added it to the collection of Nitrogen_Elements.

As far as I know Erlang ecosystem doesn’t have a convenient library to draw dot files with graphviz. Graphviz is a system which allows to describe arbitrary complex graphs in dot format, calculate a layout from the dot files and output this layout in a number of formats (PDF, XML, SVG and Postscript). Graphviz is a very large C++ library.

The control is called element_viz and it is a wrapper for two very interesting libraries:

  • Viz.js – is Emscripten generated javascript library from Graphviz C++ code base. It allows to calculate a graph layout on a browser side and display a graph in SVG format on html page
  • jquery.graphviz is a lib which allows to move (click and drag and drop) and remove (double click on a node or on a edge) the nodes and the edges of a graph created with graphviz

The control itself is extremely simple as all the magic is happening in Viz.js.

-module(element_viz).

-include ("nitrogen_elements.hrl").
-include_lib("nitrogen_core/include/wf.hrl").
-compile(export_all).

reflect() -> record_info(fields, viz).

render_element(Record) ->
    ID = Record#viz.id,

    %% get data, should be binary string in dot format
    Data = Record#viz.data,

    %% generate graph html and append to panel placeholder
    wf:wire(ID, wf:f("$(function(){jQuery(obj('~s')).html(Viz('~s', \"svg\"));})", [ID, Data])),

    %% set svg width 100% to fill panel
    wf:wire(ID, wf:f("$(function(){jQuery(obj('~s')).find(\"svg\").width('100%');})", [ID])),

    %% add jquery.graphviz
    wf:wire(ID, wf:f("$(function(){jQuery(obj('~s')).find(\"svg\").graphviz({status: true});})", [ID])),

    %% create html markup
    #panel{id = ID}.

%% not used yet
event(Event) ->

Control use is also very simple – add #viz{} record and pass a binary string with dot representation of the graph.

-define(DATA, <<"digraph G {subgraph cluster_0 {style=filled;color=lightgrey; node [style=filled,color=white]; a0 -> a1 -> a2 -> a3;label = \"process #1\";} subgraph cluster_1 {node [style=filled]; b0 -> b1 -> b2 -> b3; label = \"process #2\";color=blue} start -> a0; start -> b0; a1 -> b3; b2 -> a3; a3 -> a0; a3 -> end; b3 -> end; start [shape=Mdiamond]; end [shape=Msquare];}">>).

body(_Tag) -;
    %% output html markup
    [
	#viz{id = viz, data = ?DATA}
    ].

The final result on the page looks like this:

Screen Shot 2013-03-09 at 21.59.32

And you can move the nodes and edges of this graph – this functionality is provided by jquery.graphviz.

Screen Shot 2013-03-09 at 22.01.19

This control might be very useful and could be extended further with Websockets, so the changes to the graph could be pushed from the server side in dot format and reflected dynamically on the page.

See the full example here

About these ads
This entry was posted in custom Nitrogen elements, Nitrogen, Nitrogen_Elements and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s