#!perl -w # # Perl/tk script to present the user with the existing MAC address, and # allow them to enter a new one. # # Known bugs. # 1) Make an invalid entry '333', and tab. You go to the next field. # 2) I've seen the background stay red. Not sure how I do it, but once it # goes red it stays red. use strict; use MyPerlConstants; use Tk; # Take a 6 element array and make it string. sub makeString { my @data = @_; my $result = sprintf "%02s:%02s:%02s:%02s:%02s:%02s", $data[0], $data[1], $data[2], $data[3], $data[4], $data[5]; return $result; } my $debug = $TRUE; # If the user control-C's out, or kills my window, this will stay false my $done = $FALSE; # I want the first widget to have focus when I start, the only way I've # managed to do so is to save all my entry widgets. my @entries; # Turns out it's useful to know what entry your on.... my $current = 0; sub validate { my ($val) = @_; my $b_valid = ($val =~ /^[0-9a-f]{1,2}$/i)? 1: 0; # debugging, print the field. printf"<%s>: %s valid\n", $val, $b_valid? "IS": "is NOT" if $debug; whoopsie() if !$b_valid; if($b_valid) { $current++; $current = 0 if $current > 5; } #$entries[$current]->focus(); return $b_valid; } # Called when the user makes an invalid entry. sub whoopsie { my $widget = $entries[$current]; my $bg = $widget->cget(-background); $widget->bell; $widget->configure(-background => 'red'); $widget->update(); $widget->after(500, sub { $widget->configure(-background => $bg) } ); $widget->selectionFrom(0); $widget->selectionTo(100); $widget->focus(); #$widget->selectionRange(0, 3); } sub doit { my @addy = @_; my $mw = MainWindow->new(-title => 'MAC Address Input'); # 3 frames: original, new, and the buttons. my $forig = $mw->Frame()->pack(-expand => 1, -fill => 'both')-> pack(-side => 'top'); my $fnew = $mw->Frame()->pack(-expand => 1, -fill => 'both')-> pack(-side => 'top'); my $fdone = $mw->Frame()->pack(-expand => 1, -fill => 'both')-> pack(-side => 'top'); $forig->Label(-text => 'Current MAC address ', -width => 20)-> pack(-side => 'left'); $fnew->Label(-text => 'Enter new MAC address ', -width => 20)-> pack(-side => 'left'); # Now build some entry widgets to change it. for my $i (0 .. 5) { $forig->Label(-text => $addy[$i], -width => 2, -takefocus => 0) ->pack(-side => 'left'); # Don't add a trailing colon (jeez, the mental image that brings....) if($i != 5) { $forig->Label(-text => ':', -width => 1)->pack(-side => 'left'); } $entries[$i] = $fnew->Entry( -textvariable => \$addy[$i], -width => 2, -validate => 'focusout', -validatecommand => \&validate, #-invalidcommand => [ \&whoopsie, $entries[$i] ], )->pack(-side => 'left'); if($i != 5) { $fnew->Label(-text => ':', -width => 1)->pack(-side => 'left'); } } $entries[0]->focus; # give first widget focus. $entries[0]->selectionFrom(0); $entries[0]->selectionTo(100); $fdone->Label(-width => 12)->pack(-side => 'left'); $fdone->Label(-width => 12)->pack(-side => 'right'); $fdone->Button(-text => "Program", -command => sub {$mw->destroy;$done = $TRUE}, -background => 'green', -activebackground => 'green2', )->pack(-side => 'left'); $fdone->Button(-text => "Cancel", -command => sub {$mw->destroy;}, -background => 'red', -activebackground => 'red2', )->pack(-side => 'right'); MainLoop; return(@addy); } #my @foo = (0x10, 0x22, 0x33, 0x4b, 0x5f, 0x6d); my @foo = qw/10 22 33 4b 5f 6d/; print "Starting with: " . makeString(@foo) . "\n"; my @bar = doit(@foo); print "Ended with: " . makeString(@bar) . "\n"; print 'done: ' . $done . "\n";