File Coverage

blib/lib/Circle/WindowItem.pm
Criterion Covered Total %
statement 63 119 52.9
branch 12 34 35.2
condition 3 11 27.2
subroutine 16 23 69.5
pod 0 14 0.0
total 94 201 46.7


line stmt bran cond sub pod time code
1             # You may distribute under the terms of the GNU General Public License
2             #
3             # (C) Paul Evans, 2008-2014 -- leonerd@leonerd.org.uk
4              
5             package Circle::WindowItem;
6              
7             # An abstract role used by objects that should be placed in FE windows or tabs
8             # Combines the behaviours of:
9             # having display events
10             # responding to typed lines of text
11              
12 4     4   29 use strict;
  4         9  
  4         246  
13 4     4   21 use warnings;
  4         7  
  4         91  
14              
15 4     4   24 use Carp;
  4         6  
  4         301  
16              
17 4     4   20 use base qw( Circle::Commandable Circle::Configurable Circle::Loggable );
  4         6  
  4         2633  
18              
19 4     4   2625 use Circle::TaggedString;
  4         13  
  4         136  
20              
21 4     4   2620 use Circle::Widget::Box;
  4         11  
  4         125  
22 4     4   2052 use Circle::Widget::Scroller;
  4         12  
  4         3305  
23              
24             sub init_prop_level
25             {
26 5     5 0 1161 return 0;
27             }
28              
29             sub bump_level
30             {
31 3     3 0 15 my $self = shift;
32 3         11 my ( $newlevel ) = @_;
33              
34 3 100       49 return if $self->get_prop_level >= $newlevel;
35              
36 2         40 $self->set_prop_level( $newlevel );
37             }
38              
39             sub method_reset_level
40             {
41 0     0 0 0 my $self = shift;
42              
43 0         0 $self->set_prop_level( 0 );
44             }
45              
46             sub push_displayevent
47             {
48 8     8 0 20 my $self = shift;
49 8         30 my ( $event, $args, %opts ) = @_;
50              
51 8         37 foreach ( values %$args ) {
52 8 100       39 if( !ref $_ ) {
    50          
53 5         17 next;
54             }
55 3         36 elsif( eval { $_->isa( "Circle::TaggedString" ) } ) {
56 3         59 $_ = $_->squash;
57             }
58             else {
59 0         0 $_ = "[[TODO: Not sure how to handle $_]]";
60             }
61             }
62              
63 8   33     90 my $time = $opts{time} // time();
64              
65 8         70 my $scroller = $self->get_widget_scroller;
66 8         153 $scroller->push_event( $event, $time, $args );
67              
68 8         4705 $self->push_log( $event, $time, $args );
69             }
70              
71             sub respond
72             {
73 5     5 0 12 my $self = shift;
74 5         26 my ( $text, %opts ) = @_;
75              
76 5         78 $self->push_displayevent( "response", { text => $text } );
77 5 100       31 $self->bump_level( $opts{level} ) if $opts{level};
78              
79 5         1248 return;
80             }
81              
82             sub respondwarn
83             {
84 0     0 0 0 my $self = shift;
85 0         0 my ( $text, %opts ) = @_;
86              
87 0         0 $self->push_displayevent( "warning", { text => $text } );
88 0 0       0 $self->bump_level( $opts{level} ) if $opts{level};
89              
90 0         0 return;
91             }
92              
93             sub responderr
94             {
95 0     0 0 0 my $self = shift;
96 0         0 my ( $text, %opts ) = @_;
97              
98 0         0 $self->push_displayevent( "error", { text => $text } );
99 0 0       0 $self->bump_level( $opts{level} ) if $opts{level};
100              
101 0         0 return;
102             }
103              
104             sub respond_table
105             {
106 0     0 0 0 my $self = shift;
107 0         0 my ( $tableref, %opts ) = @_;
108              
109             # We need to avoid using join() or sprintf() here, because any of the table
110             # cell arguments might be TaggedString objects. The CORE functions won't
111             # respect this taggnig.
112              
113 0 0       0 my $colsep = exists $opts{colsep} ? delete $opts{colsep} : " ";
114              
115 0         0 my $headings = delete $opts{headings};
116              
117 0         0 my @table = @$tableref;
118              
119 0         0 my @width;
120              
121 0         0 foreach my $r ( $headings, @table ) {
122 0 0       0 next unless defined $r;
123              
124 0         0 foreach my $c ( 0 .. $#$r ) {
125 0         0 my $d = $r->[$c];
126 0 0 0     0 $width[$c] = length $d if !defined $width[$c] or length $d > $width[$c];
127             }
128             }
129              
130 0 0       0 if( $headings ) {
131 0         0 my $text = Circle::TaggedString->new();
132 0         0 foreach my $c ( 0 .. $#$headings ) {
133 0 0       0 $text->append( $colsep ) if $c > 0;
134              
135 0         0 my $col = $headings->[$c];
136 0         0 $text->append_tagged( $col . ( " " x ( $width[$c] - length $col ) ),
137             u => 1 );
138             }
139 0         0 $self->respond( $text, %opts );
140             }
141              
142 0         0 foreach my $tr ( @table ) {
143 0         0 my $text = Circle::TaggedString->new();
144 0         0 foreach my $c ( 0 .. $#width ) {
145 0 0       0 $text->append( $colsep ) if $c > 0;
146              
147 0         0 my $col = $tr->[$c];
148 0         0 $text->append( $col . ( " " x ( $width[$c] - length $col ) ) );
149             }
150 0         0 $self->respond( $text, %opts );
151             }
152             }
153              
154             sub command_clear
155             : Command_description("Clear the scrollback buffer")
156             : Command_opt('keeplines=$', desc => "keep this number of lines")
157             {
158 0     0 0 0 my $self = shift;
159 0         0 my ( $opts, $cinv ) = @_;
160              
161 0   0     0 my $keeplines = $opts->{keeplines} || 0;
162              
163 0         0 my $scroller = $self->get_widget_scroller;
164              
165 0         0 my $to_delete = scalar @{ $scroller->get_prop_displayevents } - $keeplines;
  0         0  
166              
167 0 0       0 $scroller->shift_prop_displayevents( $to_delete ) if $to_delete > 0;
168              
169 0         0 return;
170 4     4   24 }
  4         8  
  4         33  
171              
172             sub command_dumpevents
173             : Command_description("Dump a log of the raw event buffer")
174             : Command_arg('filename')
175             {
176 0     0 0 0 my $self = shift;
177 0         0 my ( $filename, $cinv ) = @_;
178              
179 0         0 my $scroller = $self->get_widget_scroller;
180 0         0 YAML::DumpFile( $filename, $scroller->get_prop_displayevents );
181              
182 0         0 $cinv->respond( "Dumped event log to $filename" );
183 0         0 return;
184 4     4   1029 }
  4         7  
  4         27  
185              
186             ###
187             # Widget
188             ###
189              
190             sub method_get_widget
191             {
192 3     3 0 50753 my $self = shift;
193              
194 3   66     43 return $self->{widget} ||= $self->make_widget();
195             }
196              
197             # Subclasses might override this, but we'll provide a default
198             sub make_widget
199             {
200 2     2 0 5 my $self = shift;
201              
202 2         6 my $registry = $self->{registry};
203              
204 2         11 my $box = $registry->construct(
205             "Circle::Widget::Box",
206             orientation => "vertical",
207             );
208              
209 2 50       175 $self->make_widget_pre_scroller( $box ) if $self->can( "make_widget_pre_scroller" );
210              
211 2         22 $box->add( $self->get_widget_scroller, expand => 1 );
212              
213 2 100       44 $box->add( $self->get_widget_statusbar ) if $self->can( "get_widget_statusbar" );
214              
215 2         45 $box->add( $self->get_widget_commandentry );
216              
217 2         35 return $box;
218             }
219              
220             sub get_widget_scroller
221             {
222 11     11 0 6368 my $self = shift;
223              
224 11 100       82 return $self->{widget_displayevents} if defined $self->{widget_displayevents};
225              
226 4         16 my $registry = $self->{registry};
227              
228 4         16 my $widget = $registry->construct(
229             "Circle::Widget::Scroller",
230             scrollback => 1000, # TODO
231             );
232              
233 4         127 return $self->{widget_displayevents} = $widget;
234             }
235              
236             sub enumerable_path
237             {
238 0     0 0   my $self = shift;
239              
240 0 0         if( my $parent = $self->parent ) {
241 0           return $parent->enumerable_path . "/" . $self->enumerable_name;
242             }
243             else {
244 0           return $self->enumerable_name;
245             }
246             }
247              
248             0x55AA;