--- loncom/xml/lontable.pm 2011/04/13 10:44:26 1.18 +++ loncom/xml/lontable.pm 2011/04/19 22:30:42 1.19 @@ -1,16 +1,13 @@ + # The LearningOnline Network with CAPA # Generating TeX tables. # -# $Id: lontable.pm,v 1.18 2011/04/13 10:44:26 foxr Exp $ +# $Id: lontable.pm,v 1.19 2011/04/19 22:30:42 foxr Exp $ # # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). -# -# LON-CAPA is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, @@ -57,7 +54,7 @@ package Apache::lontable; use strict; use Apache::lonlatextable; use Apache::lonnet; # for trace logging. - +use Data::Dumper; my $tracing = 0; # Set to 1 to enable log tracing. 2 for local sub tracing. @@ -272,7 +269,8 @@ sub new { 'foot' => [] }, col_widths => {}, - part => 'body' # one of 'body', 'head', 'foot'. + part => 'body', # one of 'body', 'head', 'foot'. + colgroups => [] # Stores information about column groups. }; @@ -931,7 +929,9 @@ define the column group. sub define_colgroup { my ($this, $attributes) = @_; if ($tracing) { &Apache::lonnet::logthis("col_group"); } - + my $colgroups = $this->{'colgroups'}; + push(@$colgroups, $attributes); # Colgroups always add at end. + } @@ -967,7 +967,8 @@ sub generate { my $cell_lr_border = (($inner_border == 1) || ($inner_border == 3)) ? 1 : 0; my $part_border = ($inner_border == 4); - # Add the caption if supplied. + + # Add the caption if supplied. if ($this->{'caption'} ne "") { $table->set_caption($this->caption); @@ -1029,22 +1030,42 @@ sub generate { } } - - if ($tracing) { &Apache::lonnet::logthis("rendering head"); } - $this->render_part('head', $table, $useP, $default_width); - if ($tracing) { &Apache::lonnet::logthis("rendering body"); } - $this->render_part('body', $table, $useP, $default_width); - if ($tracing) { &Apache::lonnet::logthis("rendering footer"); } - $this->render_part('foot', $table, $useP, $default_width); + # If rule is groups. we need to have a + # list of the column numbers at which a column ends... + # and the coldef needs to start with a | + # + my @colgroup_ends; + my $colgroup_col = 0; + my $group = 0; + my $coldef = ""; + if ($outer_border || $cell_lr_border) { + $coldef .= '|'; + } + if ($part_border) { + $coldef .= '|'; + my $colgroup_col = 0; + my $colgroups = $this->{'colgroups'}; + foreach my $group (@$colgroups) { + if (defined $group->{'span'}) { + $colgroup_col += $group->{'span'}; + } else { + $colgroup_col++; + } + push(@colgroup_ends, $colgroup_col); + } + + } + $this->render_part('head', $table, $useP, $default_width, + \@colgroup_ends); + $this->render_part('body', $table, $useP, $default_width, + \@colgroup_ends); + $this->render_part('foot', $table, $useP, $default_width, + \@colgroup_ends); - my $coldef = ""; - if ($outer_border || $cell_lr_border) { - $coldef .= '|'; - } for (my $i =0; $i < $column_count; $i++) { if ($useP) { $coldef .= "p{$default_width $colunits}"; @@ -1055,6 +1076,10 @@ sub generate { ($outer_border && ($i == $column_count-1))) { $coldef .= '|'; } + if ($part_border && ($i == ($colgroup_ends[$group]-1))) { + $coldef .= '|'; + $group++; + } } $table->{'coldef'} = $coldef; @@ -1090,6 +1115,32 @@ sub size_to_cm { } return $size; # Default is cm. +} + + + +#--------------------------------------------------------------------------- +# +# Private methods: +# + +# +# Convert size with units -> size in cm. +# The resulting size is floating point with no units so that it can be used in +# computation. Note that an illegal or missing unit is treated silently as +# cm for now. +# +sub size_to_cm { + my ($this, $size_spec) = @_; + my ($size, $units) = split(/ /, $size_spec); + if (lc($units) eq 'mm') { + return $size / 10.0; + } + if (lc($units) eq 'in') { + return $size * 2.54; + } + + return $size; # Default is cm. } # @@ -1099,7 +1150,8 @@ sub size_to_cm { # respectively. # sub render_part { - my ($this, $part, $table, $useP, $default_width) = @_; + my ($this, $part, $table, $useP, + $default_width, $colgroup_ends) = @_; if ($tracing) { &Apache::lonnet::logthis("render_part: $part") }; @@ -1110,12 +1162,12 @@ sub render_part { return; } - + my @cgends = @$colgroup_ends; # Build up the data: my @data; my $colwidths = $this->{'col_widths'}; - my $rows = $this->{'rows'}->{$part}; # TODO: Render header, body footer as groups. + my $rows = $this->{'rows'}->{$part}; my $row_count = scalar(@$rows); my $inner_border = $this->{'inner_border'}; my $outer_border = $this->{'outer_border'}; @@ -1143,11 +1195,13 @@ sub render_part { my $startcol = 1; my @underlines; # Array of \cline cells if cellborder on. - + my $colgroup_count = @cgends; # Number of column groups. + my $cgroup = 0; # Group we are on. + my $cgstart = 0; # Where the next cgroup starts. for (my $cell = 0; $cell < $cell_count; $cell++) { my $contents = $cells->[$cell]->{'contents'}; - + # # Cell alignment is the default alignment unless # explicitly specified in the cell. @@ -1196,11 +1250,29 @@ sub render_part { if ($cell_lr_border || ($outer_border && ($cell == ($cell_count -1)))) { $col_align = $col_align.'|'; } + if ($part_border) { + if ($cell == $cgstart) { + $col_align = '|' . $col_align; + if ($cgroup < $colgroup_count) { + $cgstart = $cgends[$cgroup]; + $cgroup++; + } else { + $cgstart = 1000000; # TODO: Get this logic right + } + if ($cell == ($cell_count - 1) && + ($cell == ($cgstart-1))) { + $col_align = $col_align . '|'; # last col ends colgrp. + } + } + } #factor in spans: my $cspan = $cells->[$cell]->{'colspan'}; my $nextcol = $startcol + $cspan; + + # At this point this col is the start of the span. + # nextcol is the end of the span. # If we can avoid the \multicolumn directive that's best as # that makes some things like \parpic invalid in LaTeX which @@ -1222,6 +1294,7 @@ sub render_part { push(@underlines, "\\cline{$startcol-$lastcol}"); } $startcol = $nextcol; + # Rowspans should take care of themselves. push(@row, $contents);