App-Chart
view release on metacpan or search on metacpan
lib/App/Chart/Gtk2/AnnDrag.pm view on Meta::CPAN
package App::Chart::Gtk2::AnnDrag;
use 5.008;
use strict;
use warnings;
use Gtk2 1.220;
use Gtk2::Ex::WidgetBits;
use App::Chart::Gtk2::Graph::Plugin::Alerts;
Gtk2->CHECK_VERSION(2,12,0)
or die "Need Gtk 2.12 or higher"; # for ->error_bell
use constant DEBUG => 0;
use Glib::Object::Subclass
'Gtk2::Object',
signals => { abort => { param_types => [],
return_type => undef,
flags => ['run-last','action'],
class_closure => \&_do_abort,
},
toggle_alert => { param_types => [],
return_type => undef,
flags => ['run-last','action'],
class_closure => \&_do_toggle_alert,
},
swap_ends => { param_types => [],
return_type => undef,
flags => ['run-last','action'],
class_closure => \&_do_swap_ends,
},
delete_element => { param_types => [],
return_type => undef,
flags => ['run-last','action'],
class_closure => \&_do_delete_element,
},
toggle_horizontal => { param_types => [],
return_type => undef,
flags => ['run-last','action'],
class_closure => \&_do_toggle_horizontal,
},
};
# priority level "gtk" treating this as widget level default, for overriding
# by application or user RC
Gtk2::Rc->parse_string (<<'HERE');
binding "App__Chart__Gtk2__AnnDrag_keys" {
bind "Escape" { "abort" () }
bind "a" { "toggle-alert" () }
bind "space" { "swap-ends" () }
bind "d" { "delete-element" () }
bind "h" { "toggle-horizontal" () }
}
class "App__Chart__Gtk2__AnnDrag" binding:gtk "App__Chart__Gtk2__AnnDrag_keys"
HERE
my $active = 0;
my $graph;
my $cursor;
my $drawn = 0;
my $wevents;
my $snooper;
my $orig_elem; # from database, or undef for new line
my $edit_elem;
use constant::defer init => sub {
$graph->signal_connect (motion_notify_event => \&_do_motion_notify_event);
$graph->signal_connect (button_release_event=> \&_do_button_release_event);
require Gtk2::Ex::WidgetCursor;
$cursor = Gtk2::Ex::WidgetCursor->new (widget => $graph,
cursor => 'left_ptr');
require Gtk2::Ex::WidgetEvents;
$wevents = Gtk2::Ex::WidgetEvents->new ($graph, ['key-press-mask',
'button-motion-mask',
'button-release-mask']);
require Gtk2::Ex::KeySnooper;
$snooper = Gtk2::Ex::KeySnooper->new;
return; # nothing to memoize
};
# start dragging in $graph of object nearest $event
sub start {
($graph, my $event) = @_; # global $graph
if ($active) { return; }
init ();
my $x = $event->x;
my $y = $event->y;
$orig_elem = find ($x, $y);
if ($orig_elem) {
$edit_elem = $orig_elem->clone;
$drawn = 1;
} else {
$edit_elem = App::Chart::Annotation::Line->new_for_graph ($graph, $x, $y);
$drawn = 0;
draw(1);
}
$active = 1;
$cursor->active (1);
$snooper->install (\&_do_key_snooper);
}
sub _stop {
$active = 0;
$cursor->active (0);
$snooper->remove;
}
sub done {
if (! $active) { return; }
if (DEBUG) { print "done\n"; }
_stop ();
draw (1);
}
sub abort {
goto &_do_abort;
}
sub _do_abort {
my ($self) = @_;
if (! $active) { return; }
_stop ();
draw (0);
$edit_elem = $orig_elem;
if ($edit_elem) {
draw(1);
}
}
sub delete_elem {
goto &_do_delete_element;
}
sub _do_delete_element {
my ($self) = @_;
if (! $active) { return; }
_stop();
draw (0);
if ($orig_elem) {
$orig_elem->delete;
}
}
sub _do_expose_event {
my ($graph, $event) = @_;
$drawn = 0;
draw (1, $event->region);
return Gtk2::EVENT_PROPAGATE;
}
sub _do_motion_notify_event {
my ($graph, $event) = @_;
my $x = $event->x;
my $y = $event->y;
if ($event->is_hint) {
($x, $y) = $event->window->get_pointer;
}
move ($x, $y);
return Gtk2::EVENT_PROPAGATE;
}
sub _do_button_release_event {
my ($graph, $event) = @_;
if (! $active) { # button release after Esc or D keyboard stop
return Gtk2::EVENT_PROPAGATE;
}
( run in 2.029 seconds using v1.01-cache-2.11-cpan-cdf2f3d4e48 )