File Coverage

blib/lib/Tickit/Widget/Spinner.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2013 -- leonerd@leonerd.org.uk
5              
6             package Tickit::Widget::Spinner;
7              
8 1     1   797 use strict;
  1         1  
  1         22  
9 1     1   2 use warnings;
  1         2  
  1         20  
10 1     1   3 use base qw( Tickit::Widget );
  1         1  
  1         54  
11              
12             use Tickit::Style;
13              
14             our $VERSION = '0.25';
15              
16             use List::Util qw( max );
17             use Tickit::Utils qw( textwidth );
18              
19             =head1 NAME
20              
21             C - a widget displaying a small text animation
22              
23             =head1 SYNOPSIS
24              
25             use Tickit;
26             use Tickit::Widget::Spinner;
27              
28             my $spinner = Tickit::Widget::Spinner->new(
29             chars => [ " ", " ", " ", "> <" ],
30             );
31              
32             Tickit->new( root => $spinner )->run;
33              
34             =head1 DESCRIPTION
35              
36             This class provides a widget which displays a simple animation, cycling
37             through a fixed set of strings with a fixed interval.
38              
39             =head1 STYLE
40              
41             The default style pen is used as the widget pen.
42              
43             =cut
44              
45             use constant WIDGET_PEN_FROM_STYLE => 1;
46              
47             =head1 CONSTRUCTOR
48              
49             =cut
50              
51             =head2 $spinner = Tickit::Widget::Spinner->new( %args )
52              
53             Constructs a new C object.
54              
55             Takes the following named arguments:
56              
57             =over 8
58              
59             =item chars => ARRAY
60              
61             Optional. An ARRAY reference containing the text strings to use.
62              
63             =item interval => NUM
64              
65             Optional. The time each string is displayed for. Defaults to 0.5.
66              
67             =back
68              
69             =cut
70              
71             sub new
72             {
73             my $class = shift;
74             my %params = @_;
75              
76             my $self = $class->SUPER::new( %params );
77              
78             $self->{chars} = $params{chars} || [qw( - \ | / )];
79             $self->{state} = 0;
80              
81             $self->{interval} = $params{interval} // 0.5;
82              
83             $self->{cols} = max map { textwidth $_ } @{ $self->{chars} };
84              
85             return $self;
86             }
87              
88             =head1 METHODS
89              
90             =cut
91              
92             sub lines
93             {
94             return 1;
95             }
96              
97             sub cols
98             {
99             my $self = shift;
100             return $self->{cols};
101             }
102              
103             =head2 $spinner->start
104              
105             Starts the animation effect.
106              
107             =cut
108              
109             sub start
110             {
111             my $self = shift;
112             return if $self->{running};
113             $self->{running} = 1;
114             $self->tick;
115             }
116              
117             =head2 $spinner->stop
118              
119             Stops the animation effect.
120              
121             =cut
122              
123             sub stop
124             {
125             my $self = shift;
126             $self->{running} = 0;
127             }
128              
129             sub window_gained
130             {
131             my $self = shift;
132             $self->SUPER::window_gained( @_ );
133             $self->start;
134             }
135              
136             # precache position
137             sub reshape
138             {
139             my $self = shift;
140              
141             my $win = $self->window or return;
142              
143             @{$self}{qw( x y )} = map int($_ / 2), $win->cols - $self->cols, $win->lines - $self->lines;
144              
145             $self->{rect} = Tickit::Rect->new(
146             top => $self->{y},
147             left => $self->{x},
148             lines => $self->lines,
149             cols => $self->cols,
150             );
151             }
152              
153             sub tick
154             {
155             my $self = shift;
156             return unless $self->{running};
157              
158             my $state = $self->{state}++;
159             $self->{state} %= @{ $self->{chars} };
160              
161             if( my $win = $self->window ) {
162             $win->tickit->timer( after => $self->{interval} => sub { $self->tick } );
163             $win->expose( $self->{rect} );
164             }
165             }
166              
167             sub render_to_rb
168             {
169             my $self = shift;
170             my ( $rb, $rect ) = @_;
171              
172             my $chars = $self->{chars};
173             my $state = $self->{state};
174              
175             $rb->eraserect( $rect );
176              
177             $rb->text_at( $self->{y}, $self->{x}, $chars->[$state] );
178             }
179              
180             =head1 AUTHOR
181              
182             Paul Evans
183              
184             =cut
185              
186             0x55AA;