File Coverage

lib/Gtk2/Ex/MindMapView/Graph.pm
Criterion Covered Total %
statement 12 97 12.3
branch 0 16 0.0
condition 0 3 0.0
subroutine 4 20 20.0
pod 13 13 100.0
total 29 149 19.4


line stmt bran cond sub pod time code
1             package Gtk2::Ex::MindMapView::Graph;
2              
3             our $VERSION = '0.000001';
4              
5 1     1   1870 use warnings;
  1         3  
  1         28  
6 1     1   5 use strict;
  1         2  
  1         28  
7 1     1   8 use Carp;
  1         2  
  1         86  
8              
9 1     1   852 use Graph::Directed;
  1         250257  
  1         1414  
10              
11              
12             # $graph = Gtk2::Ex::MindMapView::Graph->new();
13              
14             sub new
15             {
16 0     0 1   my $class = shift(@_);
17              
18 0           my $self = {};
19              
20 0           bless $self, $class;
21              
22 0           $self->{graph} = Graph::Directed->new(refvertexed=>1);
23              
24 0           $self->{root} = undef;
25              
26 0           return $self;
27             }
28              
29              
30             # $graph->add($item);
31             # $graph->add($predecessor_item, $item);
32              
33             sub add
34             {
35 0     0 1   my ($self, $predecessor_item, $item) = @_;
36              
37 0 0         if (!defined $item)
38             {
39 0 0         if (defined $self->{root})
40             {
41 0           croak "A root has already been defined. " .
42             "Use set_root to change the root.\n";
43             }
44              
45 0           $self->{root} = $predecessor_item;
46              
47 0           $self->{graph}->add_vertex($predecessor_item);
48              
49 0           return;
50             }
51              
52 0           $self->{graph}->add_edge($predecessor_item, $item);
53             }
54              
55              
56             # $root = $graph->get_root();
57              
58             sub get_root
59             {
60 0     0 1   my $self = shift(@_);
61              
62 0           return $self->{root};
63             }
64              
65              
66             # $boolean = $graph->has_item($item);
67              
68             sub has_item
69             {
70 0     0 1   my ($self, $item) = @_;
71              
72 0           return $self->{graph}->has_vertex($item);
73             }
74              
75              
76             # $num_items = $graph->num_items();
77              
78             sub num_items
79             {
80 0     0 1   my $self = shift(@_);
81              
82 0           my $num_items = $self->{graph}->vertices();
83              
84 0           return $num_items;
85             }
86              
87              
88             # @predecessors = $graph->predecessors($item);
89              
90             sub predecessors
91             {
92 0     0 1   my ($self, $item) = @_;
93              
94 0           return $self->{graph}->predecessors($item);
95             }
96              
97              
98             # $graph->remove($item);
99             # $graph->remove($predecessor_item, $item);
100              
101             sub remove
102             {
103 0     0 1   my ($self, $predecessor_item, $item) = @_;
104              
105 0           my $graph = $self->{graph};
106              
107 0           my @successors = $graph->successors($item);
108              
109 0 0         if (scalar @successors > 0)
110             {
111 0           croak "You must remove the successors of this item " .
112             "prior to removing this item.\n";
113             }
114              
115 0 0         if (!defined $item)
116             {
117 0 0         if ($predecessor_item != $self->{root})
118             {
119 0           croak "You must pass in both the predecessor and " .
120             "the item you wish to remove.\n";
121             }
122              
123 0           $graph->delete_vertex($predecessor_item);
124              
125 0           $self->{root} = undef;
126              
127 0           return;
128             }
129              
130 0           $graph->delete_edge($predecessor_item, $item);
131              
132 0           my @predecessors = $graph->predecessors($item);
133              
134 0 0         if (scalar @predecessors == 0)
135             {
136 0           $graph->delete_vertex($item);
137             }
138             }
139              
140              
141             # @successors = $graph->successors($item);
142              
143             sub successors
144             {
145 0     0 1   my ($self, $item) = @_;
146              
147 0           return $self->{graph}->successors($item);
148             }
149              
150              
151             # $graph->set_root($item);
152              
153             sub set_root
154             {
155 0     0 1   my ($self, $item) = @_;
156              
157 0           my $graph = $self->{graph};
158              
159 0           my $new_graph = Graph::Directed->new(refvertexed=>1);
160              
161 0           $new_graph->add_vertex($item);
162              
163 0           _set_root($self, $new_graph, $item, undef);
164              
165 0           $self->{graph} = $new_graph;
166              
167 0           $self->{root} = $item;
168             }
169              
170              
171             # $graph->traverse_BFS($item, $callack);
172              
173             sub traverse_BFS
174             {
175 0     0 1   my ($self, $item, $callback) = @_;
176              
177 0           my @pairs = ();
178              
179 0           _traverse_pairs($self, \@pairs, 0, $item);
180              
181 0 0         my @sorted_pairs = sort { ($a->[0] <=> $b->[0]) ||
  0            
182             ($a->[1] <=> $b->[1]) } @pairs;
183              
184 0           foreach my $pair_ref (@sorted_pairs)
185             {
186 0           &$callback($pair_ref->[1]);
187             }
188             }
189              
190              
191             # $graph->traverse_DFS($item, $callback)
192              
193             sub traverse_DFS
194             {
195 0     0 1   my ($self, $item, $callback) = @_;
196              
197 0           &$callback($item);
198              
199 0           my @successors = $self->{graph}->successors($item);
200              
201 0           foreach my $successor_item (@successors)
202             {
203 0           $self->traverse_DFS($successor_item, $callback);
204             }
205             }
206              
207              
208             # $graph->traverse_postorder_edge($predecessor_item, $item, $callback);
209              
210             sub traverse_postorder_edge
211             {
212 0     0 1   my ($self, $predecessor_item, $item, $callback) = @_;
213              
214 0           my @successors = $self->{graph}->successors($item);
215              
216 0           foreach my $successor_item (@successors)
217             {
218 0           traverse_postorder_edge($self, $item, $successor_item, $callback);
219             }
220              
221 0           &$callback($predecessor_item, $item);
222             }
223              
224              
225             # $graph->traverse_preorder_edge($predecessor_item, $item, $callback);
226              
227             sub traverse_preorder_edge
228             {
229 0     0 1   my ($self, $predecessor_item, $item, $callback) = @_;
230              
231 0           &$callback($predecessor_item, $item);
232              
233 0           my @successors = $self->{graph}->successors($item);
234              
235 0           foreach my $successor_item (@successors)
236             {
237 0           traverse_preorder_edge($self, $item, $successor_item, $callback);
238             }
239             }
240              
241              
242             sub _set_root
243             {
244 0     0     my ($self, $new_graph, $item, $verboten_item) = @_;
245              
246 0           my @successors = $self->{graph}->successors($item);
247              
248 0           foreach my $successor_item (@successors)
249             {
250 0 0 0       next if ((defined $verboten_item) && ($successor_item == $verboten_item));
251              
252             $self->traverse_preorder_edge($item, $successor_item,
253 0     0     sub { $new_graph->add_edge($_[0], $_[1]); });
  0            
254             }
255              
256 0           my @predecessors = $self->{graph}->predecessors($item);
257              
258 0           foreach my $predecessor_item (@predecessors)
259             {
260 0           $new_graph->add_edge($item, $predecessor_item);
261              
262 0           _set_root($self, $new_graph, $predecessor_item, $item);
263             }
264             }
265              
266              
267             sub _traverse_pairs
268             {
269 0     0     my ($self, $pairs_ref, $level, $item) = @_;
270              
271 0           push @{$pairs_ref}, [$level, $item];
  0            
272              
273 0           my @successors = $self->{graph}->successors($item);
274              
275 0           foreach my $successor_item (@successors)
276             {
277 0           _traverse_pairs($self, $pairs_ref, $level + 1, $successor_item);
278             }
279              
280             }
281              
282              
283              
284             1; # Magic true value required at end of module
285             __END__