File Coverage

blib/lib/GD/Graph/pie3d.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             ############################################################
2             #
3             # Module: GD::Graph::pie3d
4             #
5             # Description:
6             # This is merely a wrapper around GD::Graph::pie that forces
7             # the 3d option for pie charts.
8             #
9             # Created: 2000.Jan.19 by Jeremy Wadsack for Wadsack-Allen Digital Group
10             # Copyright (C) 2000,2001 Wadsack-Allen. All rights reserved.
11             ############################################################
12             # Date Modification Author
13             # ----------------------------------------------------------
14             # 2000APR18 Modified to be compatible w/ GD::Graph 1.30 JW
15             # 2000APR24 Set default slice label color to black JW
16             # 2001Feb16 Added support for a legend JW
17             ############################################################
18             package GD::Graph::pie3d;
19              
20 1     1   1036 use strict;
  1         2  
  1         36  
21 1     1   1085 use GD;
  0            
  0            
22             use GD::Graph;
23             use GD::Graph::pie;
24             use GD::Graph::utils qw(:all);
25             use Carp;
26              
27             @GD::Graph::pie3d::ISA = qw( GD::Graph::pie );
28             $GD::Graph::pie3d::VERSION = '0.63';
29              
30             my %Defaults = (
31             '3d' => 1,
32             axislabelclr => 'black', # values on slices. black because default colors use dblue
33              
34             # Size of the legend markers
35             legend_marker_height => 8,
36             legend_marker_width => 12,
37             legend_spacing => 4,
38             legend_placement => 'BC', # '[BR][LCR]'
39             lg_cols => undef,
40             legend_frame_margin => 4,
41             legend_frame_size => undef,
42             );
43              
44             # PRIVATE
45             # Have to include because this is a different %Defaults hash
46             sub _has_default {
47             my $self = shift;
48             my $attr = shift || return;
49             exists $Defaults{$attr} || $self->SUPER::_has_default($attr);
50             }
51              
52             sub initialise {
53             my $self = shift;
54             my $rc = $self->SUPER::initialise();
55              
56             while( my($key, $val) = each %Defaults ) {
57             $self->{$key} = $val;
58             } # end while
59              
60             $self->set_legend_font(GD::gdTinyFont);
61             return $rc;
62             } # end initialise
63              
64             # Add lengend calc and draw code
65             sub plot
66             {
67             my $self = shift;
68             my $data = shift;
69              
70             $self->check_data($data) or return;
71             $self->init_graph() or return;
72             $self->setup_text() or return;
73             $self->setup_legend();
74             $self->setup_coords() or return;
75             $self->{b_margin} += 4 if $self->{label}; # Kludge for descenders
76             $self->draw_text() or return;
77             $self->draw_pie() or return;
78             $self->draw_data() or return;
79             $self->draw_legend();
80              
81             return $self->{graph};
82             }
83              
84             # Added legend stuff
85             sub setup_text
86             {
87             my $self = shift;
88              
89             my $rc = $self->SUPER::setup_text( @_ );
90            
91             $self->{gdta_legend}->set(colour => $self->{legendci});
92             $self->{gdta_legend}->set_align('top', 'left');
93             $self->{lgfh} = $self->{gdta_legend}->get('height');
94            
95             return $rc
96             } # end setup_text
97              
98             # Inherit everything else from GD::Graph::pie
99              
100              
101             # Legend Support. Added 16.Feb.2001 - JW/WADG
102              
103             sub set_legend # List of legend keys
104             {
105             my $self = shift;
106             $self->{legend} = [@_];
107             }
108              
109             sub set_legend_font # (font name)
110             {
111             my $self = shift;
112             $self->_set_font('gdta_legend', @_);
113             }
114              
115              
116              
117             #
118             # Legend
119             #
120             sub setup_legend
121             {
122             my $self = shift;
123              
124             return unless defined $self->{legend};
125              
126             my $maxlen = 0;
127             my $num = 0;
128              
129             # Save some variables
130             $self->{r_margin_abs} = $self->{r_margin};
131             $self->{b_margin_abs} = $self->{b_margin};
132              
133             foreach my $legend (@{$self->{legend}})
134             {
135             if (defined($legend) and $legend ne "")
136             {
137             $self->{gdta_legend}->set_text($legend);
138             my $len = $self->{gdta_legend}->get('width');
139             $maxlen = ($maxlen > $len) ? $maxlen : $len;
140             $num++;
141             }
142             # Legend for Pie goes over first set, and all points
143             last if $num >= $self->{_data}->num_points;
144             }
145              
146             $self->{lg_num} = $num;
147              
148             # calculate the height and width of each element
149             my $legend_height = _max($self->{lgfh}, $self->{legend_marker_height});
150              
151             $self->{lg_el_width} =
152             $maxlen + $self->{legend_marker_width} + 3 * $self->{legend_spacing};
153             $self->{lg_el_height} = $legend_height + 2 * $self->{legend_spacing};
154              
155             my ($lg_pos, $lg_align) = split(//, $self->{legend_placement});
156              
157             if ($lg_pos eq 'R')
158             {
159             # Always work in one column
160             $self->{lg_cols} = 1;
161             $self->{lg_rows} = $num;
162              
163             # Just for completeness, might use this in later versions
164             $self->{lg_x_size} = $self->{lg_cols} * $self->{lg_el_width};
165             $self->{lg_y_size} = $self->{lg_rows} * $self->{lg_el_height};
166              
167             # Adjust the right margin for the rest of the graph
168             $self->{r_margin} += $self->{lg_x_size};
169              
170             # Adjust for frame if defined
171             if( $self->{legend_frame_size} ) {
172             $self->{r_margin} += 2 * ($self->{legend_frame_margin} + $self->{legend_frame_size});
173             } # end if;
174              
175             # Set the x starting point
176             $self->{lg_xs} = $self->{width} - $self->{r_margin};
177              
178             # Set the y starting point, depending on alignment
179             if ($lg_align eq 'T')
180             {
181             $self->{lg_ys} = $self->{t_margin};
182             }
183             elsif ($lg_align eq 'B')
184             {
185             $self->{lg_ys} = $self->{height} - $self->{b_margin} -
186             $self->{lg_y_size};
187             }
188             else # default 'C'
189             {
190             my $height = $self->{height} - $self->{t_margin} -
191             $self->{b_margin};
192              
193             $self->{lg_ys} =
194             int($self->{t_margin} + $height/2 - $self->{lg_y_size}/2) ;
195             }
196             }
197             else # 'B' is the default
198             {
199             # What width can we use
200             my $width = $self->{width} - $self->{l_margin} - $self->{r_margin};
201              
202             (!defined($self->{lg_cols})) and
203             $self->{lg_cols} = int($width/$self->{lg_el_width});
204            
205             $self->{lg_cols} = _min($self->{lg_cols}, $num);
206              
207             $self->{lg_rows} =
208             int($num / $self->{lg_cols}) + (($num % $self->{lg_cols}) ? 1 : 0);
209              
210             $self->{lg_x_size} = $self->{lg_cols} * $self->{lg_el_width};
211             $self->{lg_y_size} = $self->{lg_rows} * $self->{lg_el_height};
212              
213             # Adjust the bottom margin for the rest of the graph
214             $self->{b_margin} += $self->{lg_y_size};
215             # Adjust for frame if defined
216             if( $self->{legend_frame_size} ) {
217             $self->{b_margin} += 2 * ($self->{legend_frame_margin} + $self->{legend_frame_size});
218             } # end if;
219              
220             # Set the y starting point
221             $self->{lg_ys} = $self->{height} - $self->{b_margin};
222              
223             # Set the x starting point, depending on alignment
224             if ($lg_align eq 'R')
225             {
226             $self->{lg_xs} = $self->{width} - $self->{r_margin} -
227             $self->{lg_x_size};
228             }
229             elsif ($lg_align eq 'L')
230             {
231             $self->{lg_xs} = $self->{l_margin};
232             }
233             else # default 'C'
234             {
235             $self->{lg_xs} =
236             int($self->{l_margin} + $width/2 - $self->{lg_x_size}/2);
237             }
238             }
239             }
240              
241             sub draw_legend
242             {
243             my $self = shift;
244              
245             return unless defined $self->{legend};
246              
247             my $xl = $self->{lg_xs} + $self->{legend_spacing};
248             my $y = $self->{lg_ys} + $self->{legend_spacing} - 1;
249              
250             # If there's a frame, offset by the size and margin
251             $xl += $self->{legend_frame_margin} + $self->{legend_frame_size} if $self->{legend_frame_size};
252             $y += $self->{legend_frame_margin} + $self->{legend_frame_size} if $self->{legend_frame_size};
253              
254             my $i = 0;
255             my $row = 1;
256             my $x = $xl; # start position of current element
257              
258             foreach my $legend (@{$self->{legend}})
259             {
260             $i++;
261             # Legend for Pie goes over first set, and all points
262             last if $i > $self->{_data}->num_points;
263              
264             my $xe = $x; # position within an element
265              
266             next unless defined($legend) && $legend ne "";
267              
268             $self->draw_legend_marker($i, $xe, $y);
269              
270             $xe += $self->{legend_marker_width} + $self->{legend_spacing};
271             my $ys = int($y + $self->{lg_el_height}/2 - $self->{lgfh}/2);
272              
273             $self->{gdta_legend}->set_text($legend);
274             $self->{gdta_legend}->draw($xe, $ys);
275              
276             $x += $self->{lg_el_width};
277              
278             if (++$row > $self->{lg_cols})
279             {
280             $row = 1;
281             $y += $self->{lg_el_height};
282             $x = $xl;
283             }
284             }
285            
286             # If there's a frame, draw it now
287             if( $self->{legend_frame_size} ) {
288             $x = $self->{lg_xs} + $self->{legend_spacing};
289             $y = $self->{lg_ys} + $self->{legend_spacing} - 1;
290            
291             for $i ( 0 .. $self->{legend_frame_size} - 1 ) {
292             $self->{graph}->rectangle(
293             $x + $i,
294             $y + $i,
295             $x + $self->{lg_x_size} + 2 * $self->{legend_frame_margin} - $i - 1,
296             $y + $self->{lg_y_size} + 2 * $self->{legend_frame_margin} - $i - 1,
297             $self->{acci},
298             );
299             } # end for
300             } # end if
301            
302             }
303              
304             sub draw_legend_marker # data_set_number, x, y
305             {
306             my $s = shift;
307             my $n = shift;
308             my $x = shift;
309             my $y = shift;
310              
311             my $g = $s->{graph};
312              
313             my $ci = $s->set_clr($s->pick_data_clr($n));
314              
315             $y += int($s->{lg_el_height}/2 - $s->{legend_marker_height}/2);
316              
317             $g->filledRectangle(
318             $x, $y,
319             $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height},
320             $ci
321             );
322              
323             $g->rectangle(
324             $x, $y,
325             $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height},
326             $s->{acci}
327             );
328             }
329              
330              
331             1;