//*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// tvwidgets.h
//
// 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.  */ 
//*******************************************************************************************
#ifndef TV_WIDGETS
#define TV_WIDGETS
using namespace std;
#include "main.h"
#include "GL/gl.h"
#include "GL/glu.h"
#include <iostream>
#include <fstream>


//*********************************************************
// Classe de base
//*********************************************************
class TvWidget {
	protected:
		static app_objs *app_ref;
		const char *name;
		const char *sname;
		const char *tooltip;
		GtkWidget *widget;
		GtkTooltips *ttwidget;
	
	public:
		TvWidget( const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget( TvWidget & ref );
		virtual TvWidget *duplicate_yourself() { return NULL; cout << "\nWarning : duplicate_yourself not implemented here !"; cout.flush(); }

		bool in_update;
		const char *get_name() { return name; }

		// Getting the widget
		virtual void get_widget( GtkWidget *box, bool tt ) {}
		virtual void get_widget_noframe( GtkWidget *wid, bool tt ) {}
		void pack_widget( GtkWidget *box, bool tt, GtkWidget *target=NULL );
		void set_tooltip( GtkWidget *wid );
		virtual void show_widget() { gtk_widget_show_all(widget); }

		// Manipulate it
		virtual void unget_widget() { gtk_widget_unparent( widget ); widget=NULL; }
		virtual void destroy_widget() { if ( GTK_IS_WIDGET(widget)  ) gtk_widget_destroy(widget); clear_widget(); }
		virtual bool widget_visible() { return ( widget == NULL ) ? false : true; }
		virtual void clear_widget() { widget = NULL; }
		virtual void set_widget_inactive() { gtk_widget_set_sensitive( widget, FALSE ); }
		virtual void set_widget_active() { gtk_widget_set_sensitive( widget, TRUE ); }		
		virtual void update_widget() {}
		virtual void connect_signal( GtkSignalFunc func, gpointer data ) {}		
		virtual void flush();

		// Save / Load
		virtual void save( ofstream & file ) { file << sname << "{"; }
		virtual bool load( ifstream & file, char *tag ) { return false; }

		virtual void store() {}
		virtual void restore() {}
		virtual void pref_changed() {}
		virtual void output_to_povray( ofstream & file ) {}
		virtual void copy( TvWidget *wid ) {}
};

//**********************************************************
// Rolling box
//**********************************************************
class Rolling_box {	
#define SENDER ((Rolling_box*)data)
	friend void sign_rolling_box_clicked( GtkWidget *wid, gpointer data ) { SENDER->button_clicked(); }
#undef SENDER

	private:
		static app_objs *app_ref;
		const char *title;
		bool tooltips;
		TvWidget *child_widget;
		GtkWidget *bar_pix;
		bool rolled_up;
		GtkWidget *rolling_box, *mother_box;

		void button_clicked();
		void set_bar_pix();
	
	public:
		Rolling_box( const char *titre , app_objs *app_ref, TvWidget *obj );
		Rolling_box( Rolling_box & ref );
		~Rolling_box() {}

		void get_widget_rb( GtkWidget *box, bool tt );
		void copy( Rolling_box *rb );
		void set_child( TvWidget *obj ) { child_widget = obj; }
};

//**********************************************************
// TvWidget BOOL
//**********************************************************
class TvWidget_bool : public TvWidget {
	protected:
		bool data, undo_data;

	public:
		TvWidget_bool( const char *name, const char *sname, const char *tooltip, app_objs *appref, bool val = false ) : TvWidget( name, sname, tooltip, appref ) { data = val ; }
		TvWidget_bool( TvWidget_bool & ref ) : TvWidget( ref ) { data = ref.data; undo_data = data; }
		virtual TvWidget *duplicate_yourself() { TvWidget_bool *res = new TvWidget_bool( *this ); return res; }
		
		bool value() { return data; }
		void set( bool val ) { data = val; }
		void toggle() { set( !data ); }
		void copy ( TvWidget *val ) { set( ((TvWidget_bool*)val)->value() ); }
		void store() { undo_data = data; }
		void restore() { data = undo_data; }
		
		void get_widget( GtkWidget *box, bool tt );
		void update_widget() { in_update = true; if ( GTK_IS_WIDGET(widget) ) gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(widget), data ); in_update = false; }
		void connect_signal( GtkSignalFunc func, gpointer data ) { gtk_signal_connect( GTK_OBJECT(widget), "clicked", func, data ); }
		void flush();
		void pref_changed() { set_tooltip(widget); }
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};

//**********************************************************
// TvWidget BOOL ACTIVATOR
//**********************************************************
class TvWidget_bool_activator : public TvWidget_bool {
	friend void sign_bool_activator_clicked( GtkWidget *wid, gpointer data ) { ((TvWidget_bool_activator*)data)->flush(); ((TvWidget_bool_activator*)data)->toggle(); }
	
	protected:
		GtkWidget *target;
		void toggle() { if ( GTK_IS_WIDGET(target) ) gtk_widget_set_sensitive( target, data ? TRUE : FALSE ); }
		
	public:
		TvWidget_bool_activator( const char *name, const char *sname, const char *tooltip, app_objs *appref, bool val ) : TvWidget_bool( name, sname, tooltip, appref, val ) { target = NULL; }
		TvWidget_bool_activator( TvWidget_bool_activator & ref ) : TvWidget_bool( ref ) {}
		void set_target( GtkWidget* wid ) { target = wid; }
		void get_widget_no_toggle( GtkWidget *box, bool tt );
		void get_widget( GtkWidget *box, bool tt ) { get_widget_no_toggle( box, tt ); toggle(); }
		void update_widget() { toggle(); TvWidget_bool::update_widget(); }	
		void clear_widget() { target = NULL; TvWidget_bool::clear_widget(); }
};

//**********************************************************
// TvWidget INT
//**********************************************************
class TvWidget_int : public TvWidget {
	protected:
		int data, undo_data;
		int up, down, rate;
		GtkWidget *spin;

	public:
		TvWidget_int( const char *name,  const char *sname, const char *tooltip, app_objs *appref, int val = 0 ) : TvWidget( name, sname, tooltip, appref ) { data = val; up = 1000000; down = -1000000; rate = 1; }
		TvWidget_int( TvWidget_int & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_int *res = new TvWidget_int( *this ); return res; }
		int value() { return data; }
		void set( int val ) { data = val; if ( data > up ) data = up; if ( data < down ) data = down;}
		void copy ( TvWidget *val ) { set( ((TvWidget_int*)val)->value() ); }
		void store() { undo_data = data; }
		void restore() { data = undo_data; }
		
		void get_widget( GtkWidget *box, bool tt );
		void flush();
		void set_range( int s, int i, int r ) { up = s; down = i; rate = r; }
		void pref_changed() { set_tooltip(spin); }
		virtual void output_to_povray( ofstream & file ) { file << data; }
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
		void update_widget();
};

//**********************************************************
// TvWidget FLOAT
//**********************************************************
class TvWidget_float : public TvWidget {
	protected:
		double data, undo_data;
		float up, down, rate;
		int precision;
		GtkWidget *spin;
		GtkObject *adj;

	public:
		TvWidget_float( const char *name, const char *sname, const char *tooltip, app_objs *appref, float val = 0 ) : TvWidget( name, sname, tooltip, appref ) { data = val; up = 10000000; down = -10000000; rate = 1; precision = 1;}
		TvWidget_float( TvWidget_float & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_float *res = new TvWidget_float( *this ); return res; }

		double value() { return data; }
		void set( double val ) { data = val;  if ( data > up ) data = up; if ( data < down ) data = down; }
		void copy ( TvWidget *val ) { set( ((TvWidget_float*)val)->value() ); }
		void store() { undo_data = data; }
		void restore() { data = undo_data; }
		
		virtual void get_widget( GtkWidget *box, bool tt );
		virtual void update_widget();
		void connect_signal( GtkSignalFunc func, gpointer data ) { gtk_signal_connect( GTK_OBJECT(adj), "value-changed", func, data ); }
		virtual void flush();
		void set_range( float s, float i, float r, int pre = 1 ) { up = s; down = i; rate = r; precision = pre; }
		void pref_changed() { set_tooltip(spin); }	
		virtual void output_to_povray( ofstream & file ) { file << data; }		
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );	
};


class TvWidget_percent : public TvWidget_float {
	public:
		TvWidget_percent( const char *name, const char *sname, const char *tooltip, app_objs *appref, float val = 0 ) : TvWidget_float( name, sname, tooltip, appref ) { data = val; up = 1; down = 0; rate = 0.01; precision = 4;}
		TvWidget_percent( TvWidget_percent & ref ) : TvWidget_float( ref ) {}
		virtual TvWidget *duplicate_yourself() { TvWidget_percent *res = new TvWidget_percent( *this ); return res; }

		void get_widget( GtkWidget *box, bool tt );
		void update_widget();
		void flush();
};

//**********************************************************
// TvWidget ENTRY
//**********************************************************
class TvWidget_entry : public TvWidget {
	protected:
		char *data, *undo_data;
		GtkWidget *entry;

	public:
		TvWidget_entry( const char *name, const char *sname, const char *tooltip, app_objs *appref, char *val = NULL ) : TvWidget( name, sname, tooltip, appref ) { undo_data = NULL; data = NULL; set(val); }
		TvWidget_entry( TvWidget_entry & ref ) : TvWidget( ref ) { undo_data = NULL; data = NULL; set( ref.data ); }
		virtual TvWidget *duplicate_yourself() { TvWidget_entry *re = new TvWidget_entry( *this ); return re; }
		virtual ~TvWidget_entry();

		char *value() { return data; }
		char *get_previous_value() { return undo_data; }
		void set( char *val );
		void copy ( TvWidget *val ) { set( ((TvWidget_entry*)val)->value() ); }
		void store();
		void restore();
		
		void get_widget( GtkWidget *box, bool tt );
		void update_widget() { if ( !GTK_IS_WIDGET(widget) ) return;in_update = true; if ( data != NULL ) gtk_entry_set_text( GTK_ENTRY(entry), data ); in_update = false; }
		void connect_signal( GtkSignalFunc func, gpointer data ) { gtk_signal_connect( GTK_OBJECT(entry), "activate", func, data ); }
		void connect_signal2( GtkSignalFunc func, gpointer data ) { gtk_signal_connect( GTK_OBJECT(entry), "focus-out-event", func, data ); }
		void connect_signal_changed( GtkSignalFunc func, gpointer data ) { gtk_signal_connect( GTK_OBJECT(entry), "changed", func, data ); }
		
		void flush() { if ( GTK_IS_WIDGET(widget) ) set( (char*)gtk_entry_get_text(GTK_ENTRY(entry)) ); }
		char *get_current_value() { return (char*)gtk_entry_get_text(GTK_ENTRY(entry)); }
		bool has_changed() { return strcmp( data, gtk_entry_get_text(GTK_ENTRY(entry))) ? true : false;  }
		void pref_changed() { set_tooltip(entry); }
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};


//**********************************************************
// TvWidget TEXT
//**********************************************************
class TvWidget_text : public TvWidget {
	protected:
		GtkWidget *text;
		gchar *data;
		int size;

	public:
		TvWidget_text( const char *name, const char *sname, const char *tooltip, app_objs *appref, char *val = NULL ) : TvWidget( name, sname, tooltip, appref ) { data = NULL;}
		//TvWidget_text( TvWidget_text & ref ) {}
		virtual ~TvWidget_text() { if ( data != NULL ) delete data; }

		void get_widget( GtkWidget *box, bool tt );
		void flush();
		void clear() { if ( data != NULL ) delete data; data = NULL; size = 0; }
		//char *get_current_value() { return gtk_entry_get_text(GTK_ENTRY(entry)); }
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
		void update_widget();
};

//**********************************************************
// TvWidget COLOR
//**********************************************************
class TvWidget_color : public TvWidget {
	protected:
		double data[4];
		double undo_data[4];
		GtkWidget *picker;
		bool use_alpha;

	public:
		TvWidget_color( const char *name, const char *sname, const char *tooltip, app_objs *appref, bool ualpha = false ) : TvWidget( name, sname, tooltip, appref ) { use_alpha = ualpha; }
		TvWidget_color( TvWidget_color & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_color *res = new TvWidget_color( *this ); return res; }
		void set( int r, int g, int b, int a = 255 ) { set( (float)r/255.0, (float)g/255.0, (float)b/255.0, (float)a/255.0 );}
		void set( double r, double g, double b, double a = 1 ) { data[0]=r; data[1]=g; data[2]=b; data[3]=a; }
		void copy( TvWidget *col ) { for ( register int i = 0 ; i < 3 ; i++ ) data[i] = ((TvWidget_color*)col)->data[i]; }
		void store() { memcpy( undo_data, data, sizeof(double)*4 ); }
		void restore() { memcpy( data, undo_data, sizeof(double)*4 ); }
		
		void get_widget( GtkWidget *box, bool tt );
		void update_widget();
		void flush();
		void connect_signal( GtkSignalFunc func, gpointer data ) { gtk_signal_connect( GTK_OBJECT(picker), "color-set", func, data ); }

		void pref_changed() { set_tooltip(picker); }
		void output_to_povray( ofstream & file ) { file << "rgb<" << data[0] << ',' << data[1] << ',' << data[2] << '>'; }				

		void gl_set_rgb();
		void gl_set_rgb_for_wireframe();
		void gl_set_rgba() { glColor4f( data[0], data[1], data[2], data[3] ); }
		void set_bkgd() { glClearColor( data[0], data[1], data[2], data[3] ); }
		void gl_array( GLfloat *res ) { res[0]=data[0]; res[1]= data[1]; res[2]= data[2]; res[3]= data[3]; }
		//float get_as_float( int i ) { return data[i]; }
		double get( int i ) { return data[i]; }
		void gdk_col( GdkColor &col ) { col.red = (gushort)(data[0]*65535); col.green = (gushort)(data[1]*65535); col.blue = (gushort)(data[2]*65535); }

		void save( ofstream & file );
		bool load( ifstream & file, char * tag );

		// Provisoire !!
		//int get_red() { return data[0]; }
		//int get_green() { return data[1]; }
		//int get_blue() { return data[2]; }
};

//**********************************************************
// TvWidget PIGMENT
//**********************************************************
class TvWidget_pigment : public TvWidget {
	#define SENDER ((TvWidget_pigment*)data)
	friend void sign_pigcolor_changed( GnomeColorPicker *picker, guint r, guint g, guint b, guint a, gpointer data ) { SENDER->transmit_signal(); }
	friend void sign_pigalpha_changed( GtkWidget *wid, gpointer data ) { SENDER->transmit_signal(); }
	#undef SENDER

	protected:
		TvWidget_color *color;
		TvWidget_percent *filter;
		TvWidget_percent *transmit;
		void (*func)(gpointer);
		gpointer func_data;

	public:
		TvWidget_pigment( const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_pigment( TvWidget_pigment & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_pigment *res = new TvWidget_pigment( *this ); return res; }
		void set( double r, double g, double b, double a, double t = 0 ) { color->set(r,g,b, a); transmit->set(t); filter->set(a); }
		void copy( TvWidget *pig ) { TvWidget_pigment *pag = (TvWidget_pigment*)pig; color->copy( pag->color ); filter->copy( pag->filter ); transmit->copy( pag->transmit ); }
		void store() { color->store(); filter->store(); transmit->store(); }
		void restore() { color->restore(); filter->restore(); transmit->restore(); }
		
		void get_widget_wnframe( GtkWidget *box, bool tt, bool frame );
		void get_widget( GtkWidget *box, bool tt ) { get_widget_wnframe( box, tt, true ); }
		void get_widget_noframe( GtkWidget *box, bool tt ) { get_widget_wnframe( box, tt, false ); }
		void clear_widget();
		void update_widget() { if ( !GTK_IS_WIDGET(widget) ) return; color->update_widget(); filter->update_widget(); transmit->update_widget(); }
		void flush(); 
		void output_to_povray( ofstream & file );
		void connect_signal( void (*func)(gpointer), gpointer data );
		void transmit_signal() { flush(); (*func)(func_data); }
		float get_alpha() { return filter->value(); }
		double get_color( int i ) { return color->get(i); }
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};

class TvWidget_pigment_rb : public TvWidget_pigment  {
	protected:
		Rolling_box *rb;

	public:
		TvWidget_pigment_rb( const char *name, const char *sname, const char *tooltip, app_objs *appref )
			: TvWidget_pigment( name, sname, tooltip, appref )
			{ rb = new Rolling_box( name, app_ref, (TvWidget*)this ); }
		TvWidget_pigment_rb( TvWidget_pigment_rb & ref ) : TvWidget_pigment( ref ) { rb = new Rolling_box( *(ref.rb) ); rb->set_child( (TvWidget*)this ); }
		virtual TvWidget *duplicate_yourself() { TvWidget_pigment_rb *res = new TvWidget_pigment_rb( *this ); return res; }

		void get_widget_rb( GtkWidget *box, bool tt ) { rb->get_widget_rb( box, tt ); }
};

//**********************************************************
// TvWidget OPTION COMBO
//**********************************************************
class TvWidget_option_combo : public TvWidget {
	protected:
		int data, undo_data;
		char **items;
		int num_items;
		GtkWidget *combo;

	public:
		TvWidget_option_combo( const char *name, const char *sname, const char *tooltip, app_objs *appref ) : TvWidget( name, sname, tooltip, appref ) {}
		TvWidget_option_combo( TvWidget_option_combo & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_option_combo *res = new TvWidget_option_combo( *this ); return res; }
		int value() { return data; }
		void set( int val ) { data = val; }
		void copy( TvWidget *comb ) { set( ((TvWidget_option_combo*)comb)->value() ); }
		void store() { undo_data = data; }
		void restore() { data = undo_data; }
		void set_list( const char **it, const int num, int val ) { items = (char**)it; num_items = (int)num; data = val; } 
		void reset_list( const char **it, const int num );
		void pref_changed() { set_tooltip(combo); }		
		void connect_signal( GtkSignalFunc func, gpointer data ) { gtk_signal_connect( GTK_OBJECT(GTK_COMBO(combo)->entry), "changed", func, data ); }

		void get_widget( GtkWidget *box, bool tt );
		void flush();
		void update_widget();
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};


//**********************************************************
// TvWidget PATH
//**********************************************************
class TvWidget_path : public TvWidget {
	protected:
		char * data, * undo_data;
		GtkWidget *fentry, *entry;

	public:
		TvWidget_path( const char *name, const char *sname, const char *tooltip, app_objs *appref, const char *def = NULL ) 
				: TvWidget( name, sname, tooltip, appref ) { undo_data = data = NULL; set((char*)def); }
		TvWidget_path( TvWidget_path & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_path *res = new TvWidget_path( *this ); return res; }
		virtual ~TvWidget_path();
		char * value() { return data; }
		void set( char * val );
		void copy ( TvWidget *val ) { set( ((TvWidget_path*)val)->value() ); }
		void store();
		void restore();
		void pref_changed() { set_tooltip(entry); }		

		void get_widget( GtkWidget *box, bool tt );
		void set_default_path( char *path );
		void flush();
		void connect_signal( GtkSignalFunc func, gpointer data ) { gtk_signal_connect( GTK_OBJECT(entry), "changed", func, data ); }
		void save( ofstream & file );
       bool load( ifstream & file, char * tag );
};


//**********************************************************
// TvWidget POINT
//**********************************************************
class TvWidget_point : public TvWidget {
	protected:
		float data[3], undo_data[3];
		GtkWidget *spins[3];
		float up, down, rate;
		int precision;

	public:
		TvWidget_point(  const char *name, const char *sname, const char *tooltip, app_objs *appref ) : TvWidget( name, sname, tooltip, appref ) { up = 150; down = -150; rate = 0.1; precision = 5; }
		TvWidget_point( TvWidget_point & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_point *res = new TvWidget_point( *this ); return res; }
		void set( float x, float y, float z ) { data[0]=x; data[1]=y; data[2]=z; }	
		void setx( float x ) { data[0] = x; }
		void sety( float y ) { data[1] = y; }
		void setz( float z ) { data[2] = z; }
		void set_range( float s, float i, float r, int pre = 1 ) { up = s; down = i; rate = r; precision = pre; }
		void copy( TvWidget *pt ) { for ( register int i = 0 ; i < 3 ; i++ ) data[i] = ((TvWidget_point*)pt)->data[i]; }
			
		void get( float & a,  float & b, float & c ) { a=data[0]; b=data[1]; c=data[2]; }
		void get( float *pos ) { memcpy( pos, data, sizeof(float)*3 ); }
		float *get() { return data; }
		float get( int i ) { return data[i]; }
		void add( const float *v ) { for ( register int i = 0 ; i < 3 ; i++ ) data[i] += v[i]; }
		void store()  { memcpy( undo_data, data, sizeof(float)*3 ); }
		void restore() { memcpy( data, undo_data, sizeof(float)*3 ); }
		void pref_changed() { set_tooltip(spins[0]); }
		void reduce_size();

		void get_widget( GtkWidget *box, bool tt );
		void update_widget();
		void flush();
		GLfloat *gl_array() { static GLfloat pos[] = { data[0], data[1], data[2] }; return pos; }
		void output_to_povray( ofstream & file ) { file << '<' << data[0] << ',' << data[1] << ',' << data[2] << '>'; }
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );

};

//**********************************************************
// TvWidget ROTATION
//**********************************************************
class TvWidget_rotation : public TvWidget {
	protected:
		float data[3];
		GtkWidget *spins[3];

	public:
		TvWidget_rotation(  const char *name, const char *sname, const char *tooltip, app_objs *appref ) : TvWidget( name, sname, tooltip, appref ) { set(0,0,0); }
		TvWidget_rotation( TvWidget_rotation & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_rotation *res = new TvWidget_rotation( *this ); return res; }
		void set( float x, float y, float z ) { data[0]=x; data[1]=y; data[2]=z; }		
		void copy( TvWidget *pt ) { for ( register int i = 0 ; i < 3 ; i++ ) data[i] = ((TvWidget_rotation*)pt)->data[i]; }
		void get( float & a,  float & b, float & c ) { a=data[0]; b=data[1]; c=data[2]; }
		void pref_changed() { set_tooltip(spins[0]); }
		void reduce_size();

		void get_widget( GtkWidget *box, bool tt );
		void flush();
		void gl_rotate();
		//GLfloat *gl_array() { GLfloat pos[] = { data[0], data[1], data[2] }; return pos; }
		void output_to_povray( ofstream & file ) { file << '<' << data[0] << ',' << data[1] << ',' << data[2] << '>'; }
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};


//**********************************************************
// TvWidget AXIS
//**********************************************************
class TvWidget_axis : public TvWidget {
	protected:
		TvWidget_option_combo *axis;
		TvWidget_float *offset;

	public:
		TvWidget_axis(  const char *name,  const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_axis( TvWidget_axis & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_axis *res = new TvWidget_axis( *this ); return res; }
		virtual ~TvWidget_axis();

		void get_widget( GtkWidget *box, bool tt );
		void copy( TvWidget *ax ) { axis->copy( ((TvWidget_axis*)ax)->axis ); offset->copy( ((TvWidget_axis*)ax)->offset ); }
		void clear_widget();
		void flush();
		void output_to_povray( ofstream & file );
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};

//**********************************************************
// TvWidget TRANSFORMATION
//**********************************************************
class TvWidget_transformation : public TvWidget {
	protected:
		TvWidget_bool_activator *transfo;
		TvWidget_rotation *rotate;
		TvWidget_point *scale;
		TvWidget_point *translate;

	public:
		TvWidget_transformation(  const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_transformation( TvWidget_transformation & ref );
		virtual TvWidget *duplicate_yourself()  { TvWidget_transformation *res = new TvWidget_transformation( *this ); return res; }
		virtual ~TvWidget_transformation();
		void copy( TvWidget *tr ) { TvWidget_transformation *to = (TvWidget_transformation*)tr; transfo->copy( to->transfo ); rotate->copy( to->rotate ); scale->copy( to->scale ); translate->copy( to->translate ); }

		void get_widget_wnframe( GtkWidget *box, bool tt, bool frame );
		void get_widget_noframe( GtkWidget *box, bool tt )  {  get_widget_wnframe( box, tt, false ); }
		void get_widget( GtkWidget *box, bool tt ) {  get_widget_wnframe( box, tt, true ); }
		void clear_widget();
		void flush();
		void output_to_povray( ofstream & file );
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};

class TvWidget_transformation_rb : public TvWidget_transformation  {
	protected:
		Rolling_box *rb;

	public:
		TvWidget_transformation_rb( const char *name, const char *sname, const char *tooltip, app_objs *appref )
			: TvWidget_transformation( name, sname, tooltip, appref )
			{ rb = new Rolling_box( name, app_ref, (TvWidget*)this ); }
		TvWidget_transformation_rb( TvWidget_transformation_rb & ref ) : TvWidget_transformation( ref ) { rb = new Rolling_box( *(ref.rb) );  rb->set_child( (TvWidget*)this ); }
		virtual TvWidget *duplicate_yourself() { TvWidget_transformation_rb *res = new TvWidget_transformation_rb( *this ); return res; }

		void get_widget_rb( GtkWidget *box, bool tt ) { rb->get_widget_rb( box, tt ); }
};

//**********************************************************
// TvWidget FILE
//**********************************************************
class TvWidget_file : public TvWidget {
	friend void sign_file_changed( GnomeFileEntry *fentry, gpointer data ) { ((TvWidget_file*)data)->file_changed(); }
	
	protected:
		TvWidget_path *path;
		TvWidget_bool *store;
		char **ext_list;
		char **def_list;
		int list_num;
		int type;
		bool loaded;
				
	public:
		TvWidget_file(  const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_file( TvWidget_file & ref );
		virtual TvWidget* duplicate_yourself() { TvWidget_file *res = new TvWidget_file( *this ); return res; }
		virtual ~TvWidget_file();
		void copy( TvWidget *fi ) { path->copy( ((TvWidget_file*)fi)->path ); store->copy( ((TvWidget_file*)fi)->store ); }

		void get_widget( GtkWidget *box, bool tt );
		void clear_widget();
		void flush();
		void set_list( const char **ext, const char **def, const int num );
		void output_to_povray( ofstream & file );
		void file_changed();
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};


//**********************************************************
// TvWidget Block Pattern
//**********************************************************
class TvWidget_blockpattern : public TvWidget {
	#define SENDER ((TvWidget_blockpattern*)data)
	friend void sign_blockp_type_changed( GtkWidget *wid, gpointer data ) { SENDER->type_changed(); }
	#undef SENDER

	protected:
		TvWidget_option_combo *type;
		TvWidget_point *bricksize;
		TvWidget_float *mortar;

		void type_changed();
		void (*func)(gpointer);
		gpointer data;

	public:
		TvWidget_blockpattern(  const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_blockpattern( TvWidget_blockpattern & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_blockpattern *res = new TvWidget_blockpattern( *this ); return res; }
		virtual ~TvWidget_blockpattern();

		int value() { return type->value(); }
		void copy( TvWidget *bp ) { TvWidget_blockpattern *bo = ( TvWidget_blockpattern*)bp; type->copy( bo->type ); bricksize->copy( bo->bricksize ); mortar->copy( bo->mortar ); }
		void get_widget( GtkWidget *box, bool tt );
		void connect_signal(void (*funcd)(gpointer) , gpointer datad ) { func=funcd; data=datad; }

		void clear_widget();
		void flush();
		void output_to_povray( ofstream & file );
		void output_to_povray_options( ofstream & file );
		void save( ofstream & file );
		bool load( ifstream & file, char *tag );
};


//**********************************************************
// TvWidget NOISE
//**********************************************************
class TvWidget_noise : public TvWidget {
	protected:
		TvWidget_bool_activator *use;
		TvWidget_point *turbulence;
		TvWidget_int *octaves;
		TvWidget_float *omega, *lambda;

	public:
		TvWidget_noise(  const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_noise( TvWidget_noise & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_noise *res = new TvWidget_noise( *this ); return res; }
		virtual ~TvWidget_noise();

		void copy( TvWidget *ns ) { TvWidget_noise *no = (TvWidget_noise*)ns; use->copy( no->use ); turbulence->copy( no->turbulence ); octaves->copy( no->octaves ); omega->copy( no->omega ); lambda->copy( no->lambda );  }
		void get_widget_wnframe( GtkWidget *box, bool tt, bool frame );
		void get_widget( GtkWidget *box, bool tt ) { get_widget_wnframe( box, tt, true ); }
		void get_widget_noframe( GtkWidget *box, bool tt ) { get_widget_wnframe( box, tt, false ); }
		void clear_widget();
		void flush();
		void output_to_povray( ofstream & file );
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};

class TvWidget_noise_rb : public TvWidget_noise  {
	protected:
		Rolling_box *rb;

	public:
		TvWidget_noise_rb( const char *name, const char *sname, const char *tooltip, app_objs *appref )
			: TvWidget_noise( name, sname, tooltip, appref )
			{ rb = new Rolling_box( name, app_ref, (TvWidget*)this ); }
		TvWidget_noise_rb( TvWidget_noise_rb & ref ) : TvWidget_noise( ref ) { rb = new Rolling_box( *(ref.rb) );  rb->set_child( (TvWidget*)this ); }
		virtual TvWidget* duplicate_yourself() { TvWidget_noise_rb *res = new TvWidget_noise_rb( *this ); return res; }

		void get_widget_rb( GtkWidget *box, bool tt ) { rb->get_widget_rb( box, tt ); }
};

//**********************************************************
// TvWidget WARP
//**********************************************************
class TvWidget_warp : public TvWidget {
	#define SENDER ((TvWidget_warp*)data)
	friend void sign_warptype_changed( GtkWidget *wid, gpointer data ) { SENDER->type_changed(); }
	#undef SENDER

	protected:
		TvWidget_bool_activator *use;
		TvWidget_option_combo *type;

		TvWidget_point *center, *repeat;
		TvWidget_float *radius, *falloff, *strength;
		TvWidget_bool *inverse;
		TvWidget_axis *repeat_axis;
		TvWidget_point *flip, *offset;
		TvWidget_point *turbulence;
		TvWidget_int *octaves;
		TvWidget_float *omega, *lambda;

		GtkWidget *changing_box, *activated_box;

	public:
		TvWidget_warp(  const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_warp( TvWidget_warp & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_warp *res = new TvWidget_warp( *this ); return res; }
		virtual ~TvWidget_warp();

		void copy( TvWidget *warp );
		void get_widget_wnframe( GtkWidget *box, bool tt, bool frame );
		void get_widget( GtkWidget *box, bool tt) { get_widget_wnframe( box, tt, true ); }
		void get_widget_noframe( GtkWidget *box, bool tt ) { get_widget_wnframe( box, tt, false ); }
		void type_changed();
		void clear_widget();
		void flush();
		void output_to_povray( ofstream & file );
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};

class TvWidget_warp_rb : public TvWidget_warp  {
	protected:
		Rolling_box *rb;

	public:
		TvWidget_warp_rb( const char *name, const char *sname, const char *tooltip, app_objs *appref )
			: TvWidget_warp( name, sname, tooltip, appref )
			{ rb = new Rolling_box( name, app_ref, (TvWidget*)this ); }
		TvWidget_warp_rb( TvWidget_warp_rb & ref ) : TvWidget_warp( ref ) { rb = new Rolling_box( *(ref.rb) );  rb->set_child( (TvWidget*)this ); }
		virtual TvWidget *duplicate_yourself() { TvWidget_warp_rb *res = new TvWidget_warp_rb( *this ); return res; }

		void get_widget_rb( GtkWidget *box, bool tt ) { rb->get_widget_rb( box, tt ); }
};

//**********************************************************
// TvWidget BLENDMAP
//**********************************************************
class TvWidget_blendmap : public TvWidget {
	#define SENDER ((TvWidget_blendmap*)data) 
	friend void sign_blendtype_changed( GtkWidget *wid, gpointer data ) { SENDER->type_changed(); }
	#undef SENDER
	protected:
		TvWidget_option_combo *type;
		TvWidget_float *agate_turb;
		TvWidget_point *gradient_dir;
		TvWidget_int *mandel_iterations;
		TvWidget_float *quilted_control1, *quilted_control0;
		TvWidget_file *density_file;
		TvWidget_bool *interpolate;
		TvWidget_int *spiral_arms;
		TvWidget_float *frequency, *phase;
		GtkWidget *option_box;
		bool colmap_mode;
		
	public:
		TvWidget_blendmap(  const char *name, const char *sname, const char *tooltip, app_objs *appref, bool is_colmap = false );
		TvWidget_blendmap( TvWidget_blendmap & ref );
		virtual TvWidget* duplicate_yourself() { TvWidget_blendmap *res = new TvWidget_blendmap( *this ); return res; }
		virtual ~TvWidget_blendmap();

		void copy( TvWidget *bm );
		int get_type() { return type->value(); }
		void get_widget( GtkWidget *box, bool tt );
		void type_changed();
		void clear_widget();
		void flush();
		void output_to_povray( ofstream & file );
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};


//**********************************************************
// TvWidget BLENDMAP MODIFIERS
//**********************************************************
class TvWidget_blendmap_mod : public TvWidget {
	#define SENDER ((TvWidget_blendmap_mod*)data) 
	friend void sign_wavetype_changed( GtkWidget *wid, gpointer data ) { SENDER->wavetype_changed(); }
	#undef SENDER
	protected:
		TvWidget_bool_activator *use;
		TvWidget_option_combo *waveform;
		TvWidget_float *frequency, *phase;
		TvWidget_float *polywave_count;
		
	public:
		TvWidget_blendmap_mod(  const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_blendmap_mod( TvWidget_blendmap_mod & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_blendmap_mod *res = new TvWidget_blendmap_mod( *this ); return res; }
		virtual ~TvWidget_blendmap_mod();

		void copy( TvWidget *bm );
		void get_widget( GtkWidget *box, bool tt );
		void wavetype_changed();
		void clear_widget();
		void flush();
		void output_to_povray( ofstream & file );
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};


//**********************************************************
// TvWidget BITMAP
//**********************************************************
class TvWidget_bitmap : public TvWidget {
	protected:
		TvWidget_file *file;
		TvWidget_option_combo *interpolate;
		TvWidget_option_combo *maptype;
		TvWidget_bool *once;
				
	public:
		TvWidget_bitmap(  const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_bitmap( TvWidget_bitmap & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_bitmap *res = new TvWidget_bitmap( *this ); return res; }
		virtual ~TvWidget_bitmap();

		void copy( TvWidget *bo ) { TvWidget_bitmap *bt = (TvWidget_bitmap*)bo;  file->copy( bt->file ); interpolate->copy( bt->interpolate ); maptype->copy( bt->maptype ); once->copy( bt->once ); }
		void get_widget( GtkWidget *box, bool tt );
		void clear_widget();
		void flush();
		void output_to_povray( ofstream & file );
		void output_to_povray_nodecl( ofstream & file );
		void save( ofstream & file );
		bool load( ifstream & file, char * tag );
};

//**********************************************************
// TvWidget BUMPMAP
//**********************************************************
class TvWidget_bumpmap : public TvWidget_bitmap {
	protected:
		TvWidget_bool *use_color;

	public:
		TvWidget_bumpmap( const char *name, const char *sname, const char *tooltip, app_objs *appref ) 
			: TvWidget_bitmap( name, sname, tooltip, appref )
			{ use_color = new TvWidget_bool( _("Use color"), "USED", NULL, appref, false ); }
		TvWidget_bumpmap( TvWidget_bumpmap & ref ) : TvWidget_bitmap( ref ) { use_color = new TvWidget_bool( *ref.use_color ); }
		virtual TvWidget *duplicate_yourself() { TvWidget_bumpmap *res = new TvWidget_bumpmap( *this ); return res; }
		virtual ~TvWidget_bumpmap() { delete use_color; }
		
       void copy( TvWidget *bm ) { use_color->copy( ((TvWidget_bumpmap*)bm)->use_color ); TvWidget_bitmap::copy( bm ); }
		void get_widget( GtkWidget *box, bool tt ) { TvWidget_bitmap::get_widget( box, tt ); use_color->get_widget( widget, tt ); }
		void clear_widget() { TvWidget_bitmap::clear_widget(); use_color->clear_widget(); }
		void flush() { TvWidget_bitmap::flush(); use_color->flush(); } 
		void output_to_povray( ofstream & file );
};


//**********************************************************
// TvWidget GLMAT
//**********************************************************
class TvWidget_glmat : public TvWidget {
	protected:
		TvWidget_color /**ambient,*/ *diffuse, *specular, *emission;
		TvWidget_float *shininess;

	public:
		TvWidget_glmat( const char *name, const char *sname, const char *tooltip, app_objs *appref );
		TvWidget_glmat( TvWidget_glmat & ref );
		virtual TvWidget *duplicate_yourself() { TvWidget_glmat *res = new TvWidget_glmat( *this ); return res; }
		virtual ~TvWidget_glmat();

		void copy( TvWidget *go ) { TvWidget_glmat *gm = (TvWidget_glmat*)go; /*ambient->copy( gm->ambient );*/ diffuse->copy( gm->diffuse ); specular->copy( gm->specular ); emission->copy( gm->emission );  shininess->copy( gm->shininess ); }
		void get_widget( GtkWidget *box, bool tt );
		void clear_widget();
		void flush();
		void gl_set_material();
		void save ( ofstream & file );
		bool load( ifstream & file, char * tag );
};


#endif
