0
  	  0  0  li~R( *ۍ-F__ub&=LV[( 1   #============================================================= -*-Perl-*-
#
# Template::Plugin::Table
#
# DESCRIPTION
#   Plugin to order a linear data set into a virtual 2-dimensional table
#   from which row and column permutations can be fetched.
#
# AUTHOR
#   Andy Wardley   <abw@wardley.org>
#
# COPYRIGHT
#   Copyright (C) 2000-2007 Andy Wardley.  All Rights Reserved.
#
#   This module is free software; you can redistribute it and/or
#   modify it under the same terms as Perl itself.
#
#============================================================================

package Template::Plugin::Table;

use strict;
use warnings;
use base 'Template::Plugin';
use Scalar::Util 'blessed';

our $VERSION = 2.71;
our $AUTOLOAD;


#------------------------------------------------------------------------
# new($context, \@data, \%args)
#
# This constructor method initialises the object to iterate through
# the data set passed by reference to a list as the first parameter.
# It calculates the shape of the permutation table based on the ROWS
# or COLS parameters specified in the $args hash reference.  The
# OVERLAP parameter may be provided to specify the number of common
# items that should be shared between subseqent columns.
#------------------------------------------------------------------------

sub new {
    my ($class, $context, $data, $params) = @_;
    my ($size, $rows, $cols, $coloff, $overlap, $error);

    # if the data item is a reference to a Template::Iterator object,
    # or subclass thereof, we call its get_all() method to extract all
    # the data it contains
    if (blessed($data) && $data->isa('Template::Iterator')) {
        ($data, $error) = $data->get_all();
        return $class->error("iterator failed to provide data for table: ",
                             $error)
            if $error;
    }
        
    return $class->error('invalid table data, expecting a list')
        unless ref $data eq 'ARRAY';

    $params ||= { };
    return $class->error('invalid table parameters, expecting a hash')
        unless ref $params eq 'HASH';

    # ensure keys are folded to upper case
    @$params{ map { uc } keys %$params } = values %$params;

    $size = scalar @$data;
    $overlap = $params->{ OVERLAP } || 0;

    # calculate number of columns based on a specified number of rows
    if ($rows = $params->{ ROWS }) {
        if ($size < $rows) {
            $rows = $size;   # pad?
            $cols = 1;
            $coloff = 0;
        }
        else {
            $coloff = $rows - $overlap;
            $cols = int ($size / $coloff) 
                + ($size % $coloff > $overlap ? 1 : 0)
            }
    }
    # calculate number of rows based on a specified number of columns
    elsif ($cols = $params->{ COLS }) {
        if ($size < $cols) {
            $cols = $size;
            $rows = 1;
            $coloff = 1;
        }
        else {
            $coloff = int ($size / $cols) 
                + ($size % $cols > $overlap ? 1 : 0);
            $rows = $coloff + $overlap;
        }
    }
    else {
        $rows = $size;
        $cols = 1;
        $coloff = 0;
    }
    
    bless {
        _DATA    => $data,
        _SIZE    => $size,
        _NROWS   => $rows,
        _NCOLS   => $cols,
        _COLOFF  => $coloff,
        _OVERLAP => $overlap,
        _PAD     => defined $params->{ PAD } ? $params->{ PAD } : 1,
    }, $class;
}


#------------------------------------------------------------------------
# row($n)
#
# Returns a reference to a list containing the items in the row whose 
# number is specified by parameter.  If the row number is undefined,
# it calls rows() to return a list of all rows.
#------------------------------------------------------------------------

sub row {
    my ($self, $row) = @_;
    my ($data, $cols, $offset, $size, $pad) 
        = @$self{ qw( _DATA _NCOLS _COLOFF _SIZE _PAD) };
    my @set;

    # return all rows if row number not specified
    return $self->rows()
        unless defined $ro