--- loncom/xml/lontable.pm 2011/04/13 10:08:06 1.17 +++ loncom/xml/lontable.pm 2014/12/15 00:52:40 1.22 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Generating TeX tables. # -# $Id: lontable.pm,v 1.17 2011/04/13 10:08:06 foxr Exp $ +# $Id: lontable.pm,v 1.22 2014/12/15 00:52:40 raeburn Exp $ # # # Copyright Michigan State University Board of Trustees @@ -57,9 +57,8 @@ package Apache::lontable; use strict; use Apache::lonlatextable; use Apache::lonnet; # for trace logging. -use Data::Dumper; -my $tracing = 1; # Set to 1 to enable log tracing. 2 for local sub tracing. +my $tracing = 0; # Set to 1 to enable log tracing. 2 for local sub tracing. =pod @@ -272,11 +271,12 @@ 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. }; - foreach my $key (keys %$configuration) { + foreach my $key (keys(%$configuration)) { $self->{$key} = $$configuration{$key}; } @@ -500,7 +500,7 @@ sub start_row { # Override the defaults if the config hash is present: if (defined($config)) { - foreach my $key (keys %$config) { + foreach my $key (keys(%$config)) { $row_hash->{$key} = $config->{$key}; } } @@ -533,8 +533,7 @@ sub end_row { # Mostly we need to determine if this row has the maximum # cell count of any row in existence in the table: - &Apache::lonnet::logthis($self->{'part'}); - &Apache::lonnet::logthis(Dumper($self->{'rows'})); + my $row = $self->{'rows'}->{$self->{'part'}}->[-1]; my $cells = $row->{'cells'}; @@ -584,7 +583,7 @@ sub configure_row { } my $row = $self->{'rows'}->{$self->{'part'}}->[-1]; - foreach my $config_item (keys %$config) { + foreach my $config_item (keys(%$config)) { $row->{$config_item} = $config->{$config_item}; } } @@ -932,7 +931,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. + } @@ -968,7 +969,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); @@ -994,7 +996,7 @@ sub generate { my $specified_width = 0.0; my $specified_cols = 0; - foreach my $col (keys %$colwidths) { + foreach my $col (keys(%$colwidths)) { $specified_width = $specified_width + $colwidths->{$col}; $specified_cols++; } @@ -1024,28 +1026,48 @@ sub generate { $default_width = ($tablewidth/$unspecified_cols); # 'fair' default width. my $width_remaining = $tablewidth - $default_width*$unspecified_cols; # What's left for the specified cols. my $reduction = $tablewidth/$width_remaining; # Reduction fraction for specified cols - foreach my $col (keys %$colwidths) { + foreach my $col (keys(%$colwidths)) { $colwidths->{$col} = $colwidths->{$col}/$reduction; } } } - - 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}"; @@ -1056,6 +1078,10 @@ sub generate { ($outer_border && ($i == $column_count-1))) { $coldef .= '|'; } + if ($part_border && ($i == ($colgroup_ends[$group]-1))) { + $coldef .= '|'; + $group++; + } } $table->{'coldef'} = $coldef; @@ -1100,24 +1126,24 @@ 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") }; # Do nothing if that part of the table is empty: - &Apache::lonnet::logthis(Dumper($this->{'rows'})); if ($this->{'rows'}->{$part} == undef) { if ($tracing) {&Apache::lonnet::logthis("$part is empty"); } 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'}; @@ -1145,11 +1171,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. @@ -1198,11 +1226,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 @@ -1224,6 +1270,7 @@ sub render_part { push(@underlines, "\\cline{$startcol-$lastcol}"); } $startcol = $nextcol; + # Rowspans should take care of themselves. push(@row, $contents);