File Coverage

blib/lib/GD/Graph/sparklines.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package GD::Graph::sparklines;
2              
3 2     2   26050 use strict;
  2         5  
  2         80  
4 2     2   11 use vars qw($VERSION);
  2         4  
  2         122  
5 2     2   2263 use GD::Graph::utils qw(:all);
  0            
  0            
6             use GD::Graph::colour qw(:colours);
7             use base qw(GD::Graph::axestype);
8              
9             $VERSION = '0.2';
10             my $svn_info =
11             '$LastChangedDate: 2004-09-28 12:05:35 +0100 (Tue, 28 Sep 2004) $';
12              
13             # set some defaults and define our own options
14             my %Defaults = (
15             y_min_clip => undef,
16             y_max_clip => undef,
17             y_band_min => undef,
18             y_band_max => undef,
19             traditional => 1,
20              
21             x_label => undef,
22             y_label => undef,
23             title => undef,
24             x_ticks => 0,
25             y_ticks => 0,
26             no_axes => 1,
27             );
28              
29             sub initialise {
30             my $self = shift;
31             $self->SUPER::initialise();
32             my $Defaults = join "\n", keys %Defaults;
33             foreach my $key (keys %Defaults) {
34             $self->set( $key => $Defaults{$key} );
35             }
36            
37             if ($self->{traditional}) { # light grey lines
38             my $colours = $self->get('dclrs');
39             $self->set( dclrs=>['lgray', @$colours] );
40             }
41              
42             1;
43             }
44              
45             sub _has_default {
46             my $self = shift;
47             my $attr = shift || return;
48             exists $Defaults{$attr} || $self->SUPER::_has_default($attr);
49             }
50              
51             sub draw_data_set {
52             my $self = shift;
53             my $data = shift;
54             my $dsci = $self->set_clr($self->pick_data_clr($data));
55             my $medci = $self->set_clr(_rgb($self->{fgclr}));
56             my @values = $self->{_data}->y_values($data) or
57             return $self->_set_error("Impossible illegal data set: $data",
58             $self->{_data}->error);
59              
60             my %y = (
61             max => $self->get('y_max_clip'),
62             min => $self->get('y_min_clip'),
63             low => $self->get('y_band_min'),
64             hi => $self->get('y_band_max')
65             );
66              
67             # plot a "normal values" band
68             if (defined($y{low}) and defined($y{hi})) {
69             my ($tlx, $tly) = $self->val_to_pixel(0, $y{hi}, $data);
70             my ($brx, $bry) = $self->val_to_pixel(scalar @values+1, $y{low}, $data);
71             my $bg = $self->set_clr(_rgb('#DDDDDD'));
72            
73             $self->{graph}->filledRectangle($tlx, $tly, $brx, $bry, $bg);
74             }
75            
76             my ($lx, $ly) = (undef, undef);
77             for (my $i = 0; $i < @values; $i++)
78             {
79             my $value = $values[$i];
80            
81             if (!defined($value)) {
82             print "value[$i] isn't defined\n";
83             undef $lx; undef $ly;
84             next;
85             }
86            
87             my ($px, $py) = $self->val_to_pixel($i+1, $value, $data);
88              
89             if (defined($px) and defined($py)) {
90             if (defined($lx) and defined($ly)) {
91             $self->{graph}->line($lx, $ly, $px, $py, $dsci);
92             }
93             ($lx, $ly) = ($px, $py);
94             } else {
95             die "error converting [$i, $value] to coordinates";
96             }
97             }
98              
99             if ($self->{traditional}) {
100             my $red = $self->set_clr(_rgb('red'));
101              
102             # draw a single pixel if we're a shallow graph for space economy
103             if ($self->{height} < 24) {
104             $self->{graph}->setPixel($lx, $ly, $red);
105             } else {
106             $self->{graph}->filledRectangle($lx-1, $ly-1, $lx+1, $ly+1, $red);
107             }
108             }
109              
110             return $data;
111             }
112              
113             # mostly cargo-culted from GD::Graph::boxplot
114             sub set_max_min
115             {
116             my $self = shift;
117              
118             my $min = 2<<29;
119             my $max = -$min;
120            
121             for my $i ( 1 .. $self->{_data}->num_sets ) # 1 because x-labels are [0]
122             {
123             for my $j ( 0 .. $self->{_data}->num_points )
124             {
125             next unless defined($self->{_data}->[$i][$j]);
126              
127             $max = $self->{_data}->[$i][$j]
128             if ($self->{_data}->[$i][$j] > $max);
129             $min = $self->{_data}->[$i][$j]
130             if ($self->{_data}->[$i][$j] < $min);
131             }
132             }
133              
134             $self->{y_min}[1] = $min - 3;
135             $self->{y_max}[1] = $max + 3;
136              
137             # Overwrite these with any user supplied ones
138             $self->{y_min}[1] = $self->{y_min_value} if defined $self->{y_min_value};
139             $self->{y_max}[1] = $self->{y_max_value} if defined $self->{y_max_value};
140            
141             $self->{y_min}[1] = $self->{y1_min_value} if defined $self->{y1_min_value};
142             $self->{y_max}[1] = $self->{y1_max_value} if defined $self->{y1_max_value};
143              
144             # clipping overrides any max/min in the data
145             $self->{y_min}[1] = $self->{y_min_clip} if defined $self->{y_min_clip};
146             $self->{y_max}[1] = $self->{y_max_clip} if defined $self->{y_max_clip};
147              
148             return $self;
149             }
150              
151             # override these methods to force the graph to fill the image
152             sub setup_bottom_boundary {
153             my $self = shift;
154             $self->{bottom} = $self->{height} - $self->{b_margin};
155             }
156              
157             sub setup_top_boundary {
158             my $self = shift;
159             $self->{top} = $self->{t_margin};
160             }
161              
162             sub create_y_labels {
163             my $self = shift;
164             $self->{y_label_len}[$_] = 0 for 1, 2;
165             $self->{y_label_height}[$_] = 0 for 1, 2;
166             }
167              
168             sub create_x_labels {
169             my $self = shift;
170             $self->{x_label_height} = 0;
171             $self->{x_label_width} = 0;
172             }
173            
174              
175             $VERSION;
176              
177             __END__