# TODO: # # o How to get into state 's0' 'b0' so cursor keys start # working (compare with Tk/Widget XYscrollBind # o the options -browsecmd and -command callback are not # not implemented (as in Tix) # o privateData 'state' used only once (check again Grid.tcl) # o FloatEntry 'sometimes not activeted immediately on selection # o check also Leave Binding. Looks like entry does get unpost'ed package Tk::TixGrid; BEGIN { use vars '$DEBUG'; $DEBUG = (defined($ENV{USER}) and $ENV{USER} eq 'ach') ? 1 : 0; print STDERR "tixGrid: debug = $DEBUG\n" if $DEBUG; } use strict; use vars qw($VERSION); $VERSION = sprintf '4.%03d', q$Revision: #9 $ =~ /\D(\d+)\s*$/; use Tk qw(Ev $XS_VERSION); use Tk::Widget; use Carp; # carp "\n".__PACKAGE__.' is deprecated' unless defined($Test::ntest); use base 'Tk::Widget'; Construct Tk::Widget 'TixGrid'; bootstrap Tk::TixGrid; sub Tk_cmd { \&Tk::tixGrid } sub Tk::Widget::SrclTixGrid { shift->Scrolled('TixGrid' => @_) } Tk::Methods qw(anchor bdtype delete entrycget entryconfigure format index move set size unset xview yview dragsite dropsite geometryinfo info nearest see selection sort ); use Tk::Submethods ( 'anchor' => [ qw(get set) ], 'delete' => [ qw(column row) ], 'info' => [ qw(bbox exists anchor) ], 'move' => [ qw(column row) ], 'selection' => [ qw(adjust clear includes set) ], 'size' => [ qw(column row) ], 'format' => [ qw(grid border) ], ); # edit subcommand is special. It justs invokes tcl code: # # edit set x y -> tixGrid:EditCell $w, x, y # edit apply -> tixGrid:EditApply # xxx Create an edit sub? # sub edit { .... } sub editSet { die "wrong args. Should be \$w->editSet(x,y)\n" unless @_ == 3; my ($w, $x, $y) = @_; $w->EditCell($x, $y); } sub editApply { die "wrong args. Should be \$w->editApply()\n" unless @_ == 1; my ($w) = @_; $w->EditApply() } #################################################### ## ## For button 2 scrolling. So TixGrid has 'standard' ## standard scrolling interface ## #sub scanMark # { # die "wrong # args: \$w->scanMark(x,y)\n" unless @_ == 3; # my ($w) = @_; # $w->{__scanMarkXY__} = [ @_[1,2] ]; # return ""; # } # #sub scanDragto # { # die "wrong # args: \$w->scanDragto(x,y)\n" unless @_ == 3; # my ($w, $x, $y) = @_; # my ($ox, $oy) = @{ $w->{__scanMarkXY__} }; # # #... # # return ""; # } ### end button 2 scrolling stuff #################### # Grid.tcl -- # # This file defines the default bindings for Tix Grid widgets. # # Copyright (c) 1996, Expert Interface Technologies # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Bindings translated to perl/Tk by Achim Bohnet sub ClassInit { my ($class, $mw) = @_; $class->SUPER::ClassInit($mw); $mw->XYscrollBind($class); ## ## Button bindings ## $mw->bind($class, '', ['Button_1', Ev('x'), Ev('y')]); $mw->bind($class, '', ['Shift_Button_1', Ev('x'), Ev('y')]); $mw->bind($class, '',['Control_Button_1', Ev('x'), Ev('y')]); $mw->bind($class, '', ['ButtonRelease_1', Ev('x'), Ev('y')]); $mw->bind($class, '', ['Double_1', Ev('x'), Ev('y')]); $mw->bind($class, '','Button_Motion'); $mw->bind($class, '','Control_Button_Motion'); $mw->bind($class, '','Button_Leave'); $mw->bind($class, '', ['Double_1', Ev('x'), Ev('y')]); $mw->bind($class, '', ['B1_Enter', Ev('x'), Ev('y')]); $mw->bind($class, '','Control_Button_Leave'); $mw->bind($class, '', ['Control_B1_Enter', Ev('x'), Ev('y')]); ## ## Keyboard bindings ## $mw->bind($class, '', ['DirKey', 'up' ]); $mw->bind($class, '', ['DirKey', 'down' ]); $mw->bind($class, '', ['DirKey', 'left' ]); $mw->bind($class, '', ['DirKey', 'right' ]); $mw->PriorNextBind($class); $mw->bind($class, '', 'Return'); $mw->bind($class, '', 'Space' ); return $class; } #---------------------------------------------------------------------- # # # Mouse bindings # # #---------------------------------------------------------------------- sub Button_1 { my $w = shift; return if $w->cget('-state') eq 'disabled'; $w->SetFocus; $w->ChgState(@_, [ '0'=>'1', ] ); } sub Shift_Button_1 { my $w = shift; return if $w->cget('-state') eq 'disabled'; $w->SetFocus; # $w->ChgState(@_, # [ # ] # ); } sub Control_Button_1 { my $w = shift; return if $w->cget('-state') eq 'disabled'; $w->SetFocus; $w->ChgState(@_, [ 's0' => 's1', 'b0' => 'b1', 'm0' => 'm1', 'e0' => 'e10', ] ); } sub ButtonRelease_1 { shift->ChgState(@_, [ '2' => '5', '4' => '3', ] ); } sub B1_Motion { shift->ChgState(@_, [ '2' => '4', '4' => '4', ] ); } sub Control_B1_Motion { shift->ChgState(@_, [ 's2' => 's4', 's4' => 's4', 'b2' => 'b4', 'b4' => 'b4', 'm2' => 'm4', 'm5' => 'm4', ] ); } sub Double_1 { shift->ChgState(@_, [ 's0' => 's7', 'b0' => 'b7', ] ); } sub B1_Leave { shift->ChgState(@_, [ 's2' => 's5', 's4' => 's5', 'b2' => 'b5', 'b4' => 'b5', 'm2' => 'm8', 'm5' => 'm8', 'e2' => 'e8', 'e5' => 'e8', ] ); } sub B1_Enter { shift->ChgState(@_, [ 's5' => 's4', 's6' => 's4', 'b5' => 'b4', 'b6' => 'b4', 'm8' => 'm4', 'm9' => 'm4', 'e8' => 'e4', 'e9' => 'e4', ] ); } sub Control_B1_Leave { shift->ChgState(@_, [ 's2' => 's5', 's4' => 's5', 'b2' => 'b5', 'b4' => 'b5', 'm2' => 'm8', 'm5' => 'm8', ] ); } sub Control_B1_Enter { shift->ChgState(@_, [ 's5' => 's4', 's6' => 's4', 'b5' => 'b4', 'b6' => 'b4', 'm8' => 'm4', 'm9' => 'm4', ] ); } sub AutoScan { shift->ChgState(@_, [ 's5' => 's9', 's6' => 's9', 'b5' => 'b9', 'b6' => 'b9', 'm8' => 'm9', 'm9' => 'm9', 'e8' => 'm9', 'e9' => 'm9', ] ); } #---------------------------------------------------------------------- # # # Key bindings # # #---------------------------------------------------------------------- sub DirKey { my ($w, $key) = @_; return if $w->cget('-state') eq 'disabled'; print STDERR "$w->DirKey($key)\n" if $DEBUG; $w->ChgState($key, [ 's0' => 's8', 'b0' => 'b8', ] ); } sub Return { my ($w) = @_; return if $w->cget('-state') eq 'disabled'; $w->ChgState( [ 's0' => 's9', 'b0' => 'b9', ] ); } sub Space { my ($w) = @_; return if $w->cget('-state') eq 'disabled'; $w->ChgState( [ 's0' => 's10', 'b0' => 'b10', ] ); } #---------------------------------------------------------------------- # # STATE MANIPULATION # # #---------------------------------------------------------------------- sub GetState { my ($w) = @_; my $data = $w->privateData(); $data->{state} = 0 unless exists $data->{state}; return $data->{state}; } sub Button_Motion { my $w = shift; my $Ev = $w->XEvent; $Tk::x = $Ev->x; $Tk::y = $Ev->y; $Tk::X = $Ev->X; $Tk::Y = $Ev->Y; $w->B1_Motion($Tk::x, $Tk::y); } sub Control_Button_Motion { my $w = shift; my $Ev = $w->XEvent; $Tk::x = $Ev->x; $Tk::y = $Ev->y; $Tk::X = $Ev->X; $Tk::Y = $Ev->Y; $w->Control_B1_Motion($Tk::x, $Tk::y); } sub Button_Leave { my $w = shift; my $Ev = $w->XEvent; $Tk::x = $Ev->x; $Tk::y = $Ev->y; $Tk::X = $Ev->X; $Tk::Y = $Ev->Y; $w->B1_Leave(); } sub Control_Button_Leave { my $w = shift; my $Ev = $w->XEvent; $Tk::x = $Ev->x; $Tk::y = $Ev->y; $Tk::X = $Ev->X; $Tk::Y = $Ev->Y; $w->Control_B1_Leave(); } sub SetState { my ($w, $state) = @_; $w->privateData()->{state} = $state; } sub GoState { my ($w, $state) = (shift, shift); print STDERR 'Gostate: ', $w->GetState, " --> $state, " if $DEBUG; $w->SetState($state); my $method = "GoState_$state"; print STDERR 'args=(', join(',',@_), ')'. "\t(",$w->cget('-selectmode'). ',',$w->cget('-selectunit').")\n" if $DEBUG; if (0) { $@ = ''; %@ = (); # Workaround to prevent spurious loss of $@ eval { $w->$method(@_) }; print STDERR "Error Gostate: '$state': ", $@ if $@; return undef; } $w->$method(@_); return undef } ## ## ChgState is a fancy case statement ## sub ChgState { my $w = shift; my $map = pop; print STDERR 'ChgState(', join(',',@_,'['), join(',',@$map,),']) ' if $DEBUG; my $state = $w->GetState; my ($match, $to); while (@$map) { $match = shift @$map; $to = shift @$map; if ($match eq $state) { print STDERR "$state --> $to \n" if $DEBUG; $w->GoState($to, @_); return; } } print STDERR "*no* chg for $state\n" if $DEBUG; } #---------------------------------------------------------------------- # SELECTION ROUTINES #---------------------------------------------------------------------- #proc tixGrid:SelectSingle {w ent} { # $w selection set [lindex $ent 0] [lindex $ent 1] # tixGrid:CallBrowseCmd $w $ent #} sub SelectSingle { my ($w, $n1, $n2) = @_; $w->selection('set', $n1, $n2); $w->Callback('-browsecmd' => $n1, $n2); } #---------------------------------------------------------------------- # SINGLE SELECTION #---------------------------------------------------------------------- sub GoState_0 { my ($w) = @_; my $list = $w->privateData()->{list}; return unless defined $list; foreach my $cmd (@$list) { # XXX should do more something like $w->Callback'('__pending_cmds__'); eval $cmd; # XXX why in tcl in global context (binding?) } undef(@$list); # XXX should really delete? Maybe on needed in TCL } # XXXX how to translate global context # what does unset #proc tixGrid:GoState-0 {w} { # set list $w:_list # global $list # # if [info exists $list] { # foreach cmd [set $list] { # uplevel #0 $cmd # } # if [info exists $list] { # unset $list # } # } #} sub GoState_1 { my ($w, $x, $y) = @_; my @ent = $w->mynearest($x,$y); if (@ent) { $w->SetAnchor(@ent); } $w->CheckEdit; $w->selection('clear', 0, 0, 'max', 'max'); if ($w->cget('-selectmode') ne 'single') { $w->SelectSingle(@ent); } $w->GoState(2); } sub GoState_2 { my ($w) = @_; } sub GoState_3 { my ($w, $x, $y) = @_; my @ent = $w->mynearest($x,$y); if (@ent) { $w->SelectSingle(@ent); } $w->GoState(0); } sub GoState_4 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x,$y); my $mode = $w->cget('-selectmode'); if ($mode eq 'single') { $w->SetAnchor(@ent); } elsif ($mode eq 'browse') { $w->SetAnchor(@ent); $w->selection('clear', 0, 0, 'max', 'max'); $w->SelectSingle(@ent); } elsif ($mode eq 'multiple' || $mode eq 'extended') { my (@anchor) = $w->anchor('get'); $w->selection('adjust', @anchor[0,1], @ent[0,1]); } } sub GoState_5 { my ($w, $x, $y) = @_; my @ent = $w->mynearest($x,$y); if (@ent) { $w->SelectSingle(@ent); $w->SetEdit(@ent); } $w->GoState(0); } ############################################## # BUG xxx # return scalar instead of errors sub mynearest { shift->split_s2a('nearest', @_); } sub myanchorGet { shift->split_s2a('anchor', 'get', @_); } sub split_s2a { my $w = shift; my $method = shift; my @ent = $w->$method(@_); if (@ent == 1) { my $tmp = $ent[0]; @ent = split(/ /, $ent[0]) if @ent == 1; print STDERR join('|',"$method splitted '$tmp' =>",@ent,"\n") if $DEBUG; } else { #print STDERR join("|","$method splitted is okay :",@ent,"\n") if $DEBUG; } return @ent; } ############################################## sub GoState_s5 { shift->StartScan(); } sub GoState_s6 { shift->DoScan(); } sub GoState_s7 { my ($w, $x, $y) = @_; my @ent = $w->mynearest($x, $y); if (@ent) { $w->selection('clear'); $w->selection('set', @ent); $w->Callback('-command' => @ent); } $w->GoState('s0'); } sub GoState_s8 { my ($w, $key) = @_; ## BUGS .... ## - anchor is bad, only bbox, exists8 ## - looks like anchor is 1-dim: set anchor 0 ## - method see unknown (even when defined with Tk::Method) my (@anchor) = $w->info('anchor'); if (@anchor) { @anchor = (); } else { @anchor = $w->info($key, @anchor); } $w->anchor('set', @anchor); $w->see(@anchor); $w->GoState('s0'); } #proc tixGrid:GoState-s8 {w key} { # set anchor [$w info anchor] # # if {$anchor == ""} { # set anchor 0 # } else { # set anchor [$w info $key $anchor] # } # # $w anchor set $anchor # $w see $anchor # tixGrid:GoState s0 $w #} sub GoState_s9 { my ($w, $key) = @_; #print STDERR "GoState_s9 is not implemented\n"; my (@anchor) = $w->info('anchor'); unless (@anchor) { @anchor = (); $w->anchor('set', @anchor); $w->see(@anchor); } unless ($w->info('anchor')) { # ! may not have any elements # $w->Callback('-command' => $w->info('anchor')); $w->selection('clear'); $w->selection('set', @anchor); } $w->GoState('s0'); } sub GoState_s10 { my ($w, $key) = @_; my (@anchor) = $w->info('anchor'); if (@anchor) { @anchor = (); $w->anchor('set', @anchor); $w->see(@anchor); } unless ($w->info('anchor')) { # ! may not have any elements # $w->Callback('-browsecmd' => $w->info('anchor')); $w->selection('clear'); $w->selection('set', @anchor); } $w->GoState('s0'); } #---------------------------------------------------------------------- # BROWSE SELECTION #---------------------------------------------------------------------- sub GoState_b0 { my ($w) = @_; } sub GoState_b1 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { $w->anchor('set', @ent); $w->selection('clear'); $w->selection('set', @ent); $w->Callback('-browsecmd' => @ent); } $w->GoState('b2'); } sub GoState_b2 { my ($w) = @_; } sub GoState_b3 { my ($w) = @_; my (@ent) = $w->info('anchor'); if (@ent) { $w->selection('clear'); $w->selection('set', @ent); $w->selection('set', @ent); $w->Callback('-browsecmd' => @ent); } $w->GoState('b0'); } sub GoState_b4 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { $w->anchor('set', @ent); $w->selection('clear'); $w->selection('set', @ent); $w->Callback('-browsecmd' => @ent); } } sub GoState_b5 { shift->StartScan(); } sub GoState_b6 { shift->DoScan(); } sub GoState_b7 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { $w->selection('clear'); $w->selection('set', @ent); $w->Callback('-command' => @ent); } $w->GoState('b0'); } sub GoState_b8 { my ($w, $key) = @_; my (@anchor) = $w->info('anchor'); if (@anchor) { @anchor = $w->info('key', @anchor); } else { @anchor = (0,0); # ????? } $w->anchor('set', @anchor); $w->selection('clear'); $w->selection('set', @anchor); $w->see(@anchor); $w->Callback('-browsecmd' => @anchor); $w->GoState('b0'); } sub GoState_b9 { my ($w) = @_; my (@anchor) = $w->info('anchor'); unless (@anchor) { @anchor = (0,0); $w->anchor('set', @anchor); $w->see(@anchor); } if ($w->info('anchor')) { # ! may not have any elements # $w->Callback('-command' => $w->info('anchor')); $w->selection('clear'); $w->selection('set', @anchor); } $w->GoState('b0'); } sub GoState_b10 { my ($w) = @_; my (@anchor) = $w->info('anchor'); unless (@anchor) { @anchor = (0,0); $w->anchor('set', @anchor); $w->see(@anchor); } if ($w->info('anchor')) { # ! may not have any elements # $w->Callback('-browsecmd' => $w->info('anchor')); $w->selection('clear'); $w->selection('set', @anchor); } $w->GoState('b0'); } #---------------------------------------------------------------------- # MULTIPLE SELECTION #---------------------------------------------------------------------- sub GoState_m0 { my ($w) = @_; } sub GoState_m1 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x,$y); if (@ent) { $w->anchor('set', @ent); $w->selection('clear'); $w->selection('set', @ent); $w->Callback('-browsecmd' => @ent); } $w->GoState('m2'); } sub GoState_m2 { my ($w) = @_; } sub GoState_m3 { my ($w) = @_; my (@ent) = $w->info('anchor'); if (@ent) { $w->Callback('-browsecmd' => @ent); } $w->GoState('m0'); } sub GoState_m4 { my ($w, $x, $y) = @_; my (@from) = $w->info('anchor'); my (@to) = $w->mynearest($x, $y); if (@to) { $w->selection('clear'); $w->selection('set', @from, @to); $w->Callback('-browsecmd' => @to); } $w->GoState('m5'); } sub GoState_m5 { my ($w) = @_; } sub GoState_m6 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { $w->Callback('-browsecmd' => @ent); } $w->GoState('m0'); } sub GoState_m7 { my ($w, $x, $y) = @_; my (@from) = $w->info('anchor'); my (@to) = $w->mynearest($x, $y); unless (@from) { @from = @to; $w->anchor('set', @from); } if (@to) { $w->selection('clear'); $w->selection('set', @from, @to); $w->Callback('-browsecmd' => @to); } $w->GoState('m5'); } sub GoState_m8 { shift->StartScan() } sub GoState_m9 { shift->DoScan() } sub GoState_xm7 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { $w->selection('clear'); $w->selection('set', @ent); $w->Callback('-browsecmd' => @ent); } $w->GoState('m0'); } #---------------------------------------------------------------------- # EXTENDED SELECTION #---------------------------------------------------------------------- sub GoState_e0 { my ($w) = @_; } sub GoState_e1 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { $w->anchor('set', @ent); $w->selection('clear'); $w->selection('set', @ent); $w->Callback('-browsecmd' => @ent); } $w->GoState('e2'); } sub GoState_e2 { my ($w) = @_; } sub GoState_e3 { my ($w) = @_; my (@ent) = $w->info('anchor'); if (@ent) { $w->Callback('-browsecmd' => @ent); } $w->GoState('e0'); } sub GoState_e4 { my ($w, $x, $y) = @_; my (@from) = $w->info('anchor'); my (@to) = $w->mynearest($x, $y); if (@to) { $w->selection('clear'); $w->selection('set', @from, @to); $w->Callback('-browsecmd' => @to); } $w->GoState('e5'); } sub GoState_e5 { my ($w) = @_; } sub GoState_e6 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { $w->Callback('-browsecmd' => @ent); } $w->GoState('e0'); } sub GoState_e7 { my ($w, $x, $y) = @_; my (@from) = $w->info('anchor'); my (@to) = $w->mynearest($x, $y); unless (@from) { @from = @to; $w->anchor('set', @from); } if (@to) { $w->selection('clear'); $w->selection('set', @from, @to); $w->Callback('-browsecmd' => @to); } $w->GoState('e5'); } sub GoState_e8 { shift->StartScan(); } sub GoState_e9 { shift->DoScan(); } sub GoState_e10 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { if ($w->info('anchor')) { $w->anchor('set', @ent); } if ($w->selection('includes', @ent)) { $w->selection('clear', @ent); } else { $w->selection('set', @ent); } $w->Callback('-browsecmd' => @ent); } $w->GoState('e2'); } sub GoState_xe7 { my ($w, $x, $y) = @_; my (@ent) = $w->mynearest($x, $y); if (@ent) { $w->selection('clear'); $w->selection('set', @ent); $w->Callback('-command' => @ent); } $w->GoState('e0'); } #---------------------------------------------------------------------- # HODGE PODGE #---------------------------------------------------------------------- sub GoState_12 { my ($w, $x, $y) = @_; $w->CancelRepeat; # xxx will not work $w->GoState(5, $x, $y); } #proc tixGrid:GoState-12 {w x y} { # tkCancelRepeat # tixGrid:GoState 5 $w $x $y #} sub GoState_13 { # FIX: a) $ent or @ent, b) 13 is never called!!? same in Grid.tcl my ($w, @ent, @oldEnt) = @_; my $data = $w->MainWindow->privateData('Tix'); $data->{indicator} = \@ent; $data->{oldEntry} = \@oldEnt; $w->IndicatorCmd('', @ent); } # set tkPriv(tix,oldEnt) $oldEnt # tixGrid:IndicatorCmd $w $ent #} sub GoState_14 { my ($w, $x, $y) = @_; my $data = $w->MainWindow->privateData('Tix'); if ($w->InsideArmedIndicator($x, $y)) { $w->anchor('set', @{ $data->{indicator} }); $w->selection('clear'); $w->selection('set', @{ $data->{indicator} }); $w->IndicatorCmd('', @{ $data->{indicator} }); } else { $w->IndicatorCmd('', @{ $data->{indicator} }); } delete($data->{indicator}); $w->GoState(0); } sub GoState_16 { my ($w, @ent) = @_; return unless (@ent); if ($w->cget('-selectmode') ne 'single') { $w->Select(@ent); $w->Browse(@ent); } } sub GoState_18 { my ($w) = @_; $w->CancelRepeat; ## xxx $w->GoState(6, $Tk::x, $Tk::y); } sub GoState_20 { my ($w, $x, $y) = @_; my $data = $w->MainWindow->privateData('Tix'); if ($w->InsideArmedIndicator($x, $y)) { $w->IndicatorCmd('', $data->{'indicator'}); } else { $w->GoState(21, $x, $y); } } sub GoState_21 { my ($w, $x, $y) = @_; my $data = $w->MainWindow->privateData('Tix'); unless ($w->InsideArmedIndicator($x, $y)) { $w->IndicatorCmd('', $data->{'indicator'}); } else { $w->GoState(20, $x, $y); } } sub GoState_22 { my ($w) = @_; my $data = $w->MainWindow->privateData('Tix'); if (@{ $data->{oldEntry} }) { $w->anchor('set', @{ $data->{oldEntry} }); } else { $w->anchor('clear'); } $w->GoState(0); } #---------------------------------------------------------------------- # callback actions #---------------------------------------------------------------------- sub SetAnchor { my ($w, @ent) = @_; if (@ent) { $w->anchor('set', @ent); # $w->see(@ent); } } # xxx check @ent of @$ent sub Select { my ($w, @ent) = @_; $w->selection('clear'); $w->selection('set', @ent) } # xxx check new After handling sub StartScan { my ($w) = @_; $Tk::afterId = $w->after(50, [AutoScan, $w]); } sub DoScan { my ($w) = @_; my $x = $Tk::x; my $y = $Tk::y; my $X = $Tk::X; my $Y = $Tk::Y; my $out = 0; if ($y >= $w->height) { $w->yview('scroll', 1, 'units'); $out = 1; } if ($y < 0) { $w->yview('scroll', -1, 'units'); $out = 1; } if ($x >= $w->width) { $w->xview('scroll', 2, 'units'); $out = 1; } if ($x < 0) { $w->xview('scroll', -2, 'units'); $out = 1; } if ($out) { $Tk::afterId = $w->after(50, ['AutoScan', $w]); } } #proc tixGrid:CallBrowseCmd {w ent} { # return # # set browsecmd [$w cget -browsecmd] # if {$browsecmd != ""} { # set bind(specs) {%V} # set bind(%V) $ent # # tixEvalCmdBinding $w $browsecmd bind $ent # } #} #proc tixGrid:CallCommand {w ent} { # set command [$w cget -command] # if {$command != ""} { # set bind(specs) {%V} # set bind(%V) $ent # # tixEvalCmdBinding $w $command bind $ent # } #} # tixGrid:EditCell -- # # This command is called when "$w edit set $x $y" is called. It causes # an SetEdit call when the grid's state is 0. # sub EditCell { my ($w, $x, $y) = @_; my $list = $w->privateData()->{'list'}; if ($w->GetState == 0) { $w->SetEdit($x, $y); # xxx really correct ? once 2, once 4 args? } else { push(@$list, [ $w, 'SetEdit', $x, $y]); } } #proc tixGrid:EditCell {w x y} { # set list $w:_list # global $list # # case [tixGrid:GetState $w] { # {0} { # tixGrid:SetEdit $w [list $x $y] # } # default { # lappend $list [list tixGrid:SetEdit $w [list $x $y]] # } # } #} # tixGrid:EditApply -- # # This command is called when "$w edit apply $x $y" is called. It causes # an CheckEdit call when the grid's state is 0. # sub EditApply { my ($w) = @_; my $list = $w->privateData()->{'list'}; if ($w->GetState eq 0) { $w->CheckEdit; # xxx really correct ? once 2, once 4 args? } else { push(@$list, $w->CheckEdit); } } #proc tixGrid:EditApply {w} { # set list $w:_list # global $list # # case [tixGrid:GetState $w] { # {0} { # tixGrid:CheckEdit $w # } # default { # lappend $list [list tixGrid:CheckEdit $w] # } # } #} # tixGrid:CheckEdit -- # # This procedure is called when the user sets the focus on a cell. # If another cell is being edited, apply the changes of that cell. # sub CheckEdit { my ($w) = @_; my $edit = $w->privateData->{editentry}; if (Tk::Exists($edit)) { # If it -command is not empty, it is being used for another cell. # Invoke it so that the other cell can be updated. # if (defined $edit->cget('-command')) { $edit->invoke; # xxx no args?? } } } sub SetFocus { my ($w) = @_; if ($w->cget('-takefocus')) { $w->focus; # # xxx translation of if ![string match $w.* [focus -displayof $w]] { # my $hasfocus = $w->focus(-displayof => $w)->pathname; # my $pathname = $w->pathname; # if ($hasfocus =~ /\Q$pathname\E.*/) # { # $w->focus # } } } # tixGrid:SetEdit -- # # Puts a floatentry on top of an editable entry. # sub SetEdit { my ($w, $px, $py) = @_; $w->CheckEdit; my $efc = $w->cget('-editnotifycmd'); return unless ( defined($efc) && length($efc) ); unless ($w->Callback('-editnotifycmd' => $px, $py)) { print STDERR "editnotifycmd not defined or returned false\n"; return; } my $oldvalue; if ($w->info('exists', $px, $py)) { # if entry doesn't support -text option. Can't edit it. # # If the application wants to force editing of an entry, it could # delete or replace the entry in the editnotifyCmd procedure. # Tk::catch { $oldvalue = $w->entrycget($px, $py, '-text'); }; if ($@) { return; } } else { $oldvalue = ''; } my @bbox = $w->info('bbox', $px, $py); my $edit = $w->privateData()->{__EDIT__}; unless (Tk::Exists($edit)) { require Tk::FloatEntry; $edit = $w->FloatEntry(); $w->privateData()->{__EDIT__} = $edit; } $edit->configure(-command=>[\&DoneEdit, $w, $px, $py]); $edit->post(@bbox); $edit->configure(-value=>$oldvalue); } sub DoneEdit { my ($w, $x, $y, @args) = @_; my $edit = $w->privateData()->{__EDIT__}; $edit->configure(-command=>undef); $edit->unpost; # FIX xxx # set value [tixEvent value] my $value = $edit->get; if ($w->info('exists', $x, $y)) { Tk::catch { $w->entryconfigure($x, $y, -text=>$value) }; if ($@) { return } } elsif ( length($value) ) { # This needs to be catch'ed because the default itemtype may # not support the -text option # Tk::catch { $w->set($x,$y,-text $value); }; if ($@) { return; } } else { return; } $w->Callback('-editdonecmd' => $x, $y); } 1; __END__