Scaling and rotations can be tricky because they are predefined to the group's origin (usually root group at 0,0, but it may be the canvas center point, depends on the canvas type and setup). The first time you try to rotate something, people ar usually surprised to see the item fly off the screen because the $cx and $cy is 0,0 (unless you moved the root group). I havn't tried it yet, but it looks like you want to use
$item->set_simple_transform ($x, $y, $scale, $rotation)
where $x and $y will be the center point of the scale; presumably the weighted center
of your item. Computing the weighted center can be tricky for odd shapes, so you may have to resort to making a special group for each item to be scaled, add the item to the group centered, move the group, and scale it.
It's one of those things you just need to play with to get right. Look at the 'animation' section of the Goo demo.
As far as the x,y coordinates of the mouse I think you need to setup an event handler on the canvas and the items.
sub event_handler{
my ( $widget, $event ) = @_;
print $widget ,' ',$event->type,"\n";
my ($x,$y) = ($event->x,$event->y);
print "$x $y\n";
}
Once again, look at the demo and see how it does the Events tab.
Just to show you how difficult a centered rotation can be, here is an example on the Gnome2::Canvas, you will then appreciate Goo's set_simple_transform :-)
#!/usr/bin/perl
use warnings;
use strict;
use Gnome2::Canvas;
use Gtk2 '-init';
my $window = Gtk2::Window->new();
my $sw = Gtk2::ScrolledWindow->new();
$sw->set_shadow_type ('etched-out');
$sw->set_policy ('automatic', 'always');
$sw->set_placement('top-right');
$sw->set_size_request (500, 500);
$sw->set_border_width(0);
my $black = Gtk2::Gdk::Color->new (0x0000,0x0000,0x0000);
my $white = Gtk2::Gdk::Color->new (0xFFFF,0xFFFF,0xFFFF);
my $canvas = Gnome2::Canvas->new_aa();
$canvas->set_size_request(500,500);
$canvas->set_scroll_region(0,0,1000,1000);
$canvas->modify_bg('normal',$white);
$canvas->set_center_scroll_region (0);
my $root = $canvas->root();
my @points = (50,50,80,20,90,100);
my $poly = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Polygo
+n',
points => \@points,
fill_color_rgba => 0x0000ff80,
outline_color => 'black');
$poly->{'points'} = \@points;
my $id = Glib::Timeout->add (100, sub {
&rotate($poly,10);
return 1;
});
# $ztree->set_pixels_per_unit(2);
$sw->add($canvas);
$window->signal_connect('destroy'=>sub { Gtk2->main_quit(); });
$window->set_default_size(450,350);
$window->add($sw);
$window->show_all();
Gtk2->main();
######################################################################
+######
sub rotate {
my ( $item, $degree ) = @_;
my @points = @{$item->{'points'}};
$item->destroy;
@points = &rotate_poly($item, $degree);
$poly = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Poly
+gon',
points => \@points,
fill_color_rgba => 0xff000080,
outline_color => 'black');
$poly->{'points'} = \@points;
}
####################################################################3
sub rotate_poly {
my ($ind, $angle, $midx, $midy) = @_;
# Get the old coordinates.
my @coords = @{$ind->{'points'}};
# Get the center of the poly. We use this to translate the
# above coords back to the origin, and then rotate about
# the origin, then translate back. (old)
($midx, $midy) = _get_CM( @coords ) unless defined $midx;
my @new;
# Precalculate the sin/cos of the angle, since we'll call
# them a few times.
my $rad = 3.1416*$angle/180;
my $sin = sin $rad;
my $cos = cos $rad;
# Calculate the new coordinates of the line.
while (my ($x, $y) = splice @coords, 0, 2) {
my $x1 = $x - $midx;
my $y1 = $y - $midy;
push @new => $midx + ($x1 * $cos - $y1 * $sin);
push @new => $midy + ($x1 * $sin + $y1 * $cos);
}
# Redraw the poly.
return @new;
}
#################################################################
# This sub finds the center of mass of a polygon.
# I grabbed the algorithm somewhere from the web.
# I grabbed it from Ala Qumsieh's RotCanvas :-)
sub _get_CM {
my ($x, $y, $area);
my $i = 0;
while ($i < $#_) {
my $x0 = $_[$i];
my $y0 = $_[$i+1];
my ($x1, $y1);
if ($i+2 > $#_) {
$x1 = $_[0];
$y1 = $_[1];
} else {
$x1 = $_[$i+2];
$y1 = $_[$i+3];
}
$i += 2;
my $a1 = 0.5*($x0 + $x1);
my $a2 = ($x0**2 + $x0*$x1 + $x1**2)/6;
my $a3 = ($x0*$y1 + $y0*$x1 + 2*($x1*$y1 + $x0*$y0))/6;
my $b0 = $y1 - $y0;
$area += $a1 * $b0;
$x += $a2 * $b0;
$y += $a3 * $b0;
}
return split ' ', sprintf "%.0f %0.f" => $x/$area, $y/$area;
}
####################################################################