// -*- C++ -*-

/* 
 * GChemPaint atoms plugin
 * elementtool.cc 
 *
 * Copyright (C) 2001-2007 Jean Bréfort <jean.brefort@normalesup.org>
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#include "gchempaint-config.h"
#include "elementtool.h"
#include <gcu/element.h>
#include "lib/document.h"
#include "lib/settings.h"
#include "lib/application.h"
#include "lib/theme.h"
#include "libgcpcanvas/gcp-canvas-group.h"
#include <cmath>
#include <cstring>

gcpElementTool::gcpElementTool(gcpApplication *App): gcpTool(App, "Element")
{
}

gcpElementTool::~gcpElementTool()
{
}

bool gcpElementTool::OnClicked()
{
	int CurZ = m_pApp->GetCurZ ();
	if (m_pObject) {
		if (m_pObject->GetType () != AtomType)
			return false; 
		if 	(((gcpAtom*) m_pObject)->GetTotalBondsNumber () > (int) Element::GetMaxBonds (CurZ))
			return false;
		((gcpAtom*) m_pObject)->GetCoords (&m_x0, &m_y0);
		m_x0 *= m_dZoomFactor;
		m_y0 *= m_dZoomFactor;
	}
	m_bChanged = true;
	const gchar* symbol = gcu::Element::Symbol (CurZ);
	PangoLayout *pl = pango_layout_new (m_pView->GetPangoContext ());
	pango_layout_set_font_description (pl, m_pView->GetPangoFontDesc ());
	pango_layout_set_text (pl, symbol, strlen (symbol));
	gint width = pango_layout_get_width (pl);
	double padding = m_pView->GetDoc ()->GetTheme ()->GetPadding ();
	m_x1 = m_x0 - (double) width / 2 - padding;
	m_y1 = m_y0 - m_pView->GetFontHeight() / 2 - padding;
	m_x2 = m_x0 + (double) width / 2 + padding;
	m_y2 = m_y0 + m_pView->GetFontHeight () / 2 + padding;
	m_pItem = gnome_canvas_item_new (m_pGroup, gnome_canvas_group_ext_get_type (), NULL);
	gnome_canvas_item_new (
					(GnomeCanvasGroup*) m_pItem,
					gnome_canvas_rect_get_type (),
					"x1", m_x1,
					"y1", m_y1,
					"x2", m_x2,
					"y2", m_y2,
					"fill_color", "white",
					NULL);
	gnome_canvas_item_new (
					(GnomeCanvasGroup*) m_pItem,
					gnome_canvas_pango_get_type (),
					"layout", pl,
					"x", rint (m_x0),
					"y", rint (m_y0),
					"anchor", GTK_ANCHOR_CENTER,
					"fill_color", AddColor,
					NULL);
	g_object_unref (pl);
	return true;
}

void gcpElementTool::OnDrag()
{
		if ((m_x > m_x1) && (m_x2 > m_x) && (m_y > m_y1) && (m_y2 > m_y))
		{
			if (!m_bChanged)
			{
				gnome_canvas_item_show(m_pItem);
				m_bChanged = true;
			}
		}
		else if (m_bChanged)
		{
			gnome_canvas_item_hide(m_pItem);
			m_bChanged = false;
		}
}

void gcpElementTool::OnRelease ()
{
	int CurZ = m_pApp->GetCurZ () ;
	if (m_bChanged)
	{
		gcpDocument* pDoc = m_pView->GetDoc ();
		if (m_pObject)
		{
			gcpMolecule* pMol = (gcpMolecule*) m_pObject->GetMolecule ();
			gcpOperation* pOp = pDoc-> GetNewOperation (GCP_MODIFY_OPERATION);
			Object *pObj = m_pObject->GetGroup ();
			pOp->AddObject (pObj, 0);
			Object* parent = m_pObject->GetParent ();
			if (m_nState & GDK_CONTROL_MASK && (parent->GetType () == FragmentType)) {
				//If m_pObject points to an atom inside a fragment, replace the whole fragment.
				gcpAtom* pAtom = ((gcpFragment*) parent)->GetAtom ();
				map<Atom*, Bond*>::iterator i;
				gcpBond *pBond = (gcpBond*) pAtom->GetFirstBond (i);
				double x, y;
				pAtom->GetCoords (&x, &y);
				gcpAtom* pNewAtom = new gcpAtom (CurZ, x, y, 0.);
				pMol->Remove (parent);
				m_pView->Remove (parent);
				m_pView->AddObject (pNewAtom);
				parent->SetParent (NULL);
				pMol->AddAtom (pNewAtom);
				pNewAtom->SetId ((gchar*) pAtom->GetId ());
				if (pBond) {
					pBond->ReplaceAtom (pAtom, pNewAtom);
					pNewAtom->AddBond (pBond);
				}
				pNewAtom->Update ();
				m_pView->Update (pNewAtom);
				delete parent;
			} else {
				((gcpAtom*) m_pObject)->SetZ (CurZ);
				m_pView->Update ((gcpAtom*) m_pObject);
			}	
			pOp->AddObject (pObj, 1);
		} else {
			gcpAtom* pAtom = new gcpAtom (CurZ, m_x0 / m_dZoomFactor, m_y0 / m_dZoomFactor, 0);
			gcpOperation* pOp = pDoc-> GetNewOperation (GCP_ADD_OPERATION);
			pDoc->AddAtom (pAtom);
			pOp->AddObject (pAtom);
		}
		pDoc->FinishOperation ();
	}
}


syntax highlighted by Code2HTML, v. 0.9.1