File Coverage

blib/lib/Gtk2/Ex/ComboBox/Enum.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             # Copyright 2010, 2011 Kevin Ryde
2              
3             # This file is part of Gtk2-Ex-ComboBoxBits.
4             #
5             # Gtk2-Ex-ComboBoxBits 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-ComboBoxBits 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-ComboBoxBits. If not, see .
17              
18             package Gtk2::Ex::ComboBox::Enum;
19 3     3   2720 use 5.008;
  3         11  
  3         118  
20 3     3   15 use strict;
  3         6  
  3         97  
21 3     3   15 use warnings;
  3         5  
  3         98  
22 3     3   16 use Carp;
  3         4  
  3         229  
23 3     3   2156 use Gtk2;
  0            
  0            
24             use Scalar::Util;
25             use Glib::Ex::SignalBits;
26             use Glib::Ex::EnumBits;
27             use Gtk2::Ex::ComboBoxBits 5; # v.5 for set_active_text() when no model
28              
29             # uncomment this to run the ### lines
30             #use Smart::Comments;
31              
32             our $VERSION = 32;
33              
34             use Glib::Object::Subclass
35             'Gtk2::ComboBox',
36             signals => { notify => \&_do_notify,
37             'nick-to-display'
38             => { param_types => ['Glib::String'],
39             return_type => 'Glib::String',
40             flags => ['action','run-last'],
41             class_closure => \&default_nick_to_display,
42             accumulator => \&Glib::Ex::SignalBits::accumulator_first_defined,
43             },
44             },
45             properties => [
46             # FIXME: default enum-type is undef but
47             # Glib::ParamSpec->gtype() comes out as 'Glib::Enum'
48             #
49             (Glib::ParamSpec->can('gtype')
50             ?
51             # gtype() new in Glib 2.10 and Perl-Glib 1.240
52             Glib::ParamSpec->gtype
53             ('enum-type',
54             'Enum type',
55             'The enum class to display.',
56             'Glib::Enum',
57             Glib::G_PARAM_READWRITE)
58             :
59             Glib::ParamSpec->string
60             ('enum-type',
61             'Enum type',
62             'The enum class to display.',
63             (eval {Glib->VERSION(1.240);1}
64             ? undef # default
65             : ''), # no undef/NULL before Perl-Glib 1.240
66             Glib::G_PARAM_READWRITE)),
67              
68             Glib::ParamSpec->string
69             ('active-nick',
70             'Active enum nick',
71             'The selected enum value, as its nick.',
72             (eval {Glib->VERSION(1.240);1}
73             ? undef # default
74             : ''), # no undef/NULL before Perl-Glib 1.240
75             Glib::G_PARAM_READWRITE),
76             ];
77              
78             use constant _COLUMN_NICK => 0;
79              
80             my $renderer = Gtk2::CellRendererText->new;
81             $renderer->set (ypad => 0);
82              
83             sub INIT_INSTANCE {
84             my ($self) = @_;
85              
86             $self->pack_start ($renderer, 1);
87             Scalar::Util::weaken (my $weak_self = $self);
88             $self->set_cell_data_func ($renderer, \&_cell_data, \$weak_self);
89             }
90             sub _cell_data {
91             my ($cellview, $renderer, $model, $iter, $ref_weak_self) = @_;
92             ### ComboBox-Enum _cell_data()
93             ### path: $model->get_path($iter)->to_string
94             ### nick: $model->get_value ($iter, _COLUMN_NICK)
95              
96             my $self = $$ref_weak_self || return;
97             my $nick = $model->get_value ($iter, _COLUMN_NICK);
98              
99             # can be called at the $store->append() stage, before nick stored
100             if (defined $nick) {
101             $nick = $self->signal_emit ('nick-to-display', $nick);
102             }
103             $renderer->set (text => $nick);
104             }
105              
106             sub GET_PROPERTY {
107             my ($self, $pspec) = @_;
108             my $pname = $pspec->get_name;
109             ### Enum GET_PROPERTY: $pname
110              
111             if ($pname eq 'active_nick') {
112             return $self->get_active_nick;
113             }
114             # $pname eq 'enum_type'
115             return $self->{$pname};
116             }
117              
118             sub SET_PROPERTY {
119             my ($self, $pspec, $newval) = @_;
120             my $pname = $pspec->get_name;
121             ### Enum SET_PROPERTY: $pname, $newval
122              
123             if ($pname eq 'enum_type') {
124             my $enum_type = $self->{$pname} = $newval;
125              
126             # preserve active by its nick, if new type has that value
127             # set_active() below will notify if the active changes, in particular to
128             # -1 if nick not known in the new enum_type
129             $newval = $self->get('active-nick');
130              
131             # Crib note: In gtk 2.4 believe set_model() doesn't accept NULL,
132             # including through set_property(), though a combobox starts out with
133             # NULL for the model. If $enum_type is unset then just clear the
134             # existing model, don't try to set undef.
135             #
136             my $model = $self->get_model;
137             if ($model) {
138             $model->clear;
139             }
140             if (defined $enum_type && $enum_type ne '') {
141             if (! $model) {
142             $model = Gtk2::ListStore->new ('Glib::String');
143             $self->set_model ($model);
144             }
145             my @nicks = map {$_->{'nick'}} Glib::Type->list_values($enum_type);
146             # if ($self->{'sort'}) {
147             # , $self->signal_emit('nick-to-display',$_->{'nick'})
148             # @nicks = sort {$a->[1] cmp $b->[1]} @nicks;
149             # }
150              
151             ### @nicks
152             foreach my $nick (@nicks) {
153             $model->set ($model->append, _COLUMN_NICK, $nick);
154             }
155             }
156             }
157              
158             # $pname eq 'active_nick'
159             $self->set_active_nick ($newval);
160             }
161              
162             sub get_active_nick {
163             my ($self) = @_;
164             my ($model, $iter);
165             return (($model = $self->get_model)
166             && ($iter = $self->get_active_iter)
167             && $model->get_value ($iter, _COLUMN_NICK));
168             }
169             sub set_active_nick {
170             my ($self, $nick) = @_;
171             Gtk2::Ex::ComboBoxBits::set_active_text ($self, $nick);
172             }
173              
174             sub default_nick_to_display {
175             my ($self, $nick) = @_;
176             my $enum_type;
177             return (($enum_type = $self->{'enum_type'})
178             && Glib::Ex::EnumBits::to_display ($enum_type, $nick));
179             }
180              
181             # 'notify' class closure
182             sub _do_notify {
183             my ($self, $pspec) = @_;
184             shift->signal_chain_from_overridden (@_);
185              
186             if ($pspec->get_name eq 'active') {
187             $self->notify ('active-nick');
188             }
189             }
190              
191             1;
192             __END__