BikePower

 view release on metacpan or  search on metacpan

BikePower/Tk.pm  view on Meta::CPAN


sub tk_output {
    my($self) = @_;
    $self->_init_output;

    my $entry;
    for ($entry = 0; $entry < $self->N_entry; $entry++) {
	$self->calc();
	my $out;
	foreach $out (@BikePower::out) {
	    $self->{'_lab'}{$out}->[$entry]->configure
	      (-text => sprintf($BikePower::fmt{$out},
				$self->{'_out'}{$out}));
	}
	$self->_incr_output;
    }
}

sub load_air_resistance_icons {
    my $f = shift;
    my $air_r;
    foreach $air_r (keys %BikePower::air_resistance) {
	if (!defined $Bikepower::air_resistance{$air_r}->{'icon'}) {
	    eval {
		$BikePower::air_resistance{$air_r}->{'icon'} =
		  $f->MainWindow->Pixmap(-file =>
					 Tk::findINC("BikePower/$air_r.xpm"));
	    };
	}
    }
}

sub tk_interface {
    my($self, $parent, %args) = @_;

    my $lang = $args{'-lang'} || 'en';
    my %s;
    tie %s, 'Tie::Lang', $lang_s, $lang;

    require Tk::Balloon;
    require FindBin;
    push(@INC, $FindBin::Bin);

    my $entry = 'Entry';
    eval { require Tk::NumEntry;
	   Tk::NumEntry->VERSION(1.02);
	   require Tk::NumEntryPlain;
	   Tk::NumEntryPlain->VERSION(0.05);
       };
    if (!$@) { $entry = 'NumEntry' }

    my $automatic = 0;

    my $top = $parent->Toplevel(-title => 'Bikepower');
    $self->{'_top'} = $top;
    push(@interfaces, $top);

    $top->optionAdd("*font" => '-*-helvetica-medium-r-*-14-*',
		    'startupFile');

    require Tk::Menubar;
    my $menuframe = $top->Menubar(-relief => 'raised',
				  -borderwidth => 2,
				 );
    #my $menuframe = $top->Frame(-relief => 'raised',#
				#-borderwidth => 2,
			       #);
    #$menuframe->pack(-fill => 'x');

    my $mb_file = $menuframe->Menubutton(-text => $s{'File'},
					 -underline => 0);
    $mb_file->pack(-side => 'left') if $Tk::VERSION < 800;
    $mb_file->command(-label => $s{'New'},
		      -underline => 0,
 		      -command => sub {
			  eval {
			      $top->Busy;
			      my $bp = new BikePower;
			      $bp->tk_interface($parent);
			      $top->Unbusy;
			  };
			  warn $@ if $@;
		      });
    $mb_file->command(-label => $s{'Clone'},
		      -underline => 1,
 		      -command => sub {
 		          eval {
 		              $top->Busy;
 		              my $bp = clone BikePower $self;
			      $bp->tk_interface($parent, %args);
			      $top->Unbusy;
			  };
			  warn $@ if $@;
		      });
    $mb_file->command(-label => $s{'Close'},
		      -underline => 0,
 		      -command => sub { $top->destroy });

    my $mb_set = $menuframe->Menubutton(-text => $s{'Settings'},
					-underline => 0);
    $mb_set->pack(-side => 'left') if $Tk::VERSION < 800;
    $mb_set->command
      (-label => $s{'Load defaults'},
       -underline => 5,
       -command => sub { $self->load_defaults });
    $mb_set->command
      (-label => $s{'Load...'},
       -underline => 0,
       -command => sub {
	   my $file;
	   eval { 
	       $file = $top->getOpenFile
		 (-defaultextension => '*.pl');
	   };
	   if ($@) {
	       require Tk::FileSelect;
	       $self->{'_load_fd'} =
		 $top->FileSelect(-create => 0,
				  -filter => "*.pl");
	       $file = $self->{'_load_fd'}->Show;
	   }
	   if (defined $file) {
	       $self->load_defaults($file);
	   }
       });
    $mb_set->command
      (-label => $s{'Save as default'},
       -underline => 5,
       -command => sub { $self->save_defaults });
    $mb_set->command
      (-label => $s{'Save as...'},
       -underline => 0,
       -command => sub {
	   my $file;
	   eval { 
	       $file = $top->getSaveFile
		 (-defaultextension => '*.pl');
	   };
	   if ($@) {
	       require Tk::FileSelect;
	       $self->{'_save_fd'} = 
		 $top->FileSelect(-create => 1,
				  -filter => "*.pl");
	       $file = $self->{'_save_fd'}->Show;
	       if ($file) {
		   if ($file !~ /\.pl$/) {
		       $file .= ".pl";
		   }
		   if (-e $file) {
		       require Tk::Dialog;
		       my $d = $top->Dialog
			 (-title => $s{'Warning'},
			  -text  => sprintf($s{'Overwrite existing file <%s>?'}, $file),
			  -default_button => $s{'No'},
			  -buttons => [$s{'Yes'}, $s{'No'}],
			  -popover => 'cursor');
		       return if $d->Show ne $s{'Yes'};
		   }
	       }
	   }
	   if (defined $file) {
	       $self->save_defaults($file);
	   }
       });

    my $mb_help = $menuframe->Menubutton(-text => $s{'Help'},
					 -underline => 0);
    $mb_help->pack(-side => 'right') if $Tk::VERSION < 800;
    $mb_help->command
      (-label => $s{'About...'},
       -underline => 0,
       -command => sub { 
	   require Tk::Dialog;
	   $top->Dialog(-text =>
			"BikePower.pm $BikePower::VERSION\n" .
			"(c) 1997,1998 Slaven Rezic")->Show;
       },
      );
    $mb_help->command
      (-label => $s{'Reference...'},
       -underline => 0,
       -command => sub { 
	   eval {
	       require Tk::Pod;
	       Tk::Pod->Dir($FindBin::Bin);
	       $top->Pod(-file => 'BikePower.pm');
	   };
	   if ($@) {
	       require Tk::Dialog;
	       $top->Dialog(-text => "Error: $@")->Show;
	   }
       });


    my $f = $top->Frame->pack;
    my $balloon = $f->Balloon;

    load_air_resistance_icons($f);
    {
	my $icon;
	foreach $icon ('up_down', 'change_wind') {
	    if (!defined $icons{$icon}) {
		eval { 
		    $icons{$icon} =
		      $f->Pixmap(-file => Tk::findINC("BikePower/$icon.xpm"));
		};
	    }
	}
    }

    my $row = 0;

    my $calc_button;
    my $autocalc = sub {
	$calc_button->invoke if $automatic;
    };

    my $labentry = sub {
	my($top, $row, $text, $varref, $unit, %a) = @_;
	my $entry = ($a{-forceentry} ? 'Entry' : $entry);
	$top->Label(-text => $text)->grid(-row => $row,
					  -column => 0,
					  -sticky => 'w');
	my $w;
	if (exists $a{-choices}) {
	    require Tk::BrowseEntry;

BikePower/Tk.pm  view on Meta::CPAN


    &$labentry($f, $row, $s{'Temperature'} . ':', \$self->{'T_a'}, '°C');
    $row++;

    &$labentry($f, $row, $s{'Velocity of headwind'} . ':',
	       \$self->{'H'}, 'm/s');
    if (defined $icons{'change_wind'}) {
 	my $btn = $f->Button(-image => $icons{'change_wind'},
			     -command => sub { $self->{'H'} = -$self->{'H'};
					       &$autocalc;
					   },
			    )->grid(-row => $row,
				    -column => 3,
				    -sticky => 'w',
				    -padx => 3);
	$balloon->attach($btn, -msg => $s{'toggle headwind and backwind'});
    }
    $row++;
    $f->Checkbutton(-text => $s{'Crosswind'},
		    -variable => \$self->{'cross_wind'},
		    -command => $autocalc,
		   )->grid(-row => $row,
			   -column => 0,
			   -sticky => 'w',
			   -ipady => 0,
			  ); $row++;

    &$labentry($f, $row, $s{'Grade of hill'} . ':', \$self->{'G'}, 'm/m',
	       -resolution => 0.01);
    if (defined $icons{'up_down'}) {
 	my $btn =$f->Button(-image => $icons{'up_down'},
			    -command => sub { $self->{'G'} = -$self->{'G'};
					      &$autocalc;
					  },
			   )->grid(-row => $row,
				   -column => 3,
				   -sticky => 'w',
				   -padx => 3);
	$balloon->attach($btn, -msg => $s{'toggle up and down hill'});
    }
    $row++;

    &$labentry($f, $row, $s{'Weight of cyclist'} . ':',
	       \$self->{'Wc'}, 'kg');
    $row++;
    &$labentry($f, $row, $s{'Weight of bike+clothes'} . ':',
	       \$self->{'Wm'}, 'kg');
    $row++;

    my @std_a_c =
      map { $BikePower::air_resistance{$_}->{'A_c'} . " (" .
	      $BikePower::air_resistance{$_}->{"text_$lang"}
	    . ")"
	} @BikePower::air_resistance_order;
    &$labentry($f, $row, '', \$self->{'A_c'}, 'm²',
	       -choices => \@std_a_c);
    my $ac_frame = $f->Frame(-relief => 'raised',
			     -borderwidth => 2)->grid(-row => $row,
						      -column => 0,
						      -sticky => 'w'); $row++;
    my $ac_mb = $ac_frame->Menubutton(-text => $s{'Frontal area'} . ':',
					-padx => 0,
					-pady => 0)->pack;
    $balloon->attach($ac_mb, -msg => $s{'set air resistance'});
    {
	my $i = 0;
	my $air_r;
	foreach $air_r (@BikePower::air_resistance_order) {
	    {
		my $i = $i; # wegen des Closures...
		my $icon = $BikePower::air_resistance{$air_r}->{'icon'};
		$ac_mb->command
		  ((defined $icon ? (-image => $icon) : (-label => $air_r)),
		   -command => sub { $self->{'A_c'} = $std_a_c[$i];
				     &$autocalc;
				 });
	    }
	    $i++;
	}
	if ($Tk::VERSION >= 800.010) {
	    $balloon->attach
	      ($ac_mb->cget(-menu),
	       -msg => ['',
			map { $BikePower::air_resistance{$_}->{"text_$lang"} }
			@BikePower::air_resistance_order]);
	}
    }

    {
	my @choices;
	foreach my $r (@BikePower::rolling_friction) {
	    push @choices, sprintf("%-6s ", $r->{'R'}) 
	      . "(" . $r->{"text_$lang"} . ")";
	}
	&$labentry($f, $row, $s{'Rolling friction'} . ':', \$self->{'R'},
		   undef,
		   -choices => \@choices); $row++;
    }

    &$labentry($f, $row, $s{'Transmission efficiency'} . ':',
	       \$self->{'T'}, undef,
	       -resolution => 0.01); $row++;
    
    my $res_frame = $top->Frame(-bg => 'yellow')->pack(-fill => 'x',
						       -ipady => 5);
    $res_frame->optionAdd('*' . substr($res_frame->PathName, 1) . "*background"
			  => 'yellow', 'userDefault');
    $row = 0;
    $res_frame->Label(-text => $s{'Resolve for'} . ':'
		     )->grid(-row => $row,
			     -column => 0,
			     -sticky => 'w');
    my $first_label = $res_frame->Label(-text => $s{'first'}
				       )->grid(-row => $row,
					       -column => 1);
    $balloon->attach($first_label, -msg => $s{'first value in table'});
    $res_frame->Label(-text => $s{'increment'})->grid(-row => $row,
							-column => 2);

    my $w;



( run in 0.432 second using v1.01-cache-2.11-cpan-483215c6ad5 )