/*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// matlib.cc
//
// Vincent LE PRINCE <vincentleprince@users.sourceforge.net>
// Copyright (C) 2000-2005 Vincent LE PRINCE
// This file is part of the TRUEVISION Package

//   This program is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation; either version 2 of the License, or
//   (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
//*******************************************************************************************
#include "include/matlib.h"
#include "include/matlist.h"
#include "include/preferences.h"
#include "config.h"
#include "include/tvio.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <zlib.h>
#include <algorithm>

const char *sep = "/";
bool compare_items( MatLibItem *item1, MatLibItem *item2 ) { return ( strcmp( item1->name, item2->name ) < 0 ) ? true : false; }
bool compare_nodes( MatLibNode *node1, MatLibNode *node2 ) { return ( strcmp( node1->name, node2->name ) < 0 ) ? true : false; }


//*******************************************************
// Material library tree node
//
// Represent a category of material
// ie a directory on the hard disk
//*******************************************************
app_objs *MatLibNode::app_ref = NULL;
GtkWidget *MatLibNode::tree_view = NULL;
GtkTreeStore *MatLibNode::tree_store = NULL;
GtkTreeSelection *MatLibNode::tree_selection = NULL;


//********************************************************
// Constructor
//
// Load the tree from a directory tree on filesystem
//********************************************************
MatLibNode::MatLibNode( char *syspath, char *hpath, char *nom, app_objs *appref )
{
	app_ref = appref;

	// Directory name
	if ( nom == NULL ) {
		// Root
		char *matlibname = _("Material Library");
		name = new char[ strlen(matlibname) +1 ];
		strcpy( name, matlibname );
	
		if ( syspath != NULL ) {
			systempath = new char[ strlen(syspath) + 1 ];
			strcpy( systempath, syspath );
		}
		else 
			systempath = NULL;
		if ( hpath != NULL ) {
			homepath = new char[ strlen(hpath) + 1 ];
			strcpy( homepath, hpath );
		}
		else homepath = NULL;
	}
	else {
		// SubNode
		int nsize = strlen( nom ) +2;
		name = new char[nsize-1];
		strcpy( name, nom );

		if ( syspath != NULL ) {
			systempath = new char[ strlen(syspath) + nsize ];
			strcpy( systempath, syspath );
			strcat( systempath, sep );
			strcat( systempath, nom );
		}
		else 
			systempath = NULL;
	
		if ( hpath != NULL ) {
			homepath = new char[ strlen(hpath) + nsize ];
			strcpy( homepath, hpath );
			strcat( homepath, sep );
			strcat( homepath, nom );
		}
		else 
			homepath = NULL;
	}

	// Load files and subdirectories list
	char *path[2] = { systempath, homepath };
	for ( int i = 0 ; i < 2 ; i++ ) {
		if ( path[i] == NULL ) 
			continue;
		int psize = strlen( path[i] ) + 2;
		DIR *dir = opendir( path[i] );
	 	if ( dir == NULL ) 
			continue;
	 	struct dirent *dp;
	 	do  {
	 		dp = readdir( dir );
	 		if ( dp == NULL ) 
				break;
	 		if ( dp->d_name[0] == '.' ) 
				continue;
	 		char *tmp = new char[ psize + strlen( dp->d_name )  ];
	 		strcpy( tmp, path[i] );
	 		strcat( tmp, sep );
	 		strcat( tmp, dp->d_name );
	 		
	 		DIR *subdir = opendir( tmp );
	 		if ( subdir == NULL ) {
		 		MatLibItem *item = new MatLibItem( tmp, dp->d_name, app_ref );	
		 		Children.push_back( item );
		 	}
			else {
		 		closedir( subdir );
		 		bool exist = false;
		 		for ( register unsigned int i = 0 ; i < SubNodes.size() ; i ++ )
		 			if ( !strcmp( SubNodes[i]->name, dp->d_name ) ) { 
						exist = true ; 
						break; 
					}
		 		if ( ! exist ) {	 			
			 		MatLibNode *node = new MatLibNode( path[0], path[1],  dp->d_name, app_ref );
			 		SubNodes.push_back( node );
			 	}
			}		 				 		
	 		delete tmp;
		 } while ( dp != NULL );
	closedir( dir );
	}
	
	// Sort the list
	sort( Children.begin(), Children.end(), compare_items );
	sort( SubNodes.begin(), SubNodes.end(), compare_nodes );
}


//*************************************************************
// Destructor
//
// Delete trees
//*************************************************************
MatLibNode::~MatLibNode()
{
// TREE !!
delete name;
if ( homepath != NULL ) delete homepath;
if ( systempath != NULL ) delete systempath;
}


//**************************************************************
// Add to tree
//
// Add the node to the tree view 
//**************************************************************
void MatLibNode::add_to_tree( GtkWidget *view, GtkTreeStore *store, GtkTreeSelection *selection, GtkTreeIter *parent )
{
	tree_view = view;
	tree_store = store;
	tree_selection = selection;

	if ( parent != NULL ) 
		gtk_tree_store_insert_before( tree_store, &node_iter, parent, NULL );
	else
		gtk_tree_store_append( tree_store, &node_iter, NULL );
	gtk_tree_store_set( tree_store, &node_iter, 0, name,  1, this, -1);

	for ( register unsigned int i = 0 ; i < SubNodes.size() ; i ++ )
		SubNodes[i]->add_to_tree( view, store, selection, &node_iter );
}


//*************************************************************
// Expand
//
// expand node ( for root )
//************************************************************
void MatLibNode::expand()
{
	GtkTreePath *path = gtk_tree_model_get_path( GTK_TREE_MODEL(tree_store), &node_iter );
	gtk_tree_view_expand_row( GTK_TREE_VIEW(tree_view), path, FALSE );
}


//*************************************************************
// Draw thumbs
//
// Draw thumbnail preview for each item
//************************************************************
void MatLibNode::draw_thumbs( GtkWidget *view, GtkListStore *store, GtkWidget *progress, GtkWidget *label )
{
	const char *mesg1 = N_("Display");
	char  *mesg = new char[ strlen( mesg1 ) + strlen(name) + 10 ];
	sprintf( mesg, " %s %s ...", mesg1, name );
	gtk_label_set_text(  GTK_LABEL(label), mesg );
	delete mesg;

	unsigned int node_size = Children.size();
	
	gtk_list_store_clear( store );

	for ( unsigned int i = 0 ; i < node_size		; i++ ) {
		Children[i]->draw_thumb( view, store );
		gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(progress), (float)i/(float)node_size );
		while ( gtk_events_pending() > 0 ) 
			gtk_main_iteration();
	}
		
	gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(progress), 0 );
	const char *mesg2 = N_("Node :");
	char  *mesg3 = new char[ strlen( mesg1 ) + strlen(name) + 50 ];
	sprintf( mesg3, " %s %s , %u materials", mesg2, name, node_size );
	gtk_label_set_text(  GTK_LABEL(label), mesg3 );
	delete mesg3;
}



//*******************************************************
// Material Library item
//*******************************************************
app_objs *MatLibItem::app_ref = NULL;

//******************************************************
// Constructor
//******************************************************
MatLibItem::MatLibItem( char *file, char *nom, app_objs *appref )
{
	app_ref = appref;
	path = new char[ strlen( file ) +1 ];
	strcpy( path, file );
	name = new char[ strlen( nom ) + 1 ];
	strcpy( name, nom );
	real_name = NULL;
	comment = NULL;
	author = NULL;
}

//******************************************************
// Destructor
//******************************************************
MatLibItem::~MatLibItem()
{
	delete path;
	delete name;
}


//*****************************************************
// Draw thumb
//
// Get the preview from material file and add it to icon view
//******************************************************
void MatLibItem::draw_thumb( GtkWidget *view, GtkListStore *store )
{
	// Get the preview buffer
	GdkPixbuf *image_buffer = NULL;
	
	// Open file and initialize
	bool has_preview = true;
	ifstream file( path, ios::binary );
	if ( ! file )  has_preview = false;
	char * tag = NULL;
	char *val = NULL;
	unsigned long size = 0;

	// read the material file
	do {
	    if ( !has_preview ) 
			break;
		tag = tvio_get_next_tag( file );
		if ( tag == NULL ) { 
			has_preview = false; 
			break; 
			}
	
		// Look for a preview tag
		if ( ! strcmp( "PREVIEW", tag ) ) {
      		do {
				val = tvio_get_next_val( file );
				if ( val == NULL ) 
					break;
				if ( ! strcmp( val, "SIZE" ) ) {
					size = tvio_get_value_as_int( file );
					continue;
				}
				if ( !strcmp( val, "DATA" ) ) {
					if ( size == 0 ) { 
						has_preview = false; 
						break; 
					}
					char *zdata = new char[ size+1 ];
					for ( unsigned long i = 0 ; i < size ; i ++ ) 
						zdata[i] = file.get();
					unsigned long destlen = 19200;
					data = new char[ destlen ];
					if ( uncompress( (Bytef*)data, (uLongf*)&destlen, (Bytef*)zdata, size ) != Z_OK ) 	{ 
						has_preview= false; 
						break; 
					}
					image_buffer = gdk_pixbuf_new_from_data( (guchar*)data, GDK_COLORSPACE_RGB, FALSE, 8, 80, 80, 79*3, (sign_thumb_data_free), this );
					delete zdata;
					break;
				}
			} while( val != NULL );
			break;
			tvio_skip_section( file );	
		}
	
		if ( !strcmp( tag, "MATERIAL" ) ) {
			has_preview = false;
			break;
		}
		
		tvio_skip_section( file );
  	}  while( tag != NULL );
	file.close();

	// If we don't have a preview use a default icon
	if ( !has_preview ) { 
		char *fname = tv_get_pixmap( "nopreview.xpm" );
		image_buffer = gdk_pixbuf_new_from_file( fname, NULL );
		delete fname;
		}

	// Get the name of the material		
	int len = strlen( name );
	char labtext[ len +1 ];
	strcpy( labtext, name );
	labtext[ len - 4 ] = '\0';

	GtkTreeIter node_iter;
	gtk_list_store_append( store, &node_iter );
	gtk_list_store_set( store, &node_iter, 0, image_buffer, 1, labtext, 2, this, -1);
}


//***********************************************************
// Load 
//
// Load the material contained in the material file pointed by item
//***********************************************************
void MatLibItem::load()
{
	MATLIST_DEF
	matlist->mat_load_from_file( path );
}


//***********************************************************
// Show infos
//
// Display informations about the material
//***********************************************************
void MatLibItem::show_info(TvWidget_entry *name_label, TvWidget_entry *author_label, TvWidget_text *description  )
{
	ifstream file( path, ios::binary );
	if ( ! file )  return;
	char * tag = NULL;
	char *val = NULL;

	do {
		tag = tvio_get_next_tag( file );
	
		if ( tag == NULL ) { break; }
	 	if (author_label->load( file , tag ) )  continue;
		if (description->load( file , tag ) ) continue;		
	
	    if ( ! strcmp( "MATERIAL", tag ) ) {
      		do {
				val = tvio_get_next_tag( file );
				if ( val == NULL ) 
					break;
				if (name_label->load( file , val ) ) 
					continue;	
				tvio_skip_section( file );				
			} while( val != NULL );
		}
    	
    	if ( ! strcmp( "PREVIEW", tag ) ) {
    	  	do {
				val = tvio_get_next_val( file );
				if ( val == NULL ) 
					break;
				if ( ! strcmp( val, "SIZE" ) ) {
					int size = tvio_get_value_as_int( file );
					file.seekg( size+6, ios::cur );
					break;
				}
			} while( val != NULL );
			tvio_skip_section( file );	
			continue;
		}

		tvio_skip_section( file );
  	} while( tag != NULL );
	
	file.close();
	author_label->update_widget();
	name_label->update_widget();
	description->update_widget();
}



//*******************************************************
// The Material library
//*******************************************************

//******************************************************
// Constructor
//******************************************************
MatLib::MatLib( app_objs *appref )
{
	// Initialisations
	app_ref = appref;
	app_ref->matlib = this;
	dialog = NULL;
	PREF_DEF
	freeze = false;

	// Path to system wide material repository
	char *tmp = tv_get_data( "truevision/materials" );

	if ( tmp != NULL ) {
		systemlib = new char[strlen( tmp ) + 1];
		strcpy( systemlib, tmp );
		delete tmp;
	}
	else 
		systemlib = NULL;
	
	// Path to user material repository
	char *home = pref->get_home_dir();
	if ( home != NULL ) {
		homelib = new char[ strlen(pref->get_home_dir()) + 12 ];
		strcpy( homelib, pref->get_home_dir() );
		strcat( homelib, "/materials" );
		if ( access( homelib, F_OK ) == -1 ) 
			mkdir( homelib, S_IRWXU );
	}
	else 
		homelib = NULL;

	// Create the material tree :)
	root = new MatLibNode( systemlib, homelib, NULL, app_ref );
}

//******************************************************
// Destructor 
//******************************************************
MatLib::~MatLib()
{
	if ( homelib != NULL ) delete homelib;
	if ( systemlib != NULL ) delete systemlib;
	delete root;
}


//**********************************************************
// Raise dialog box
//
// open the material library dialog box 
//**********************************************************
void MatLib::raise_dlg_box()
{
	// Show it if already exists
	if ( GTK_IS_DIALOG(dialog) ) {
		gdk_window_raise( dialog->window );
		return;
	}
	PREF_DEF
	bool tt = pref->tooltips->value();

	// Create the dialog box
	dialog =  gtk_dialog_new_with_buttons( _("Material Library"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_HELP, GTK_RESPONSE_HELP, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,NULL );
	g_signal_connect( G_OBJECT(dialog), "response", G_CALLBACK(sign_matlib_dlg_click), this );
	g_signal_connect( G_OBJECT(dialog), "close", G_CALLBACK(sign_matlib_dlg_destroy), this );
	
	// restore geometry if wanted
	if ( pref->save_dlg_geo->value() ) {
		if ( pref->mlib_xpos->value() < 0 ) 
			pref->mlib_xpos->set(0);
		if ( pref->mlib_ypos->value() < 0 ) 
			pref->mlib_ypos->set(0);	
		gtk_widget_set_uposition( dialog, pref->mlib_xpos->value(), pref->mlib_ypos->value() );
		gtk_window_set_default_size( GTK_WINDOW(dialog), pref->mlib_xsize->value(), pref->mlib_ysize->value() );
	}

	GtkWidget *hbox = gtk_hbox_new( FALSE, 2 );
	gtk_box_pack_start( GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 2 );

	// The selection tree
	GtkWidget *scrolled = gtk_scrolled_window_new( NULL, NULL );
	gtk_widget_set_usize( scrolled, 250, -1 );
	gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
	gtk_box_pack_start( GTK_BOX(hbox), scrolled, FALSE, TRUE, 4 );
	material_tree_store = gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER, -1 );
	material_tree_view = gtk_tree_view_new_with_model( GTK_TREE_MODEL(material_tree_store) );
	gtk_container_add( GTK_CONTAINER(scrolled), material_tree_view );

	GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
	GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ( N_("Categories"), renderer, "text", 0, NULL);
	gtk_tree_view_append_column( GTK_TREE_VIEW(material_tree_view), column );
	
	material_tree_selection = gtk_tree_view_get_selection( GTK_TREE_VIEW (material_tree_view) );
	gtk_tree_selection_set_mode ( material_tree_selection, GTK_SELECTION_SINGLE );
	g_signal_connect( G_OBJECT(material_tree_selection), "changed", G_CALLBACK(sign_matlib_tree_select), this );
	gtk_signal_connect( GTK_OBJECT(material_tree_view), "row-activated", GTK_SIGNAL_FUNC(sign_matlib_tree_doubleclick), this );
	
	root->add_to_tree( material_tree_view, material_tree_store, material_tree_selection, NULL ); 	

	// Icon view
	GtkWidget *vbox = gtk_vbox_new( FALSE, 3 );
	gtk_box_pack_start( GTK_BOX(hbox), vbox, TRUE, TRUE, 2 );
	GtkWidget *iframe = gtk_frame_new( NULL );
	gtk_box_pack_start( GTK_BOX(vbox), iframe, TRUE, TRUE, 4 );	
	GtkWidget *ibox = gtk_vbox_new( FALSE, 3 );
	gtk_container_set_border_width( GTK_CONTAINER(ibox), 3 );
	gtk_container_add( GTK_CONTAINER(iframe), ibox );

	// Thumbs
	scrolled = gtk_scrolled_window_new( NULL, NULL );
	gtk_widget_set_usize( scrolled, 600, 280 );
	gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
	gtk_box_pack_start( GTK_BOX(ibox), scrolled, TRUE, TRUE, 4 );
	material_icon_store = gtk_list_store_new( 3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, -1 );
	material_icon_view = gtk_icon_view_new_with_model( GTK_TREE_MODEL(material_icon_store) );
	gtk_container_add( GTK_CONTAINER(scrolled), material_icon_view );
	gtk_icon_view_set_text_column( GTK_ICON_VIEW(material_icon_view), 1 );
	gtk_icon_view_set_pixbuf_column( GTK_ICON_VIEW(material_icon_view), 0 );

	gtk_icon_view_set_selection_mode ( GTK_ICON_VIEW(material_icon_view), GTK_SELECTION_MULTIPLE );
	gtk_signal_connect( GTK_OBJECT(material_icon_view), "selection-changed", GTK_SIGNAL_FUNC(sign_matlib_icon_select), this );
	gtk_signal_connect( GTK_OBJECT(material_icon_view), "item-activated", GTK_SIGNAL_FUNC(sign_matlib_icon_doubleclick), this );

	// Statusbar
	GtkWidget *stat_box = gtk_hbox_new( FALSE, 2 );
	gtk_box_pack_start( GTK_BOX(ibox), stat_box, FALSE, TRUE, 2 );	
	progress_bar = gtk_progress_bar_new( );
	gtk_box_pack_start( GTK_BOX(stat_box), progress_bar, FALSE, TRUE, 2 );	
	label = gtk_label_new( NULL );
	gtk_box_pack_start( GTK_BOX(stat_box), label, FALSE, TRUE, 2 );	
	
	// Description
	GtkWidget *dframe = gtk_frame_new( NULL );
	gtk_box_pack_start( GTK_BOX(vbox), dframe, FALSE, TRUE, 4 );	
	GtkWidget *dbox = gtk_vbox_new( FALSE, 5 );
	gtk_container_set_border_width( GTK_CONTAINER(dbox), 3 );
	gtk_container_add( GTK_CONTAINER(dframe), dbox );
		name_label = new TvWidget_entry( 	 _("Name"), "NAME", NULL, app_ref );
		name_label->get_widget( dbox, tt );
	
	author_label = new TvWidget_entry( _("Author"), "AUTHOR", NULL, app_ref );
	author_label ->get_widget( dbox, tt );

	description = new TvWidget_text( _("Comment"), "COMMENT", NULL, app_ref );
	description->get_widget( dbox, tt );
	
	gtk_widget_show_all(dialog);
	root->expand();
	root->select();
}


//***********************************************************
// Dialog clicked
//
// Dialog box callback
//**********************************************************
void MatLib::clicked_dlg( int button )
{
	switch( button ) {
		// Load & Close			
		case GTK_RESPONSE_OK:
			load_selection();
			clicked_dlg( -1 );
			break;
		
		// Load ( apply )
		case GTK_RESPONSE_APPLY:
			load_selection();	
			break;

		// Help
		case GTK_RESPONSE_HELP:
			truevision_help_display( "truevision.xml",  "sect-gui-matlibrary", NULL );
			break;
	
		// Close
		default:
		case GTK_RESPONSE_CLOSE:
			PREF_DEF
			if ( pref->save_dlg_geo->value() ) {
				gint x,y;
				gdk_window_get_root_origin( dialog->window, &x, &y );
				pref->mlib_xpos->set( x );
				pref->mlib_ypos->set( y );
				pref->mlib_xsize->set( dialog->allocation.width );
				pref->mlib_ysize->set( dialog->allocation.height );
			}
			gtk_widget_destroy( dialog );
			delete name_label;
			delete author_label;
			delete description;
			dialog = NULL;
			break;
	}
}

  			
//*******************************************************************
// Tree clicked
//
// Tree selection callback
//*******************************************************************
void MatLib::tree_select( GtkTreeSelection *selection )
{
	// Check if tree is currently freezed ( in update )
	if ( freeze ) 
		return;
	freeze = true;
	
	GtkTreeIter iter;
	GtkTreeModel *model;
	gpointer node_pointer = NULL;
	if (gtk_tree_selection_get_selected (selection, &model, &iter))
	    gtk_tree_model_get (model, &iter, 1, &node_pointer, -1);
	if ( node_pointer == NULL ) return;

	selected_node = (MatLibNode*)node_pointer;

	selected_node->draw_thumbs( material_icon_view, material_icon_store, progress_bar, label );

	while ( gtk_events_pending() > 0 ) 
		gtk_main_iteration();
	freeze = false;
}

//*******************************************************************
// Tree double clicked
//
// Tree ctivation callback : collapse / expand node
//*******************************************************************
void MatLib::tree_doubleclick()
{
	GtkTreeIter iter;
	GtkTreeModel *model;
	gtk_tree_selection_get_selected (material_tree_selection, &model, &iter);
	GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
	if ( path == NULL ) 
		return;
	bool isexp = gtk_tree_view_row_expanded( GTK_TREE_VIEW(material_tree_view), path );
	if ( isexp ) 
		gtk_tree_view_collapse_row( GTK_TREE_VIEW(material_tree_view), path );			
	else
		gtk_tree_view_expand_row( GTK_TREE_VIEW(material_tree_view), path, FALSE );
}
	
	
//*******************************************************************
// Icon select
//
// Material selection callback
//*******************************************************************
void MatLib::icon_select(  )
{
	// Get first item in selection
	GList *list = gtk_icon_view_get_selected_items( GTK_ICON_VIEW(material_icon_view) );
	list = g_list_first( list );
	if ( list == NULL ) return;
	GtkTreePath *path = (GtkTreePath*)list->data;
	GtkTreeIter iter;
	gtk_tree_model_get_iter( GTK_TREE_MODEL(material_icon_store), &iter, path );	
	gpointer matitem_ptr;
	MatLibItem *selection = NULL;
	gtk_tree_model_get ( GTK_TREE_MODEL(material_icon_store), &iter, 2, &matitem_ptr, -1);
	if ( matitem_ptr != NULL ) 
		selection = (MatLibItem*)matitem_ptr;
	
	// Display infos about selection
	if ( selection != NULL )
		selection->show_info( name_label, author_label, description );
	
	// Clear selection
	while ( list->next != NULL ) {
		gtk_tree_path_free( (GtkTreePath*)list->data );
		list = g_list_next( list );
	}
	gtk_tree_path_free( (GtkTreePath*)list->data );
	g_list_free (list);
}


//*******************************************************************
// Load selection
//
// Load selected materials
//*******************************************************************
void MatLib::load_selection(  )
{
	// Get first item in selection
	GList *list = gtk_icon_view_get_selected_items( GTK_ICON_VIEW(material_icon_view) );
	list = g_list_first( list );
	if ( list == NULL ) return;
	
	// Load each item of the list, and clear the list
	  while( 1 ) {
		GtkTreePath *path = (GtkTreePath*)list->data;
		GtkTreeIter iter;
		gtk_tree_model_get_iter( GTK_TREE_MODEL(material_icon_store), &iter, path );	
		gpointer matitem_ptr;
		MatLibItem *selection = NULL;
		gtk_tree_model_get ( GTK_TREE_MODEL(material_icon_store), &iter, 2, &matitem_ptr, -1);
		if ( matitem_ptr != NULL ) 
			selection = (MatLibItem*)matitem_ptr;
		if ( selection != NULL )
			selection->load();
		gtk_tree_path_free( path );
		if ( list-> next != NULL )
			list = g_list_next( list );
		else 
			break;
	} 
	g_list_free (list);
}

//*******************************************************************
// Icon douibleclick
//
// Material selection callback
//*******************************************************************
void MatLib::icon_doubleclick( GtkTreePath *path )
{		
	// get selection
	GtkTreeIter iter;
	gtk_tree_model_get_iter( GTK_TREE_MODEL(material_icon_store), &iter, path );	
	gpointer matitem_ptr;
	MatLibItem *selection = NULL;
	gtk_tree_model_get ( GTK_TREE_MODEL(material_icon_store), &iter, 2, &matitem_ptr, -1);
	if ( matitem_ptr != NULL ) 
		selection = (MatLibItem*)matitem_ptr;
	
	// Load selection
	if ( selection == NULL )
		return;
	selection->load();
}
