I like your idea of using libraries to hide widget definitions. I would even suggest going a step further, and creating wrappers to simplify some of your widget subroutines, since many of them use the same parameters. Here's how I would be inclined to simplify the library module (note btw, that in the call to
pack(), you should set the value of
-expand to either 0 or nonzero; it's
-fill which takes one of "none", "x", or "y", or "both"):
### A Different file
package PhoneList;
use Tk;
sub placement($$) {
my ($w, $placement) = @_;
if ($placement =~ s/^p,(\w+),(\w+),(\w+)//) {
$w->pack(-side => $1, -fill => $2, -expand => $3);
} elsif ($placement =~ s/^g,(\d+),(\d+)//) {
$w->grid(-column => $1, -row => $2);
} else {
die "Illegal placement format '$placement'\n";
}
return $w;
}
sub myFrame($$$$) {
my ($w, $ix, $iy, $placement) = @_;
my $fr = $w->Frame();
return &placement($fr, $placement);
}
sub myLabel($$$) {
my ($w, $text, $placement) = @_;
my $lbl = $w->Label(-text => $text);
return &placement($lbl, $placement);
}
sub myEntry($$$) {
my ($w, $tvar, $placement) = @_;
my $e = $w->Entry(-textvariable => $tvar);
return &placement($e, $placement);
}
sub myCheckbutton($$$$$) {
my ($w, $v, $b0, $b1, $placement) = @_;
my $c = $w->Checkbutton(-textvar => $v, -offvalue => $b0, -onvalue
+ => $b1);
return &placement($c, $placement);
}
sub setup {
my $parent = shift;
my %args = @_;
my $top = myFrame $parent, 5, 5, 'p,top,x,1';
my $list = myFrame $parent, 5, 5, 'p,top,x,1';
myLabel $top, 'Enter some phone numbers.', 'p,top,none,0';
myLabel $top, 'Check numbers to activate them.', 'p,top,none,0';
myLabel $list, 'Enabled', 'g,0,0';
myLabel $list, 'Phone number', 'g,1,0';
myLabel $list, 'Description', 'g,2,0';
for ( 1..5 ) {
my $textvar = \$args{-numbers}->[$_]{enable};
myCheckbutton $list, $textvar, '', 'ACTIVE', "g,0,$_";
myEntry $list, \$args{-numbers}->[$_]{number}, "g,1,$_";
myEntry $list, \$args{-numbers}->[$_]{description}, "g,2,$_";
}
MainLoop
}
1;
And here's the main program (with a fix to the line "
PhoneList::setup($mw, -numbers => $phoneNumbers;);", which had an extraneous ';' before the final parenthesis):
#!/usr/bin/perl -w
use strict;
use warnings;
use lib ".";
use PhoneList;
my $mw = MainWindow->new;
$mw->configure(-title => "A phone List");
my $phoneNumbers = [
{ number => '123-4321',
enable => 'ACTIvE',
description => 'Bob',
},
{ number => '321-1234',
enable => '',
description => 'Not Bob',
},
];
PhoneList::setup($mw, -numbers => $phoneNumbers);