File Coverage

blib/lib/Gtk2/Ex/ComboBox/PixbufType.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              
19              
20             # for-pixbuf-save ?
21             # insensitive or omit ?
22             # Glib::ParamSpec->object
23             # ('for-pixbuf-save',
24             # 'for-pixbuf-save',
25             # 'Blurb.',
26             # 'Gtk2::Gdk::Pixbuf',
27             # Glib::G_PARAM_READWRITE),
28             # if ($pname eq 'for_pixbuf_save') {
29             # Scalar::Util::weaken ($self->{$pname});
30             # }
31             # my $pixbuf = $self->{'for_pixbuf_save'};
32             # ,
33             # ($pixbuf ? ($pixbuf->get_width, $pixbuf->get_height) : ())
34              
35             # writable =>
36             # exclude_read_only =>
37             # include-read-only ?
38              
39             # always-select ?
40              
41             # set_active_from_filename
42              
43             # alphabetical ?
44              
45             # type or active-type ?
46             # active-format ?
47              
48             # $ptypecombo->order_first ('png', 'jpeg')
49             # $ptypecombo->order_last ('ico')
50              
51              
52             package Gtk2::Ex::ComboBox::PixbufType;
53 1     1   781 use 5.008;
  1         2  
  1         35  
54 1     1   4 use strict;
  1         2  
  1         30  
55 1     1   4 use warnings;
  1         1  
  1         32  
56 1     1   4 use Carp;
  1         1  
  1         63  
57 1     1   472 use Gtk2;
  0            
  0            
58             use Scalar::Util;
59             use List::Util qw(max);
60             use POSIX ();
61             use Gtk2::Ex::ComboBoxBits;
62             use Gtk2::Ex::PixbufBits 38; # v.38 for type_supports_size()
63              
64             # uncomment this to run the ### lines
65             #use Smart::Comments;
66              
67             our $VERSION = 32;
68              
69             if (0) {
70             # These are the type names as of Gtk 2.20, extend if there's more and
71             # want to translate their names.
72             #
73             # TRANSLATORS: These format names are localized in case a non-Latin script
74             # ought to be shown instead, or as well. Latin script languages will
75             # probably leave all unchanged as that should make them easiest for the
76             # user identify, even if a literal translation would result in a different
77             # abbreviation.
78             __('ANI');
79             __('BMP');
80             __('GIF');
81             __('ICNS');
82             __('ICO');
83             __('JPEG');
84             __('JPEG2000');
85             __('PCX');
86             __('PNG');
87             __('PNM');
88             __('QTIF');
89             __('RAS');
90             __('SVG');
91             __('TGA');
92             __('TIFF');
93             __('WBMP');
94             __('WMF');
95             __('XBM');
96             __('XPM');
97             }
98              
99             use Glib::Object::Subclass
100             'Gtk2::ComboBox',
101             signals => { notify => \&_do_notify },
102             properties => [ Glib::ParamSpec->string
103             ('active-type',
104             'Active pixbuf type',
105             'Gdk Pixbuf file save format, such as "png".',
106             (eval {Glib->VERSION(1.240);1}
107             ? undef # default
108             : ''), # no undef/NULL before Perl-Glib 1.240
109             Glib::G_PARAM_READWRITE),
110              
111             Glib::ParamSpec->int
112             ('for-width',
113             'for-width',
114             'Only show file formats which support this width.',
115             0, POSIX::INT_MAX(),
116             0,
117             Glib::G_PARAM_READWRITE),
118             Glib::ParamSpec->int
119             ('for-height',
120             'for-height',
121             'Only show file formats which support this height.',
122             0, POSIX::INT_MAX(),
123             0,
124             Glib::G_PARAM_READWRITE),
125              
126             ];
127              
128             use constant { _COLUMN_TYPE => 0, # arg string for gdk_pixbuf_save()
129             _COLUMN_DISPLAY => 1, # translated display string
130             };
131              
132             sub INIT_INSTANCE {
133             my ($self) = @_;
134              
135             my $renderer = Gtk2::CellRendererText->new;
136             $renderer->set (ypad => 0);
137             $self->pack_start ($renderer, 1);
138             $self->set_attributes ($renderer, text => _COLUMN_DISPLAY);
139              
140             $self->set_model (Gtk2::ListStore->new ('Glib::String', 'Glib::String'));
141             _update_model($self);
142             }
143              
144             sub GET_PROPERTY {
145             my ($self, $pspec) = @_;
146             my $pname = $pspec->get_name;
147             ### ComboBox-PixbufType GET_PROPERTY: $pname
148              
149             if ($pname eq 'active_type') {
150             my $iter;
151             return (($iter = $self->get_active_iter)
152             && $self->get_model->get_value ($iter, _COLUMN_TYPE));
153             }
154             # $pname eq 'for_width' or 'for_height' integers
155             return $self->{$pname} || 0;
156             }
157              
158             sub SET_PROPERTY {
159             my ($self, $pspec, $newval) = @_;
160             my $pname = $pspec->get_name;
161             ### ComboBox-PixbufType SET_PROPERTY: $pname, $newval
162              
163             if ($pname eq 'active_type') {
164             # because _COLUMN_TYPE==0
165             Gtk2::Ex::ComboBoxBits::set_active_text ($self, $newval);
166             ### active num now: $self->get_active
167             } else {
168             $self->{$pname} = $newval;
169             _update_model($self);
170             }
171             }
172              
173             # 'notify' class closure
174             sub _do_notify {
175             my ($self, $pspec) = @_;
176             if ($pspec->get_name eq 'active') {
177             $self->notify ('active-type');
178             }
179             }
180              
181             # Gtk2::Gdk::Pixbuf->$get_formats_method
182             # being either get_formats() or a fallback enough for the formats
183             # examinations below. The fallback includes an 'is_writable' to use the
184             # smaller _is_writable().
185             #
186             my $get_formats_method
187             = (Gtk2::Gdk::Pixbuf->can('get_formats') # new in Gtk 2.2
188             ? 'get_formats'
189             : sub { return ({ name => 'png',
190             is_writable => 1},
191             { name => 'jpeg',
192             is_writable => 1 }) });
193              
194             # _is_writable($format) returning bool
195             #
196             *_is_writable =
197             (exists((Gtk2::Gdk::Pixbuf->$get_formats_method)[0]->{'is_writable'})
198             ?
199             # 'is_writable' field, new in Perl-Gtk 1.240
200             sub {
201             my ($format) = @_;
202             ### _is_writable() using field
203             ### $format
204             return $format->{'is_writable'};
205             }
206             : do {
207             # Perl-Gtk 1.222 and earlier hard coded
208             #
209             my %is_writable = (png => 1, # Gtk 2.0 and 2.2
210             jpeg => 1,
211              
212             (Gtk2->check_version(2,4,0) # 2.4.0 for ico saving
213             ? () : (ico => 1)),
214              
215             (Gtk2->check_version(2,8,0) # 2.8.0 for bmp saving
216             ? () : (bmp => 1)),
217              
218             (Gtk2->check_version(2,10,0) # 2.10.0 for tiff saving
219             ? () : (tiff => 1)),
220             );
221             sub {
222             my ($format) = @_;
223             ### _is_writable() using fallback
224             ### $format
225             return $is_writable{$format->{'name'}};
226             }
227             });
228              
229             sub _update_model {
230             my ($self) = @_;
231             ### PixbufType _update_model()
232              
233             my $for_width = max (1, $self->get('for-width'));
234             my $for_height = max (1, $self->get('for-height'));
235             my @types =
236             grep {Gtk2::Ex::PixbufBits::type_supports_size($_,$for_width,$for_height)}
237             map {$_->{'name'}}
238             grep {_is_writable($_)}
239             Gtk2::Gdk::Pixbuf->$get_formats_method;
240              
241             # eg. 'png' => 'PNG'
242             my %display = map { $_ => uc($_) } @types;
243              
244             # translated descriptions
245             if (eval { require Locale::Messages }) {
246             foreach my $type (@types) {
247             $display{$type} = Locale::Messages::dgettext ('Gtk2-Ex-ComboBoxBits',
248             uc($display{$type}));
249             }
250             }
251              
252             # alphabetical by translated description
253             @types = sort { $display{$a} cmp $display{$b} } @types;
254              
255             my $type = $self->get('active-type');
256             my $model = $self->get_model;
257             $model->clear;
258             foreach my $type (@types) {
259             ### $type
260             ### display: $display{$type}
261             $model->set ($model->append,
262             _COLUMN_TYPE, $type,
263             _COLUMN_DISPLAY, $display{$type});
264             }
265              
266             # preserve existing setting
267             $self->set (active_type => $type);
268             }
269              
270             1;
271             __END__