//*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// matlist.cc
//
// Vincent LE PRINCE <vincentleprince@users.sourceforge.net>
// Copyright (C) 2000-2001 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/matlist.h"
#include "include/preferences.h"
#include "include/interface.h"
#include "config.h"
#include "include/tvio.h"
#include "include/viewmanager.h"
#include "include/matlib.h"
#include "include/scene.h"
#include "include/undo.h"

//**************************************
// Définitions
//**************************************
const char *select_tex_buttons_icons[MAX_TEX_BUTTONS] =
	{ GNOME_STOCK_PIXMAP_NEW, GNOME_STOCK_PIXMAP_CLOSE, GNOME_STOCK_PIXMAP_PROPERTIES, GNOME_STOCK_PIXMAP_SAVE, GNOME_STOCK_PIXMAP_REVERT, GNOME_STOCK_PIXMAP_BOOK_BLUE };
const char *select_tex_buttons_tooltips[MAX_TEX_BUTTONS] =
	{ N_("New"), N_("Delete"), N_("Edit"), N_("Save"), N_("Load"), N_("Library") };

const char *ref_list_def[] = { N_("None") };

//**************************************
// Constructeur
//**************************************
TexList::TexList( app_objs *appref )
{
app_ref = appref;
app_ref->texlist = this;
select_widget = NULL;

Material *tex = new PovMaterial( app_ref );
mat_liste.push_back( tex );
texed_select = new TvWidget_option_combo( N_("Name"), NULL, NULL, app_ref );
mat_name_list = NULL;
mat_name_list_size = 0;
load_list = NULL;
copied_item = NULL;

current = -1;
ed_dialog = NULL;
edited = -1;
default_path = NULL;
current_ref = NULL;
update_mat_name_list();
}


TexList::~TexList()
{
for ( unsigned int i = 0 ; i < mat_liste.size() ; i++ )
	delete mat_liste[i];
}


//**************************************
// Set select_widget
//**************************************
void TexList::set_select_widget( GtkWidget *wid )
{
PREF_DEF
select_widget = wid;

// Arbre
GtkWidget *scrolled = gtk_scrolled_window_new( NULL, NULL );
gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
gtk_box_pack_start( GTK_BOX(wid), scrolled, TRUE, TRUE, 4 );
GtkWidget *viewp = gtk_viewport_new( NULL, NULL );
gtk_viewport_set_shadow_type( GTK_VIEWPORT(viewp), GTK_SHADOW_ETCHED_IN );
gtk_container_add( GTK_CONTAINER(scrolled), viewp );

gchar *titres[] = { N_("Name") }; 
select_list = gtk_clist_new_with_titles( 1, titres );
gtk_clist_set_selection_mode( GTK_CLIST(select_list), GTK_SELECTION_SINGLE );
gtk_container_add( GTK_CONTAINER(viewp), select_list );
for ( unsigned int i = 0 ; i < mat_liste.size() ; i++ )
	mat_liste[i]->add_to_list( select_list );
gtk_signal_connect( GTK_OBJECT(select_list), "select_row", GTK_SIGNAL_FUNC(sign_tex_select), this );

// Bouttons de manipulation des objets
GtkWidget *hbox = gtk_hbox_new( FALSE, 0 );
gtk_box_pack_start( GTK_BOX(wid), hbox, FALSE, TRUE, 2 );
//INTERF_DEF
//GtkWidget *win = interf->get_gtkwin();
GtkWidget *pix;
for ( int i = 0 ; i < MAX_TEX_BUTTONS ; i ++ )
	{
	select_buttons[i] = gtk_button_new();
	gtk_box_pack_start( GTK_BOX(hbox), select_buttons[i], TRUE, FALSE, 0 );
	gtk_signal_connect( GTK_OBJECT(select_buttons[i]), "clicked", GTK_SIGNAL_FUNC(sign_tex_buttons_clicked), this );	
	//pix = gnome_stock_pixmap_widget( win, select_tex_buttons_icons[i] );
	pix = gtk_image_new_from_stock( select_tex_buttons_icons[i], GTK_ICON_SIZE_BUTTON );
	gtk_container_add( GTK_CONTAINER(select_buttons[i]), pix );
	select_tooltips[i] = gtk_tooltips_new();
	gtk_tooltips_set_tip( select_tooltips[i], select_buttons[i], _(select_tex_buttons_tooltips[i]), NULL );
	if ( !pref->tooltips->value() ) gtk_tooltips_disable( select_tooltips[i] );
	}
}



//**************************************
// Gestion des noms
//**************************************
bool TexList::test_name_exist( char *name )
{
bool exist = false;
char *res;
//cout << "\nTesting name : " << name; cout.flush( );
if ( ! strcmp( name, "NONE" ) ) return true;
for ( unsigned int i = 0 ; i < mat_liste.size() ; i++ )
	{
	res = mat_liste[i]->get_name();
	if ( res == NULL ) continue;
	if ( strcmp( res, name ) == 0 ) { exist = true; break; }
	}
return exist;
}

char *TexList::create_name( char *name )
{
if ( !test_name_exist( name ) ) return NULL;
int num = 1;
int len = strlen(name);
if ( ( name[len-1] >= 0x30 ) && ( name[len-1] <= 0x39 ) )
	{
	int i;
	for ( i = len ; i > 0 ; i-- )
		if ( name[i] == '#' ) break;
	if ( i > 0 ) { sscanf( name+i-1, "#%u", &num ); num++; len -= len - i; }
	}

char buffer[ len + 30 ];
char num_buffer[30];
strcpy( buffer, name );
do 	{
	sprintf( num_buffer, "#%u", num++ );
	memcpy( buffer+len, num_buffer, strlen(num_buffer)+1 );
	} while ( test_name_exist(buffer) );

char *res = new char[ strlen(buffer) + 1 ];
strcpy( res, buffer );
return res;
}

void TexList::rename_list_row( Material* tex, char *name )
{
int index = get_index_by_pointer( tex );
gtk_clist_set_text( GTK_CLIST(select_list), index, 0, name );
update_mat_name_list();
}

//**************************************
// Callbacks
//**************************************
void TexList::tex_buttons_clicked( GtkWidget *wid )
{
int button = -1;
for ( int i = 0 ; i < MAX_TEX_BUTTONS ; i ++ )
	if ( wid == select_buttons[i] ) { button = i; break; }

SCENE_DEF
UNDO_DEF
if ( button == -1 ) return;
switch( button ) 
	{
	default:
		break;
	
	// New
	case 0:
		{
		scene->set_modified();
		Material *tex = (Material*)(new PovMaterial( app_ref ));
		mat_liste.push_back( tex );
		tex->add_to_list( select_list );
		update_mat_name_list();
		gtk_clist_select_row( GTK_CLIST(select_list), mat_liste.size()-1, 0 );
		PREF_DEF
		if ( pref->matedit->value() ) raise_texeditor();
		undoman->push( TV_UNDO_MAT_CREATE, tex, -1 );
		}
		break;

	// Delete
	case 1:
		{
		scene->set_modified();
		Material *selected = (Material*)gtk_clist_get_row_data( GTK_CLIST(select_list), current );
		remove_material( selected );
		}
		break;

	// Edit
	case 2:
		{
		raise_texeditor();
		}
		break;

	// Save
	case 3:
		{
		if ( current == -1 ) return;
		mat_save_dlgbox();
		}
		break;

	// Load
	case 4:
		{
		filebox = gtk_file_selection_new( _("Load material") );
		GtkFileSelection *box = GTK_FILE_SELECTION(filebox);
		//gtk_window_set_modal( & box->window, TRUE );
		if ( default_path != NULL ) gtk_file_selection_set_filename( box, default_path );
		gtk_signal_connect( GTK_OBJECT(box->ok_button), "clicked", GTK_SIGNAL_FUNC(sign_mat_load_with_fbox), this );
		gtk_signal_connect( GTK_OBJECT(box->cancel_button), "clicked", GTK_SIGNAL_FUNC(sign_mat_del_filebox), this );
		gtk_widget_show( filebox );
		}
		break;
		
	case 5:
		{
		MATLIB_DEF
		matlib->raise_dlg_box();
		break;
		}
	}
}


void TexList::remove_material( Material *mat )
{
vector<Material*>::iterator node;
unsigned int i = 0;
for ( node = mat_liste.begin() ; node != mat_liste.end() ; node++ )
	{
	i++;
	if ( *node != mat ) continue;
	mat_liste.erase(node);
	gtk_clist_remove( GTK_CLIST(select_list), i-1 );
	break;
	}
current = -1;
i--;
if ( i > mat_liste.size() - 1) i = mat_liste.size() - 1;
if ( mat_liste.size() != 0 ) gtk_clist_select_row( GTK_CLIST(select_list), i, 0 );

update_mat_name_list();
if ( edited_pointer == mat )
	{
	texed_select->set( i );
	texed_select->update_widget();
	}
}


void TexList::insert_material( Material *material, int position )
{
vector<Material*>::iterator node;
int i = 0;
for ( node = mat_liste.begin(); i < position ; node++ )
	i++;
	
mat_liste.insert( node, material );
material->add_to_list( select_list, position );

update_mat_name_list();
gtk_clist_select_row( GTK_CLIST(select_list), i, 0 );
}



//**************************************
//Sauvegarde
//**************************************
/*void TexList::mat_save()
{
// Creation du nom de fichier
char *filename;
bool added_ext = false;
gchar *fname = gtk_file_selection_get_filename( GTK_FILE_SELECTION(filebox) );
int offset = strlen( fname ) - 4;
if ( offset < 1 || ( strcmp( fname + offset, ".tvm" ) && strcmp( fname + offset, ".TVM" ) ) )
	{
	filename = new char[ offset + 9 ];
	strcpy( filename, fname );
	strcat( filename, ".tvm" );
	added_ext = true;
	}
else filename = fname;

// Ouverture du fichier
// Add file existence test
ofstream file( filename, ios::out );
file.setf( ios::fixed, ios::floatfield );
if ( file == NULL ) { app_warning( _("Cannot open : "), filename ); return; }

// Ecriture
Material *sel = (Material*)gtk_clist_get_row_data( GTK_CLIST(select_list), current );
file << "TRUEVISION MATERIAL";
file << "\nVERSION " << VERSION;
sel->save( file );
file.close();

sign_mat_del_filebox( filebox, this );
if ( added_ext ) delete filename;
} */


//**************************************
// Chargement
//**************************************
void TexList::mat_load_with_fbox()
{
gchar *fname = (gchar*)gtk_file_selection_get_filename( GTK_FILE_SELECTION(filebox) );
store_default_path( fname );
ifstream file( fname, ios::binary );
if ( file == NULL ) 
	{
	app_warning( _("Cannot open : "), fname );
	sign_mat_del_filebox( filebox, this );
	return;
	}
if ( ! tvio_check_file_sig( file, "TRUEVISION MATERIAL" ) )
	{
	app_warning( _("File type unknown : "), fname );
	sign_mat_del_filebox( filebox, this );
	return;
	}
tvio_get_soft_version( file );
	
Material *tex = (Material*)(new PovMaterial( app_ref ));
tex->load( file );

mat_liste.push_back( tex );
tex->add_to_list( select_list );
update_mat_name_list();	
file.close();
sign_mat_del_filebox( filebox, this );  		
SCENE_DEF
scene->set_modified();
gtk_clist_select_row( GTK_CLIST(select_list), mat_liste.size()-1, 0 );
}


 void TexList::mat_load_from_file( char *fname )
{
ifstream file( fname, ios::binary );
if ( file == NULL )
	{
	app_warning( _("Cannot open : "), fname );
	return;
	}
if ( ! tvio_check_file_sig( file, "TRUEVISION MATERIAL" ) )
	{
	app_warning( _("File type unknown : "), fname );
	return;
	}
tvio_get_soft_version( file );
	
Material *tex = (Material*)(new PovMaterial( app_ref ));
tex->load( file );

mat_liste.push_back( tex );
tex->add_to_list( select_list );
update_mat_name_list();	
file.close();
SCENE_DEF
scene->set_modified();
gtk_clist_select_row( GTK_CLIST(select_list), mat_liste.size()-1, 0 );
}


//**************************************
// Update material name list
//**************************************
void TexList::update_mat_name_list()
{
if ( mat_name_list != NULL )
	{
	for ( int i = 0 ; i < mat_name_list_size ; i++ )
		delete mat_name_list[i];
	delete mat_name_list;
	}

mat_name_list = new char*[ mat_liste.size() + 1 ];
mat_name_list[0] = new char[ strlen( ref_list_def[0] ) + 1 ];
strcpy( mat_name_list[0], (char*)ref_list_def[0] );
for ( unsigned int i = 0 ; i < mat_liste.size() ; i ++ )
	{
	mat_name_list[i+1] = new char[ strlen( mat_liste[i]->get_name() ) + 1 ];
	strcpy( mat_name_list[i+1], mat_liste[i]->get_name() );
	}
mat_name_list_size = mat_liste.size() + 1;
if ( current_ref !=NULL ) current_ref->update_ref_list();

update_texeditor();
}


int TexList::get_index_by_pointer( Material *tex )
{
int res = -1;
for ( unsigned int i = 0 ; i < mat_liste.size() ; i ++ )
	if ( mat_liste[i] == tex ) { res = i; break; }
return res;
}


Material *TexList::get_pointer_by_name( char *str )
{
if ( load_list == NULL )
	{
	for ( unsigned int i = 0 ; i < mat_liste.size() ; i ++ )
		if ( !strcmp( str, mat_liste[i]->get_name() ) ) return mat_liste[i];
	return NULL;
	}
else
	{
	for ( unsigned int i = 0 ; i < load_list->size() ; i ++ )
		{
		char *mat_name =  (*load_list)[i]->get_previous_name();
		if ( mat_name == NULL ) { mat_name =  (*load_list)[i]->get_name(); }
		if ( !strcmp( str, mat_name ) ) return (*load_list)[i];
		}
	return NULL;	
	}
return NULL;
}


//**************************************
// output
//**************************************
void TexList::output_to_povray( ofstream & file )
{
if ( edited != -1 ) mat_liste[edited]->flush_material();

file << "\n//---------------------------------------------";
file << "\n//   Textures";
file << "\n//---------------------------------------------";
for ( unsigned int i = 0 ; i < mat_liste.size() ; i++ )
	mat_liste[i]->output_to_povray(file);
}



//**************************************
// Editeur
//**************************************
const char *edit_butt_tt_text[MAX_EDIT_BUTTONS] = { _("New material"), _("Delete"), _("Copy"), _("Paste"), _("Move up"), _("Move down") };
const char *edit_butt_pix[MAX_EDIT_BUTTONS] = { GNOME_STOCK_PIXMAP_NEW, GNOME_STOCK_PIXMAP_CLOSE, GNOME_STOCK_PIXMAP_COPY,
	GNOME_STOCK_PIXMAP_PASTE, GNOME_STOCK_PIXMAP_UP, GNOME_STOCK_PIXMAP_DOWN };


void TexList::raise_texeditor()
{
if ( GTK_IS_DIALOG(ed_dialog) )
	{
	gdk_window_raise( ed_dialog->window );
	return;
	}
if ( mat_liste.size() < 1 ) return;
PREF_DEF
ed_applied = false;
bool tt = pref->tooltips->value();

ed_dialog = gtk_dialog_new_with_buttons( _("Material editor"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL );
g_signal_connect( G_OBJECT(ed_dialog), "response", G_CALLBACK(sign_ed_dlg_click), this );
g_signal_connect( G_OBJECT(ed_dialog), "close", G_CALLBACK(sign_ed_dlg_destroy), this );
if ( pref->save_dlg_geo->value() )
	{
	if ( pref->med_xpos->value() < 0 ) pref->med_xpos->set(0);
	if ( pref->med_ypos->value() < 0 ) pref->med_ypos->set(0);	
	gtk_widget_set_uposition( ed_dialog, pref->med_xpos->value(), pref->med_ypos->value() );
	gtk_widget_set_usize( ed_dialog, pref->med_xsize->value(), pref->med_ysize->value() );
	}

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

GtkWidget *vbox1 = gtk_vbox_new( FALSE, 2 );
gtk_box_pack_start( GTK_BOX(hbox), vbox1, FALSE, TRUE, 2 );
	// Sélecteur de materiel
	edited = ( current != -1 ) ? current : 0;
	texed_select->set_list( (const char **)&(mat_name_list[1]), mat_liste.size(), edited );
	texed_select->get_widget( vbox1, tt );
	texed_select->connect_signal( GTK_SIGNAL_FUNC(sign_ed_dlg_select), this );

	// Arbre
	GtkWidget *scrolled = gtk_scrolled_window_new( NULL, NULL );
	gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
	gtk_box_pack_start( GTK_BOX(vbox1), scrolled, TRUE, TRUE, 4 );
	GtkWidget *viewp = gtk_viewport_new( NULL, NULL );
	gtk_viewport_set_shadow_type( GTK_VIEWPORT(viewp), GTK_SHADOW_ETCHED_IN );
	gtk_container_add( GTK_CONTAINER(scrolled), viewp );

	ed_tree = gtk_ctree_new( 1, 0 );
	gtk_ctree_set_expander_style( GTK_CTREE(ed_tree), GTK_CTREE_EXPANDER_CIRCULAR );
	gtk_clist_set_selection_mode( GTK_CLIST(ed_tree), GTK_SELECTION_SINGLE );
	gtk_container_add( GTK_CONTAINER(viewp), ed_tree );
	gtk_signal_connect( GTK_OBJECT(ed_tree), "tree_select_row", GTK_SIGNAL_FUNC(sign_ed_tree_select), this );

	// Bouttons de manipulation des matériaux
	GtkWidget *bbox = gtk_hbox_new( FALSE, 3 );
	gtk_box_pack_start( GTK_BOX(vbox1), bbox, FALSE, TRUE, 2 );
	

//INTERF_DEF
GtkWidget *pix;
for ( int i = 0 ; i < MAX_EDIT_BUTTONS ; i ++ )
	{
	edit_butt_wid[i] = gtk_button_new();
	gtk_box_pack_start( GTK_BOX(bbox), edit_butt_wid[i], TRUE, FALSE, 0 );
	gtk_signal_connect( GTK_OBJECT(edit_butt_wid[i]), "clicked", GTK_SIGNAL_FUNC(sign_edit_button_clicked), this );	
	pix = gtk_image_new_from_stock( edit_butt_pix[i], GTK_ICON_SIZE_BUTTON );
	gtk_container_add( GTK_CONTAINER(edit_butt_wid[i]), pix );
	edit_butt_tt_wid[i] = gtk_tooltips_new();
	gtk_tooltips_set_tip( edit_butt_tt_wid[i], edit_butt_wid[i], edit_butt_tt_text[i], NULL );
	if ( !pref->tooltips->value() ) gtk_tooltips_disable( edit_butt_tt_wid[i] );
	}
	
edit_box = gtk_vbox_new( FALSE, 2 );
gtk_box_pack_start( GTK_BOX(hbox), edit_box, TRUE, TRUE, 2 );

mat_liste[edited]->get_editor( ed_tree, edit_box );
edited_pointer = mat_liste[edited];

GtkWidget *prev_box = gtk_vbox_new( FALSE, 2 );
gtk_box_pack_start( GTK_BOX(hbox), prev_box, TRUE, TRUE, 2 );
preview = new PovrayFE( app_ref );
preview->set_size( 140, 140 );
preview->set_current_material( mat_liste[edited] );
preview->show_image_as_widget( prev_box, tt );
preview->get_progress_bar( prev_box, tt );
preview->get_start_button( prev_box, tt );
preview->get_predef_sizes( prev_box, tt );
preview->get_predef_scene_widget( prev_box, tt );
preview->get_antialias_widget( prev_box, tt );

gtk_widget_show_all(ed_dialog);
}

//****************************************************
// Select
// ***************************************************
void TexList::ed_dlg_select()
{
if ( texed_select->in_update ) return;
texed_select->flush();
if ( edited != -1 )
	{
	mat_liste[edited]->flush_material();
	 mat_liste[edited]->save_node_state();
	mat_liste[edited]->destroy_editor();
	}
edited = texed_select->value();
mat_liste[edited]->get_editor( ed_tree, edit_box );
edited_pointer = mat_liste[edited];
preview->set_current_material( mat_liste[edited] );
}

//****************************************************
// Result
// ***************************************************
void TexList::clicked_ed_dlg( gint button )
{
if ( edited != -1 ) mat_liste[edited]->flush_material();
VMAN_DEF

switch( button ) 
	{
	default:
	case GTK_RESPONSE_CLOSE:	
		preview->cancel_preview();
		close_ed_dlg();
		vmanager->force_refresh();
		break;

	case GTK_RESPONSE_APPLY:
		vmanager->force_refresh();
		break;
	}
}

void  TexList::close_ed_dlg()
{ 
if ( !GTK_IS_DIALOG(ed_dialog) ) return;
preview->save_preview_settings();
PREF_DEF
if ( pref->save_dlg_geo->value() )
	{
	gint x,y;
	gdk_window_get_root_origin( ed_dialog->window, &x, &y );
	pref->med_xpos->set( x );
	pref->med_ypos->set( y );
	pref->med_xsize->set( ed_dialog->allocation.width );
	pref->med_ysize->set( ed_dialog->allocation.height );
	}

if ( edited != -1 ) mat_liste[edited]->destroy_editor();
gtk_widget_destroy( ed_dialog ); 
ed_dialog = NULL;
delete preview;
}


// Material editor buttons : cut / copy / paste / move up / move down
const char *matnames[] ={ N_("Material"), N_("Texture"), N_("Interior"), N_("Finish"), N_("pigment"), N_("Normal"), N_("Media"), N_("Density") };

void  TexList::edit_button_clicked( GtkWidget *wid )
{
int button = -1;
for ( int i = 0 ; i < MAX_EDIT_BUTTONS ; i ++ )
	if ( wid == edit_butt_wid[i] ) { button = i; break; }
if ( button == -1 ) return;
if ( edited == -1 ) return;
SCENE_DEF
UNDO_DEF

switch ( button )
	{
	// New
	case 0:
		{
		scene->set_modified();
		Material *tex = (Material*)(new PovMaterial( app_ref ));
		mat_liste.push_back( tex );
		tex->add_to_list( select_list );
		update_mat_name_list();
		gtk_clist_select_row( GTK_CLIST(select_list), mat_liste.size()-1, 0 );
		undoman->push( TV_UNDO_MAT_CREATE, tex, -1 );
		texed_select->set( mat_liste.size() -1 );
		texed_select->update_widget();
		ed_dlg_select();
		}
		break;
	
	// Delete
	case 1:
		mat_liste[edited]->delete_mat_item( selected_node );
		break;
		
	// Copy
	case 2:
		{
		if ( copied_item != NULL ) delete copied_item;
		MaterialItem *target = mat_liste[edited]->get_selected_item();
		target->flush();
		copied_item = target->duplicate_yourself();
		}
		break;
		
	// Paste
	case 3:
		{	
		if ( copied_item == NULL ) return;
		bool res = mat_liste[edited]->get_selected_item()->paste( copied_item );
		if ( ! res ) app_warning( _("Cannot paste here item of type :"), matnames[ (int)copied_item->get_type() ] );
		}
		break;
		
	// Move up
	case 4:
		mat_liste[edited]->move_mat_item( selected_node, 0 );
		break;
	
	// Move up
	case 5:
		mat_liste[edited]->move_mat_item( selected_node, 1 );
		break;
	
	default:
		break;
	}
}



//****************************************************
// Pref changed
// ***************************************************
void  TexList::pref_changed()
{
PREF_DEF
bool tt = pref->tooltips->value();
	
for ( int i = 0 ; i < MAX_TEX_BUTTONS ; i ++ )
	if ( tt ) gtk_tooltips_enable( select_tooltips[i] );
	else gtk_tooltips_disable( select_tooltips[i] );

if ( ed_dialog != NULL )
	{
	for ( int i = 0 ; i < MAX_EDIT_BUTTONS ; i ++ )
		if ( tt ) gtk_tooltips_enable( edit_butt_tt_wid[i] );
		else gtk_tooltips_disable( edit_butt_tt_wid[i] );
	}
}


//****************************************************
// Update
// ***************************************************
void  TexList::update_texeditor()
{
if ( !GTK_IS_DIALOG(ed_dialog) ) return;
if ( mat_liste.size() < 1 ) { close_ed_dlg(); return; }

int current_index = get_index_by_pointer( edited_pointer );
if ( current_index == -1 ) 
	{
	current_index = 0;
	edited = -1;
	}
texed_select->set_list( (const char **)&mat_name_list[1], mat_liste.size(), current_index );
texed_select->update_widget();
}



//***************************************************
// Save  box
//***************************************************
void TexList::mat_save_dlgbox()
{
if ( mat_liste.size() < 1 ) return;
PREF_DEF
bool tt = pref->tooltips->value();
Material *sel = (Material*)gtk_clist_get_row_data( GTK_CLIST(select_list), current );

//save_dialog = gnome_dialog_new( _("Save material"), GNOME_STOCK_BUTTON_CANCEL, GNOME_STOCK_BUTTON_OK, NULL );
save_dialog =  gtk_dialog_new_with_buttons( _("Save material"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL );
//gtk_window_set_modal( & GNOME_DIALOG(save_dialog)->window, TRUE );
//gtk_window_set_policy( GTK_WINDOW(save_dialog), FALSE, TRUE, FALSE );
gtk_window_set_wmclass( GTK_WINDOW(save_dialog), PACKAGE, "Save material" );
g_signal_connect( G_OBJECT(save_dialog), "response", G_CALLBACK(sign_save_dlg_click), this );
g_signal_connect( G_OBJECT(save_dialog), "close", G_CALLBACK(sign_save_dlg_destroy), this );

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

// Boite de gauche
GtkWidget *vbox1 = gtk_vbox_new( FALSE, 2 );
gtk_box_pack_start( GTK_BOX(hbox), vbox1, FALSE, TRUE, 2 );

	file = new TvWidget_path( N_("File"), NULL, NULL, app_ref );
	file->get_widget( vbox1, tt );
	if ( default_path != NULL )	file->set_default_path( default_path );

	//author= new TvWidget_entry( N_("Author"), "AUTHOR", NULL, app_ref );
	//author->set( pref->author->value() );
	sel->author->get_widget( vbox1, tt );

	//comment= new TvWidget_text( N_("Comment"), "COMMENT", NULL, app_ref );
	sel->comment->get_widget( vbox1, tt );
	

// Boite de droite
GtkWidget *vbox2 = gtk_vbox_new( FALSE, 2 );
gtk_box_pack_start( GTK_BOX(hbox), vbox2, TRUE, TRUE, 2 );

	use_preview = new TvWidget_bool_activator( N_("Include preview"), NULL, NULL, app_ref, true );
	use_preview->get_widget_no_toggle( vbox2, tt );
	GtkWidget *vbox3 = gtk_vbox_new( FALSE, 2 );
	gtk_box_pack_start( GTK_BOX(vbox2), vbox3, TRUE, TRUE, 2 );
	use_preview->set_target( vbox3 );
	use_preview->update_widget();

	save_preview = new PovrayFE( app_ref );
	save_preview->set_size( 80, 80 );
	save_preview->show_image_as_widget( vbox3, tt );
	save_preview->get_predef_scene_widget( vbox3, tt );
	save_preview->get_antialias_widget( vbox3, tt );

gtk_widget_show_all( save_dialog );
}



void TexList::clicked_save_dlg( gint button )
{
if ( button == GTK_RESPONSE_CLOSE ) { close_save_dialog(); 	return; }
Material *sel = (Material*)gtk_clist_get_row_data( GTK_CLIST(select_list), current );

file->flush();
sel->author->flush();
sel->comment->flush();
store_default_path( file->value() );

// Presence du nom de fichier
if ( file->value() == NULL )
	{
	GtkWidget *dialog =  gtk_message_dialog_new ( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("No file name specified"));	
	gtk_dialog_run( GTK_DIALOG(dialog));
	gtk_widget_destroy( dialog );
	return;
	}

// Creation du nom de fichier
char *filename;
bool added_ext = false;
gchar *fname = file->value();
int offset = strlen( fname ) - 4;
if ( offset < 1 || ( strcmp( fname + offset, ".tvm" ) && strcmp( fname + offset, ".TVM" ) ) )
	{
	filename = new char[ offset + 9 ];
	strcpy( filename, fname );
	strcat( filename, ".tvm" );
	added_ext = true;
	}
else filename = fname;

// Ouverture du fichier
ifstream ifile( filename, ios::binary );
if ( ifile != NULL )
	{
	//GtkWidget *question = gnome_question_dialog_modal( _("File already exists, overwrite ?"), NULL, NULL );
	//if ( gnome_dialog_run_and_close( GNOME_DIALOG(question) ) != 0 ) { return; }
	GtkWidget *dialog =  gtk_message_dialog_new ( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("File already exists, overwrite ?"));	
	gint button = gtk_dialog_run( GTK_DIALOG(dialog));
	gtk_widget_destroy( dialog );
	if ( button == GTK_RESPONSE_NO ) return;
	}
ifile.close();

ofstream ofile( filename, ios::out );
ofile.setf( ios::fixed, ios::floatfield );
if ( ofile == NULL ) { app_warning( _("Cannot create : "), filename ); close_save_dialog(); return; }

// Curseur
GdkCursor *pointer = gdk_cursor_new( GDK_WATCH );
gdk_window_set_cursor( save_dialog->window,  pointer );

// Preview
if ( use_preview->value() )
	{
	if ( save_preview->start_rendering_predef( sel, true, true ) == false )
		{
		app_warning( _("Can't create preview : povray error.") );
		if ( added_ext ) delete filename;
		gdk_cursor_destroy( pointer );
		close_save_dialog();
		return;
		}
	}
	
// Ecriture
ofile << "TRUEVISION MATERIAL";
ofile << "\nVERSION " << VERSION << '\n';
sel->author->save( ofile );
ofile << '\n';
sel->comment->save( ofile );
save_preview->save_as_preview( ofile );
sel->save( ofile );
ofile.close();

if ( added_ext ) delete filename;
gdk_cursor_destroy( pointer );
close_save_dialog();
}

void TexList::close_save_dialog()
{
gtk_widget_destroy( save_dialog );
delete file;
delete author;
delete comment;
delete save_preview;
delete use_preview;
}


void TexList::save( ofstream & file )
{
SCENE_DEF
file << "\nMATERIALS{";
for ( unsigned int i = 0 ; i < mat_liste.size() ; i++ )
	{
	mat_liste[i]->save( file );
	scene->set_save_progress();
	}
file << "\n}\n";
}


bool TexList::load( ifstream & file, char *ltag )
{
if ( strcmp( ltag, "MATERIALS" ) ) return false;
SCENE_DEF

char * tag = NULL;
do {
	tag = tvio_get_next_tag( file );
	if ( tag == NULL ) break;
    Material *tex = (Material*)(new PovMaterial( app_ref ));
    if ( tex->load( file, tag ) )
    	{
    	mat_liste.push_back( tex );
    	tex->add_to_list( select_list );
    	scene->set_load_progress( file );
    	continue;
    	}
    else { delete tex; }
		
	tvio_skip_section(file );
	} while ( tag != NULL );

update_mat_name_list();	
return true;
}


void TexList::clear()
{
for ( unsigned int i = 0 ; i < mat_liste.size() ; i++ )
	delete mat_liste[i];
mat_liste.clear();
gtk_clist_clear(  GTK_CLIST(select_list) );
current = -1;
edited = -1;
current_ref = NULL;
}


void TexList::store_default_path( char *path )
{
if ( path == NULL ) return;
if ( default_path != NULL ) delete default_path;
int len = strlen( path );
while ( len > 0 && path[len] != '/' ) len--;
if ( len == 0 ) return;
default_path = new char[ len + 2 ];
strncpy( default_path, path, len+1 );
default_path[len+1] = '\0';
}

void TexList::flush_load_list()
{
if ( load_list == NULL ) return;
for ( unsigned int i = 0 ; i < load_list->size() ; i ++ )
	{
	mat_liste.push_back( (*load_list)[i] );
	(*load_list)[i]->add_to_list( select_list );
	}
update_mat_name_list();	
load_list = NULL;
}
