File Coverage

blib/lib/Renard/Incunabula/Frontend/Gtk3/Helper.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 1     1   429143 use Renard::Incunabula::Common::Setup;
  1         2  
  1         14  
2             package Renard::Incunabula::Frontend::Gtk3::Helper;
3             $Renard::Incunabula::Frontend::Gtk3::Helper::VERSION = '0.003';
4             # ABSTRACT: Collection of helper utilities for Gtk3 and Glib
5              
6              
7 1     1   9779 use Renard::Incunabula::Common::Types qw(Str);
  1         5  
  1         20  
8 1     1   1448 use Class::Method::Modifiers;
  1         1362  
  1         55  
9 1     1   1762 use Gtk3 -init;
  0            
  0            
10             use Function::Parameters;
11              
12             our $LOADED = 0;
13              
14             fun _scrolled_window_viewport_shim() {
15             # Note: The code below is marked as uncoverable because it only applies
16             # to a single version of GTK+ and thus is not part of the general
17             # coverage. The functionality that it adds is tested in other ways.
18             # uncoverable branch true
19             if( not Gtk3::CHECK_VERSION('3', '8', '0') ) {
20             # For versions of Gtk+ less than v3.8.0, we need to call
21             # `Gtk3::ScrolledWindow->add_with_viewport( ... )` so that the
22             # child widget gets placed in a viewport.
23             #
24             # Newer versions of Gtk+ automatically create the viewport when
25             # `Gtk3::ScrolledWindow->add( ... )` is called.
26             #
27             # See:
28             # - <https://developer.gnome.org/gtk3/3.6/GtkScrolledWindow.html>
29             # - <https://developer.gnome.org/gtk3/3.8/GtkScrolledWindow.html>
30             Class::Method::Modifiers::install_modifier
31             "Gtk3::ScrolledWindow",
32             around => add => fun(@) {
33             # uncoverable subroutine
34             my $orig = shift; # uncoverable statement
35             my $self = shift; # uncoverable statement
36             $self->add_with_viewport(@_); # uncoverable statement
37             }; # uncoverable statement
38             }
39             }
40              
41             fun _can_set_theme() {
42             # uncoverable branch true
43             return $^O ne 'MSWin32' && Gtk3::CHECK_VERSION('3', '20', '1');
44             }
45              
46             fun _set_theme( (Str) $theme_name ) {
47             # uncoverable subroutine
48             # uncoverable branch true
49             return unless _can_set_theme;
50              
51             my $adwaita = Gtk3::CssProvider::get_named('Adawaita')->to_string; # uncoverable statement
52             my $custom = Gtk3::CssProvider::get_named($theme_name)->to_string; # uncoverable statement
53             if( $adwaita ne $custom ) { # uncoverable statement
54             my $settings = Gtk3::Settings::get_default; # uncoverable statement
55             $settings->set_property('gtk-theme-name', $theme_name); # uncoverable statement
56             } else { # uncoverable statement
57             warn "Not able to find theme ${theme_name}.\n"; # uncoverable statement
58             } # uncoverable statement
59             }
60              
61              
62             fun _set_icon_theme( (Str) $icon_theme_name ) {
63             # uncoverable subroutine
64             # uncoverable branch true
65             return unless _can_set_theme;
66              
67             my $i = Gtk3::IconTheme->new; # uncoverable statement
68             $i->set_custom_theme($icon_theme_name); # uncoverable statement
69             my $n = $i->choose_icon_for_scale(['gtk-open'], 16, 1, 'no-svg'); # uncoverable statement
70             my $expected_path = qr,/$icon_theme_name/.*\Qgtk-open.png\E$,; # uncoverable statement
71             if ( defined $n && $n->get_filename =~ $expected_path ) { # uncoverable statement
72             my $settings = Gtk3::Settings::get_default; # uncoverable statement
73             $settings->set_property('gtk-icon-theme-name', # uncoverable statement
74             $icon_theme_name); # uncoverable statement
75             } else { # uncoverable statement
76             warn "Not able to find icon-theme ${icon_theme_name}.\n"; # uncoverable statement
77             } # uncoverable statement
78             }
79              
80             fun _setup_gtk() {
81             # stub out the GDL loading for now. Docking is not yet used.
82             ##Glib::Object::Introspection->setup(
83             ##basename => 'Gdl',
84             ##version => '3',
85             ##package => 'Gdl', );
86             }
87              
88             fun _gtk_box_shim() {
89             my $shim = fun(@) {
90             my $orig = shift;
91             my $self = shift;
92             my $widget = shift;
93             if( $widget->can('_gtk_widget') ) {
94             $orig->($self, $widget->_gtk_widget, @_);
95             } else {
96             $orig->($self, $widget, @_);
97             }
98             };
99             for my $method (qw(pack_start add)) {
100             Class::Method::Modifiers::install_modifier
101             "Gtk3::Box",
102             around => $method => $shim;
103             }
104             }
105              
106             sub import {
107             unless( $::LOADED ) {
108             _setup_gtk();
109             _scrolled_window_viewport_shim;
110             _gtk_box_shim;
111             #_set_theme('Flat-Plat');
112             #_set_icon_theme('Arc');
113             $::LOADED = 1;
114             }
115             return;
116             }
117              
118             # Note: :prototype($$) would help here, but is only possible on Perl v5.20+
119              
120             classmethod gval( $glib_typename, $value ) { ## no critic
121             # GValue wrapper shortcut
122             Glib::Object::Introspection::GValueWrapper->new('Glib::'.ucfirst($glib_typename) => $value);
123             }
124              
125             classmethod genum( $package, $sv ) {
126             Glib::Object::Introspection->convert_sv_to_enum($package, $sv);
127             }
128              
129             classmethod callback( $invocant, $callback_name, @args ) {
130             my $fun = $invocant->can( $callback_name );
131             $fun->( @args, $invocant );
132             }
133              
134             1;
135              
136             __END__
137              
138             =pod
139              
140             =encoding UTF-8
141              
142             =for stopwords gval genum
143              
144             =head1 NAME
145              
146             Renard::Incunabula::Frontend::Gtk3::Helper - Collection of helper utilities for Gtk3 and Glib
147              
148             =head1 VERSION
149              
150             version 0.003
151              
152             =head1 FUNCTIONS
153              
154             =head2 _setup_gtk
155              
156             fun _setup_gtk()
157              
158             Sets up any of the L<Glib::Object::Introspection>-based libraries needed for
159             the application.
160              
161             Currently loads nothing, but will load the Gnome Docking Library (C<libgdl>) in
162             the future.
163              
164             =head1 CLASS METHODS
165              
166             =head2 C<gval>
167              
168             classmethod gval( $glib_typename, $value )
169              
170             Given a L<Glib type name|https://developer.gnome.org/glib/stable/glib-Basic-Types.html>, wraps a
171             Perl value in an object that can be passed to other L<Glib>-based functions.
172              
173             =over 4
174              
175             =item *
176              
177             C<$glib_typename>
178              
179             The name of a type under the C<Glib::> namespace. For
180             example, passing in C<"int"> gives a wrapper to the C<gint>
181             C type which is known as C<Glib::Int> in Perl.
182              
183             =item *
184              
185             C<$value>
186              
187             The value to put inside the wrapper.
188              
189             =back
190              
191             See L<Glib::Object::Introspection::GValueWrapper> in
192             L<Glib::Object::Introspection> for more information.
193              
194             =head2 genum
195              
196             classmethod genum( $package, $sv )
197              
198             Returns an enumeration value of type C<$package> which contains the matching
199             enum value given in C<$sv> as a string.
200              
201             =over 4
202              
203             =item *
204              
205             C<$package>
206              
207             The package name of a L<Glib> enumeration.
208              
209             =item *
210              
211             C<$sv>
212              
213             A string representation of the enumeration value.
214              
215             =back
216              
217             For example, for
218             L<GtkPackType|https://developer.gnome.org/gtk3/stable/gtk3-Standard-Enumerations.html#GtkPackType>
219             enum, we set C<$package> to C<'Gtk3::PackType'> and C<$sv> to C<'GTK_PACK_START'>.
220             This can be passed on to other L<Glib::Object::Introspection> methods.
221              
222             =head2 callback
223              
224             classmethod callback( $invocant, $callback_name, @args )
225              
226             A helper function to redirect to other callback functions. Given an
227             C<$invocant> and the name of the callback function, C<$callback_name>, which is
228             defined in the package of C<$invocant>, calls that function with arguments
229             C<( @args, $invocant )>.
230              
231             For example, if we are trying to call the callback function
232             C<Target::Package::on_event_cb> and C<$target> is a blessed reference of type
233             C<Target::Package>, then by using
234              
235             Renard::Incunabula::Frontend::Gtk3::Helper->callback( $target, on_event_cb => @rest_of_args );
236              
237             effectively calls
238              
239             Target::Package::on_event_cb( @rest_of_args, $target );
240              
241             =head1 AUTHOR
242              
243             Project Renard
244              
245             =head1 COPYRIGHT AND LICENSE
246              
247             This software is copyright (c) 2017 by Project Renard.
248              
249             This is free software; you can redistribute it and/or modify it under
250             the same terms as the Perl 5 programming language system itself.
251              
252             =cut