This module provides a Perl interface to the amazing Graphviz, an open source graph visualization tool from AT&T.

It is called GraphViz2 so that pre-existing code using (the Perl module) GraphViz continues to work.

To avoid confusion, when I use GraphViz2 (note the capital V), I'm referring to this Perl module, and when I use Graphviz (lower-case v) I'm referring to the underlying tool (which is in fact a set of programs).

Version 1.00 of GraphViz2 is a complete re-write, by Ron Savage, of GraphViz V 2, which was written by Leon Brocard. The point of the re-write is to provide access to all the latest options available to users of Graphviz.

GraphViz2 V 1 is not backwards compatible with GraphViz V 2, despite the considerable similarity. It was not possible to maintain compatibility while extending support to all the latest features of Graphviz.

To ensure GraphViz2 is a light-weight module, Moo has been used to provide getters and setters, rather than Moose.

As of V 2.43, GraphViz2 supports image maps, both client and server side.

The subgraph key points to a hashref which is used to set attributes for all subgraphs, unless overridden for specific subgraphs in a call of the form push_subgraph(subgraph => {$attribute => $string}).

The secondary keys (under the primary keys 'edge|graph|node') are checked against lists of valid attributes (stored at the end of this module, after the __DATA__ token, and made available using Data::Section::Simple).

This mechanism has the effect of hard-coding Graphviz options in the source code of GraphViz2.

Nevertheless, the implementation of these lists is handled differently from the way it was done in V 2.

V 2 ships with a set of scripts, scripts/extract.*.pl, which retrieve pages from the Graphviz web site and extract the current lists of valid attributes.

These are then copied manually into the source code of GraphViz2, meaning any time those lists change on the Graphviz web site, it's a trivial matter to update the lists stored within this module.

These attributes are pushed onto a scope stack during new()'s processing of its parameters, and they apply thereafter until changed. They are the 'current' attributes. They live at scope level 0 (zero).

You change the 'current' attributes by calling any of the methods default_edge(%hash), default_graph(%hash) and default_node(%hash).

When you wish to create a subgraph, you call push_subgraph(%hash). The word push emphasises that you are moving into a new scope, and that the default attributes for the new scope are pushed onto the scope stack.

This module, as with Graphviz, defaults to using inheritance of attributes.

That means the parent's 'current' attributes are combined with the parameters to push_subgraph(%hash) to generate a new set of 'current' attributes for each of the graphical elements, graph, node and edge.

After a single call to push_subgraph(%hash), these 'current' attributes will live a level 1 in the scope stack.

The way you set such a url in GraphViz2 is via a new parameter to new(). This parameter is called im_meta and it takes a hashref as a value. Currently the only key used within that hashref is the case-sensitive URL.

Each demo, when FTPed to your web server displays some text with an image in the middle. In each case you can click on the upper oval to jump to one page, or click on the lower oval to jump to a different page, or click anywhere else in the image to jump to a third page.

This set demonstrates a client-side image map but does not use GraphViz2.

You have to run demo.2.sh which generates demo.2.map, and then you manually copy demo.2.map into demo.2.html, replacing any version of the map already present. After that you FTP the whole dir maps/ to your web server.

This set demonstrates a client-side image map using GraphViz2 via demo.4.pl.

As with demo.2.* there is some manually editing to be done.

Note line 54 of demo.4.pl which sets the default im_format to 'cmapx'. This is the only important difference between this demo and the previous one.

There are other minor differences, in that one uses 'svg' and the other 'png'. And of course the urls of the web pages embedded in the code and in those web pages differs, just to demonstate that the maps do indeed lead to different pages.

If either of these node names is unknown, add_node(name => $node_name) is called automatically. The lack of attributes in this call means such nodes are created with the default set of attributes, and that may not be what you want. To avoid this, you have to call add_node(...) yourself, with the appropriate attributes, before calling add_edge(...).

%hash is any edge attributes accepted as Graphviz attributes. These are validated in exactly the same way as the edge parameters in the calls to default_edge(%hash), new(edge => {}) and push_subgraph(edge => {}).

%hash is any node attributes accepted as Graphviz attributes. These are validated in exactly the same way as the node parameters in the calls to default_node(%hash), new(node => {}) and push_subgraph(node => {}).

%hash is any cluster or subgraph attribute accepted as Graphviz attributes. These are validated in exactly the same way as the subgraph parameter in the calls to new(subgraph => {}) and push_subgraph(subgraph => {}).

If the caller adds the same edge two (or more) times, the attributes from each call are not coalesced (unlike "node_hash()"), but rather the attributes from each call are stored separately in an arrayref.

A bit more formally then, $$edge_hash{$from_node}{$to_node} is an arrayref where each element describes one edge, and which defaults to:

{
attributes => {},
from_port => $from_port,
to_port => $to_port,
}

If from_port is not provided by the caller, it defaults to '' (the empty string). If it is provided, it contains a leading ':'. Likewise for to_port.

See scripts/report.nodes.and.edges.pl (a version of scripts/html.labels.1.pl) for a complete example.

If the caller adds the same node two (or more) times, the attributes from each call are coalesced (unlike "edge_hash()"), meaning all attributes from all calls are combined under the attributes sub-key.

A bit more formally then, $$node_hash{$node_name} is a hashref where each element describes one node, and which defaults to:

{
attributes => {},
}

See scripts/report.nodes.and.edges.pl (a version of scripts/html.labels.1.pl) for a complete example, including usage of the corresponding "edge_hash()" method.

See scripts/rank.sub.graph.[1234].pl for the effect of various values for $name.

edge => {...} is any edge attributes accepted as Graphviz attributes. These are validated in exactly the same way as the edge parameters in the calls to default_edge(%hash), new(edge => {}) and push_subgraph(edge => {}).

graph => {...} is any graph attributes accepted as Graphviz attributes. These are validated in exactly the same way as the graph parameters in the calls to default_graph(%hash), new(graph => {}) and push_subgraph(graph => {}).

node => {...} is any node attributes accepted as Graphviz attributes. These are validated in exactly the same way as the node parameters in the calls to default_node(%hash), new(node => {}) and push_subgraph(node => {}).

subgraph => {..} is for setting attributes applicable to clusters and subgraphs.

Currently the only subgraph attribute is rank, but clusters have many attributes available.

Escaping the 2 chars [] started with V 2.10. Previously, all of []{} were escaped, but {} are used in records to control the orientation of fields, so they should not have been escaped in the first place. See scripts/record.1.pl.

Double-quotes are escaped when the label is not an HTML label. See scripts/html.labels.*.pl for sample code.

It would be nice to also escape | and <, but these characters are used in specifying fields and ports in records.

You can patch the scripts/parse.stt.pl to read from t/sample.stt.2.dat instead of t/sample.stt.1.dat. t/sample.stt.2.dat was extracted from a obsolete version of Graph::Easy::Marpa, i.e. V 1.*. The Marpa-based parts of the latter module were completely rewritten for V 2.*.

All Programs of mine are 'OSI Certified Open Source Software';
you can redistribute them and/or modify them under the terms of
The Perl License, a copy of which is available at:
http://dev.perl.org/licenses/