In quite a few locations you could have abstracted a bit more. F.ex:
my $cmds = $tl->Frame;
$cmds->pack;
if (defined $idx) {
# Existing activity - OK Apply Delete Cancel
$cmds->Button(-text => 'OK', -command => sub {&edit_entry($idx,$le
+gentry);$tl->destroy;})
->pack(-side => 'left');
$cmds->Button(-text => 'Apply', -command => [\&edit_entry, $idx, $
+legentry])
->pack(-side => 'left');
$cmds->Button(-text => 'Delete', -command => sub {&delete_entry($i
+dx);$tl->destroy;})
->pack(-side => 'left');
} else {
# New activity - OK Apply Cancel
$cmds->Button(-text => 'OK', -command => sub {&add_entry($legentry
+);$tl->destroy;})
->pack(-side => 'left');
$cmds->Button(-text => 'Apply', -command => [\&add_entry, $legentr
+y])
->pack(-side => 'left');
}
$cmds->Button(-text => 'Cancel', -command => [$tl => 'destroy'])->pack
+(-side => 'left');
You can write that as:
my @button = defined $idx ? (
OK => sub { &edit_entry($idx,$legentry); $tl->destroy; },
Apply => [\&edit_entry, $idx, $legentry],
Delete => sub { &delete_entry($idx); $tl->destroy; },
Cancel => [$tl => 'destroy'],
)
: (
OK => sub { &add_entry($legentry); $tl->destroy; },
Apply => [\&add_entry, $legentry],
Cancel => [$tl => 'destroy'],
);
for($tl->Frame) {
$_->pack;
while(my ($text, $command) = splice @button, 0, 2) {
$_->Button(-text => $text, -command => $command)
->pack(-side => 'left');
}
}
Note how the layout now directly conveys the information you previously had to sum up in comments.
If you don't like the scoping to main:: (I don't either), and you have a relatively involved data structure, that usually means you should abstract out your backend logic into a class. Use Class::Accessor to save the hassle of writing a lot of accessors and mutators and life is good. See also Damian Conway's ten rules for when to use OO.
F.ex given a class Activity, and with a slightly different INI format, you could have wittled down this:
print SAVE <<END;
for (0..$#activity) {
my ($legend,$time,$start,$end,$elapsed) =
@{%{$activity[$_]}}{qw(legend timstr start end elapsed)};
# Add up times of current activity
my $tsecs = 0;
for my $i (0..$#$end) {
$tsecs += tv_interval($start->[$i],$end->[$i]);
}
$tsecs += $elapsed if $elapsed;
$tsecs += tv_interval($start->[-1],[gettimeofday]) if defined($cur
+rent) && ($_ == $current);
print SAVE <<END2;
[Button $legend]
time=$time
elapsed=$tsecs
END2
}
to this:
for (@activity) {
print SAVE "[Button]\n";
my $item;
print SAVE "$item=" . $_->$item() for qw(legend time elapsed);
}
with calculation for time elapsed being hidden away at the particular spot, since it's not where it logically belongs anyway.
In general, try to abstract a bit more - capture regularities in code, irregularities in data.
Makeshifts last the longest. |