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. 

_Ofey

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>
        <Node Name="Vegetables">
                <Node Name="Potato"
                        Color = "Brown" 
                        Price = "100.00"
                        Source = "Idaho"
                />
                <Node Name="Onion"
                        Color = "Yellow" 
                        Taste = "Pungent"
                />      
        </Node>
</Node>

-----------------
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
module
my $tree_xml_file = 'data.xml';
my $data_tree = XMLin($tree_xml_file, forcearray =>
1);

# 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'}
@$all_columns;
my @tree_store_frozen_types = map {'Glib::String'}
@$frozen_columns;

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

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

# Synchronize the frozen-tree with the full-tree
$tree_view_frozen->signal_connect('row-expanded' =>
                        sub {
                                my ($view, $iter, $path) = @_;
                                $tree_view_full->expand_row($path,0);
                        }
                        );      
$tree_view_frozen->signal_connect('row-collapsed' =>
                        sub {
                                my ($view, $iter, $path) = @_;
                                $tree_view_full->collapse_row($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
window.
$tree_view_frozen->set_size_request (-1, 10);

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

# Synchronize the scrolling
$tree_view_frozen->set(vadjustment =>
$tree_view_full->get_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->add($paned);
$window->set_default_size(300, 100);
$window->show_all;
Gtk2->main;

# The obligatory recursive function to display the
tree
# I don't know the performance implications of using
recursion,
#   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,
$data_tree->{$column_name});
                        }
                        $count++;
                }
                foreach my $child(@{$data_tree->{'Node'}}) {
                        append_children($tree_store, $child_iter, $child,
$columns);
                }
        }
}




        
                
__________________________________
Do you Yahoo!?
Friends.  Fun.  Try the all-new Yahoo! Messenger.
http://messenger.yahoo.com/ 



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