line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#######################################################DWidth |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Family Tree generation program, v2.0 |
4
|
|
|
|
|
|
|
# Written by Ferenc Bodon and Simon Ward, March 2000 (simonward.com) |
5
|
|
|
|
|
|
|
# Copyright (C) 2000 Ferenc Bodon, Simon K Ward |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or |
8
|
|
|
|
|
|
|
# modify it under the terms of the GNU General Public License |
9
|
|
|
|
|
|
|
# as published by the Free Software Foundation; either version 2 |
10
|
|
|
|
|
|
|
# of the License, or (at your option) any later version. |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
13
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
14
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15
|
|
|
|
|
|
|
# GNU General Public License for more details. |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
# For a copy of the GNU General Public License, visit |
18
|
|
|
|
|
|
|
# http://www.gnu.org or write to the Free Software Foundation, Inc., |
19
|
|
|
|
|
|
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20
|
|
|
|
|
|
|
# |
21
|
|
|
|
|
|
|
####################################################### |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
package Ftree::FamilyTreeGraphics; |
25
|
1
|
|
|
1
|
|
22518
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
35
|
|
26
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
43
|
|
27
|
|
|
|
|
|
|
|
28
|
1
|
|
|
1
|
|
731
|
use version; our $VERSION = qv('2.3.31'); |
|
1
|
|
|
|
|
4189
|
|
|
1
|
|
|
|
|
7
|
|
29
|
|
|
|
|
|
|
|
30
|
1
|
|
|
1
|
|
710
|
use Ftree::FamilyTreeBase; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
7
|
|
31
|
|
|
|
|
|
|
|
32
|
1
|
|
|
1
|
|
201
|
use Params::Validate qw(:all); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
213
|
|
33
|
1
|
|
|
1
|
|
5
|
use List::Util qw(first max); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
98
|
|
34
|
1
|
|
|
1
|
|
6
|
use List::MoreUtils qw(first_index); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
12
|
|
35
|
1
|
|
|
1
|
|
547
|
use CGI::Carp qw(fatalsToBrowser warningsToBrowser); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
9
|
|
36
|
1
|
|
|
1
|
|
96
|
use Sub::Exporter -setup => { exports => [ qw(new main) ] }; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
9
|
|
37
|
1
|
|
|
1
|
|
383
|
use utf8; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
38
|
1
|
|
|
1
|
|
31
|
use Encode qw(decode_utf8); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
34
|
|
39
|
1
|
|
|
1
|
|
550
|
use Ftree::Picture; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
75
|
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
####################################################### |
44
|
|
|
|
|
|
|
# |
45
|
|
|
|
|
|
|
# The HTML output table is generated in three parts: |
46
|
|
|
|
|
|
|
# - the Ancestor tree (ATree) |
47
|
|
|
|
|
|
|
# - the peer level (peers) |
48
|
|
|
|
|
|
|
# - the Descendant tree (DTree) |
49
|
|
|
|
|
|
|
# |
50
|
|
|
|
|
|
|
# |
51
|
|
|
|
|
|
|
####################################################### |
52
|
|
|
|
|
|
|
|
53
|
1
|
|
|
1
|
|
6
|
use base 'Ftree::FamilyTreeBase'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5051
|
|
54
|
|
|
|
|
|
|
sub new{ |
55
|
0
|
|
|
0
|
0
|
|
my $type = shift; |
56
|
0
|
|
|
|
|
|
my $self = $type->SUPER::new(@_); |
57
|
0
|
|
|
|
|
|
$self->{target_person} = undef; |
58
|
0
|
|
|
|
|
|
$self->{DLevels} = 0; # nr of levels in DTree |
59
|
0
|
|
|
|
|
|
$self->{cellwidth} = undef; # width of a cell |
60
|
0
|
|
|
|
|
|
$self->{gridWidth} = undef; # width of the tree |
61
|
0
|
|
|
|
|
|
$self->{fontsize} = undef; |
62
|
|
|
|
|
|
|
|
63
|
0
|
|
|
|
|
|
return $self; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub main{ |
67
|
0
|
|
|
0
|
0
|
|
my ($self) = validate_pos(@_, HASHREF); |
68
|
0
|
|
|
|
|
|
$self->_process_parameters(); |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
$Person::unknown_male->set_default_picture(Picture->new( |
71
|
0
|
|
|
|
|
|
{file_name => $self->{graphicsUrl} . '/nophoto_m.jpg', |
72
|
|
|
|
|
|
|
comment => ""})); |
73
|
|
|
|
|
|
|
$Person::unknown_female->set_default_picture(Picture->new( |
74
|
0
|
|
|
|
|
|
{file_name => $self->{graphicsUrl} . '/nophoto_f.jpg', |
75
|
|
|
|
|
|
|
comment => ""})); |
76
|
|
|
|
|
|
|
|
77
|
0
|
|
|
|
|
|
$self->_target_check(); |
78
|
0
|
|
|
|
|
|
$self->set_size(); |
79
|
0
|
|
|
|
|
|
$self->_password_check(); |
80
|
|
|
|
|
|
|
|
81
|
0
|
0
|
|
|
|
|
if ( $self->{reqLevels} > 0 ) { |
82
|
0
|
|
|
|
|
|
$self->_draw_familytree_page(); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
else { |
85
|
0
|
|
|
|
|
|
my $address = $self->{cgi}->url(-relative=>0); |
86
|
0
|
|
|
|
|
|
$address =~ s/$self->{treeScript}/$self->{personScript}/xm; |
87
|
|
|
|
|
|
|
$address .= "?target=".$self->{target_person}->get_id() |
88
|
0
|
|
|
|
|
|
.";lang=".$self->{lang}; |
89
|
0
|
|
|
|
|
|
print $self->{cgi}->redirect($address); |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
|
return; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
####################################################### |
96
|
|
|
|
|
|
|
# processing the parameters (type and passwd) |
97
|
|
|
|
|
|
|
sub _process_parameters { |
98
|
0
|
|
|
0
|
|
|
my ($self) = validate_pos(@_, HASHREF); |
99
|
0
|
|
|
|
|
|
$self->SUPER::_process_parameters(); |
100
|
0
|
|
|
|
|
|
my $id = decode_utf8(CGI::param('target')); |
101
|
|
|
|
|
|
|
my $family_tree_data = |
102
|
0
|
|
|
|
|
|
Ftree::FamilyTreeDataFactory::getFamilyTree( $self->{settings}{data_source} ); |
103
|
0
|
|
|
|
|
|
$self->{target_person} = $family_tree_data->get_person($id); |
104
|
0
|
|
|
|
|
|
$self->{reqLevels} = CGI::param('levels'); |
105
|
0
|
0
|
|
|
|
|
$self->{reqLevels} = 2 unless ( defined $self->{reqLevels} ); |
106
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
return; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
####################################################### |
111
|
|
|
|
|
|
|
# check if target person exists in database |
112
|
|
|
|
|
|
|
sub _target_check { |
113
|
0
|
|
|
0
|
|
|
my ($self) = validate_pos(@_, HASHREF); |
114
|
0
|
0
|
|
|
|
|
if ( !defined $self->{target_person} ) { |
115
|
0
|
|
|
|
|
|
my $title = $self->{textGenerator}->noDataAbout( CGI::param('target') ); |
116
|
0
|
|
|
|
|
|
$self->_toppage($title); |
117
|
0
|
|
|
|
|
|
print $self->{cgi}->br, $title, $self->{cgi}->br, "\n"; |
118
|
0
|
|
|
|
|
|
$self->_endpage(); |
119
|
0
|
|
|
|
|
|
exit 1; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
0
|
|
|
|
|
|
return; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
####################################################### |
126
|
|
|
|
|
|
|
# Size the output according to the no. levels being displayed |
127
|
|
|
|
|
|
|
sub set_size { |
128
|
0
|
|
|
0
|
0
|
|
my ($self) = validate_pos(@_, HASHREF); |
129
|
0
|
0
|
|
|
|
|
if ( $self->{reqLevels} > 3 ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
130
|
0
|
|
|
|
|
|
$self->{imgwidth} = 45; |
131
|
0
|
|
|
|
|
|
$self->{fontsize} = 1; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
elsif ( $self->{reqLevels} == 3 ) { |
134
|
0
|
|
|
|
|
|
$self->{imgwidth} = 60; |
135
|
0
|
|
|
|
|
|
$self->{fontsize} = 2; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
elsif ( $self->{reqLevels} == 2 ) { |
138
|
0
|
|
|
|
|
|
$self->{imgwidth} = 90; |
139
|
0
|
|
|
|
|
|
$self->{fontsize} = 3; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
elsif ( $self->{reqLevels} == 1 ) { |
142
|
0
|
|
|
|
|
|
$self->{imgwidth} = 110; |
143
|
0
|
|
|
|
|
|
$self->{fontsize} = 2; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
elsif ( $self->{reqLevels} == 0 ) { |
146
|
0
|
|
|
|
|
|
$self->{imgwidth} = 240; |
147
|
0
|
|
|
|
|
|
$self->{fontsize} = 2; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
else { |
150
|
0
|
|
|
|
|
|
$self->{cellwidth} = 70; |
151
|
0
|
|
|
|
|
|
$self->{imgwidth} = 60; |
152
|
0
|
|
|
|
|
|
$self->{fontsize} = 2; |
153
|
|
|
|
|
|
|
} |
154
|
0
|
|
|
|
|
|
$self->{cellwidth} = "100%"; |
155
|
0
|
|
|
|
|
|
$self->{imgheight} = $self->{imgwidth} * 1.5; |
156
|
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
|
return; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub html_img { |
161
|
0
|
|
|
0
|
0
|
|
my ( $self, $person ) = validate_pos(@_, HASHREF, SCALARREF); |
162
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
|
my $img = $self->SUPER::html_img($person); |
164
|
|
|
|
|
|
|
return ($person == $self->{target_person} || |
165
|
0
|
0
|
0
|
|
|
|
$person == $Person::unknown_male || |
166
|
|
|
|
|
|
|
$person == $Person::unknown_female ) ? $img : $self->aref_tree($img, $person); |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub img_graph { |
170
|
0
|
|
|
0
|
0
|
|
my ( $self, $graphics ) = validate_pos(@_, HASHREF, SCALAR, 0); |
171
|
|
|
|
|
|
|
return $self->{cgi}->img( |
172
|
|
|
|
|
|
|
{ |
173
|
|
|
|
|
|
|
-width => $self->{cellwidth}, |
174
|
0
|
|
|
|
|
|
-height=> "26", |
175
|
|
|
|
|
|
|
-src => "$self->{graphicsUrl}/".$graphics.".gif", |
176
|
|
|
|
|
|
|
-alt => "", |
177
|
|
|
|
|
|
|
} ); |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
sub hone_img_graph { |
180
|
0
|
|
|
0
|
0
|
|
my ( $self ) = validate_pos(@_, HASHREF, 0); |
181
|
0
|
|
|
|
|
|
return $self->img_graph('hone'); |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
sub getATreeWidth { |
184
|
0
|
|
|
0
|
0
|
|
my ( $self, $levels ) = validate_pos(@_, HASHREF, SCALAR, 0); |
185
|
0
|
|
|
|
|
|
return 2**( $levels ); |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
####################################################### |
188
|
|
|
|
|
|
|
# returns the width of tree below this person |
189
|
|
|
|
|
|
|
# root_person: this person |
190
|
|
|
|
|
|
|
# levels: no. of levels to descend in tree |
191
|
|
|
|
|
|
|
sub getDTreeWidth { |
192
|
0
|
|
|
0
|
0
|
|
my ( $self, $levels, $root_person ) = validate_pos(@_, |
193
|
|
|
|
|
|
|
HASHREF, SCALAR, SCALARREF ); |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# carp "called: getDTreeWidth with \$root_person = " . $root_person->get_name()->get_long_name() . ", \$levels = $levels"; |
196
|
|
|
|
|
|
|
|
197
|
0
|
0
|
|
|
|
|
return 1 if ( 0 == $levels); |
198
|
0
|
0
|
0
|
|
|
|
return 1 if ($root_person == $Person::unknown_male || |
199
|
|
|
|
|
|
|
$root_person == $Person::unknown_female); |
200
|
0
|
0
|
|
|
|
|
return 1 unless defined $root_person->get_children(); |
201
|
|
|
|
|
|
|
|
202
|
0
|
|
|
|
|
|
my $width = 0; |
203
|
|
|
|
|
|
|
$width += $self->getDTreeWidth( $levels - 1, $_ ) |
204
|
0
|
|
|
|
|
|
for ( @{ $root_person->get_children() } ); |
|
0
|
|
|
|
|
|
|
205
|
0
|
|
|
|
|
|
return $width; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
####################################################### |
209
|
|
|
|
|
|
|
# returns the no. levels available in Ancestor tree |
210
|
|
|
|
|
|
|
# above this person |
211
|
|
|
|
|
|
|
# root_person: this person |
212
|
|
|
|
|
|
|
# anc_level: current level of ancestor tree (0=root_node) |
213
|
|
|
|
|
|
|
# req_levels: no. levels requested |
214
|
|
|
|
|
|
|
sub getATreeLevels { |
215
|
0
|
|
|
0
|
0
|
|
my ( $self, $root_person, $anc_level, $req_levels ) = validate_pos(@_, |
216
|
|
|
|
|
|
|
HASHREF, {type => SCALARREF|UNDEF}, SCALAR, SCALAR ); |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# print "called: getATreeLevels (root_node=$root_person->get_name()->get_full_name(), anc_level=$anc_level, req_levels=$req_levels)\n"; |
219
|
0
|
0
|
|
|
|
|
return 0 if ( $req_levels == 0 ); |
220
|
0
|
0
|
|
|
|
|
return $anc_level unless defined $root_person; |
221
|
0
|
0
|
0
|
|
|
|
return $anc_level unless ( defined $root_person->get_father() || |
222
|
|
|
|
|
|
|
defined $root_person->get_mother()); |
223
|
0
|
0
|
|
|
|
|
return $anc_level if($anc_level == $req_levels ); |
224
|
|
|
|
|
|
|
|
225
|
0
|
|
|
|
|
|
my $p1_levels = $self->getATreeLevels( $root_person->get_father(), |
226
|
|
|
|
|
|
|
$anc_level + 1, $req_levels ); |
227
|
0
|
|
|
|
|
|
my $p2_levels = $self->getATreeLevels( $root_person->get_mother(), |
228
|
|
|
|
|
|
|
$anc_level + 1, $req_levels ); |
229
|
0
|
|
|
|
|
|
return List::Util::max($p1_levels, $p2_levels); |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
####################################################### |
233
|
|
|
|
|
|
|
# populate the Descendant Tree structure for all |
234
|
|
|
|
|
|
|
# people below the person specified |
235
|
|
|
|
|
|
|
# $root_person: this person |
236
|
|
|
|
|
|
|
# dec_level: current level of descendant tree (0=root_node) |
237
|
|
|
|
|
|
|
# req_levels: no. levels requested |
238
|
|
|
|
|
|
|
sub fillDTree { |
239
|
0
|
|
|
0
|
0
|
|
my ( $self, $root_person, $dec_level, $req_levels, $DTree_ref ) = validate_pos(@_, |
240
|
|
|
|
|
|
|
HASHREF, SCALARREF, SCALAR, SCALAR, ARRAYREF ); |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# print "called: fillDTree (root_node=$root_node_id, dec_level=$dec_level, req_levels=$req_levels)\n"; |
243
|
0
|
|
|
|
|
|
$dec_level++; |
244
|
|
|
|
|
|
|
|
245
|
0
|
0
|
0
|
|
|
|
if ( $root_person != $Person::unknown_male |
|
|
|
0
|
|
|
|
|
246
|
|
|
|
|
|
|
&& $root_person != $Person::unknown_female |
247
|
|
|
|
|
|
|
&& defined $root_person->get_children() ) { |
248
|
0
|
|
|
|
|
|
push @{ $DTree_ref->[$dec_level] }, @{$root_person->get_children()}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
249
|
0
|
0
|
|
|
|
|
$self->{DLevels} = $dec_level if ( $dec_level > $self->{DLevels} ); |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
else { |
252
|
0
|
|
|
|
|
|
push @{ $DTree_ref->[$dec_level] }, $Person::unknown_female; |
|
0
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
0
|
0
|
|
|
|
|
if ( $dec_level < $req_levels ) { |
256
|
0
|
0
|
|
|
|
|
if(defined $root_person->get_children()) { |
257
|
|
|
|
|
|
|
$self->fillDTree( $_, $dec_level, $req_levels, $DTree_ref ) |
258
|
0
|
|
|
|
|
|
for ( @{ $root_person->get_children() } ); |
|
0
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
else { |
261
|
0
|
|
|
|
|
|
$self->fillDTree( $Person::unknown_female, $dec_level, $req_levels, $DTree_ref ); |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
0
|
|
|
|
|
|
return; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub putNTD { |
269
|
0
|
|
|
0
|
0
|
|
my ( $self, $n, $data ) = validate_pos(@_, |
270
|
|
|
|
|
|
|
HASHREF, SCALAR, {type => SCALAR, default => ""} ); |
271
|
0
|
|
|
|
|
|
print $self->{cgi}->td($data), "\n" for (1 .. $n); |
272
|
|
|
|
|
|
|
|
273
|
0
|
|
|
|
|
|
return; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
sub drawRow { |
276
|
0
|
|
|
0
|
0
|
|
my ( $self, $used_width, $people, $diff_levels, $this_level, |
277
|
|
|
|
|
|
|
$left_fill, $emptyTDCond, $group_width_func, $display_func ) = validate_pos(@_, |
278
|
|
|
|
|
|
|
HASHREF, SCALAR, ARRAYREF, {type => SCALAR|UNDEF}, |
279
|
|
|
|
|
|
|
{type => SCALAR|UNDEF}, SCALAR, CODEREF, CODEREF, CODEREF ); |
280
|
0
|
|
|
|
|
|
my $right_fill = $self->{gridWidth} - $used_width - $left_fill; |
281
|
0
|
|
|
|
|
|
my $is_blank_line = 1; |
282
|
|
|
|
|
|
|
|
283
|
0
|
|
|
|
|
|
print $self->{cgi}->start_Tr, "\n"; |
284
|
0
|
|
|
|
|
|
$self->putNTD($left_fill); |
285
|
0
|
|
|
|
|
|
foreach my $person (@{$people}) { |
|
0
|
|
|
|
|
|
|
286
|
0
|
|
|
|
|
|
my $group_width = $group_width_func->($self, $diff_levels, $person); |
287
|
0
|
|
|
|
|
|
my $left = int( ( $group_width - 1 ) / 2 ); |
288
|
0
|
|
|
|
|
|
my $right = $group_width - 1 - $left; |
289
|
|
|
|
|
|
|
|
290
|
0
|
|
|
|
|
|
$self->putNTD($left); |
291
|
0
|
0
|
|
|
|
|
if ( $emptyTDCond->($self, $person, $this_level) ) { |
292
|
0
|
|
|
|
|
|
print $self->{cgi}->td(), "\n"; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
else { |
295
|
0
|
|
|
|
|
|
print $self->{cgi}->td( {-align => "center" }, |
296
|
|
|
|
|
|
|
$display_func->($self, $person) ); |
297
|
0
|
|
|
|
|
|
$is_blank_line = 0; |
298
|
|
|
|
|
|
|
} |
299
|
0
|
|
|
|
|
|
$self->putNTD($right); |
300
|
|
|
|
|
|
|
} |
301
|
0
|
|
|
|
|
|
$self->putNTD($right_fill); |
302
|
0
|
|
|
|
|
|
print $self->{cgi}->end_Tr, "\n"; |
303
|
|
|
|
|
|
|
|
304
|
0
|
|
|
|
|
|
return $is_blank_line; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
sub unknownEquiCond { |
307
|
0
|
|
|
0
|
0
|
|
my ( $self, $person ) = validate_pos(@_, HASHREF, SCALARREF, 0 ); |
308
|
0
|
|
0
|
|
|
|
return $person == $Person::unknown_male || $person == $Person::unknown_female; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
sub unknownEquiNoChildrenCond { |
311
|
0
|
|
|
0
|
0
|
|
my ( $self, $person, $this_level ) = validate_pos(@_, |
312
|
|
|
|
|
|
|
HASHREF, SCALARREF, SCALAR ); |
313
|
|
|
|
|
|
|
return $person == $Person::unknown_female || |
314
|
|
|
|
|
|
|
$person == $Person::unknown_male || |
315
|
|
|
|
|
|
|
! defined $person->get_children() || |
316
|
0
|
|
0
|
|
|
|
( $this_level == $self->{reqLevels} ); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
sub falseCond { |
319
|
0
|
|
|
0
|
0
|
|
return 0; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
####################################################### |
322
|
|
|
|
|
|
|
# generate a line of the D-tree graphics OVER the |
323
|
|
|
|
|
|
|
# level specified |
324
|
|
|
|
|
|
|
# this_level: level of grid to generate |
325
|
|
|
|
|
|
|
# max_levels: max depth that will be shown |
326
|
|
|
|
|
|
|
sub getDGridLineG { |
327
|
0
|
|
|
0
|
0
|
|
my ( $self, $this_level, $max_levels, $DWidth, $DTree_ref ) = validate_pos(@_, |
328
|
|
|
|
|
|
|
HASHREF, SCALAR, SCALAR, SCALAR, ARRAYREF ); |
329
|
|
|
|
|
|
|
# print "called: getDGridLineG (this_level = $this_level, max_levels = $max_levels)\n"; |
330
|
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
my ( $left_fill, $branch, $right_fill ); |
332
|
0
|
|
|
|
|
|
my $lefto_fill = int( ( $self->{gridWidth} - $DWidth ) / 2 ); |
333
|
0
|
|
|
|
|
|
my $righto_fill = $self->{gridWidth} - $DWidth - $lefto_fill; |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# Spacers on LHS - fills gap between overall grid width and width of Dgrid |
336
|
0
|
|
|
|
|
|
print $self->{cgi}->start_Tr, "\n"; |
337
|
0
|
|
|
|
|
|
$self->putNTD($lefto_fill); |
338
|
|
|
|
|
|
|
|
339
|
0
|
0
|
|
|
|
|
if ( @{ $DTree_ref->[$this_level] } == 0 ) { |
|
0
|
|
|
|
|
|
|
340
|
0
|
|
|
|
|
|
printf '|;'; |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
else { |
343
|
0
|
|
|
|
|
|
foreach my $person (@{ $DTree_ref->[$this_level] }) { |
|
0
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
# Find which parent is in the level above... |
345
|
0
|
|
|
|
|
|
my $this_parent; |
346
|
|
|
|
|
|
|
|
347
|
0
|
0
|
|
|
|
|
if ( 1 == $this_level ) { |
348
|
0
|
|
|
|
|
|
$this_parent = $self->{target_person}; |
349
|
|
|
|
|
|
|
} else { |
350
|
0
|
|
|
0
|
|
|
$this_parent = List::Util::first {$_ == $person->get_father()} |
351
|
0
|
0
|
|
|
|
|
@{ $DTree_ref->[$this_level - 1] } |
|
0
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
if(defined $person->get_father()); |
353
|
0
|
|
|
0
|
|
|
$this_parent = List::Util::first {$_ == $person->get_mother()} |
354
|
0
|
0
|
|
|
|
|
@{ $DTree_ref->[$this_level - 1] } |
|
0
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
unless( defined $this_parent); |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
0
|
0
|
|
|
|
|
if ( $person == $Person::unknown_female ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# This blank person |
360
|
0
|
|
|
|
|
|
$left_fill = $branch = $right_fill = ""; |
361
|
|
|
|
|
|
|
} |
362
|
0
|
|
|
|
|
|
elsif ( 1 == @{$this_parent->get_children() } ) |
363
|
|
|
|
|
|
|
{ |
364
|
|
|
|
|
|
|
# This person is an only child |
365
|
0
|
|
|
|
|
|
$left_fill = $right_fill = ""; |
366
|
0
|
|
|
|
|
|
$branch = $self->img_graph('hone'); |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
elsif ( $person == $this_parent->get_children()->[0] ) |
369
|
|
|
|
|
|
|
{ |
370
|
|
|
|
|
|
|
# Is this person the first child of this parent? |
371
|
0
|
|
|
|
|
|
$left_fill = ""; |
372
|
0
|
|
|
|
|
|
$branch = $self->img_graph('hleft'); |
373
|
0
|
|
|
|
|
|
$right_fill = $self->img_graph('hblank'); |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
elsif ( $person == $this_parent->get_children()->[-1] ) |
376
|
|
|
|
|
|
|
{ |
377
|
|
|
|
|
|
|
# Is this person the last child of this parent? |
378
|
0
|
|
|
|
|
|
$left_fill = $self->img_graph('hblank'); |
379
|
0
|
|
|
|
|
|
$branch = $self->img_graph('hright'); |
380
|
0
|
|
|
|
|
|
$right_fill = ""; |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
else { |
383
|
0
|
|
|
|
|
|
$left_fill = $right_fill = $self->img_graph('hblank'); |
384
|
0
|
|
|
|
|
|
$branch = $self->img_graph('hbranch'); |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
0
|
|
|
|
|
|
my $group_width = $self->getDTreeWidth( $max_levels - $this_level, $person ); |
388
|
0
|
|
|
|
|
|
my $left = int( ( $group_width - 1 ) / 2 ); |
389
|
0
|
|
|
|
|
|
my $right = $group_width - 1 - $left; |
390
|
|
|
|
|
|
|
|
391
|
0
|
|
|
|
|
|
$self->putNTD( $left, $left_fill ); |
392
|
0
|
|
|
|
|
|
print $self->{cgi}->td($branch); |
393
|
0
|
|
|
|
|
|
$self->putNTD( $right, $right_fill ); |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# Spacers on RHS - fills gap between overall grid width and width of Dgrid |
398
|
0
|
|
|
|
|
|
$self->putNTD($righto_fill); |
399
|
0
|
|
|
|
|
|
print $self->{cgi}->end_Tr, "\n"; |
400
|
|
|
|
|
|
|
|
401
|
0
|
|
|
|
|
|
return; |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
####################################################### |
405
|
|
|
|
|
|
|
# build A-tree for this person |
406
|
|
|
|
|
|
|
# root_node: this person |
407
|
|
|
|
|
|
|
# anc_level: current level of ancestor tree (0=root node) |
408
|
|
|
|
|
|
|
# req_levels: no. levels requested |
409
|
|
|
|
|
|
|
sub fillATree { |
410
|
0
|
|
|
0
|
0
|
|
my ( $self, $root_person, $anc_level, $req_levels, $ATree_ref ) = |
411
|
|
|
|
|
|
|
validate_pos(@_, HASHREF, {type => SCALARREF|UNDEF}, |
412
|
|
|
|
|
|
|
SCALAR, SCALAR, ARRAYREF ); |
413
|
|
|
|
|
|
|
|
414
|
0
|
0
|
|
|
|
|
return unless $anc_level < $req_levels; |
415
|
|
|
|
|
|
|
# print "called: fillATree (root_node = $root_person, anc_level = $anc_level, req_levels = $req_levels)\n"; |
416
|
|
|
|
|
|
|
|
417
|
0
|
0
|
|
|
|
|
my $father = defined $root_person->get_father() ? |
418
|
|
|
|
|
|
|
$root_person->get_father() : $Person::unknown_male; |
419
|
|
|
|
|
|
|
|
420
|
0
|
0
|
|
|
|
|
my $mother = defined $root_person->get_mother() ? |
421
|
|
|
|
|
|
|
$root_person->get_mother() : $Person::unknown_female; |
422
|
|
|
|
|
|
|
|
423
|
0
|
|
|
|
|
|
push @{ $ATree_ref->[$anc_level] }, ($father, $mother); |
|
0
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
|
425
|
0
|
|
|
|
|
|
$anc_level++; |
426
|
0
|
|
|
|
|
|
$self->fillATree( $father, $anc_level, $req_levels, $ATree_ref ); |
427
|
0
|
|
|
|
|
|
$self->fillATree( $mother, $anc_level, $req_levels, $ATree_ref ); |
428
|
|
|
|
|
|
|
|
429
|
0
|
|
|
|
|
|
return; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
####################################################### |
433
|
|
|
|
|
|
|
# draw the graphics UNDER the level specified |
434
|
|
|
|
|
|
|
# this_level: level of grid to generate |
435
|
|
|
|
|
|
|
# max_levels: max depth that will be shown |
436
|
|
|
|
|
|
|
sub getAGridLineG { |
437
|
0
|
|
|
0
|
0
|
|
my ( $self, $diff_levels, $AWidth, $aRow ) = validate_pos(@_, |
438
|
|
|
|
|
|
|
HASHREF, SCALAR, SCALAR, ARRAYREF); |
439
|
|
|
|
|
|
|
|
440
|
0
|
0
|
|
|
|
|
return if ( 0 > $diff_levels ); |
441
|
|
|
|
|
|
|
|
442
|
0
|
|
|
|
|
|
my $left_fill = int( ( $self->{gridWidth} - $AWidth + 1 ) / 2 ); |
443
|
0
|
|
|
|
|
|
my $right_fill = $self->{gridWidth} - $AWidth - $left_fill; |
444
|
|
|
|
|
|
|
|
445
|
0
|
|
|
|
|
|
print $self->{cgi}->start_Tr, "\n"; |
446
|
0
|
|
|
|
|
|
$self->putNTD($left_fill); |
447
|
|
|
|
|
|
|
|
448
|
0
|
|
|
|
|
|
my $node_width = 2**$diff_levels ; |
449
|
0
|
|
|
|
|
|
my $nodel_fill = int( ( $node_width - 1 ) / 2 ); |
450
|
0
|
|
|
|
|
|
my $noder_fill = $node_width - 1 - $nodel_fill; |
451
|
|
|
|
|
|
|
|
452
|
0
|
|
|
|
|
|
for ( my $index = 0; $index < @$aRow; $index += 2 ) |
453
|
|
|
|
|
|
|
{ |
454
|
0
|
|
|
|
|
|
$self->putNTD($nodel_fill); |
455
|
0
|
|
|
|
|
|
print $self->{cgi}->td( $self->img_graph("hleftup")),"\n"; |
456
|
0
|
|
|
|
|
|
$self->putNTD( $node_width - 1, $self->img_graph("hblankup") ); |
457
|
0
|
|
|
|
|
|
print $self->{cgi}->td( $self->img_graph("hrightup") ), "\n"; |
458
|
0
|
|
|
|
|
|
$self->putNTD($noder_fill); |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
0
|
|
|
|
|
|
$self->putNTD($right_fill); |
462
|
0
|
|
|
|
|
|
print $self->{cgi}->end_Tr, "\n"; |
463
|
|
|
|
|
|
|
|
464
|
0
|
|
|
|
|
|
print $self->{cgi}->start_Tr, "\n"; |
465
|
0
|
|
|
|
|
|
$self->putNTD($left_fill); |
466
|
|
|
|
|
|
|
|
467
|
0
|
|
|
|
|
|
for ( my $index = 0 ; $index < @$aRow; $index += 2 ) |
468
|
|
|
|
|
|
|
{ |
469
|
0
|
|
|
|
|
|
$self->putNTD( $node_width - 1 ); |
470
|
0
|
|
|
|
|
|
print $self->{cgi}->td( $self->img_graph("hone") ), "\n"; |
471
|
0
|
|
|
|
|
|
$self->putNTD($node_width); |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
0
|
|
|
|
|
|
$self->putNTD($right_fill); |
475
|
0
|
|
|
|
|
|
print $self->{cgi}->end_Tr, "\n"; |
476
|
|
|
|
|
|
|
|
477
|
0
|
|
|
|
|
|
return; |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
####################################################### |
481
|
|
|
|
|
|
|
sub buildDGrid { |
482
|
0
|
|
|
0
|
0
|
|
my ($self, $DWidth, $DTree_ref) = validate_pos(@_, HASHREF, SCALAR, ARRAYREF); |
483
|
|
|
|
|
|
|
|
484
|
0
|
|
|
|
|
|
my $left_fill = int( ( $self->{gridWidth} - $DWidth ) / 2 ); |
485
|
|
|
|
|
|
|
|
486
|
0
|
|
|
|
|
|
for my $this_level (1 .. $self->{DLevels}) { |
487
|
0
|
|
|
|
|
|
$self->getDGridLineG( $this_level, $self->{reqLevels}, $DWidth, $DTree_ref ); |
488
|
|
|
|
|
|
|
|
489
|
0
|
|
|
|
|
|
my $is_blank_line = $self->drawRow($DWidth, \@{ $DTree_ref->[$this_level] }, |
490
|
0
|
|
|
|
|
|
$self->{reqLevels} - $this_level, $this_level, $left_fill, |
491
|
|
|
|
|
|
|
\&unknownEquiCond, \&getDTreeWidth, \&Ftree::FamilyTreeGraphics::html_img); |
492
|
|
|
|
|
|
|
|
493
|
0
|
|
|
|
|
|
$self->drawRow($DWidth, \@{ $DTree_ref->[$this_level] }, |
494
|
0
|
|
|
|
|
|
$self->{reqLevels} - $this_level, $this_level, $left_fill, |
495
|
|
|
|
|
|
|
\&unknownEquiCond, \&getDTreeWidth, \&html_name); |
496
|
|
|
|
|
|
|
|
497
|
0
|
|
|
|
|
|
$self->drawRow($DWidth, \@{ $DTree_ref->[$this_level] }, |
498
|
0
|
|
|
|
|
|
$self->{reqLevels} - $this_level, $this_level, $left_fill, |
499
|
|
|
|
|
|
|
\&unknownEquiNoChildrenCond, \&getDTreeWidth, \&hone_img_graph); |
500
|
|
|
|
|
|
|
|
501
|
0
|
0
|
|
|
|
|
$self->{DLevels} = $this_level - 1 if ( $is_blank_line ); |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
|
504
|
0
|
|
|
|
|
|
return; |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
####################################################### |
508
|
|
|
|
|
|
|
sub buildDestroyAGrid { |
509
|
0
|
|
|
0
|
0
|
|
my ( $self, $ATree_ref ) = validate_pos(@_, {type => HASHREF}, ARRAYREF); |
510
|
|
|
|
|
|
|
#printf "calling: getAGridLine \n"; |
511
|
|
|
|
|
|
|
|
512
|
0
|
|
|
|
|
|
my $aLevel = @$ATree_ref; |
513
|
0
|
|
|
|
|
|
my $AWidth = 2 ** $aLevel; |
514
|
0
|
|
|
|
|
|
--$aLevel; |
515
|
0
|
|
|
|
|
|
my $left_fill = int( ( $self->{gridWidth} - $AWidth + 1 ) / 2 ); |
516
|
|
|
|
|
|
|
|
517
|
0
|
|
|
|
|
|
for ( my $this_level = $aLevel; $this_level >= 0 ; --$this_level ) { |
518
|
0
|
|
|
|
|
|
my $aRow = pop @$ATree_ref; |
519
|
0
|
|
|
|
|
|
$self->drawRow($AWidth, $aRow, $aLevel - $this_level, $this_level, $left_fill, |
520
|
|
|
|
|
|
|
\&falseCond, \&getATreeWidth , \&Ftree::FamilyTreeGraphics::html_img); |
521
|
|
|
|
|
|
|
|
522
|
0
|
|
|
|
|
|
$self->drawRow($AWidth, $aRow, $aLevel - $this_level, $this_level, $left_fill, |
523
|
|
|
|
|
|
|
\&falseCond, \&getATreeWidth, \&html_name); |
524
|
|
|
|
|
|
|
|
525
|
0
|
|
|
|
|
|
$self->getAGridLineG( $aLevel - $this_level, $AWidth, $aRow ); |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
#printf "buildAGrid returns"; |
529
|
0
|
|
|
|
|
|
return; |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
####################################################### |
533
|
|
|
|
|
|
|
sub buildPGrid { |
534
|
0
|
|
|
0
|
0
|
|
my ($self, $PWidth) = validate_pos(@_, {type => HASHREF}, SCALAR); |
535
|
|
|
|
|
|
|
|
536
|
0
|
|
|
|
|
|
my @peers = $self->{target_person}->get_peers( ); |
537
|
|
|
|
|
|
|
|
538
|
0
|
|
|
0
|
|
|
my $left_side = List::MoreUtils::first_index {$_ == $self->{target_person}} @peers; |
|
0
|
|
|
|
|
|
|
539
|
0
|
|
|
|
|
|
my $left_fill = int(( $self->{gridWidth} - 1 ) / 2 ) - $left_side; |
540
|
0
|
|
|
|
|
|
my $right_fill = $self->{gridWidth} - $PWidth - $left_fill; |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
|
543
|
0
|
|
|
|
|
|
print $self->{cgi}->start_Tr, "\n"; |
544
|
0
|
|
|
|
|
|
$self->putNTD($left_fill); |
545
|
|
|
|
|
|
|
|
546
|
0
|
0
|
|
|
|
|
if ( @peers > 1 ) { |
547
|
0
|
|
|
|
|
|
print $self->{cgi}->td( $self->img_graph("hleft") ), "\n"; |
548
|
0
|
|
|
|
|
|
$self->putNTD($#peers - 1, $self->img_graph("hbranch")); |
549
|
0
|
|
|
|
|
|
print $self->{cgi}->td( $self->img_graph("hright") ), "\n"; |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
else { |
552
|
0
|
|
|
|
|
|
print $self->{cgi}->td( $self->img_graph("hone") ), "\n"; |
553
|
|
|
|
|
|
|
} |
554
|
0
|
|
|
|
|
|
$self->putNTD($right_fill); |
555
|
0
|
|
|
|
|
|
print $self->{cgi}->end_Tr, "\n"; |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
$self->drawRow($PWidth, \@peers, |
558
|
|
|
|
|
|
|
undef, undef, $left_fill, |
559
|
0
|
|
|
0
|
|
|
\&falseCond, sub {return 1} , \&Ftree::FamilyTreeGraphics::html_img); |
|
0
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
$self->drawRow($PWidth, \@peers, |
562
|
|
|
|
|
|
|
undef, undef, $left_fill, |
563
|
0
|
|
|
0
|
|
|
\&falseCond, sub {return 1} , \&Ftree::FamilyTreeGraphics::html_name); |
|
0
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
|
565
|
0
|
0
|
|
|
|
|
if ( defined $self->{target_person}->get_children() ) { |
566
|
0
|
|
|
|
|
|
print $self->{cgi}->start_Tr, "\n"; |
567
|
0
|
|
|
|
|
|
my $gridLeft = int( ( $self->{gridWidth} - 1 ) / 2 ); |
568
|
0
|
|
|
|
|
|
my $gridRight = $self->{gridWidth} - 1 - $gridLeft; |
569
|
0
|
|
|
|
|
|
$self->putNTD($gridLeft); |
570
|
0
|
|
|
|
|
|
print $self->{cgi}->td( $self->img_graph("hone") ), "\n"; |
571
|
0
|
|
|
|
|
|
$self->putNTD($gridRight); |
572
|
0
|
|
|
|
|
|
print $self->{cgi}->end_Tr, "\n"; |
573
|
|
|
|
|
|
|
} |
574
|
|
|
|
|
|
|
|
575
|
0
|
|
|
|
|
|
return; |
576
|
|
|
|
|
|
|
} |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
####################################################### |
579
|
|
|
|
|
|
|
# find the width of the peer line |
580
|
|
|
|
|
|
|
# (allowing for the fact that it may be off-centre) |
581
|
|
|
|
|
|
|
sub getPTreeWidth { |
582
|
0
|
|
|
0
|
0
|
|
my ($self) = validate_pos(@_, {type => HASHREF}); |
583
|
|
|
|
|
|
|
|
584
|
0
|
|
|
|
|
|
my @peers = $self->{target_person}->get_peers( ); |
585
|
0
|
|
|
0
|
|
|
my $node_pos = List::MoreUtils::first_index {$_ == $self->{target_person}} @peers; |
|
0
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
|
587
|
0
|
|
|
|
|
|
my $right_side = $#peers - $node_pos; |
588
|
0
|
|
|
|
|
|
my $big_side = List::Util::max ($node_pos, $right_side ); |
589
|
0
|
|
|
|
|
|
return $big_side * 2 + 1; |
590
|
|
|
|
|
|
|
} |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
####################################################### |
593
|
|
|
|
|
|
|
# generates the html for the name of this person |
594
|
|
|
|
|
|
|
sub html_name { |
595
|
0
|
|
|
0
|
0
|
|
my ( $self, $person ) = validate_pos(@_, {type => HASHREF}, {type => SCALARREF}); |
596
|
|
|
|
|
|
|
return $self->{cgi}->font({-size => $self->{fontsize}}, $self->{textGenerator}{Unknown}) |
597
|
0
|
0
|
0
|
|
|
|
if ( !defined $person || $person == $Person::unknown_male || $person == $Person::unknown_female ); |
|
|
|
0
|
|
|
|
|
598
|
0
|
|
|
|
|
|
my $show_name; |
599
|
0
|
0
|
|
|
|
|
if(defined $person->get_name()) { |
600
|
0
|
0
|
|
|
|
|
$show_name = ( $self->{reqLevels} > 1 ) ? |
601
|
|
|
|
|
|
|
$person->get_name()->get_first_name() : $person->get_name()->get_short_name(); |
602
|
|
|
|
|
|
|
} else { |
603
|
0
|
|
|
|
|
|
$show_name = $self->{textGenerator}{Unknown}; |
604
|
|
|
|
|
|
|
} |
605
|
0
|
0
|
|
|
|
|
if ( $person == $self->{target_person} ) { |
606
|
0
|
|
|
|
|
|
return $self->{cgi}->strong($self->{cgi}->font({-size => $self->{fontsize}}, $show_name)); |
607
|
|
|
|
|
|
|
} |
608
|
|
|
|
|
|
|
else { |
609
|
0
|
|
|
|
|
|
return $self->{cgi}->font({-size => $self->{fontsize}}, $self->aref_tree($show_name, $person)); |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
sub print_zoom_buttons { |
615
|
0
|
|
|
0
|
0
|
|
my ( $self, $aLevels ) = validate_pos(@_, {type => HASHREF}, SCALAR); |
616
|
0
|
|
|
|
|
|
my $lev_minus1 = $self->{reqLevels} - 1; |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
print $self->{cgi}->start_table( |
619
|
|
|
|
|
|
|
{ -border => "0", -cellpadding => "0", -cellspacing => "2" } ), "\n", |
620
|
0
|
|
|
|
|
|
$self->{cgi}->start_Tr; |
621
|
0
|
0
|
|
|
|
|
if ( $lev_minus1 >= 0 ) { |
622
|
|
|
|
|
|
|
print $self->{cgi}->start_td({-align => "center"}), "\n", |
623
|
|
|
|
|
|
|
$self->aref_tree($self->{cgi}->img( { |
624
|
|
|
|
|
|
|
-src => "$self->{graphicsUrl}/zoomin.gif", |
625
|
|
|
|
|
|
|
-alt => $self->{textGenerator}->ZoomIn($lev_minus1) }), $self->{target_person}, $lev_minus1), |
626
|
0
|
|
|
|
|
|
$self->{cgi}->end_td, "\n"; |
627
|
|
|
|
|
|
|
} |
628
|
|
|
|
|
|
|
|
629
|
0
|
0
|
|
|
|
|
if( $self->{reqLevels} <= $aLevels ) { |
630
|
0
|
|
|
|
|
|
my $lev_plus1 = $self->{reqLevels} + 1; |
631
|
|
|
|
|
|
|
print $self->{cgi}->start_td({-align => "center"}), "\n", |
632
|
|
|
|
|
|
|
$self->aref_tree($self->{cgi}->img( { |
633
|
|
|
|
|
|
|
-src => "$self->{graphicsUrl}/zoomout.gif", |
634
|
|
|
|
|
|
|
-alt => $self->{textGenerator}->ZoomOut($lev_plus1) }), $self->{target_person}, $lev_plus1), |
635
|
0
|
|
|
|
|
|
$self->{cgi}->end_td; |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
print $self->{cgi}->end_Tr, "\n", |
638
|
0
|
|
|
|
|
|
$self->{cgi}->end_table, $self->{cgi}->br, $self->{cgi}->br, "\n"; |
639
|
|
|
|
|
|
|
|
640
|
0
|
|
|
|
|
|
return; |
641
|
|
|
|
|
|
|
} |
642
|
|
|
|
|
|
|
######################################################### |
643
|
|
|
|
|
|
|
# OUTPUT SECTION # |
644
|
|
|
|
|
|
|
######################################################### |
645
|
|
|
|
|
|
|
sub _draw_start_page { |
646
|
0
|
|
|
0
|
|
|
my ( $self, $aLevels ) = validate_pos(@_, {type => HASHREF}, SCALAR); |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
# header html for page |
649
|
|
|
|
|
|
|
my $title = $self->{textGenerator}->familyTreeFor( |
650
|
|
|
|
|
|
|
defined $self->{target_person}->get_name() ? # He may have id but not any name |
651
|
|
|
|
|
|
|
$self->{target_person}->get_name()->get_full_name(): |
652
|
0
|
0
|
|
|
|
|
$self->{textGenerator}->{Unknown}); |
653
|
0
|
|
|
|
|
|
$self->_toppage($title); |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
# Zoom buttons |
656
|
0
|
|
|
|
|
|
print $self->{cgi}->start_center, "\n"; |
657
|
0
|
|
|
|
|
|
$self->print_zoom_buttons($aLevels); |
658
|
|
|
|
|
|
|
|
659
|
0
|
|
|
|
|
|
return; |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
sub _draw_familytree_page { |
663
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
664
|
|
|
|
|
|
|
|
665
|
0
|
|
|
|
|
|
my $aLevels = $self->getATreeLevels( $self->{target_person}, 0, $self->{reqLevels} ); |
666
|
0
|
|
|
|
|
|
my $AWidth = 2 ** $aLevels; |
667
|
0
|
|
|
|
|
|
my $PWidth = $self->getPTreeWidth(); |
668
|
0
|
|
|
|
|
|
my $DWidth = $self->getDTreeWidth( $self->{reqLevels}, $self->{target_person} ); |
669
|
|
|
|
|
|
|
|
670
|
0
|
|
|
|
|
|
$self->{gridWidth} = List::Util::max( $AWidth, $PWidth, $DWidth ); |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
# fill the grid |
673
|
0
|
|
|
|
|
|
my @ATree; |
674
|
0
|
|
|
|
|
|
$self->fillATree( $self->{target_person}, 0, $aLevels, \@ATree ); |
675
|
0
|
|
|
|
|
|
my @DTree; |
676
|
0
|
|
|
|
|
|
$self->fillDTree( $self->{target_person}, 0, $self->{reqLevels}, \@DTree ); |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
|
679
|
0
|
|
|
|
|
|
$self->_draw_start_page(List::Util::max($aLevels, $self->{DLevels})); |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
# Draw the grid |
683
|
|
|
|
|
|
|
print $self->{cgi}->start_table( |
684
|
0
|
|
|
|
|
|
{ -border => "0", -cellpadding => "0", -cellspacing => "0" } ), "\n"; |
685
|
0
|
|
|
|
|
|
$self->buildDestroyAGrid(\@ATree); |
686
|
0
|
|
|
|
|
|
$self->buildPGrid($PWidth); |
687
|
0
|
|
|
|
|
|
$self->buildDGrid($DWidth, \@DTree); |
688
|
0
|
|
|
|
|
|
print $self->{cgi}->end_table, "\n", $self->{cgi}->end_center, "\n"; |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
|
691
|
0
|
|
|
|
|
|
$self->_endpage(); |
692
|
0
|
|
|
|
|
|
return; |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
1; |
696
|
|
|
|
|
|
|
|