File Coverage

blib/lib/Gtk2/Ex/Statusbar/MessageUntilKey.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             # Copyright 2008, 2009, 2010, 2011, 2012 Kevin Ryde
2              
3             # This file is part of Gtk2-Ex-WidgetBits.
4             #
5             # Gtk2-Ex-WidgetBits is free software; you can redistribute it and/or
6             # modify it under the terms of the GNU General Public License as published
7             # by the Free Software Foundation; either version 3, or (at your option) any
8             # later version.
9             #
10             # Gtk2-Ex-WidgetBits is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13             # Public License for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Gtk2-Ex-WidgetBits. If not, see .
17              
18             package Gtk2::Ex::Statusbar::MessageUntilKey;
19 1     1   30678 use 5.008;
  1         3  
  1         50  
20 1     1   5 use strict;
  1         1  
  1         29  
21 1     1   4 use warnings;
  1         1  
  1         37  
22 1     1   1513 use Gtk2;
  0            
  0            
23              
24             # WidgetBits 11 through 15 mistakenly had only $VERSION==1 here
25             our $VERSION = 48;
26              
27             sub message {
28             my ($class, $statusbar, $str) = @_;
29             $statusbar->{(__PACKAGE__)} ||= $class->_new($statusbar);
30             my $id = $statusbar->get_context_id(__PACKAGE__);
31             $statusbar->pop ($id);
32             $statusbar->push ($id, $str);
33             }
34              
35             # The alternative would be a single KeySnooper object and emission hook, and
36             # have it look through a list of statusbars with messages, maybe held in a
37             # Tie::RefHash::Weak. But normally there'll be just one or two statusbars,
38             # so aim for small and simple.
39             #
40             sub _new {
41             my ($class, $statusbar) = @_;
42              
43             require Scalar::Util;
44             require Gtk2::Ex::KeySnooper;
45             Scalar::Util::weaken (my $weak_statusbar = $statusbar);
46             return bless
47             { snooper => Gtk2::Ex::KeySnooper->new (\&_do_event, \$weak_statusbar),
48             emission_id => Gtk2::Widget->signal_add_emission_hook
49             (button_press_event => \&_do_button_hook, \$weak_statusbar)
50             }, $class;
51             }
52              
53             sub DESTROY {
54             my ($self) = @_;
55             Gtk2::Widget->signal_remove_emission_hook
56             (button_press_event => $self->{'emission_id'});
57             }
58              
59             sub remove {
60             my ($class_or_self, $statusbar) = @_;
61             ### MessageUntilKey remove: $statusbar->{(__PACKAGE__)}
62              
63             delete $statusbar->{(__PACKAGE__)} || return;
64             my $id = $statusbar->get_context_id(__PACKAGE__);
65             $statusbar->pop ($id);
66             }
67              
68             # KeySnooper handler, and called from button below
69             sub _do_event {
70             my ($widget, $event, $ref_weak_statusbar) = @_;
71             ### MessageUntilKey _do_event: $event->type
72              
73             # the snooper should be destroyed together with statusbar, but the button
74             # hook isn't, so check $ref_weak_statusbar hasn't gone away
75             #
76             # $statusbar->get_display() is the default display if not under a toplevel
77             # (it's never NULL or undef), which means events there will clear
78             # unparented statusbars. Not sure if that's ideal, but close enough for
79             # now.
80              
81             if ($event->type eq 'key-press' || $event->type eq 'button-press') {
82             if (my $statusbar = $$ref_weak_statusbar) {
83             if (! $widget->can('get_display')
84             || $widget->get_display == $statusbar->get_display) {
85             # call through object to allow for subclassing
86             if (my $self = $statusbar->{(__PACKAGE__)}) {
87             $self->remove ($statusbar);
88             }
89             }
90             }
91             }
92             return 0; # Gtk2::EVENT_PROPAGATE
93             }
94              
95             # 'button-press-event' signal emission hook
96             sub _do_button_hook {
97             my ($invocation_hint, $parameters, $ref_weak_statusbar) = @_;
98             my ($widget, $event) = @$parameters;
99             _do_event ($widget, $event, $ref_weak_statusbar);
100             return 1; # stay connected, remove() does any disconnect
101             }
102              
103             1;
104             __END__