FreezePane using Gtk2::TreeStore

Last month, I saw this nifty piece of code (from
muppet et al) in this list to create a freeze-pane
using Gtk2::TreeView.

I thought it will be cool to have a freezepane with a
Gtk2::TreeStore in place of Gtk2::ListStore. Also,
since we are talking about hierarchical data, I
thought it will be cool to use XML::Simple and build
the tree from a simple xml definition file.

Here is my code for that. This is my first
contribution to the 'free' world. I would love
feedback from you guys. (Assuming no one is annoyed by
a posting of code into the email list :) ). And may be
this can be included in the documentation/examples. 


Here it comes :
Tree data is contained in data.xml as follows
<Node Name="Food Products">
        <Node Name="Fruits">
                <Node Name="Apple"
                        Color = "Red"
                        Price = "100.00"
                        Taste = "Sweet"
                <Node Name="Lemon"
                        Color = "Yellow" 
                        Price = "78.10"
                        Taste = "Sour"
        <Node Name="Vegetables">
                <Node Name="Potato"
                        Color = "Brown" 
                        Price = "100.00"
                        Source = "Idaho"
                <Node Name="Onion"
                        Color = "Yellow" 
                        Taste = "Pungent"

And the code
use strict;
use warnings;
use constant TRUE => 1;
use constant FALSE => !TRUE;
use Gtk2 -init;
use XML::Simple;

# Read the xml file into a hash using the XML::Simple
my $tree_xml_file = 'data.xml';
my $data_tree = XMLin($tree_xml_file, forcearray =>

# Define the columns in the order to be seen
my $all_columns = [
        { ColumnName => 'Name' }, 
        { ColumnName => 'Color'},
        { ColumnName => 'Price'}, 
        { ColumnName => 'Taste'},
        { ColumnName => 'Source'}

# Let us choose to freeze the first column
my $frozen_columns = [$all_columns->[0]];

# Create two arrays for sending into the
Gtk2::TreeStore->new method
my @tree_store_full_types = map {'Glib::String'}
my @tree_store_frozen_types = map {'Glib::String'}

# Create the 'full' tree on the right side pane
my $tree_store_full =
my $tree_view_full =
my $column_count = 0;
for my $column (@$all_columns) {
        my $column_name =  $column->{ColumnName};
        my $column =
                                                $column_name, Gtk2::CellRendererText->new(),
text => $column_count);
        # Hide the first column
        # Ensure that the expander is fixed to the first
column (and hence is hidden too)
        if ($column_count == 0) {

# Create the single column tree for the left side pane
my $tree_store_frozen =
my $tree_view_frozen =
# There is only one column (the first column) in this
my $column_name =  $frozen_columns->[0]->{ColumnName};
my $column =
                                                $column_name, Gtk2::CellRendererText->new(),
text => 0);

# Synchronize the frozen-tree with the full-tree
$tree_view_frozen->signal_connect('row-expanded' =>
                        sub {
                                my ($view, $iter, $path) = @_;
$tree_view_frozen->signal_connect('row-collapsed' =>
                        sub {
                                my ($view, $iter, $path) = @_;

# Recursive function to actually create the tree                                
append_children($tree_view_full->get_model(), undef,
$data_tree, $all_columns);      
append_children($tree_view_frozen->get_model(), undef,
$data_tree, $frozen_columns);   

# Add the frozen-tree to the left side of the pane
my $paned = Gtk2::HPaned->new;
$paned->add1 ($tree_view_frozen);

# we set the vertical size request very small, and it
will fill up the
# available space when we set the default size of the
$tree_view_frozen->set_size_request (-1, 10);

# Add the full-tree to a scrolled window in the right
my $scroll = Gtk2::ScrolledWindow->new;
$scroll->add ($tree_view_full);
$paned->add2 ($scroll);

# Synchronize the scrolling
$tree_view_frozen->set(vadjustment =>

# Create a new window and add the pane into it
my $window = Gtk2::Window->new;
$window->signal_connect(destroy => sub {
Gtk2->main_quit; });
$window->set_default_size(300, 100);

# The obligatory recursive function to display the
# I don't know the performance implications of using
#   but it seems easy to write and understand
sub append_children {
        my ($tree_store, $iter, $data_tree, $columns) = @_;
        if ($data_tree) {               
                my $count = 0;          
                my $child_iter = $tree_store->append ($iter);
                for my $column(@$columns) {
                        my $column_name = $column->{ColumnName};
                        if ($data_tree->{$column_name}) {
                                $tree_store->set($child_iter, $count,
                foreach my $child(@{$data_tree->{'Node'}}) {
                        append_children($tree_store, $child_iter, $child,

Do you Yahoo!?
Friends.  Fun.  Try the all-new Yahoo! Messenger. 

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