line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package ProgressMonitor::Stringify::AbstractMonitor;
|
2
|
|
|
|
|
|
|
|
3
|
10
|
|
|
10
|
|
10108
|
use warnings;
|
|
10
|
|
|
|
|
29
|
|
|
10
|
|
|
|
|
480
|
|
4
|
10
|
|
|
10
|
|
60
|
use strict;
|
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
358
|
|
5
|
|
|
|
|
|
|
|
6
|
10
|
|
|
10
|
|
980884
|
use ProgressMonitor::Exceptions;
|
|
10
|
|
|
|
|
131
|
|
|
10
|
|
|
|
|
695
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
require ProgressMonitor::AbstractStatefulMonitor if 0;
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# Attributes:
|
11
|
|
|
|
|
|
|
# width
|
12
|
|
|
|
|
|
|
# The final width the field(s) this monitor manages will occupy
|
13
|
|
|
|
|
|
|
use classes
|
14
|
10
|
|
|
|
|
70
|
extends => 'ProgressMonitor::AbstractStatefulMonitor',
|
15
|
|
|
|
|
|
|
class_methods => ['_new'],
|
16
|
|
|
|
|
|
|
attrs_ro => ['width',],
|
17
|
|
|
|
|
|
|
attrs_pr => ['msgto'],
|
18
|
10
|
|
|
10
|
|
66
|
;
|
|
10
|
|
|
|
|
18
|
|
19
|
|
|
|
|
|
|
|
20
|
10
|
|
|
10
|
|
8330
|
use ProgressMonitor::SubTask;
|
|
10
|
|
|
|
|
38
|
|
|
10
|
|
|
|
|
311
|
|
21
|
10
|
|
|
10
|
|
65
|
use ProgressMonitor::SetMessageFlags;
|
|
10
|
|
|
|
|
16
|
|
|
10
|
|
|
|
|
14451
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sub _new
|
24
|
|
|
|
|
|
|
{
|
25
|
11
|
|
|
11
|
|
24
|
my $class = shift;
|
26
|
11
|
|
|
|
|
24
|
my $cfg = shift;
|
27
|
11
|
|
|
|
|
27
|
my $cfgPkg = shift;
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# get the instance from the super class
|
30
|
|
|
|
|
|
|
#
|
31
|
11
|
|
|
|
|
123
|
my $self = $class->SUPER::_new($cfg, $cfgPkg);
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# retrieve the configuration for easy reference
|
34
|
|
|
|
|
|
|
#
|
35
|
11
|
|
|
|
|
100
|
$cfg = $self->_get_cfg;
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# what max width has the user asked for?
|
38
|
|
|
|
|
|
|
#
|
39
|
11
|
|
|
|
|
39
|
my $maxWidth = $cfg->get_maxWidth;
|
40
|
|
|
|
|
|
|
|
41
|
11
|
|
|
|
|
80
|
my $allFields = $cfg->get_fields;
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# what is the minimum combined width needed to begin with?
|
44
|
|
|
|
|
|
|
#
|
45
|
11
|
|
|
|
|
48
|
my $wsum = 0;
|
46
|
11
|
|
|
|
|
100
|
$wsum += $_->get_width for (@$allFields);
|
47
|
11
|
50
|
|
|
|
96
|
print STDERR ("WARNING: Insufficient width for monitor ($maxWidth < $wsum). Feedback output will not display properly.\n") if $wsum > $maxWidth;
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# now try to make the stringification fit 'best possible'
|
50
|
|
|
|
|
|
|
#
|
51
|
11
|
|
|
|
|
24
|
my $remainingWidth = $maxWidth - $wsum;
|
52
|
11
|
50
|
|
|
|
54
|
if ($remainingWidth < 0)
|
53
|
|
|
|
|
|
|
{
|
54
|
|
|
|
|
|
|
# in this case, the available line is too short
|
55
|
|
|
|
|
|
|
#
|
56
|
|
|
|
|
|
|
# just set the width we can use, regardless
|
57
|
|
|
|
|
|
|
#
|
58
|
0
|
|
|
|
|
0
|
$self->{$ATTR_width} = $maxWidth;
|
59
|
|
|
|
|
|
|
}
|
60
|
|
|
|
|
|
|
else
|
61
|
|
|
|
|
|
|
{
|
62
|
|
|
|
|
|
|
# in this case, the line may provide extra space for dynamic fields to get more
|
63
|
|
|
|
|
|
|
# than they minimally need, which may make them look nicer
|
64
|
|
|
|
|
|
|
#
|
65
|
|
|
|
|
|
|
# in a round robin fashion, try to fairly give dynfields
|
66
|
|
|
|
|
|
|
# extra width until all are full, or width is exhausted
|
67
|
|
|
|
|
|
|
#
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# first make a separate list of the dynamic fields
|
70
|
|
|
|
|
|
|
#
|
71
|
11
|
|
|
|
|
18
|
my @dynFields;
|
72
|
11
|
|
|
|
|
31
|
for (@$allFields)
|
73
|
|
|
|
|
|
|
{
|
74
|
11
|
50
|
|
|
|
84
|
push(@dynFields, $_) if $_->isDynamic;
|
75
|
|
|
|
|
|
|
}
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# begin with the width we have left to give out
|
78
|
|
|
|
|
|
|
# and loop while there is any width left and there are any dynamic fields
|
79
|
|
|
|
|
|
|
# that are 'still hungry'...
|
80
|
|
|
|
|
|
|
#
|
81
|
11
|
|
33
|
|
|
99
|
while ($remainingWidth && @dynFields)
|
82
|
|
|
|
|
|
|
{
|
83
|
0
|
|
|
|
|
0
|
my $dynFieldCount = @dynFields;
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# make a list with the current width we have fairly distributed
|
86
|
|
|
|
|
|
|
#
|
87
|
0
|
|
|
|
|
0
|
my @allotments;
|
88
|
0
|
|
|
|
|
0
|
$allotments[$_ % $dynFieldCount]++ for (0 .. ($remainingWidth - 1));
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# now iterate over the list and give the corresponding dynfield the
|
91
|
|
|
|
|
|
|
# width it has been allotted.
|
92
|
|
|
|
|
|
|
# it will report how much it 'used' (due to its own constraints, if any)
|
93
|
|
|
|
|
|
|
# and we can disseminate remains in the next loop
|
94
|
|
|
|
|
|
|
#
|
95
|
0
|
|
|
|
|
0
|
for (0 .. (@allotments - 1))
|
96
|
|
|
|
|
|
|
{
|
97
|
0
|
|
|
|
|
0
|
my $allottedExtraWidth = $allotments[$_];
|
98
|
0
|
|
|
|
|
0
|
my $unusedExtraWidth = $dynFields[$_]->grabExtraWidth($allottedExtraWidth);
|
99
|
0
|
|
|
|
|
0
|
$remainingWidth -= $allottedExtraWidth - $unusedExtraWidth;
|
100
|
|
|
|
|
|
|
}
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# now recalculate the list with dynfields (any fields that have
|
103
|
|
|
|
|
|
|
# reached their max width are no longer (dynamic')
|
104
|
|
|
|
|
|
|
#
|
105
|
0
|
|
|
|
|
0
|
@dynFields = ();
|
106
|
0
|
|
|
|
|
0
|
for (@$allFields)
|
107
|
|
|
|
|
|
|
{
|
108
|
0
|
0
|
|
|
|
0
|
push(@dynFields, $_) if $_->isDynamic;
|
109
|
|
|
|
|
|
|
}
|
110
|
|
|
|
|
|
|
}
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# finally set the width we've actually used
|
113
|
|
|
|
|
|
|
#
|
114
|
11
|
|
|
|
|
151
|
$self->{$ATTR_width} = $maxWidth - $remainingWidth;
|
115
|
|
|
|
|
|
|
}
|
116
|
|
|
|
|
|
|
|
117
|
11
|
|
|
|
|
41
|
return $self;
|
118
|
|
|
|
|
|
|
}
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub setMessage
|
121
|
|
|
|
|
|
|
{
|
122
|
200
|
|
|
200
|
0
|
808
|
my $self = shift;
|
123
|
200
|
|
|
|
|
245
|
my $msg = shift;
|
124
|
200
|
|
50
|
|
|
747
|
my $when = shift || SM_NOW;
|
125
|
|
|
|
|
|
|
|
126
|
200
|
50
|
|
|
|
558
|
$self->{$ATTR_msgto} = undef if $when == SM_NOW;
|
127
|
|
|
|
|
|
|
|
128
|
200
|
|
|
|
|
674
|
return $self->SUPER::setMessage($msg, $when);
|
129
|
|
|
|
|
|
|
}
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub subMonitor
|
132
|
|
|
|
|
|
|
{
|
133
|
0
|
|
|
0
|
0
|
0
|
my $self = shift;
|
134
|
0
|
|
0
|
|
|
0
|
my $subCfg = shift || {};
|
135
|
|
|
|
|
|
|
|
136
|
0
|
|
|
|
|
0
|
$subCfg->{parent} = $self;
|
137
|
0
|
|
|
|
|
0
|
return ProgressMonitor::SubTask->new($subCfg);
|
138
|
|
|
|
|
|
|
}
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub setErrorMessage
|
141
|
|
|
|
|
|
|
{
|
142
|
0
|
|
|
0
|
0
|
0
|
my $self = shift;
|
143
|
0
|
|
|
|
|
0
|
my $msg = shift;
|
144
|
|
|
|
|
|
|
|
145
|
0
|
|
|
|
|
0
|
return $msg;
|
146
|
|
|
|
|
|
|
}
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
### protected
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub _get_message
|
151
|
|
|
|
|
|
|
{
|
152
|
600
|
|
|
600
|
|
726
|
my $self = shift;
|
153
|
|
|
|
|
|
|
|
154
|
600
|
|
|
|
|
796
|
my $now = time;
|
155
|
600
|
50
|
|
|
|
1643
|
if (defined($self->{$ATTR_msgto}))
|
156
|
|
|
|
|
|
|
{
|
157
|
0
|
0
|
|
|
|
0
|
$self->_set_message(undef) if ($self->{$ATTR_msgto} <= $now);
|
158
|
|
|
|
|
|
|
}
|
159
|
|
|
|
|
|
|
else
|
160
|
|
|
|
|
|
|
{
|
161
|
600
|
|
|
|
|
1608
|
my $to = $self->_get_cfg->get_messageTimeout;
|
162
|
600
|
50
|
|
|
|
3104
|
$self->{$ATTR_msgto} = time + $to if $to >= 0;
|
163
|
|
|
|
|
|
|
}
|
164
|
|
|
|
|
|
|
|
165
|
600
|
|
|
|
|
1966
|
return $self->SUPER::_get_message;
|
166
|
|
|
|
|
|
|
}
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub _set_message
|
169
|
|
|
|
|
|
|
{
|
170
|
220
|
|
|
220
|
|
264
|
my $self = shift;
|
171
|
220
|
|
|
|
|
373
|
my $msg = shift;
|
172
|
|
|
|
|
|
|
|
173
|
220
|
|
|
|
|
362
|
$self->{$ATTR_msgto} = undef;
|
174
|
|
|
|
|
|
|
|
175
|
220
|
|
|
|
|
633
|
return $self->SUPER::_set_message($msg);
|
176
|
|
|
|
|
|
|
}
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# helper method to call each field and render a complete line
|
179
|
|
|
|
|
|
|
#
|
180
|
|
|
|
|
|
|
sub _toString
|
181
|
|
|
|
|
|
|
{
|
182
|
411
|
|
|
411
|
|
533
|
my $self = shift;
|
183
|
411
|
|
|
|
|
498
|
my $considerMessage = shift();
|
184
|
|
|
|
|
|
|
|
185
|
411
|
50
|
|
|
|
907
|
$considerMessage = 1 unless defined($considerMessage);
|
186
|
|
|
|
|
|
|
|
187
|
411
|
|
|
|
|
1072
|
my $state = $self->_get_state;
|
188
|
411
|
|
|
|
|
1056
|
my $ticks = $self->_get_ticks;
|
189
|
411
|
|
|
|
|
1162
|
my $totalTicks = $self->_get_totalTicks;
|
190
|
|
|
|
|
|
|
|
191
|
411
|
|
|
|
|
1115
|
my $cfg = $self->_get_cfg;
|
192
|
411
|
|
|
|
|
999
|
my $ms = $cfg->get_messageStrategy;
|
193
|
411
|
|
|
|
|
2097
|
my $msg = $self->_get_message;
|
194
|
411
|
|
|
|
|
583
|
my $rendition = '';
|
195
|
|
|
|
|
|
|
|
196
|
411
|
|
|
|
|
505
|
my $forceNewline = 0;
|
197
|
411
|
50
|
|
|
|
1140
|
if ($ms eq 'overlay_newline')
|
|
|
50
|
|
|
|
|
|
198
|
|
|
|
|
|
|
{
|
199
|
0
|
|
|
|
|
0
|
$forceNewline = 1;
|
200
|
|
|
|
|
|
|
}
|
201
|
|
|
|
|
|
|
elsif ($ms eq 'overlay_honor_newline')
|
202
|
|
|
|
|
|
|
{
|
203
|
0
|
|
0
|
|
|
0
|
$forceNewline = ($msg && $msg =~ /\n$/);
|
204
|
|
|
|
|
|
|
}
|
205
|
|
|
|
|
|
|
|
206
|
411
|
|
|
|
|
1251
|
my $allFields = $cfg->get_fields;
|
207
|
411
|
|
|
|
|
1929
|
for (@$allFields)
|
208
|
|
|
|
|
|
|
{
|
209
|
|
|
|
|
|
|
# ask each field to render itself but ensure the result is exactly the width is
|
210
|
|
|
|
|
|
|
# what its supposed to be
|
211
|
|
|
|
|
|
|
#
|
212
|
411
|
|
33
|
|
|
2166
|
my $fr = $_->render($state, $ticks, $totalTicks, ($forceNewline && $considerMessage && $msg));
|
213
|
411
|
|
|
|
|
2419
|
my $fw = $_->get_width;
|
214
|
411
|
|
|
|
|
3155
|
$rendition .= sprintf("%*.*s", $fw, $fw, $fr);
|
215
|
|
|
|
|
|
|
}
|
216
|
|
|
|
|
|
|
|
217
|
411
|
50
|
|
|
|
1349
|
if (!$cfg->get_allowOverflow)
|
218
|
|
|
|
|
|
|
{
|
219
|
|
|
|
|
|
|
# we must make sure the width of the rendition won't cause linewrapping
|
220
|
|
|
|
|
|
|
#
|
221
|
411
|
|
|
|
|
2360
|
my $w = $self->{$ATTR_width};
|
222
|
411
|
50
|
|
|
|
1066
|
$rendition = sprintf("%*.*s", $w, $w, $rendition) if (length($rendition) > $w);
|
223
|
|
|
|
|
|
|
}
|
224
|
|
|
|
|
|
|
|
225
|
411
|
100
|
|
|
|
1406
|
if ($considerMessage)
|
226
|
|
|
|
|
|
|
{
|
227
|
222
|
100
|
66
|
|
|
1046
|
if ($msg && $ms ne 'none')
|
228
|
|
|
|
|
|
|
{
|
229
|
40
|
|
|
|
|
70
|
my $w = $self->{$ATTR_width};
|
230
|
|
|
|
|
|
|
|
231
|
40
|
100
|
|
|
|
89
|
if ($ms eq 'newline')
|
232
|
|
|
|
|
|
|
{
|
233
|
|
|
|
|
|
|
# accept embedded newlines, but ensure the message filler is applied (if set)
|
234
|
|
|
|
|
|
|
# the split will also avoid stray empty lines at the end
|
235
|
|
|
|
|
|
|
#
|
236
|
20
|
|
|
|
|
27
|
my $fullMsg = '';
|
237
|
20
|
|
|
|
|
62
|
foreach my $msgLine (split(/\n/, $msg))
|
238
|
|
|
|
|
|
|
{
|
239
|
20
|
50
|
|
|
|
107
|
$msgLine .= $cfg->get_messageFiller x ($w - length($msgLine)) if ($w > length($msgLine));
|
240
|
20
|
|
|
|
|
135
|
$fullMsg .= "$msgLine\n";
|
241
|
|
|
|
|
|
|
}
|
242
|
20
|
|
|
|
|
61
|
$rendition = sprintf("%s%s", $fullMsg, $rendition);
|
243
|
20
|
|
|
|
|
45
|
$self->_set_message(undef);
|
244
|
|
|
|
|
|
|
}
|
245
|
|
|
|
|
|
|
else
|
246
|
|
|
|
|
|
|
{
|
247
|
|
|
|
|
|
|
# overlay or overlay_newline or overlay_honor_newline
|
248
|
|
|
|
|
|
|
#
|
249
|
20
|
|
|
|
|
48
|
my $nlConversion = $cfg->get_messageOverlayNewlineConversion;
|
250
|
20
|
|
|
|
|
95
|
my $start_ovrfld = $cfg->get_messageOverlayStartField;
|
251
|
20
|
|
|
|
|
86
|
my $end_ovrfld = $cfg->get_messageOverlayEndField;
|
252
|
20
|
|
|
|
|
62
|
my $start_ovrpos;
|
253
|
|
|
|
|
|
|
my $end_ovrpos;
|
254
|
20
|
|
|
|
|
22
|
my $offset = 0;
|
255
|
20
|
|
|
|
|
40
|
for (1 .. @$allFields)
|
256
|
|
|
|
|
|
|
{
|
257
|
20
|
50
|
|
|
|
39
|
$start_ovrpos = $offset if $start_ovrfld == $_;
|
258
|
20
|
|
|
|
|
49
|
$offset += $allFields->[$_ - 1]->get_width;
|
259
|
20
|
50
|
|
|
|
79
|
$end_ovrpos = $offset if $end_ovrfld == $_;
|
260
|
20
|
50
|
33
|
|
|
64
|
last if ($start_ovrpos && $end_ovrpos);
|
261
|
|
|
|
|
|
|
}
|
262
|
|
|
|
|
|
|
|
263
|
20
|
|
|
|
|
51
|
$msg =~ s/\n/$nlConversion/g;
|
264
|
20
|
|
|
|
|
46
|
my $mf = $cfg->get_messageFiller;
|
265
|
20
|
50
|
|
|
|
88
|
my $len = $mf ? $end_ovrpos - $start_ovrpos : length($msg);
|
266
|
20
|
50
|
|
|
|
50
|
$msg .= $mf x ($len - length($msg)) if ($len > length($msg));
|
267
|
|
|
|
|
|
|
|
268
|
20
|
50
|
0
|
|
|
119
|
if ($ms eq 'overlay' || ($ms eq 'overlay_honor_newline' && !$forceNewline))
|
|
|
|
33
|
|
|
|
|
269
|
|
|
|
|
|
|
{
|
270
|
20
|
|
|
|
|
45
|
substr($rendition, $start_ovrpos, $len) = sprintf("%*.*s", $len, $len, $msg);
|
271
|
|
|
|
|
|
|
}
|
272
|
|
|
|
|
|
|
else
|
273
|
|
|
|
|
|
|
{
|
274
|
0
|
|
|
|
|
0
|
substr($rendition, $start_ovrpos) = $msg;
|
275
|
|
|
|
|
|
|
}
|
276
|
|
|
|
|
|
|
|
277
|
20
|
50
|
|
|
|
55
|
if ($forceNewline)
|
278
|
|
|
|
|
|
|
{
|
279
|
0
|
|
|
|
|
0
|
$rendition .= "\n";
|
280
|
0
|
|
|
|
|
0
|
$self->_set_message(undef);
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
}
|
283
|
|
|
|
|
|
|
}
|
284
|
|
|
|
|
|
|
}
|
285
|
|
|
|
|
|
|
|
286
|
411
|
|
|
|
|
1586
|
return $rendition;
|
287
|
|
|
|
|
|
|
}
|
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
###
|
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
package ProgressMonitor::Stringify::AbstractMonitorConfiguration;
|
292
|
|
|
|
|
|
|
|
293
|
10
|
|
|
10
|
|
72
|
use strict;
|
|
10
|
|
|
|
|
26
|
|
|
10
|
|
|
|
|
326
|
|
294
|
10
|
|
|
10
|
|
50
|
use warnings;
|
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
351
|
|
295
|
|
|
|
|
|
|
|
296
|
10
|
|
|
10
|
|
51
|
use Scalar::Util qw(blessed);
|
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
970
|
|
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# Attributes:
|
299
|
|
|
|
|
|
|
# maxWidth
|
300
|
|
|
|
|
|
|
# The maximum width this monitor can occupy altogether.
|
301
|
|
|
|
|
|
|
# allowOverflow
|
302
|
|
|
|
|
|
|
# In case the width is too small, let it overflow and linewrap.
|
303
|
|
|
|
|
|
|
# Else, cut the finished rendition so no linewrap occurs, but loses info.
|
304
|
|
|
|
|
|
|
# fields
|
305
|
|
|
|
|
|
|
# An array of fields (or a single field if only one) that should be used
|
306
|
|
|
|
|
|
|
# A field instance can not be reused in the list!
|
307
|
|
|
|
|
|
|
# messageStrategy
|
308
|
|
|
|
|
|
|
# Determines the strategy to use when displaying messages.
|
309
|
|
|
|
|
|
|
# 'none' : doesn't display messages
|
310
|
|
|
|
|
|
|
# 'overlay': requires 'messageOverlaysFields' to be set
|
311
|
|
|
|
|
|
|
# 'newline': renders the message only with a newline at the end, in
|
312
|
|
|
|
|
|
|
# effect pushing the other fields 'down'. Handles and 'honors'
|
313
|
|
|
|
|
|
|
# embedded newlines, trailing newlines are dropped.
|
314
|
|
|
|
|
|
|
# 'overlay_newline' : combines the effects of 'overlay' and 'newline'
|
315
|
|
|
|
|
|
|
# 'overlay_honor_newline' : acts as 'overlay', but will ensure to make a
|
316
|
|
|
|
|
|
|
# newline if the message has a trailing one.
|
317
|
|
|
|
|
|
|
# messageOverlayStartfield
|
318
|
|
|
|
|
|
|
# The field on which message overlay should start. Defaults to 0.
|
319
|
|
|
|
|
|
|
# messageOverlayEndfield
|
320
|
|
|
|
|
|
|
# The field on which message overlay should end. Defaults to last field.
|
321
|
|
|
|
|
|
|
# messageFiller
|
322
|
|
|
|
|
|
|
# The character for filling out the length of the message if
|
323
|
|
|
|
|
|
|
# is not long enough to overlay the full length of the field(s)
|
324
|
|
|
|
|
|
|
# it is set to overlay.
|
325
|
|
|
|
|
|
|
# messageTimeout
|
326
|
|
|
|
|
|
|
# The time in seconds before the message is cleared automatically. This
|
327
|
|
|
|
|
|
|
# is only relevant for overlay (for newline, it only appears once).
|
328
|
|
|
|
|
|
|
# Defaults to 3 seconds. Set to -1 for 'no timeout'.
|
329
|
|
|
|
|
|
|
# messageOverlayNewlineConversion
|
330
|
|
|
|
|
|
|
# For 'overlay' and 'overlay_newline', any embedded/trailing newlines
|
331
|
|
|
|
|
|
|
# will be converted to another string, settable by this cfg variable.
|
332
|
|
|
|
|
|
|
# Defaults to ' ' (space).
|
333
|
|
|
|
|
|
|
#
|
334
|
|
|
|
|
|
|
use classes
|
335
|
10
|
|
|
|
|
66
|
extends => 'ProgressMonitor::AbstractStatefulMonitorConfiguration',
|
336
|
|
|
|
|
|
|
attrs => [
|
337
|
|
|
|
|
|
|
'maxWidth', 'allowOverflow', 'fields',
|
338
|
|
|
|
|
|
|
'messageStrategy', 'messageOverlayStartField',
|
339
|
|
|
|
|
|
|
'messageOverlayEndField', 'messageFiller',
|
340
|
|
|
|
|
|
|
'messageTimeout', 'messageOverlayNewlineConversion'
|
341
|
|
|
|
|
|
|
],
|
342
|
10
|
|
|
10
|
|
50
|
;
|
|
10
|
|
|
|
|
21
|
|
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub defaultAttributeValues
|
345
|
|
|
|
|
|
|
{
|
346
|
11
|
|
|
11
|
|
25
|
my $self = shift;
|
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
return {
|
349
|
11
|
|
|
|
|
24
|
%{$self->SUPER::defaultAttributeValues()},
|
|
11
|
|
|
|
|
107
|
|
350
|
|
|
|
|
|
|
maxWidth => 0,
|
351
|
|
|
|
|
|
|
allowOverflow => 0,
|
352
|
|
|
|
|
|
|
fields => [],
|
353
|
|
|
|
|
|
|
messageStrategy => 'newline',
|
354
|
|
|
|
|
|
|
messageOverlayStartField => 1,
|
355
|
|
|
|
|
|
|
messageOverlayEndField => undef,
|
356
|
|
|
|
|
|
|
messageFiller => ' ',
|
357
|
|
|
|
|
|
|
messageTimeout => -1,
|
358
|
|
|
|
|
|
|
messageOverlayNewlineConversion => ' ',
|
359
|
|
|
|
|
|
|
};
|
360
|
|
|
|
|
|
|
}
|
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
sub checkAttributeValues
|
363
|
|
|
|
|
|
|
{
|
364
|
11
|
|
|
11
|
|
45
|
my $self = shift;
|
365
|
|
|
|
|
|
|
|
366
|
11
|
|
|
|
|
76
|
$self->SUPER::checkAttributeValues;
|
367
|
|
|
|
|
|
|
|
368
|
11
|
|
|
|
|
113
|
my $maxWidth = $self->get_maxWidth;
|
369
|
11
|
50
|
|
|
|
76
|
X::Usage->throw("invalid maxWidth: $maxWidth") unless $maxWidth >= 0;
|
370
|
|
|
|
|
|
|
|
371
|
11
|
|
|
|
|
119
|
my $fields = $self->get_fields;
|
372
|
11
|
50
|
|
|
|
122
|
if (ref($fields) ne 'ARRAY')
|
373
|
|
|
|
|
|
|
{
|
374
|
0
|
|
|
|
|
0
|
$fields = [$fields];
|
375
|
0
|
|
|
|
|
0
|
$self->set_fields($fields);
|
376
|
|
|
|
|
|
|
}
|
377
|
|
|
|
|
|
|
|
378
|
11
|
|
|
|
|
23
|
my %seenFields;
|
379
|
11
|
|
|
|
|
31
|
for (@$fields)
|
380
|
|
|
|
|
|
|
{
|
381
|
11
|
50
|
33
|
|
|
201
|
X::Usage->throw("not a field: $_") unless (blessed($_) && $_->isa("ProgressMonitor::Stringify::Fields::AbstractField"));
|
382
|
11
|
50
|
|
|
|
54
|
X::Usage->throw("same instance of field used more than once: $_") if $seenFields{$_};
|
383
|
11
|
|
|
|
|
68
|
$seenFields{$_} = 1;
|
384
|
|
|
|
|
|
|
}
|
385
|
|
|
|
|
|
|
|
386
|
11
|
|
|
|
|
85
|
my $ms = $self->get_messageStrategy;
|
387
|
11
|
50
|
|
|
|
130
|
X::Usage->throw("invalid value for messageStrategy: $ms")
|
388
|
|
|
|
|
|
|
unless $ms =~ /^(?:none|overlay|newline|overlay_newline|overlay_honor_newline)$/;
|
389
|
|
|
|
|
|
|
|
390
|
11
|
100
|
|
|
|
60
|
if ($ms =~ /^overlay/)
|
391
|
|
|
|
|
|
|
{
|
392
|
2
|
|
|
|
|
4
|
my $maxFieldNum = @$fields;
|
393
|
2
|
50
|
|
|
|
13
|
$self->set_messageOverlayEndField($maxFieldNum) unless defined($self->get_messageOverlayEndField);
|
394
|
|
|
|
|
|
|
|
395
|
2
|
|
|
|
|
29
|
my $start = $self->get_messageOverlayStartField;
|
396
|
2
|
|
|
|
|
11
|
my $end = $self->get_messageOverlayEndField;
|
397
|
2
|
50
|
33
|
|
|
18
|
X::Usage->throw("illegal overlay start field: $start") if ($start < 1 || $start > $maxFieldNum);
|
398
|
2
|
50
|
33
|
|
|
30
|
X::Usage->throw("illegal overlay end field: $end")
|
|
|
|
33
|
|
|
|
|
399
|
|
|
|
|
|
|
if ($end < 1 || $end > $maxFieldNum || $end < $start);
|
400
|
|
|
|
|
|
|
}
|
401
|
|
|
|
|
|
|
|
402
|
11
|
|
|
|
|
74
|
my $mf = $self->get_messageFiller;
|
403
|
11
|
50
|
|
|
|
80
|
X::Usage->throw("messageFiller not a character: $mf") if length($mf) > 1;
|
404
|
|
|
|
|
|
|
|
405
|
11
|
|
|
|
|
49
|
return;
|
406
|
|
|
|
|
|
|
}
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
############################
|
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=head1 NAME
|
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
ProgressMonitor::Stringify::AbstractMonitor - A reusable/abstract monitor implementation
|
413
|
|
|
|
|
|
|
that deals in stringified feedback.
|
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
This is an abstract base class for monitors that will render their result as a string
|
418
|
|
|
|
|
|
|
through the use of 'fields' (see the L packages).
|
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=head1 PROTECTED METHODS
|
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=over 2
|
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=item _new( $hashRef, $package )
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
Configuration data:
|
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=over 2
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
=item maxWidth (default => 79)
|
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
The monitor should have this maxWidth. The actual width used may be less. This
|
433
|
|
|
|
|
|
|
depends on the fields it uses; specifically, if dynamic fields are used, they
|
434
|
|
|
|
|
|
|
will be given width until all is used or until the dynamic fields themselves
|
435
|
|
|
|
|
|
|
have reached their maxWidth if any.
|
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
If the maxWidth is too small to handle the minimum requirements for all fields
|
438
|
|
|
|
|
|
|
the C setting controls whether the rendition causes linewrapping
|
439
|
|
|
|
|
|
|
or if it's just cut.
|
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
=item allowOverflow (default => 0)
|
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
If set to true and maxWidth is exceeded, linewrapping will occur for a possibly ugly display.
|
444
|
|
|
|
|
|
|
If set to false, the rendition will be cut to avoid linewrapping, for a possible loss of important
|
445
|
|
|
|
|
|
|
information.
|
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=item fields (default => [])
|
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
An array ref with field instances.
|
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=item messageStrategy (default => newline)
|
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
An identifiers that describes how messages should be inserted into the
|
454
|
|
|
|
|
|
|
rendition:
|
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
=over 2
|
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
=item none
|
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
Not surprisingly, this suppresses message presentation.
|
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
=item overlay
|
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
This will cause the message to overlay one or more of the other
|
465
|
|
|
|
|
|
|
fields, so as to keep things on one line. This setting will work
|
466
|
|
|
|
|
|
|
in conjunction with messageTimeout, messageOverlayStartField and
|
467
|
|
|
|
|
|
|
messageOverlayEndField.
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
=item newline
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
This will cause the message and a newline to be inserted in front
|
472
|
|
|
|
|
|
|
of the regular rendition, causing the running rendition to be
|
473
|
|
|
|
|
|
|
'pushed' forward.
|
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
=item overlay_newline
|
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
This will combine the effects of 'overlay' and 'newline'.
|
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=back
|
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=item messageFiller (default => ' ')
|
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
If the message is too short for the allotted space, it will be filled with
|
484
|
|
|
|
|
|
|
this character. Can be set to the empty string or undef to skip filling,
|
485
|
|
|
|
|
|
|
causing a 'partial overlay', i.e. just as much as the string is, which
|
486
|
|
|
|
|
|
|
obviously can give a confusing mixed message with the underlying field.
|
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=item messageTimeout (default => 3 seconds)
|
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
This is only relevant for the 'overlay' strategy. If the code doesn't
|
491
|
|
|
|
|
|
|
explicitly set the message to undef/blank, the timeout will automatically
|
492
|
|
|
|
|
|
|
remove it. Set to -1 for infinite.
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=item messageOverlayStartField, messageOverlayEndField (defaults => all fields)
|
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
Together these define the starting and ending field number that the message
|
497
|
|
|
|
|
|
|
should overlay. This defaults to 'all fields'.
|
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=item messageOverlayNewlineConversion (default => ' ')
|
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Embedded/trailing newlines will be converted to this string for the 'overlay'
|
502
|
|
|
|
|
|
|
and 'overlay_newline' strategies.
|
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=back
|
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=item _toString
|
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
Contains the logic to assemble the fields into a current string.
|
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
=back
|
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
=head1 AUTHOR
|
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
Kenneth Olwing, C<< >>
|
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=head1 BUGS
|
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
I wouldn't be surprised! If you can come up with a minimal test that shows the
|
519
|
|
|
|
|
|
|
problem I might be able to take a look. Even better, send me a patch.
|
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
Please report any bugs or feature requests to
|
522
|
|
|
|
|
|
|
C, or through the web interface at
|
523
|
|
|
|
|
|
|
L.
|
524
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on
|
525
|
|
|
|
|
|
|
your bug as I make changes.
|
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=head1 SUPPORT
|
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
You can find general documentation for this module with the perldoc command:
|
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
perldoc ProgressMonitor
|
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS
|
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
Thanks to my family. I'm deeply grateful for you!
|
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE
|
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
Copyright 2006,2007 Kenneth Olwing, all rights reserved.
|
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
542
|
|
|
|
|
|
|
under the same terms as Perl itself.
|
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
=cut
|
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
1; # End of ProgressMonitor::Stringify::AbstractMonitor
|