1: # The LearningOnline Network with CAPA
2: # Generating TeX tables.
3: #
4: # $Id: lontable.pm,v 1.2 2008/11/25 12:27:34 foxr Exp $
5: #
6: #
7: # Copyright Michigan State University Board of Trustees
8: #
9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
10: #
11: # LON-CAPA is free software; you can redistribute it and/or modify
12: # it under the terms of the GNU General Public License as published by
13: # the Free Software Foundation; either version 2 of the License, or
14: # (at your option) any later version.
15: #
16: # LON-CAPA is distributed in the hope that it will be useful,
17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19: # GNU General Public License for more details.
20: #
21: # You should have received a copy of the GNU General Public License
22: # along with LON-CAPA; if not, write to the Free Software
23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24: #
25: # /home/httpd/html/adm/gpl.txt
26: #
27: # http://www.lon-capa.org/
28: ## Copyright for TtHfunc and TtMfunc by Ian Hutchinson.
29: # TtHfunc and TtMfunc (the "Code") may be compiled and linked into
30: # binary executable programs or libraries distributed by the
31: # Michigan State University (the "Licensee"), but any binaries so
32: # distributed are hereby licensed only for use in the context
33: # of a program or computational system for which the Licensee is the
34: # primary author or distributor, and which performs substantial
35: # additional tasks beyond the translation of (La)TeX into HTML.
36: # The C source of the Code may not be distributed by the Licensee
37: # to any other parties under any circumstances.
38: #
39:
40: # This module is a support packkage that helps londefdef generate
41: # LaTeX tables using the LaTeX::Table package. A prerequisite is that
42: # the print generator must have added the following to the LaTeX header:
43: #
44: # \usepackage{xtab}
45: # \usepackage{booktabs}
46: # \usepackage{array}
47: # \usepackage{colortbl}
48: # \usepackage{xcolor}
49: #
50: # These packages are installed in the packaged LaTeX distributions we know of as of
51: # 11/24/2008
52: #
53:
54:
55:
56: package Apache::lontable;
57: use strict;
58: use LaTeX::Table;
59:
60:
61: =pod
62:
63: =head1 lontable Table generation assistant for the LaTeX target
64:
65: This module contains support software for generating tables in LaTeX output mode
66: In this implementation, we use the LaTeX::Table package to do the actual final formatting.
67: Each table creates a new object. Table objects can have global properties configured.
68: The main operations on a table object are:
69:
70: =over 3
71:
72: =item start_row
73:
74: Opens a new table row.
75:
76: =item end_row
77:
78: Closes a table row.
79:
80: =item start_header
81:
82: Starts a new row that has the header attribute (e.g. <th> tagged row).
83: header rows are ended with an end_row just like any ordinary row.
84:
85: =item configure_row
86:
87: Modifies a configuration item in the currently open row.
88:
89: =item generate
90:
91: Returns the generated table string.
92:
93: =item configure
94:
95: Configures a table's global configuration.
96:
97: =back
98:
99: =cut
100:
101: =pod
102:
103: =head2 new - create a new object.
104:
105: Create a new table object. Any of the raw table configuration items can be
106: modified by this. These configuration items include:
107:
108: my $table = lontable::new(\%config_hash)
109:
110: =over3
111:
112: =item alignment
113:
114: Table alignment. Some table styles support this but not all.
115:
116: =item tableborder
117:
118: If true, a border is drawn around the table.
119:
120: =item cellborder
121:
122: If true, borders are drawn around the cells inside a table.
123:
124: =item caption
125:
126: The table caption text.
127:
128: =item theme
129:
130: The theme of the table to use. Defaults to Zurich. Themes we know about are:
131: NYC, NYC2, Zurich, Berlin, Dresden, Houston, Miami, plain, Paris. Other themes can be added
132: to the LaTeX::Table package, and they will become supported automatically, as theme names are
133: not error checked. Any use of a non-existent theme is reported by the LaTeX::Table package
134: when the table text is generated.
135:
136: =back
137:
138: =head3 Member data
139:
140: The object hash has the following members:
141:
142: =over 3
143:
144: =item column_count
145:
146: Maintained internally, the number of colums in the widest row.
147:
148: =item alignment
149:
150: Table alignment (configurable) "left", "center", or "right".
151:
152: =item outer_border
153:
154: True if a border should be drawn around the entire table (configurable)
155:
156: =item inner_borders
157:
158: True if a border should be drawn around all cells (configurable).
159:
160: =item caption
161:
162: Table caption (configurable).
163:
164: =item theme
165:
166: Theme desired (configurable).
167:
168: =item row_open
169:
170: True if a row is open and not yet closed.
171:
172: =item rows
173:
174: Array of row data. This is an array of hashes described below.
175:
176: =back
177:
178: =head3 Row data.
179:
180: Each row of table data is an element of the rows hash array. Hash elements are
181:
182: =over 3
183:
184: =item is_header
185:
186: True if the user wants to format this row like a header. This row will be used to generate
187: the table header. All header rows will be gathered together into the table header. If there
188: are multiple table headers interspersed with non table header data, this can lead to some
189: surprises.
190:
191: =item default_halign
192:
193: Default horizontal alignment for cells in this row.
194:
195: =item default_valign
196:
197: Default vertical alignment for cells in this row (may be ignored).
198:
199: =item cells
200:
201: Array of hashes where each element represents the data for a cell.
202: The contents of each element of this hash are described below:
203:
204: =over 3
205:
206: =item halign
207:
208: If present, overrides the row default horizontal alignment.
209:
210: =item valign
211:
212: if present, override the row default vertical alignment.
213:
214: =item rowspan
215:
216: If present, indicates the number of rows this cell spans.
217:
218: =item colspan
219:
220: If present indicates the number of columns this cell spans.
221: Note that a cell can span both rows and columns.
222:
223: =item contents
224:
225: The contents of the cell.
226:
227: =back
228:
229: =back
230:
231: =cut
232:
233: sub new {
234: my ($class, $configuration) = @_;
235:
236: # Initialize the object member data with the default values
237: # then override with any stuff in $configuration.
238:
239: my $self = {
240: alignment => "left",
241: outer_border => 0,
242: inner_border => 0,
243: caption => "",
244: theme => "Zurich",
245: column_count => 0,
246: row_open => 0,
247: rows => [],
248: };
249:
250: foreach my $key (keys %$configuration) {
251: $self->{$key} = $$configuration{$key};
252: }
253:
254: bless($self, $class);
255:
256: return $self;
257: }
258:
259: #-------------------------------------------------------------------------
260: #
261: # Methods that get/set table global configuration.
262: #
263:
264: =pod
265:
266: =head2 Gets/set alignment.
267:
268: If the method is passed a new alignment value, that replaces the current one.
269: Regardless, the current alignment is used:
270:
271: =head3 Examples:
272:
273: my $align = $table->alignment(); # Return current alignment
274: $table->alignment("center"); # Attempt centered alignment.
275:
276: =cut
277:
278: sub alignment {
279: my ($self, $new_value) = @_;
280:
281: if (defined($new_value)) {
282: $self->{alignment} = $new_value;
283: }
284: return $self->{alignment};
285: }
286:
287: =pod
288:
289: =head2 table_border
290:
291: Set or get the presence of an outer border in the table.
292: If passed a parameter, that parameter replaces the current request
293: for or not for an outer border. Regardless, the function returns
294: the final value of the outer_border request.
295:
296: =head3 Examples:
297:
298: $table->table_border(1); # Request an outer border.
299: my $outer_requested = $table->table_border();
300:
301: =cut
302:
303: sub table_border {
304: my ($self, $new_value) = @_;
305:
306: if (defined($new_value)) {
307: $self->{outer_border} = $new_value;
308: }
309: return $self->{outer_border};
310: }
311:
312:
313: =pod
314:
315: =head2 cell_border
316:
317: Set or get the presence of a request for cells to have borders
318: drawn around them. If a paramter is passed, it will be treated as
319: a new value for the cell border configuration. Regardless,the final
320: value of that configuration parameter is returned.
321:
322: =head3 Examples:
323:
324: my $cell_borders = $table->cell_border(); # ask if cell borders are requested.
325: $table->cell_border(1); # Request cell borders.
326:
327: =cut
328:
329: sub cell_borders {
330: my ($self, $new_value) = @_;
331:
332: if (defined($new_value)) {
333: $self->{inner_border} = $new_value;
334: }
335: reurn $self->{inner_border};
336: }
337:
338: =pod
339:
340: =head2 caption
341:
342: Gets and/or sets the caption string for the table. The caption string appears to label
343: the table. If a parameter is supplied it will become the new caption string.k
344:
345: =head3 Examples:
346:
347:
348: $my caption = $table->caption();
349: $table->caption("This is the new table caption");
350:
351: =cut
352:
353: sub caption {
354: my ($self, $new_value) = @_;
355:
356: if (defined($new_value)) {
357: $self->catpion = $new_value;
358: }
359:
360: return $self->caption;
361: }
362:
363: =pod
364:
365: =head2 theme
366:
367: Gets and optionally sets the table theme. The table theme describes how the
368: table will be typset by the table package. If a parameter is supplied it
369: will be the new theme selection.
370:
371: =head3 Examples:
372:
373: my $theme = $table->theme();
374: $table->theme("Dresden");
375:
376: =cut
377:
378: sub theme {
379: my ($self, $new_value) = @_;
380:
381: if (defined($new_value)) {
382: $self->theme = $new_value;
383: }
384: return $self->theme;
385: }
386:
387: =pod
388:
389: =head2 start_row
390:
391: Begins a new row in the table. If a row is already open, that row is
392: closed off prior to starting the new row. Rows can have the following attributes
393: which are specified by an optional hash passed in to this function.
394:
395: =over 3
396:
397: =item default_halign
398:
399: The default horizontal alignment of the row. This can be "left", "center", or "right"
400:
401: =item default_valign
402:
403: The default vertical alignment of the row. This can be "top", "center", or "bottom"
404:
405: =back
406:
407: =head3 Examples:
408:
409: $table_start_row(); # no attributes.
410: $table_start({default_halign => "center",
411: default_valign => "bottom"}); # Create setting the attrbutes.
412:
413: =cut
414:
415: sub start_row {
416: my ($self, %config) = @_;
417:
418: if ($self->row_open) {
419: $self->end_row;
420: }
421: my $row_hash = {
422: is_header => 0,
423: default_halign => "left",
424: default_valign => "top",
425: cells => []
426: };
427:
428: # Override the defaults if the config hash is present:
429:
430: if (defined(%config)) {
431: foreach my $key (keys %config) {
432: $row_hash->{$key} = $config{$key};
433: }
434: }
435:
436: my $rows = $self->{rows};
437: push(@$rows, $row_hash);
438:
439: $self->row_open = 1; # Row is now open and ready for business.
440: }
441:
442: =pod
443:
444: =head2 end_row
445:
446: Closes off a row. Once closed, cells cannot be added to this row again.
447:
448: =head3 Examples:
449:
450: $table->close_row();
451:
452:
453: =cut
454:
455: sub close_row {
456: my ($self) = @_;
457:
458: if ($self->row_open) {
459:
460: # Mostly we need to determine if this row has the maximum
461: # cell count of any row in existence in the table:
462:
463: my $row = $self->{rows}[-1];
464: my $cells = $row->{cells};
465: my $cell_count = scalar(@$cells);
466: if ($cell_count > $self->{column_count}) {
467: $self->{column_count} = $cell_count;
468: }
469:
470: $self->row_closed;
471: }
472: }
473:
474: =pod
475:
476: =head2 start_header
477:
478: Starts a row that is a header. This is the same as start_row,but the is_header flag
479: is set to true.
480:
481:
482: =cut
483:
484: sub start_header {
485: my ($self, %config) = @_;
486:
487: $self->start_row(%config);
488: $self->{rows}[-1]->is_header = 1;
489: }
490:
491:
492:
493: # Mandatory initialization.
494:
495: 1;
496: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>