# Tix Demostration Program # # This sample program is structured in such a way so that it can be # executed from the Tix demo program "widget": it must have a # procedure called "RunSample". It should also have the "if" statment # at the end of this file so that it can be run as a standalone # program using tixwish. require Tk; require Tk::TixGrid; # Demonstrates the use of editable entries in a Grid widget. # my %editgrid; use strict; use vars '$mw'; my $hasmw = (Tk::Exists($mw) ? 1 : 0); $mw = Tk::MainWindow->new(-title=>'Edit TixGrid Demo') unless $hasmw; RunSample($mw); Tk::MainLoop() unless $hasmw; sub RunSample { my ($w) = shift; $w->title("Doe Inc. Performance"); #$w->geometry('640x300'); $w->Label(-justify=>'left', -text => 'The left column is calculated automatically. To calculate the right column, press the "Calculate" button') ->pack(qw(-side top -anchor c -padx 3 -pady 3)); # Create the buttons # my $f = $w->Frame(qw/-relief flat/)->pack(qw/-side right -fill y/); my $add = $f->Button(-text=>"Add Row", -width=>9, -command=>\&EditGrid_addRow); my $edit = $f->Button(-text=>"Edit", -width=>9, -command=>\&EditGrid_edit); my $cal = $f->Button(-text=>"Calculate",-width=>9, -command=>\&EditGrid_calculate); my $close= $f->Button(-text=>"Close", -width=>9, -command=>[$w=>'destroy']); $add->pack( qw/-side top -padx 10/); $edit->pack( qw/-side top -padx 10/); $cal->pack( qw/-side top -padx 10 -pady 2/); $close->pack(qw/-side bottom -padx 10/); # Create the grid and set options to make it editable. # my $grid = $w->Scrolled('TixGrid', -bd=>0)-> pack(qw/-expand yes -fill both -padx 3 -pady 3/); $grid->configure( -formatcmd => [\&EditGrid_format,$grid], -editnotifycmd => \&EditGrid_editNotify, -editdonecmd => \&EditGrid_editDone, -selectunit => \&cell, -selectmode => \&single); # Insert some initial data # $grid->set(0,1, -text=>"City #1"); $grid->set(0,2, -text=>"City #2"); $grid->set(0,3, -text=>"City #3"); $grid->set(0,5, -text=>"Combined"); $grid->set(2,0, -text=>"Population"); $grid->set(4,0, -text=>"Avg. Income"); $grid->set(qw/2 1 -text 125/); $grid->set(qw/2 2 -text 81/); $grid->set(qw/2 3 -text 724/); $grid->set(qw/4 1 -text 24432.12/); $grid->set(qw/4 2 -text 18290.24/); $grid->set(qw/4 3 -text 18906.34/); # Global data used by other EditGrid_ procedures. # %editgrid = ( g => $grid, top => 1, bot => 3, result => 5, ); EditGrid_calPop(); EditGrid_calIncome(); } # EditGrid_edit -- # # Prompts the user to edit a cell. # sub EditGrid_edit { my $grid = $editgrid{g}; my @ent = $grid->anchor('get'); unless (@ent) { #$grid->edit('set', @ent[0,1]); $grid->editSet(@ent[0,1]); } } # EditGrid_addRow -- # # Adds a new row to the table. # sub EditGrid_addRow { my $grid = $editgrid{g}; #$grid->edit('apply'); $grid->editApply; $grid->move('row', $editgrid{result}, $editgrid{result}, 1); $editgrid{bot}++; $editgrid{result} = $editgrid{bot} + 2; $grid->set(0, $editgrid{bot}, -text=>"City #$editgrid{bot}"); $grid->set(2, $editgrid{bot}, -text=>0); $grid->set(4, $editgrid{bot}, -text=>0.0); EditGrid_calPop(); EditGrid_calIncome(); } # EditGrid_calPop -- # # Calculates the total population # sub EditGrid_calPop { my $grid = $editgrid{g}; my $pop = 0; for (my $i = $editgrid{top}; $i <= $editgrid{bot}; $i++) { $pop += $grid->entrycget(2,$i,'-text'); } $grid->set(2, $editgrid{result}, -text=>$pop); } # EditGrid_calIncome -- # # Calculates the average income. # sub EditGrid_calIncome { my $grid = $editgrid{g}; my $income = 0; my $total_pop = 0; my ($pop, $inc); for (my $i = $editgrid{top}; $i <= $editgrid{bot}; $i++) { $pop = $grid->entrycget(2, $i, '-text'); $inc = $grid->entrycget(4, $i, '-text'); $income = $income + ($pop+0) * $inc; $total_pop += $pop; } $grid->set(4, $editgrid{result}, -text=>($income/$total_pop)); } # EditGrid_calculate -- # # Recalculates both columns. # sub EditGrid_calculate { my $grid = $editgrid{g}; #$grid->edit('apply'); $grid->editApply; EditGrid_calIncome(); } # EditGrid_editNotify -- # # Returns true if an entry can be edited. # sub EditGrid_editNotify { my ($x, $y) = @_; my $grid = $editgrid{g}; if ($x == 2 || $x == 4) { if ($y >= $editgrid{top} && $y <= $editgrid{bot}) { $editgrid{oldValue} = $grid->entrycget($x, $y, '-text'); return 1; } } return 0; } # EditGrid_editDone -- # # Gets called when the user is done editing an entry. # sub EditGrid_editDone { my ($x, $y) = @_; my $grid = $editgrid{g}; if ($x == 2) { my $pop = $grid->entrycget($x, $y, '-text'); my $val; eval { $val = sprintf("%d",$pop); } ; if ($@) { $grid->entryconfigure($x, $y, -text=>$editgrid{oldValue}); # should be a custom warning. $grid->TraceBack("$pop is not an valid integer. Try again"); } else { $grid->entryconfigure(4, $editgrid{result}, -text=>"-"); EditGrid_calPop(); } } else { my $income = $grid->entrycget($x, $y, '-text'); my $val; eval { $val = sprintf("%f",$income); } ; if ($@) { $grid->entryconfigure($x, $y, -text=>$editgrid{oldValue}); # should be a custom warning. $grid->TraceBack("$income is not an valid floating number. Try again"); } else { $grid->entryconfigure(4, $editgrid{result}, -text=>'-'); } } } # EditGrid_format -- # # This command is called whenever the background of the grid # needs to be reformatted. The x1, y1, x2, y2 sprcifies the four # corners of the area that needs to be reformatted. # sub EditGrid_format { my ($w, $area, $x1, $y1, $x2, $y2) = @_; my $grid = $editgrid{g}; my %bg = qw( s-margin gray65 x-margin gray65 y-margin gray65 main gray20 ); if ($area eq 'main') { foreach my $col (2, 4) { $w->format('border', $col, 1, $col, $editgrid{bot}, qw/-relief flat -filled 1 -yon 1 -yoff 1 -bd 0 -bg #b0b0f0 -selectbackground #a0b0ff/); $w->format('border', $col, 2, $col, $editgrid{bot}, qw/-relief flat -filled 1 -yon 1 -yoff 1 -bd 0 -bg #80b080 -selectbackground #80b0ff/); } $w->format('grid', $x1, $y1, $x2, $y2, -bordercolor=>$bg{$area}, qw/-relief raised -bd 1 -filled 0 -bg red -xon 1 -yon 1 -xoff 0 -yoff 0 -anchor se/ ); } elsif ($area eq 'y-margin') { $w->format('border', $x1, $y1, $x2, $y2, -bg=>$bg{$area}, qw/-filled 1 -relief raised -bd 1 -selectbackground gray80/); } else { $w->format('border', $x1, $y1, $x2, $y2, -bg=>$bg{$area}, qw/-filled 1 -relief raised -bd 1 -selectbackground gray80/); } # case $area { # {main y-margin} { # set y [expr $editgrid(bot) + 1] # $w format border 0 $y 100 $y -bg black -filled 1 -bd 0 # } # } }