Gtk2-Ex-DateSpinner
view release on metacpan or search on metacpan
lib/Gtk2/Ex/DateSpinner/CellRenderer.pm view on Meta::CPAN
# with Gtk2-Ex-DateSpinner. If not, see <http://www.gnu.org/licenses/>.
package Gtk2::Ex::DateSpinner::CellRenderer;
use 5.008;
use strict;
use warnings;
use Gtk2;
our $VERSION = 10;
use Glib::Object::Subclass
'Gtk2::CellRendererText';
# gtk_cell_renderer_start_editing()
#
# Cannot use parent $self->SUPER::START_EDITING from Gtk2::CellRendererText
# to do the Gtk2::Entry creation because it sets that widget to stop editing
# on losing key focus (handler gtk_cell_renderer_text_focus_out_event()),
# which includes the switch away to the DateSpinner::PopupEntry window, the
# effect being to immediately stop editing when that window pops up.
#
# There doesn't seem to be an easy way to suppress that
# gtk_cell_renderer_text_focus_out_event() editing-done behaviour. Can't
# catch focus-out and not propagate it, as the GtkEntry code needs it.
#
sub START_EDITING {
my ($self, $event, $view, $pathstr, $back_rect, $cell_rect, $flags) = @_;
### Renderer START_EDITING
### $pathstr
### back: $back_rect->x.",".$back_rect->y." ".$back_rect->width."x".$back_rect->width
### cell: $cell_rect->x.",".$cell_rect->y." ".$cell_rect->width."x".$cell_rect->width
$self->{'pathstr'} = $pathstr;
# no frame and copy 'xalign' across, the same as CellRendererText does
my $entry = Gtk2::Entry->new;
$entry->set (has_frame => 0,
xalign => $self->get('xalign'));
$entry->signal_connect (key_press_event => \&_do_entry_key_press);
### edit with: "$entry"
{
# This is a hack for Gtk2-Perl 1.210 and earlier ensuring
# gtk2perl_cell_renderer_start_editing() doesn't see $entry with a
# refcount of 1, since it would increment that as a protection against
# premature destruction -- but then never decrement. If the refcount is
# 2 it leaves it alone.
Glib::Idle->add (sub { 0 }, # Glib::SOURCE_REMOVE
$entry);
}
require Gtk2::Ex::DateSpinner::PopupForEntry;
Gtk2::Ex::DateSpinner::PopupForEntry->new (entry => $entry);
my $value = $self->get('text');
$entry->set_text (defined $value ? $value : '');
$entry->select_region (0, -1);
my $ref_weak_self = \$self;
require Scalar::Util;
Scalar::Util::weaken ($ref_weak_self);
$entry->signal_connect (editing_done => \&_do_entry_editing_done,
$ref_weak_self);
# {
# $entry->signal_connect (destroy => sub {
# print "editable: destroy\n";
# });
# $entry->signal_connect (focus_out_event => sub {
# print "editable: focus_out_event\n";
# return 0; # Gtk2::EVENT_PROPAGATE
# });
# }
$entry->show;
return $entry;
}
# 'key-press-event' handler for Gtk2::Entry
# An Escape for cancelling the edit is noted in a flag.
# This is like gtk_cell_editable_key_press_event() notes in its (mis-spelt)
# "editing_canceled" field. Would prefer to look at that field, but it's
# private.
sub _do_entry_key_press {
my ($entry, $event) = @_;
if ($event->keyval == Gtk2::Gdk->keyval_from_name('Escape')) {
$entry->{'editing_cancelled'} = 1;
}
return 0; # Gtk2::EVENT_PROPAGATE
}
# 'editing-done' handler on the Gtk2::Entry
#
sub _do_entry_editing_done {
my ($entry, $ref_weak_self) = @_;
my $self = $$ref_weak_self || return;
### DateSpinner-CellRenderer _do_entry_editing_done() ...
### cancelled: $entry->{'editing_cancelled'}
my $cancelled = $entry->{'editing_cancelled'};
$self->stop_editing ($cancelled);
if (! $cancelled) {
$self->signal_emit ('edited', $self->{'pathstr'}, $entry->get_text);
}
}
1;
__END__
=for stopwords renderer DateSpinner Gtk2-Ex-DateSpinner YYYY-MM-DD popup decrement Ok Eg Gtk2-Perl Ryde
=head1 NAME
Gtk2::Ex::DateSpinner::CellRenderer -- date cell renderer with DateSpinner for editing
=for test_synopsis my ($treeviewcolumn)
=head1 SYNOPSIS
use Gtk2::Ex::DateSpinner::CellRenderer;
my $renderer = Gtk2::Ex::DateSpinner::CellRenderer->new;
( run in 0.566 second using v1.01-cache-2.11-cpan-5a3173703d6 )