1 // -*- C++ -*-
2 
3 /*
4  * GChemPaint arrows plugin
5  * retrosynthesisstep.cc
6  *
7  * Copyright (C) 2005-2010 Jean Bréfort <jean.brefort@normalesup.org>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 3 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
22  * USA
23  */
24 
25 #include "config.h"
26 #include "retrosynthesisstep.h"
27 #include "retrosynthesis.h"
28 #include "retrosynthesisarrow.h"
29 #include <gcp/application.h>
30 #include <gcp/molecule.h>
31 #include <gcp/document.h>
32 #include <gcu/objprops.h>
33 #include <glib/gi18n-lib.h>
34 
35 TypeId RetrosynthesisStepType;
36 
gcpRetrosynthesisStep()37 gcpRetrosynthesisStep::gcpRetrosynthesisStep (): gcp::Step (RetrosynthesisStepType)
38 {
39 	SetId ("rss1");
40 	Molecule = NULL;
41 }
42 
~gcpRetrosynthesisStep()43 gcpRetrosynthesisStep::~gcpRetrosynthesisStep ()
44 {
45 	if (IsLocked ())
46 		return;
47 	gcp::Document *pDoc = reinterpret_cast<gcp::Document *> (GetDocument ());
48 	gcp::Operation *pOp = pDoc->GetCurrentOperation ();
49 	gcpRetrosynthesis *rs = reinterpret_cast<gcpRetrosynthesis *> (GetParent ());
50 	if (!rs)
51 		return;
52 	map<string, Object *>::iterator i;
53 	Object *Child, *Group = rs->GetGroup ();
54 	while (HasChildren ()) {
55 		Child = GetFirstChild (i);
56 		GetParent ()->GetParent ()->AddChild (Child);
57 		if (pOp && !Group)
58 			pOp->AddObject (Child, 1);
59 	}
60 }
61 
gcpRetrosynthesisStep(gcpRetrosynthesis * synthesis,gcp::Molecule * molecule)62 gcpRetrosynthesisStep::gcpRetrosynthesisStep (gcpRetrosynthesis *synthesis, gcp::Molecule* molecule) throw (std::invalid_argument): gcp::Step (RetrosynthesisStepType)
63 {
64 	if (!synthesis || !molecule)
65 		throw invalid_argument ("NULL argument to gcpRetrosynthesisStep constructor!");
66 	SetId ("rss1");
67 	synthesis->AddChild (this);
68 	GetDocument ()->EmptyTranslationTable();
69 	AddChild (molecule);
70 	Molecule = molecule;
71 	Arrow = NULL;
72 }
73 
AddArrow(gcpRetrosynthesisArrow * arrow,gcpRetrosynthesisStep * step,bool start)74 void gcpRetrosynthesisStep::AddArrow (gcpRetrosynthesisArrow *arrow, gcpRetrosynthesisStep *step, bool start) throw (std::invalid_argument)
75 {
76 	if (start) {
77 		if (Arrows[step])
78 			throw invalid_argument (_("Only one arrow can link two given steps."));
79 		Arrows[step] = arrow;
80 	} else {
81 		Arrow = arrow;
82 		Precursor = step;
83 	}
84 }
85 
Load(xmlNodePtr node)86 bool gcpRetrosynthesisStep::Load(xmlNodePtr node)
87 {
88 	if (Object::Load (node)) {
89 		if (GetChildrenNumber () != 1)
90 			return false;
91 		map<string, Object*>::iterator i;
92 		Molecule = reinterpret_cast<gcp::Molecule *> (GetFirstChild (i));
93 		GetDocument ()->ObjectLoaded (this);
94 		return true;
95 	}
96 	return false;
97 }
98 
GetYAlign()99 double gcpRetrosynthesisStep::GetYAlign ()
100 {
101 	return (Molecule)? Molecule->GetYAlign (): 0.;
102 }
103 
RemoveArrow(G_GNUC_UNUSED gcpRetrosynthesisArrow * arrow,gcpRetrosynthesisStep * step)104 void gcpRetrosynthesisStep::RemoveArrow (G_GNUC_UNUSED gcpRetrosynthesisArrow *arrow, gcpRetrosynthesisStep *step)
105 {
106 	if (step == Precursor) {
107 		Precursor = NULL;
108 		Arrow = NULL;
109 	} else
110 		Arrows.erase (step);
111 }
112 
OnSignal(G_GNUC_UNUSED SignalId Signal,G_GNUC_UNUSED Object * Child)113 bool gcpRetrosynthesisStep::OnSignal (G_GNUC_UNUSED SignalId Signal, G_GNUC_UNUSED Object *Child)
114 {
115 	if (GetChildrenNumber () != 1) {
116 		delete GetParent ();
117 		return false;
118 	}
119 	return true;
120 }
121 
SetProperty(unsigned property,char const * value)122 bool gcpRetrosynthesisStep::SetProperty (unsigned property, char const *value)
123 {
124 	gcu::Document *doc = GetDocument ();
125 	switch (property) {
126 	case GCU_PROP_MOLECULE: {
127 		if (doc == NULL)
128 			return false;
129 		if (Molecule != NULL && !strcmp (Molecule->GetId (), value)) {
130 			break;
131 		}
132 		gcu::Object *new_child = doc->GetDescendant (value);
133 		gcp::Application *app = static_cast <gcp::Application * > (doc->GetApplication ());
134 		std::set < TypeId > const &rules = app->GetRules (RetrosynthesisStepType, RuleMayContain);
135 		if (new_child != NULL && rules.find (new_child->GetType ()) != rules.end ()) {
136 			if (Molecule != NULL)
137 				Molecule->SetParent (doc);
138 			Molecule = dynamic_cast < gcp::Molecule * > (new_child);
139 			if (Molecule)
140 				AddChild (Molecule);
141 		}
142 		break;
143 	}
144 	}
145 	return true;
146 }
147 
Name()148 std::string gcpRetrosynthesisStep::Name ()
149 {
150 	return _("Retrosynthesis step");
151 }
152