1#!/usr/bin/perl -w
2
3# $Id$
4
5use Gtk2::TestHelper tests => 46;
6use strict;
7
8##########################################################################
9# custom cell renderer
10package Mup::CellRendererPopup;
11
12use Test::More;
13
14use Glib::Object::Subclass
15	Gtk2::CellRendererText::,
16	;
17
18my %hits;
19
20sub INIT_INSTANCE { $hits{init}++; }
21
22sub GET_SIZE { $hits{size}++;  shift->SUPER::GET_SIZE (@_) }
23sub RENDER { $hits{render}++;  shift->SUPER::RENDER (@_) }
24sub ACTIVATE { $hits{activate}++;  shift->SUPER::ACTIVATE (@_) }
25sub START_EDITING { $hits{edit}++;  shift->SUPER::START_EDITING (@_) }
26
27##########################################################################
28# custom cell renderer in the style of 1.02x, to check for regressions of
29# backward compatibility.
30package Mup::CellRendererPopupCompat;
31
32use Test::More;
33
34use Glib::Object::Subclass
35	Gtk2::CellRendererText::,
36	;
37
38__PACKAGE__->_install_overrides;
39
40my %hits_compat;
41
42sub INIT_INSTANCE { $hits_compat{init}++; }
43
44sub on_get_size { $hits_compat{size}++;  shift->parent_get_size (@_) }
45sub on_render { $hits_compat{render}++;  shift->parent_render (@_) }
46sub on_activate { $hits_compat{activate}++;  shift->parent_activate (@_) }
47sub on_start_editing { $hits_compat{edit}++;  shift->parent_start_editing (@_) }
48
49##########################################################################
50# custom cell renderer with newly created entry in START_EDITING
51package My::CellRendererNewEntry;
52use strict;
53use warnings;
54use Glib::Object::Subclass 'Gtk2::CellRendererText';
55my %hits_newentry;
56sub INIT_INSTANCE { $hits_newentry{init}++; }
57sub GET_SIZE { $hits_newentry{size}++;  shift->SUPER::GET_SIZE (@_) }
58sub RENDER { $hits_newentry{render}++;  shift->SUPER::RENDER (@_) }
59sub ACTIVATE { $hits_newentry{activate}++;  shift->SUPER::ACTIVATE (@_) }
60sub START_EDITING { $hits_newentry{edit}++;
61                    my $entry = Gtk2::Entry->new;
62                    $entry->signal_connect (destroy => \&_editable_destroy);
63                    return $entry;
64                  }
65sub _editable_destroy { $hits_newentry{editable_destroy}++ }
66
67##########################################################################
68# driver code
69package main;
70
71my $window = Gtk2::Window->new;
72$window->set_title ('cell renderer test');
73$window->signal_connect (delete_event => sub { Gtk2->main_quit; 0; });
74
75my $vbox = Gtk2::VBox->new;
76$window->add ($vbox);
77
78my $label = Gtk2::Label->new;
79$label->set_markup ('<big>F-Words</big>');
80$vbox->pack_start ($label, 0, 0, 0);
81
82# create and load the model
83my $model = Gtk2::ListStore->new ('Glib::String', 'Glib::Scalar', 'Glib::Int');
84foreach (qw/foo fluffy flurble frob frobnitz ftang fire truck/) {
85	my $iter = $model->append;
86	$model->set ($iter, 0, $_);
87}
88
89# now a view
90my $treeview = Gtk2::TreeView->new ($model);
91
92#
93# custom cell renderer
94#
95ok (my $renderer = Mup::CellRendererPopup->new, 'Mup::CellRendererPopup->new');
96$renderer->set (mode => 'editable');
97$renderer->set (editable => 1);
98my $column = Gtk2::TreeViewColumn->new_with_attributes ('selector', $renderer,
99                                                        text => 0,);
100# this handler commits the user's selection to the model.  compare with
101# the one for the typical text renderer -- the only difference is a var name.
102$renderer->signal_connect (edited => sub {
103		my ($cell, $text_path, $new_text, $model) = @_;
104		my $path = Gtk2::TreePath->new_from_string ($text_path);
105		my $iter = $model->get_iter ($path);
106		$model->set ($iter, 2, $new_text);
107	}, $model);
108$treeview->append_column ($column);
109
110#
111# custom cell renderer, compat mode
112#
113ok (my $renderer_compat = Mup::CellRendererPopupCompat->new, 'Mup::CellRendererPopupCompat->new');
114$renderer_compat->set (mode => 'editable');
115$renderer_compat->set (editable => 1);
116my $column_compat = Gtk2::TreeViewColumn->new_with_attributes ('selector', $renderer_compat,
117                                                               text => 0,);
118# this handler commits the user's selection to the model.  compare with
119# the one for the typical text renderer -- the only difference is a var name.
120$renderer_compat->signal_connect (edited => sub {
121		my ($cell, $text_path, $new_text, $model) = @_;
122		my $path = Gtk2::TreePath->new_from_string ($text_path);
123		my $iter = $model->get_iter ($path);
124		$model->set ($iter, 2, $new_text);
125	}, $model);
126$treeview->append_column ($column_compat);
127
128#
129# new entry cell renderer
130#
131my $renderer_newentry = My::CellRendererNewEntry->new;
132$renderer_newentry->set (mode => 'editable');
133my $column_newentry = Gtk2::TreeViewColumn->new_with_attributes
134    ('new-entry', $renderer_newentry, text => 0,);
135$treeview->append_column ($column_newentry);
136
137#
138# plain core CellRendererText
139#
140my $renderer_text = Gtk2::CellRendererText->new;
141$renderer_text->set (editable => 1);
142my $column_text = Gtk2::TreeViewColumn->new_with_attributes
143    ('core-text', $renderer_text, text => 0,);
144$treeview->append_column ($column_text);
145
146##########################################################################
147
148$vbox->pack_start ($treeview, 1, 1, 0);
149
150$window->show_all;
151
152##########################################################################
153
154#
155# test the vfunc-involving stuff for all renderers
156#
157my $rect = Gtk2::Gdk::Rectangle->new (5, 5, 10, 10);
158my $event = Gtk2::Gdk::Event->new ("button-press");
159foreach my $r ($renderer, $renderer_compat, $renderer_newentry, $renderer_text) {
160	my @size = $r->get_size ($treeview, $rect);
161	is (@size, 4);
162	like($size[0], qr/^\d+$/);
163	like($size[1], qr/^\d+$/);
164	like($size[2], qr/^\d+$/);
165	like($size[3], qr/^\d+$/);
166
167	$r->render ($window->window, $treeview, $rect, $rect, $rect, [qw(sorted prelit)]);
168	ok(!$r->activate ($event, $treeview, "0", $rect, $rect, qw(selected)));
169
170	{
171	  my $editable = $r->start_editing ($event, $treeview, "0", $rect, $rect, qw(selected));
172	  isa_ok ($editable, "Gtk2::Entry");
173	  my $destroyed = 0;
174	  $editable->signal_connect (destroy => sub { $destroyed = 1 });
175	  undef $editable;
176	  is ($destroyed, 1,
177	      "editable from start_editing using $r destroyed when forgotten");
178	}
179}
180
181#
182# test the normal stuff just for one renderer
183#
184isa_ok ($renderer, "Gtk2::CellRenderer");
185
186$renderer->set_fixed_size (23, 42);
187is_deeply([$renderer->get_fixed_size], [23, 42]);
188
189SKIP: {
190	skip "editing_canceled is new in 2.4", 0
191		unless Gtk2->CHECK_VERSION (2, 4, 0);
192
193	my $renderer = Gtk2::CellRendererText->new;
194	$renderer->editing_canceled;
195}
196
197SKIP: {
198	skip "stop_editing is new in 2.6", 0
199		unless Gtk2->CHECK_VERSION (2, 6, 0);
200
201	my $renderer = Gtk2::CellRendererText->new;
202	$renderer->stop_editing (FALSE);
203}
204
205SKIP: {
206	skip 'new 2.18 stuff', 6
207		unless Gtk2->CHECK_VERSION(2, 18, 0);
208
209	my $renderer = Gtk2::CellRendererText->new;
210
211	$renderer->set_visible (TRUE);
212	ok ($renderer->get_visible);
213
214	$renderer->set_sensitive (TRUE);
215	ok ($renderer->get_sensitive);
216
217	$renderer->set_alignment (0.5, 0.5);
218	my ($x, $y) = $renderer->get_alignment;
219	delta_ok ($x, 0.5);
220	delta_ok ($y, 0.5);
221
222	$renderer->set_padding (23, 42);
223	($x, $y) = $renderer->get_padding;
224	is ($x, 23);
225	is ($y, 42);
226}
227
228##########################################################################
229
230run_main sub {
231	# set the cursor on the various columns, with editing mode on, to
232	# trigger the vfuncs
233	$treeview->set_cursor (Gtk2::TreePath->new_from_string ('0'),
234	                       $column, 1);
235	$treeview->set_cursor (Gtk2::TreePath->new_from_string ('0'),
236	                       $column_compat, 1);
237	$treeview->set_cursor (Gtk2::TreePath->new_from_string ('0'),
238	                       $column_newentry, 1);
239
240        # and not editing any more
241	$treeview->set_cursor (Gtk2::TreePath->new_from_string ('0'),
242	                       $column_text, 0);
243};
244
245
246is_deeply ([ sort keys %hits ], [ qw/edit init render size/ ], 'callbacks encountered');
247is_deeply ([ sort keys %hits_compat ], [ qw/edit init render size/ ], 'callbacks encountered');
248
249# one start_editing programmatically, and one from set_cursor of $treeview
250is ($hits_newentry{edit}, 2);
251is ($hits_newentry{editable_destroy}, 2,
252   'the otherwise unreferenced GtkEntry should be destroyed');
253
254__END__
255
256Copyright (C) 2003-2005, 2009 by the gtk2-perl team (see the file AUTHORS for the
257full list).  See LICENSE for more information.
258