// -*- C++ -*-

/* 
 * GChemPaint selection plugin
 * erasertool.cc
 *
 * Copyright (C) 2001-2005 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 "erasertool.h"
#include "lib/settings.h"
#include "lib/document.h"
#include "lib/atom.h"
#include "lib/bond.h"
#include "lib/theme.h"
#include <cmath>

gcpEraserTool::gcpEraserTool(gcpApplication* App): gcpTool(App, "Erase")
{
	m_bChanged = false;
}

gcpEraserTool::~gcpEraserTool()
{
}

bool gcpEraserTool::OnClicked()
{
	if (m_pObject)
	{
		TypeId Id = m_pObject->GetType();
		if (Id == ReactionOperatorType)
			return false; //It's an automatic object, don't delete it
		m_pObject->SetSelected(m_pWidget, SelStateErasing);
		m_pItem = m_pView->GetCanvasItem(m_pWidget, m_pObject);
		if (Id == AtomType)
		{
			Object* parent = m_pObject->GetParent();
			if (parent->GetType() == FragmentType)
				m_pItem = m_pView->GetCanvasItem(m_pWidget, parent);
			std::map<Atom*, Bond*>::iterator i;
			gcpBond* pBond = (gcpBond*)((gcpAtom*)m_pObject)->GetFirstBond(i);
			while (pBond)
			{
				pBond->SetSelected(m_pWidget, SelStateErasing);
				pBond = (gcpBond*)((gcpAtom*)m_pObject)->GetNextBond(i);
			}
		}
		m_bChanged = true;
		return true;
	}
	return false;
}

void gcpEraserTool::OnDrag()
{
	if (!m_pObject) return;
	TypeId Id = m_pObject->GetType();
	GnomeCanvasItem* pItem = gnome_canvas_get_item_at(GNOME_CANVAS(m_pWidget), m_x, m_y);
	gcpTheme *Theme = m_pView->GetDoc ()->GetTheme ();
	Object* pObject = NULL;
	switch (Id)
	{
		case BondType:
			if (((gcpBond*)m_pObject)->GetDist(m_x / m_dZoomFactor, m_y / m_dZoomFactor) < (Theme->GetPadding () + Theme->GetBondWidth () / 2) / m_dZoomFactor)
			{
				if (!m_bChanged)
				{
					m_pObject->SetSelected(m_pWidget, SelStateErasing);
					m_bChanged = true;
				}
			}
			else if (m_bChanged)
			{
				m_pObject->SetSelected(m_pWidget, SelStateUnselected);
				m_bChanged = false;
			}
			break;
		case AtomType:
			if (pItem == (GnomeCanvasItem*)m_pBackground) pItem = NULL;
			if (pItem) pObject = (Object*)g_object_get_data(G_OBJECT(pItem), "object");
			if (pObject)
			{
				if (pObject->GetType() == BondType)
					pObject = ((gcpBond*)pObject)->GetAtomAt(m_x / m_dZoomFactor, m_y / m_dZoomFactor);
				else if (pObject->GetType() == FragmentType)
					pObject = ((gcpFragment*)pObject)->GetAtom();
			}
			if (pObject == m_pObject)
			{
				if (!m_bChanged)
				{
					m_pObject->SetSelected(m_pWidget, SelStateErasing);
					std::map<Atom*, Bond*>::iterator i;
					gcpBond* pBond = (gcpBond*)((gcpAtom*)m_pObject)->GetFirstBond(i);
					while (pBond)
					{
						pBond->SetSelected(m_pWidget, SelStateErasing);
						pBond = (gcpBond*)((gcpAtom*)m_pObject)->GetNextBond(i);
					}
					m_bChanged = true;
				}
			}
			else if (m_bChanged)
			{
				m_pObject->SetSelected(m_pWidget, SelStateUnselected);
				std::map<Atom*, Bond*>::iterator i;
				gcpBond* pBond = (gcpBond*)((gcpAtom*)m_pObject)->GetFirstBond(i);
				while (pBond)
				{
					pBond->SetSelected(m_pWidget, SelStateUnselected);
					pBond = (gcpBond*)((gcpAtom*)m_pObject)->GetNextBond(i);
				}
				m_bChanged = false;
			}
			break;
		default:
			if (pItem) pObject = (Object*)g_object_get_data(G_OBJECT(pItem), "object");
			if (pObject == m_pObject)
			{
				if (!m_bChanged)
				{
					m_pObject->SetSelected(m_pWidget, SelStateErasing);
					m_bChanged = true;
				}
			}
			else if (m_bChanged)
			{
				m_pObject->SetSelected(m_pWidget, SelStateUnselected);
				m_bChanged = false;
			}
			
	}
}

void gcpEraserTool::OnRelease()
{
	char *id = NULL;
	if ((!m_pObject) || (!m_bChanged)) {
		m_pItem = NULL;
		return;
	}
	gcpDocument* pDoc = m_pView->GetDoc ();
	gcpOperation *pOp;
	Object *pObj = m_pObject->GetGroup (), *Parent;
	if (pObj && (pObj->GetType () != MoleculeType || m_pObject->GetType () == OtherType)) {
		pOp = pDoc->GetNewOperation (GCP_MODIFY_OPERATION);
		pOp->AddObject (pObj, 0);
		id = g_strdup (pObj->GetId ());
	} else {
		pOp = pDoc->GetNewOperation (GCP_DELETE_OPERATION);
		pOp->AddObject (m_pObject);
	}
	if (m_pObject->GetType () == AtomType) {
		Object* parent = m_pObject->GetParent ();
		if (parent->GetType () == FragmentType)
			m_pObject = parent;
	}
	Parent = m_pObject->GetParent ();
// A molecule might disappear, so get its parent
	if (Parent->GetType () == MoleculeType)
		Parent = Parent->GetParent ();
	m_pItem = NULL;
	if (m_pData->Items[m_pObject] == NULL) {
		m_pData->Items.erase (m_pObject);
		return;
	}
	pDoc->Remove (m_pObject);
	Parent->EmitSignal (OnChangedSignal);
	if (id) {
		pObj = pDoc->GetChild (id);
		if (pObj)
			pOp->AddObject (pObj, 1);
		g_free (id);
	}
	pDoc->FinishOperation ();
}


syntax highlighted by Code2HTML, v. 0.9.1