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 )