# You may distribute under the terms of either the GNU General Public License
# or the Artistic License (the same terms as Perl itself)
#
# (C) Paul Evans, 2011 -- leonerd@leonerd.org.uk
package Tickit::Rect;
use strict;
use List::Util qw( min max );
our $VERSION = '0.11';
=head1 NAME
C<Tickit::Rect> - a lightweight data structure representing a rectangle
=head1 SYNOPSIS
use Tickit::Rect;
my $rect = Tickit::Rect->new(
top => 0, left => 5, lines => 3, cols => 10
);
=head1 DESCRIPTION
Objects in this class represent a rectangle, by storing the top left corner
coordinate and the size in lines and columns. This data structure is purely
abstract and not tied to a particular window or coordinate system. It exists
simply as a convenient data store containing some useful utility methods.
=cut
=head1 CONSTRUCTORS
=cut
=head2 $rect = Tickit::Rect->new( %args )
Construct a new rectangle of the given geometry, given by C<top>, C<left> and
either C<lines> and C<cols>, or C<bottom> and C<right>.
=cut
sub new
{
my $class = shift;
my %args = @_;
defined $args{lines} or $args{lines} = $args{bottom} - $args{top};
defined $args{cols} or $args{cols} = $args{right} - $args{left};
my $self = bless [ @args{qw( top left lines cols )} ], $class;
}
=head2 $rect = $existing_rect->intersect( $other_rect )
If there is an intersection between the given rectangles, return it. If not,
return C<undef>.
=cut
sub intersect
{
my $self = shift;
my ( $other ) = @_;
my $top = max $self->top, $other->top;
my $bottom = min $self->bottom, $other->bottom;
return undef if $top >= $bottom;
my $left = max $self->left, $other->left;
my $right = min $self->right, $other->right;
return undef if $left >= $right;
return (ref $self)->new( top => $top, left => $left, bottom => $bottom, right => $right );
}
=head2 $rect = $existing_rect->translate( $rightward, $downward )
Returns a new rectangle of the same size as the given one, moved right and
down by the given argmuents (which may be negative)
=cut
sub translate
{
my $self = shift;
my ( $leftward, $downward ) = @_;
return (ref $self)->new(
top => $self->top + $downward,
left => $self->left + $leftward,
lines => $self->lines,
cols => $self->cols,
);
}
=head1 ACCESSORS
=cut
=head2 $top = $rect->top
=head2 $left = $rect->left
=head2 $bottom = $rect->bottom
=head2 $right = $rect->right
Return the edge boundaries of the rectangle.
=head2 $lines = $rect->lines
=head2 $cols = $rect->cols
Return the size of the rectangle.
=cut
sub top { $_[0]->[0] }
sub left { $_[0]->[1] }
sub lines { $_[0]->[2] }
sub cols { $_[0]->[3] }
sub bottom { $_[0]->[0] + $_[0]->[2] }
sub right { $_[0]->[1] + $_[0]->[3] }
use overload '""' => sub {
my $self = shift;
sprintf "Tickit::Rect[(%d,%d)..(%d,%d)]", $self->left, $self->top, $self->right, $self->bottom;
};
=head1 AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
=cut
0x55AA;