File: Dragger.pm

package info (click to toggle)
libgtk3-imageview-perl 6-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 176 kB
  • sloc: perl: 995; makefile: 4
file content (108 lines) | stat: -rw-r--r-- 2,846 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package Gtk3::ImageView::Tool::Dragger;

use warnings;
use strict;
use base 'Gtk3::ImageView::Tool';
use Glib qw(TRUE FALSE);    # To get TRUE and FALSE
use Readonly;
Readonly my $FLOAT_EPS    => 0.01;
Readonly my $RIGHT_BUTTON => 3;

our $VERSION = 6;

sub button_pressed {
    my $self  = shift;
    my $event = shift;

    # Don't block context menu
    if ( $event->button == $RIGHT_BUTTON ) {
        return FALSE;
    }

    $self->{drag_start} = { x => $event->x, y => $event->y };
    $self->{dnd_start}  = { x => $event->x, y => $event->y };
    $self->{dnd_eligible} = TRUE;
    $self->{dragging}     = TRUE;
    $self->{button}       = $event->button;
    $self->view->update_cursor( $event->x, $event->y );
    return TRUE;
}

sub button_released {
    my $self  = shift;
    my $event = shift;
    $self->{dragging} = FALSE;
    $self->view->update_cursor( $event->x, $event->y );
    return;
}

sub motion {
    my $self  = shift;
    my $event = shift;
    if ( not $self->{dragging} ) { return FALSE }
    my $offset = $self->view->get_offset;
    my $zoom   = $self->view->get_zoom;
    my $ratio  = $self->view->get_resolution_ratio;
    my $offset_x =
      $offset->{x} + ( $event->x - $self->{drag_start}{x} ) / $zoom * $ratio;
    my $offset_y =
      $offset->{y} + ( $event->y - $self->{drag_start}{y} ) / $zoom;
    ( $self->{drag_start}{x}, $self->{drag_start}{y} ) =
      ( $event->x, $event->y );
    $self->view->set_offset( $offset_x, $offset_y );
    my $new_offset = $self->view->get_offset;

    if ( not $self->{dnd_eligible} ) {
        return;
    }

    if (    _approximately( $new_offset->{x}, $offset_x )
        and _approximately( $new_offset->{y}, $offset_y ) )
    {
        # If there was a movement in the image, disable start of dnd until
        # mouse button is pressed again
        $self->{dnd_eligible} = FALSE;
        return;
    }

    # movement was clamped because of the edge, but did mouse move far enough?
    if (
        $self->view->drag_check_threshold(
            $self->{dnd_start}{x}, $self->{dnd_start}{y},
            $event->x,             $event->y
        )
        and $self->view->signal_emit(
            'dnd-start', $event->x, $event->y, $self->{button}
        )
      )
    {
        $self->{dragging} = FALSE;
    }
    return;
}

sub _approximately {
    my ( $a, $b ) = @_;
    return abs( $a - $b ) < $FLOAT_EPS;
}

sub cursor_type_at_point {
    my ( $self, $x, $y ) = @_;
    ( $x, $y ) = $self->view->to_image_coords( $x, $y );
    my $pixbuf_size = $self->view->get_pixbuf_size;
    if (    $x > 0
        and $x < $pixbuf_size->{width}
        and $y > 0
        and $y < $pixbuf_size->{height} )
    {
        if ( $self->{dragging} ) {
            return 'grabbing';
        }
        else {
            return 'grab';
        }
    }
    return;
}

1;