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