/* -*- mia-c++ -*-
 *
 * This file is part of viewitgui - a library and program for the
 * visualization of 3D data sets. 
 *
 * Copyright (c) Leipzig, Madrid 1999-2013 Mirco Hellmann, Gert Wollny
 *
 * viewitgui 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 3 of the License, or
 * (at your option) any later version.
 *
 * viewitgui 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 viewitgui; if not, see <http://www.gnu.org/licenses/>.
 */


#include "config.h"

#include "WinMain.hh"
#include <iostream>
#include <gtkmm.h>

#include "userini.hh"
#include "WinDialogs.hh"

#include <mia.hh>

//#include "../pixmaps/viewit_empty.xpm"

#include "pixmaps/clipplane32.xpm"
#include "pixmaps/mesh32.xpm"
//#include "pixmaps/colormesh32.xpm"
#include "pixmaps/arrowlist32.xpm"
#include "pixmaps/arrowlistgrow32.xpm"
#include "pixmaps/measure32.xpm"
#include "pixmaps/unknown32.xpm"
#include "pixmaps/slice32.xpm"
#include "pixmaps/selector32.xpm"
#include "pixmaps/pixel32.xpm"
#include "pixmaps/vectorfield32.xpm"
#include "pixmaps/smarties32.xpm"
#include "pixmaps/wireframe32.xpm"
#include "pixmaps/axes32.xpm"

#include <viewit/vistaloader.hh>
#include <viewit/glviewer.hh>
#include <viewit/event.hh>
#include <viewit/trajects.hh>
#include <viewit/clip_plane.hh>
#include <viewit/wireframe.hh>
#include <viewit/smarty.hh>
#include <viewit/arrow.hh>
#include <viewit/selector.hh>
#include <viewit/measure.hh>
#include <viewit/glmesh.hh>
#include <viewit/voxelmove.hh>
#include <viewit/glimage.hh>
#include <viewit/coordaxes.hh>
#include <viewit/sphere.hh>
#include <viewit/trajects.hh>


#include "progress_window.hh"

//Volumerenderer Options
#include <viewit/volumerenderer.hh>
#include "volume_options.hh"


#define SAGGITAL_SLICE "saggital slice"
#define CORONAL_SLICE  "coronal slice"
#define AXIAL_SLICE    "axial slice"
#define CRITICAL_POINT_LIST "critical points"
#define VECTORFIELD_CLASSNAME "C3DTransformation"
#define VIEWIT_ERROR_OPEN_FILE "unable to open file "


#ifdef ENABLE_NLS
#  include <libintl.h>
#  undef _
#  define _(String) dgettext (GETTEXT_PACKAGE, String)
#  ifdef gettext_noop
#    define N_(String) gettext_noop (String)
#  else
#    define N_(String) (String)
#  endif
#else
#  define textdomain(String) (String)
#  define gettext(String) (String)
#  define dgettext(Domain,Message) (Message)
#  define dcgettext(Domain,Message,Type) (Message)
#  define bindtextdomain(Domain,Directory) (Domain)
#  define _(String) (String)
#  define N_(String) (String)
#endif


const string axial_slice_str(AXIAL_SLICE);
const string coronal_slice_str(CORONAL_SLICE);
const string saggital_slice_str(SAGGITAL_SLICE);
const string critical_points_str(CRITICAL_POINT_LIST);

extern SignalHandler	*viewit_signal_handler;
extern XMLini		*inifile;
extern ViewitObjects	*vobjects;
extern CEventQueue	*pending_events;

///////////////////////////////////////////////////////////////////////////////
//
// class WinMain - construction and destruction
//
///////////////////////////////////////////////////////////////////////////////

//
// constructor
//
WinMain::WinMain(PGLViewer glview):
	m_glview(glview)
{
	cerr << "WinMain::WinMain()" << endl; 
	init_menu();
	
	//Create the Tree model:
	m_refTreeModel = Gtk::ListStore::create(m_Columns);
	add_columns();
	treeview1->set_model(m_refTreeModel);
	treeview1->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &WinMain::on_object_row_selected));

	// create pixmaps for treeview1	
	Icons[GLMESH_CLASSNAME]			= Gdk::Pixbuf::create_from_xpm_data(mesh32_xpm);	
	Icons[ARROWLIST_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(arrowlist32_xpm);
	Icons[ARROWLISTGROW_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(arrowlistgrow32_xpm);
	Icons[CLIPPLANE_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(clipplane32_xpm);
	Icons[FREECLIPPLANE_CLASSNAME]		= Icons[CLIPPLANE_CLASSNAME];
	Icons[SELECTOR_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(selector32_xpm);
	Icons[GLSLICE_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(slice32_xpm);
	Icons[VOXELCLOUD_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(pixel32_xpm);
	Icons[MEASURE_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(measure32_xpm);
	Icons[VECTORFIELD_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(vectorfield32_xpm);	
	Icons[SMARTIES_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(smarties32_xpm);	
	Icons[WIREFRAME_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(wireframe32_xpm);	
	Icons[COORDAXES_CLASSNAME]		= Gdk::Pixbuf::create_from_xpm_data(axes32_xpm);		
	Icon_Unknown				= Gdk::Pixbuf::create_from_xpm_data(unknown32_xpm);
	show_all_children();
	
	// get path for FileSelectionDialog used in the last session
	std::string section = "FileSelectionDialog";
	std::string key	    = "datapath";
	std::string value;
	inifile->get_value(section,key,FileSelectionDialog::path());

	// set the position for this widget
	section = "WinMain";
	key	= "position";
	
	int width  = 0;
	int height = 0;
	
	if (inifile->get_value(section,key,value)) {
		unsigned int pos = value.find_first_of(' ');
		width  = atoi(std::string(value.substr(0,pos)).c_str());
		height = atoi(std::string(value.substr(pos+1,value.length())).c_str());
	}		
	this->move(width,height);

	// set the size for this widget
	key	= "size";
	width   = 300;
	height  = 500;
	if (inifile->get_value(section,key,value)) {
		unsigned int pos = value.find_first_of(' ');
		width  = atoi(std::string(value.substr(0,pos)).c_str());
		height = atoi(std::string(value.substr(pos+1,value.length())).c_str());
	}		
	this->resize(width,height);

	
	init_plugins();
}

//
// destructor
//
WinMain::~WinMain() 
{
	std::string section;
	std::string key     = "visible";
	std::string value;
	
	section = "WinStatus";
	value   = view1_status->get_active() ? "true" : "false";
	inifile->set_value(section,key,value);

	section = "WinOptions";
	value   = view1_options->get_active() ? "true" : "false";
	inifile->set_value(section,key,value);
	
	section = "WinScene";
	value   = "true";
	inifile->set_value(section,key,value);
	
	section = "FileSelectionDialog";
	key	= "datapath";
	inifile->set_value(section,key,FileSelectionDialog::path());

	// write the current size of the widget to the config file	
	section = "WinMain";
	key	= "size";
	char buffer[255];
	int width,height;
	get_size(width,height);
	sprintf(buffer,"%d %d",width,height);
	value = buffer;
	inifile->set_value(section,key,value);
	
	// write the current position of the widget to the config file	
	key	= "position";
	get_position(width,height);
	sprintf(buffer,"%d %d",width,height);
	value = buffer;
	inifile->set_value(section,key,value);	
	
	delete m_plugin_search_paths;
}

void WinMain::init_plugins() 
{
	// get the plugin_paths from the configfile
	m_plugin_search_paths = new std::list<std::string>;
	std::string section = "PluginSearchPath";
	std::string key = "path0";
	std::string value;

	int pathidx = 1;

	
	while (inifile->get_value(section,key,value)) {
		m_plugin_search_paths->push_back(value);
		char buffer[10];
		sprintf(buffer,"path%d",pathidx++);
		key = buffer;
	}
	

}

void WinMain::on_create_surface_vectors_activate()
{
	if (!vobjects->field) {
		Gtk::MessageDialog("You have to load a vectorfield first!");
		return;
	}
	
	const Gtk::TreeModel::iterator selected = treeview1->get_selection()->get_selected();
	TDrawable *selected_object		= selected ? selected->get_value(m_Columns.m_col_object) : NULL;
	std::string object_type			= selected ? selected->get_value(m_Columns.m_col_type) : "";
	std::string object_name			= selected ? selected->get_value(m_Columns.m_col_name) : "";

	object_name = object_name + "_vectors";
	do {
		object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
	} while ( (object_name.length() > 0) &&
		  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );

	
	if ( object_type != GLMESH_CLASSNAME )
	{
		Gtk::MessageDialog("No mesh selected!");
		return;
	}
	
	TGLMesh *cm = dynamic_cast<TGLMesh *>(selected_object);
	
	CTriangleMesh::const_vertex_iterator b = cm->get_mesh()->vertices_begin();
	CTriangleMesh::const_vertex_iterator e = cm->get_mesh()->vertices_end(); 	

	TDrawable * trajects = new TArrowList(object_name,TColor(0.0,0.7,0.0,0.3),
					     TColor(.7,0.7,0.0,1.0),b,e,*vobjects->field);

	// and finally insert the object into the objectlist
	m_glview->add_object(trajects);
	add_object_to_list(trajects, trajects->get_classname(), object_name, false);	
	
}


///////////////////////////////////////////////////////////////////////////////
//
// class WinMain - functions to add and remove objects
//
///////////////////////////////////////////////////////////////////////////////

std::string WinMain::add_vectorfield(const std::string& filename, const std::string& object_name)
{
	std::string mesg; 
	
	const C3DTransformationIOPluginHandler::Instance&  vfioh = C3DTransformationIOPluginHandler::instance();
	
	auto field = vfioh.load(filename);
	
	if (field) {
		mesg += filename + " DONE\n";
		vobjects->field = field;
	} else
		mesg += VIEWIT_ERROR_OPEN_FILE + filename + "\n";

	
	// and finally insert it into the objectlist and reinit the glviewer
	if (vobjects->field) {
		vobjects->field_name = object_name;
		add_object_to_list(NULL, VECTORFIELD_CLASSNAME, object_name, false);
		m_glview->reinit(vobjects->field);
	}
	return mesg; 
}


void WinMain::add_vectorfield()
{
	
	
	// obtain the name of the file to load
	std::string filename	= FileSelectionDialog::create_FileSelectionDialog("Load vectorfield");
	
	if (filename.empty()) return;
	
	std::string mesg	= "Load vectorfield: ";
	
	// obtain the name of the new object
	std::string object_name = filename.substr(filename.find_last_of('/')+1,filename.length());
	do {
		object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
	} while ( (object_name.length() > 0) &&
		  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );

	//	get_root_window()->set_cursor(Gdk::Cursor(Gdk::WATCH));
	mesg += add_vectorfield(filename, object_name);
	
	// display a message
	viewit_signal_handler->WinStatus_append_text().emit(mesg);
	//	get_root_window()->set_cursor(Gdk::Cursor(Gdk::ARROW));
}

void WinMain::add_object_trajectories()
{
	if (!vobjects->field) {
		Gtk::MessageDialog("You have to load a vectorfield first!");
		return;
	}
	
	// obtain the name of the new object
	std::string object_name = vobjects->field_name + "_trajectories";
	do {
		object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
	} while ( (object_name.length() > 0) &&
		  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );

#if 0
	// create the trajectories
	TFieldTracer tracer(vobjects->field, 4.0f, 5.0f);
	unique_ptr<TVertexList> vlist = tracer.get_start_vertexes(); 

	TDrawable * trajects = new TArrowList(object_name,TColor(0.0,0.7,0.0,0.3),
					  TColor(.6,0.6,0.0,1.0),
					  *vlist,*vobjects->field);
	
	// and finally insert the object into the objectlist
	m_glview->add_object(trajects);
	add_object_to_list(trajects, trajects->get_classname(), object_name, false);
#endif 
}

void WinMain::add_object_voxelcloud()
{
	if (!vobjects->field) {
		Gtk::MessageDialog("You have to load a vectorfield first!");
		return;
	}
	
	if (vobjects->cloud) {
		Gtk::MessageDialog("You already have created a voxelcloud!");
		return;
	}

	TDeformation *defo= new TDeformation(*(vobjects->field),0.5); 
	
	vobjects->cloud = new TVoxelCloud("voxelcloud",5000, 1.0, 2000, *defo,C3DFVectorSource(vobjects->field->get_size()));
	vobjects->cloud->set_color1(TColor(0.0f, 1.0f, 0.0f,0.5f));
	vobjects->cloud->set_color2(TColor(1.0f, 0.0f, 0.0f,0.5f));		
	m_glview->add_object(vobjects->cloud);
	add_object_to_list(vobjects->cloud, vobjects->cloud->get_classname(), "voxelcloud", false);
}

std::string WinMain::add_object_mesh(const std::string& filename, const std::string& name, bool visible)
{
	std::string mesg;
	CLoadProgress load_progress; 

	auto tempmesh = CMeshIOPluginHandler::instance().load(filename);
	
	if (tempmesh) {
		TDrawable *mesh = new TGLMesh(name, tempmesh);	
		mesh->set_color1(TColor(.7,.7,.7,1.0));
		mesh->set_color2(TColor(.3,.3,1.0,1.0));
		mesh->set_color3(TColor(1.0,.3,.2,1.0));
		mesh->set_diffuse_front_color(TColor(0.9,0.9,0.9,1.0));	
		mesh->set_diffuse_back_color(TColor(0.7,1.0,0.9,1.0));
		
		m_glview->add_object(mesh);
		
		add_object_to_list(mesh, mesh->get_classname(), name, visible);
		
		if (visible) {
			mesh->show();
		}
		
		mesg += filename + " DONE\n";
	} else {
		mesg += "no mesh data found in " + filename + "\n";
	}
	return mesg;
}

std::string WinMain::add_object_points(const std::string& filename, const std::string& name, bool visible)
{
	std::string mesg;

	ifstream inf(filename.c_str());
	if (!inf.good())
		return filename + string(" not found"); 
	
	int n; 
	
	inf >> n; 
	
	TSphereList *points_object= new TSphereList(name);
	
	while (n-- && inf.good()) {
		C3DFVector loc(0,0,0); 
		float radius = 0; 
		TColor color(0,0,0,0); 

		string line; 
	
		inf >> loc.x >> loc.y >> loc.z >> color.x >> color.y >> color.z >> radius; 
		color /= 255.0;
		color.a = 1.0; 
		
		cvdebug() << "sphere" << loc << color << radius << endl; 
		if (inf.good())
			points_object->add_sphere(CSphereDescr(loc,radius,color));
		else if (!inf.eof()) {
			mesg += "bougus sphere list file '" + filename + "'\n";  
			delete points_object; 
			points_object = NULL; 
		}
	}

	if (points_object) {
		cvdebug() << "Created a points list\n";
		m_glview->add_object(points_object);
		if (visible)
			points_object->show(); 
		cvdebug() << "Add points list\n";
		
		add_object_to_list(points_object, points_object->get_classname(), name, visible);
		cvdebug() << "Add points list done\n"; 
		mesg += filename + " DONE\n";
	} else {
		mesg += "no points data found in " + filename + "\n";
	}
	return mesg;
}


void WinMain::add_object_points()
{

	std::list<std::string> *filenames = FileSelectionDialog::create_FilesSelectionDialog("Load point description");
	if (!filenames) return;
		
	std::list<std::string>::iterator i_beg = filenames->begin();
	std::list<std::string>::iterator i_end = filenames->end();
	
	std::string mesg;
	
	while (i_beg != i_end) {
		
		std::string object_name = *i_beg;
		object_name = object_name.substr(object_name.find_last_of('/')+1,object_name.length());
		mesg = "Load points: ";
		
		do {
			object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
		} while ( (object_name.length() > 0) &&
			  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );
		
		mesg += add_object_points(*i_beg, object_name, true);
		
		++i_beg;
		viewit_signal_handler->WinStatus_append_text().emit(mesg);
	}	
	cvdebug() << "add_object_points() done\n"; 
}

void WinMain::add_object_mesh()
{

	std::list<std::string> *filenames = FileSelectionDialog::create_FilesSelectionDialog("Load mesh");
	if (!filenames) return;
		
	std::list<std::string>::iterator i_beg = filenames->begin();
	std::list<std::string>::iterator i_end = filenames->end();
	
	std::string mesg;
	
	while (i_beg != i_end) {
		
		std::string object_name = *i_beg;
		object_name = object_name.substr(object_name.find_last_of('/')+1,object_name.length());
		mesg = "Load mesh: ";
		
		do {
			object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
		} while ( (object_name.length() > 0) &&
			  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );
		
		mesg += add_object_mesh(*i_beg, object_name, false);
		
		i_beg++;
		viewit_signal_handler->WinStatus_append_text().emit(mesg);
	}	
}

void WinMain::add_object_colormesh()
{
	std::cout << "WinMain::add_object_colormesh\n" << std::endl;
	
	if (!vobjects->field) {
		Gtk::MessageDialog("You have to load a vectorfield first!");
		return;
	}

	const Gtk::TreeModel::iterator selected = treeview1->get_selection()->get_selected();
	TDrawable *selected_object		= selected ? selected->get_value(m_Columns.m_col_object) : NULL;
	std::string object_type			= selected ? selected->get_value(m_Columns.m_col_type) : "";
	std::string object_name			= selected ? selected->get_value(m_Columns.m_col_name) : "";
	
	if ( object_type != GLMESH_CLASSNAME )
	{
		Gtk::MessageDialog("No mesh selected!");
		return;
	}
	
	//TDrawable *colored_mesh = NULL;
	
	TGLMesh *cm = dynamic_cast<TGLMesh *>(selected_object);
	if (cm) {
		colorize_mesh(cm->get_mesh(),*(vobjects->field));
		cm->set_color1(TColor(0.7,0.7,0.7,0.7));
		cm->set_color2(TColor(0.3,0.3,1.0,0.7));
		cm->set_color3(TColor(1.0,0.3,0.2,0.7));
		cm->apply_color_change();
		// show the color legend and force a redraw
		event_t event;
		event.what = event_t::ev_command; 
		event.info = PEventInfo(new CEventInfo(EV_GLMESH_TOGGLE_COLORSCALE));
		pending_events->push(event);
		on_object_row_selected();
	} else
		std::cerr<<" No mesh?" << std::endl;  
}
	


#if 0
						 
void WinMain::add_object_texture()
{
	std::string filename = FileSelectionDialog::create_FileSelectionDialog("Load 3D textur image");
	if (filename.empty()) return;	
	
	
	C3DImageIOPluginHandler imageio;
	auto_ptr<C3DImageList>
		//image_list(imageio.load(options::in_filename));
		image_list(imageio.load(filename));
                if (! image_list.get() || !image_list->size()) {
			string not_found = ("No supported data found in" + filename);
			return; 
		}
	
	C3DImageWrap& imagew = *image_list->begin();

	if (imagew.get_type() == it_ubyte) {
		
		C3DUBImage *image = new C3DUBImage(*imagew.getC3DUBImage());
		
	}	
	

}

#endif

void WinMain::add_object_cplist() 
{
#if 1
	std::cerr << "FIXME:cp loading not yet supported in mona" << std::endl; 
#else
	if (!vobjects->field) {
		Gtk::MessageDialog("You have to load a vectorfield first!");
		return;
	}

	std::string filename = FileSelectionDialog::create_FileSelectionDialog("Load CP-List");
	if (filename.empty()) return;

	std::string mesg = "Load critical point list: ";
	std::string object_name = critical_points_str;
	
	do {
		object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
	} while ( (object_name.length() > 0) &&
		  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );

	FILE *file = fopen(filename.c_str(),"r");
	if (file) {
		CCPEList cpe_list;
		if (load_cp_eigen(file, &cpe_list)) {
			vobjects->cplist = new TCPDrawList(object_name,*vobjects->alpha);
			CCPEList::const_iterator c_i = cpe_list.begin();
			while (c_i != cpe_list.end()) {
				if ( fabs((*c_i).get_eval1()) >= 1 &&
				     fabs((*c_i).get_eval2()) >= 1 && 
				     fabs((*c_i).get_eval3()) >= 1)
					vobjects->cplist->add(TCPAppearance(*c_i));
				++c_i;
			}
			m_glview->add_object(vobjects->cplist);
			add_object_to_list(vobjects->cplist,vobjects->cplist->get_type(),object_name,false);
			mesg += filename + " DONE\n";
		}else{
			mesg += "No cplist found in " + filename + "\n"; 
		}
	} else {
		mesg += VIEWIT_ERROR_OPEN_FILE + filename + "\n";
	}
	viewit_signal_handler->WinStatus_append_text().emit(mesg);	
#endif	
}

						 
void WinMain::add_object_texture()
{
#ifndef VOLUME_RENDERER
	std::string filename = FileSelectionDialog::create_FileSelectionDialog("Load 3D textur image");
	if (filename.empty()) return;

	std::string mesg = "Load 3D texture image: ";
	

	auto pimage = load_image3d(filename);
	if (! pimage) {
		string not_found = ("No supported data found in" + filename);
		return; 
	}

	// load the textur image
	pimage = run_filter(*pimage, "convert:repn=ubyte");
	
	const C3DUBImage& lumindata = static_cast<const C3DUBImage&>(*pimage); 

	TDrawable *xy_slice = new TXYGLSlice(axial_slice_str, lumindata, P3DTransformation ());
	TDrawable *xz_slice = new TXZGLSlice(coronal_slice_str, lumindata, P3DTransformation ());
	TDrawable *yz_slice = new TYZGLSlice(saggital_slice_str, lumindata, P3DTransformation ());
	
	remove_object_from_list(axial_slice_str, true);
	remove_object_from_list(coronal_slice_str, true);
	remove_object_from_list(saggital_slice_str, true);
		
	m_glview->add_object(xy_slice);
	add_object_to_list(xy_slice, xy_slice->get_classname(), xy_slice->get_name(), false);
	m_glview->add_object(xz_slice);
	add_object_to_list(xz_slice, xz_slice->get_classname(), xz_slice->get_name(), false);
	m_glview->add_object(yz_slice);
	add_object_to_list(yz_slice, yz_slice->get_classname(), yz_slice->get_name(), false);
	mesg += filename + " DONE\n";
		
	viewit_signal_handler->WinStatus_append_text().emit(mesg);
#else 
	std::string filename = FileSelectionDialog::create_FileSelectionDialog("Load volume file");
	if (filename.empty()) 
		return;	
	
	auto pimage = load_image3d(filename);
	if (! pimage) {
		string not_found = ("No supported data found in" + filename);
		return; 
	}
	
	if (pimage->get_pixel_type() == it_ubyte) {
		const C3DUBImage& image = dynamic_cast<const C3DUBImage&>(*pimage);
		
	// Create Volume renderer with image	
		
		
		std::string mesg	= "Show Volume";
		std::string object_name = filename.substr(filename.find_last_of('/')+1,filename.length());	
		
		do {
			object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
		} while ( (object_name.length() > 0) &&
			  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );
	
		TVolumeRenderer *VolumeRenderer = new TVolumeRenderer(object_name, image);
		TDrawable *object = VolumeRenderer;
		
		m_glview->add_object(object);						//adding the object to viewer
		add_object_to_list(object,object->get_type(),object_name,false);

#warning is this a memory leak or what???		
		volume_options *volume_options = new class volume_options();		//init options dialog
		volume_options->VolumeRenderer=VolumeRenderer;				//passing a handle to the volumerenderer
		
		viewit_signal_handler->WinStatus_append_text().emit(mesg);
	}	

#endif
}
 

void WinMain::add_object_wireframe()
{
	std::string filename = FileSelectionDialog::create_FileSelectionDialog("Load wireframe file");
	if (filename.empty()) return;

	std::string mesg	= "Load wireframe file: ";
	std::string object_name = filename.substr(filename.find_last_of('/')+1,filename.length());	
	
	do {
		object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
	} while ( (object_name.length() > 0) &&
		  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );

	TDrawable *object = NULL;
	
	// load the wireframe file
	
	if ((object=load_wireframe(object_name,filename))) {
		mesg += filename + " DONE\n";
		m_glview->add_object(object);
		add_object_to_list(object,object->get_type(),object_name,false);
	} else
		mesg += "no wireframe data found in " + filename + "\n";
	
	viewit_signal_handler->WinStatus_append_text().emit(mesg);		
}




void WinMain::add_object_tensorfield()
{
	std::string filename = FileSelectionDialog::create_FileSelectionDialog("Load tensordata file");
	if (filename.empty()) return;

	std::string mesg	= "Load tensordata file: ";
	std::string object_name = filename.substr(filename.find_last_of('/')+1,filename.length());	
	
	do {
		object_name = StringInputDialog::create_StringInputDialog("Enter name for this object",object_name);
	} while ( (object_name.length() > 0) &&
		  (m_glview->get_object_map()->find(object_name) != m_glview->get_object_map()->end()) );

	TDrawable *object = NULL;
	
	// load the tensordata file 
	if ( (object = load_tensorfield(object_name,filename)) ) {
		mesg += filename + " DONE\n";
		m_glview->add_object(object);
		add_object_to_list(object,object->get_classname(),object_name,false);
		std::cout << "WinMain::add_object_tensorfield : " << object->get_classname() << std::endl;
	} else
		mesg += "no tensordata found in " + filename + "\n";
	
	viewit_signal_handler->WinStatus_append_text().emit(mesg);		
}


void WinMain::remove_object_selected()
{
	const Gtk::TreeModel::iterator selected = treeview1->get_selection()->get_selected();
	
	if (!selected) return;
	
	std::string obj_name  = (*selected)->get_value(m_Columns.m_col_name);
	std::string classname = (*selected)->get_value(m_Columns.m_col_type);
	
	std::cout << classname << endl;
	
	if (classname == CLIPPLANE_CLASSNAME) {
		return; // default object
	} else if (classname == ARROWLISTGROW_CLASSNAME) {
		if (obj_name == "arrow_edited") return; // default object
		remove_object_from_list(obj_name,true);
	} else if (classname == SELECTOR_CLASSNAME || classname == MEASURE_CLASSNAME) {
		return; // default object
	} else if (classname == VOXELCLOUD_CLASSNAME) {
		
		remove_object_from_list(obj_name,true);
		vobjects->cloud = NULL;
	} else if (classname == GLSLICE_CLASSNAME) {
		remove_object_from_list(axial_slice_str,true);
		remove_object_from_list(coronal_slice_str,true);
		remove_object_from_list(saggital_slice_str,true);
	} else if (classname == CPDRAWLIST_CLASSNAME) {
		remove_object_from_list(obj_name,true);
		vobjects->cplist = NULL;
	} else if (classname == VECTORFIELD_CLASSNAME) {
		
		// if there is a voxelcloud or a cplist it has to be removed at first so ask the user
		int remove_it = Gtk::RESPONSE_YES;
		
		if (vobjects->cloud || vobjects->cplist) {
			Gtk::MessageDialog dialog("All depending objects will be removed!\rDo you wish to continue?", false,
						  Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO,  false);
			remove_it = dialog.run();
		}
		
		if (remove_it == Gtk::RESPONSE_YES) {
			
			// remove the voxelcloud
			if (vobjects->cloud) {
				remove_object_from_list(vobjects->cloud->get_name(),true);
				vobjects->cloud = NULL;
			}
			
			// remove the cplist
			if (vobjects->cplist) {
				remove_object_from_list(vobjects->cplist->get_name(),true);
				vobjects->cplist = NULL;
			}
				
			// finally delete the vectorfield 
			m_glview->reinit(NULL);
			remove_object_from_list(obj_name,false);
		}
	}else
		 remove_object_from_list(obj_name,true);
	
}
///////////////////////////////////////////////////////////////////////////////
//
// class WinMain - event handling - menus
//
///////////////////////////////////////////////////////////////////////////////

void WinMain::on_open_scene_activate()
{}

void WinMain::on_save_scene_activate()
{;}


void WinMain::on_snapshot_activate()
{
	event_t event;
	event.what = event_t::ev_command; 
	event.info = PEventInfo(new CEventInfo(EV_GLVIEWER_SNAP_THIS));
	pending_events->push(event);
}


void WinMain::on_quit_activate()
{  
	Gtk::Main::quit();	
}

void WinMain::on_about_activate()
{
	Gtk::AboutDialog dialog; 

	std::vector< Glib::ustring > authors; 
	authors.push_back("Mirko Hellmann"); 
	authors.push_back("Gert Wollny"); 

	dialog.set_program_name("mia-viewitgui"); 
	dialog.set_version ("1.0"); 
	dialog.set_copyright ("This software is Copyright (c) 1999-2013 Leipzig, Germany\n"
			      "and Madrid, Spain. It comes with ABSOLUTELY NO WARRANTY and\n"
			      "you may redistribute it under the terms of the GNU GENERAL\n"
			      "PUBLIC LICENSE Version 3 (or later)."); 
	dialog.set_authors(authors);  
	// not supported in gtkmm < 3.0
        // dialog.set_license_type (LICENSE_GPL_3_0); 
	dialog.set_website("http://sourceforge.net/p/mia/wiki/viewit-gui/"); 
	dialog.set_website_label("Online tutorial"); 

	dialog.run(); 
}

void WinMain::on_object1_activate()
{
	const Gtk::TreeModel::iterator selected = treeview1->get_selection()->get_selected();
	//TDrawable *selected_object		= selected ? selected->get_value(m_Columns.m_col_object) : NULL;
	std::string object_type			= selected ? selected->get_value(m_Columns.m_col_type) : "";
	
	if (vobjects->field) {
		object1_add_vectorfield->hide();
		object1_add_trajectories->show();
		
		if (vobjects->cplist) object1_add_cplist->hide();
		else object1_add_cplist->show();
		
		if (vobjects->cloud) object1_add_voxels->hide(); 
		else object1_add_voxels->show();
		
		if ( object_type == GLMESH_CLASSNAME ) 
			object1_add_colormesh->show();
		else 
			object1_add_colormesh->hide();
	}
	else {
		object1_add_vectorfield->show();
		object1_add_trajectories->hide();
		object1_add_voxels->hide();
		object1_add_colormesh->hide();
		object1_add_cplist->hide();
	}
}

void WinMain::extn1_plugins_activate()
{
	bool changed = StringListDialog::create_StringListDialog("Plugin search paths",m_plugin_search_paths);
	
	if (changed) {
		std::string section = "PluginSearchPath";
		std::string key;
		std::string value;
		char buffer[10];
		
		std::list<std::string>::iterator ibeg = m_plugin_search_paths->begin();
		std::list<std::string>::iterator iend = m_plugin_search_paths->end();
		unsigned int pathidx = 0;
		
		inifile->remove_section(section);
		
		while (ibeg != iend) {
			sprintf(buffer,"path%d",pathidx++);
			key   = std::string(buffer);
			value = *ibeg++;
			inifile->set_value(section,key,value);
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
//
// class WinMain - event handling - toolbar
//
///////////////////////////////////////////////////////////////////////////////

void WinMain::on_resize1_clicked() 
{
	viewit_signal_handler->WinScene_resize().emit(675,900);
}


void WinMain::on_resize2_clicked()
{
	viewit_signal_handler->WinScene_resize().emit(1024,768);
}


void WinMain::on_unselect_clicked()
{
	treeview1->get_selection()->unselect_all();
}



///////////////////////////////////////////////////////////////////////////////
//
// class WinMain - event handling - called from viewit_signal_handler
//
///////////////////////////////////////////////////////////////////////////////


void WinMain::on_WinMain_hide_notification(std::string sender) 
{
	if (sender == "WinStatus") view1_status->set_active(false);	
	if (sender == "WinScene") view1_scene->set_active(false);
	if (sender == "WinOptions") view1_options->set_active(false);
}

void WinMain::on_WinMain_objectmap_changed() 
{
	// insert the standard objects into the object list
 	const TDrawMap *objmap = m_glview->get_object_map();
	
	Gtk::TreeModel::Children children = m_refTreeModel->children();
	Gtk::TreeModel::Children::iterator i_beg;
	Gtk::TreeModel::Children::iterator i_end;

	
	TDrawMap::const_iterator om_beg = objmap->begin();
	TDrawMap::const_iterator om_end = objmap->end();
	
	while (om_beg != om_end) {

		i_beg = children.begin();
		i_end = children.end();
		
		while (i_beg != i_end) {
			std::string obj_name = (*i_beg)[m_Columns.m_col_name];
			if (obj_name == (*om_beg).first) break;
			i_beg++;
		}
	
		if ( i_beg == i_end) 
			add_object_to_list((*om_beg).second,(*om_beg).second->get_classname(),(*om_beg).first,false);
		
		om_beg++;
	}
}
///////////////////////////////////////////////////////////////////////////////
//
// class WinMain - event handling - others
//
///////////////////////////////////////////////////////////////////////////////

bool WinMain::on_WinMain_delete_event(GdkEventAny *ev)
{  
	viewit_signal_handler->WinScene_detach().emit();
	return false;
}

void WinMain::on_view1_menu_element_activated(Gtk::CheckMenuItem *sender, std::string name) {
	
	if (name == "WinStatus")	viewit_signal_handler->WinStatus_set_visibility().emit(sender->get_active());
	else if (name == "WinScene")	viewit_signal_handler->WinScene_set_visibility().emit(sender->get_active());
	else if (name == "WinOptions")	viewit_signal_handler->WinOptions_set_visibility().emit(sender->get_active());
}


void WinMain::on_object_visibility_toggled(const Glib::ustring& path_string)
{
	
	// Get the model row that has been toggled.
	Gtk::TreeModel::Row row = *m_refTreeModel->get_iter(Gtk::TreeModel::Path(path_string));
	row[m_Columns.m_col_visible] = ! row[m_Columns.m_col_visible];
	
	// and toogle the visibility of the corresponding object
	viewit_signal_handler->WinScene_press_key().emit(VIEWIT_KEY_TOGGLE_VISIBILITY);
}



void WinMain::on_object_row_selected()
{
	// Get the model row that has been selected
	const Gtk::TreeModel::iterator selected = treeview1->get_selection()->get_selected();
	
	Glib::RefPtr<Gdk::Pixbuf> selected_icon = Icon_Unknown;
	TDrawable *selected_object = NULL;
	
	if (selected) {
		
		// get the name and type of the selected object
		std::string obj_type = selected->get_value(m_Columns.m_col_type);
		std::string object_name = selected->get_value(m_Columns.m_col_name);

		IconMapType::iterator IconIter = Icons.find(selected->get_value(m_Columns.m_col_type));
		if (IconIter != Icons.end()) selected_icon = (*IconIter).second;
		
		if (obj_type == VECTORFIELD_CLASSNAME) {
			//viewit_signal_handler->WinOptions_set_vectorfield().emit(vobjects->field, object_name, selected_icon);
			viewit_signal_handler->WinOptions_set_object().emit(NULL, NULL, selected_icon);
			m_glview->select("");
		} else {
			m_glview->select(object_name);
			selected_object = selected->get_value(m_Columns.m_col_object);
			viewit_signal_handler->WinOptions_set_object().emit(selected_object, vobjects->field, selected_icon);
		}
	} else {
		m_glview->select("");
		viewit_signal_handler->WinOptions_set_viewer().emit(selected_icon);
	}
		
	
}

///////////////////////////////////////////////////////////////////////////////
//
// class WinMain - other functions
//
///////////////////////////////////////////////////////////////////////////////



void WinMain::init_menu()
{
	std::string section = "WinStatus";
	std::string key     = "visible";
	std::string value   = "";
	

	//
	// menuitem view1_status
	//
	view1_status->signal_activate().connect( sigc::bind( sigc::mem_fun(*this, &WinMain::on_view1_menu_element_activated) , view1_status, "WinStatus") );
	if (!inifile->get_value(section,key,value)) {
		value = "true";
		inifile->set_value(section,key,value);
	}
	view1_status->set_active(value == "true");
	

	//
	// menuitem view1_options
	//
	section = "WinOptions";
	view1_options->signal_activate().connect(sigc::bind( sigc::mem_fun(*this, &WinMain::on_view1_menu_element_activated), view1_options, "WinOptions") );
	if (!inifile->get_value(section,key,value)) {
		value = "true";
		inifile->set_value(section,key,value);
	}
	view1_options->set_active(value == "true");
	
	//
	// menuitem view1_scene
	//
	section = "WinScene";
	view1_scene->signal_activate().connect(sigc::bind( sigc::mem_fun(*this, &WinMain::on_view1_menu_element_activated), view1_scene, "WinScene") );
	if (!inifile->get_value(section,key,value)) {
		value = "true";
		inifile->set_value(section,key,value);
	}
	view1_scene->set_active(value == "true");
}

///////////////////////////////////////////////////////////////////////////////
//
// class WinMain - object list
//
///////////////////////////////////////////////////////////////////////////////

void WinMain::Icon_SlotCell_data (Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator& iter)
{
	const Gtk::TreeModel::Row row = *iter;
	Gtk::CellRendererPixbuf *pRenderer = dynamic_cast<Gtk::CellRendererPixbuf *>(cell);
	IconMapType::iterator IconIter = Icons.find(row[m_Columns.m_col_type]);
	pRenderer->property_pixbuf() = (IconIter != Icons.end()) ? (*IconIter).second : Icon_Unknown;
}


void WinMain::Visible_SlotCell_data (Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator& iter)
{
	const Gtk::TreeModel::Row row = *iter;
	Gtk::CellRendererToggle *pRenderer = dynamic_cast<Gtk::CellRendererToggle *>(cell);
	pRenderer->property_visible() = row[m_Columns.m_col_has_visibility];
}


void WinMain::add_columns()
{
	// column for object type icon 
	{
		// create a pixbufrenderer and a slot to show the correct icon in the object list
		Gtk::CellRendererPixbuf* pRenderer = Gtk::manage( new Gtk::CellRendererPixbuf() );
		Gtk::TreeViewColumn::SlotCellData *slot = new Gtk::TreeViewColumn::SlotCellData(sigc::mem_fun(*this, &WinMain::Icon_SlotCell_data));
		
		int cols_count = treeview1->append_column("Type", *pRenderer);
		Gtk::TreeViewColumn* pColumn = treeview1->get_column(cols_count-1);
		pColumn->set_cell_data_func (*pRenderer, *slot);
	}

	// column for object name 
	{
		Gtk::CellRendererText* pRenderer = Gtk::manage( new Gtk::CellRendererText() );
		
		int cols_count = treeview1->append_column("Name", *pRenderer);
		Gtk::TreeViewColumn* pColumn =treeview1->get_column(cols_count-1);

		pColumn->add_attribute(pRenderer->property_text(), m_Columns.m_col_name);
	}
	
	// column for object visibility 
	{
		Gtk::CellRendererToggle* pRenderer = Gtk::manage( new Gtk::CellRendererToggle() );
		Gtk::TreeViewColumn::SlotCellData *slot = new Gtk::TreeViewColumn::SlotCellData(sigc::mem_fun(*this, &WinMain::Visible_SlotCell_data));
		
		int cols_count = treeview1->append_column("Visible", *pRenderer);
		Gtk::TreeViewColumn* pColumn = treeview1->get_column(cols_count-1);
		pColumn->add_attribute(pRenderer->property_active(), m_Columns.m_col_visible);
		pColumn->set_cell_data_func(*pRenderer, *slot);
		pColumn->set_fixed_width(40);
		pColumn->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED);		
		pColumn->set_clickable();
		pRenderer->signal_toggled().connect(sigc::mem_fun(*this, &WinMain::on_object_visibility_toggled));
	}
	

}


void WinMain::add_object_to_list(TDrawable *obj_ptr, const std::string obj_type, const std::string obj_name, const bool visible) 
{
	Gtk::TreeModel::Row row = *(m_refTreeModel->append());
	row[m_Columns.m_col_name] = obj_name;
	row[m_Columns.m_col_visible] = visible;
	row[m_Columns.m_col_type] = obj_type;
	row[m_Columns.m_col_object] = obj_ptr;

	bool has_visi = !((obj_type == MEASURE_CLASSNAME) || 
			  (obj_type == CLIPPLANE_CLASSNAME) || 
			  (obj_type == SELECTOR_CLASSNAME) || 
			  (obj_type == FREECLIPPLANE_CLASSNAME) ||
			  (obj_type == VECTORFIELD_CLASSNAME));
	row[m_Columns.m_col_has_visibility] = has_visi;
	treeview1->get_selection()->select(row);
}


void WinMain::remove_object_from_list(const std::string &obj_name, bool remove_from_viewer)
{
	treeview1->get_selection()->unselect_all();
	m_glview->select("unselect");
	
	if (remove_from_viewer)
		if (!m_glview->remove_object(obj_name)) return;
	
	Gtk::TreeModel::Children children = m_refTreeModel->children();
	Gtk::TreeModel::Children::iterator i_beg = children.begin();
	Gtk::TreeModel::Children::iterator i_end = children.end();

	std::string tempname;
	
	while (i_beg != i_end) {
		
		tempname = (*i_beg)[m_Columns.m_col_name];
		if ( tempname == obj_name ) {
			m_refTreeModel->erase(i_beg);
			i_beg = i_end;
			continue;
		}
		
		i_beg++;
	}
}


void WinMain::on_open_view_anterior() 
{
}

void WinMain::on_open_view_posterior()
{
}

void WinMain::on_open_view_left()    
{
}

void WinMain::on_open_view_right()
{
}

void WinMain::on_open_view_top()
{
}

void WinMain::on_open_view_bottom()
{
}

void WinMain::on_open_view_background()
{
	TColor c_bg = m_glview->get_bg_color();
	
	Gdk::Color current_color;
	
	current_color.set_rgb(gushort(0xFFFF * c_bg.x), 
			      gushort(0xFFFF * c_bg.y), 
			      gushort(0xFFFF * c_bg.z));
	Gtk::ColorSelectionDialog amy(_("Select new background colour"));
	
	amy.get_colorsel()->set_current_color(current_color);
	
	
	switch (amy.run()) {
	case Gtk::RESPONSE_OK: 
		current_color = amy.get_colorsel()->get_current_color();
		break; 
	}
	
	c_bg.x = current_color.get_red() / (1.0 * 0xFFFF);
	c_bg.y = current_color.get_green() / (1.0 * 0xFFFF);
	c_bg.z = current_color.get_blue() / (1.0 * 0xFFFF);

	cerr << c_bg << endl; 
	m_glview->set_bg_color(c_bg);
}

