// -*- C++ -*- /* * GChemPaint library * fragment-atom.cc * * Copyright (C) 2003-2005 Jean Bréfort * * 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 #include 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() { }