| Gtk2-Ex-DateSpinner documentation | Contained in the Gtk2-Ex-DateSpinner distribution. |
Gtk2::Ex::DateSpinner::CellRenderer -- date cell renderer with DateSpinner for editing
use Gtk2::Ex::DateSpinner::CellRenderer;
my $renderer = Gtk2::Ex::DateSpinner::CellRenderer->new;
$treeviewcolumn->pack_start ($renderer, 0);
$treeviewcolumn->add_attribute ($renderer, text => 0);
$renderer->signal_connect (edited => sub { some_code() });
Gtk2::Ex::DateSpinner::CellRenderer is a subclass of
Gtk2::CellRendererText.
Gtk2::Object
Gtk2::CellRenderer
Gtk2::CellRendererText
Gtk2::Ex::DateSpinner::CellRenderer
DateSpinner::CellRenderer displays an ISO format YYYY-MM-DD date as a
text field. Editing the field presents both a Gtk2::Entry and a popup
Gtk2::Ex::DateSpinner.
+------------+
| 2008-06-14 |
+------------+
+-----------------------------------------------------+
| +------+ +----+ +----+ +----+ +------+ |
| | 2008 |^ | 6 |^ | 14 |^ Sat | Ok | |Cancel| |
| +------+v +----+v +----+v +----+ +------+ |
+-----------------------------------------------------+
The popup allows mouse clicks or arrow keys to increment or decrement the date components. This is good if you often just want to bump a date up or down a bit. And when you're displaying YYYY-MM-DD it makes sense to present it like that for editing. Of course there's a huge range of other ways you can display or edit a date, this is merely one.
The date to display, and edit, is taken from the renderer text property
and must be in YYYY-MM-DD format. A new edited value is passed to the
edited signal emitted from the renderer in the usual way (see
Gtk2::CellRenderer). Text renderer properties affect the display and
xalign in the renderer is copied to the Entry widget so it's left, right
or centred while editing the same as displayed (like CellRendererText
does).
Pressing Return in the fields accepts the values. Pressing Escape cancels the edit. Likewise the Ok and Cancel button widgets. The stock accelerators activate the buttons too, Alt-O and Alt-C in an English locale, though Return and Escape are much easier to remember.
Note you must set the editable property (per the base class
Gtk2::CellRendererText) to make the DateSpinner::CellRenderer editable,
otherwise nothing happens when you click. That property can be controlled
by the usual model column or data function mechanisms to make some rows
editable and others not.
$renderer = Gtk2::Ex::DateSpinner::CellRenderer->new (key=>value,...)Create and return a new DateSpinner::CellRenderer object. Optional key/value
pairs set initial properties as per Glib::Object->new. Eg.
my $renderer = Gtk2::Ex::DateSpinner::CellRenderer->new
(editable => 1);
DateSpinner::CellRenderer creates new a new entry widget and a new popup
window for each edit and both are destroyed on accept or cancel. This is
the same as the base CellRendererText does. It's a little wasteful, but
is normally fast enough for casual editing and it might save some memory in
between.
The code for the popup is in the Gtk2::Ex::DateSpinner::PopupForEntry
component. It's not loaded until the first edit and is only meant for
internal use as yet.
Gtk2::Ex::DateSpinner, Gtk2::CellRendererText
Gtk2-Perl examples/cellrenderer_date.pl does a similar display/edit
popping up a Gtk2::Calendar. See
Gtk2::Ex::Datasheet::DBI (Gtk2::Ex::Datasheet::DBI) for a version of it in
use.
Gtk2-Ex-DateSpinner is Copyright 2008, 2009, 2010 Kevin Ryde
Gtk2-Ex-DateSpinner is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Gtk2-Ex-DateSpinner is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Gtk2-Ex-DateSpinner. If not, see http://www.gnu.org/licenses/.
| Gtk2-Ex-DateSpinner documentation | Contained in the Gtk2-Ex-DateSpinner distribution. |
# Copyright 2008, 2009, 2010 Kevin Ryde # This file is part of Gtk2-Ex-DateSpinner. # # Gtk2-Ex-DateSpinner is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 3, or (at your option) any # later version. # # Gtk2-Ex-DateSpinner is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License along # 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 = 8; use constant DEBUG => 0; 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) = @_; if (DEBUG) { print "Renderer START_EDITING '$pathstr'\n"; print " 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,"\n"; } $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); if (DEBUG) { print " edit with $entry\n"; } { # 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); if (DEBUG) { $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; if (DEBUG) { print "DateSpinner::CellRenderer _do_entry_editing_done,", " cancelled ",($entry->{'editing_cancelled'}?"yes":"no"), "\n"; } my $cancelled = $entry->{'editing_cancelled'}; $self->stop_editing ($cancelled); if (! $cancelled) { $self->signal_emit ('edited', $self->{'pathstr'}, $entry->get_text); } } 1; __END__