File Coverage

blib/lib/Gtk2/Ex/DateSpinner/CellRenderer.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, 2013 Kevin Ryde
2              
3             # This file is part of Gtk2-Ex-DateSpinner.
4             #
5             # Gtk2-Ex-DateSpinner 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-DateSpinner is distributed in the hope that it will be useful, but
11             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13             # for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Gtk2-Ex-DateSpinner. If not, see .
17              
18             package Gtk2::Ex::DateSpinner::CellRenderer;
19 1     1   968 use 5.008;
  1         4  
  1         47  
20 1     1   7 use strict;
  1         3  
  1         41  
21 1     1   26 use warnings;
  1         2  
  1         38  
22 1     1   665 use Gtk2;
  0            
  0            
23              
24             our $VERSION = 9;
25              
26             use Glib::Object::Subclass
27             'Gtk2::CellRendererText';
28              
29             # gtk_cell_renderer_start_editing()
30             #
31             # Cannot use parent $self->SUPER::START_EDITING from Gtk2::CellRendererText
32             # to do the Gtk2::Entry creation because it sets that widget to stop editing
33             # on losing key focus (handler gtk_cell_renderer_text_focus_out_event()),
34             # which includes the switch away to the DateSpinner::PopupEntry window, the
35             # effect being to immediately stop editing when that window pops up.
36             #
37             # There doesn't seem to be an easy way to suppress that
38             # gtk_cell_renderer_text_focus_out_event() editing-done behaviour. Can't
39             # catch focus-out and not propagate it, as the GtkEntry code needs it.
40             #
41             sub START_EDITING {
42             my ($self, $event, $view, $pathstr, $back_rect, $cell_rect, $flags) = @_;
43             ### Renderer START_EDITING
44             ### $pathstr
45             ### back: $back_rect->x.",".$back_rect->y." ".$back_rect->width."x".$back_rect->width
46             ### cell: $cell_rect->x.",".$cell_rect->y." ".$cell_rect->width."x".$cell_rect->width
47              
48             $self->{'pathstr'} = $pathstr;
49              
50             # no frame and copy 'xalign' across, the same as CellRendererText does
51             my $entry = Gtk2::Entry->new;
52             $entry->set (has_frame => 0,
53             xalign => $self->get('xalign'));
54             $entry->signal_connect (key_press_event => \&_do_entry_key_press);
55             ### edit with: "$entry"
56              
57             {
58             # This is a hack for Gtk2-Perl 1.210 and earlier ensuring
59             # gtk2perl_cell_renderer_start_editing() doesn't see $entry with a
60             # refcount of 1, since it would increment that as a protection against
61             # premature destruction -- but then never decrement. If the refcount is
62             # 2 it leaves it alone.
63             Glib::Idle->add (sub { 0 }, # Glib::SOURCE_REMOVE
64             $entry);
65             }
66              
67             require Gtk2::Ex::DateSpinner::PopupForEntry;
68             Gtk2::Ex::DateSpinner::PopupForEntry->new (entry => $entry);
69              
70             my $value = $self->get('text');
71             $entry->set_text (defined $value ? $value : '');
72             $entry->select_region (0, -1);
73              
74             my $ref_weak_self = \$self;
75             require Scalar::Util;
76             Scalar::Util::weaken ($ref_weak_self);
77             $entry->signal_connect (editing_done => \&_do_entry_editing_done,
78             $ref_weak_self);
79              
80             # {
81             # $entry->signal_connect (destroy => sub {
82             # print "editable: destroy\n";
83             # });
84             # $entry->signal_connect (focus_out_event => sub {
85             # print "editable: focus_out_event\n";
86             # return 0; # Gtk2::EVENT_PROPAGATE
87             # });
88             # }
89              
90             $entry->show;
91             return $entry;
92             }
93              
94             # 'key-press-event' handler for Gtk2::Entry
95             # An Escape for cancelling the edit is noted in a flag.
96             # This is like gtk_cell_editable_key_press_event() notes in its (mis-spelt)
97             # "editing_canceled" field. Would prefer to look at that field, but it's
98             # private.
99             sub _do_entry_key_press {
100             my ($entry, $event) = @_;
101             if ($event->keyval == Gtk2::Gdk->keyval_from_name('Escape')) {
102             $entry->{'editing_cancelled'} = 1;
103             }
104             return 0; # Gtk2::EVENT_PROPAGATE
105             }
106              
107             # 'editing-done' handler on the Gtk2::Entry
108             #
109             sub _do_entry_editing_done {
110             my ($entry, $ref_weak_self) = @_;
111             my $self = $$ref_weak_self || return;
112             ### DateSpinner-CellRenderer _do_entry_editing_done() ...
113             ### cancelled: $entry->{'editing_cancelled'}
114              
115             my $cancelled = $entry->{'editing_cancelled'};
116             $self->stop_editing ($cancelled);
117             if (! $cancelled) {
118             $self->signal_emit ('edited', $self->{'pathstr'}, $entry->get_text);
119             }
120             }
121              
122             1;
123             __END__