[LON-CAPA-cvs] cvs: loncom /xml londefdef.pm lontable.pm
foxr
foxr@source.lon-capa.org
Tue, 20 Jan 2009 12:01:01 -0000
This is a MIME encoded message
--foxr1232452861
Content-Type: text/plain
foxr Tue Jan 20 12:01:01 2009 EDT
Modified files:
/loncom/xml londefdef.pm lontable.pm
Log:
Switch to new table code. It seems to work for all my table problems.
--foxr1232452861
Content-Type: text/plain
Content-Disposition: attachment; filename="foxr-20090120120101.txt"
Index: loncom/xml/londefdef.pm
diff -u loncom/xml/londefdef.pm:1.397 loncom/xml/londefdef.pm:1.398
--- loncom/xml/londefdef.pm:1.397 Mon Nov 24 18:55:01 2008
+++ loncom/xml/londefdef.pm Tue Jan 20 12:01:00 2009
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Tags Default Definition Module
#
-# $Id: londefdef.pm,v 1.397 2008/11/24 18:55:01 jms Exp $
+# $Id: londefdef.pm,v 1.398 2009/01/20 12:01:00 foxr Exp $
#
#
# Copyright Michigan State University Board of Trustees
@@ -42,6 +42,7 @@
use Apache::lonnet;
use strict;
use Apache::lonxml;
+use Apache::lontable;
use Apache::File();
use Image::Magick;
use Apache::lonmenu();
@@ -58,20 +59,7 @@
}
-#
-# Dumps all elements of the table structure.
-# Need this 'cause evidently when given an array, Data::Dumper only seems
-# to dump element 0.
-#
-#sub debug_dump_table {
-# my $lastrow = $#Apache::londefdef::table;
-# &Apache::lonnet::logthis("Dumping table: Last row index: $lastrow");
-# my $row;
-# for ($row =0; $row <= $lastrow; $row++ ) {
-# my $text = Dumper($Apache::londefdef::table[$row]);
-# &Apache::lonnet::logthis("table [ $row ]".$text);
-# }
-#}
+
sub initialize_londefdef {
$Apache::londefdef::TD_redirection=0;
@Apache::londefdef::table = ();
@@ -208,6 +196,12 @@
'\usepackage{pifont}' ."\n".
'\usepackage{latexsym}'."\n".
'\usepackage{epsfig}'.
+ "\\usepackage{xtab}\n".
+ "\\usepackage{tabularx}\n".
+ "\\usepackage{booktabs}\n".
+ "\\usepackage{array}\n".
+ "\\usepackage{colortbl}\n".
+ "\\usepackage{xcolor}\n".
'\usepackage{calc}'.
'\usepackage{amsmath}'.
'\usepackage{amssymb}'.
@@ -2018,7 +2012,8 @@
# only way I could think of to allow <p> in
# <tr> <th> bodies
#
-#list of supported attributes: border,width,TeXwidth
+#list of supported attributes: border,width,TeXwidth,TeXtheme
+# align
sub start_table {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $textwidth = '';
@@ -2027,6 +2022,59 @@
$currentstring .= $token->[4];
} elsif ($target eq 'tex') {
&disable_para(); # Can't have paras in a table.
+
+
+ # New table code:
+
+ # Get the parameters that we can do something about:
+
+ my $border = &Apache::lonxml::get_param('border', $parstack, $safeeval, undef, 0);
+ my $width = &Apache::lonxml::get_param('TeXwidth', $parstack, $safeeval, undef, 0);
+ my $theme = &Apache::lonxml::get_param('TeXtheme', $parstack, $safeeval, undef, 0);
+ my $align = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 0);
+
+ # The only thing that needs any figuring out is the width.. and then only if it is
+ # a percent. If not it's assumed to be some valid TeX measurement unit e.g. 3.0cm
+ #
+
+ my $table = new Apache::lontable();
+ if ($border ne '') {
+ $table->table_border(1);
+ $table->cell_border(1);
+ }
+ if ($theme ne '') {
+ $table->theme($theme);
+ }
+ if ($align ne '') {
+ $table->alignment($align);
+ }
+
+ # Missing width is most of page width
+
+ if ($width eq "") {
+ $width = '70%';
+ }
+
+ # If a percentage, need to calculate what this means in terms of
+ # page width:
+
+ if ($width =~ /%$/) {
+ my $textwidth = &recalc($env{'form.textwidth'}); # Page width in mm.
+ $width =~ s/%//;
+ $width = $width * $textwidth / 100.0;
+ $width .= " mm";
+ $table->width($width);
+ }
+
+ push(@Apache::londefdef::table, $table);
+ $currentstring.=' \keephidden{NEW TABLE ENTRY}';
+
+ #--------------------------------------------------------
+ # Old table code here.
+ #--------------------------------------------------------
+
+
+ if (0) {
push(@Apache::londefdef::table, {});
$Apache::londefdef::table[-1]{'row_number'} = -1;
#maximum table's width (default coincides with text line length)
@@ -2101,7 +2149,7 @@
$Apache::londefdef::table[-1]{'content'}=[];
$Apache::londefdef::table[-1]{'align'}=[];
$currentstring.=' \keephidden{NEW TABLE ENTRY}';
-
+ }
}
return $currentstring;
@@ -2113,6 +2161,20 @@
if ($target eq 'web' || $target eq 'webgrade') {
$currentstring = $token->[2];
} elsif ($target eq 'tex') {
+
+
+ # New table code:
+
+ my $table = pop(@Apache::londefdef::table);
+ my $t = $table->generate();
+ $currentstring = $t->generate_string();
+ &enable_para();
+ #--------------------------------------------------------------
+ # Old table code:
+ #--------------------------------------------------------------
+
+ if (0) {
+
my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval);
my $inmemory = '';
my $output = '';
@@ -2528,6 +2590,7 @@
}
&enable_para();
}
+ }
return $currentstring;
}
@@ -2538,6 +2601,19 @@
if ($target eq 'web' || $target eq 'webgrade') {
$currentstring = $token->[4];
} elsif ($target eq 'tex') {
+
+ my $align = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 1);
+ $Apache::londefdef::table[-1]->start_row();
+
+ if ($align ne '') {
+ $Apache::londefdef::table[-1]->configure_row({default_halign => $align});
+ }
+
+ #---------------------------------------------------------------
+ # Old table code.
+ #---------------------------------------------------------------
+
+ if (0) {
$Apache::londefdef::table[-1]{'row_number'}++;
my $alignchar=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
if ($alignchar ne '') {
@@ -2556,6 +2632,7 @@
push @ {$Apache::londefdef::table[-1]{'minlen'}}, [];
push @ {$Apache::londefdef::table[-1]{'maxlen'}}, [];
push @ {$Apache::londefdef::table[-1]{'content'}}, [];
+ }
}
return $currentstring;
}
@@ -2566,6 +2643,19 @@
if ($target eq 'web' || $target eq 'webgrade') {
$currentstring .= $token->[2];
} elsif ($target eq 'tex') {
+
+ # In case the user is missing a </td> or </th> tag:
+
+ if ($Apache::londefdef::TD_redirection) {
+ &end_td_tex($parstack,$parser,$safeeval);
+ }
+ $Apache::londefdef::table[-1]->end_row();
+
+ #-----------------------------------------------
+ # Old table code
+ #-----------------------------------------------
+
+ if (0) {
if ($Apache::londefdef::TD_redirection) {
&end_td_tex($parstack,$parser,$safeeval);
}
@@ -2574,7 +2664,7 @@
if ($Apache::londefdef::table[-1]{'prior_columns'} > $Apache::londefdef::table[-1]{'counter_columns'}) {
$Apache::londefdef::table[-1]{'counter_columns'} = $Apache::londefdef::table[-1]{'prior_columns'};
}
-
+ }
}
@@ -2610,9 +2700,50 @@
}
return '';
}
+
+#
+# Factor out cell configuration hash generation:
+#
+
+sub cell_config_hash {
+ my ($align, $rowspan, $colspan) = @_;
+ my %config;
+ if ($align ne '') {
+ $config{'halign'} = $align;
+ }
+ if ($colspan ne "") {
+ $config{'colspan'} = $colspan;
+ }
+ if ($rowspan ne '') {
+ $config{'rowspan'} = $rowspan;
+ }
+ return \%config;
+}
sub start_td_tex {
my ($parstack,$parser,$safeeval) = @_;
+
+ # At this stage, an empty cell is created with the
+ # appropriate rowspan/colspan and alignment
+ # attributes, but empty of text. end_td_tex will
+ # fetch the contents from the recursive parse and
+ # fill the cell with them:
+ my $align = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 1);
+ my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval, undef, 1);
+ my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval, undef, 1);
+
+ my $config = &cell_config_hash($align, $rowspan, $colspan);
+
+ my $table = $Apache::londefdef::table[-1];
+ $table->add_cell('', $config);
+
+
+ #------------------------------------------------
+ # Old table code.
+ #------------------------------------------------
+
+ if (0) {
+
my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
if ($alignchar eq '') {
$alignchar = $Apache::londefdef::table[-1]{'rows'}[-1];
@@ -2625,11 +2756,22 @@
$current_length=~/(\d+\.?\d*)/;
push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1;
}
+ }
&Apache::lonxml::startredirection();
return '';
}
sub end_td_tex {
+
+ my $text = &Apache::lonxml::endredirection();
+ my $table = $Apache::londefdef::table[-1];
+ $table->append_cell_text($text);
+
+ #-------------------------------------------------
+ # Old table code
+ #-------------------------------------------------
+
+ if (0) {
my ($parstack,$parser,$safeeval) = @_;
my $current_row = $Apache::londefdef::table[-1]{'row_number'};
my $current_column = $Apache::londefdef::table[-1]{'counter_columns'};
@@ -2794,7 +2936,7 @@
}
-
+ }
return '';
}
@@ -2843,6 +2985,24 @@
sub start_th_tex {
my ($parstack,$parser,$safeeval) = @_;
+
+ my $alignment = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef,1);
+ my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval, undef, 1);
+ my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval, undef, 1);
+
+ my $config = cell_config_hash($alignment, $rowspan, $colspan);
+ my $table = $Apache::londefdef::table[-1];
+ $table->add_cell('\textbf{', $config);
+
+ #-------------------------------------------------------------------------------------
+ #
+ # Old table code.
+ #
+ #--------------------------------------------------------------------------------------
+
+ if (0) {
+
+
my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
if ($alignchar eq '') {
$alignchar = $Apache::londefdef::table[-1]{'rows'}[-1];
@@ -2855,12 +3015,26 @@
$current_length=~/(\d+\.?\d*)/;
push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1;
}
+ }
+
+ # Accept xml until the </th> tag.
+
&Apache::lonxml::startredirection();
return '';
}
sub end_th_tex {
my ($parstack,$parser,$safeeval) = @_;
+
+ my $table = $Apache::londefdef::table[-1];
+ my $text = &Apache::lonxml::endredirection();
+ $table->append_cell_text($text.'}');
+
+ #-----------------------------------------------------------------------------
+ # Old table code:
+ #-----------------------------------------------------------------------------
+
+ if (0) {
my $current_row = $Apache::londefdef::table[-1]{'row_number'};
my $data=&Apache::lonxml::endredirection();
my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
@@ -2925,6 +3099,7 @@
#make data bold
$data='\textbf{'.$data.'}';
push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data;
+ }
return'';
}
Index: loncom/xml/lontable.pm
diff -u loncom/xml/lontable.pm:1.7 loncom/xml/lontable.pm:1.8
--- loncom/xml/lontable.pm:1.7 Mon Dec 29 11:57:37 2008
+++ loncom/xml/lontable.pm Tue Jan 20 12:01:01 2009
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Generating TeX tables.
#
-# $Id: lontable.pm,v 1.7 2008/12/29 11:57:37 foxr Exp $
+# $Id: lontable.pm,v 1.8 2009/01/20 12:01:01 foxr Exp $
#
#
# Copyright Michigan State University Board of Trustees
@@ -56,7 +56,9 @@
package Apache::lontable;
use strict;
use LaTeX::Table;
+use Apache::lonnet; # for trace logging.
+my $tracing = 0; # Set to 1 to enable log tracing. 2 for local sub tracing.
=pod
@@ -135,9 +137,10 @@
=item width
-The width of the table. This can be expressed as fractions of full width, or in any
-TeX unit measure e.g. 0.75 for 75% of the width, or 10.8cm This forces the table to the
-tabularx environment.
+The width of the table. in any
+TeX unit measure e.g. 10.8cm This forces the table to the
+tabularx environment. It also forces the declarations for
+cells to be paragraph mode which supports more internal formatting.
=back
@@ -252,6 +255,8 @@
sub new {
my ($class, $configuration) = @_;
+ if($tracing) {&Apache::lonnet::logthis("new table object");}
+
# Initialize the object member data with the default values
# then override with any stuff in $configuration.
@@ -298,6 +303,8 @@
sub alignment {
my ($self, $new_value) = @_;
+ if ($tracing) {&Apache::lonnet::logthis("alignment = $new_value");}
+
if (defined($new_value)) {
$self->{'alignment'} = $new_value;
}
@@ -323,6 +330,8 @@
sub table_border {
my ($self, $new_value) = @_;
+ if ($tracing) {&Apache::lonnet::logthis("table_border $new_value");}
+
if (defined($new_value)) {
$self->{'outer_border'} = $new_value;
}
@@ -348,7 +357,7 @@
sub cell_border {
my ($self, $new_value) = @_;
-
+ if($tracing) {&Apache::lonnet::logthis("cell_border: $new_value"); }
if (defined($new_value)) {
$self->{'inner_border'} = $new_value;
}
@@ -373,6 +382,7 @@
sub caption {
my ($self, $new_value) = @_;
+ if($tracing) {&Apache::lonnet::logthis("caption: $new_value"); }
if (defined($new_value)) {
$self->{'caption'} = $new_value;
}
@@ -397,7 +407,7 @@
sub theme {
my ($self, $new_value) = @_;
-
+ if($tracing) {&Apache::lonnet::logthis("theme $new_value"); }
if (defined($new_value)) {
$self->{'theme'} = $new_value;
}
@@ -412,12 +422,13 @@
=head 3 Examples:
- $table->width("0.8"); # 80% of the column width.
my $newwidth = $table->width("10cm"); # 10cm width returns "10cm".
=cut
sub width {
my ($self, $new_value) = @_;
+ if($tracing) {&Apache::lonnet::logthis("width = $new_value"); }
+
if (defined($new_value)) {
$self->{'width'} = $new_value;
}
@@ -454,7 +465,7 @@
sub start_row {
my ($self, $config) = @_;
-
+ if($tracing) {&Apache::lonnet::logthis("start_row"); }
if ($self->{'row_open'}) {
$self->end_row();
}
@@ -495,7 +506,7 @@
sub end_row {
my ($self) = @_;
-
+ if($tracing) {&Apache::lonnet::logthis("end_row"); }
if ($self->{'row_open'}) {
# Mostly we need to determine if this row has the maximum
@@ -543,7 +554,7 @@
sub configure_row {
my ($self, $config) = @_;
-
+ if($tracing) {&Apache::lonnet::logthis("configure_row");}
if (!$self->{'row_open'}) {
$self->start_row();
}
@@ -601,6 +612,8 @@
sub add_cell {
my ($self, $text, $config) = @_;
+ if($tracing) {&Apache::lonnet::logthis("add_cell : $text"); }
+
# If a row is not open, we must open it:
if (!$self->{'row_open'}) {
@@ -627,6 +640,9 @@
# end point of the pulled down cell.
my $prior_cell = $last_row->{'cells'}->[$prior_cell_index];
+ if (!defined($prior_cell)) {
+ last;
+ }
if (($prior_cell->{'start_col'} == $last_coord) &&
($prior_cell->{'rowspan'} > 1)) {
@@ -666,8 +682,36 @@
$current_row->{'cell_width'} += $cell->{'colspan'};
push(@$current_cells, $cell);
+
+ if ($tracing) { &Apache::lonnet::logthis("add_cell done"); }
}
+
+=pod
+
+=head2 append_cell_text
+
+Sometimes it's necessary to create/configure the cell and then later add text to it.
+This sub allows text to be appended to the most recently created cell.
+
+=head3 Parameters
+
+The text to add to the cell.
+
+=cut
+sub append_cell_text {
+ my ($this, $text) = @_;
+
+ if($tracing) {&Apache::lonnet::logthis("append_cell_text: $text"); }
+ my $rows = $this->{'rows'};
+ my $current_row = $rows->[-1];
+ my $cells = $current_row->{'cells'};
+ my $current_cell = $cells->[-1];
+ $current_cell->{'contents'} .= $text;
+
+}
+
+
=pod
=head2 generate
@@ -681,21 +725,31 @@
=cut
sub generate {
my ($this) = @_;
+ my $useP = 0;
+ my $colwidth;
+ my $colunits;
+ if($tracing) {&Apache::lonnet::logthis("generate"); }
my $table = LaTeX::Table->new();
+ $table->set_center(0); # loncapa tables don't float.
+ $table->set_environment(0);
+
# Add the caption if supplied.
if ($this->{'caption'} ne "") {
$table->set_caption($this->caption);
}
-
# Set the width if defined:
if (defined ($this->{'width'})) {
- $table->set_width($this->{'width'});
- $table->set_width_environment('tabularx');
+# $table->set_width($this->{'width'});
+# $table->set_width_environment('tabularx');
+ $useP = 1;
+ ($colwidth, $colunits) = split(/ /, $this->{'width'});
+ $colwidth = $colwidth/$this->{'column_count'};
+
}
# Build up the data:
@@ -715,6 +769,7 @@
my $startcol = 1;
my @underlines; # Array of \cline cells if cellborder on.
+
for (my $cell = 0; $cell < $cell_count; $cell++) {
my $contents = $cells->[$cell]->{'contents'};
@@ -732,12 +787,29 @@
# Create the horizontal alignment character:
my $col_align = 'l';
+ my $embeddedAlignStart = "";
+ my $embeddedAlignEnd = "";
+
if ($halign eq 'right') {
$col_align = 'r';
+ $embeddedAlignStart = '\begin{flushright} ';
+ $embeddedAlignEnd = ' \end{flushright}';
}
if ($halign eq 'center') {
$col_align = 'c';
+ $embeddedAlignStart = '\begin{center}';
+ $embeddedAlignEnd = '\end{center}';
}
+
+ # If the width has been specified, turn these into
+ # para mode; and wrap the contents in the start/stop stuff:
+
+ if ($useP) {
+ my $cw = $colwidth * $cells->[$cell]->{'colspan'};
+ $col_align = "p{$cw $colunits}";
+ $contents = $embeddedAlignStart . $contents . $embeddedAlignEnd;
+ }
+
if ($inner_border || ($outer_border && ($cell == 0))) {
$col_align = '|'.$col_align;
}
@@ -749,7 +821,22 @@
my $cspan = $cells->[$cell]->{'colspan'};
my $nextcol = $startcol + $cspan;
- $contents = '\multicolumn{'.$cspan.'}{'.$col_align.'}{'.$contents.'}';
+
+ # If we can avoid the \multicolumn directive that's best as
+ # that makes some things like \parpic invalid in LaTeX which
+ # screws everything up.
+
+ if (($cspan > 1) || !($col_align =~ /l/)) {
+
+ $contents = '\multicolumn{'.$cspan.'}{'.$col_align.'}{'.$contents.'}';
+
+ # A nasty edge case. If there's only one cell, the software will assume
+ # we're in complete control of the row so we need to end the row ourselves.
+
+ if ($cell_count == 1) {
+ $contents .= ' \\\\';
+ }
+ }
if ($inner_border && ($cells->[$cell]->{'rowspan'} == 1)) {
my $lastcol = $nextcol -1;
push(@underlines, "\\cline{$startcol-$lastcol}");
@@ -757,7 +844,6 @@
$startcol = $nextcol;
# Rowspans should take care of themselves.
-
push(@row, $contents);
}
@@ -776,7 +862,11 @@
$coldef .= '|';
}
for (my $i =0; $i < $column_count; $i++) {
- $coldef .= 'l';
+ if ($useP) {
+ $coldef .= "p{$colwidth $colunits}";
+ } else {
+ $coldef .= 'l';
+ }
if ($inner_border ||
($outer_border && ($i == $column_count-1))) {
$coldef .= '|';
@@ -786,6 +876,8 @@
# Return the table:
+ if ($tracing) { &Apache::lonnet::logthis("Leaving generate"); }
+
return $table;
}
@@ -795,11 +887,14 @@
sub get_object_attribute {
my ($self, $attribute) = @_;
+ if ($tracing > 1) { &Apache::lonnet::logthis("get_object_attribute: $attribute"); }
return $self->{$attribute};
}
sub get_row {
my ($self, $row) = @_;
+ if ($tracing > 1) { &Apache::lonnet::logthis("get_row"); }
+
my $rows = $self->{'rows'}; # ref to an array....
return $rows->[$row]; # ref to the row hash for the selected row.
}
--foxr1232452861--