// -*- C++ -*-
/*
* GChemPaint library
* fragment-atom.cc
*
* Copyright (C) 2003-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 "fragment-atom.h"
#include "fragment.h"
#include "molecule.h"
#include <gcu/element.h>
#include <cstring>
gcpFragmentAtom::gcpFragmentAtom(): gcpAtom()
{
SetId ((char*) "a1");
}
gcpFragmentAtom::gcpFragmentAtom(gcpFragment *fragment, int Z): gcpAtom()
{
m_Fragment = fragment;
SetZ(Z);
SetId ((char*) "a1");
}
gcpFragmentAtom::~gcpFragmentAtom() {}
void gcpFragmentAtom::SetZ(int Z)
{
static bool setting = false;
if (setting) return;
setting = true;
Atom::SetZ(Z);
if (Z != 0) m_Fragment->OnChangeAtom();
setting = false;
}
/*!
Only accept a new bond if none exists. So only one bond.
*/
bool gcpFragmentAtom::AcceptNewBonds(int nb)
{
return (nb > 1)? false: GetBondsNumber() == 0;
}
/*!
Overrided to avoid gcpAtom::Add execution. Don't do anything.
*/
void gcpFragmentAtom::Add(GtkWidget* w)
{
}
/*!
Overrided to avoid gcpAtom::Update execution. Just call fragment Update method.
*/
void gcpFragmentAtom::Update(GtkWidget* w)
{
m_Fragment->Update(w);
}
/*!
Overrided to avoid gcpAtom::SetSelected execution. Just call fragment SetSelected method.
*/
void gcpFragmentAtom::SetSelected(GtkWidget* w, int state)
{
m_Fragment->SetSelected(w, state);
}
xmlNodePtr gcpFragmentAtom::Save(xmlDocPtr xml)
{
xmlNodePtr node;
gchar buf[16];
node = xmlNewDocNode(xml, NULL, (xmlChar*)"atom", NULL);
if (!node) return NULL;
SaveId(node);
strncpy(buf, GetSymbol(), sizeof(buf));
xmlNodeSetContent(node, (xmlChar*)buf);
if (m_Charge)
{
snprintf(buf, sizeof(buf), "%d", m_Charge);
xmlNewProp(node, (xmlChar*)"charge", (xmlChar*)buf);
double Angle, Dist;
unsigned char ChargePos = gcpAtom::GetChargePosition (&Angle, &Dist);
if (ChargePos != 0xff) {
char *buf;
if (ChargePos) {
switch (ChargePos) {
case CHARGE_NE:
buf = (char*) "ne";
break;
case CHARGE_NW:
buf = (char*) "nw";
break;
case CHARGE_N:
buf = (char*) "n";
break;
case CHARGE_SE:
buf = (char*) "se";
break;
case CHARGE_SW:
buf = (char*) "sw";
break;
case CHARGE_S:
buf= (char*) "s";
break;
case CHARGE_E:
buf = (char*) "e";
break;
case CHARGE_W:
buf = (char*) "w";
break;
default:
buf = (char*) "def"; // should not occur
}
xmlNewProp (node, (xmlChar*) "charge-position", (xmlChar*) buf);
} else {
buf = g_strdup_printf ("%g", Angle * 180. / M_PI);
xmlNewProp (node, (xmlChar*) "charge-angle", (xmlChar*) buf);
g_free (buf);
}
if (Dist != 0.) {
buf = g_strdup_printf ("%g", Dist);
xmlNewProp (node, (xmlChar*) "charge-dist", (xmlChar*) buf);
g_free (buf);
}
}
}
return node;
}
bool gcpFragmentAtom::Load (xmlNodePtr node)
{
char* buf;
unsigned char ChargePos = 0xff;
double Angle = 0., Dist = 0.;
buf = (char*) xmlGetProp (node, (xmlChar*) "id");
if (buf) {
SetId (buf);
xmlFree (buf);
}
buf = (char*) xmlNodeGetContent (node);
if (buf) {
m_Z = Element::Z (buf);
xmlFree (buf);
}
buf = (char*) xmlGetProp (node, (xmlChar*) "charge");
m_Charge = (buf)? (char) atoi (buf): 0;
if (buf)
xmlFree (buf);
if (m_Charge) {
char *buf = (char*) xmlGetProp (node, (xmlChar*) "charge-position");
if (buf) {
if (! strcmp (buf, "ne")) {
ChargePos = CHARGE_NE;
Angle = M_PI / 4.;
} else if (! strcmp (buf, "nw")) {
ChargePos = CHARGE_NW;
Angle = 3. * M_PI / 4.;
} else if (! strcmp (buf, "n")) {
ChargePos = CHARGE_N;
Angle = M_PI / 2.;
} else if (! strcmp (buf, "se")) {
ChargePos = CHARGE_SE;
Angle = 7. * M_PI / 4;
} else if (! strcmp (buf, "sw")) {
ChargePos = CHARGE_SW;
Angle = 5. * M_PI / 4;
} else if (! strcmp (buf, "s")) {
ChargePos = CHARGE_S;
Angle = 3 * M_PI / 2.;
} else if (! strcmp (buf, "e")) {
ChargePos = CHARGE_E;
Angle = 0.;
} else if (! strcmp (buf, "w")) {
ChargePos = CHARGE_W;
Angle = M_PI;
}
xmlFree (buf);
} else {
buf = (char*) xmlGetProp (node, (xmlChar*)"charge-angle");
if (buf) {
sscanf (buf, "%lg", &Angle);
Angle *= M_PI / 180.;
xmlFree (buf);
ChargePos = 0;
}
}
buf = (char*) xmlGetProp (node, (xmlChar*)"charge-dist");
if (buf) {
sscanf (buf, "%lg", &Dist);
xmlFree (buf);
}
SetChargePosition (ChargePos, ChargePos == 0xff, Angle, Dist);
}
return true;
}
void gcpFragmentAtom::AddToMolecule(gcpMolecule* Mol)
{
Mol->AddFragment(m_Fragment);
}
int gcpFragmentAtom::GetChargePosition(unsigned char& Pos, double Angle, double& x, double& y)
{
return m_Fragment->GetChargePosition(this, Pos, Angle, x, y);
}
int gcpFragmentAtom::GetAvailablePosition(double& x, double& y)
{
return m_Fragment->GetAvailablePosition(x, y);
}
bool gcpFragmentAtom::GetPosition(double angle, double& x, double& y)
{
return m_Fragment->GetPosition(angle, x, y);
}
bool gcpFragmentAtom::AcceptCharge (int charge) {
return (charge >= -1 && charge <= 1);
}
void gcpFragmentAtom::Update()
{
}
syntax highlighted by Code2HTML, v. 0.9.1