2008/05/16

The Labs.Com Issue_02_Tk
Last update 1999/02/20

TPJ: Issue_02_Tk

This is a collection of programs published by The Perl Journal. You can download all source-code also from TPJ: Programs.
  1. modo
  2. modo.man
  3. Makefile
  4. README
  5. lib
  6. More Samples on Tk
Issue_02_Tk
1. modo
Download modo

 #!/usr/local/bin/perl -w 
 # 
 # modometer - the Mac Mouse Odometer, Perl/Tk style. 
 # 
 # Accumulate distances using this formula: 
 # 
 #   distance = sqrt( (dX * (Xmm/Xpixels))**2 + (dY * (Ymm/Ypixels))**2\ 
  ) 
 # 
 # Where dX and dY are pixel differentials, and Xmm, Ymm and Xpixels, Y\ 
 pixels 
 # are the screen dimensions in millimeters and pixels, respectively. 
 # 
 # Stephen O. Lidie, Lehigh University Computing Center, lusol@Lehigh.E\ 
 DU 
 # 96/04/29. 
 # 
 # Copyright (C) 1995 - 1996 Stephen O. Lidie. All rights reserved. 
 # 
 # This program is free software; you can redistribute it and/or modify\ 
  it under 
 # the same terms as Perl itself. 
  
 require 5.002; 
 my $LIBDIR; BEGIN {$LIBDIR = "./lib"} # modo auxiliary files directory 
 use lib $LIBDIR; 
 use English; 
 use strict; 
 use Tk; 
 use Tk::ColorEditor; 
 use Tk::ErrorDialog; 
 use Tk::Odometer; 
 use Tk::ROText; 
 # Predeclare global subroutines and variables. 
 use subs qw(sub build_main_window build_usage_window build_verify_wind\ 
 ow 
             initialize modo save_modo set_modo_colors update_status wh\ 
 ich_odo); 
  
 my $ABOUT;                      # modo's About Dialog widget 
 my $ACCELERATION;               # pointing device's acceleration facto\ 
 r 
 my ($AUTOSAVE_COUNT, $AUTOSAVE_TICKS); # .modo auto-save information 
 my $COLOR_STATE;                # do we have a color monitor? 
 my $CREF;                       # ColorEditor widget reference 
 my $CURSOR;                     # mouse cursor list reference 
 my $DEFAULT_UNITS;              # default human units 
 my ($LAST_X, $LAST_Y);          # previous pointing device coordinates 
 my $MILLISECOND_DELAY;          # time delay before rescheduling the m\ 
 ain loop 
 my ($MM_PIXEL_X, $MM_PIXEL_Y);  # mm/pixel in width and height 
 my $MODO_UNITS;                 # numeric conversion factor --> mil\ 
 limeters 
 my $MODO_UNITS_HUMAN;           # description of above for human consu\ 
 mption 
 my $MW;                         # Tk main Window 
 my $NUMBERS;                    # verify toplevel widget 
 my %OPT;                        # command line option values go here 
 my ($PIXELS_IN_X, $PIXELS_IN_Y); # pixels/inch in width and height 
 my ($PIXELS_CM_X, $PIXELS_CM_Y); # pixels/cm   in width and height 
 my $QUIT_COMMAND;               # code reference of Quit subroutine 
 my ($STATUS, $STATUS_B, $STATUS_L); # initialization status widgets 
 my $THRESHOLD;                  # pointer threshold 
 my @UNITS;                      # modo units list 
 my $USAGE;                      # usage toplevel widget 
 my $VERSION;                    # version number 
 my ($W_CODO, $W_PODO);          # cursor and pointer Odometer widgets 
 my ($W_MISC, $W_MISC_TEXT);     # miscellaneous status line widget 
  
 # Begin main. 
  
 initialize; 
 modo; 
 MainLoop; 
  
 # End main. 
  
 sub build_main_window { 
  
     # Construct the main modometer window. 
  
     update_status 'Odometer Window'; 
  
     my $w = $MW->Frame; 
  
     # Frame to contain the menu buttons across the top of the main win\ 
 dow. 
  
     my $mb = $w->Frame(qw(-bd 1 -relief raised)); 
  
     # File menu. 
  
     my $mbf = $mb->Menubutton( 
         -text        => 'File', 
         -underline   => 0, 
         -borderwidth => 1, 
         -relief      => 'raised', 
         -cursor      => $CURSOR, 
         -padx        => 0, 
     ); 
     $mbf->command(-label => 'Abort', -underline => 0, -comman\ 
 d => \&exit); 
     $mbf->separator; 
     my $close_command = [$MW => 'iconify']; 
     $mbf->command( 
         -label       => 'Close', 
         -underline   => 0, 
         -command     => $close_command, 
         -accelerator => 'Ctrl-w', 
     ); 
     $MW->bind('<Control-Key-w>' => $close_command); 
     $mbf->separator; 
     my $save_command = \&save_modo; 
     $mbf->command( 
         -label       => 'Save', 
         -underline   => 0, 
         -command     => $save_command, 
         -accelerator => 'Ctrl-s', 
     ); 
     $MW->bind('<Control-Key-s>' => $save_command); 
     $mbf->separator; 
     $mbf->command( 
         -label       => 'Quit', 
         -underline   => 0, 
         -command     => $QUIT_COMMAND, 
         -accelerator => 'Ctrl-q', 
     ); 
     $MW->bind('<Control-Key-q>' => $QUIT_COMMAND); 
  
     # Prefs menu. 
  
     my $mbp = $mb->Menubutton( 
         -text        => 'Prefs', 
         -underline   => 0, 
         -borderwidth => 1, 
         -relief      => 'raised', 
         -cursor      => $CURSOR, 
         -padx        => 0, 
     ); 
     my $odometers = 'Odometers'; 
     $mbp->cascade( 
         -label       => $odometers, 
         -underline   => 0, 
     ); 
     $mbp->separator; 
     $mbp->command( 
         -label       => 'Color Editor', 
         -underline   => 0, 
         -state       => $COLOR_STATE, 
         -command     => [$CREF => 'Show'], 
     ); 
     my $mbpm = $mbp->cget(-menu); 
     my $mbpmo = $mbpm->Menu; 
     $mbp->entryconfigure($odometers, -menu => $mbpmo); 
     $mbpmo->radiobutton( 
         -label       => 'Cursor', 
         -variable    => \$OPT{'odometer'}, 
         -value       => 'cursor', 
         -command     => \&which_odo, 
     ); 
     $mbpmo->radiobutton( 
         -label       => 'Pointer', 
         -variable    => \$OPT{'odometer'}, 
         -value       => 'pointer', 
         -command     => \&which_odo, 
     ); 
     $mbpmo->radiobutton( 
         -label       => 'Both', 
         -variable    => \$OPT{'odometer'}, 
         -value       => 'both', 
         -command     => \&which_odo, 
     ); 
  
     # Units menu. 
  
     my $mbu = $mb->Menubutton( 
         -text        => 'Units', 
         -underline   => 0, 
         -borderwidth => 1, 
         -relief      => 'raised', 
         -cursor      => $CURSOR, 
         -padx        => 0, 
     ); 
     foreach (@UNITS) { 
         my($un, @ur) = @$ARG; 
         $mbu->cascade(-label => $un, -underline => 0); 
         my $mbum = $mbu->cget(-menu); 
         my $m = $mbum->Menu; 
         $mbu->entryconfigure($un, -menu => $m); 
         foreach (@ur) { 
             my($l, $a, $v) = @$ARG; 
             $m->radiobutton( 
                 -label    => $l, 
                 -variable => \$MODO_UNITS, 
                 -value    => $v, 
                 -command  => sub {$MODO_UNITS_HUMAN = $a}, 
             ); 
             $m->invoke($l) if $l eq $DEFAULT_UNITS; # initialize va\ 
 riables 
         } # forend all radiobuttons 
     } # forend all units 
  
     # Help Menu. 
  
     my $mbh = $mb->Menubutton( 
         -text        => 'Help', 
         -underline   => 0, 
         -cursor      => $CURSOR, 
         -borderwidth => 1, 
         -relief      => 'raised', 
         -padx        => 0, 
     ); 
     $mbh->command( 
         -label       => 'About', 
         -underline   => 0, 
         -command     => [$ABOUT => 'Show'], 
     ); 
     $mbh->separator; 
     my $usage_command = [$USAGE => 'deiconify']; 
     $mbh->command( 
         -label       => 'Usage', 
         -underline   => 0, 
         -command     => $usage_command, 
         -accelerator => 'Ctrl-u', 
     ); 
     $MW->bind('<Control-Key-u>' => $usage_command); 
     $mbh->separator; 
     $mbh->command( 
         -label       => 'Verify', 
         -underline   => 0, 
         -command     => [$NUMBERS => 'deiconify'], 
     ); 
     # Create two odometers, one for the cursor and one for the pointin\ 
 g device. 
     # Create bindings to reset both trip values simultaneously. 
      
     $W_CODO = $w->Odometer( 
         -odometerlabel  => 'Cursor', 
         -font           => $OPT{'fontname'}, 
         -foreground     => $OPT{'foreground'}, 
         -background     => $OPT{'background'}, 
         -cursor         => $CURSOR, 
     ); 
     $W_PODO = $w->Odometer( 
         -odometerlabel  => 'Pointer', 
         -font           => $OPT{'fontname'}, 
         -foreground     => $OPT{'foreground'}, 
         -background     => $OPT{'background'}, 
         -cursor         => $CURSOR, 
     ); 
     my $b2_release_code = sub {$W_CODO->reset_trip; $W_PODO->res\ 
 et_trip}; 
     $W_CODO->bind('<Button2-ButtonRelease>' => $b2_release\ 
 _code); 
     $W_PODO->bind('<Button2-ButtonRelease>' => $b2_release\ 
 _code); 
  
     # Miscellaneous information. 
  
     $W_MISC_TEXT = ''; 
     $W_MISC = $w->Label(-font => 'fixed', -textvariable => \$\ 
 W_MISC_TEXT); 
     # Pack it all up.  We may see one or the other odometer, or perhap\ 
 s both. 
     $w->pack; 
     $mb->pack(qw(-side top -fill x)); 
     $mbf->pack(qw(-side left)); 
     $mbp->pack(qw(-side left)); 
     $mbu->pack(qw(-side left)); 
     $mbh->pack(qw(-side right)); 
     $W_MISC->pack(-pady => '2m'); 
     which_odo; 
 } # end build_main_window 
 sub build_usage_window { 
     # Configure the usage information window using Evaluate Parameters\ 
 ' 
     # -full_help and stuff the data into a scrolled read-only Text wid\ 
 get. 
  
     update_status 'Usage Window'; 
  
     $USAGE = $MW->Toplevel; 
     $USAGE->withdraw; 
     $USAGE->title('modo Usage'); 
     $USAGE->iconname('Usage'); 
     $USAGE->iconbitmap("\@$LIBDIR/icon.xbm"); 
  
     my $mb = $USAGE->Frame( 
         -borderwidth => 1, 
         -relief      => 'raised', 
     )->pack(-fill => 'x'); 
     my $mbf = $mb->Menubutton( 
         -text        => 'File', 
         -underline   => 0, 
         -cursor      => $CURSOR, 
         -borderwidth => 1, 
         -relief      => 'raised', 
     )->pack(-side => 'left'); 
     my $close_command = [$USAGE => 'withdraw']; 
     $mbf->command( 
         -label       => 'Close', 
         -underline   => 0, 
         -command     => $close_command, 
         -accelerator => 'Ctrl-w', 
     ); 
     $USAGE->bind('<Control-Key-w>' => $close_command); 
  
     my $ut = $USAGE->Scrolled( 
         'ROText', 
         qw(-wrap word -bd 1 -relief raised), 
     )->pack; 
     my $help = `$OPT{'help'} -full_help`; 
     $ut->insert('end',  $help); 
 }; # end build_usage_window 
 sub build_verify_window { 
     # Create the modometer Verify window to ensure correct calibration\ 
 . 
     # Some items are tagged so our special ColorEditor colorizer can 
     # configure canvas items. 
     update_status 'Verify Window'; 
     $NUMBERS = $MW->Toplevel; 
     $NUMBERS->withdraw; 
     $NUMBERS->title('Verify modo'); 
     $NUMBERS->iconname('Verify'); 
     $NUMBERS->iconbitmap("\@$LIBDIR/icon.xbm"); 
     # Create the File menu. 
     my $mb = $NUMBERS->Frame(qw(-bd 1 -relief raised))->pack(-fi\ 
 ll => 'x'); 
     my $mbf = $mb->Menubutton( 
         -text        => 'File', 
         -underline   => 0, 
         -cursor      => $CURSOR, 
         -borderwidth => 1, 
         -relief      => 'raised', 
     )->pack(-side => 'left'); 
     my $close_command = [$NUMBERS => 'withdraw']; 
     $mbf->command( 
         -label       => 'Close', 
         -underline   => 0, 
         -command     => $close_command, 
         -accelerator => 'Ctrl-w', 
     ); 
     $NUMBERS->bind('<Control-Key-w>' => $close_command); 
  
     # Create a cm/in scale for modometer scaling verification. 
  
     my $nf = $NUMBERS->Frame(qw(-relief raised -bd 1))->pack; 
     my $nfc = $nf->Canvas(qw(-width 3.2i -height 2.25i))->pack; 
     my $nfm = $nf->Message( 
         -borderwidth => 1, 
         -relief      => 'sunken', 
         -text        => 'Use this data to verify that modometer is \ 
 properly ' . 
                         'calibrated.  The X-Y axes should both be 1 in\ 
 ch ' . 
                         '(2.54 centimeters) in length.', 
     ); 
     $nfc->create('window', 200, 50, -window => $nfm); 
     $nfc->create('bitmap', '2.55i', '1.75i', 
         -bitmap => "\@$LIBDIR/icon.xbm", 
         -tags   => ['background', 'foreground'], 
     ); 
     $nfc->create('line', 10, 10, 10, $PIXELS_IN_Y+10, $PIXELS_IN_X+\ 
 10,  
                  $PIXELS_IN_Y+10, -tags => 'fill'); 
     $nfc->create('line', 10, $PIXELS_IN_Y+10-$PIXELS_CM_Y, 20,  
                  $PIXELS_IN_Y+10-$PIXELS_CM_Y, -tags => 'fill'); 
     $nfc->create('line', 10, $PIXELS_IN_Y+10-(2*$PIXELS_CM_Y), 20,  
                  $PIXELS_IN_Y+10-(2*$PIXELS_CM_Y), -tags => 'fill')\ 
 ; 
     $nfc->create('line', $PIXELS_CM_X+10, $PIXELS_IN_Y+10, $PIXELS_\ 
 CM_X+10,  
                  $PIXELS_IN_Y+10-10, -tags => 'fill'); 
     $nfc->create('line',  (2*$PIXELS_CM_X)+10, $PIXELS_IN_Y+10,  
                  (2*$PIXELS_CM_X)+10, $PIXELS_IN_Y+10-10, -tags => \ 
 'fill'); 
     # Create miscellaneous textual information. 
     my $numbers = sprintf( 
         "       Pointer Scale Factor :  %.2f\n" . 
         "       Threshold            :  %d\n" . 
         "       Acceleration         :  %.2f\n" . 
         "       Pixles/inch X        :  %d\n" . 
         "       Pixles/inch Y        :  %d", 
         $OPT{'pointer_scale_factor'}, 
         $THRESHOLD,  
         $ACCELERATION,  
         $PIXELS_IN_X,  
         $PIXELS_IN_Y, 
     ); 
     $nfc->create('text', '1.0i', '1.75i', 
         -text => $numbers, 
         -font => 'fixed', 
         -tags => 'fill', 
     ); 
     $nfc->create('text', '0.7i', '0.55i', 
         -text => '2.54 cm/in', 
         -font => 'fixed', 
         -tags => 'fill', 
     ); 
  
 } # end build_verify_window 
  
 sub initialize { 
  
     # First evaluate command line parameters and store values in the h\ 
 ash %OPT. 
     # Create the main window and, unless modo is starting up iconified\ 
 , the 
     # initialization status window. 
  
     use Getopt::EvaP;           # Evaluate Parameters 
     use inied;                        # initialize Evaluate Parameters\ 
  data 
     EvaP \@inied::PDT, \@inied::MM, \%OPT; # evaluate command line par\ 
 ameters 
  
     $VERSION = '1.1'; 
     $QUIT_COMMAND = sub {save_modo; exit}; 
     $MW = MainWindow->new($OPT{'display'}); 
     $MW->withdraw; 
     $MW->title($OPT{'title'}); 
     $MW->iconname('modo'); 
     $MW->iconbitmap("\@$LIBDIR/icon.xbm"); 
     $MW->minsize(50, 50); 
     $MW->protocol('WM_DELETE_WINDOW' => $QUIT_COMMAND); 
     foreach (qw(foreground background)) { 
         no strict 'refs'; 
         my $o = $OPT{$ARG}; # command line overrides option database 
         $MW->optionAdd("*${ARG}", $o) if $o ne ${"inied::def_${ARG}\ 
 "}; 
     } 
     unless ($OPT{'iconic'}) { 
         # Realize a transient toplevel to display modo's initializatio\ 
 n status. 
         $STATUS = $MW->Toplevel; 
         $STATUS->positionfrom('user'); 
         $STATUS->geometry('+100+100'); 
         $STATUS->title('Initializing modo'); 
         $STATUS_B = $STATUS->Label(-bitmap => "\@$LIBDIR/icon.xb\ 
 m")->pack; 
         $STATUS_L = $STATUS->Label( 
             -text  => 'Main Window ...', 
             -width => 25, 
         )->pack; 
         $MW->idletasks; 
     } # unlessend iconic 
     # Global objects and variables. 
     update_status 'Global Stuff'; 
     # Convert microseconds to milliseconds for after(); 
     if ($OPT{'microsecond_interval_time'} >= 1000) { 
         $MILLISECOND_DELAY = $OPT{'microsecond_interval_time'} / 1000; 
     } else { 
         $MILLISECOND_DELAY = 100; 
     } 
     $ABOUT = $MW->Dialog( 
         -title  => 'About modo', 
         -bitmap => "\@$LIBDIR/SOL.xbm", 
     ); 
     $ABOUT->configure( 
         -wraplength => '5i', 
         -text   => "modometer $VERSION\n\nThe Mac Mouse Odometer, P\ 
 erl/Tk " . 
                    "Style\n\nStephen O. Lidie, 96/02/11\nlusol\@Lehigh\ 
 .EDU", 
     ); 
     $ACCELERATION = 2.0; 
     $AUTOSAVE_TICKS = $OPT{'odometer_autosave_time'} * 60 * 1000 /  
       $MILLISECOND_DELAY; 
     $AUTOSAVE_COUNT = $AUTOSAVE_TICKS; 
     $COLOR_STATE = $MW->depth > 1 ? 'normal' : 'disabled';  
     $CREF = $MW->ColorEditor(-title => 'modo') if $COLOR_STATE e\ 
 q 'normal'; 
     $CURSOR = ["\@$LIBDIR/mouse.xbm", "$LIBDIR/mouse.mask", 'Black', '\ 
 White']; 
     $DEFAULT_UNITS = 'kilometers'; 
     ($LAST_X, $LAST_Y) = $MW->pointerxy; 
     $MM_PIXEL_X = $OPT{'display_width_millimeters'} /  
       $OPT{'display_width_pixels'}; 
     $MM_PIXEL_Y = $OPT{'display_height_millimeters'} /  
       $OPT{'display_height_pixels'};  
     $PIXELS_IN_X = int((25.4 / $MM_PIXEL_X) + 0.5); 
     $PIXELS_IN_Y = int((25.4 / $MM_PIXEL_Y) + 0.5); 
     $PIXELS_CM_X = int((10.0 / $MM_PIXEL_X) + 0.5); 
     $PIXELS_CM_Y = int((10.0 / $MM_PIXEL_Y) + 0.5); 
     $SIG{'INT'} = $QUIT_COMMAND; 
     $THRESHOLD = 4.0; 
     @UNITS = ( 
         ['Metric', 
             [qw(millimeters  mm),        1.], 
             [qw(centimeters  cm),        0.1], 
             [qw(decimeters   dm),        0.01], 
             [qw(meters        m),        0.001], 
             [qw(dekameters  dam),        0.0001],  
             [qw(hectometers  hm),        0.00001], 
             [qw(kilometers   km),        0.000001], 
             [qw(myriameters mym),        0.0000001], 
         ], 
         ['English', 
             [qw(inches       in),        0.1/2.54],  
             [qw(feet         ft),        0.1/2.54/12.0], 
             [qw(yards        yd),        0.1/2.54/12.0/3.0], 
             [qw(fathoms      fm),        0.1/2.54/12.0/6.0], 
             [qw(rods         rd),        0.1/2.54/12.0/3.0/6.0],  
             [qw(furlongs     fl),        0.1/2.54/12.0/3.0/220.0], 
             [qw(miles        mi),        0.1/2.54/12.0/3.0/1760.0],  
         ],  
         ['Other', 
             ['light-nanoseconds', 'lns', 0.001/299792458.0*1.0E+9], 
             ['nautical miles',     'nm', 0.001/1852.0], 
             ['marine leagues',    'mlg', 0.001/1852.0/3.0], 
         ], 
     ); # end UNITS 
  
     # See if xset is around so we can get true pointer control informa\ 
 tion. 
  
     update_status 'Pointer Control Information'; 
  
     my ($xset, $a, $t); 
     if (($xset) = grep /acceleration:/, `xset -q`) { 
         $xset =~ s/\d+\s+=//; 
         if (($a, $t) = $xset =~ /acceleration:\s+(.*)\s+threshold:\s+(\ 
 .*)$/) { 
             $ACCELERATION = eval $a; 
             $THRESHOLD = eval $t; 
         } 
     } 
     # Build widgets. 
     build_verify_window; 
     build_usage_window; 
     build_main_window; 
     # Initialize odometers from modo state file. 
     update_status 'State Information'; 
     $SIG{'INT'} = $QUIT_COMMAND; 
     my ($tc, $tp) = (0.0, 0.0); 
     my $o = $OPT{'odometer_file'}; 
     if (-s $o and -r $o) { 
         open MODO, "<$o"; 
         ($tc, $tp, $MODO_UNITS_HUMAN, $MODO_UNITS) = split ' ', <MO\ 
 DO>; 
         close MODO; 
     } 
     $W_CODO->add($tc, $MODO_UNITS); $W_CODO->reset_trip; 
     $W_PODO->add($tp, $MODO_UNITS); $W_PODO->reset_trip; 
     $MW->geometry($OPT{'geometry'}) if $OPT{'geometry'} ne $inied::\ 
 def_geometry; 
     if ($COLOR_STATE eq 'normal') { 
         # Establish the list of widgets for the ColorEditor to coloriz\ 
 e,  
         # excluding ColorEditor itself and the Odometers' descendants. 
         # 
         # A special colorizing procedure is required for canvas items. 
         # 
         # See if background/foreground command line options were speci\ 
 fied and 
         # use them to initialize modo's colors. 
         $CREF->configure( 
             -widgets => [$MW, $MW->Descendants], 
             -command => [\&set_modo_colors, $CREF], 
             -cursor  => $CURSOR,                          
         ); 
         $CREF->delete_widgets( 
             [$CREF,                # ColorEditor ... 
              $CREF->Descendants,   # ... and all its descendant wid\ 
 gets 
              $W_CODO->Descendants, # Odometer descendants because .\ 
 .. 
              $W_PODO->Descendants, # the class handles configuratio\ 
 n changes 
             ] 
         ); 
          
         foreach ([qw(foreground Foreground)], [qw(background Backgroun\ 
 d)]) { 
             my $color = $MW->optionGet($ARG->[0], $ARG->[1]); 
             set_modo_colors($CREF, $ARG->[0], $color) if defined $c\ 
 olor; 
         } 
     } # ifend color 
  
     if ($OPT{'iconic'}) { 
         $MW->iconify; 
     } else { 
         $CREF->delete_widgets([$STATUS, $STATUS->Descendants]); 
         $STATUS->destroy; 
         $MW->update; 
         $MW->deiconify; 
     } 
 } # end initialize 
 sub modo { 
     # Track the cursor forever, updating the odometer file every so of\ 
 ten. 
     my($x, $y) = $MW->pointerxy; 
     $W_MISC_TEXT = sprintf("U=%-3s (%4d,%4d)", $MODO_UNITS_HUMAN, $x, \ 
 $y); 
     my($dx, $dy) = (abs($x - $LAST_X), abs($y - $LAST_Y)); 
     ($LAST_X, $LAST_Y) = ($x, $y); 
     my($dxmm, $dymm) = ($dx * $MM_PIXEL_X, $dy * $MM_PIXEL_Y); 
     my $d = sqrt( ($dxmm * $dxmm) + ($dymm * $dymm) ); 
     if ($d > 0) { 
         $W_CODO->add($d, $MODO_UNITS); 
         if ($dx > $THRESHOLD || $dy > $THRESHOLD) { 
             $d /= $ACCELERATION; 
         } 
         $d /= $OPT{'pointer_scale_factor'}; 
         $W_PODO->add($d, $MODO_UNITS); 
     } 
  
     if ($AUTOSAVE_COUNT-- <= 0) { 
         $AUTOSAVE_COUNT = $AUTOSAVE_TICKS; 
         eval {save_modo}; 
     } 
     $MW->after($MILLISECOND_DELAY, \&modo); 
 } # end modo 
 sub save_modo { 
     # Update modometer state file. 
     open(MODO, ">$OPT{'odometer_file'}") or die "Cannot open:  $OS_\ 
 ERROR"; 
     printf MODO "%f %f %s %s\n", $W_CODO->get_total_distance, 
                                  $W_PODO->get_total_distance, 
                                  $MODO_UNITS_HUMAN, 
                                  $MODO_UNITS; 
     close MODO; 
  
 } # end save_modo 
  
 sub set_modo_colors { 
  
     # Configure all the widgets in $widgets for attribute $type and co\ 
 lor 
     # $color.  If $color is undef then reset all colors to the Tk defa\ 
 ults. 
     #  
     # This is a special modometer version of the released ColorEditor \ 
 color 
     # configurator to handle coloring Canvas items. 
  
     my($objref, $type, $color) = @ARG; 
  
     my $display = $objref->cget('-display_status'); 
  
     $objref->{'Status'}->title("Configure $type"); 
     $objref->{'Status'}->deiconify if $display; 
     my $w; 
     my $reset = not defined($color); 
     foreach $w (@{$objref->cget('-widgets')}) { 
         if ($display) { 
             $objref->{'Status_l'}->configure( 
                 -text => "WIDGET:  " . $w->PathName 
             ); 
             $objref->update; 
         }  
         if ($w->class eq 'Canvas') { 
             eval {$w->configure("-\L${type}" => $color)}; 
             my $tag; 
             if ($type eq 'background') { 
                 foreach $tag ($w->find('withtag', 'background')) { 
                     eval {$color = ($w->configure("-\L${type}"))[3]\ 
 } if $reset; 
                     $w->itemconfigure($tag, -background => $colo\ 
 r); 
                 } 
             } elsif ($type eq 'foreground') { 
                 foreach $tag ($w->find('withtag', 'foreground')) { 
                     eval {$color = ($w->configure("-\L${type}"))[3]\ 
 } if $reset; 
                     $w->itemconfigure($tag, -foreground => $colo\ 
 r); 
                 } 
                 foreach $tag ($w->find('withtag', 'fill')) { 
                     eval {$color = ($w->configure("-\L${type}"))[3]\ 
 } if $reset; 
                     $w->itemconfigure($tag, -fill => $color); 
                 } 
             } 
         } else { 
             eval {$color = ($w->configure("-\L${type}"))[3]} if $re\ 
 set; 
             eval {$w->configure("-\L${type}" => $color)}; 
         } 
     } # forend all widgets 
  
     $objref->{'Status'}->withdraw if $display; 
  
 } # end set_modo_colors 
  
 sub update_status { 
  
     my($state_text) = @ARG; 
  
     unless ($OPT{'iconic'}) { 
         $STATUS_L->configure(-text => "$state_text ..."); 
         $MW->idletasks; 
     } 
 } # end update_status 
 sub which_odo { 
     $W_CODO->packForget; 
     $W_PODO->packForget; 
  
     if ($OPT{'odometer'} eq 'cursor') { 
         $W_CODO->pack(-before => $W_MISC); 
     } elsif ($OPT{'odometer'} eq 'pointer') { 
         $W_PODO->pack(-before => $W_MISC); 
     } else { 
         $W_CODO->pack(-before => $W_MISC); 
         $W_PODO->pack(-before => $W_MISC); 
     } 
  
 } # end which_odo 

Issue_02_Tk
2. modo.man

  • modo.man
  • Issue_02_Tk
    3. Makefile

  • Makefile
  • Issue_02_Tk
    4. README

    Download README

      
                                 modometer 1.1 
     Here is modometer, a Perl/Tk implementation of my Xlib program xodomet\ 
     er, 
     which tracks the total distance your cursor and pointing device (typic\ 
     ally a 
     mouse) travel.  It also maintains "trip" distance since the applicatio\ 
     n 
     started or since you clicked on a trip reset button. 
      
     A pull-down menu allows you to select in which units the distance is 
     displayed, from millimeters to nautical miles to light-nanoseconds, an\ 
     d more. 
     modometer requires a one-time calibration procedure which is fully des\ 
     cribed 
     by reading the man page, entering "modo -full_help" or selecting Help/\ 
     Usage 
     from the modometer Menu bar. 
     modometer was inspired by the Macintosh Mouse Odometer program written\ 
      by 
     Sean P. Nolan. 
      
     An IBM RS/6000 model 320 running AIX 3.2.5 with mwm and X11 Release 5 \ 
     was the 
     primary developement environment.  Please report any bugs and be sure \ 
     to 
     fully specify your configuration. 
      
     Although in theory the cursor distance can be reliably tracked, the ac\ 
     tual 
     distance your pointing device moves is only APPROXIMATED and will not \ 
     be very 
     exact, so don't report this as a bug :-)! 
      
                                 Installation 
     The modometer tar file is available via anonymous FTP from FTP.Lehigh.\ 
     EDU in 
     the directory pub/odometer/modo.  Unpack it, and assuming Perl/Tk is k\ 
     nown 
     as /usr/local/bin/perl, just type ./modo. 
     To really "install" modometer edit the Makefile variables and `make in\ 
     stall'. 
      
     I welcome comments, enhancements, and bug reports. 
      
     Stephen O. Lidie 
     Lehigh University Computing Center 
      
     lusol@Lehigh.EDU 
      
                             Revision History 
     lusol@Lehigh.EDU, LUCC, 95/08/17 
      . Original version 1.1 release. 
      
     lusol@Lehigh.EDU, LUCC, 95/12/11 
      . Add use strict to tidy things up. 

    Issue_02_Tk
    5. lib

    Download lib

    Issue_02_Tk
    6. More Samples on Tk

                                                                                                                                       

    Last update 1999/02/20

    All Rights Reserved - (C) 1997 - 2008 by The Labs.Com

    Top of Page

    The Labs.Com