/usr/local/CPAN/tk-zinc/SimpleRadarControls.pm
package SimpleRadarControls;
# $Id: SimpleRadarControls.pm,v 1.2 2003/09/15 12:25:06 mertz Exp $
# This simple radar has been initially developped by P. Lecoanet <lecoanet@cena.fr>
# It has been adapted by C. Mertz <mertz@cena.fr> for demo purpose.
# Thanks to Dunnigan,Jack [Edm]" <Jack.Dunnigan@EC.gc.ca> for a bug correction.
use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
$top = 1;
sub new {
my $proto = shift;
my $type = ref($proto) || $proto;
my ($zinc) = @_;
my $self = {};
$self{'zinc'} = $zinc;
$self{'cur_x'} = 0;
$self{'cur_y'} = 0;
$self{'cur_angle'} = 0;
$self{'corner_x'} = 0;
$self{'corner_y'} = 0;
$self{'tlbbox'} = $zinc->add('group', $top,
-sensitive => 0, -visible => 0,
-tags => 'currentbbox');
$zinc->add('rectangle', $self{'tlbbox'}, [-3, -3, +3, +3]);
$self{'trbbox'} = $zinc->add('group', $top,
-sensitive => 0, -visible => 0,
-tags => 'currentbbox');
$zinc->add('rectangle', $self{'trbbox'}, [-3, -3, +3, +3]);
$self{'blbbox'} = $zinc->add('group', $top,
-sensitive => 0, -visible => 0,
-tags => 'currentbbox');
$zinc->add('rectangle', $self{'blbbox'}, [-3, -3, +3, +3]);
$self{'brbbox'} = $zinc->add('group', $top,
-sensitive => 0, -visible => 0,
-tags => 'currentbbox');
$zinc->add('rectangle', $self{'brbbox'}, [-3, -3, +3, +3]);
$zinc->add('rectangle', $top, [0, 0, 1, 1],
-linecolor => 'red', -tags => 'lasso',
-visible => 0, -sensitive => 0);
$zinc->Tk::bind('<Shift-ButtonPress-1>', [\&start_lasso, $self]);
$zinc->Tk::bind('<Shift-ButtonRelease-1>', [\&fin_lasso, $self]);
$zinc->Tk::bind('<ButtonPress-2>', sub { my $ev = $zinc->XEvent();
my @closest = $zinc->find('closest',
$ev->x, $ev->y);
print "at point=$closest[0]\n" });
$zinc->Tk::bind('<ButtonPress-3>', [\&press, $self, \&motion]);
$zinc->Tk::bind('<ButtonRelease-3>', [\&release, $self]);
$zinc->Tk::bind('<Shift-ButtonPress-3>', [\&press, $self, \&zoom]);
$zinc->Tk::bind('<Shift-ButtonRelease-3>', [\&release, $self]);
$zinc->Tk::bind('<Control-ButtonPress-3>', [\&press, $self, \&rotate]);
$zinc->Tk::bind('<Control-ButtonRelease-3>', [\&release, $self]);
$zinc->Tk::bind('current', '<Enter>', [\&showbox, $self]);
$zinc->Tk::bind('current', '<Leave>', [\&hidebox, $self]);
bless ($self, $type);
return $self;
}
#
# Controls for the window transform.
#
sub press {
my ($zinc, $self, $action) = @_;
my $ev = $zinc->XEvent();
my $lx = $ev->x;
my $ly = $ev->y;
$self->{'cur_x'} = $lx;
$self->{'cur_y'} = $ly;
$self->{'cur_angle'} = atan2($ly, $lx);
$zinc->Tk::bind('<Motion>', [$action, $self]);
}
sub motion {
my ($zinc, $self) = @_;
my $ev = $zinc->XEvent();
my $lx = $ev->x;
my $ly = $ev->y;
my @it;
my @res;
@it = $zinc->find('withtag', 'controls');
if (scalar(@it) == 0) {
return;
}
@res = $zinc->transform($it[0], [$lx, $ly, $self->{'cur_x'}, $self->{'cur_y'}]);
$zinc->translate('controls', $res[0] - $res[2], $res[1] - $res[3]);
$self->{'cur_x'} = $lx;
$self->{'cur_y'} = $ly;
}
sub zoom {
my ($zinc, $self) = @_;
my $ev = $zinc->XEvent();
my $lx = $ev->x;
my $ly = $ev->y;
my $maxx;
my $maxy;
my $sx;
my $sy;
if ($lx > $self->{'cur_x'}) {
$maxx = $lx;
} else {
$maxx = $self->{'cur_x'};
}
if ($ly > $self->{'cur_y'}) {
$maxy = $ly
} else {
$maxy = $self->{'cur_y'};
}
#avoid illegal division by zero
return unless ($maxx && $maxy);
$sx = 1.0 + ($lx - $self->{'cur_x'})/$maxx;
$sy = 1.0 + ($ly - $self->{'cur_y'})/$maxy;
$self->{'cur_x'} = $lx if ($lx>0); # avoid ZnTransfoDecompose :singular matrix
$self->{'cur_y'} = $ly if ($ly>0); # error messages
$zinc->scale('controls', $sx, $sy);
# $main::scale *= $sx;
# main::update_transform($zinc);
}
sub rotate {
my ($zinc, $self) = @_;
my $ev = $zinc->XEvent();
my $lx = $ev->x;
my $ly = $ev->y;
my $langle;
$langle = atan2($ly, $lx);
$zinc->rotate('controls', -($langle - $self->{'cur_angle'}));
$self->{'cur_angle'} = $langle;
}
sub release {
my ($zinc, $self) = @_;
$zinc->Tk::bind('<Motion>', '');
}
sub start_lasso {
my ($zinc, $self) = @_;
my $ev = $zinc->XEvent();
my $lx = $ev->x;
my $ly = $ev->y;
my @coords;
$self->{'cur_x'} = $lx;
$self->{'cur_y'} = $ly;
$self->{'corner_x'} = $lx;
$self->{'corner_y'} = $ly;
@coords = $zinc->transform($top, [$lx, $ly]);
$zinc->coords('lasso', [$coords[0], $coords[1], $coords[0], $coords[1]]);
$zinc->itemconfigure('lasso', -visible => 1);
$zinc->raise('lasso');
$zinc->Tk::bind('<Motion>', [\&lasso, $self]);
}
sub lasso {
my ($zinc, $self) = @_;
my $ev = $zinc->XEvent();
my $lx = $ev->x;
my $ly = $ev->y;
my @coords;
$self->{'corner_x'} = $lx;
$self->{'corner_y'} = $ly;
@coords = $zinc->transform($top, [$self->{'cur_x'}, $self->{'cur_y'}, $lx, $ly]);
$zinc->coords('lasso', [$coords[0], $coords[1], $coords[2], $coords[3]]);
}
sub fin_lasso {
my ($zinc, $self) = @_;
my $enclosed;
my $overlapping;
$zinc->Tk::bind('<Motion>', '');
$zinc->itemconfigure('lasso', -visible => 0);
$enclosed = join(', ', $zinc->find('enclosed',
$self->{'cur_x'}, $self->{'cur_y'},
$self->{'corner_x'}, $self->{'corner_y'}));
$overlapping = join(', ', $zinc->find('overlapping',
$self->{'cur_x'}, $self->{'cur_y'},
$self->{'corner_x'}, $self->{'corner_y'}));
print "enclosed=$enclosed, overlapping=$overlapping\n";
}
sub showbox {
my ($zinc, $self) = @_;
my @coords;
my @it;
if (! $zinc->hastag('current', 'currentbbox')) {
@it = $zinc->find('withtag', 'current');
if (scalar(@it) == 0) {
return;
}
@coords = $zinc->transform($top, $zinc->bbox('current'));
$zinc->coords($self->{'tlbbox'}, [$coords[0], $coords[1]]);
$zinc->coords($self->{'trbbox'}, [$coords[2], $coords[1]]);
$zinc->coords($self->{'brbbox'}, [$coords[2], $coords[3]]);
$zinc->coords($self->{'blbbox'}, [$coords[0], $coords[3]]);
$zinc->itemconfigure('currentbbox', -visible => 1);
}
}
sub hidebox {
my ($zinc, $self) = @_;
my $ev = $zinc->XEvent();
my $lx = $ev->x;
my $ly = $ev->y;
my @next;
@next = $zinc->find('closest', $lx, $ly);
if ((scalar(@next) == 0) ||
! $zinc->hastag($next[0], 'currentbbox') ||
$zinc->hastag('current', 'currentbbox')) {
$zinc->itemconfigure('currentbbox', -visible => 0);
}
}