File Coverage

blib/lib/XAO/DO/Web/TextTable.pm
Criterion Covered Total %
statement 70 71 98.5
branch 19 26 73.0
condition 8 12 66.6
subroutine 13 13 100.0
pod 0 8 0.0
total 110 130 84.6


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             XAO::DO::Web::TextTable - plain text tables
4              
5             =head1 SYNOPSIS
6              
7             <%TextTable mode="start"
8             format=" l | r | l "
9             %>
10              
11             <%TextTable mode="head"
12             cell.1.template="Name"
13             cell.2.template="Price"
14             cell.3.template="Description"
15             %>
16              
17             <%TextTable mode="ruler" symbol="-"%>
18              
19             <%TextTable cell.1.template="Fubar"
20             cell.2.template={<%Styler/f dollars="123.34"%>}
21             cell.3.path="/bits/show-description
22             cell.3.ID="123456"
23             %>
24              
25             <%TextTable mode="render" width="70"%>
26              
27             =cut
28              
29             ###############################################################################
30             package XAO::DO::Web::TextTable;
31 1     1   821 use strict;
  1         2  
  1         53  
32 1     1   6 use XAO::Utils;
  1         4  
  1         66  
33 1     1   8 use XAO::Objects;
  1         2  
  1         19  
34 1     1   578 use Text::FormatTable;
  1         3261  
  1         41  
35              
36 1     1   7 use base XAO::Objects->load(objname => 'Web::Action');
  1         2  
  1         13  
37              
38             our $VERSION='2.001';
39              
40             ###############################################################################
41              
42             =head1 DESCRIPTION
43              
44             Web::TextTable object allows to create simple pre-formatted text only
45             tables out of various dynamic content. It currently uses David
46             Schweikert's Text::FormatTable module internally.
47              
48             Due to rendering requirements generating a table is a multi-step process:
49              
50             =over
51              
52             =item 1
53              
54             First you declare a new text table and specify its format. Arguments
55             accepted on that step are:
56              
57             mode => 'start'
58             format => format string as descriped in L
59              
60             =item 2
61              
62             You fill the table by using mode equal to 'row' (default mode), 'head'
63             or 'ruler'.
64              
65             Modes for 'row' and 'head' take the same arguments and currently display
66             exactly the same results:
67              
68             mode => 'head' or 'row'
69             cell.X.template => inline template for cell X of the row (see below)
70             cell.X.path => path to a template
71             cell.X.pass => pass all current arguments to the template
72             cell.X.VAR => make 'VAR' available to the template with the given
73             content
74              
75             Here 'X' may be anything as long as alphanumerically ordered cell.*.*
76             lines give exactly the required number of columns. It is recommended to
77             use single digits in incrementing order to designate rows:
78              
79             <%TextTable mode="head"
80             cell.1.template="Fubar"
81             cell.2.path="/bits/show-price"
82             cell.2.PRICE="123.23"
83             cell.3.path="/bits/show-description
84             cell.3.ID="123456"
85             %>
86              
87             For 'ruler' mode the only optional argument is 'symbol' - what symbol to
88             use to draw the ruler. The default is '-'.
89              
90             =item 3
91              
92             Final step is to use 'render' mode to actually draw the table. One
93             optional argument is 'width' -- the final width of the table. Default
94             width is 75 characters.
95              
96             <%TextTable mode="render"%>
97              
98             =back
99              
100             Tables can be nested as long as there is a 'render' for each 'start'.
101              
102             Internally Web::TextTable uses clipboard variable located at
103             '/var/TextTable'.
104              
105             B You need to be careful with extra spaces and newlines. One
106             way of dealing with it is to enclose table preparation into an unused
107             variable brackets to just throw away extra space:
108              
109             <%SetArg name="UNUSED" value={
110             <%TextTable ....%>
111             <%TextTable ....%>
112             <%TextTable ....%>
113             }%><%TextTable mode="render"%>
114              
115              
116             =cut
117              
118             sub check_mode ($%) {
119 14     14 0 22 my $self=shift;
120 14         32 my $args=get_args(\@_);
121 14   100     162 my $mode=$args->{mode} || 'row';
122              
123 14 100 66     59 if($mode eq 'start') {
    100          
    100          
    100          
    50          
124 2         6 $self->table_start($args);
125             }
126             elsif($mode eq 'head') {
127 1         4 $self->table_head($args);
128             }
129             elsif($mode eq 'ruler' || $mode eq 'rule') {
130 3         8 $self->table_ruler($args);
131             }
132             elsif($mode eq 'row') {
133 6         20 $self->table_row($args);
134             }
135             elsif($mode eq 'render') {
136 2         12 $self->table_render($args);
137             }
138             else {
139 0         0 $self->check_mode($args);
140             }
141             }
142              
143             sub table_start ($%) {
144 2     2 0 3 my $self=shift;
145 2         5 my $args=get_args(\@_);
146              
147             my $format=$args->{format} ||
148 2   33     20 throw $self "table_start - no 'format' argument";
149              
150 2         8 my $table=Text::FormatTable->new($format);
151              
152 2         185 my $tstack=$self->get_tstack;
153 2         11 unshift(@$tstack,$table);
154             }
155              
156             sub table_head ($%) {
157 1     1 0 5 my $self=shift;
158 1         2 my $args=get_args(\@_);
159              
160 1         23 my $tstack=$self->get_tstack;
161              
162 1 50       5 $tstack->[0] ||
163             throw $self "table_head - no current table (start/render mismatch)";
164              
165 1         3 $tstack->[0]->head($self->generate_row($args));
166             }
167              
168             sub table_row ($%) {
169 6     6 0 7 my $self=shift;
170 6         14 my $args=get_args(\@_);
171              
172 6         52 my $tstack=$self->get_tstack;
173              
174 6 50       15 $tstack->[0] ||
175             throw $self "table_row - no current table (start/render mismatch)";
176              
177 6         14 $tstack->[0]->row($self->generate_row($args));
178             }
179              
180             sub table_ruler ($%) {
181 3     3 0 4 my $self=shift;
182 3         9 my $args=get_args(\@_);
183              
184 3         25 my $tstack=$self->get_tstack;
185              
186 3 50       18 $tstack->[0] ||
187             throw $self "table_ruler - no current table (start/render mismatch)";
188              
189 3 50       14 $tstack->[0]->rule(defined($args->{symbol}) ? $args->{symbol} : '-');
190             }
191              
192             sub table_render ($%) {
193 2     2 0 4 my $self=shift;
194 2         20 my $args=get_args(\@_);
195              
196 2         20 my $tstack=$self->get_tstack;
197              
198 2 50       11 $tstack->[0] ||
199             throw $self "table_render - no current table (start/render mismatch)";
200              
201 2   100     12 $self->textout(shift(@$tstack)->render($args->{width} || 75));
202             }
203              
204             sub get_tstack ($) {
205 14     14 0 21 my $self=shift;
206 14         37 my $tstack=$self->clipboard->get('/var/TextTable');
207              
208 14 100       856 if(!$tstack) {
209 1         3 $tstack=[];
210 1         2 $self->clipboard->put('/var/TextTable' => $tstack);
211             }
212              
213 14         82 return $tstack;
214             }
215              
216             sub generate_row ($%) {
217 7     7 0 10 my $self=shift;
218 7         19 my $args=get_args(\@_);
219              
220 7         61 my %params;
221 7         20 foreach my $name (keys %$args) {
222 20 100       66 next unless $name =~ /^cell\.(\w+)\.(.*)$/;
223 19         85 $params{$1}->{$2}=$args->{$name};
224             }
225              
226 7         15 my @row;
227 7         33 foreach my $name (sort keys %params) {
228 19         32 my $p=$params{$name};
229              
230 19   50     60 my $objname=$p->{'objname'} || 'Page';
231              
232 19 50       50 $p=$self->pass_args($p->{'pass'},$p) if $p->{'pass'};
233              
234 19         50 my $obj=$self->object(objname => $objname);
235              
236 19         1343 push(@row,$obj->expand($p));
237             }
238              
239 7         42 return @row;
240             }
241              
242             ###############################################################################
243             1;
244             __END__