Annotation of loncom/xml/lonlatextable.pm, revision 1.4

1.1       foxr        1: #  Generating TeX tables.
                      2: #
1.4     ! foxr        3: # $Id: lonlatextable.pm,v 1.3 2011/04/13 10:08:06 foxr Exp $
1.1       foxr        4: # 
                      5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: ## Copyright for TtHfunc and TtMfunc by Ian Hutchinson. 
                     28: # TtHfunc and TtMfunc (the "Code") may be compiled and linked into 
                     29: # binary executable programs or libraries distributed by the 
                     30: # Michigan State University (the "Licensee"), but any binaries so 
                     31: # distributed are hereby licensed only for use in the context
                     32: # of a program or computational system for which the Licensee is the 
                     33: # primary author or distributor, and which performs substantial 
                     34: # additional tasks beyond the translation of (La)TeX into HTML.
                     35: # The C source of the Code may not be distributed by the Licensee
                     36: # to any other parties under any circumstances.
                     37: #
                     38: 
                     39: # This module is a support packkage that helps londefdef generate
                     40: # LaTeX tables using the LaTeX::Table package.  A prerequisite is that
                     41: # the print generator must have added the following to the LaTeX 
                     42: #
                     43: #  \usepackage{xtab}
                     44: #  \usepackage{booktabs}
                     45: #  \usepackage{array}
                     46: #  \usepackage{colortbl}
                     47: #  \usepackage{xcolor}
                     48: #
                     49: #  These packages are installed in the packaged LaTeX distributions we know of as of
                     50: #  11/24/2008
                     51: #
                     52: 
                     53: 
                     54: # 
                     55: #  This module provides a sub-set substitute for LaTeX::table 
                     56: #  which is a great module but unfortunately not usable in safe space
                     57: #  
                     58: 
                     59: 
                     60: =pod
                     61: 
                     62: =head1  NAME
                     63: 
                     64: Apache:lonltextable
                     65: 
                     66: =head1 SYNOPSIS
                     67: 
                     68:     use Apache::lonlatextable;
                     69: 
                     70:     $table = Apache::lonlatextable->new();
                     71:     $table->set_caption("some text");
                     72:     $table->set_data(cell_descriptions);
                     73:     $table->{'coldef'} = column_definitions;
                     74:     $table->generate_string();
                     75: 
                     76: =head1 DETAILS
                     77: 
                     78: =cut
                     79: 
                     80: package Apache::lonlatextable;
                     81: use strict;
                     82: 
                     83: =pod
                     84: 
                     85: =head2 new
                     86: 
                     87: Creates a new instance of a lonlatextable.  The returned value should be used on the left side of the
                     88: -> for further calls to object methods
                     89: 
                     90: =head3 Example:
                     91:    
                     92:     my $latexTable = &Apache::lonlatextable->new();
                     93: 
                     94: =cut
                     95: 
                     96: 
                     97: sub new {
                     98:     my ($class) = @_;
                     99: 
                    100:     my $self = {
                    101: 	caption           => '',
                    102: 	data              => [],
                    103: 	coldef            =>  '',
                    104: 	
                    105:     };
                    106:     bless($self, $class);
                    107:     return $self;
                    108: }
                    109: 
                    110: =pod
                    111: 
                    112: =head2 set_caption(some_text)
                    113: 
                    114: Set the table caption value.  If this string is empty, the table will be generated without a caption.
                    115: some_text will be the  new table caption value.
                    116: 
                    117: =head3 Example:
                    118: 
                    119:     $table = Apache::lonlatextable->new();
                    120:     $table->set_caption("Some very interesting table");
                    121: 
                    122: =cut
                    123: 
                    124: sub set_caption {
                    125:     my ($self, $caption) = @_;
                    126:     $self->{'caption'} = $caption;
                    127: }
                    128: 
                    129: =pod
                    130: 
                    131: =head2 set_data(cell_descriptions)
                    132: 
                    133: Sets the table cell data.  Table data in its simplest is an aray of arrays.  Each outer 
                    134: array element is a table row. However:
                    135:   
                    136: =over 3
                    137: 
                    138: =item Single column rows sarting with \
                    139: 
                    140: These are treated as LaTeX/TeX commands and, when the table is generated, 
                    141: passed without interpretation.
                    142: 
1.2       foxr      143: =item Lines with one cell that is empty.
1.1       foxr      144: 
                    145: These produce a horizontal rule that spans the width of the table.
                    146: 
                    147: =back
                    148: 
1.3       foxr      149: Calling this multiple times will continue to append cell data.
                    150: 
1.1       foxr      151: =head3 Example
                    152: 
                    153:     $table->set_data([ ['Gnu', '92.52'], [], ['Emu', '33.33'] ]);
                    154: 
                    155: Produces
                    156:     +--------------+--------------+
                    157:     |   Gnu        | 92.52        |
                    158:     +--------------+--------------+ (due to the empty row).
                    159:     |   Emu        | 33.33        |
                    160:     +--------------+--------------+
                    161: 
1.3       foxr      162: 
1.1       foxr      163: =cut
                    164: 
                    165: sub set_data {
                    166:     my ($self, $data) = @_;
1.3       foxr      167:     my $current_data = $self->{'data'};
                    168:     push (@$current_data, @$data);
                    169:     $self->{'data'} = $current_data;
                    170: 
1.1       foxr      171: 
                    172: }
                    173: 
                    174: =pod
                    175: 
                    176: =head2 Column  definitions.
                    177: 
                    178: The hash value 'coldef' can overide the column definitions computed by default for the table.
                    179: 
                    180: =head3 Example
                    181: 
                    182:     $table->{'coldef'} = 'lrcr';
                    183: 
                    184: Produces table header output of:
                    185: 
                    186:     \begin{tabular}{lrcr}
                    187: 
                    188: The default is to produce a set of left aligned columns.  The number of columns produced
                    189: will be determined by the size of the longest row.
                    190: 
                    191: =cut
                    192: 
                    193: =pod
                    194: 
                    195: =head2   $table->generate_string()
                    196: 
                    197: Generates the LaTeX for the table as a string that is returned to the caller.
                    198: 
                    199: =head3 Example
                    200: 
                    201:     $latex = $table->generate_string();
                    202: 
                    203: =cut
                    204: 
                    205: sub generate_string {
                    206: 
                    207:     my ($self) = @_;
                    208:     my $result;
                    209: 
                    210:     $result  = $self->table_header();
                    211:     $result .= $self->table_body();
                    212:     $result .= $self->table_trailer();
                    213: 
                    214: 
                    215: 
                    216:     return $result;
                    217: }
                    218:  
                    219: 
                    220: ###################################################################################
                    221: #
                    222: #  Private methods:
                    223: #
                    224: 
                    225: #  generate the table header.
                    226: #  If coldef is an empty string, the default column definition is computed instead.
                    227: #
                    228: sub table_header()
                    229: {
                    230:     my ($self) = @_;
1.2       foxr      231:     my $result = '\begin{tabular}{';
1.1       foxr      232:     my $coldef = $self->{'coldef'};
                    233: 
                    234:     if ($coldef eq '') {
                    235: 	my @rows   = @$self->{'data'};
                    236: 	my $longest = 0;
                    237: 	foreach my $row (@rows) {
                    238: 	    my $length = scalar @{$row};
                    239: 	    if ($length > $longest) {
                    240: 		$longest = $length;
                    241: 	    }
                    242:         } 
                    243: 	# $longest cells all left aligned.
                    244: 	# There's got to be a better way than this in perl?
                    245: 
                    246: 	for (my $i =0; $i < $longest; $i++) {
                    247: 	    $coldef .= 'l';
                    248: 	}
                    249:     }
                    250:     
                    251:     $result .= $coldef . '}';
                    252:     $result .= "\n";
                    253: 
                    254:     return $result;
                    255: }
                    256: #
                    257: #   Generate the table body
                    258: #
                    259: sub table_body()
                    260: {
1.2       foxr      261:     my ($self) = @_;
                    262:     my $result = '';
                    263:     foreach my $row (@{$self->{'data'}}) {
                    264: 	#
                    265: 	# If a row has only a single cell we need to deal with the two special cases
                    266: 	# Pass LaTeX uninterpreted or \hline.
                    267: 	#
                    268: 	if ((scalar @{$row}) == 1) {
                    269: 	    my $cell = $row->[0];
                    270: 	    if ($cell eq '') {
                    271: 		$result .= '\hline' . "\n";
                    272: 	    } elsif (substr($cell, 0, 1) eq "\\") {
                    273: 		$result .= $cell . "\n";
                    274: 	    } else {
                    275: 		# could just be a table with one col...
                    276: 
                    277: 		$result .= $cell . ' \\\\ ' ."\n";
                    278: 	    }
                    279: 	} else {
                    280: 	    my $line = '';
                    281: 	    foreach my $cell (@{$row}) {
                    282: 		$line .= $cell . ' & ';
                    283: 	    }
                    284: 	    #  Replace the last ' & ' with \\ and a line terminator..
                    285: 	    #  and append the line to the result.
                    286: 
                    287: 	    $line =~ s/ & $/ \\\\\n/;
                    288: 	    $result .= $line;
                    289: 	}
                    290:     }
                    291:     return $result;
1.1       foxr      292: }
                    293: 
                    294: #
                    295: #  Generate the table trailer
                    296: #
                    297: sub table_trailer {
                    298:     my ($self) = @_;
                    299: 
                    300:     my $result = '\end{tabular}' . "\n";
                    301:     if ($self->{'caption'} ne '') {
                    302: 	$result .= '\caption{' . $self->{'caption'} . '}' . "\n";
                    303:     }
                    304:     return $result;
                    305: }
                    306: 
                    307: 
                    308: 
                    309: 1;
                    310: __END__

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>