1 package SL::Template::Plugin::MultiColumnIterator;
 
   4 use base 'Template::Plugin';
 
   5 use Template::Constants;
 
   6 use Template::Exception;
 
   7 use Template::Iterator;
 
  14     $main::lxdebug->enter_sub(); 
 
  17     my $data    = shift || [ ];
 
  23     push @ISA, "Template::Iterator";
 
  25     if (ref $data eq 'HASH') {
 
  26         # map a hash into a list of { key => ???, value => ??? } hashes,
 
  27         # one for each key, sorted by keys
 
  28         $data = [ map { { key => $_, value => $data->{ $_ } } }
 
  31     elsif (UNIVERSAL::can($data, 'as_list')) {
 
  32         $data = $data->as_list();
 
  34     elsif (ref $data ne 'ARRAY') {
 
  35         # coerce any non-list data into an array reference
 
  39     $main::lxdebug->leave_sub(); 
 
  50     $main::lxdebug->enter_sub(); 
 
  52     my $data  = $self->{ _DATA };
 
  53     my $dim   = $self->{ _DIM  };
 
  55     $self->{ _DATASET } = $self->{ _DATA };
 
  56     my $size = int ((scalar @$data - 1) / $dim) + 1;
 
  59     return (undef, Template::Constants::STATUS_DONE) unless $size;
 
  61     # initialise various counters, flags, etc.
 
  62     @$self{ qw( SIZE MAX INDEX COUNT FIRST LAST ) } = ( $size, $size - 1, $index, 1, 1, $size > 1 ? 0 : 1, undef );
 
  63     @$self{ qw( PREV ) } = ( undef );
 
  64     $$self{ qw( NEXT ) } = [ @{ $self->{ _DATASET }  }[ map { $index + 1 + $_ * $size } 0 .. ($dim - 1) ] ];
 
  66     $main::lxdebug->leave_sub(); 
 
  67     return [ @{ $self->{ _DATASET } }[ map { $index + $_ * $size } 0 .. ($dim - 1) ] ];
 
  71     $main::lxdebug->enter_sub(); 
 
  73     my ($max, $index) = @$self{ qw( MAX INDEX ) };
 
  74     my $data = $self->{ _DATASET };
 
  75     my $dim  = $self->{ _DIM  };
 
  76     my $size = $self->{ SIZE  };
 
  78     # warn about incorrect usage
 
  79     unless (defined $index) {
 
  80         my ($pack, $file, $line) = caller();
 
  81         warn("iterator get_next() called before get_first() at $file line $line\n");
 
  82         return (undef, Template::Constants::STATUS_DONE);   ## RETURN ##
 
  85     # if there's still some data to go...
 
  87         # update counters and flags
 
  89         @$self{ qw( INDEX COUNT FIRST LAST ) } = ( $index, $index + 1, 0, $index == $max ? 1 : 0 );
 
  90         $$self{ qw( PREV ) } = [ @{ $self->{ _DATASET } }[ map { $index - 1 + $_ * $size } 0 .. ($dim - 1) ] ];
 
  91         $$self{ qw( NEXT ) } = [ @{ $self->{ _DATASET } }[ map { $index + 1 + $_ * $size } 0 .. ($dim - 1) ] ];
 
  92         $main::lxdebug->leave_sub(); 
 
  93         return [ @{ $self->{ _DATASET } }[ map { $index + $_ * $size } 0 .. ($dim - 1) ] ];
 
  96         $main::lxdebug->leave_sub(); 
 
  97         return (undef, Template::Constants::STATUS_DONE);   ## RETURN ##
 
 103     my ($max, $index, $dim, $size) = @$self{ qw( MAX INDEX _DIM SIZE) };
 
 106     # if there's still some data to go...
 
 109         @data = map do{ !($i = $_) || +[ @{ $self->{ _DATASET } }[ map { $i + $_ * $size } 0 .. ($dim - 1) ] ] }, $index .. $max;
 
 110         # update counters and flags
 
 111         @$self{ qw( INDEX COUNT FIRST LAST ) } = ( $max, $max + 1, 0, 1 );
 
 112         $main::lxdebug->leave_sub();
 
 113         return \@data;                                      ## RETURN ##
 
 116         $main::lxdebug->leave_sub();
 
 117         return (undef, Template::Constants::STATUS_DONE);   ## RETURN ##
 
 123     my $item = $AUTOLOAD;
 
 125     return if $item eq 'DESTROY';
 
 127     # alias NUMBER to COUNT for backwards compatability
 
 128     $item = 'COUNT' if $item =~ /NUMBER/i;
 
 130     return $self->{ uc $item };
 
 134     $main::lxdebug->enter_sub(); 
 
 136     $main::lxdebug->leave_sub(); 
 
 139          "  Data: ", Dumper($self->{ _DATA  }), "\n",
 
 140          " Index: ", $self->{ INDEX  }, "\n",
 
 141          "Number: ", $self->{ NUMBER }, "\n",
 
 142          "   Max: ", $self->{ MAX    }, "\n",
 
 143          "  Size: ", $self->{ SIZE   }, "\n",
 
 144          " First: ", $self->{ FIRST  }, "\n",
 
 145          "  Last: ", $self->{ LAST   }, "\n",
 
 152   $main::lxdebug->enter_sub(); 
 
 154   $main::lxdebug->leave_sub(); 
 
 155   return $self->{ INDEX };
 
 159   $main::lxdebug->enter_sub(); 
 
 161   $main::lxdebug->leave_sub(); 
 
 162   return $self->{ NUMBER };
 
 166   $main::lxdebug->enter_sub(); 
 
 168   $main::lxdebug->leave_sub(); 
 
 169   return $self->{ COUNT };
 
 172   $main::lxdebug->enter_sub(); 
 
 174   $main::lxdebug->leave_sub(); 
 
 175   return $self->{ MAX };
 
 179   $main::lxdebug->enter_sub(); 
 
 181   $main::lxdebug->leave_sub(); 
 
 182   return $self->{ SIZE };
 
 186   $main::lxdebug->enter_sub(); 
 
 188   $main::lxdebug->leave_sub(); 
 
 189   return $self->{ FIRST };
 
 193   $main::lxdebug->enter_sub(); 
 
 195   $main::lxdebug->leave_sub(); 
 
 196   return $self->{ LAST};