#!/usr/bin/perl -w # ported from Tim-Philipp Meuller's Tree View tutorial, # http://scentric.net/tutorial/sec-custom-cell-renderers.html#sec-custom-cell-renderer-example-body # by muppet, 6 feb 04. # # This is based mainly on GtkCellRendererProgress # in GAIM, written and (c) 2002 by Sean Egan # (Licensed under the GPL), which in turn is # based on Gtk's GtkCellRenderer[Text|Toggle|Pixbuf] # implementation by Jonathan Blandford */ package Mup::CellRendererProgress; use strict; use warnings; use Glib qw(G_PARAM_READWRITE); use Gtk2; use Glib::Object::Subclass Gtk2::CellRenderer::, properties => [ Glib::ParamSpec->double ('percentage', 'Percentage', 'The fractional progress to display', 0.0, 1.0, 0.0, G_PARAM_READWRITE), ], ; sub INIT_INSTANCE { my $self = shift; $self->set (mode => 'inert', xpad => 2, ypad => 2); $self->{percentage} = 0.0; } # we'll use the default new, GET_PROPERTY and SET_PROPERTY provided by # Glib::Object::Subclass. # # calculate the size of our cell, taking into account padding and # alignment properties of parent. # use constant FIXED_WIDTH => 100; use constant FIXED_HEIGHT => 10; sub MAX { $_[0] > $_[1] ? $_[0] : $_[1] } sub GET_SIZE { my ($cell, $widget, $cell_area) = @_; my ($x_offset, $y_offset) = (0, 0); my $width = int ($cell->get ('xpad') * 2 + FIXED_WIDTH); my $height = int ($cell->get ('ypad') * 2 + FIXED_HEIGHT); if ($cell_area) { $x_offset = $cell->get ('xalign') * ($cell_area->width - $width); $x_offset = MAX ($x_offset, 0); $y_offset = $cell->get ('yalign') * ($cell_area->height - $height); $y_offset = MAX ($y_offset, 0); } return ($x_offset, $y_offset, $width, $height); } sub RENDER { my ($cell, $window, $widget, $background_area, $cell_area, $expose_area, $flags) = @_; # invoke GET_SIZE directly to avoid a lot of marshalling overhead. my ($x_offset, $y_offset, $width, $height) = $cell->GET_SIZE ($widget, $cell_area); my $state = $widget->has_focus ? 'active' : 'normal'; my ($xpad, $ypad) = $cell->get (qw(xpad ypad)); $width -= $xpad*2; $height -= $ypad*2; my $style = $widget->style; $style->paint_box ($window, 'normal', 'in', undef, $widget, "trough", $cell_area->x + $x_offset + $xpad, $cell_area->y + $y_offset + $ypad, $width - 1, $height - 1); $style->paint_box ($window, $state, 'out', undef, $widget, "bar", $cell_area->x + $x_offset + $xpad, $cell_area->y + $y_offset + $ypad, $width * $cell->{percentage}, $height - 1); } package main; use strict; use Glib qw(TRUE FALSE); use Gtk2 -init; my $liststore; my $increasing = TRUE; # direction of progress bar change use constant { COL_PERCENTAGE => 0, COL_TEXT => 1, NUM_COLS => 2, STEP => 0.01, }; sub increase_progress_timeout { my $renderer = shift; my $iter = $liststore->get_iter_first; # first and only row my $perc = $liststore->get ($iter, COL_PERCENTAGE); if ($perc > (1.0 - STEP) || ($perc < STEP && $perc > 0.0) ) { $increasing = (!$increasing); } if ($increasing) { $perc += STEP; } else { $perc -= STEP; } my $buf = sprintf '%u %%', $perc*100; $liststore->set ($iter, COL_PERCENTAGE, $perc, COL_TEXT, $buf); return TRUE; # Call again } sub create_view_and_model { $liststore = Gtk2::ListStore->new (qw(Glib::Double Glib::String)); my $iter = $liststore->append; $liststore->set ($iter, COL_PERCENTAGE, 0.5); # start at 50% my $view = Gtk2::TreeView->new ($liststore); my $renderer = Gtk2::CellRendererText->new; my $col = Gtk2::TreeViewColumn->new; $col->pack_start ($renderer, TRUE); $col->add_attribute ($renderer, text => COL_TEXT); $col->set_title ("Progress"); $view->append_column ($col); $renderer = Mup::CellRendererProgress->new; $col = Gtk2::TreeViewColumn->new; $col->pack_start ($renderer, TRUE); $col->add_attribute ($renderer, percentage => COL_PERCENTAGE); $col->set_title ("Progress"); $view->append_column ($col); Glib::Timeout->add (50, \&increase_progress_timeout); return $view; } my $window = Gtk2::Window->new; $window->set_default_size (150, 100); $window->signal_connect (delete_event => sub {Gtk2->main_quit}); my $view = create_view_and_model(); $window->add ($view); $window->show_all; Gtk2->main;