// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Implements the rename_object_dialog class, which provides a UI for renaming a K-3D object
		\author Tim Shead (tshead@k-3d.com)
*/


#include "edit_control.h"
#include "k3ddialog.h"
#include "rename_object_dialog.h"

#include <k3dsdk/iobject.h>
#include <k3dsdk/state_change_set.h>

#include <sdpgtk/sdpgtkevents.h>

namespace
{

const std::string control_oldname = "oldname";
const std::string control_newname = "newname";
const std::string control_ok = "ok";
const std::string control_cancel = "cancel";

/////////////////////////////////////////////////////////////////////////////
// rename_object_dialog

/// Provides a user interface for changing an object's name
class rename_object_dialog :
	public k3dDialog
{
	typedef k3dDialog base;
	
public:
	rename_object_dialog(k3d::iobject& Object) :
		base(&Object, "rename", new k3d::options_window_geometry_store()),
		m_name(Object.name()),
		m_object(Object)
	{
		// We want to be notified if the object is renamed or deleted
		m_object.name_changed_signal().connect(SigC::slot(*this, &rename_object_dialog::on_object_renamed));
		m_object.deleted_signal().connect(SigC::slot(*this, &rename_object_dialog::on_object_deleted));

		return_if_fail(LoadGTKMLTemplate("renameobject.gtkml"));

		k3d::edit_control::control* const control = dynamic_cast<k3d::edit_control::control*>(CustomObject(control_newname.c_str()));
		if(control)
			{
				control->attach(k3d::edit_control::proxy(m_name), 0, "Name");
				control->set_focus();
			}

		on_object_renamed();

		Widget(control_ok).GrabDefault();

		Show();
	}

	~rename_object_dialog()
	{
		// No more events from this point forward ...
		DisconnectAllEvents();

		// Clean-up the GTK+ tree ...
		if(Root())
			RootWidget().Destroy();

		// Get rid of our widget pointers ...
		Clear();
	}

private:	
	void OnEvent(sdpGtkEvent* Event)
	{
		// Sanity checks ...
		assert_warning(Event);

		if(Event->Name() == control_newname)
			OnNewName();
		else if(Event->Name() == control_ok)
			OnOK();
		else if(Event->Name() == control_cancel)
			OnCancel();
		else if(Event->Name() == "activate")
			OnOK();
		else
			base::OnEvent(Event);
	}

	void OnDelete(sdpGtkEvent* Event)
	{
		// Sanity checks ...
		assert_warning(Event);

		// Don't let it happen ...
		((sdpGtkEventWidgetDeleteEvent*)Event)->SetResult(true);

		// Turn it into a "cancel", instead ...
		OnCancel();
	}
	
	void OnNewName()
	{
		k3d::record_command(*this, k3d::icommand_node::command_t::USER_INTERFACE, control_newname, Entry(control_newname).GetText());
	}
	
	void OnOK()
	{
		k3d::record_command(*this, k3d::icommand_node::command_t::USER_INTERFACE, control_ok);
		k3d::record_state_change_set changeset(m_object.document(), "Rename Object");

		m_object.set_name(m_name.value());
		
		delete this;
	}
	
	void OnCancel()
	{
		k3d::record_command(*this, k3d::icommand_node::command_t::USER_INTERFACE, control_cancel);
		delete this;
	}

	/// Called by the signal system if the underlying object is renamed
	void on_object_renamed()
	{
		Entry(control_oldname).SetText(m_object.name().c_str());
		Widget(control_oldname).SetSensitive(false);

		m_name.set_value(m_object.name());
	}
	
	/// Called by the signal system if the underlying object is deleted
	void on_object_deleted()
	{
		delete this;
	}

	class name_proxy :
		public k3d::edit_control::idata_proxy
	{
	public:
		name_proxy(const std::string& Name) :
			m_name(Name)
		{
		}
		
		const std::string value()
		{
			return m_name;
		}
		
		void set_value(const std::string& Value)
		{
			m_name = Value;
			m_changed_signal.emit();
		}
		
		changed_signal_t& changed_signal()
		{
			return m_changed_signal;
		}

	private:
		std::string m_name;
		changed_signal_t m_changed_signal;
	} m_name;

	/// Stores a reference to the object to be renamed
	k3d::iobject& m_object;
};

} // namespace

namespace k3d
{

void show_rename_object_dialog(iobject& Object)
{
	new rename_object_dialog(Object);
}

} // namespace k3d


