#!/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 to create column data. The format for this data is shown below. C 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;