#!/usr/bin/perl use strict; use warnings; use Glib qw(TRUE FALSE); use Gtk2 -init; my($numAdded)=0; my($win,$tree)=createWin(); Glib::Timeout->add(1000,sub {tickCB($tree)}); $win->show_all(); Gtk2->main(); # # Creates the widgets in the application. Returns the main # window and tree view. # sub createWin { my($win,$scroll,$tree,$model,$mustScroll); $win=new Gtk2::Window(); $win->set_default_size(250,300); $win->signal_connect(destroy => \&Gtk2::main_quit); $win->add($scroll=new Gtk2::ScrolledWindow()); $scroll->add($tree=new Gtk2::TreeView()); $tree->set_rules_hint(TRUE); $tree->insert_column_with_attributes(-1,'Goo', new Gtk2::CellRendererText(),text => 0); $tree->set_model($model= new Gtk2::ListStore('Glib::String')); $tree->signal_connect( size_allocate => sub {sizeCB(\$mustScroll,@_)}); $model->signal_connect( row_inserted => sub {rowCB(\$mustScroll,$tree,@_)}); $scroll->get_vadjustment()->signal_connect( value_changed => sub {$numAdded=0}); addWords($model,100); showLast($tree,\$mustScroll); return ($win,$tree); } # # Called at regular intervals to add more random "words" to # the bottom of the tree view. If the previous word was # visible beforehand, scrolls the tree view so the new # words are visible. # sub tickCB { my($tree)=@_; addWords($tree->get_model(),100); return TRUE; } # # Adds random "words" to the bottom of the tree view. # sub addWords { my($model,$numAdd)=@_; my(@cons)=grep !/[aeiou]/,'a' .. 'z'; for (1 .. $numAdd) { $model->set($model->append(),0, $cons[rand @cons] . 'oo'); $numAdded++; } } # # Scrolls the tree view so the last row is visible. # sub showLast { my($tree,$mustScroll)=@_; my($numRows)=$tree->get_model()->iter_n_children(undef); $tree->scroll_to_cell( new Gtk2::TreePath($numRows-1),undef,TRUE,0.0,1.0); $$mustScroll=TRUE; $numAdded=0; } # # Called each time the tree view is resized. This is where # we correct the scroll bar, moving it to the bottom if # appropriate. # sub sizeCB { my($mustScroll,$tree,$rect)=@_; showLast($tree,$mustScroll) if $$mustScroll; } # # Called each time a row is added to the model. # sub rowCB { my($mustScroll,$tree,$model,$path,$it)=@_; my($numRows)=$model->iter_n_children(undef); my($lastVis); if ($tree->realized()) { $lastVis=($tree->get_visible_range())[1]; $$mustScroll=$lastVis && $lastVis->get_indices() == $numRows-2-$numAdded; } else { $$mustScroll=TRUE; } }