#  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, 2009-2012 -- leonerd@leonerd.org.uk

package Tickit::Widget::Static;

use strict;
use warnings;
use base qw( Tickit::Widget );

use Tickit::WidgetRole::Alignable name => 'align',  dir => 'h';
use Tickit::WidgetRole::Alignable name => 'valign', dir => 'v';

our $VERSION = '0.21';

use List::Util qw( max );
use Tickit::Utils qw( textwidth substrwidth );

=head1 NAME

C<Tickit::Widget::Static> - a widget displaying static text

=head1 SYNOPSIS

 use Tickit;
 use Tickit::Widget::Static;
 
 my $tickit = Tickit->new;
 
 my $hello = Tickit::Widget::Static->new(
    text   => "Hello, world",
    align  => "centre",
    valign => "middle",
 );
 
 $tickit->set_root_widget( $hello );
 
 $tickit->run;

=head1 DESCRIPTION

This class provides a widget which displays a single piece of static text. The
text may contain more than one line, separated by linefeed (C<\n>) characters.
No other control sequences are allowed in the string.

=cut

=head1 CONSTRUCTOR

=cut

=head2 $static = Tickit::Widget::Static->new( %args )

Constructs a new C<Tickit::Widget::Static> object.

Takes the following named arguments in addition to those taken by the base
L<Tickit::Widget> constructor:

=over 8

=item text => STRING

The text to display

=item align => FLOAT|STRING

Optional. Defaults to C<0.0> if unspecified.

=item valign => FLOAT|STRING

Optional. Defaults to C<0.0> if unspecified.

=back

For more details see the accessors below.

=cut

sub new
{
   my $class = shift;
   my %args = @_;

   my $self = $class->SUPER::new( %args );

   $self->set_text( $args{text} );
   $self->set_align( $args{align} || 0 );
   $self->set_valign( $args{valign} || 0 );

   return $self;
}

=head1 ACCESSORS

=cut

sub lines
{
   my $self = shift;
   return scalar @{ $self->{lines} };
}

sub cols
{
   my $self = shift;
   return max map { textwidth $_ } @{ $self->{lines} }
}

=head2 $text = $static->text

=cut

sub text
{
   my $self = shift;
   return join "\n", @{ $self->{lines} };
}

=head2 $static->set_text( $text )

Accessor for C<text> property; the actual text on display in the widget

=cut

sub set_text
{
   my $self = shift;
   my ( $text ) = @_;
   my @lines = split m/\n/, $text;
   # split on empty string returns empty list
   @lines = ( "" ) if !@lines;
   $self->{lines} = \@lines;
   $self->resized;
   $self->redraw;
}

=head2 $align = $static->align

=head2 $static->set_align( $align )

Accessor for horizontal alignment value.

Gives a value in the range from C<0.0> to C<1.0> to align the text display
within the window. If the window is larger than the width of the text, it will
be aligned according to this value; with C<0.0> on the left, C<1.0> on the
right, and other values inbetween.

See also L<Tickit::WidgetRole::Alignable>.

=cut

use constant CLEAR_BEFORE_RENDER => 0;

sub render
{
   my $self = shift;
   my %args = @_;

   my $win = $self->window;
   $win->is_visible or return;
   my $rect = $args{rect};

   my $cols = $win->cols;

   my ( $above, $lines ) = $self->_valign_allocation( $self->lines, $win->lines );

   $win->goto( $_, 0 ), $win->erasech( $cols ) for $rect->top .. $above - 1;

   foreach my $line ( 0 .. $lines - 1 ) {
      my $text = $self->{lines}[$line];

      my ( $left, $textwidth, $right ) = $self->_align_allocation( textwidth( $text ), $cols );

      $win->goto( $above + $line, 0 );
      $win->erasech( $left, 1 ) if $left;
      $win->print( substrwidth $text, 0, $textwidth );
      $win->erasech( $right ) if $right;
   }

   $win->goto( $_, 0 ), $win->erasech( $cols ) for $above + $lines .. $rect->bottom - 1;
}

=head1 AUTHOR

Paul Evans <leonerd@leonerd.org.uk>

=cut

0x55AA;