##
##  wml::std::grid - Layout Grid
##  Copyright (c) 1997-2001 Ralf S. Engelschall, All Rights Reserved. 
##

#  The <preserve>/<restore> tags with multiple arguments require WML 2.0.3
#use wml::mod::version
<require 2.0.3 />

#use wml::std::tags

<: 
#   top-level globals
$NGRID     = 0;
$GRIDLEVEL = 0;
:>

#
#   THE GRID CONTAINER TAG
#
<define-tag grid endtag=required>
<preserve layout align valign width padding spacing border
          bgcolor color summary />
<set-var %attributes />
<perl>
{
    $GRIDLEVEL++;

    #  grid globals
    my $ngrid = $NGRID++;
    my $NCELL = 0;
    my %CELL_ATTR = ();
    my %CELL_BODY = ();

    #   import cell specs... 
    my $div;
</perl>\
%body
<perl>
    #   then import attributes to ePerl 
    my $layout  = '<get-var layout />';
    my $align   = '<get-var align />';
    my $valign  = '<get-var valign />';
    my $width   = '<get-var width />';
    my $spacing = '<get-var spacing />';
    my $padding = '<get-var padding />';
    my $border  = '<get-var border />';
    my $bgcolor = '<get-var bgcolor />';
    my $color   = '<get-var color />';
    my $summary = qq|<get-var summary />|;
    my $height;
    #    set defaults for attributes
    $layout  = "1x$NCELL"                  if ($layout  eq '');
    ($xsize, $ysize) = ($layout =~ m|^(\d+)x(\d+)$|);
    $align   = 'l' x $xsize                if ($align   eq '');
    @ALIGNS  = split("", $align);
    $valign  = 't' x $ysize                if ($valign  eq '');
    @VALIGNS = split("", $valign);
    $width   = " width=\"$width\""         if ($width   ne '');
    $spacing = '0'                         if ($spacing eq '');
    $spacing = " cellspacing=\"$spacing\"" if ($spacing ne '');
    $padding = '0'                         if ($padding eq '');
    $padding = " cellpadding=\"$padding\"" if ($padding ne '');
    $border  = '0'                         if ($border  eq '');
    $border  = " border=\"$border\""       if ($border  ne '');
    $bgcolor = " bgcolor=\"$bgcolor\""     if ($bgcolor ne '');
    $summary = " summary=\"$summary\""     if ($summary ne '');

    #   some more setups
    my $pad = '    ' x ($GRIDLEVEL-1);
    my $globalcolor = $color;
    my %ALIGNTEXT = ( 'l' => 'left', 'c' => 'center', 'r' => 'right',
                      't' => 'top',  'm' => 'middle', 'b' => 'bottom' );

    #   create table container
    <perl:print>\
       $pad<table*$width$border$spacing$padding$bgcolor$summary>
</perl:print>

    #   create cell entries
    my %SPAN = ();
    my $n = 0;
    my ($y, $x, $body, $attr, $i);
    for ($y = 0; $y < $ysize; $y++) {
        #   start of a row
        <perl:print>$pad  <tr*>
</perl:print>

        #   create cells in a row
        for ($x = 0; $x < $xsize; $x++) {

            #   skip current grid position if spanning is active
            next if ($SPAN{$y*$xsize+$x});

            #   get the next cell info
            $body = $CELL_BODY{$n};
            $attr = $CELL_ATTR{$n};
            ($align, $valign, $bgcolor, $color, $rowspan, $colspan, $width, $height) = split(':', $attr);

            #   remember row spanning (current one can be ignored)
            if ($rowspan ne '') {
                for ($i = 1; $i < $rowspan; $i++) {
                    $SPAN{$y*$xsize+$x + $xsize*$i} = 1;
                }
            }
            #   remember column spanning (current one can be ignored)
            if ($colspan ne '') {
                for ($i = 1; $i < $colspan; $i++) {
                    $SPAN{$y*$xsize+$x + $i} = 1;
                }
            }

            #   complete the info
            $align   = "$ALIGNTEXT{$ALIGNS[$x]}"  if ($align eq '');
            $align   = " align=\"$align\"";
            $valign  = "$ALIGNTEXT{$VALIGNS[$y]}" if ($valign eq '');
            $valign  = " valign=\"$valign\"";
            $bgcolor = " bgcolor=\"$bgcolor\""    if ($bgcolor ne '');
            $color   = $globalcolor if ($globalcolor ne '' and $color eq '');
            $body    = "<"."font color=\"$color\">".$body."<*/font>" if ($color ne '');
            $rowspan = " rowspan=\"$rowspan\""    if ($rowspan ne '');
            $colspan = " colspan=\"$colspan\""    if ($colspan ne '');
            $width   = " width=\"$width\""        if ($width ne '');
            $height  = " height=\"$height\""      if ($height ne '');

            #   insert cell
            <perl:print>\
               $pad    <td$align$valign$bgcolor$rowspan$colspan$width$height>\
               $body</td>
</perl:print>

            #   increase cell counter
            $n++;
        }

        #   end of a row
        <perl:print>$pad  </tr*>
</perl:print>
    }

    #   end of the table
    <perl:print>$pad</table*>
</perl:print>

    $GRIDLEVEL--;
}
</perl>\
<restore  layout align valign width padding spacing border
          bgcolor color summary />
</define-tag>

#
#   THE CELL ELEMENT TAG
#
<define-tag cell endtag=required>
<preserve align valign bgcolor color rowspan colspan width height />
<set-var %attributes />
<perl>
    #   set the information for the surrounding grid container
    $div = "GRID${ngrid}_CELL${NCELL}";
    $CELL_BODY{$NCELL} = "{#${div}#}";
    $CELL_ATTR{$NCELL} = '<get-var align />:<get-var valign />:<get-var bgcolor />:<get-var color />:<get-var rowspan />:<get-var colspan />:<get-var width />:<get-var height />';
    $NCELL++;

    #   now finally inline the body via divertions
    #   (we could put the body tag directly above
    #   but then this will limit the usage dramatically!)
    <perl:print>{#${div}#:</perl:print>
</perl>\
%body\
<perl>
    <perl:print>:#${div}#}</perl:print>
</perl>\
<restore  align valign bgcolor color rowspan colspan width height />
</define-tag>

##EOF##
__END__

=head1 NAME

wml::std::grid - Layout Grid

=head1 SYNOPSIS

 #use wml::std::grid

 <grid [attributes]>
   <cell [attributes]>...</cell>
     :
   <cell [attributes]>...</cell>
 </grid>

=head1 DESCRIPTION

The C<E<lt>gridE<gt>> container tag provides a mixture between a HTML table
and a TeX-like way of specifying its dimensions and the alignment of its
cells. 

=head1 ATTRIBUTES

First the possible attributes for C<E<lt>gridE<gt>>:

=over 4

=item C<summary>

This attribute will be inserted into the C<table> tag, see documentation
of HTML 4.0 for details on why this attribute is recommended.

=item C<layout>

This specifies the layout of the grid in X and Y dimension, i.e.  C<3x2> means
3 columns (x-dimension) and 2 rows (y-dimension). Default is C<1x>I<NCELL>
where I<NCELL> is the number of B<cell> tags or in other words: Default is a
top-down list.

=item C<align>

This specifies the horizontal alignment of the cells in a row. The argument
has to contain as many characters as there are cells in a row. The supported
alignment characters are `C<l>' (left), `C<r>' (right) and `C<c>' (center).
Default is `C<l...l>' (as much C<l>'s as there are cells in a row).

=item C<valign>

This specifies the vertical alignment of the cells in a column. The argument
has to contain as many characters as there are cells in a column.  The
supported alignment characters are `C<t>' (top), `C<b>' (bottom) and `C<m>'
(middle). Default is `C<t...t>' (as much C<t>'s as there are cells in a
column).

=item C<width>

This is the corresponding attribute of the HTML C<E<lt>tableE<gt>> tag. Use it
to set the width of the grid. Default is no specified width.

=item C<spacing>

This is the corresponding attribute to C<cellspacing> of the HTML
C<E<lt>tableE<gt>> tag. Use it to set the spacing of cells in the grid, i.e.
the space around the content of each cell. Default is 0 (no space).

=item C<padding>

This is the corresponding attribute to C<E<lt>cellpaddingE<gt>> of the HTML
C<E<lt>tableE<gt>> tag. Use it to set the padding between cells in the grid,
i.e.  the inter-cell space. Default is 0 (no space).

=item C<border>

This is the corresponding attribute of the HTML C<E<lt>tableE<gt>> tag. Use it
to set the border width of the grid. Default is 0 (no border).

=item C<bgcolor>

This is the corresponding attribute of the HTML C<E<lt>tableE<gt>> tag. Use it
to set the background color of the grid. Default is no specified color.

=item C<color>

This sets the foreground (text) color of the grid's contents. Actually this
sets the default for the same attribute of C<E<lt>cellE<gt>>. Default is no
specified color. 

=back

Second the possible attributes for C<E<lt>cellE<gt>>:

=over 4

=item C<align>

This is the corresponding attribute of the HTML C<E<lt>tdE<gt>> tag. Use it to
set the horizontal alignment of the cell's contents. Default is taken from the
same attribute of C<E<lt>gridE<gt>>.

=item C<valign>

This is the corresponding attribute of the HTML C<E<lt>tdE<gt>> tag. Use it to
set the vertical alignment of the cell's contents. Default is taken from the
same attribute of C<E<lt>gridE<gt>>.

=item C<bgcolor>

This is the corresponding attribute of the HTML C<E<lt>tdE<gt>> tag. Use it to
set the background color of a particular cell. Default is no specified color.

=item C<color>

This sets the foreground (text) color of the cell's contents.  This is done
via the HTML C<E<lt>fontE<gt>> tag.  Default is no specified color or the
color from the same attribute of C<E<lt>gridE<gt>>.

=item C<rowspan>

This is the corresponding attribute of the HTML C<E<lt>tdE<gt>> tag. Use it to
span a cell over more then one row of the grid. Default is 1 row.

=item C<colspan>

This is the corresponding attribute of the HTML C<E<lt>tdE<gt>> tag. Use it to
span a cell over more then one column of the grid. Default is 1 column.

=item C<width>

This is the corresponding attribute of the HTML C<E<lt>tdE<gt>> tag. Use it to
set the width of the cell. Default is no specified width.

=item C<height>

This is the corresponding attribute of the HTML C<E<lt>tdE<gt>> tag. Use it to
set the height of the cell. Default is no specified height.

=back

=head1 EXAMPLE

  <grid bgcolor="#000000" color="#ffffff" 
        layout="3x2" align="llr" valign="tm">
    <cell>A</cell> <cell>B</cell> <cell>C</cell>
    <cell>D</cell> <cell>E</cell> <cell>F</cell>
  </grid>

=head1 AUTHOR

 Ralf S. Engelschall
 rse@engelschall.com
 www.engelschall.com

=head1 REQUIRES

 Internal: P1, P2, P3, P5
 External: --

=head1 SEEALSO

HTML E<lt>C<table>E<gt>-tag.

=cut

