#!/usr/bin/perl

use strict;

use Gtk2 -init;
use Glib qw/TRUE FALSE/;

my $window = Gtk2::Window->new( "toplevel" );
$window->signal_connect( "destroy", sub { Gtk2->main_quit(); } );

my $vbox = Gtk2::VBox->new( 0, 5 );

my $model = Gtk2::ListStore->new(
				    "Glib::String",
				    "Glib::String",
				    "Glib::Int"
				);

$model->set( $model->append, 0, "Hi", 1, "There", 2, 5 );

my $renderer_1 = Gtk2::CellRendererText->new;
$renderer_1->set( editable => TRUE );
$renderer_1->signal_connect( edited => sub { &process_editing( @_, 0 ); } );

my $renderer_2 = Gtk2::CellRendererText->new;
$renderer_2->set( editable => TRUE );
$renderer_2->signal_connect( edited => sub { &process_editing( @_, 1 ); } );

my $column_1 = Gtk2::TreeViewColumn->new_with_attributes(
							    "Some Text",
							    $renderer_1,
							    'text'	=> 0
							);

my $column_2 = Gtk2::TreeViewColumn->new_with_attributes(
							    "More Text",
							    $renderer_2,
							    'text'	=> 1
							);

my $combo_model = Gtk2::ListStore->new(
					"Glib::Int",
					"Glib::String"
				      );

foreach my $thingy (
			[ 1,	"one" ],
			[ 2,	"two" ],
			[ 3,	"three" ],
			[ 4,	"four" ],
			[ 5,	"five" ]
		   )
{
	$combo_model->set(
			    $combo_model->append,
			    0,		$$thingy[0],
			    1,		$$thingy[1]
			 );
}

my $renderer_3 = Gtk2::CellRendererCombo->new;

$renderer_3->set(
		    editable	=> TRUE,
		    text_column	=> 1,
		    has_entry	=> TRUE,
		    model	=> $combo_model
		);

$renderer_3->signal_connect( edited => sub { &process_editing( @_, 2 ); } );

my $column_3 = Gtk2::TreeViewColumn->new_with_attributes(
							    "A Combo",
							    $renderer_3,
							    text	=> 2
							);

$column_3->set_cell_data_func( $renderer_3, sub { &render_combo_cell( @_ ); } );

my $treeview = Gtk2::TreeView->new( $model );
$treeview->set_rules_hint( TRUE );

$treeview->append_column( $column_1 );
$treeview->append_column( $column_2 );
$treeview->append_column( $column_3 );


my $sw = Gtk2::ScrolledWindow->new( undef, undef );
$sw->set_shadow_type( "etched-in" );
$sw->set_policy( "never", "always" );

$sw->add( $treeview );

$vbox->pack_start( $sw, TRUE, TRUE, 0 );

my $button = Gtk2::Button->new( "Dump Values" );
$button->signal_connect( "clicked"	=> sub { &dump_values(@_); } );

$vbox->pack_start( $button, TRUE, TRUE, 0 );

$window->add( $vbox );
$window->show_all;

Gtk2->main;

sub process_editing {
    
    my ( $renderer, $text_path, $new_text, $columnno ) = @_;
    
    my $path = Gtk2::TreePath->new_from_string ($text_path);
    my $iter = $model->get_iter ($path);
    
    if ( $columnno == 2 ) { # Column 2 is a combo - we need to fetch the ID from the combo's model
	
	my $combo_model;
	
	$combo_model = $renderer->get("model");
	
	my $combo_iter = $combo_model->get_iter_first;
	my $found_match = FALSE;
	
	while ($combo_iter) {
		
		if ($combo_model->get($combo_iter, 1) eq $new_text) {
			$found_match = TRUE;
			$new_text = $combo_model->get( $combo_iter, 0 ); # It's possible that this is a bad idea
			last;
		}
		
		$combo_iter = $combo_model->iter_next($combo_iter);
		
	}
	
	# If we haven't found a match, default to a zero
	if ( !$found_match ) {
		$new_text = 0;
	}
	
    }
    
    $model->set( $iter, $columnno, $new_text);
    
}

sub dump_values {
    
    my $iter = $model->get_iter_first;
    
    print "Column 0 contains: " . $model->get( $iter, 0 ) . "\n";
    print "Column 1 contains: " . $model->get( $iter, 1 ) . "\n";
    print "Column 2 contains: " . $model->get( $iter, 2 ) . "\n";
    print "\n";
    
}

sub render_combo_cell {
	
	my ( $tree_column, $renderer, $model, $iter ) = @_;
	
	# Get the ID that represents the text value to display
	my $key_value = $model->get( $iter, 2 );
	
	# Loop through our combo's model and find a match for the above ID to get our text value
	my $combo_iter = $combo_model->get_iter_first;
	my $found_match = FALSE;
	
	while ($combo_iter) {
	    
	    if (
		    $combo_model->get( $combo_iter, 0 )
			&& $key_value
			&& $combo_model->get( $combo_iter, 0 ) == $key_value
	       )
	    {
		    $found_match = TRUE;
		    $renderer->set( text	=> $combo_model->get( $combo_iter, 1 ) );
		    last;
	    }
	    
	    $combo_iter = $combo_model->iter_next($combo_iter);
	    
	}
	
	# If we haven't found a match, default to displaying an empty value
	if ( !$found_match ) {
		$renderer->set( text	=> "" );
	}
	
}