File:  [LON-CAPA] / loncom / xml / lontable.pm
Revision 1.2: download - view: text, annotated - select for diffs
Tue Nov 25 12:27:34 2008 UTC (15 years, 6 months ago) by foxr
Branches: MAIN
CVS tags: HEAD
Bunch o' coding.

    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>