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 )