Gtk2

 view release on metacpan or  search on metacpan

examples/cellrenderer_popup.pl  view on Meta::CPAN

	# menu to start xpad from the left of the cell (just like the 
	# button graphic), and we'll start by centering it vertically.
	# got all that?
	my ($wx, $wy) = $treeview->get_bin_window->get_origin;
	my ($tx, $ty) = $treeview->tree_to_widget_coords($cell_area->x, $cell_area->y);
	my $visible = $treeview->get_visible_rect;

	$x = $wx + $visible->x + $tx + xpad;
	$y = $wy + $visible->y + $ty + $cell_area->height / 2 - 2;

	# center the menu vertically around the selected item.
	# this is inspired heavily by GtkOptionMenu.
	my $active = $menu->get_active;
	$y -= $active->get_child_requisition->height / 2 if $active;
	foreach my $i ($menu->get_children) {
		last if $i == $active;
		$y -= $i->get_child_requisition->height if $i->visible;
	}
	# play nicely with rtl languages
	if ($treeview->get_direction eq 'rtl') {
		$x = $wx + $tx + $cell_area->width -
			$menu->get_child_requisition->width;
	}
	return ($x, $y, 1);
}




sub editing_done {
	my ($item, $info) = @_;
	my ($cell, $editable) = @$info;
	$cell->signal_emit ('edited', $item->{path}, $item->{index});
	# see the evil trick description below
	$editable->remove_widget;
}

sub START_EDITING {
	my ($cell, $event, $widget, $path, $background_area, $cell_area, $flags) = @_;
	my $menu = Gtk2::Menu->new;
	my @data = @{ $cell->{list} };

	# this is an evil trick.  we're creating a custom widget and handling
	# the editing ourselves, but the higher level code only thinks we're
	# editing if we return an editable.  so we return an editable.  of
	# course, we have to remove it in the menu activate callbacks so that
	# it doesn't stick around.
	my $editable = Gtk2::Entry->new;

	for (my $i = 0 ; $i < @data ; $i++) {
		my $item = Gtk2::MenuItem->new ($data[$i]);
		$item->show;
		$menu->append ($item);
		$item->{path} = $path;
		$item->{index} = $i;
		$item->{text} = $data[$i];
		#$item->signal_connect (activate => \&editing_done, $cell);
		$item->signal_connect (activate => \&editing_done, [$cell, $editable]);
	}
	$menu->set_active ($cell->{index});
	$menu->popup (undef, undef,
	              \&menu_pos_func, [$widget, $cell_area],
	              $event ? $event->button : 0,
	              $event ? $event->time : 0);
	$item = $menu->get_active;
	$menu->select_item ($item) if $item;

	# see the evil trick mentioned above.
	$editable;
}


##########################################################################
# driver code
package main;

use Glib qw(FALSE TRUE);

$window = Gtk2::Window->new;
$window->set_title ('cell renderer test');
$window->signal_connect (delete_event => sub { Gtk2->main_quit; FALSE; });

$vbox = Gtk2::VBox->new;
$window->add ($vbox);

$label = Gtk2::Label->new;
$label->set_markup ('<big>F-Words</big>');
$vbox->pack_start ($label, FALSE, FALSE, 0);

# create and load the model
$model = Gtk2::ListStore->new ('Glib::String', 'Glib::Scalar', 'Glib::Int');
foreach ([ 'foo',        [qw/foo bar baz/]],
         [ 'fluffy',     [qw/muffy tuffy buffy willow/]],
         [ 'flurble',    [qw/murble swurble curble/]],
         [ 'frob',       [qw/blob clob plob mob rob gob glob wob dob/]],
         [ 'frobnitz',   [qw/fronbination that's sweepin' the nation/]],
	 [ 'repeated',   [qw/fronbination that's sweepin' the nation the the the the/]],
#	 [ 'none',       []],
#	 [ 'verymany',   [(1..50)]],
         [ 'ftang',      [qw/quisinart/]],
         [ 'fire truck', [qw/red white green yellow polka-dot/]]) {
	my $iter = $model->append;
	$model->set ($iter, 0, $_->[0], 1, $_->[1], 2, rand (@{$_->[1]}));
}


# now a view
$treeview = Gtk2::TreeView->new ($model);
$treeview->set_rules_hint (TRUE);
$treeview->set_reorderable (TRUE);


#
# regular editable text column for column 0, the string
#
$renderer = Gtk2::CellRendererText->new;
$renderer->set (editable => TRUE);;
$column = Gtk2::TreeViewColumn->new_with_attributes ('something', $renderer,
                                                     text => 0);
# this commits changes from the user's editing to the model.  compare and
# contrast with the one for the popup, below.
$renderer->signal_connect (edited => sub {
		my ($cell, $text_path, $new_text, $model) = @_;
		my $path = Gtk2::TreePath->new_from_string ($text_path);
		my $iter = $model->get_iter ($path);
		$model->set ($iter, 0, $new_text);
	}, $model);
$treeview->append_column ($column);

#
# text for col[1]
#
$renderer = Gtk2::CellRendererText->new;
$column = Gtk2::TreeViewColumn->new_with_attributes ('list', $renderer,);
# custom data func to show the list items from the scalar.
$column->set_cell_data_func ($renderer, sub {
		my ($tree_column, $cell, $model, $iter) = @_;
		my ($info) = $model->get ($iter, 1);
		$cell->set (text => "[".join(", ", @$info)."]");
	});
$treeview->append_column ($column);

#
# text for col[2]
#
$renderer = Gtk2::CellRendererText->new;
$column = Gtk2::TreeViewColumn->new_with_attributes ('index', $renderer,
                                                     text => 2);
$treeview->append_column ($column);

#
# custom cell renderer for cols 1 and 2, an editable popup menu
#
$renderer = Mup::CellRendererPopup->new;
$renderer->set (mode => 'editable');
$column = Gtk2::TreeViewColumn->new_with_attributes ('selector', $renderer,
                                                     list => 1,
						     'index' => 2,
						     );
# this handler commits the user's selection to the model.  compare with
# the one for the typical text renderer -- the only difference is a var name.
$renderer->signal_connect (edited => sub {
		my ($cell, $text_path, $new_index, $model) = @_;
		my $path = Gtk2::TreePath->new_from_string ($text_path);
		my $iter = $model->get_iter ($path);
		$model->set ($iter, 2, $new_index);
	}, $model);
$treeview->append_column ($column);


my $scroll = Gtk2::ScrolledWindow->new;
$scroll->set_policy ('never', 'automatic');
$scroll->add ($treeview);
$vbox->pack_start ($scroll, TRUE, TRUE, 0);

# since we have a scroller, we need to set some reasonable initial size.
# i'll set one that should have the window scroll a bit, to make sure we
# can easily test the popup behavior when the treeview is scrolled.
$window->set_default_size (-1, 150);

my $check = Gtk2::CheckButton->new ('_show boxes');
$check->set_active ($renderer->get ('show-box'));
$check->signal_connect (toggled => sub {
		$renderer->set (show_box => $check->get_active);
		$treeview->queue_draw;
});
$vbox->pack_start ($check, FALSE, FALSE, 0);

$window->show_all;

Gtk2->main;



( run in 0.587 second using v1.01-cache-2.11-cpan-364913b4093 )