Gtk2-Ex-Geo
view release on metacpan or search on metacpan
lib/Gtk2/Ex/Geo/Overlay.pm view on Meta::CPAN
sub draw_mode {
my($self) = @_;
return ($self->{rubberband_mode} eq 'select' or $self->{rubberband_mode} eq 'draw');
}
## @method key_release_event($event)
# @brief Handling of key release events.
#
# Unsets object attribute "_control_down" if "Ctrl" released.
sub key_release_event {
my($self, $event) = @_;
my $key = $event->keyval;
if ($key == $Gtk2::Gdk::Keysyms{Control_L} or $key == $Gtk2::Gdk::Keysyms{Control_R}) {
$self->{_control_down} = 0;
} elsif ($key == $Gtk2::Gdk::Keysyms{Shift_L} or $key == $Gtk2::Gdk::Keysyms{Shift_R}) {
$self->{_shift_down} = 0;
}
}
sub add_to_selection {
my($self, $geom) = @_;
my $store = ($self->{rubberband_mode} eq 'select') ? 'selection' : 'drawing';
if ($self->{_control_down}) {
# create first a multi something, then fall back to collection if need be
unless ($self->{$store} and $self->{$store}->isa('Geo::OGC::GeometryCollection')) {
my $coll = Geo::OGC::GeometryCollection->new;
$coll->AddGeometry($self->{$store}) if $self->{$store};
$self->{$store} = $coll;
}
$self->{$store}->AddGeometry($geom) if $geom;
} elsif ($self->{_shift_down}) {
my $polygon = $self->{$store}->LastPolygon;
if ($polygon and $geom->isa('Geo::OGC::Polygon')) {
$geom = $geom->ExteriorRing;
# exterior is ccw, interior is cw
$geom->Rotate;
$polygon->AddInteriorRing($geom);
}
} else {
$self->{$store} = $geom;
}
$self->signal_emit('new_selection') if $self->{rubberband_mode} eq 'select';
$self->signal_emit('drawing-changed') if $self->{rubberband_mode} eq 'draw';
}
## @method button_press_event()
# @brief Pops up a context menu or (optionally) does rubberbanding.
sub button_press_event {
my(undef, $event, $self) = @_;
return 0 unless $self->{layers} and @{$self->{layers}};
$self->grab_focus;
my $handled = 0;
if ($event->button == 3 and $self->{menu}) {
$self->delete_rubberband if $self->{path};
my $menu = Gtk2::Menu->new;
for (my $i =0; $i < @{$self->{menu}}; $i+=2) {
my $name = $self->{menu_item_setup}->($self->{menu}->[$i], $self);
my $item;
unless ($self->{menu}->[$i+1]) {
$item = Gtk2::SeparatorMenuItem->new();
} else {
$item = Gtk2::MenuItem->new($name);
$item->signal_connect(activate => $self->{menu}->[$i+1], $self);
}
$item->show;
$menu->append ($item);
}
$menu->popup(undef, undef, undef, undef, $event->button, $event->time);
$handled = 1;
} elsif ($event->button == 1) {
push @{$self->{path}}, [$event->x, $event->y];
unless ($self->{rubberband_mode} eq 'edit') {
$self->{rubberband_gc} = Gtk2::Gdk::GC->new($self->{pixmap});
$self->{rubberband_gc}->copy($self->style->fg_gc($self->state));
$self->{rubberband_gc}->set_function('invert');
}
if ($self->{rubberband_mode} eq 'edit' and $self->{drawing}) {
# find the closest point in drawing
my @p = $self->event_pixel2point($event->x, $event->y);
my @q = $self->{drawing}->ClosestVertex(@p);
my $d = pop @q;
$self->{drawing_edit} = \@q if $d/$self->{pixel_size} < $EDIT_SNAP_DISTANCE;
} elsif ($self->draw_mode and !($self->{_control_down} or $self->{_shift_down}) and
!($self->{rubberband_geometry} eq 'polygon' or $self->{rubberband_geometry} eq 'path')
)
{
if ($self->{rubberband_mode} eq 'select') {
delete $self->{selection};
#$self->signal_emit('new_selection');
} elsif ($self->{rubberband_mode} eq 'draw') {
delete $self->{drawing};
#$self->signal_emit('drawing-changed');
}
}
$handled = 1;
}
return $handled;
}
## @method motion_notify()
# @brief Updates the rubberband if rubberbanding.
# @todo Use more visible rubberband, there's no need to use XOR.
sub motion_notify {
my(undef, $event, $self) = @_;
return 0 unless $self->{layers} and @{$self->{layers}};
@{$self->{event_coordinates}} = ($event->x, $event->y);
unless ($self->{path}) {
$self->signal_emit('motion-notify');
return 0; # not handled
}
my $pm = $self->{pixmap};
( run in 1.375 second using v1.01-cache-2.11-cpan-39bf76dae61 )