File Coverage

blib/lib/Gtk2/Ex/Spinner/EntryWithCancel.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             package Gtk2::Ex::Spinner::EntryWithCancel;
2 1     1   596 use 5.008;
  1         4  
  1         37  
3 1     1   5 use strict;
  1         1  
  1         27  
4 1     1   5 use warnings;
  1         13  
  1         23  
5             # version 1.180 for perl subclass to override GInterfaces from superclass
6 1     1   1336 use Gtk2 1.180;
  0            
  0            
7              
8             our $VERSION = 5.1;
9              
10             use constant DEBUG => 0;
11              
12             use Glib::Object::Subclass
13             'Gtk2::Entry',
14             signals => { activate => \&_do_activate,
15             editing_done => \&_do_editing_done,
16             cancel => { param_types => [],
17             return_type => undef,
18             flags => [ 'action','run-last' ],
19             class_closure => \&_do_cancel,
20             },
21             },
22             interfaces => [ 'Gtk2::CellEditable' ],
23             properties => [ Glib::ParamSpec->boolean
24             ('editing-cancelled',
25             'editing-cancelled',
26             'True if editing was cancelled with Escape rather than activated with Return etc.',
27             0, # default
28             Glib::G_PARAM_READWRITE) ];
29              
30             # In GtkCellRendererText and the GtkEntry it creates the cancel is noticed
31             # by gtk_cell_editable_key_press_event() installed on key-press-event. Here
32             # it's through key bindings, in the interests of possible configurability.
33             #
34             # FIXME: Up and Down are specific to moving between view cells to end an
35             # edit, rather than an "edit with cancel" as such. Would it be better for
36             # Spinner::CellRenderer to give its created entry a widget name and
37             # establish bindings that way?
38             #
39             sub INIT_INSTANCE {
40              
41             # once only RC additions, done at first instance creation
42              
43             # priority level "gtk" treating this as widget level default, for
44             # overriding by application or user RC
45             Gtk2::Rc->parse_string (<<'HERE');
46             binding "Gtk2__Ex__Spinner__EntryWithCancel_keys" {
47             bind "Escape" { "cancel" () }
48             bind "Up" { "activate" () }
49             bind "Down" { "activate" () }
50             }
51             class "Gtk2__Ex__Spinner__EntryWithCancel"
52             binding:gtk "Gtk2__Ex__Spinner__EntryWithCancel_keys"
53             HERE
54             { no warnings; *INIT_INSTANCE = \&Glib::FALSE; }
55             }
56              
57             # if (DEBUG) {
58             # *SET_PROPERTY = sub {
59             # my ($self, $pspec, $newval) = @_;
60             # if (DEBUG) { print "EntryWithCancel: SET_PROPERTY ",$pspec->get_name,
61             # " ",(defined $newval ? $newval : 'undef'),"\n"; }
62             # $self->{$pspec->get_name} = $newval;
63             # };
64             # }
65              
66             # gtk_cell_editable_start_editing(), cf. gtk_entry_start_editing()
67             #
68             sub START_EDITING {
69             my ($self, $event) = @_;
70             if (DEBUG) { print "EntryWithCancel: START_EDITING\n"; }
71             $self->set ('editing-cancelled', 0);
72             $self->{'editing_active'} = 1;
73             }
74              
75             # 'editing-done' class closure, from GtkCellEditable interface
76             sub _do_editing_done {
77             my ($self) = @_;
78             $self->{'editing_active'} = 0;
79             return $self->signal_chain_from_overridden;
80             }
81              
82             # like gtk_cell_editable_entry_activated()
83             #
84             # In GtkEntry gtk_cell_editable_entry_activated() and
85             # gtk_cell_editable_key_press_event() are as a signal connections on self.
86             # Is there a reason for that? Seems easier to test a flag for when to act
87             # rather than connect and disconnect.
88             #
89             sub _do_activate {
90             my ($self) = @_;
91             if (DEBUG) { print "EntryWithCancel: _do_activate\n"; }
92             $self->set ('editing-cancelled', 0);
93             _emit_editing_done ($self, 0);
94             return $self->signal_chain_from_overridden;
95             }
96              
97             sub cancel {
98             my ($self) = @_;
99             $self->signal_emit ('cancel');
100             }
101              
102             # 'cancel' class closure
103             sub _do_cancel {
104             my ($self) = @_;
105             if (DEBUG) { print "EntryWithCancel: cancel signal\n"; }
106             $self->set ('editing-cancelled', 1);
107             _emit_editing_done ($self, 1); # if active
108             }
109              
110             sub _emit_editing_done {
111             my ($self, $cancelled) = @_;
112             if ($self->{'editing_active'}) {
113             $self->editing_done;
114             $self->remove_widget;
115             }
116             }
117              
118             1;
119             __END__