• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

lib/H21-Feb-2021-3,1691,204

t/H21-Feb-2021-3,5482,995

xt/H21-Feb-2021-2114

ChangesH A D21-Feb-202134.5 KiB655574

LICENSEH A D17-Sep-202019.8 KiB379305

MANIFESTH A D21-Feb-20212.6 KiB9897

MANIFEST.SKIPH A D03-Nov-2020718 5747

META.jsonH A D21-Feb-20212 KiB8281

META.ymlH A D21-Feb-2021917 3635

Makefile.PLH A D09-Jan-20212.4 KiB8775

README.mdH A D09-Jan-202140.5 KiB1,134695

README.md

1# NAME
2
3GraphViz2 - A wrapper for AT&T's Graphviz
4
5# Synopsis
6
7## Sample output
8
9See [https://graphviz-perl.github.io/](https://graphviz-perl.github.io/).
10
11## Perl code
12
13### Typical Usage
14
15        use strict;
16        use warnings;
17        use File::Spec;
18        use GraphViz2;
19
20        use Log::Handler;
21        my $logger = Log::Handler->new;
22        $logger->add(screen => {
23                maxlevel => 'debug', message_layout => '%m', minlevel => 'error'
24        });
25
26        my $graph = GraphViz2->new(
27                edge   => {color => 'grey'},
28                global => {directed => 1},
29                graph  => {label => 'Adult', rankdir => 'TB'},
30                logger => $logger,
31                node   => {shape => 'oval'},
32        );
33
34        $graph->add_node(name => 'Carnegie', shape => 'circle');
35        $graph->add_node(name => 'Murrumbeena', shape => 'box', color => 'green');
36        $graph->add_node(name => 'Oakleigh',    color => 'blue');
37        $graph->add_edge(from => 'Murrumbeena', to    => 'Carnegie', arrowsize => 2);
38        $graph->add_edge(from => 'Murrumbeena', to    => 'Oakleigh', color => 'brown');
39
40        $graph->push_subgraph(
41                name  => 'cluster_1',
42                graph => {label => 'Child'},
43                node  => {color => 'magenta', shape => 'diamond'},
44        );
45        $graph->add_node(name => 'Chadstone', shape => 'hexagon');
46        $graph->add_node(name => 'Waverley', color => 'orange');
47        $graph->add_edge(from => 'Chadstone', to => 'Waverley');
48        $graph->pop_subgraph;
49
50        $graph->default_node(color => 'cyan');
51
52        $graph->add_node(name => 'Malvern');
53        $graph->add_node(name => 'Prahran', shape => 'trapezium');
54        $graph->add_edge(from => 'Malvern', to => 'Prahran');
55        $graph->add_edge(from => 'Malvern', to => 'Murrumbeena');
56
57        my $format      = shift || 'svg';
58        my $output_file = shift || File::Spec->catfile('html', "sub.graph.$format");
59        $graph->run(format => $format, output_file => $output_file);
60
61# Description
62
63## Overview
64
65This module provides a Perl interface to the amazing [Graphviz](http://www.graphviz.org/), an open source graph visualization tool from AT&T.
66
67It is called GraphViz2 so that pre-existing code using (the Perl module) GraphViz continues to work.
68
69To avoid confusion, when I use [GraphViz2](https://metacpan.org/pod/GraphViz2) (note the capital V), I'm referring to this Perl module, and
70when I use [Graphviz](http://www.graphviz.org/) (lower-case v) I'm referring to the underlying tool (which is in fact a set of programs).
71
72Version 1.00 of [GraphViz2](https://metacpan.org/pod/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
73is to provide access to all the latest options available to users of [Graphviz](http://www.graphviz.org/).
74
75GraphViz2 V 1 is not backwards compatible with GraphViz V 2, despite the considerable similarity. It was not possible to maintain compatibility
76while extending support to all the latest features of [Graphviz](http://www.graphviz.org/).
77
78To ensure [GraphViz2](https://metacpan.org/pod/GraphViz2) is a light-weight module, [Moo](https://metacpan.org/pod/Moo) has been used to provide getters and setters,
79rather than [Moose](https://metacpan.org/pod/Moose).
80
81As of V 2.43, `GraphViz2` supports image maps, both client and server side.
82
83See ["Image Maps"](#image-maps) below.
84
85## What is a Graph?
86
87An undirected graph is a collection of nodes optionally linked together with edges.
88
89A directed graph is the same, except that the edges have a direction, normally indicated by an arrow head.
90
91A quick inspection of [Graphviz](http://www.graphviz.org/)'s [gallery](http://www.graphviz.org/gallery/) will show better than words
92just how good [Graphviz](http://www.graphviz.org/) is, and will reinforce the point that humans are very visual creatures.
93
94# Installation
95
96Of course you need to install AT&T's Graphviz before using this module.
97See [http://www.graphviz.org/download/](http://www.graphviz.org/download/).
98
99# Constructor and Initialization
100
101## Calling new()
102
103`new()` is called as `my($obj) = GraphViz2 -> new(k1 => v1, k2 => v2, ...)`.
104
105It returns a new object of type `GraphViz2`.
106
107Key-value pairs accepted in the parameter list:
108
109### edge => $hashref
110
111The _edge_ key points to a hashref which is used to set default attributes for edges.
112
113Hence, allowable keys and values within that hashref are anything supported by [Graphviz](http://www.graphviz.org/).
114
115The default is {}.
116
117This key is optional.
118
119### global => $hashref
120
121The _global_ key points to a hashref which is used to set attributes for the output stream.
122
123This key is optional.
124
125Valid keys within this hashref are:
126
127#### combine\_node\_and\_port
128
129New in 2.58. It defaults to true, but in due course (currently planned
130May 2021) it will default to false. When true, `add_node` and `add_edge`
131will escape only some characters in the label and names, and in particular
132the "from" and "to" parameters on edges will combine the node name
133and port in one string, with a `:` in the middle (except for special
134treatment of double-colons).
135
136When the option is false, any name may be given to nodes, and edges can
137be created between them. To specify ports, give the additional parameter
138of `tailport` or `headport`. To specify a compass point in addition,
139give array-refs with two values for these parameters. Also, `add_node`'s
140treatment of labels is more DWIM, with `{` etc being transparently
141quoted.
142
143#### directed => $Boolean
144
145This option affects the content of the output stream.
146
147directed => 1 outputs 'digraph name {...}', while directed => 0 outputs 'graph name {...}'.
148
149At the Perl level, directed graphs have edges with arrow heads, such as '->', while undirected graphs have
150unadorned edges, such as '--'.
151
152The default is 0.
153
154This key is optional.
155
156#### driver => $program\_name
157
158This option specifies which external program to run to process the output stream.
159
160The default is to use [File::Which](https://metacpan.org/pod/File%3A%3AWhich)'s which() method to find the 'dot' program.
161
162This key is optional.
163
164#### format => $string
165
166This option specifies what type of output file to create.
167
168The default is 'svg'.
169
170Output formats of the form 'png:gd' etc are also supported, but only the component before
171the first ':' is validated by [GraphViz2](https://metacpan.org/pod/GraphViz2).
172
173This key is optional.
174
175#### label => $string
176
177This option specifies what an edge looks like: '->' for directed graphs and '--' for undirected graphs.
178
179You wouldn't normally need to use this option.
180
181The default is '->' if directed is 1, and '--' if directed is 0.
182
183This key is optional.
184
185#### name => $string
186
187This option affects the content of the output stream.
188
189name => 'G666' outputs 'digraph G666 {...}'.
190
191The default is 'Perl' :-).
192
193This key is optional.
194
195#### record\_shape => /^(?:M?record)$/
196
197This option affects the shape of records. The value must be 'Mrecord' or 'record'.
198
199Mrecords have nice, rounded corners, whereas plain old records have square corners.
200
201The default is 'Mrecord'.
202
203See [Record shapes](http://www.graphviz.org/doc/info/shapes.html#record) for details.
204
205#### strict => $Boolean
206
207This option affects the content of the output stream.
208
209strict => 1 outputs 'strict digraph name {...}', while strict => 0 outputs 'digraph name {...}'.
210
211The default is 0.
212
213This key is optional.
214
215#### timeout => $integer
216
217This option specifies how long to wait for the external program before exiting with an error.
218
219The default is 10 (seconds).
220
221This key is optional.
222
223### graph => $hashref
224
225The _graph_ key points to a hashref which is used to set default attributes for graphs.
226
227Hence, allowable keys and values within that hashref are anything supported by [Graphviz](http://www.graphviz.org/).
228
229The default is {}.
230
231This key is optional.
232
233### logger => $logger\_object
234
235Provides a logger object so $logger\_object -> $level($message) can be called at certain times. Any object with `debug` and `error` methods
236will do, since these are the only levels emitted by this module.
237One option is a [Log::Handler](https://metacpan.org/pod/Log%3A%3AHandler) object.
238
239Retrieve and update the value with the logger() method.
240
241By default (i.e. without a logger object), [GraphViz2](https://metacpan.org/pod/GraphViz2) prints warning and debug messages to STDOUT,
242and dies upon errors.
243
244However, by supplying a log object, you can capture these events.
245
246Not only that, you can change the behaviour of your log object at any time, by calling
247["logger($logger\_object)"](#logger-logger_object).
248
249See also the verbose option, which can interact with the logger option.
250
251This key is optional.
252
253### node => $hashref
254
255The _node_ key points to a hashref which is used to set default attributes for nodes.
256
257Hence, allowable keys and values within that hashref are anything supported by [Graphviz](http://www.graphviz.org/).
258
259The default is {}.
260
261This key is optional.
262
263### subgraph => $hashref
264
265The _subgraph_ key points to a hashref which is used to set attributes for all subgraphs, unless overridden
266for specific subgraphs in a call of the form push\_subgraph(subgraph => {$attribute => $string}).
267
268Valid keys within this hashref are:
269
270- rank => $string
271
272    This option affects the content of all subgraphs, unless overridden later.
273
274    A typical usage would be new(subgraph => {rank => 'same'}) so that all nodes mentioned within each subgraph
275    are constrained to be horizontally aligned.
276
277    See scripts/rank.sub.graph.1.pl for sample code.
278
279    Possible values for $string are: max, min, same, sink and source.
280
281    See the [Graphviz 'rank' docs](http://www.graphviz.org/doc/info/attrs.html#d:rank) for details.
282
283The default is {}.
284
285This key is optional.
286
287### verbose => $Boolean
288
289Provides a way to control the amount of output when a logger is not specified.
290
291Setting verbose to 0 means print nothing.
292
293Setting verbose to 1 means print the log level and the message to STDOUT, when a logger is not specified.
294
295Retrieve and update the value with the verbose() method.
296
297The default is 0.
298
299See also the logger option, which can interact with the verbose option.
300
301This key is optional.
302
303## Validating Parameters
304
305The secondary keys (under the primary keys 'edge|graph|node') are checked against lists of valid attributes (stored at the end of this
306module, after the \_\_DATA\_\_ token, and made available using [Data::Section::Simple](https://metacpan.org/pod/Data%3A%3ASection%3A%3ASimple)).
307
308This mechanism has the effect of hard-coding [Graphviz](http://www.graphviz.org/) options in the source code of [GraphViz2](https://metacpan.org/pod/GraphViz2).
309
310Nevertheless, the implementation of these lists is handled differently from the way it was done in V 2.
311
312V 2 ships with a set of scripts, scripts/extract.\*.pl, which retrieve pages from the
313[Graphviz](http://www.graphviz.org/) web site and extract the current lists of valid attributes.
314
315These are then copied manually into the source code of [GraphViz2](https://metacpan.org/pod/GraphViz2), meaning any time those lists change on the
316[Graphviz](http://www.graphviz.org/) web site, it's a trivial matter to update the lists stored within this module.
317
318See ["Scripts Shipped with this Module" in GraphViz2](https://metacpan.org/pod/GraphViz2#Scripts-Shipped-with-this-Module).
319
320## Alternate constructor and object method
321
322### from\_graph
323
324        my $gv = GraphViz2->from_graph($g);
325
326        # alternatively
327        my $gv = GraphViz2->new;
328        $gv->from_graph($g);
329
330        # for handy debugging of arbitrary graphs:
331        GraphViz2->from_graph($g)->run(format => 'svg', output_file => 'output.svg');
332
333Takes a [Graph](https://metacpan.org/pod/Graph) object. This module will figure out various defaults from it,
334including whether it is directed or not.
335
336Will also use any node-, edge-, and graph-level attributes named
337`graphviz` as a hash-ref for setting attributes on the corresponding
338entities in the constructed GraphViz2 object. These will override the
339figured-out defaults referred to above.
340
341For a `multivertexed` graph, will only create one node per vertex,
342but will search all the multi-IDs for a `graphviz` attribute, taking
343the first one it finds (sorted alphabetically).
344
345For a `multiedged` graph, will create one edge per multi-edge.
346
347Will only set the `global` attribute if called as a constructor. This
348will be dropped from any passed-in graph-level `graphviz` attribute
349when called as an object method.
350
351A special graph-level attribute (under `graphviz`) called `groups` will
352be given further special meaning: it is an array-ref of hash-refs. Those
353will have keys, used to create subgraphs:
354
355- attributes
356
357    Hash-ref of arguments to supply to `push_subgraph` for this subgraph.
358
359- nodes
360
361    Array-ref of node names to put in this subgraph.
362
363Example:
364
365        $g->set_graph_attribute(graphviz => {
366                groups => [
367                        {nodes => [1, 2], attributes => {subgraph=>{rank => 'same'}}},
368                ],
369                # other graph-level attributes...
370        });
371
372# Attribute Scope
373
374## Graph Scope
375
376The graphical elements graph, node and edge, have attributes. Attributes can be set when calling new().
377
378Within new(), the defaults are graph => {}, node => {}, and edge => {}.
379
380You override these with code such as new(edge => {color => 'red'}).
381
382These attributes are pushed onto a scope stack during new()'s processing of its parameters, and they apply thereafter until changed.
383They are the 'current' attributes. They live at scope level 0 (zero).
384
385You change the 'current' attributes by calling any of the methods default\_edge(%hash), default\_graph(%hash) and default\_node(%hash).
386
387See scripts/trivial.pl (["Scripts Shipped with this Module" in GraphViz2](https://metacpan.org/pod/GraphViz2#Scripts-Shipped-with-this-Module)) for an example.
388
389## Subgraph Scope
390
391When you wish to create a subgraph, you call push\_subgraph(%hash). The word push emphasises that you are moving into a new scope,
392and that the default attributes for the new scope are pushed onto the scope stack.
393
394This module, as with [Graphviz](http://www.graphviz.org/), defaults to using inheritance of attributes.
395
396That means the parent's 'current' attributes are combined with the parameters to push\_subgraph(%hash) to generate a new set of 'current'
397attributes for each of the graphical elements, graph, node and edge.
398
399After a single call to push\_subgraph(%hash), these 'current' attributes will live a level 1 in the scope stack.
400
401See scripts/sub.graph.pl (["Scripts Shipped with this Module" in GraphViz2](https://metacpan.org/pod/GraphViz2#Scripts-Shipped-with-this-Module)) for an example.
402
403Another call to push\_subgraph(%hash), _without_ an intervening call to pop\_subgraph(), will repeat the process, leaving you with
404a set of attributes at level 2 in the scope stack.
405
406Both [GraphViz2](https://metacpan.org/pod/GraphViz2) and [Graphviz](http://www.graphviz.org/) handle this situation properly.
407
408See scripts/sub.sub.graph.pl (["Scripts Shipped with this Module" in GraphViz2](https://metacpan.org/pod/GraphViz2#Scripts-Shipped-with-this-Module)) for an example.
409
410At the moment, due to design defects (IMHO) in the underlying [Graphviz](http://www.graphviz.org/) logic, there are some tiny problems with this:
411
412- A global frame
413
414    I can't see how to make the graph as a whole (at level 0 in the scope stack) have a frame.
415
416- Frame color
417
418    When you specify graph => {color => 'red'} at the parent level, the subgraph has a red frame.
419
420    I think a subgraph should control its own frame.
421
422- Parent and child frames
423
424    When you specify graph => {color => 'red'} at the subgraph level, both that subgraph and it children have red frames.
425
426    This contradicts what happens at the global level, in that specifying color there does not given the whole graph a frame.
427
428- Frame visibility
429
430    A subgraph whose name starts with 'cluster' is currently forced to have a frame, unless you rig it by specifying a
431    color the same as the background.
432
433    For sample code, see scripts/sub.graph.frames.pl.
434
435Also, check [the pencolor docs](http://www.graphviz.org/doc/info/attrs.html#d:pencolor) for how the color of the frame is
436chosen by cascading thru a set of options.
437
438I've posted an email to the [Graphviz](http://www.graphviz.org/) mailing list suggesting a new option, framecolor, so deal with
439this issue, including a special color of 'invisible'.
440
441# Image Maps
442
443As of V 2.43, `GraphViz2` supports image maps, both client and server side.
444For web use, note that these options also take effect when generating SVGs,
445for a much lighter-weight solution to hyperlinking graph nodes and edges.
446
447## The Default URL
448
449See the [Graphviz docs for 'cmapx'](http://www.graphviz.org/doc/info/output.html#d:cmapx).
450
451Their sample code has a dot file - x.gv - containing this line:
452
453        URL="http://www.research.att.com/base.html";
454
455The way you set such a url in `GraphViz2` is via a new parameter to `new()`. This parameter is called `im_meta`
456and it takes a hashref as a value. Currently the only key used within that hashref is the case-sensitive `URL`.
457
458Thus you must do this to set a URL:
459
460        my($graph) = GraphViz2 -> new
461                     (
462                        ...
463                        im_meta =>
464                        {
465                            URL => 'http://savage.net.au/maps/demo.3.1.html', # Note: URL must be in caps.
466                        },
467                     );
468
469See maps/demo.3.pl and maps/demo.4.pl for sample code.
470
471## Typical Code
472
473Normally you would call `run()` as:
474
475        $graph -> run
476        (
477            format      => $format,
478            output_file => $output_file
479        );
480
481That line was copied from scripts/cluster.pl.
482
483To trigger image map processing, you must include 2 new parameters:
484
485        $graph -> run
486        (
487            format         => $format,
488            output_file    => $output_file,
489            im_format      => $im_format,
490            im_output_file => $im_output_file
491        );
492
493That line was copied from maps/demo.3.pl, and there is an identical line in maps/demo.4.pl.
494
495## The New Parameters to run()
496
497- im\_format => $str
498
499    Expected values: 'imap' (server-side) and 'cmapx' (client-side).
500
501    Default value: 'cmapx'.
502
503- im\_output\_file => $file\_name
504
505    The name of the output map file.
506
507    Default: ''.
508
509    If you do not set it to anything, the new image maps code is ignored.
510
511## Sample Code
512
513Various demos are shipped in the new maps/ directory:
514
515Each demo, when FTPed to your web server displays some text with an image in the middle. In each case
516you can click on the upper oval to jump to one page, or click on the lower oval to jump to a different
517page, or click anywhere else in the image to jump to a third page.
518
519- demo.1.\*
520
521    This set demonstrates a server-side image map but does not use `GraphViz2`.
522
523    You have to run demo.1.sh which generates demo.1.map, and then you FTP the whole dir maps/ to your web server.
524
525    URL: your.domain.name/maps/demo.1.html.
526
527- demo.2.\*
528
529    This set demonstrates a client-side image map but does not use `GraphViz2`.
530
531    You have to run demo.2.sh which generates demo.2.map, and then you manually copy demo.2.map into demo.2.html,
532    replacing any version of the map already present. After that you FTP the whole dir maps/ to your web server.
533
534    URL: your.domain.name/maps/demo.2.html.
535
536- demo.3.\*
537
538    This set demonstrates a server-side image map using `GraphViz2` via demo.3.pl.
539
540    Note line 54 of demo.3.pl which sets the default `im_format` to 'imap'.
541
542    URL: your.domain.name/maps/demo.3.html.
543
544- demo.4.\*
545
546    This set demonstrates a client-side image map using `GraphViz2` via demo.4.pl.
547
548    As with demo.2.\* there is some manually editing to be done.
549
550    Note line 54 of demo.4.pl which sets the default `im_format` to 'cmapx'. This is the only important
551    difference between this demo and the previous one.
552
553    There are other minor differences, in that one uses 'svg' and the other 'png'. And of course the urls
554    of the web pages embedded in the code and in those web pages differs, just to demonstate that the maps
555    do indeed lead to different pages.
556
557    URL: your.domain.name/maps/demo.4.html.
558
559# Methods
560
561## add\_edge(from => $from\_node\_name, to => $to\_node\_name, \[label => $label, %hash\])
562
563Adds an edge to the graph.
564
565Returns $self to allow method chaining.
566
567Here, \[\] indicate optional parameters.
568
569Add a edge from 1 node to another.
570
571$from\_node\_name and $to\_node\_name default to ''.
572
573%hash is any edge attributes accepted as
574[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
575These are validated in exactly the same way as the edge parameters in the calls to
576default\_edge(%hash), new(edge => {}) and push\_subgraph(edge => {}).
577
578To make the edge start or finish on a port, see ["combine\_node\_and\_port"](#combine_node_and_port).
579
580## add\_node(name => $node\_name, \[%hash\])
581
582        my $graph = GraphViz2->new(global => {combine_node_and_port => 0});
583        $graph->add_node(name => 'struct3', shape => 'record', label => [
584                { text => "hello\\nworld" },
585                [
586                        { text => 'b' },
587                        [
588                                { text => 'c{}' }, # reproduced literally
589                                { text => 'd', port => 'here' },
590                                { text => 'e' },
591                        ]
592                        { text => 'f' },
593                ],
594                { text => 'g' },
595                { text => 'h' },
596        ]);
597
598Adds a node to the graph.
599
600Returns $self to allow method chaining.
601
602If you want to embed newlines or double-quotes in node names or labels, see scripts/quote.pl in ["Scripts Shipped with this Module" in GraphViz2](https://metacpan.org/pod/GraphViz2#Scripts-Shipped-with-this-Module).
603
604If you want anonymous nodes, see scripts/anonymous.pl in ["Scripts Shipped with this Module" in GraphViz2](https://metacpan.org/pod/GraphViz2#Scripts-Shipped-with-this-Module).
605
606Here, \[\] indicates an optional parameter.
607
608%hash is any node attributes accepted as
609[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
610These are validated in exactly the same way as the node parameters in the calls to
611default\_node(%hash), new(node => {}) and push\_subgraph(node => {}).
612
613The attribute name 'label' may point to a string or an arrayref.
614
615### If it is a string...
616
617The string is the label. If the `shape` is a record, you can give any
618text and it will be passed for interpretation by Graphviz. This means
619you will need to quote < and > (port specifiers), `|` (cell
620separator) and `{` `}` (structure depth) with `\` to make them appear
621literally.
622
623For records, the cells start horizontal. Each additional layer of
624structure will switch the orientation between horizontal and vertical.
625
626### If it is an arrayref of strings...
627
628- The node is forced to be a record
629
630    The actual shape, 'record' or 'Mrecord', is set globally, with:
631
632            my($graph) = GraphViz2 -> new
633            (
634                    global => {record_shape => 'record'}, # Override default 'Mrecord'.
635                    ...
636            );
637
638    Or set locally with:
639
640            $graph -> add_node(name => 'Three', label => ['Good', 'Bad'], shape => 'record');
641
642- Each element in the array defines a field in the record
643
644    These fields are combined into a single node
645
646- Each element is treated as a label
647- Each label is given a port name (1 .. N) of the form "port$port\_count"
648- Judicious use of '{' and '}' in the label can make this record appear horizontally or vertically, and even nested
649
650### If it is an arrayref of hashrefs...
651
652- The node is forced to be a record
653
654    The actual shape, 'record' or 'Mrecord', can be set globally or locally, as explained just above.
655
656- Each element in the array defines a field in the record
657- Each element is treated as a hashref with keys 'text' and 'port'
658
659    The 'port' key is optional.
660
661- The value of the 'text' key is the label
662- The value of the 'port' key is the port
663- Judicious use of '{' and '}' in the label can make this record appear horizontally or vertically, and even nested
664
665See scripts/html.labels.\*.pl and scripts/record.\*.pl for sample code.
666
667See also ["How labels interact with ports"](#how-labels-interact-with-ports).
668
669For more details on this complex topic, see [Records](http://www.graphviz.org/doc/info/shapes.html#record) and [Ports](http://www.graphviz.org/doc/info/attrs.html#k:portPos).
670
671## default\_edge(%hash)
672
673Sets defaults attributes for edges added subsequently.
674
675Returns $self to allow method chaining.
676
677%hash is any edge attributes accepted as
678[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
679These are validated in exactly the same way as the edge parameters in the calls to new(edge => {})
680and push\_subgraph(edge => {}).
681
682## default\_graph(%hash)
683
684Sets defaults attributes for the graph.
685
686Returns $self to allow method chaining.
687
688%hash is any graph attributes accepted as
689[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
690These are validated in exactly the same way as the graph parameter in the calls to new(graph => {})
691and push\_subgraph(graph => {}).
692
693## default\_node(%hash)
694
695Sets defaults attributes for nodes added subsequently.
696
697Returns $self to allow method chaining.
698
699%hash is any node attributes accepted as
700[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
701These are validated in exactly the same way as the node parameters in the calls to new(node => {})
702and push\_subgraph(node => {}).
703
704## default\_subgraph(%hash)
705
706Sets defaults attributes for clusters and subgraphs.
707
708Returns $self to allow method chaining.
709
710%hash is any cluster or subgraph attribute accepted as
711[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
712These are validated in exactly the same way as the subgraph parameter in the calls to
713new(subgraph => {}) and push\_subgraph(subgraph => {}).
714
715## dot\_input()
716
717Returns the output stream, formatted nicely, to be passed to the external program (e.g. dot).
718
719## dot\_output()
720
721Returns the output from calling the external program (e.g. dot).
722
723You _must_ call run() before calling dot\_output(), since it is only during the call to run() that the output of the
724external program is stored in the buffer controlled by dot\_output().
725
726This output is available even if run() does not write the output to a file.
727
728## edge\_hash()
729
730Returns, at the end of the run, a hashref keyed by node name, specifically the node at the arrow_tail_ end of
731the hash, i.e. where the edge starts from.
732
733Use this to get a list of all nodes and the edges which leave those nodes, the corresponding destination
734nodes, and the attributes of each edge.
735
736        my($node_hash) = $graph -> node_hash;
737        my($edge_hash) = $graph -> edge_hash;
738
739        for my $from (sort keys %$node_hash)
740        {
741                my($attr) = $$node_hash{$from}{attributes};
742                my($s)    = join(', ', map{"$_ => $$attr{$_}"} sort keys %$attr);
743
744                print "Node: $from\n";
745                print "\tAttributes: $s\n";
746
747                for my $to (sort keys %{$$edge_hash{$from} })
748                {
749                        for my $edge (@{$$edge_hash{$from}{$to} })
750                        {
751                                $attr = $$edge{attributes};
752                                $s    = join(', ', map{"$_ => $$attr{$_}"} sort keys %$attr);
753
754                                print "\tEdge: $from$$edge{from_port} -> $to$$edge{to_port}\n";
755                                print "\t\tAttributes: $s\n";
756                        }
757                }
758        }
759
760If the caller adds the same edge two (or more) times, the attributes from each call are
761_not_ coalesced (unlike ["node\_hash()"](#node_hash)), but rather the attributes from each call are stored separately
762in an arrayref.
763
764A bit more formally then, $$edge\_hash{$from\_node}{$to\_node} is an arrayref where each element describes
765one edge, and which defaults to:
766
767        {
768                attributes => {},
769                from_port  => $from_port,
770                to_port    => $to_port,
771        }
772
773If _from\_port_ is not provided by the caller, it defaults to '' (the empty string). If it is provided,
774it contains a leading ':'. Likewise for _to\_port_.
775
776See scripts/report.nodes.and.edges.pl (a version of scripts/html.labels.1.pl) for a complete example.
777
778## log(\[$level, $message\])
779
780Logs the message at the given log level.
781
782Returns $self to allow method chaining.
783
784Here, \[\] indicate optional parameters.
785
786$level defaults to 'debug', and $message defaults to ''.
787
788If called with $level eq 'error', it dies with $message.
789
790## logger($logger\_object)
791
792Gets or sets the log object.
793
794Here, \[\] indicates an optional parameter.
795
796## node\_hash()
797
798Returns, at the end of the run, a hashref keyed by node name. Use this to get a list of all nodes
799and their attributes.
800
801        my($node_hash) = $graph -> node_hash;
802
803        for my $name (sort keys %$node_hash)
804        {
805                my($attr) = $$node_hash{$name}{attributes};
806                my($s)    = join(', ', map{"$_ => $$attr{$_}"} sort keys %$attr);
807
808                print "Node: $name\n";
809                print "\tAttributes: $s\n";
810        }
811
812If the caller adds the same node two (or more) times, the attributes from each call are
813_coalesced_ (unlike ["edge\_hash()"](#edge_hash)), meaning all attributes from all calls are combined under the
814_attributes_ sub-key.
815
816A bit more formally then, $$node\_hash{$node\_name} is a hashref where each element describes one node, and
817which defaults to:
818
819        {
820                attributes => {},
821        }
822
823See scripts/report.nodes.and.edges.pl (a version of scripts/html.labels.1.pl) for a complete example,
824including usage of the corresponding ["edge\_hash()"](#edge_hash) method.
825
826## pop\_subgraph()
827
828Pop off and discard the top element of the scope stack.
829
830Returns $self to allow method chaining.
831
832## push\_subgraph(\[name => $name, edge => {...}, graph => {...}, node => {...}, subgraph => {...}\])
833
834Sets up a new subgraph environment.
835
836Returns $self to allow method chaining.
837
838Here, \[\] indicate optional parameters.
839
840name => $name is the name to assign to the subgraph. Name defaults to ''.
841
842So, without $name, 'subgraph {' is written to the output stream.
843
844With $name, 'subgraph "$name" {' is written to the output stream.
845
846Note that subgraph names beginning with 'cluster' [are special to Graphviz](http://www.graphviz.org/doc/info/attrs.html#d:clusterrank).
847
848See scripts/rank.sub.graph.\[1234\].pl for the effect of various values for $name.
849
850edge => {...} is any edge attributes accepted as
851[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
852These are validated in exactly the same way as the edge parameters in the calls to
853default\_edge(%hash), new(edge => {}) and push\_subgraph(edge => {}).
854
855graph => {...} is any graph attributes accepted as
856[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
857These are validated in exactly the same way as the graph parameters in the calls to
858default\_graph(%hash), new(graph => {}) and push\_subgraph(graph => {}).
859
860node => {...} is any node attributes accepted as
861[Graphviz attributes](https://www.graphviz.org/doc/info/attrs.html).
862These are validated in exactly the same way as the node parameters in the calls to
863default\_node(%hash), new(node => {}) and push\_subgraph(node => {}).
864
865subgraph => {..} is for setting attributes applicable to clusters and subgraphs.
866
867Currently the only subgraph attribute is `rank`, but clusters have many attributes available.
868
869See the second column of the
870[Graphviz attribute docs](https://www.graphviz.org/doc/info/attrs.html) for details.
871
872A typical usage would be push\_subgraph(subgraph => {rank => 'same'}) so that all nodes mentioned within the subgraph
873are constrained to be horizontally aligned.
874
875See scripts/rank.sub.graph.\[12\].pl and scripts/sub.graph.frames.pl for sample code.
876
877## valid\_attributes()
878
879Returns a hashref of all attributes known to this module, keyed by type
880to hashrefs to true values.
881
882Stored in this module, using [Data::Section::Simple](https://metacpan.org/pod/Data%3A%3ASection%3A%3ASimple).
883
884These attributes are used to validate attributes in many situations.
885
886You wouldn't normally need to use this method.
887
888See scripts/report.valid.attributes.pl. See ["Scripts Shipped with this Module" in GraphViz2](https://metacpan.org/pod/GraphViz2#Scripts-Shipped-with-this-Module).
889
890## run(\[driver => $exe, format => $string, timeout => $integer, output\_file => $output\_file\])
891
892Runs the given program to process the output stream.
893
894Returns $self to allow method chaining.
895
896Here, \[\] indicate optional parameters.
897
898$driver is the name of the external program to run.
899
900It defaults to the value supplied in the call to new(global => {driver => '...'}), which in turn defaults
901to [File::Which](https://metacpan.org/pod/File%3A%3AWhich)'s which('dot') return value.
902
903$format is the type of output file to write.
904
905It defaults to the value supplied in the call to new(global => {format => '...'}), which in turn defaults
906to 'svg'.
907
908$timeout is the time in seconds to wait while the external program runs, before dieing with an error.
909
910It defaults to the value supplied in the call to new(global => {timeout => '...'}), which in turn defaults
911to 10.
912
913$output\_file is the name of the file into which the output from the external program is written.
914
915There is no default value for $output\_file. If a value is not supplied for $output\_file, the only way
916to recover the output of the external program is to call dot\_output().
917
918This method performs a series of tasks:
919
920- Run the chosen external program on the ["dot\_input"](#dot_input)
921- Capture STDOUT and STDERR from that program
922- Die if STDERR contains anything
923- Copies STDOUT to the buffer controlled by the dot\_output() method
924- Write the captured contents of STDOUT to $output\_file, if $output\_file has a value
925
926## stringify\_attributes($context, $option)
927
928Returns a string suitable to writing to the output stream.
929
930$context is one of 'edge', 'graph', 'node', or a special string. See the code for details.
931
932You wouldn't normally need to use this method.
933
934## validate\_params($context, \\%attributes)
935
936Validate the given attributes within the given context.
937
938Also, if $context is 'subgraph', attributes are allowed to be in the 'cluster' context.
939
940Returns $self to allow method chaining.
941
942$context is one of 'edge', 'global', 'graph', or 'node'.
943
944You wouldn't normally need to use this method.
945
946## verbose(\[$integer\])
947
948Gets or sets the verbosity level, for when a logging object is not used.
949
950Here, \[\] indicates an optional parameter.
951
952# MISC
953
954## Graphviz version supported
955
956GraphViz2 targets V 2.34.0 of [Graphviz](http://www.graphviz.org/).
957
958This affects the list of available attributes per graph item (node, edge, cluster, etc) available.
959
960See the second column of the
961[Graphviz attribute docs](https://www.graphviz.org/doc/info/attrs.html) for details.
962
963## Supported file formats
964
965Parses the output of `dot -T?`, so depends on local installation.
966
967## Special characters in node names and labels
968
969[GraphViz2](https://metacpan.org/pod/GraphViz2) escapes these 2 characters in those contexts: \[\].
970
971Escaping the 2 chars \[\] started with V 2.10. Previously, all of \[\]{} were escaped, but {} are used in records
972to control the orientation of fields, so they should not have been escaped in the first place.
973
974It would be nice to also escape | and <, but these characters are used in specifying fields and ports in records.
975
976See the next couple of points for details.
977
978## Ports
979
980Ports are what [Graphviz](http://www.graphviz.org/) calls those places on the outline of a node where edges
981leave and terminate.
982
983The [Graphviz](http://www.graphviz.org/) syntax for ports is a bit unusual:
984
985- This works: "node\_name":port5
986- This doesn't: "node\_name:port5"
987
988Let me repeat - that is Graphviz syntax, not GraphViz2 syntax. In Perl, you must do this:
989
990        $graph -> add_edge(from => 'struct1:f1', to => 'struct2:f0', color => 'blue');
991
992You don't have to quote all node names in [Graphviz](http://www.graphviz.org/), but some, such as digits, must be quoted, so I've decided to quote them all.
993
994## How labels interact with ports
995
996You can specify labels with ports in these ways:
997
998- As a string
999
1000            $graph -> add_node(name => 'struct3', label => "hello\nworld |{ b |{c|<here> d|e}| f}| g | h");
1001
1002    Here, the string contains a port (&lt;here>), field markers (|), and orientation markers ({}).
1003
1004    Clearly, you must specify the field separator character '|' explicitly. In the next 2 cases, it is implicit.
1005
1006    Then you use $graph -> add\_edge(...) to refer to those ports, if desired:
1007
1008            $graph -> add_edge(from => 'struct1:f2', to => 'struct3:here', color => 'red');
1009
1010    The same label is specified in the next case.
1011
1012- As an arrayref of hashrefs
1013
1014    From scripts/record.2.pl:
1015
1016            $graph -> add_node(name => 'struct3', label =>
1017            [
1018                    {
1019                            text => "hello\nworld",
1020                    },
1021                    {
1022                            text => '{b',
1023                    },
1024                    {
1025                            text => '{c',
1026                    },
1027                    {
1028                            port => '<here>',
1029                            text => 'd',
1030                    },
1031                    {
1032                            text => 'e}',
1033                    },
1034                    {
1035                            text => 'f}',
1036                    },
1037                    {
1038                            text => 'g',
1039                    },
1040                    {
1041                            text => 'h',
1042                    },
1043            ]);
1044
1045    Each hashref is a field, and hence you do not specify the field separator character '|'.
1046
1047    Then you use $graph -> add\_edge(...) to refer to those ports, if desired. Again, from scripts/record.2.pl:
1048
1049            $graph -> add_edge(from => 'struct1:f2', to => 'struct3:here', color => 'red');
1050
1051    The same label is specified in the previous case.
1052
1053- As an arrayref of strings
1054
1055    From scripts/html.labels.1.pl:
1056
1057            $graph -> add_node(name => 'Oakleigh', shape => 'record', color => 'blue',
1058                    label => ['West Oakleigh', 'East Oakleigh']);
1059
1060    Here, again, you do not specify the field separator character '|'.
1061
1062    What happens is that each string is taken to be the label of a field, and each field is given
1063    an auto-generated port name of the form "&lt;port$n>", where $n starts from 1.
1064
1065    Here's how you refer to those ports, again from scripts/html.labels.1.pl:
1066
1067            $graph -> add_edge(from => 'Murrumbeena', to => 'Oakleigh:port2',
1068                    color => 'green', label => '<Drive<br/>Run<br/>Sprint>');
1069
1070See also the docs for the `add_node(name => $node_name, [%hash])` method.
1071
1072## Attributes for clusters
1073
1074Just use subgraph => {...}, because the code (as of V 2.22) accepts attributes belonging to either clusters or subgraphs.
1075
1076An example attribute is `pencolor`, which is used for clusters but not for subgraphs:
1077
1078        $graph->push_subgraph(
1079                graph    => {label => 'Child the Second'},
1080                name     => 'cluster Second subgraph',
1081                node     => {color => 'magenta', shape => 'diamond'},
1082                subgraph => {pencolor => 'white'}, # White hides the cluster's frame.
1083        );
1084        # other nodes or edges can be added within it...
1085        $graph->pop_subgraph;
1086
1087# TODO
1088
1089- Handle edges such as 1 -> 2 -> {A B}, as seen in [Graphviz](http://www.graphviz.org/)'s graphs/directed/switch.gv
1090
1091    But how?
1092
1093- Validate parameters more carefully, e.g. to reject non-hashref arguments where appropriate
1094
1095    Some method parameter lists take keys whose value must be a hashref.
1096
1097# A Extremely Short List of Other Graphing Software
1098
1099[Axis Maps](http://www.axismaps.com/).
1100
1101[Polygon Map Generation](http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/).
1102Read more on that [here](http://blogs.perl.org/users/max_maischein/2011/06/display-your-data---randompoissondisc.html).
1103
1104[Voronoi Applications](http://www.voronoi.com/wiki/index.php?title=Voronoi_Applications).
1105
1106# Thanks
1107
1108Many thanks are due to the people who chose to make [Graphviz](http://www.graphviz.org/) Open Source.
1109
1110And thanks to [Leon Brocard](http://search.cpan.org/~lbrocard/), who wrote [GraphViz](https://metacpan.org/pod/GraphViz), and kindly gave me co-maint of the module.
1111
1112# Version Numbers
1113
1114Version numbers < 1.00 represent development versions. From 1.00 up, they are production versions.
1115
1116# Repository
1117
1118[https://github.com/ronsavage/GraphViz2.git](https://github.com/ronsavage/GraphViz2.git)
1119
1120# Author
1121
1122[GraphViz2](https://metacpan.org/pod/GraphViz2) was written by Ron Savage _<ron@savage.net.au>_ in 2011.
1123
1124Home page: [http://savage.net.au/index.html](http://savage.net.au/index.html).
1125
1126# Copyright
1127
1128Australian copyright (c) 2011, Ron Savage.
1129
1130        All Programs of mine are 'OSI Certified Open Source Software';
1131        you can redistribute them and/or modify them under the terms of
1132        The Perl License, a copy of which is available at:
1133        http://dev.perl.org/licenses/
1134