/* -*- 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 "WinDialogs.hh"

/************************************************************************************************************************
 *															*
 *							FileSelectionDialog						*
 *															*
 ***********************************************************************************************************************/


std::string FileSelectionDialog::__path;

FileSelectionDialog::FileSelectionDialog(const std::string title)
	: Gtk::FileSelection(title), __filelist(NULL)
{
	get_cancel_button()->set_flags(Gtk::CAN_FOCUS);
	get_cancel_button()->set_relief(Gtk::RELIEF_NORMAL);
	
	get_ok_button()->set_flags(Gtk::CAN_FOCUS);
	get_ok_button()->set_relief(Gtk::RELIEF_NORMAL);
	
	set_border_width(10);
	set_title(title.empty() ? "Select file" : title);
	set_modal(true);
	property_window_position().set_value(Gtk::WIN_POS_CENTER);
	set_resizable(true);
	property_destroy_with_parent().set_value(false);
	show_fileop_buttons();
	show();
	
	get_cancel_button()->signal_clicked().connect(sigc::mem_fun(*this, &FileSelectionDialog::on_cancel_clicked));
	get_ok_button()->signal_clicked().connect(sigc::mem_fun(*this, &FileSelectionDialog::on_ok_clicked));

	if (!__path.empty()) 
		set_filename(__path);
}


void FileSelectionDialog::on_cancel_clicked() 
{
	this->response(Gtk::RESPONSE_CANCEL);
}


void FileSelectionDialog::on_ok_clicked() {
	
	// get the list of selected files
	Glib::ArrayHandle<std::string> files = get_selections();
	Glib::ArrayHandle<std::string>::const_iterator ibeg = files.begin();
	Glib::ArrayHandle<std::string>::const_iterator iend = files.end();
	
	// if the list contains some entries copy them into a stl::list 
	if (!files.empty()) {
	
		__filelist = new std::list<std::string>;
		
		while (ibeg != iend) {
			if ((*ibeg).length()) __filelist->push_back( *ibeg );
			ibeg++;
		}
	}
	
	std::string curr_path = get_filename();
	
	__path = curr_path.substr(0,curr_path.find_last_of('/')+1);
	this->response(Gtk::RESPONSE_OK);
}


std::list<std::string> * FileSelectionDialog::create_FilesSelectionDialog(const std::string title)
{
	// create file selection dialog
	FileSelectionDialog *fs = new class FileSelectionDialog(title); 

	// enable multiple file selections
	fs->set_select_multiple(true);
	
	// and run that dialog
	fs->run();
	
	std::list<std::string> *fl = fs->__filelist;
	
	// delete the dialog
	delete fs;
	
	// and return the filelist
	return fl;
}

std::string FileSelectionDialog::create_FileSelectionDialog(const std::string title)
{
	// create file selection dialog
	FileSelectionDialog *fs = new class FileSelectionDialog(title);
	
	// disable multiple file selections
	fs->set_select_multiple(false);

	// and run that dialog
	fs->run();
	
	std::string fn;
		
	if (fs->__filelist) {
		fn = fs->get_filename();
		delete fs->__filelist;
	}
	
	// delete the dialog
	delete fs;
	
	// and return the filename
	return fn;
}

std::string& FileSelectionDialog::path()
{
	return __path;
}


/************************************************************************************************************************
 *															*
 *							WinStringDialog							*
 *															*
 ***********************************************************************************************************************/


StringInputDialog::StringInputDialog(const std::string title, const std::string default_text)
{
	set_title(title);

	m_string_entry = Gtk::manage(new class Gtk::Entry());
	m_string_entry->set_flags(Gtk::CAN_FOCUS);
	m_string_entry->set_visibility(true);
	m_string_entry->set_editable(true);
	m_string_entry->set_max_length(0);
	m_string_entry->set_text(default_text);
	m_string_entry->set_has_frame(true);
	m_string_entry->set_activates_default(true);
	
	Gtk::VBox *vbox = this->get_vbox();
	vbox->set_border_width(10);
	vbox->set_spacing(6);
	vbox->pack_start(*m_string_entry, Gtk::PACK_SHRINK, 0);
	
	this->add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
	m_string_entry->show();	
	
	m_string_entry->signal_activate().connect( sigc::bind( sigc::mem_fun(*this, &StringInputDialog::response), Gtk::RESPONSE_OK));
}


std::string StringInputDialog::create_StringInputDialog(const std::string title, const std::string default_text)
{
	// create string dialog
	StringInputDialog *sd = new class StringInputDialog(title,default_text); 
	
	// and run that dialog
	sd->run();
	
	// thereafter retrieve the entered string
	std::string retval = sd->m_string_entry->get_text();
		
	// delete the dialog
	delete sd;
	
	// and return the string
	return retval;
}


/************************************************************************************************************************
 *															*
 *							StringListDialog						*
 *															*
 ***********************************************************************************************************************/
StringListDialog::StringListDialog(const std::string title, std::list<std::string> *strings) 
	: stringlist(strings)
{
	m_listview = Gtk::manage(new class Gtk::TreeView());
	m_listview->set_flags(Gtk::CAN_FOCUS);
	m_listview->set_headers_visible(false);
	m_listview->set_rules_hint(false);
	m_listview->set_reorderable(false);
	m_listview->set_enable_search(true);
	
	m_refTreeModel = Gtk::ListStore::create(m_columns);
	Gtk::CellRendererText* pRenderer = Gtk::manage( new Gtk::CellRendererText() );
	Gtk::TreeViewColumn* pColumn = m_listview->get_column(m_listview->append_column("Name", *pRenderer) - 1);
	pColumn->add_attribute(pRenderer->property_text(), m_columns.m_col_string);
	m_listview->set_model(m_refTreeModel);
	m_listview->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &StringListDialog::on_row_changed));

   
	m_textentry = Gtk::manage(new class Gtk::Entry());
	m_textentry->set_flags(Gtk::CAN_FOCUS);
	m_textentry->set_visibility(true);
	m_textentry->set_editable(true);
	m_textentry->set_max_length(0);
	m_textentry->set_text("");
	m_textentry->set_has_frame(true);
	m_textentry->set_activates_default(false);

	Gtk::Button *b_add = Gtk::manage(new class Gtk::Button("Add"));
	b_add->set_flags(Gtk::CAN_FOCUS);
	b_add->set_relief(Gtk::RELIEF_NORMAL);
	
	Gtk::Button *b_update = Gtk::manage(new class Gtk::Button("Update"));
	b_update->set_flags(Gtk::CAN_FOCUS);
	b_update->set_relief(Gtk::RELIEF_NORMAL);
	
	Gtk::Button *b_delete = Gtk::manage(new class Gtk::Button("Delete"));
	b_delete->set_flags(Gtk::CAN_FOCUS);
	b_delete->set_relief(Gtk::RELIEF_NORMAL);
	
	Gtk::Button *b_clear = Gtk::manage(new class Gtk::Button("Clear"));
	b_clear->set_flags(Gtk::CAN_FOCUS);
	b_clear->set_relief(Gtk::RELIEF_NORMAL);
	
	Gtk::HButtonBox *b_entrybuttonbox = Gtk::manage(new class Gtk::HButtonBox(Gtk::BUTTONBOX_END, 0));
	b_entrybuttonbox->pack_start(*b_add);
	b_entrybuttonbox->pack_start(*b_update);
	b_entrybuttonbox->pack_start(*b_delete);
	b_entrybuttonbox->pack_start(*b_clear);
	
	Gtk::Button *b_ok = Gtk::manage(new class Gtk::Button("OK"));
	b_ok->set_flags(Gtk::CAN_FOCUS);
	b_ok->set_relief(Gtk::RELIEF_NORMAL);
	
	Gtk::Button *b_cancel = Gtk::manage(new class Gtk::Button("Cancel"));
	b_cancel->set_flags(Gtk::CAN_FOCUS);
	b_cancel->set_relief(Gtk::RELIEF_NORMAL);
	
	get_action_area()->pack_start(*b_ok);
	get_action_area()->pack_start(*b_cancel);

	
	Gtk::VBox *b_vbox = get_vbox();
	b_vbox->set_border_width(2);
	b_vbox->pack_start(*m_listview);
	b_vbox->pack_start(*m_textentry, Gtk::PACK_SHRINK, 2);
	b_vbox->pack_start(*b_entrybuttonbox, Gtk::PACK_SHRINK, 0);

	
	m_listview->show();
	m_textentry->show();
	b_add->show();
	b_update->show();
	b_delete->show();
	b_clear->show();
	b_entrybuttonbox->show();
	b_ok->show();
	b_cancel->show();
	b_vbox->show();

	set_title(title);
	set_modal(true);
	property_window_position().set_value(Gtk::WIN_POS_CENTER);
	set_resizable(true);
	property_destroy_with_parent().set_value(false);
	set_default_size(100,100);
	show();
	
	b_add->signal_clicked().connect(sigc::mem_fun(*this, &StringListDialog::on_add_clicked));
	b_update->signal_clicked().connect(sigc::mem_fun(*this, &StringListDialog::on_update_clicked));
	b_delete->signal_clicked().connect(sigc::mem_fun(*this, &StringListDialog::on_delete_clicked));
	b_clear->signal_clicked().connect(sigc::mem_fun(*this, &StringListDialog::on_clear_clicked));
	b_ok->signal_clicked().connect(sigc::mem_fun(*this, &StringListDialog::on_ok_clicked));
	b_cancel->signal_clicked().connect(sigc::mem_fun(*this, &StringListDialog::on_cancel_clicked));	
	
	for (std::list<std::string>::iterator beg = strings->begin(); beg != strings->end(); beg++) {
		Gtk::TreeModel::Row row = *(m_refTreeModel->append());
		row[m_columns.m_col_string] = *beg;
	}
	
	this->set_size_request(360,300);
}


void StringListDialog::on_add_clicked()
{  
	if (m_textentry->get_text().empty()) return;
	Gtk::TreeModel::Row row = *(m_refTreeModel->append());
	row[m_columns.m_col_string] = m_textentry->get_text();
	m_textentry->set_text("");
}

void StringListDialog::on_update_clicked()
{  
	if (m_textentry->get_text().empty()) return;

	const Gtk::TreeModel::iterator selected = m_listview->get_selection()->get_selected();
	if (selected) (*selected)[m_columns.m_col_string] = m_textentry->get_text();
}

void StringListDialog::on_delete_clicked()
{  
	const Gtk::TreeModel::iterator selected = m_listview->get_selection()->get_selected();
	if (selected) m_refTreeModel->erase(selected);
}

void StringListDialog::on_clear_clicked()
{  
	m_textentry->set_text("");
	m_listview->get_selection()->unselect_all();	
}

void StringListDialog::on_ok_clicked()
{  
	stringlist->clear();
	
	Gtk::TreeModel::Children::iterator i_beg = m_refTreeModel->children().begin();
	Gtk::TreeModel::Children::iterator i_end = m_refTreeModel->children().end();

	while (i_beg != i_end) stringlist->push_back((*i_beg++)[m_columns.m_col_string]);
	
	this->response(Gtk::RESPONSE_OK);	
}

void StringListDialog::on_cancel_clicked()
{  
	this->response(Gtk::RESPONSE_CANCEL);
}

void StringListDialog::on_row_changed()
{
	const Gtk::TreeModel::iterator selected = m_listview->get_selection()->get_selected();
	if (selected) m_textentry->set_text(selected->get_value(m_columns.m_col_string));
}	



bool StringListDialog::create_StringListDialog(const std::string title, std::list<std::string> *strings)
{
	if (!strings) return false;
	
	// create string dialog
	StringListDialog *sld = new class StringListDialog(title, strings); 
	
	// and run that dialog
	int response_id = sld->run();
	
	// delete the dialog
	delete sld;

	// and return wheater the list has been changed
	return (response_id == Gtk::RESPONSE_OK);
}

