File Coverage

blib/lib/Chart/Clicker.pm
Criterion Covered Total %
statement 61 97 62.8
branch 10 26 38.4
condition 0 3 0.0
subroutine 19 23 82.6
pod 7 8 87.5
total 97 157 61.7


line stmt bran cond sub pod time code
1             package Chart::Clicker;
2             $Chart::Clicker::VERSION = '2.89';
3 7     7   161325 use Moose;
  7         882740  
  7         73  
4              
5             extends 'Chart::Clicker::Container';
6              
7             # ABSTRACT: Powerful, extensible charting.
8              
9 7     7   36989 use Layout::Manager::Compass;
  7         162680  
  7         316  
10              
11 7     7   4009 use Graphics::Color::RGB;
  7         3113738  
  7         383  
12              
13 7     7   1968 use Graphics::Primitive::Insets;
  7         245834  
  7         274  
14 7     7   1516 use Graphics::Primitive::Border;
  7         233030  
  7         278  
15              
16             #use Graphics::Primitive::Driver::Cairo;
17              
18 7     7   5483 use Chart::Clicker::Context;
  7         27  
  7         382  
19              
20 7     7   1530 use Chart::Clicker::Data::DataSet;
  7         18  
  7         279  
21 7     7   1584 use Chart::Clicker::Data::Series;
  7         17  
  7         401  
22 7     7   5555 use Chart::Clicker::Decoration::Legend;
  7         24  
  7         349  
23 7     7   5061 use Chart::Clicker::Decoration::MarkerOverlay;
  7         21  
  7         328  
24 7     7   4559 use Chart::Clicker::Decoration::Plot;
  7         29  
  7         427  
25 7     7   5081 use Chart::Clicker::Drawing::ColorAllocator;
  7         27  
  7         495  
26              
27 7     7   69 use Carp qw(croak);
  7         12  
  7         597  
28 7     7   47 use Scalar::Util qw(refaddr);
  7         16  
  7         18242  
29              
30              
31             has '+background_color' => (
32             default => sub {
33             Graphics::Color::RGB->new({ red => 1, green => 1, blue => 1, alpha => 1 })
34             }
35             );
36              
37              
38             has '+border' => (
39             default => sub {
40             my $b = Graphics::Primitive::Border->new;
41             $b->color(Graphics::Color::RGB->new(red => 0, green => 0, blue => 0));
42             $b->width(1);
43             return $b;
44             }
45             );
46              
47              
48             has 'color_allocator' => (
49             is => 'rw',
50             isa => 'Chart::Clicker::Drawing::ColorAllocator',
51             default => sub { Chart::Clicker::Drawing::ColorAllocator->new }
52             );
53              
54              
55             has 'contexts' => (
56             traits => [ 'Hash' ],
57             is => 'rw',
58             isa => 'HashRef[Chart::Clicker::Context]',
59             default => sub { { default => Chart::Clicker::Context->new(name => 'default') } },
60             handles => {
61             'set_context' => 'set',
62             'get_context' => 'get',
63             'context_names' => 'keys',
64             'context_count' => 'count',
65             'delete_context' => 'delete'
66             }
67             );
68              
69             has '_data' => (
70             traits => [ 'Hash' ],
71             is => 'rw',
72             isa => 'HashRef[Str]',
73             default => sub { {} }
74             );
75              
76              
77             has 'datasets' => (
78             traits => [ 'Array' ],
79             is => 'rw',
80             isa => 'ArrayRef',
81             default => sub { [] },
82             handles => {
83             'dataset_count' => 'count',
84             'add_to_datasets' => 'push',
85             'get_dataset' => 'get'
86             }
87             );
88              
89              
90             has 'driver' => (
91             is => 'rw',
92             does => 'Graphics::Primitive::Driver',
93             default => sub {
94             my ($self) = @_;
95             my $driver = $ENV{CHART_CLICKER_DEFAULT_DRIVER} || ($^O eq 'MSWin32'?"Graphics::Primitive::Driver::GD":"Graphics::Primitive::Driver::Cairo");
96             eval "require $driver;" or die "Cannot load driver $driver";
97             $driver->new(
98             'format' => $self->format,
99             )
100             },
101             handles => {
102             rendered_data => 'data',
103             write => 'write'
104             },
105             lazy => 1
106             );
107              
108              
109             has 'format' => (
110             is => 'rw',
111             isa => 'Str',
112             default => 'PNG'
113             );
114              
115              
116             has 'plot_mode' => (
117             is => 'rw',
118             isa => 'Str',
119             default => 'slow'
120             );
121              
122              
123             has 'grid_over' => (
124             is => 'rw',
125             isa => 'Bool',
126             default => 0
127             );
128              
129              
130             has '+height' => (
131             default => 300
132             );
133              
134              
135             has '+layout_manager' => (
136             default => sub { Layout::Manager::Compass->new }
137             );
138              
139              
140             has 'legend' => (
141             is => 'rw',
142             isa => 'Chart::Clicker::Decoration::Legend',
143             default => sub {
144             Chart::Clicker::Decoration::Legend->new(
145             name => 'legend',
146             );
147             }
148             );
149              
150              
151             has 'legend_position' => (
152             is => 'rw',
153             isa => 'Str',
154             default => 's'
155             );
156              
157              
158             has 'marker_overlay' => (
159             is => 'rw',
160             isa => 'Chart::Clicker::Decoration::MarkerOverlay',
161             lazy => 1,
162             default => sub {
163             Chart::Clicker::Decoration::MarkerOverlay->new
164             }
165             );
166              
167              
168             has 'over_decorations' => (
169             traits => [ 'Array' ],
170             is => 'rw',
171             isa => 'ArrayRef',
172             default => sub { [] },
173             handles => {
174             'over_decoration_count' => 'count',
175             'add_to_over_decorations' => 'push',
176             'get_over_decoration' => 'get'
177             }
178             );
179              
180              
181             has '+padding' => (
182             default => sub {
183             Graphics::Primitive::Insets->new(
184             top => 3, bottom => 3, right => 3, left => 3
185             )
186             }
187             );
188              
189              
190             has 'plot' => (
191             is => 'rw',
192             isa => 'Chart::Clicker::Decoration::Plot',
193             default => sub {
194             Chart::Clicker::Decoration::Plot->new
195             }
196             );
197              
198              
199             has 'subgraphs' => (
200             is => 'rw',
201             isa => 'ArrayRef',
202             default => sub { [] },
203             predicate => 'has_subgraphs'
204             );
205              
206              
207             has 'title' => (
208             is => 'rw',
209             isa => 'Graphics::Primitive::TextBox',
210             default => sub {
211             Graphics::Primitive::TextBox->new(
212             color => Graphics::Color::RGB->new( red => 0, green => 0, blue => 0),
213             horizontal_alignment => 'center'
214             )
215             }
216             );
217              
218              
219             has 'title_position' => (
220             is => 'rw',
221             isa => 'Str',
222             default => 'n'
223             );
224              
225              
226             has '+width' => (
227             default => 500
228             );
229              
230              
231             sub add_to_contexts {
232 2     2 1 20 my ($self, $ctx) = @_;
233              
234 2 50       65 if(defined($self->get_context($ctx->name))) {
235 0         0 croak("Context named '".$ctx->name."' already exists.");
236             }
237 2         65 $self->set_context($ctx->name, $ctx);
238             }
239              
240              
241             sub add_subgraph {
242 0     0 1 0 my ($self, $graph) = @_;
243              
244 0 0 0     0 if (not ref $graph or not $graph->isa('Chart::Clicker')) {
245 0         0 die('Sub-Graphs must be Chart::Clicker objects');
246             }
247 0         0 push(@{$self->subgraphs}, $graph);
  0         0  
248             }
249              
250             sub data {
251 0     0 0 0 my ($self) = @_;
252 0         0 print STDERR "WARNING: Calling 'data' to get image data is deprecated, please use rendered_data\n";
253 0         0 $self->rendered_data;
254             }
255              
256              
257             sub draw {
258 6     6 1 34 my ($self) = @_;
259 6         176 my $driver = $self->driver;
260 0         0 $driver->prepare($self);
261              
262 0         0 $self->layout_manager->do_layout($self);
263 0         0 $driver->finalize($self);
264 0         0 $driver->draw($self);
265             }
266              
267              
268             sub get_datasets_for_context {
269 0     0 1 0 my ($self, $name) = @_;
270              
271 0         0 my @dses;
272 0         0 foreach my $ds (@{ $self->datasets }) {
  0         0  
273 0 0       0 if($ds->context eq $name) {
274 0         0 push(@dses, $ds);
275             }
276             }
277              
278 0         0 return \@dses;
279             }
280              
281              
282             sub add_data {
283 10     10 1 29 my ($self, $name, $data) = @_;
284              
285 10 50       21 if(ref($data) eq 'ARRAY') {
    50          
286             croak "Can't add arrayref data after adding hashrefs"
287 0 0       0 if ref($self->_data->{$name}) eq 'HASH';
288 0 0       0 $self->_data->{$name} = [] unless defined($self->_data->{$name});
289 0         0 push(@{ $self->_data->{$name}}, @{ $data });
  0         0  
  0         0  
290             } elsif(ref($data) eq 'HASH') {
291 0 0       0 if (!defined $self->_data->{$name}) {
    0          
292 0         0 $self->_data->{$name} = {};
293             } elsif (ref($self->_data->{$name}) eq 'ARRAY') {
294 0         0 my $old_data = $self->_data->{$name};
295 0         0 $self->_data->{$name} = {};
296 0         0 for my $i (0 .. @$old_data - 1) {
297 0         0 $self->_data->{$name}{$i} = $old_data->[$i];
298             }
299             }
300 0         0 for my $key (keys %$data) {
301 0         0 $self->_data->{$name}{$key} = $data->{$key};
302             }
303             } else {
304             croak "Can't add scalar data after adding hashrefs"
305 10 50       232 if ref($self->_data->{$name}) eq 'HASH';
306 10 100       230 $self->_data->{$name} = [] unless defined($self->_data->{$name});
307 10         7 push(@{ $self->_data->{$name}}, $data);
  10         223  
308             }
309             }
310              
311             override('prepare', sub {
312             my ($self, $driver) = @_;
313              
314             return if $self->prepared;
315              
316             if(scalar(keys(%{ $self->_data }))) {
317              
318             my $ds = Chart::Clicker::Data::DataSet->new;
319             foreach my $name (keys(%{ $self->_data })) {
320              
321             my $vals = $self->_data->{$name};
322              
323             if(ref($vals) eq 'ARRAY') {
324             # This allows the user to add data as an array
325              
326             $ds->add_to_series(
327             Chart::Clicker::Data::Series->new(
328             name => $name,
329             keys => [ 0..scalar(@{ $vals }) - 1 ],
330             values => $vals
331             )
332             );
333             } elsif(ref($vals) eq 'HASH') {
334             # This allows the user to add data as a hashref
335             my @keys = sort { $a <=> $b } keys %{ $vals };
336              
337             my @values = ();
338             foreach my $k (@keys) {
339             push(@values, $vals->{$k})
340             }
341              
342             $ds->add_to_series(
343             Chart::Clicker::Data::Series->new(
344             name => $name,
345             keys => \@keys,
346             values => \@values
347             )
348             );
349             }
350             }
351             $self->add_to_datasets($ds);
352             }
353              
354             unless(scalar(@{ $self->components })) {
355             $self->add_component($self->plot, 'c');
356              
357             my $lp = lc($self->legend_position);
358             if($self->legend->visible) {
359             if(($lp =~ /^e/) || ($lp =~ /^w/)) {
360             $self->legend->orientation('vertical');
361             }
362             $self->add_component($self->legend, $self->legend_position);
363             }
364              
365             # Add subgraphs
366             if($self->has_subgraphs) {
367             for my $subgraph (@{$self->subgraphs}) {
368             $subgraph->border->width(0);
369             $subgraph->padding(0);
370              
371             $self->add_component($subgraph, 'south');
372             }
373             }
374              
375             if(defined($self->title->text)) {
376             my $tp = $self->title_position;
377             if(($tp =~ /^e/) || ($tp =~ /^w/)) {
378             unless(defined($self->title->angle)) {
379             $self->title->angle(-1.5707);
380             }
381             }
382             $self->add_component($self->title, $tp);
383             }
384             }
385              
386             my $plot = $self->plot;
387              
388             $plot->clear_components;
389             $plot->render_area->clear_components;
390              
391             # These two adds are here because the plot is too dependant on changes
392             # in the axes and such to trust it across multiple prepares. Putting all
393             # of this here made it easier to digest, although this has some codestink
394             # to it...
395             if($plot->grid->visible && !$self->grid_over) {
396             $plot->render_area->add_component($plot->grid, 'c');
397             }
398              
399             $plot->render_area->add_component(
400             $self->marker_overlay
401             );
402              
403             # Sentinels to control the side that the axes will be drawn on.
404             my $dcount = 0;
405             my $rcount = 0;
406             # Hashes of axes & renderers we've already seen, as we don't want to add
407             # them again...
408             my %xaxes;
409             my %yaxes;
410              
411             # A "seen" hash to prevent us from adding multiple renderers for the same
412             # context.
413             my %rends;
414              
415             my $dflt_ctx = $self->get_context('default');
416             die('Clicker must have a default context') unless defined($dflt_ctx);
417              
418             # Prepare the datasets and establish ranges for the axes.
419             my $count = 0;
420             foreach my $ds (@{ $self->datasets }) {
421             unless($ds->count > 0) {
422             die("Dataset $count is empty.");
423             }
424              
425             $ds->prepare;
426              
427             my $ctx = $self->get_context($ds->context);
428              
429             unless(defined($ctx)) {
430             $ctx = $dflt_ctx;
431             }
432              
433             # Find our x axis and add it.
434             my $xaxis = $ctx->domain_axis;
435             unless(exists($xaxes{refaddr($xaxis)})) {
436             $xaxis->range->combine($ds->domain);
437              
438             $xaxis->orientation('horizontal');
439              
440             if($dcount % 2) {
441             $xaxis->position('top');
442             $xaxis->border->bottom->width($xaxis->brush->width);
443             } else {
444             $xaxis->position('bottom');
445             $xaxis->border->top->width($xaxis->brush->width);
446             }
447             $xaxis->border->color($xaxis->color);
448              
449             $plot->add_component($xaxis, $xaxis->is_top ? 'n' : 's');
450             $xaxes{refaddr($xaxis)} = 1;
451             $dcount++;
452             }
453              
454             # Find our y axis and add it.
455             my $yaxis = $ctx->range_axis;
456             unless(exists($yaxes{refaddr($yaxis)})) {
457             $yaxis->range->combine($ds->range);
458              
459             $yaxis->orientation('vertical');
460              
461             if($rcount % 2) {
462             $yaxis->position('right');
463             $yaxis->border->left->width($yaxis->brush->width);
464             } else {
465             $yaxis->position('left');
466             $yaxis->border->right->width($yaxis->brush->width);
467             }
468             $yaxis->border->color($yaxis->color);
469              
470             $plot->add_component($yaxis, $yaxis->is_left ? 'w' : 'e');
471             $rcount++;
472             $yaxes{refaddr($yaxis)} = 1;
473             }
474              
475             my $rend = $ctx->renderer;
476             if($rend->additive) {
477             $yaxis->range->upper($ds->largest_value_slice);
478             } else {
479             $yaxis->range->combine($ds->range);
480             }
481              
482             # Only add this renderer to the chart if we haven't seen it already.
483             unless(exists($rends{$ctx->name})) {
484             $rend->context($ctx->name);
485             $rend->clicker($self);
486             $plot->render_area->add_component($rend, 'c');
487             $rends{$ctx->name} = $rend;
488             }
489              
490             $count++;
491             }
492              
493             if($plot->grid->visible && $self->grid_over) {
494             $plot->grid->background_color->alpha(0);
495             $plot->render_area->add_component($plot->grid, 'c');
496             }
497              
498             foreach my $c (@{ $self->components }) {
499             $c->clicker($self) if $c->can('clicker');
500             }
501              
502             $plot->add_component($plot->render_area, 'c');
503              
504             foreach my $oc (@{ $self->over_decorations }) {
505             $plot->render_area->add_component($oc, 'c');
506             }
507              
508             super;
509             });
510              
511              
512             sub set_renderer {
513 3     3 1 4 my ($self, $renderer, $context) = @_;
514              
515 3 100       11 $context = 'default' unless defined($context);
516              
517 3         103 my $ctx = $self->get_context($context);
518 3 100       23 die("Unknown context: '$context'") unless defined($ctx);
519              
520 2         80 $ctx->renderer($renderer);
521             }
522              
523              
524             sub write_output {
525 0     0 1   my $self = shift;
526              
527 0           $self->draw;
528 0           $self->write(@_);
529             }
530              
531             __PACKAGE__->meta->make_immutable;
532              
533 7     7   62 no Moose;
  7         14  
  7         61  
534              
535             1;
536              
537             __END__
538              
539             =pod
540              
541             =head1 NAME
542              
543             Chart::Clicker - Powerful, extensible charting.
544              
545             =head1 VERSION
546              
547             version 2.89
548              
549             =head1 SYNOPSIS
550              
551             use Chart::Clicker;
552              
553             my $cc = Chart::Clicker->new;
554              
555             my @values = (42, 25, 86, 23, 2, 19, 103, 12, 54, 9);
556             $cc->add_data('Sales', \@values);
557              
558             # alternately, you can add data one bit at a time...
559             foreach my $v (@values) {
560             $cc->add_data('Sales', $v);
561             }
562              
563             # Or, if you want to specify the keys you can use a hashref
564             my $data = { 12 => 123, 13 => 341, 14 => 1241 };
565             $cc->add_data('Sales', $data);
566              
567             $cc->write_output('foo.png');
568              
569             =head1 DESCRIPTION
570              
571             Chart::Clicker aims to be a powerful, extensible charting package that creates
572             really pretty output. Charts can be saved in png, svg, pdf and postscript
573             format.
574              
575             Clicker leverages the power of Graphics::Primitive to create snazzy graphics
576             without being tied to specific backend. You may want to begin with
577             L<Chart::Clicker::Tutorial>.
578              
579             =head1 EXAMPLES
580              
581             For code examples see the examples repository on GitHub:
582             L<http://github.com/gphat/chart-clicker-examples/>
583              
584             =head1 FEATURES
585              
586             =head2 Renderers
587              
588             Clicker supports the following renderers:
589              
590             =over 4
591              
592             =item B<Line>
593              
594             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/line.png" width="500" height="250" alt="Line Chart" /></p>
595              
596             =item B<StackedLine>
597              
598             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/stacked-line.png" width="500" height="250" alt="Stacked Line Chart" /></p>
599              
600             =item B<Bar>
601              
602             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/bar.png" width="500" height="250" alt="Bar Chart" /></p>
603              
604             =item B<StackedBar>
605              
606             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/stacked-bar.png" width="500" height="250" alt="Stacked Bar Chart" /></p>
607              
608             =item B<Area>
609              
610             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/area.png" width="500" height="250" alt="Area Chart" /></p>
611              
612             =item B<StackedArea>
613              
614             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/stacked-area.png" width="500" height="250" alt="Stacked Area Chart" /></p>
615              
616             =item B<Bubble>
617              
618             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/bubble.png" width="500" height="250" alt="Bubble Chart" /></p>
619              
620             =item B<CandleStick>
621              
622             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/candlestick.png" width="500" height="250" alt="Candlestick Chart" /></p>
623              
624             =item B<Point>
625              
626             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/point.png" width="500" height="250" alt="Point Chart" /></p>
627              
628             =item B<Pie>
629              
630             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/pie.png" width="300" height="250" alt="Pie Chart" /></p>
631              
632             =item B<PolarArea>
633              
634             =for HTML <p><img src="http://gphat.github.com/chart-clicker/static/images/examples/polararea.png" width="300" height="250" alt="Polar Area Chart" /></p>
635              
636             =back
637              
638             =head1 ADDING DATA
639              
640             The synopsis shows the simple way to add data.
641              
642             my @values = (42, 25, 86, 23, 2, 19, 103, 12, 54, 9);
643             foreach my $v (@values) {
644             $cc->add_data('Sales', $v);
645             }
646              
647             This is a convenience method provided to make simple cases much simpler. Adding
648             multiple Series to a chart is as easy as changing the name argument of
649             C<add_data>. Each unique first argument will result in a separate series. See
650             the docs for C<add_data> to learn more.
651              
652             If you'd like to use the more advanced features of Clicker you'll need to
653             shake off this simple method and build Series & DataSets explicitly.
654              
655             use Chart::Clicker::Data::Series;
656             use Chart::Clicker::Data::DataSet;
657              
658             ...
659              
660             my $series = Chart::Clicker::Data::Series->new(
661             keys => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
662             values => [ 42, 25, 86, 23, 2, 19, 103, 12, 54, 9 ],
663             );
664              
665             my $ds = Chart::Clicker::Data::DataSet->new(series => [ $series ]);
666              
667             $cc->add_to_datasets($ds);
668              
669             This used to be the only way to add data, but repeated requests to make the
670             common case easier resulted in the inclusion of C<add_data>.
671              
672             =head1 CONTEXTS
673              
674             The normal use case for a chart is a couple of datasets on the same axes.
675             Sometimes you want to chart one or more datasets on different axes. A common
676             need for this is when you are comparing two datasets of vastly different scale
677             such as the number of employees in an office (1-10) to monthly revenues (10s
678             of thousands). On a normal chart the number of employees would show up as a
679             flat line at the bottom of the chart.
680              
681             To correct this, Clicker has contexts. A context is a pair of axes, a
682             renderer and a name. The name is the 'key' by which you will refer to the
683             context.
684              
685             my $context = Chart::Clicker::Context->new( name => 'sales' );
686             $clicker->add_to_contexts($context);
687              
688             $dataset->context('sales');
689              
690             $clicker->add_to_datasets($dataset);
691              
692             New contexts provide a fresh domain and range axis and default to a Line
693             renderer.
694              
695             B<Caveat>: Clicker expects that the default context (identified by the string
696             "default") will always be present. It is from this context that some of
697             Clicker's internals draw their values. You should use the default context
698             unless you need more than one, in which case you should use "default" as the
699             base context.
700              
701             =head1 FORMATS & OUTPUT
702              
703             Clicker supports PNG, SVG, PDF and PostScript output. To change your output
704             type, specificy it when you create your Clicker object:
705              
706             my $cc = Chart::Clicker->new(format => 'pdf', ...);
707             # ...
708             $cc->write_output('chart.pdf');
709              
710             If you are looking to get a scalar of the output for use with HTTP or
711             similar things, you can use:
712              
713             # ... make your chart
714             $cc->draw;
715             my $image_data = $cc->rendered_data;
716              
717             If you happen to be using Catalyst then take a look at
718             L<Catalyst::View::Graphics::Primitive>.
719              
720             =head1 ATTRIBUTES
721              
722             =head2 background_color
723              
724             Set/Get the background L<color|Graphics::Color::RGB>. Defaults to white.
725              
726             =head2 border
727              
728             Set/Get the L<border|Graphics::Primitive::Border>.
729              
730             =head2 color_allocator
731              
732             Set/Get the L<color_allocator|Chart::Clicker::Drawing::ColorAllocator> for this chart.
733              
734             =head2 contexts
735              
736             Set/Get the L<contexts|Chart::Clicker::Context> for this chart.
737              
738             =head2 datasets
739              
740             Get/Set the datasets for this chart.
741              
742             =head2 driver
743              
744             Set/Get the L<driver|Graphics::Primitive::Driver> used to render this Chart. Defaults to
745             L<Graphics::Primitive::Driver::Cairo>.
746              
747             =head2 format
748              
749             Get the format for this Chart. Required in the constructor. Must be on of
750             Png, Pdf, Ps or Svg.
751              
752             =head2 plot_mode
753              
754             Fast or slow plot mode. When in fast mode, data elements that are deemed to be
755             superfluous or invisible will not be drawn. Default is 'slow'
756              
757             =head2 grid_over
758              
759             Flag controlling if the grid is rendered B<over> the data. Defaults to 0.
760             You probably want to set the grid's background color to an alpha of 0 if you
761             enable this flag.
762              
763             =head2 height
764              
765             Set/Get the height. Defaults to 300.
766              
767             =head2 layout_manager
768              
769             Set/Get the layout manager. Defaults to L<Layout::Manager::Compass>.
770              
771             =head2 legend
772              
773             Set/Get the L<legend|Chart::Clicker::Decoration::Legend> that will be used with this chart.
774              
775             =head2 legend_position
776              
777             The position the legend will be added. Should be one of north, south, east,
778             west or center as required by L<Layout::Manager::Compass>.
779              
780             =head2 marker_overlay
781              
782             Set/Get the L<marker overlay|Chart::Clicker::Decoration::MarkerOverlay> object that will be used if this chart
783             has markers. This is lazily constructed to save time.
784              
785             =head2 over_decorations
786              
787             Set/Get an arrayref of "over decorations", or things that are drawn OVER the
788             chart. This is an advanced feature. See C<overaxis-bar.pl> in the examples.
789              
790             =head2 padding
791              
792             Set/Get the L<padding|Graphics::Primitive::Insets>. Defaults
793             to 3px on all sides.
794              
795             =head2 plot
796              
797             Set/Get the L<plot|Chart::Clicker::Decoration::Plot> on which things are drawn.
798              
799             =head2 subgraphs
800              
801             You can add "child" graphs to this one via C<add_subgraph>. These must be
802             Chart::Clicker objects and they will be added to the bottom of the existing
803             chart. This is a rather esoteric feature.
804              
805             =head2 title
806              
807             Set/Get the title component for this chart. This is a
808             L<Graphics::Primitive::TextBox>, not a string. To set the title of a chart
809             you should access the TextBox's C<text> method.
810              
811             $cc->title->text('A Title!');
812             $cc->title->font->size(20);
813             # etc, etc
814              
815             If the title has text then it is added to the chart in the position specified
816             by C<title_position>.
817              
818             You should consult the documentation for L<Graphics::Primitive::TextBox> for
819             things like padding and text rotation. If you are adding it to the top and
820             want some padding between it and the plot, you can:
821              
822             $cc->title->padding->bottom(5);
823              
824             =head2 title_position
825              
826             The position the title will be added. Should be one of north, south, east,
827             west or center as required by L<Layout::Manager::Compass>.
828              
829             Note that if no angle is set for the title then it will be changed to
830             -1.5707 if the title position is east or west.
831              
832             =head2 width
833              
834             Set/Get the width. Defaults to 500.
835              
836             =head1 METHODS
837              
838             =head2 context_count
839              
840             Get a count of contexts.
841              
842             =head2 context_names
843              
844             Get a list of context names.
845              
846             =head2 delete_context ($name)
847              
848             Remove the context with the specified name.
849              
850             =head2 get_context ($name)
851              
852             Get the context with the specified name
853              
854             =head2 set_context ($name, $context)
855              
856             Set a context of the specified name.
857              
858             =head2 add_to_datasets
859              
860             Add the specified dataset (or arrayref of datasets) to the chart.
861              
862             =head2 dataset_count
863              
864             Get a count of datasets.
865              
866             =head2 get_dataset ($index)
867              
868             Get the dataset at the specified index.
869              
870             =head2 rendered_data
871              
872             Returns the data for this chart as a scalar. Suitable for 'streaming' to a
873             client.
874              
875             =head2 add_to_over_decorations
876              
877             Add an over decoration to the list.
878              
879             =head2 get_over_decoration ($index)
880              
881             Get the over decoration at the specified index.
882              
883             =head2 over_decoration_count
884              
885             Get a count of over decorations.
886              
887             =head2 add_to_contexts
888              
889             Add the specified context to the chart.
890              
891             =head2 add_subgraph
892              
893             Add a subgraph to this chart.
894              
895             =head2 draw
896              
897             Draw this chart.
898              
899             =head2 get_datasets_for_context
900              
901             Returns an arrayref containing all datasets for the given context. Used by
902             renderers to get a list of datasets to chart.
903              
904             =head2 add_data ($name, $data)
905              
906             Convenience method for adding data to the chart. Can be called one of three
907             ways.
908              
909             =over 4
910              
911             =item B<scalar>
912              
913             Passing a name and a scalar will append the scalar data to that series' data.
914              
915             $cc->add_data('Sales', 1234);
916             $cc->add_data('Sales', 1235);
917              
918             This will result in a Series named 'Sales' with two values.
919              
920             =item B<arrayref>
921              
922             Passing a name and an arrayref works much the same as the scalar method
923             discussed above, but appends the supplied arrayref to the existing one. It
924             may be mixed with the scalar method.
925              
926             $cc->add_data('Sales', \@some_sales);
927             $cc->add_data('Sales', \@some_more_sales);
928             # This works still!
929             $cc->add_data('Sales', 1234);
930              
931             =item B<hashref>
932              
933             This allows you to pass both keys and values in all at once.
934              
935             $cc->add_data('Sales', { 2009 => 1234, 2010 => 1235 });
936             # appends to last call
937             $cc->add_data('Sales', { 2011 => 1234, 2012 => 1235 });
938              
939             You may call the hashref version after the scalar or arrayref versions, but you
940             may not add a scalar or arrayref after adding a hashref (as it's not clear what
941             indices should be used for the new data).
942              
943             =back
944              
945             =head2 set_renderer ($renderer_object, [ $context ]);
946              
947             Sets the renderer on the specified context. If no context is provided then
948             'default' is assumed.
949              
950             =head2 write
951              
952             This method is passed through to the underlying driver. It is only necessary
953             that you call this if you manually called C<draw> beforehand. You likely
954             want to use C<write_output>.
955              
956             =head2 write_output ($path)
957              
958             Write the chart output to the specified location. Output is written in the
959             format provided to the constructor (which defaults to Png). Internally
960             calls C<draw> for you. If you use this method, do not call C<draw> first!
961              
962             $c->write_output('/path/to/the.png');
963              
964             =head2 inside_width
965              
966             Get the width available in this container after taking away space for
967             insets and borders.
968              
969             =head2 inside_height
970              
971             Get the height available in this container after taking away space for
972             insets and borders.
973              
974             =head1 ISSUES WITH CENTOS
975              
976             I've had numerous reports of problems with Chart::Clicker when using CentOS.
977             This problem has usually be solved by updating the version of cairo. I've
978             had reports that upgrading to at least cairo-1.8.8-3 makes thinks work properly.
979              
980             I hesitate to provide any other data with this because it may get out of date
981             fast. If you have trouble feel free to drop me an email and I'll tell you
982             what I know.
983              
984             =head1 CONTRIBUTORS
985              
986             Many thanks to the individuals who have contributed various bits:
987              
988             Ash Berlin
989              
990             Brian Cassidy
991              
992             Guillermo Roditi
993              
994             Torsten Schoenfeld
995              
996             Yuval Kogman
997              
998             =head1 SOURCE
999              
1000             Chart::Clicker is on github:
1001              
1002             http://github.com/gphat/chart-clicker/tree/master
1003              
1004             =head1 AUTHOR
1005              
1006             Cory G Watson <gphat@cpan.org>
1007              
1008             =head1 COPYRIGHT AND LICENSE
1009              
1010             This software is copyright (c) 2016 by Cory G Watson.
1011              
1012             This is free software; you can redistribute it and/or modify it under
1013             the same terms as the Perl 5 programming language system itself.
1014              
1015             =cut