#!/usr/bin/perl -w use strict; use warnings; use Graph::Easy; my $graph = Graph::Easy->new(); my $bonn = $graph->add_node('Bonn'); my $berlin = $graph->add_node('Berlin'); $graph->add_edge ($bonn, $berlin, 'car'); $berlin->set_attributes({ link => "http://www.visit-berlin.org/", label => "berlin"}); my $asc = $graph->as_ascii(); print "Original:\n"; print $asc."\n"; my $labelmap = pre_process_graph($graph); my $asc2 = $graph->as_ascii(); print "After pre-process:\n"; print $asc2."\n"; my $asc3 = post_process_ascii($labelmap, $asc2); print "After post-process:\n"; print $asc3."\n"; ########################################################################### # Scan graph object and replace labels on nodes. ########################################################################### sub pre_process_graph { my ($graph) = @_; my $labelmap = {}; # Just look at Node text for starters. foreach my $node ($graph->nodes()) { my $name = $node->name(); my $label = $node->attribute('label'); my $labeltext = defined $label ? $label : $name; $label = "undef" if !defined $label; #print "node: name=$name label=$label labeltext=$labeltext\n"; my $key = "$name,$label"; $labelmap->{$key} = { node => $node, name => $name, labeltext => $labeltext, }; } # How many labels have we found? my $count = scalar(keys %$labelmap); # Return early if nothing to do. return $labelmap if $count == 0; # How many digits identifier do we need? my $digits = length("$count"); # Create printf format: "_%01d", "_%02d" my $fmt = "_%0"."$digits"."d"; # label format is _01, _02 etc # so the min length is 3 if $digits == 2; (2 if $digits == 1) my $minlen = $digits + 1; my $labelnum = 1; foreach my $key (keys %$labelmap) { my $lmap = $labelmap->{$key}; my $textlen = length $lmap->{labeltext}; # Copy above default format string my $fmt = $fmt; # Pad string with underscores to maintain correct length. $fmt .= '_' x ($textlen - $minlen) if $textlen > $minlen; # Create new label. my $newlabel = sprintf $fmt, $labelnum; $lmap->{labelnum} = $labelnum; $lmap->{newlabel} = $newlabel; $lmap->{node}->set_attribute('label', $newlabel); $labelnum++; } return $labelmap; } ########################################################################### # Scan ascii string and replace labels on nodes. ########################################################################### sub post_process_ascii { my ($labelmap, $asc) = @_; foreach my $key (keys %$labelmap) { my $lmap = $labelmap->{$key}; my $newlabel = $lmap->{newlabel}; my $labeltext = $lmap->{labeltext}; my $link = $lmap->{node}->link(); # Pad out the old label if it was too short, # since we forced a minimum of 2 characters. my $minlen = length($newlabel); my $lablen = length($labeltext); $labeltext .= ' ' x ($minlen - $lablen) if $minlen > $lablen; if (defined $link && $link ne '') { my $href = "$labeltext"; # If a link, replace text with link. $asc =~ s/\b$newlabel\b/$href/s; } else { # If not a link, restore original label. $asc =~ s/\b$newlabel\b/$labeltext/s; } } return $asc; } __END__ Original: +------+ car +--------+ | Bonn | -----> | berlin | +------+ +--------+ After pre-process: +------+ car +--------+ | _1__ | -----> | _2____ | +------+ +--------+ After post-process: +------+ car +--------+ | Bonn | -----> | berlin | +------+ +--------+