[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Gtk2::SimpleList



I've attached a really, *really* rough attempt at providing a more
Perlish interface to Gtk2's MVC gubbins, in a similar way that
Gtk::HandyCList works.

In the couple of months that I've been playing with Gtk2 the extra
complexity in the new model has been getting right up my nose, since in
the vast majority of situations it simply isn't needed.

The attached file contains a module called Gtk2::SimpleList, some POD
documentation and a bit of code to test it.

Basically this is an RFC - I'd like to get an idea of how people want to
use/are using Gtk2 lists and how closely this might meet their needs.

Thanks,

Gavin.

-- 
Gavin Brown
e: gavin brown uk com
w: http://jodrell.net/
PGP/GPG key ID: 891D8FCA
#!/usr/bin/perl

package Gtk2::SimpleList;
use Gtk2;
use base 'Gtk2::TreeView';
use strict;

=pod

=head1 NAME

Gtk2::SimpleList - a simple list widget for Gtk2.

=head1 SYNOPSIS

	use Gtk2;
	use Gtk2::SimpleList;
	use strict;

	# create a new list widget:
	my $list = Gtk2::SimpleList->new;

	# tell it what columns we want:
	$list->set_columns(
		'Author',	'string',
		'title',	'string',
		'Read it?'	'boolean',
	);

	my $data = [
		[
			'Bruce Sterling',
			'Holy Fire',
			1,
		],
		[
			'L. Ron Hubbard',
			'Battlefield Earth',
			0,
		],
		[
			'Arthur C. Clarke',
			'Rendezvous with Rama',
			1
		]
		# and so on
	];

	# tell it to use this ref for data:
	$list->set_ref($data);

	# tell it to update its contents:
	$list->update;

	# add it to the rest of the application:
	$window->add($list);
	$window->show_all;
	Gtk2->main;

=head1 DESCRIPTION

Gtk2::SimpleList is an attempt to bury some of the complexity of Gtk2's
model-view-controller architecture behind a more Perl-ish interface.
Instead of manually constructing complex combinations of columns,
renderers and list stores you simply create a widget, tell it to look at
a data structure, and leave it at that. Any of the underlying complexity
that you might want to get your hands on is there, but in the majority
of cases it isn't needed.

This is a very early attempt - and will almost certainly be subject to
revision. There might also be some companion modules to handle tree
widgets and combined lists/trees in the future.

=head1 CONSTRUCTOR

	my $list = Gtk2::SimpleList->new;

Returns a new Gtk2::SimpleList instance, which is essentially a
Gtk2::TreeView.

	my $list = Gtk2::SimpleList->new_with_columns([COLDATA]);

Returns a new Gtk2::SimpleList instance, using the supplied C<COLDATA>
to create column data. The format for this data is shown below.

C<new_with_columns> is equivalent to:

	my $list = Gtk2::SimpleList->new;
	$list->set_columns([COLDATA]);

=cut

sub new {
	my $package = shift;
	my $self = $package->SUPER::new;
	bless($self, $package);
	return $self;
}

sub new_with_columns {
	my $package = shift;
	my @columns = @_;
	my $self = new($package);
	$self->set_columns(@columns);
	return $self;
}

=pod

=head1 METHODS

Gtk2::SimpleList inherits all the methods from its base class,
Gtk2::TreeView.

	$list->set_columns([COLDATA]);

This defines the columns for the list. You should supply an array of
values of the form

	(
		'Name0', 'Type',
		'Name1', 'Type',
		# ...and so on
	)

where 'Name' is a string containing the text to be used in the column
header. 'Type' can be one of 'string', 'uint' or 'boolean'.

=cut

sub set_columns {
	my ($self, @coldata) = @_;
	$self->{renderers} = {};
	$self->{columns} = {};
	my $colcount = 0;
	my @columns;
	while (scalar(@coldata) > 0) {
		my ($name, $type) = splice(@coldata, 0, 2);
		my ($renderer, $column);
		if (lc($type) eq 'boolean') {
			$renderer = Gtk2::CellRendererToggle->new;
			$column = Gtk2::TreeViewColumn->new_with_attributes($name, $renderer, active => $colcount);
		} else {
			$renderer = Gtk2::CellRendererText->new;
			$column = Gtk2::TreeViewColumn->new_with_attributes($name, $renderer, text => $colcount);
		}
		$colcount++;
		$self->append_column($column);
		$self->{renderers}{$name} = $renderer;
		$self->{columns}{$name} = $column;
		push(@columns, sprintf('Glib::%s', ucfirst(lc($type))));
	}
	$self->{store} = Gtk2::ListStore->new(@columns);
	$self->set_model($self->{store});
	return 1;
}

=pod

	$list->set_ref($dataref);

This tells the list to refer to the array referenced by $dataref when
generating its content. This array should be of the form

	@data = (
		$rowref0,
		$rowref1,
		$rowref2,
		# ...and so on
	);

where the $rowrefs are references to arrays of the form

	$rowref = [
		'value for the first column',
		'value for the second column',
		1 # for a boolean
	];

=cut

sub set_ref {
	my ($self, $ref) = @_;
	$self->{ref} = $ref;
	return 1;
}

=pod

	$list->update;

Tells the list to regenerate its content using the specified reference.

=cut

sub update {
	my $self = shift;
	$self->{store}->clear;
	foreach my $item (@{$self->{ref}}) {
		my @rows;
		for (my $i = 0 ; $i < scalar(@{$item}) ; $i++) {
			push(@rows, $i, @{$item}[$i]);
		}
		my $iter = $self->{store}->append;
		$self->{store}->set($iter, @rows);
	}
	return 1;
}

=pod

	$list->get_renderer($column_name);
	$list->get_column($column_name);

Respectively, return the GtkCellRenderer or GtkTreeViewColumn for
$column_name. These are useful if you want to tweak the properties of
the columns.

=cut

sub get_renderer {
	my ($self, $name) = @_;
	return $self->{renderers}{$name};
}

sub get_column {
	my ($self, $name) = @_;
	return $self->{columns}{$name};
}

package main;

use Gtk2;
use strict;

Gtk2->init;

my $data = [
	[
		'Ernest Hemingway',
		'For Whom The Bell Tolls',
		0,
		undef,
	],
	[
		'Oscar Wilde',
		'The Picture of Dorian Grey',
		1,
		'2003-08-17',
	],
	[
		'Margaret Atwood',
		'Oryx and Crake',
		0,
		undef,
	],
];

my $list = Gtk2::SimpleList->new;
$list->set_columns(
	'Author',	'string',
	'Title',	'string',
	'On loan',	'boolean',
	'Return date',	'string',
);

$list->set_ref($data);

$list->update;

my $scrwin = Gtk2::ScrolledWindow->new;
$scrwin->set_policy('automatic', 'automatic');

$scrwin->add_with_viewport($list);

my $button = Gtk2::Button->new('Update');
$button->signal_connect('clicked', sub {
	push(
		@{$data},
		[
			'James Heller',
			'Catch 22',
			0,
			undef,
		],
	);
	$list->update;
});

my $vbox = Gtk2::VBox->new;
$vbox->set_spacing(8);

$vbox->pack_start($scrwin, 1, 1, 0);
$vbox->pack_start($button, 0, 0, 0);

my $window = Gtk2::Window->new('toplevel');
$window->signal_connect('delete_event', sub { exit });
$window->set_border_width(8);
$window->set_default_size(400, 300);

$window->add($vbox);

$window->show_all;

Gtk2->main;

exit;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]