1package Chart::Clicker::Decoration::Legend::Tabular;
2$Chart::Clicker::Decoration::Legend::Tabular::VERSION = '2.90';
3use Moose;
4
5extends 'Chart::Clicker::Decoration::Legend';
6
7# ABSTRACT: Tabular version of Legend
8
9use Graphics::Primitive::Font;
10use Graphics::Primitive::Insets;
11use Graphics::Primitive::TextBox;
12use Graphics::Color::RGB;
13
14use Layout::Manager::Grid;
15
16
17has '+border' => (
18    default => sub {
19        my $b = Graphics::Primitive::Border->new;
20        $b->color(Graphics::Color::RGB->new( red => 0, green => 0, blue => 0));
21        $b->width(1);
22        return $b;
23    }
24);
25
26
27has '+color' => (
28    default => sub { Graphics::Color::RGB->new( red => 0, green => 0, blue => 0) }
29);
30
31
32has 'data'  => (
33    is => 'rw',
34    isa => 'ArrayRef[ArrayRef[Str]]',
35    required => 1
36);
37
38
39has 'font' => (
40    is => 'rw',
41    isa => 'Graphics::Primitive::Font',
42    default => sub {
43        Graphics::Primitive::Font->new
44    }
45);
46
47
48has 'header' => (
49    is => 'rw',
50    isa => 'ArrayRef[Str]',
51    predicate => 'has_header'
52);
53
54
55has 'item_padding' => (
56    is => 'rw',
57    isa => 'Graphics::Primitive::Insets',
58    default => sub {
59        Graphics::Primitive::Insets->new({
60            top => 3, left => 3, bottom => 3, right => 5
61        })
62    }
63);
64has '+layout_manager' => (
65    default => sub {
66        my $self = shift;
67        my $header_rows = $self->has_header ? 1 : 0;
68        return Layout::Manager::Grid->new(
69            rows => scalar(@{ $self->data }) + $header_rows,
70            columns => scalar(@{ $self->data->[0] }) + 1
71        );
72    },
73    lazy => 1
74);
75
76override('prepare', sub {
77    my ($self, $driver) = @_;
78
79    return if $self->component_count > 0;
80
81    my $ca = $self->clicker->color_allocator;
82
83    my $font = $self->font;
84
85    my $ii = $self->item_padding;
86
87    if($self->is_vertical) {
88        # This assumes you aren't changing the layout manager...
89        $self->layout_manager->anchor('north');
90    }
91
92    my $row_offset = 0;
93    if($self->has_header) {
94        $row_offset = 1;
95        my $count = 0;
96        # foreach my $d (@{ $self->header }) {
97        for(0..scalar(@{ $self->header }) - 1) {
98            $self->add_component(
99                Graphics::Primitive::TextBox->new(
100                    color => $self->color,
101                    font => $font,
102                    padding => $ii,
103                    text => $self->header->[$_]
104                ),
105                { row => 0, column => $_ }
106            );
107            $count++;
108        }
109    }
110
111    my @data = @{ $self->data };
112
113    my $count = 0;
114    foreach my $ds (@{ $self->clicker->datasets }) {
115        foreach my $s (@{ $ds->series }) {
116
117            my $color = $ca->next;
118
119            unless($s->has_name) {
120                $s->name("Series $count");
121            }
122
123            my $tb = Graphics::Primitive::TextBox->new(
124                color => $color,
125                font => $font,
126                padding => $ii,
127                text => $s->name
128            );
129
130            $self->add_component($tb, { row => $count + $row_offset, column => 0 });
131
132            for(0..scalar(@{ $data[$count] }) - 1) {
133                $self->add_component(
134                    Graphics::Primitive::TextBox->new(
135                        color => $color,
136                        font => $font,
137                        padding => $ii,
138                        text => $data[$count]->[$_]
139                    ),
140                    { row => $count + $row_offset, column => $_ + 1 }
141                );
142            }
143
144            $count++;
145        }
146    }
147
148    super;
149
150    $ca->reset;
151});
152
153__PACKAGE__->meta->make_immutable;
154
155no Moose;
156
1571;
158
159__END__
160
161=pod
162
163=head1 NAME
164
165Chart::Clicker::Decoration::Legend::Tabular - Tabular version of Legend
166
167=head1 VERSION
168
169version 2.90
170
171=head1 SYNOPSIS
172
173    my $cc = Chart::Clicker->new;
174
175    my $series1 = Chart::Clicker::Data::Series->new;
176    my $series2 = Chart::Clicker::Data::Series->new;
177
178    $cc->legend(Chart::Clicker::Decoration::Legend::Tabular->new(
179        header => [ qw(Name Min Max) ],
180        data => [
181            [ min(@{ $series1->values }), max(@{ $series1->values }) ],
182            [ min(@{ $series2->values }), max(@{ $series2->values }) ]
183        ]
184    ));
185
186=head1 DESCRIPTION
187
188Chart::Clicker::Decoration::Legend::Tabular draws a legend on a Chart with
189tabular data display.
190
191The Tabular legend is a legend with a few extra attributes that allow you to
192pass it data to display.  The attributes are c<header> and c<data>.  The
193C<header> (optional) allows you to specify the strings to display at the top
194of the table and the C<data> attribute allows you to pass in arrayrefs of
195strings for display aside each of the series.
196
197B<Note>: The first string in the C<header> arrayref should be the header for
198the column above the name of the series.  This code does not do anything
199to verify that you've given the appropriate counts of data.  It is expected
200that you will provide C<data> with one arrayref for every series, each
201containing n elements.  Having that, C<header> will expect n + 1 elements
202with one for the series name and the remaining (n) matching the number of
203elements in each of C<data>'s arrayrefs.
204
205=head1 ATTRIBUTES
206
207=head2 border
208
209Set/Get this Legend's L<border|Graphics::Primitive::Border>.
210
211=head2 color
212
213Set/Get the L<color|Graphics::Color::RGB> to use as the foreground for the legend.
214
215=head2 data
216
217Set/Get the data for this legend.  Expects an arrayref of arrayrefs, with
218one inner arrayref for every series charted.
219
220=head2 font
221
222Set/Get the L<font|Graphics::Primitive::Font> used for this legend's items.
223
224=head2 header
225
226Set/Get the header data used for this legend.  Expects an arrayref of Strings.
227
228=head2 insets
229
230Set/Get this Legend's insets.
231
232=head2 item_padding
233
234Set/Get the L<padding|Graphics::Primitive::Insets> for this legend's items.
235
236=head1 METHODS
237
238=head2 has_header
239
240Predicate returning true of this legend has a header, else 1.
241
242=head1 AUTHOR
243
244Cory G Watson <gphat@cpan.org>
245
246=head1 COPYRIGHT AND LICENSE
247
248This software is copyright (c) 2016 by Cory G Watson.
249
250This is free software; you can redistribute it and/or modify it under
251the same terms as the Perl 5 programming language system itself.
252
253=cut
254