File Coverage

blib/lib/VCG.pm
Criterion Covered Total %
statement 9 92 9.7
branch 0 42 0.0
condition 0 20 0.0
subroutine 3 9 33.3
pod 4 4 100.0
total 16 167 9.5


line stmt bran cond sub pod time code
1             package VCG;
2              
3 1     1   6690 use strict;
  1         2  
  1         42  
4 1     1   6 use vars qw($AUTOLOAD $VERSION $DEBUG $program);
  1         3  
  1         77  
5              
6 1     1   1553 use IPC::Run qw(run);
  1         68701  
  1         1278  
7              
8             $VERSION = '0.5';
9             $DEBUG = 0;
10             $program = "xvcg";
11              
12             =head1 NAME
13              
14             VCG - Interface to the VCG graphing tool
15              
16             =head1 SYNOPSIS
17              
18              
19             use VCG;
20             my $vcg = VCG->new(outfile=>'resulta.vcg');
21             $vcg->add_node(title => 'aaa');
22             $vcg->add_node(title => 'bbb', label='b');
23             $vcg->add_node(title => 'ccc', color=>'yellow');
24              
25             $vcg->add_edge(source => 'aaa', target=>'bbb');
26              
27             $vcg->output_as_pbm('mygraph.pbm');
28              
29             $vcg->output_as_ps(filename=>'mygraph.ps');
30              
31             my $data = $vcg->as_ppm();
32             open (OUTFILE, 'outfile.ppm') or die "error $!\n";
33             print OUTFILE $data;
34             close OUTFILE;
35              
36             =head1 DESCRIPTION
37              
38             This module provides an interface to to the vcg graphing tool. It supports a
39             limited selection of options and file formats. The vcg graphing tool homepage
40             is currently http://rw4.cs.uni-sb.de/users/sander/html/gsvcg1.html but is being actively
41             developed elsewhere.
42              
43             This module is based on Leon Brocard's GraphViz module, it tries
44             to provide a similar interface to offer some sense of consistency.
45              
46             VCG is now in active development and although Graph::Writer::VCG already exists,
47             this module provides a similar interface to graphviz and will be more closely tied
48             into vcg as it becomes more actively developed - see James Micheal DuPont's announcement
49             at http://mail.gnome.org/archives/dia-list/2003-February/msg00029.html.
50              
51             =cut
52              
53             =head1 METHODS
54              
55             =head2 new
56              
57             new objects are created using the constructor method 'new'.
58              
59             This method accepts name attributes in the form :
60              
61             my $vcg = VCG->new(outfile=>'foo.pbm')
62              
63             my $vcg = VCG->new(title=>'Dia Dependancies Diagram',debug=>1);
64              
65             my $vcg = VCG->new();
66              
67             my %config = ( xmax => 700, ymax=>700, program=>'xvcg', x=>30, y=>30 );
68             my $vcg = VCG->new(%config);
69              
70             my $vcg = VCG->new( outfile=>'diagram.ps', landscape=>1, paper=>'tabloid', spline=>1 );
71              
72             =cut
73              
74             sub new {
75 0     0 1   my $class = shift;
76 0           my %config = @_;
77              
78 0           my $self = \%config;;
79 0           bless($self, $class);
80 0           $self->{edges} = [];
81 0           $self->{nodes} = [];
82 0   0       $self->{title} ||= "untitled";
83 0   0       $self->{outfile} ||= "vcg.out";
84 0   0       $self->{program} ||= $program;
85 0           $self->{error} = "none - everything is fine";
86              
87 0 0         $DEBUG = 1 if ($config{debug});
88              
89 0           return $self;
90             }
91              
92             =head2 add_edge
93              
94             add_edge allows you to add edges to your vcg object (edges are the lines or relationships between nodes).
95              
96             In a Finite State Diagram, edges would represent transitions between states.
97              
98             This method accepts the source, target and colour of the edge :
99              
100             $vcg->add_edge( source=>'from_node', target=>'to_node');
101              
102             $vcg->add_edge( source=>'aaa', target=>'bbb', color=>'grey');
103              
104             =cut
105              
106             sub add_edge {
107 0     0 1   my $self = shift;
108 0           my %args = @_;
109 0   0       $args{color} ||= 'black';
110 0           my $edge = qq(edge: { sourcename: "$args{source}" targetname: "$args{target}" color: $args{color}});
111 0           push (@{$self->{edges}}, $edge);
  0            
112 0           return 1;
113             }
114              
115             =head2 add_node
116              
117             add_node allows you to add nodes to your vcg object (nodes are the things connected, while edges are the connections).
118              
119             In a Finite State Diagram, nodes would be the individual states.
120              
121             This method accepts the label, title and background colour of the node :
122              
123             $vcg->add_node( title=>'aaa' );
124              
125             $vcg->add_node( label=>'aaa' );
126              
127             $vcg->add_node( label=>'aaa', title=>'A', color=>'yellow' );
128              
129              
130             =cut
131              
132             sub add_node {
133 0     0 1   my $self = shift;
134 0           my %args = @_;
135 0   0       $args{color} ||= 'white';
136 0   0       $args{label} ||= $args{title};
137 0           my $node = qq(node: { title: "$args{title}" color: $args{color} label: "$args{label}"});
138 0           push (@{$self->{nodes}}, $node);
  0            
139 0           return 1;
140             }
141              
142             =head2 get_vcg_version
143              
144             You can get the version and copyright message as a string using the vcg object (requires vcg be installed)
145              
146             my $version = $vcg->get_vcg_version() or die "couldn't get version : $vcg->error() \n";
147              
148              
149             =cut
150              
151             sub get_vcg_version {
152 0     0 1   my $self = shift;
153 0           my $version;
154             my $error;
155 0           run [$self->{program}, '-version'], \undef, \$version, \$self->{error};
156 0           return $version;
157             }
158              
159              
160             ######################################################################################
161             # generate the vcg grammar for the graph
162              
163             sub _get_graph {
164 0     0     my $self = shift;
165 0           my $nodes = join ("\n",@{$self->{nodes}});
  0            
166 0           my $edges = join ("\n",@{$self->{edges}});
  0            
167 0           my $values = "";
168 0           foreach my $field (qw/xmax ymax x y/) {
169 0 0         $values .= "$field:$self->{$field} " if ( defined $self->{$field} );
170             }
171              
172 0           my $graph = <
173             graph: { title: "$self->{title}"
174             $values
175             $nodes
176             $edges
177             }
178             end
179 0           return $graph;
180             }
181              
182             =head2 as_ps, as_pbm, as_ppm, as_vcg, as_plainvcg
183              
184             The VCG object allows you to access the output of the vcg tool directly, suitable for using with graphic libraries - although some libraries or older versions may not be able to cope with these formats.
185              
186             You can access the output in any of postscript, pbm, ppm, vcg (annotated) and vcg (plain) :
187              
188             my $image_as_ppm = $vcg->as_ppm(); # string of image as formatted as ppm
189              
190             my $vcg_with_coords = $vcg->as_vcg(); # handy for building a pixmap or something or converting to dia xml for example
191              
192             =head2 output_as_ps, output_as_pbm, output_as_ppm
193              
194             The VCG object allows you to output straight to a file through the vcg tool in any of postscript, pbm and ppm. This functionality requires that the vcg tool be installed.
195              
196             $vcg->output_as_ps('my_diagram.ps'); # now open the file in the gimp or import into LaTeX and you can get this free Mad Scientist (TM) white coat and bunsen burner.
197              
198             =head2 output_as_vcg, output_as_plainvcg
199              
200             The VCG object also allows you to output straight to file in annotated vcg with coordinates, or plain vcg syntax. The plain syntax does not require the vcg tool to be installed.
201              
202             $vcg->output_as_plainvcg('compiler_graph.vcg'); # just in case you want to generate a diagram but don't have vcg installed.
203              
204             $vcg->output_as_vcg('compiler_graph_with_coords.vcg'); # lovely jubbly
205              
206             =cut
207              
208             ######################################################################################
209             # Generate magic methods to save typing
210              
211             sub AUTOLOAD {
212 0     0     my $self = shift;
213 0 0         my $type = ref($self)
214             or die "$self is not an object";
215              
216 0           my $name = $AUTOLOAD;
217 0           $name =~ s/.*://; # strip fully-qualified portion
218 0 0         return if $name =~ /DESTROY/;
219              
220 0 0         my $filename = shift() unless (scalar @_ % 2);
221 0           my %args = @_;
222 0   0       $filename ||= $args{filename};
223 0   0       $filename ||= $self->{outfile};
224              
225 0           my $vcg = $self->_get_graph();
226 0           my $output;
227              
228 0           my @vcg_args = ($filename);
229 0 0         push (@vcg_args, "-scale $self->{scale}") if (defined $self->{scale}) ;
230 0 0         push (@vcg_args, "-spline") if (defined $self->{spline}) ;
231 0 0         push (@vcg_args, "-paper $self->{paper}") if (defined $self->{paper}) ;
232 0 0         push (@vcg_args, "-portrait") if (defined $self->{portrait}) ;
233 0 0         push (@vcg_args, "-landscape") if (defined $self->{landscape}) ;
234              
235 0 0         if ($name =~ /^as_(ps|pbm|ppm|plainvcg|vcg)/) {
    0          
236 0           my $filetype = $1;
237 0           unshift(@vcg_args,"-$filetype".'output');
238 0 0         if ($filetype eq "plainvcg") {
239 0           $output = $vcg;
240             } else {
241 0 0         unlink $filename if (-f $filename);
242              
243 0           run [$self->{program}, @vcg_args , "- "], \$vcg, \$output;
244              
245 0 0         warn $output if ($DEBUG);
246              
247 0 0         open (FILE,$filename) or die "unable to open $filename : $!\n";
248 0           my $data = join ('',());
249 0           close FILE;
250 0 0         if (-f $filename) { unlink $filename or die "unable to remove tempory file $filename : $! \n"; }
  0 0          
251 0           $output = $data;
252             }
253             } elsif ($name =~ /output_as_(ps|pbm|ppm|plainvcg|vcg)$/){
254 0           my $filetype = $1;
255 0           unshift(@vcg_args,"-$filetype".'output');
256 0 0         if ($filetype eq "plainvcg") {
257 0 0         open OUTFILE,">$filename" or die "couldn't open $filename for output : $!\n";
258 0           print OUTFILE $vcg;
259 0           close OUTFILE;
260 0           $output = 1;
261             } else {
262 0 0         unlink $filename if (-f $filename);
263 0           run [$self->{program}, @vcg_args , "- "], \$vcg, \$output;
264             }
265             } else {
266 0           die "Method $name not defined!";
267             }
268 0           return $output;
269             }
270              
271              
272             ##########################################################################
273              
274             =head1 SEE ALSO
275              
276             GraphViz : http://www.graphviz.org
277              
278             GraphViz perl module
279              
280             Graph::Writer::VCG perl module
281              
282             vcg/xvcg : man pages
283              
284             =head1 AUTHOR
285              
286             Aaron Trevena EFE
287              
288             =head1 COPYRIGHT
289              
290             Copyright (C) 2003, Aaron Trevena, Leon Brocard
291              
292             This module is free software; you can redistribute it or modify it
293             under the same terms as Perl itself.
294              
295             =cut
296              
297             ##########################################################################
298              
299             1;
300              
301             ##########################################################################
302             ##########################################################################