Alt-Tickit-Widgets-ObjectPad

 view release on metacpan or  search on metacpan

lib/Tickit/Widget/GridBox.pm  view on Meta::CPAN

         my $r = $_;
         max map {
            my $c = $_;
            my $child = $_grid[$r][$c];
            $child ? $child->requested_lines : 0;
         } 0 .. $_max_col
      } 0 .. $max_row ) ) +
      $row_spacing * $max_row;
}

method cols
{
   my $col_spacing = $self->get_style_values( "col_spacing" );
   my $max_row = $#_grid;
   return ( sum( map {
         my $c = $_;
         max map {
            my $r = $_;
            my $child = $_grid[$r][$c];
            $child ? $child->requested_cols : 0;
         } 0 .. $max_row
      } 0 .. $_max_col ) ) +
      $col_spacing * $_max_col;
}

method children
{
   map {
      my $r = $_;
      map {
         $_grid[$r][$_] ? ( $_grid[$r][$_] ) : ()
      } 0 .. $_max_col
   } 0.. $#_grid;
}

=head1 METHODS

=cut

=head2 $count = $gridbox->rowcount

=head2 $count = $gridbox->colcount

Returns the number of rows or columns in the grid.

=cut

method rowcount
{
   return scalar @_grid;
}

method colcount
{
   return $_max_col + 1;
}

=head2 $gridbox->add( $row, $col, $child, %opts )

Sets the child widget to display in the given grid cell. Cells do not need to
be explicitly constructed; the grid will automatically expand to the size
required. This method can also be used to replace an existing child at the
given cell location. To remove a cell entirely, use the C<remove> method.

The following options are recognised:

=over 8

=item col_expand => INT

=item row_expand => INT

Values for the C<expand> setting for this column or row of the table. The
largest C<expand> setting for any cell in a given column or row sets the value
used to distribute space to that column or row.

=back

=cut

method add
{
   my ( $row, $col, $child, %opts ) = @_;

   if( my $old_child = $_grid[$row][$col] ) {
      $self->SUPER::remove( $old_child );
   }

   $_max_col = $col if $col > $_max_col;

   $_grid[$row][$col] = $child;
   $self->SUPER::add( $child,
      col_expand => $opts{col_expand} || 0,
      row_expand => $opts{row_expand} || 0,
   );
}

=head2 $gridbox->remove( $row, $col )

Removes the child widget on display in the given cell. May shrink the grid if
this was the last child widget in the given row or column.

=cut

method remove
{
   my ( $row, $col ) = @_;

   my $child = $_grid[$row][$col];
   undef $_grid[$row][$col];

   # Tidy up the row
   my $max_col = 0;
   foreach my $col ( reverse 0 .. $#{ $_grid[$row] } ) {
      next if !defined $_grid[$row][$col];

      $max_col = $col+1;
      last;
   }

   splice @{ $_grid[$row] }, $max_col;

   # Tidy up the grid
   my $max_row = 0;
   foreach my $row ( reverse 0 .. $#_grid ) {
      next if !defined $_grid[$row] or !@{ $_grid[$row] };

      $max_row = $row+1;
      last;
   }

   splice @_grid, $max_row;

   $_max_col = max map { $_ ? $#$_ : 0 } @_grid;

   my $childrect = $child->window ? $child->window->rect : undef;

   $self->SUPER::remove( $child );

   $self->window->expose( $childrect ) if $childrect;
}

=head2 $child = $gridbox->get( $row, $col )

Returns the child widget at the given cell in the grid. If the row or column
index are beyond the bounds of the grid, or if there is no widget in the given
cell, returns C<undef>.

=cut

method get
{
   my ( $row, $col ) = @_;

lib/Tickit/Widget/GridBox.pm  view on Meta::CPAN


Shortcut to inserting a new column after the end of the current grid.

=cut

method append_col
{
   $self->insert_col( $self->colcount, @_ );
}

=head2 $gridbox->delete_row( $row )

Deletes a row of the grid by moving the existing rows after it higher up.

=cut

method delete_row
{
   my ( $row ) = @_;

   $self->remove( $row, $_ ) for 0 .. $self->colcount - 1;

   splice @_grid, $row, 1, ();
   $self->children_changed;
}

=head2 $gridbox->delete_col( $col )

Deletes a column of the grid by moving the existing columns after it to the
left.

=cut

method delete_col
{
   my ( $col ) = @_;

   $self->remove( $_, $col ) for 0 .. $self->rowcount - 1;

   splice @{ $_grid[$_] }, $col, 1, () for 0 .. $self->rowcount - 1;
   $_max_col--;
   $self->children_changed;
}

method reshape
{
   my $win = $self->window or return;

   my @row_buckets;
   my @col_buckets;

   my $max_row = $self->rowcount - 1;
   my $max_col = $self->colcount - 1;

   my ( $row_spacing, $col_spacing ) = $self->get_style_values(qw( row_spacing col_spacing ));

   foreach my $row ( 0 .. $max_row ) {
      push @row_buckets, { fixed => $row_spacing } if @row_buckets;

      my $base = 0;
      my $expand = 0;

      foreach my $col ( 0 .. $max_col ) {
         my $child = $_grid[$row][$col] or next;

         $base   = max $base, $child->requested_lines;
         $expand = max $expand, $self->child_opts( $child )->{row_expand};
      }

      push @row_buckets, {
         row    => $row,
         base   => $base,
         expand => $expand,
      };
   }

   foreach my $col ( 0 .. $max_col ) {
      push @col_buckets, { fixed => $col_spacing } if @col_buckets;

      my $base = 0;
      my $expand = 0;

      foreach my $row ( 0 .. $max_row ) {
         my $child = $_grid[$row][$col] or next;

         $base   = max $base, $child->requested_cols;
         $expand = max $expand, $self->child_opts( $child )->{col_expand};
      }

      push @col_buckets, {
         col    => $col,
         base   => $base,
         expand => $expand,
      };
   }

   distribute( $win->lines, @row_buckets );
   distribute( $win->cols,  @col_buckets );

   my @rows;
   foreach ( @row_buckets ) {
      $rows[$_->{row}] = [ $_->{start}, $_->{value} ] if defined $_->{row};
   }

   my @cols;
   foreach ( @col_buckets ) {
      $cols[$_->{col}] = [ $_->{start}, $_->{value} ] if defined $_->{col};
   }

   foreach my $row ( 0 .. $max_row ) {
      foreach my $col ( 0 .. $max_col ) {
         my $child = $_grid[$row][$col] or next;

         # Don't try to use zero-sized rows or cols
         next unless $rows[$row][1] and $cols[$col][1];

         my @geom = ( $rows[$row][0], $cols[$col][0], $rows[$row][1], $cols[$col][1] );

         if( my $childwin = $child->window ) {
            $childwin->change_geometry( @geom );
         }
         else {
            $childwin = $win->make_sub( @geom );
            $child->set_window( $childwin );
         }
      }
   }
}

method render_to_rb
{
   my ( $rb, $rect ) = @_;

   $rb->eraserect( $rect );
}

=head1 TODO

=over 4

=item *

Add C<move_{row,col}> methods for re-ordering existing rows or columns

=item *

Make C<{insert,append,delete,move}> operations more efficient by deferring the
C<children_changed> call until they are done.

=back

=head1 AUTHOR



( run in 0.424 second using v1.01-cache-2.11-cpan-5623c5533a1 )