File Coverage

lib/Gtk2/Ex/MindMapView/Item.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Gtk2::Ex::MindMapView::Item;
2              
3             our $VERSION = '0.000001';
4              
5 9     9   118092 use warnings;
  9         30  
  9         372  
6 9     9   51 use strict;
  9         22  
  9         12562  
7 9     9   58 use Carp;
  9         18  
  9         828  
8              
9 9     9   55 use List::Util;
  9         25  
  9         964  
10              
11 9     9   5933 use Gnome2::Canvas;
  0            
  0            
12              
13             use POSIX qw(DBL_MAX);
14              
15             use Glib ':constants';
16              
17             use Glib::Object::Subclass
18             Gnome2::Canvas::Group::,
19              
20             signals => {
21             'layout' => { flags => 'run-last' },
22             'connection_adjust' => { flags => 'run-last' },
23             'hotspot_adjust' => { flags => 'run-last' },
24             },
25              
26             properties => [
27             Glib::ParamSpec->scalar ('graph', 'graph',
28             'The graph that this item belongs to', G_PARAM_READWRITE),
29              
30             Glib::ParamSpec->scalar ('column', 'column',
31             'The column this item belongs to', G_PARAM_READWRITE),
32              
33             Glib::ParamSpec->scalar ('border', 'border',
34             'The border and containing content', G_PARAM_READWRITE),
35              
36             Glib::ParamSpec->boolean ('visible', 'visible', 'Indicates whether the item is visible',
37             TRUE, G_PARAM_READWRITE),
38              
39             Glib::ParamSpec->double ('x', 'x', 'Upper left X coord',
40             -(DBL_MAX), DBL_MAX, 0.0, G_PARAM_READWRITE),
41              
42             Glib::ParamSpec->double ('y', 'y', 'Upper left y coord',
43             -(DBL_MAX), DBL_MAX, 0.0, G_PARAM_READWRITE),
44              
45             Glib::ParamSpec->double ('height', 'height', 'Height of map item',
46             0.0, DBL_MAX, 25.0, G_PARAM_READWRITE),
47              
48             Glib::ParamSpec->double ('width', 'width', 'Width of map item',
49             0.0, DBL_MAX, 300.0, G_PARAM_READWRITE),
50             ]
51             ;
52              
53              
54             sub INIT_INSTANCE
55             {
56             my $self = shift(@_);
57              
58             $self->{graph} = undef;
59              
60             $self->{column} = undef;
61              
62             $self->{border} = undef;
63              
64             $self->{hotspots} = {};
65              
66             $self->{visible} = TRUE;
67              
68             $self->{date_time} = undef;
69             }
70              
71              
72             sub SET_PROPERTY
73             {
74             my ($self, $pspec, $newval) = @_;
75              
76             my $param_name = $pspec->get_name;
77              
78             # print "Item, SET_PROPERTY: name: $param_name value: $newval\n";
79              
80              
81             if ($param_name eq 'graph')
82             {
83             $self->{graph} = $newval;
84              
85             my @predecessors = $self->{graph}->predecessors($self);
86              
87             foreach my $predecessor_item (@predecessors)
88             {
89             $predecessor_item->signal_emit('hotspot_adjust');
90             }
91             }
92              
93              
94             if ($param_name eq 'border')
95             {
96             if (!$newval->isa('Gtk2::Ex::MindMapView::Border'))
97             {
98             print "Item, border: $newval\n";
99             croak "Unexpected border. Must be 'Gtk2::Ex::MindMapView::Border' type.\n";
100             }
101              
102             $newval->reparent($self);
103              
104             my $content = $newval->get('content');
105              
106             croak ("Cannot set border, no content defined.\n") if (!defined $content);
107              
108             $content->reparent($self);
109              
110             if (defined $self->{border})
111             {
112             my ($x, $y, $width, $height) = $self->{border}->get(qw(x y width height));
113              
114             $newval->set(x=>$x, y=>$y, width=>$width, height=>$height);
115              
116             $self->{border}->get('content')->destroy();
117              
118             $self->{border}->destroy();
119             }
120              
121             $self->{border} = $newval;
122              
123             $self->set(width=>$newval->get('width'), height=>$newval->get('height'));
124             }
125              
126              
127             if ($param_name eq 'column')
128             {
129             if (!$newval->isa('Gtk2::Ex::MindMapView::Layout::Column'))
130             {
131             croak "Unexpected column value.\nYou may only assign a " .
132             "'Gtk2::Ex::MindMapView::Layout::Column as a column.\n";
133             }
134              
135             $self->{column} = $newval;
136             }
137              
138              
139             if ($param_name eq 'visible')
140             {
141             $self->{visible} = $newval;
142              
143             if ($newval)
144             {
145             $self->show();
146             }
147             else
148             {
149             $self->hide();
150             }
151              
152             $self->signal_emit('connection_adjust');
153             }
154              
155              
156             if ($param_name eq 'x')
157             {
158             $self->{x} = $newval;
159              
160             if (defined $self->{border})
161             {
162             $self->{border}->set(x=>$newval);
163              
164             $self->signal_emit('hotspot_adjust');
165              
166             $self->signal_emit('connection_adjust');
167             }
168              
169             return;
170             }
171              
172            
173             if ($param_name eq 'y')
174             {
175             $self->{y} = $newval;
176              
177             if (defined $self->{border})
178             {
179             $self->{border}->set(y=>$newval);
180              
181             $self->signal_emit('hotspot_adjust');
182              
183             $self->signal_emit('connection_adjust');
184             }
185              
186             return;
187             }
188              
189              
190             if ($param_name eq 'height')
191             {
192             $self->{height} = $newval;
193              
194             if (defined $self->{border})
195             {
196             $self->{border}->set(height=>$newval);
197              
198             $self->signal_emit('hotspot_adjust');
199              
200             $self->signal_emit('connection_adjust');
201             }
202              
203             return;
204             }
205              
206             if ($param_name eq 'width')
207             {
208             $self->{width} = $newval;
209              
210             if (defined $self->{border})
211             {
212             $self->{border}->set(width=>$newval);
213              
214             $self->signal_emit('hotspot_adjust');
215              
216             $self->signal_emit('connection_adjust');
217             }
218              
219             return;
220             }
221             }
222              
223              
224             # $item->add_hotspot
225              
226             sub add_hotspot
227             {
228             my ($self, $hotspot_type, $hotspot) = @_;
229              
230             $self->{hotspots}{$hotspot_type} = $hotspot;
231             }
232              
233              
234             # $item->get_column_no();
235              
236             sub get_column_no
237             {
238             my $self = shift(@_);
239              
240             my $column = $self->{column};
241              
242             if (!defined $column)
243             {
244             croak "Attempt to get column_no on undefined column.\n";
245             }
246              
247             return $column->get('column_no');
248             }
249              
250              
251             # $item->get_connection_point('left');
252              
253             sub get_connection_point
254             {
255             my ($self, $side) = @_;
256              
257             return $self->{border}->get_connection_point($side);
258             }
259              
260              
261             # my ($top, $left, $bottom, $right) = $item->get_insets();
262              
263             sub get_insets
264             {
265             my $self = shift(@_);
266              
267             return $self->{border}->border_insets();
268             }
269              
270              
271             # my $min_height = $item->get_min_height();
272              
273             sub get_min_height
274             {
275             my $self = shift(@_);
276              
277             return 0 if (!defined $self->{border});
278              
279             return $self->{border}->get_min_height();
280             }
281              
282              
283             # my $min_width = $item->get_min_width();
284              
285             sub get_min_width
286             {
287             my $self = shift(@_);
288              
289             return 0 if (!defined $self->{border});
290              
291             return $self->{border}->get_min_width();
292             }
293              
294              
295             # $item->get_weight();
296              
297             sub get_weight
298             {
299             my $self = shift(@_);
300              
301             return ($self->get('height') * $self->get('width'));
302             }
303              
304              
305             # $item->is_visible();
306              
307             sub is_visible
308             {
309             my $self = shift(@_);
310              
311             return $self->get('visible');
312             }
313              
314              
315             # my @predecessors = $item->predecessors();
316              
317             sub predecessors
318             {
319             my $self = shift(@_);
320              
321             return () if (!defined $self->{graph});
322              
323             return $self->{graph}->predecessors($self);
324             }
325              
326              
327             # my @successors = $item->successors();
328             # my @successors = $item->successors('left');
329              
330             sub successors
331             {
332             my ($self, $side) = @_;
333              
334             return () if (!defined $self->{graph});
335              
336             my @items = $self->{graph}->successors($self);
337              
338             return () if (scalar @items == 0);
339              
340             return @items if (!defined $side);
341              
342             my $column = $self->get('column');
343              
344             return () if (!defined $column);
345              
346             my $column_no = $column->get('column_no');
347              
348             if ($side eq 'right')
349             {
350             return grep {$_->get_column_no() >= $column_no } @items;
351             }
352              
353             # $side eq 'left'
354              
355             return grep {$_->get_column_no() <= $column_no } @items;
356             }
357              
358              
359             # resize: adjust the size of this item. This routine is needed because
360             # the simple: $self->set(x=>$x1, width=>$width, height=>$height) is
361             # too slow due to an excessive number of signals.
362              
363             sub resize
364             {
365             my ($self, $side, $delta_x, $delta_y) = @_;
366              
367             return if (!defined $self->{border});
368              
369             $self->raise(1);
370              
371             my ($x, $width, $height) = _resize($self, $side, $delta_x, $delta_y);
372              
373             $self->{x} = $x;
374              
375             $self->{width} = $width;
376              
377             $self->{height} = $height;
378              
379             $self->{border}->set(x=>$x, width=>$width, height=>$height);
380              
381             $self->signal_emit('hotspot_adjust');
382              
383             $self->signal_emit('connection_adjust');
384             }
385              
386              
387             sub _resize
388             {
389             my ($self, $side, $delta_x, $delta_y) = @_;
390              
391             my $min_height = $self->{border}->get_min_height();
392              
393             my $min_width = $self->{border}->get_min_width();
394              
395             my ($x, $width, $height) = $self->get(qw(x width height));
396              
397             if ($side eq 'right')
398             {
399             my $new_width = List::Util::max($min_width, ($width + $delta_x));
400              
401             my $new_height = List::Util::max($min_height, ($height + $delta_y));
402              
403             return ($x, $new_width, $new_height);
404             }
405              
406             # $side eq 'left'
407              
408             my $new_width = List::Util::max($min_width, ($width - $delta_x));
409              
410             my $new_height = List::Util::max($min_height, ($height + $delta_y));
411              
412             my $new_x = ($new_width > $min_width) ? $x + $delta_x : $x;
413              
414             return ($new_x, $new_width, $new_height);
415             }
416              
417              
418             sub toggle
419             {
420             my ($self, @items) = @_;
421              
422             my $number_visible = grep {$_->is_visible()} @items;
423              
424             foreach my $item (@items)
425             {
426             if ($number_visible == 0)
427             {
428             my $date_time = $item->{hide_date_time};
429              
430             $self->{graph}->traverse_DFS($item, sub { _set_visible($_[0], $date_time); });
431             }
432             else
433             {
434             my $date_time = time();
435              
436             $self->{graph}->traverse_DFS($item, sub { _set_invisible($_[0], $date_time); });
437             }
438             }
439              
440             $self->signal_emit('layout');
441             }
442              
443              
444             sub _set_visible
445             {
446             my ($self, $date_time) = @_;
447              
448             # print "_set_visible, self: $self date_time: $date_time self date time: $self->{hide_date_time}\n";
449              
450             if ((!defined $self->{hide_date_time}) || ($self->{hide_date_time} == $date_time))
451             {
452             $self->set(visible=>TRUE);
453              
454             $self->{hide_date_time} = undef;
455             }
456             }
457              
458              
459             sub _set_invisible
460             {
461             my ($self, $date_time) = @_;
462              
463             # print "_set_invisible, self: $self date_time: $date_time\n";
464              
465             if ($self->is_visible())
466             {
467             $self->set(visible=>FALSE);
468              
469             $self->{hide_date_time} = $date_time;
470             }
471             }
472              
473              
474             1; # Magic true value required at end of module
475             __END__