FOX/ObjCryst++  1.10.X (development)
wxMolecule.cpp
1 /* ObjCryst++ Object-Oriented Crystallographic Library
2  (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net
3  2000-2001 University of Geneva (Switzerland)
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 
20 // wx headers, with or without precompilation
21 #include "wx/wxprec.h"
22 #ifdef __BORLANDC__
23  #pragma hdrstop
24 #endif
25 #ifndef WX_PRECOMP
26  #include "wx/wx.h"
27 #endif
28 #include "wx/notebook.h"
29 #include "wx/minifram.h"
30 #include <wx/wfstream.h>
31 #include "wx/progdlg.h"
32 
33 #include <sstream>
34 #include <fstream>
35 #include <algorithm>
36 #include "ObjCryst/wxCryst/wxMolecule.h"
37 #include "ObjCryst/RefinableObj/LSQNumObj.h"
38 #include "ObjCryst/Quirks/Chronometer.h"
39 
40 namespace ObjCryst
41 {
42 
43 //:TODO: Move this to wxCryst.h
44 template<class T> T const* WXDialogChooseFromVector(const vector<T*> &reg,wxWindow*parent,
45  const string &message,int &choice)
46 {
47  wxString *choices = new wxString[reg.size()];
48  for(unsigned int i=0;i<reg.size();i++)
49  choices[i]= wxString::FromAscii((reg[i]->GetName()).c_str());
50  wxSingleChoiceDialog dialog
51  (parent,message.c_str(),"Choose",reg.size(),choices,NULL,wxOK | wxCANCEL);
52  dialog.SetSize(300,300);
53  if(wxID_OK!=dialog.ShowModal()) return 0;
54  choice=dialog.GetSelection();
55  delete[] choices;
56  return reg[choice];
57 }
58 
59 template<class T> T * WXDialogChooseFromVector(vector<T*> &reg,wxWindow*parent,
60  const string &message,int &choice)
61 {
62  wxString *choices = new wxString[reg.size()];
63  for(unsigned int i=0;i<reg.size();i++)
64  choices[i]= wxString::FromAscii((reg[i]->GetName()).c_str());
65  #if wxCHECK_VERSION( 2, 9, 4 )
66  wxSingleChoiceDialog dialog
67  (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices,(void**)NULL,wxOK | wxCANCEL);
68  #else
69  wxSingleChoiceDialog dialog
70  (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices,NULL,wxOK | wxCANCEL);
71  #endif
72  dialog.SetSize(300,300);
73  if(wxID_OK!=dialog.ShowModal()) return 0;
74  choice=dialog.GetSelection();
75  delete[] choices;
76  return reg[choice];
77 }
78 
79 template<class T> list<T *> WXDialogChooseMultipleFromVector(vector<T*> &reg,wxWindow*parent,
80  const string &message)
81 {
82  wxString *choices = new wxString[reg.size()];
83  for(unsigned int i=0;i<reg.size();i++)
84  choices[i]= wxString::FromAscii((reg[i]->GetName()).c_str());
85  wxMultiChoiceDialog_ListBox dialog
86  (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices);
87  dialog.ShowModal();
88  wxArrayInt choice=dialog.GetSelections();
89  list<T*> vChoice;
90  for(unsigned int i=0;i<choice.GetCount();++i) vChoice.push_back(reg[choice.Item(i)]);
91  delete[] choices;
92  return vChoice;
93 }
94 template<class T> list<T const*> WXDialogChooseMultipleFromVector(const vector<T*> &reg,wxWindow*parent,
95  const string &message)
96 {
97  wxString *choices = new wxString[reg.size()];
98  for(unsigned int i=0;i<reg.size();i++)
99  choices[i]= wxString::FromAscii((reg[i]->GetName()).c_str());
100  wxMultiChoiceDialog_ListBox dialog
101  (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices);
102  dialog.ShowModal();
103  wxArrayInt choice=dialog.GetSelections();
104  list<T const*> vChoice;
105  for(unsigned int i=0;i<choice.GetCount();++i) vChoice.push_back(reg[choice.Item(i)]);
106  delete[] choices;
107  return vChoice;
108 }
109 
110 // Compress a string by removing a given character
111 string CompressString(const string &s,const string &c)
112 {
113  string sc=s;
114  string::size_type idx=0;
115  while(idx!=string::npos)
116  {
117  idx=sc.find(c);
118  if(idx!=string::npos) sc.erase(idx,c.size());
119  }
120  return sc;
121 }
122 // Split
123 list<string> SplitString(const string &str, const string &separator)
124 {
125  string::size_type idx0=(string::size_type) 0;
126  string::size_type idx1=(string::size_type) 0;
127  list<string> l;
128  while((idx1!=string::npos)&&(idx0<str.size()))
129  {
130  idx1=str.find(separator,idx0);
131  if(idx1==string::npos) l.push_back(str.substr(idx0,idx1));
132  if(idx1>idx0) l.push_back(str.substr(idx0,idx1-idx0));
133  idx0=idx1+1;
134  }
135  //for(list<string>::const_iterator pos=l.begin();pos!=l.end();++pos) cout <<*pos<<" / ";
136  //cout<<endl;
137  return l;
138 }
139 
141 //
142 // WXMolScrolledWindow
143 //
145 WXMolScrolledWindow::WXMolScrolledWindow(wxWindow* parent, WXMolecule* pWXMol, long id):
146 wxGrid(parent,id),mpWXMolecule(pWXMol)
147 {}
148 WXMolScrolledWindow::~WXMolScrolledWindow()
149 {
151 }
153 //
154 // WXMolAtom
155 //
157 static const long ID_MOLATOM_SCATTPOW=WXCRYST_ID();
158 static const long ID_MOLATOM_NAME=WXCRYST_ID();
159 
160 BEGIN_EVENT_TABLE(WXMolAtom,wxWindow)
161  EVT_BUTTON(ID_MOLATOM_SCATTPOW, WXMolAtom::OnChangeScattPow)
162 END_EVENT_TABLE()
163 
164 WXMolAtom::WXMolAtom(wxWindow *parent, MolAtom*obj):
165 WXCrystObjBasic(parent),mpMolAtom(obj)
166 {
167  VFN_DEBUG_ENTRY("WXMolAtom::WXMolAtom():"<<obj->GetName(),6)
168  mpSizer=new wxBoxSizer(wxHORIZONTAL);
169  wxStaticText* label=new wxStaticText(this,-1,_T("Atom"));
170  mpSizer->Add(label);
171  {
172  mpFieldName=new WXFieldString(this, mpMolAtom->GetName(),ID_MOLATOM_NAME,80,true);
173  mpSizer->Add(mpFieldName,0,wxALIGN_CENTER);
174  mpFieldScattPower=new WXFieldChoice(this,ID_MOLATOM_SCATTPOW,"Type:",60);
175  mpSizer->Add(mpFieldScattPower,0,wxALIGN_CENTER);
176  mList.Add(mpFieldScattPower);
177  if(mpMolAtom->IsDummy())
178  mpFieldScattPower->SetValue("Dummy");
179  else
180  mpFieldScattPower->SetValue(mpMolAtom->GetScatteringPower().GetName());
181  }
182  {
183  WXCrystObjBasic* pFieldX=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->X())).WXCreate(this);
184  mpSizer->Add(pFieldX,0,wxALIGN_CENTER);
185  mList.Add(pFieldX);
186  }
187  {
188  WXCrystObjBasic* pFieldY=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->Y())).WXCreate(this);
189  mpSizer->Add(pFieldY,0,wxALIGN_CENTER);
190  mList.Add(pFieldY);
191  }
192  {
193  WXCrystObjBasic* pFieldZ=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->Z())).WXCreate(this);
194  mpSizer->Add(pFieldZ,0,wxALIGN_CENTER);
195  mList.Add(pFieldZ);
196  }
197 
198  this->SetSizer(mpSizer);
199  this->Layout();
200  this->CrystUpdate(true);
201  VFN_DEBUG_EXIT("WXMolAtom::WXMolAtom():"<<obj->GetName(),6)
202 }
203 
204 WXMolAtom::~WXMolAtom()
205 {
206  mpMolAtom->WXNotifyDelete();
207 }
208 
209 void WXMolAtom::CrystUpdate(const bool uui,const bool lock)
210 {
211  VFN_DEBUG_ENTRY("WXMolAtom::CrystUpdate()",5)
212  if(lock) mMutex.Lock();
213  mList.CrystUpdate(uui,false);
214  if(lock) mMutex.Unlock();
215  VFN_DEBUG_EXIT("WXMolAtom::CrystUpdate()",5)
216 }
217 
218 void WXMolAtom::UpdateUI(const bool lock)
219 {
220  VFN_DEBUG_ENTRY("WXMolAtom::UpdateUI()",5)
221  if(lock) mMutex.Lock();
222  mList.UpdateUI(false);
223  mpFieldName->SetValue(mpMolAtom->GetName().c_str());
224  if(mpMolAtom->IsDummy())
225  mpFieldScattPower->SetValue("Dummy");
226  else
227  mpFieldScattPower->SetValue(mpMolAtom->GetScatteringPower().GetName());
228  if(lock) mMutex.Unlock();
229  VFN_DEBUG_EXIT("WXMolAtom::UpdateUI()",5)
230 }
231 
232 void WXMolAtom::OnChangeScattPow(wxCommandEvent & WXUNUSED(event))
233 {
234  VFN_DEBUG_ENTRY("WXMolAtom::OnChangeScattPow()",6)
236  int choice;
238  mpMolAtom->GetMolecule().GetCrystal().GetScatteringPowerRegistry(),
239  (wxWindow*)this,"Choose a new Scattering Power",choice);
240  if(0==scatt) return;
241  mpMolAtom->SetScatteringPower(*scatt);
242  this->CrystUpdate(true);
243  this->UpdateUI(true);
244  VFN_DEBUG_EXIT("WXMolAtom::OnChangeScattPow()",6)
245 }
247 //
248 // WXMolBond
249 //
251 WXCRYST_ID ID_MOLBOND_ATOM1;
252 WXCRYST_ID ID_MOLBOND_ATOM2;
253 WXCRYST_ID ID_MOLBOND_FREEBUTTON;
254 
255 BEGIN_EVENT_TABLE(WXMolBond,wxWindow)
256  EVT_BUTTON(ID_MOLBOND_ATOM1, WXMolBond::OnChangeAtom)
257  EVT_BUTTON(ID_MOLBOND_ATOM2, WXMolBond::OnChangeAtom)
258  EVT_CHECKBOX(ID_MOLBOND_FREEBUTTON, WXMolBond::OnToggleFree)
259 END_EVENT_TABLE()
260 
261 WXMolBond::WXMolBond(wxWindow *parent, MolBond*obj):
262 WXCrystObjBasic(parent),mpMolBond(obj),mpButtonFree(0)
263 {
264  VFN_DEBUG_ENTRY("WXMolBond::WXMolBond():"<<obj->GetName(),6)
265  mpSizer=new wxBoxSizer(wxHORIZONTAL);
266  #if 1
267  mpButtonFree=new wxCheckBox(this,ID_MOLBOND_FREEBUTTON,_T(""),wxDefaultPosition, wxDefaultSize);
268  mpButtonFree->Fit();
269  mpSizer->Add(mpButtonFree,0,wxALIGN_CENTER);
270  #endif
271  mpFieldAtom1=new WXFieldChoice(this,ID_MOLBOND_ATOM1,"Bond:",60);
272  mpFieldAtom1->SetValue(mpMolBond->GetAtom1().GetName());
273  mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER);
274  mList.Add(mpFieldAtom1);
275 
276  mpFieldAtom2=new WXFieldChoice(this,ID_MOLBOND_ATOM2,"-",60);
277  mpFieldAtom2->SetValue(mpMolBond->GetAtom2().GetName());
278  mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER);
279  mList.Add(mpFieldAtom2);
280 
281  WXFieldPar<REAL> *value=
282  new WXFieldPar<REAL>(this,"Length=",-1,&mValue);
283  mpSizer->Add(value,0,wxALIGN_CENTER);
284  mList.Add(value);
285 
286  WXFieldPar<REAL> *length=
287  new WXFieldPar<REAL>(this,",Restraint=",-1,&(mpMolBond->Length0()));
288  mpSizer->Add(length,0,wxALIGN_CENTER);
289  mList.Add(length);
290 
291  WXFieldPar<REAL> *delta=
292  new WXFieldPar<REAL>(this,",delta=",-1,&(mpMolBond->LengthDelta()));
293  mpSizer->Add(delta,0,wxALIGN_CENTER);
294  mList.Add(delta);
295 
296  WXFieldPar<REAL> *sigma=
297  new WXFieldPar<REAL>(this,",sigma=",-1,&(mpMolBond->LengthSigma()));
298  mpSizer->Add(sigma,0,wxALIGN_CENTER);
299  mList.Add(sigma);
300 
301  this->SetSizer(mpSizer);
302  this->Layout();
303  this->CrystUpdate(true,true);
304  VFN_DEBUG_EXIT("WXMolBond::WXMolBond():"<<obj->GetName(),6)
305 }
306 WXMolBond::~WXMolBond()
307 {
308  mpMolBond->WXNotifyDelete();
309 }
310 
311 void WXMolBond::CrystUpdate(const bool uui,const bool lock)
312 {
313  VFN_DEBUG_ENTRY("WXMolBond::CrystUpdate()",5)
314  if(lock) mMutex.Lock();
315  mValue=mpMolBond->GetLength();
316  mList.CrystUpdate(uui,false);
317  if(lock) mMutex.Unlock();
318  VFN_DEBUG_EXIT("WXMolBond::CrystUpdate()",5)
319 }
320 
321 void WXMolBond::UpdateUI(const bool lock)
322 {
323  VFN_DEBUG_ENTRY("WXMolBond::UpdateUI()",5)
324  if(lock) mMutex.Lock();
325  if(0!=mpButtonFree) mpButtonFree->SetValue(mpMolBond->IsFreeTorsion());
326  mList.UpdateUI(false);
327  mpFieldAtom1->SetValue(mpMolBond->GetAtom1().GetName().c_str());
328  mpFieldAtom2->SetValue(mpMolBond->GetAtom2().GetName().c_str());
329  if(lock) mMutex.Unlock();
330  VFN_DEBUG_EXIT("WXMolBond::UpdateUI()",5)
331 }
332 
333 void WXMolBond::OnChangeAtom(wxCommandEvent &event)
334 {
335  VFN_DEBUG_ENTRY("WXMolBond::OnChangeAtom()",6)
337  int choice;
338  MolAtom *const at=WXDialogChooseFromVector(mpMolBond->GetMolecule().GetAtomList(),
339  (wxWindow*)this,"Choose a new Atom",choice);
340  if(0==at) return;
341  if((long)ID_MOLBOND_ATOM1==event.GetId())
342  {
343  if(at==&(mpMolBond->GetAtom2()))
344  {
345  wxMessageDialog dumbUser(this,_T("The two atoms must be different !"),
346  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
347  dumbUser.ShowModal();
348  return;
349  }
350  mpMolBond->SetAtom1(*at);
351  }
352  if((long)ID_MOLBOND_ATOM2==event.GetId())
353  {
354  if(at==&(mpMolBond->GetAtom1()))
355  {
356  wxMessageDialog dumbUser(this,_T("The two atoms must be different !"),
357  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
358  dumbUser.ShowModal();
359  return;
360  }
361  mpMolBond->SetAtom2(*at);
362  }
363 
364  this->CrystUpdate(true);
365  this->UpdateUI(true);
366  VFN_DEBUG_EXIT("WXMolBond::OnChangeScattPow()",6)
367 }
368 
369 void WXMolBond::OnToggleFree(wxCommandEvent & WXUNUSED(event))
370 {
371  VFN_DEBUG_MESSAGE("WXMolBond::OnToggleFree()",6)
372  if(0!=mpButtonFree) mpMolBond->SetFreeTorsion(mpButtonFree->GetValue());
373 }
374 
376 //
377 // WXMolBondAngle
378 //
380 WXCRYST_ID ID_MOLBONDANGLE_ATOM1;
381 WXCRYST_ID ID_MOLBONDANGLE_ATOM2;
382 WXCRYST_ID ID_MOLBONDANGLE_ATOM3;
383 
384 BEGIN_EVENT_TABLE(WXMolBondAngle,wxWindow)
385  EVT_BUTTON(ID_MOLBONDANGLE_ATOM1, WXMolBondAngle::OnChangeAtom)
386  EVT_BUTTON(ID_MOLBONDANGLE_ATOM2, WXMolBondAngle::OnChangeAtom)
387  EVT_BUTTON(ID_MOLBONDANGLE_ATOM3, WXMolBondAngle::OnChangeAtom)
388 END_EVENT_TABLE()
389 
390 WXMolBondAngle::WXMolBondAngle(wxWindow *parent, MolBondAngle*obj):
391 WXCrystObjBasic(parent),mpMolBondAngle(obj)
392 {
393  VFN_DEBUG_ENTRY("WXMolBondAngle::WXMolBond():"<<obj->GetName(),6)
394  mpSizer=new wxBoxSizer(wxHORIZONTAL);
395 
396  mpFieldAtom1=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM1,"Bond Angle:",60);
397  mpFieldAtom1->SetValue(mpMolBondAngle->GetAtom1().GetName());
398  mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER);
399  mList.Add(mpFieldAtom1);
400 
401  mpFieldAtom2=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM2,"-",60);
402  mpFieldAtom2->SetValue(mpMolBondAngle->GetAtom2().GetName());
403  mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER);
404  mList.Add(mpFieldAtom2);
405 
406  mpFieldAtom3=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM3,"-",60);
407  mpFieldAtom3->SetValue(mpMolBondAngle->GetAtom3().GetName());
408  mpSizer->Add(mpFieldAtom3,0,wxALIGN_CENTER);
409  mList.Add(mpFieldAtom3);
410 
411  WXFieldPar<REAL> *value=
412  new WXFieldPar<REAL>(this,"Angle=",-1,&mValue);
413  value->SetHumanValueScale(RAD2DEG);
414  mpSizer->Add(value,0,wxALIGN_CENTER);
415  mList.Add(value);
416 
417  WXFieldPar<REAL> *angle=
418  new WXFieldPar<REAL>(this,",Restraint=",WXCRYST_ID(),&(mpMolBondAngle->Angle0()));
419  angle->SetHumanValueScale(RAD2DEG);
420  mpSizer->Add(angle,0,wxALIGN_CENTER);
421  mList.Add(angle);
422 
423  WXFieldPar<REAL> *delta=
424  new WXFieldPar<REAL>(this,",delta=",WXCRYST_ID(),&(mpMolBondAngle->AngleDelta()));
425  delta->SetHumanValueScale(RAD2DEG);
426  mpSizer->Add(delta,0,wxALIGN_CENTER);
427  mList.Add(delta);
428 
429  WXFieldPar<REAL> *sigma=
430  new WXFieldPar<REAL>(this,",sigma=",WXCRYST_ID(),&(mpMolBondAngle->AngleSigma()));
431  sigma->SetHumanValueScale(RAD2DEG);
432  mpSizer->Add(sigma,0,wxALIGN_CENTER);
433  mList.Add(sigma);
434 
435  this->SetSizer(mpSizer);
436  this->Layout();
437  this->CrystUpdate(true,true);
438  VFN_DEBUG_EXIT("WXMolBondAngle::WXMolBond():"<<obj->GetName(),6)
439 }
440 
442 {
443  mpMolBondAngle->WXNotifyDelete();
444 }
445 
446 void WXMolBondAngle::CrystUpdate(const bool uui,const bool lock)
447 {
448  VFN_DEBUG_ENTRY("WXMolBondAngle::CrystUpdate()",5)
449  if(lock) mMutex.Lock();
450  mValue=mpMolBondAngle->GetAngle();
451  mList.CrystUpdate(uui,false);
452  if(lock) mMutex.Unlock();
453  VFN_DEBUG_EXIT("WXMolBondAngle::CrystUpdate()",5)
454 }
455 
456 void WXMolBondAngle::UpdateUI(const bool lock)
457 {
458  VFN_DEBUG_ENTRY("WXMolBondAngle::UpdateUI()",5)
459  if(lock) mMutex.Lock();
460  mList.UpdateUI(false);
461  mpFieldAtom1->SetValue(mpMolBondAngle->GetAtom1().GetName().c_str());
462  mpFieldAtom2->SetValue(mpMolBondAngle->GetAtom2().GetName().c_str());
463  mpFieldAtom3->SetValue(mpMolBondAngle->GetAtom3().GetName().c_str());
464  if(lock) mMutex.Unlock();
465  VFN_DEBUG_EXIT("WXMolBondAngle::UpdateUI()",5)
466 }
467 
468 void WXMolBondAngle::OnChangeAtom(wxCommandEvent &event)
469 {
470  VFN_DEBUG_ENTRY("WXMolBondAngle::OnChangeAtom()",6)
472  int choice;
473  MolAtom *const at=WXDialogChooseFromVector(mpMolBondAngle->GetMolecule().GetAtomList(),
474  (wxWindow*)this,"Choose a new Atom",choice);
475  if(0==at) return;
476  if((long)ID_MOLBONDANGLE_ATOM1==event.GetId())
477  {
478  if((at==&(mpMolBondAngle->GetAtom2()) )||(at==&(mpMolBondAngle->GetAtom3())) )
479  {
480  wxMessageDialog dumbUser(this,_T("The three atoms must be different !"),
481  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
482  dumbUser.ShowModal();
483  return;
484  }
485  mpMolBondAngle->SetAtom1(*at);
486  }
487  if((long)ID_MOLBONDANGLE_ATOM2==event.GetId())
488  {
489  if((at==&(mpMolBondAngle->GetAtom1()) )||(at==&(mpMolBondAngle->GetAtom3())) )
490  {
491  wxMessageDialog dumbUser(this,_T("The three atoms must be different !"),
492  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
493  dumbUser.ShowModal();
494  return;
495  }
496  mpMolBondAngle->SetAtom2(*at);
497  }
498  if((long)ID_MOLBONDANGLE_ATOM3==event.GetId())
499  {
500  if((at==&(mpMolBondAngle->GetAtom1()) )||(at==&(mpMolBondAngle->GetAtom2())) )
501  {
502  wxMessageDialog dumbUser(this,_T("The three atoms must be different !"),
503  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
504  dumbUser.ShowModal();
505  return;
506  }
507  mpMolBondAngle->SetAtom3(*at);
508  }
509 
510  this->CrystUpdate(true);
511  this->UpdateUI(true);
512  VFN_DEBUG_EXIT("WXMolBondAngle::OnChangeScattPow()",6)
513 }
515 //
516 // WXMolDihedralAngle
517 //
519 WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM1;
520 WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM2;
521 WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM3;
522 WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM4;
523 
524 BEGIN_EVENT_TABLE(WXMolDihedralAngle,wxWindow)
525  EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM1, WXMolDihedralAngle::OnChangeAtom)
526  EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM2, WXMolDihedralAngle::OnChangeAtom)
527  EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM3, WXMolDihedralAngle::OnChangeAtom)
528  EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM4, WXMolDihedralAngle::OnChangeAtom)
529 END_EVENT_TABLE()
530 
531 WXMolDihedralAngle::WXMolDihedralAngle(wxWindow *parent, MolDihedralAngle*obj):
532 WXCrystObjBasic(parent),mpMolDihedralAngle(obj)
533 {
534  VFN_DEBUG_ENTRY("WXMolDihedralAngle::WXMolBond()",6)
535  mpSizer=new wxBoxSizer(wxHORIZONTAL);
536 
537  mpFieldAtom1=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM1,"Dihedral Angle:",60);
538  mpFieldAtom1->SetValue(mpMolDihedralAngle->GetAtom1().GetName());
539  mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER);
540  mList.Add(mpFieldAtom1);
541 
542  mpFieldAtom2=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM2,"-",60);
543  mpFieldAtom2->SetValue(mpMolDihedralAngle->GetAtom2().GetName());
544  mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER);
545  mList.Add(mpFieldAtom2);
546 
547  mpFieldAtom3=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM3,"-",60);
548  mpFieldAtom3->SetValue(mpMolDihedralAngle->GetAtom3().GetName());
549  mpSizer->Add(mpFieldAtom3,0,wxALIGN_CENTER);
550  mList.Add(mpFieldAtom3);
551 
552  mpFieldAtom4=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM4,"-",60);
553  mpFieldAtom4->SetValue(mpMolDihedralAngle->GetAtom4().GetName());
554  mpSizer->Add(mpFieldAtom4,0,wxALIGN_CENTER);
555  mList.Add(mpFieldAtom4);
556 
557  WXFieldPar<REAL> *value=
558  new WXFieldPar<REAL>(this,"Angle=",-1,&mValue);
559  value->SetHumanValueScale(RAD2DEG);
560  mpSizer->Add(value,0,wxALIGN_CENTER);
561  mList.Add(value);
562 
563  WXFieldPar<REAL> *angle=
564  new WXFieldPar<REAL>(this,"Restraint:",-1,&(mpMolDihedralAngle->Angle0()));
565  angle->SetHumanValueScale(RAD2DEG);
566  mpSizer->Add(angle,0,wxALIGN_CENTER);
567  mList.Add(angle);
568 
569  WXFieldPar<REAL> *delta=
570  new WXFieldPar<REAL>(this,",delta=",-1,&(mpMolDihedralAngle->AngleDelta()));
571  delta->SetHumanValueScale(RAD2DEG);
572  mpSizer->Add(delta,0,wxALIGN_CENTER);
573  mList.Add(delta);
574 
575  WXFieldPar<REAL> *sigma=
576  new WXFieldPar<REAL>(this,",sigma=",-1,&(mpMolDihedralAngle->AngleSigma()));
577  sigma->SetHumanValueScale(RAD2DEG);
578  mpSizer->Add(sigma,0,wxALIGN_CENTER);
579  mList.Add(sigma);
580 
581  this->SetSizer(mpSizer);
582  this->Layout();
583  this->CrystUpdate(true);
584  VFN_DEBUG_EXIT("WXMolDihedralAngle::WXMolBond():"<<obj->GetName(),6)
585 }
586 
587 WXMolDihedralAngle::~WXMolDihedralAngle()
588 {
589  mpMolDihedralAngle->WXNotifyDelete();
590 }
591 
592 void WXMolDihedralAngle::CrystUpdate(const bool uui,const bool lock)
593 {
594  VFN_DEBUG_ENTRY("WXMolDihedralAngle::CrystUpdate()",5)
595  if(lock) mMutex.Lock();
596  mValue=mpMolDihedralAngle->GetAngle();
597  mList.CrystUpdate(uui,false);
598  if(lock) mMutex.Unlock();
599  VFN_DEBUG_EXIT("WXMolDihedralAngle::CrystUpdate()",5)
600 }
601 
602 void WXMolDihedralAngle::UpdateUI(const bool lock)
603 {
604  VFN_DEBUG_ENTRY("WXMolDihedralAngle::UpdateUI()",5)
605  if(lock) mMutex.Lock();
606  mList.UpdateUI(false);
607  mpFieldAtom1->SetValue(mpMolDihedralAngle->GetAtom1().GetName().c_str());
608  mpFieldAtom2->SetValue(mpMolDihedralAngle->GetAtom2().GetName().c_str());
609  mpFieldAtom3->SetValue(mpMolDihedralAngle->GetAtom3().GetName().c_str());
610  if(lock) mMutex.Unlock();
611  VFN_DEBUG_EXIT("WXMolDihedralAngle::UpdateUI()",5)
612 }
613 
614 void WXMolDihedralAngle::OnChangeAtom(wxCommandEvent &event)
615 {
616  VFN_DEBUG_ENTRY("WXMolDihedralAngle::OnChangeAtom()",6)
618  int choice;
619  MolAtom *const at=WXDialogChooseFromVector(mpMolDihedralAngle->GetMolecule().GetAtomList(),
620  (wxWindow*)this,"Choose a new Atom",choice);
621  if(0==at) return;
622  if((long)ID_MOLDIHEDRALANGLE_ATOM1==event.GetId())
623  {
624  if( (at==&(mpMolDihedralAngle->GetAtom2()))
625  ||(at==&(mpMolDihedralAngle->GetAtom3()))
626  ||(at==&(mpMolDihedralAngle->GetAtom4())) )
627  {
628  wxMessageDialog dumbUser(this,_T("The four atoms must be different !"),
629  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
630  dumbUser.ShowModal();
631  return;
632  }
633  mpMolDihedralAngle->SetAtom1(*at);
634  }
635  if((long)ID_MOLDIHEDRALANGLE_ATOM2==event.GetId())
636  {
637  if( (at==&(mpMolDihedralAngle->GetAtom1()))
638  ||(at==&(mpMolDihedralAngle->GetAtom3()))
639  ||(at==&(mpMolDihedralAngle->GetAtom4())) )
640  {
641  wxMessageDialog dumbUser(this,_T("The four atoms must be different !"),
642  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
643  dumbUser.ShowModal();
644  return;
645  }
646  mpMolDihedralAngle->SetAtom2(*at);
647  }
648  if((long)ID_MOLDIHEDRALANGLE_ATOM3==event.GetId())
649  {
650  if( (at==&(mpMolDihedralAngle->GetAtom1()))
651  ||(at==&(mpMolDihedralAngle->GetAtom2()))
652  ||(at==&(mpMolDihedralAngle->GetAtom4())) )
653  {
654  wxMessageDialog dumbUser(this,_T("The four atoms must be different !"),
655  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
656  dumbUser.ShowModal();
657  return;
658  }
659  mpMolDihedralAngle->SetAtom3(*at);
660  }
661  if((long)ID_MOLDIHEDRALANGLE_ATOM4==event.GetId())
662  {
663  if( (at==&(mpMolDihedralAngle->GetAtom1()))
664  ||(at==&(mpMolDihedralAngle->GetAtom2()))
665  ||(at==&(mpMolDihedralAngle->GetAtom3())) )
666  {
667  wxMessageDialog dumbUser(this,_T("The four atoms must be different !"),
668  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
669  dumbUser.ShowModal();
670  return;
671  }
672  mpMolDihedralAngle->SetAtom4(*at);
673  }
674 
675  this->CrystUpdate(true);
676  this->UpdateUI(true);
677  VFN_DEBUG_EXIT("WXMolDihedralAngle::OnChangeScattPow()",6)
678 }
679 
681 //
682 // WXMolecule Grid objects
683 //
685 WXMolecule::CellAtom::CellAtom():
686 mpAtom(0),mName(""),mpScatteringPower(0),mX(0),mY(0),mZ(0),mNeedUpdateUI(true)
687 {}
688 
689 WXMolecule::CellBond::CellBond():
690 mpBond(0),mAtom1(""),mAtom2(""),
691 mLength(0),mLength0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true)
692 {}
693 
694 WXMolecule::CellBondAngle::CellBondAngle():
695 mpBondAngle(0),mAtom1(""),mAtom2(""),mAtom3(""),
696 mAngle(0),mAngle0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true)
697 {}
698 
699 WXMolecule::CellDihedralAngle::CellDihedralAngle():
700 mpDihedralAngle(0),mAtom1(""),mAtom2(""),mAtom3(""),mAtom4(""),
701 mAngle(0),mAngle0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true)
702 {}
703 
704 WXMolecule::CellRigidGroup::CellRigidGroup():
705 mpGroup(0),mNeedUpdateUI(false)
706 {}
707 
708 
710 //
711 // WXMolecule
712 //
714 
715 WXCRYST_ID ID_MENU_OPTIMIZECONFORMATION;
716 WXCRYST_ID ID_MENU_SETLIMITS;
717 WXCRYST_ID ID_MOLECULE_MENU_FILE;
718 WXCRYST_ID ID_MOLECULE_MENU_FILE_2ZMATRIX;
719 WXCRYST_ID ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED;
720 WXCRYST_ID ID_MOLECULE_MENU_PAR_MDTEST;
721 WXCRYST_ID ID_MOLECULE_MENU_FORMULA;
722 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION;
723 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_STATUS;
724 WXCRYST_ID ID_MOLECULE_MENU_EXPORT_RESTRAINTS;
725 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_ATOM;
726 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_BOND;
727 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_ANGLE;
728 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL;
729 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP;
730 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM;
731 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES;
732 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_TEST;
733 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM;
734 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_BOND;
735 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE;
736 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL;
737 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP;
738 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM;
739 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT;
740 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA;
741 WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY;
742 WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND;
743 WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED;
744 
745 WXCRYST_ID ID_MOLECULE_CHANGE_CENTER_ATOM;
746 
747 
748 WXCRYST_ID ID_WINDOW_ATOM;
749 WXCRYST_ID ID_WINDOW_BONDLENGTH;
750 WXCRYST_ID ID_WINDOW_BONDANGLE;
751 WXCRYST_ID ID_WINDOW_DIHEDRALANGLE;
752 WXCRYST_ID ID_WINDOW_RIGIDGROUP;
753 WXCRYST_ID ID_WINDOW_NONFLIPATOM;
754 
755 BEGIN_EVENT_TABLE(WXMolecule,wxWindow)
756  EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse)
757  EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar)
758  EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar)
759  EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize)
760  EVT_MENU(ID_MOLECULE_MENU_PAR_MDTEST, WXMolecule::OnMenuMDTest)
761  EVT_MENU(ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION,WXMolecule::OnMenuOptimizeConformation)
762  EVT_MENU(ID_MOLECULE_MENU_FORMULA_STATUS, WXMolecule::OnMenuPrintRestraintStatus)
763  EVT_MENU(ID_MOLECULE_MENU_EXPORT_RESTRAINTS, WXMolecule::OnMenuExportRestraints)
764  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_ATOM, WXMolecule::OnMenuAddAtom)
765  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_BOND, WXMolecule::OnMenuAddBond)
766  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_ANGLE, WXMolecule::OnMenuAddAngle)
767  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL, WXMolecule::OnMenuAddDihedralAngle)
768  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP, WXMolecule::OnMenuAddRigidGroup)
769  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM, WXMolecule::OnMenuAddNonFlipAtom)
770  EVT_MENU(ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES,WXMolecule::OnMenuRigidfyWithDihedralAngles)
771  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM, WXMolecule::OnMenuRemoveAtom)
772  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_BOND, WXMolecule::OnMenuRemoveBond)
773  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE, WXMolecule::OnMenuRemoveAngle)
774  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL, WXMolecule::OnMenuRemoveDihedralAngle)
775  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP, WXMolecule::OnMenuRemoveRigidGroup)
776  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM, WXMolecule::OnMenuRemoveNonFlipAtom)
777  EVT_MENU(ID_MOLECULE_MENU_FORMULA_TEST , WXMolecule::OnMenuTest)
778  EVT_MENU(ID_MENU_SETLIMITS, WXMolecule::OnMenuSetLimits)
779  EVT_MENU(ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT, WXMolecule::OnMenuShowRestraintWindow)
780  EVT_MENU(ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA ,WXMolecule::OnMenuSetDeltaSigma)
781  EVT_MENU(ID_MOLECULE_MENU_FILE_2ZMATRIX, WXMolecule::OnMenuExport2ZMatrix)
782  EVT_MENU(ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED, WXMolecule::OnMenuExport2ZMatrix)
783  EVT_MENU(ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND, WXMolecule::OnMenuRotate)
784  EVT_MENU(ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED, WXMolecule::OnMenuRotate)
785  EVT_GRID_CMD_CELL_CHANGE(ID_WINDOW_ATOM, WXMolecule::OnEditGridAtom)
786  EVT_GRID_CMD_CELL_CHANGE(ID_WINDOW_BONDLENGTH, WXMolecule::OnEditGridBondLength)
787  EVT_GRID_CMD_CELL_CHANGE(ID_WINDOW_BONDANGLE, WXMolecule::OnEditGridBondAngle)
788  EVT_GRID_CMD_CELL_CHANGE(ID_WINDOW_DIHEDRALANGLE, WXMolecule::OnEditGridDihedralAngle)
789  EVT_GRID_CMD_CELL_CHANGE(ID_WINDOW_RIGIDGROUP, WXMolecule::OnEditGridRigidGroup)
790  EVT_BUTTON(ID_MOLECULE_CHANGE_CENTER_ATOM, WXMolecule::OnChangeCenterAtom)
791 END_EVENT_TABLE()
792 
793 WXMolecule::WXMolecule(wxWindow *parent, Molecule *mol):
794 WXScatterer(parent,mol),mpMolecule(mol),
795 mpBondWin(0),mpAngleWin(0),mpDihedralAngleWin(0),mpRigidGroupWin(0),mpNonFlipAtomWin(0),mIsSelfUpdating(false)
796 {
797  VFN_DEBUG_ENTRY("WXMolecule::WXMolecule():"<<mol->GetName(),6)
798  //Menus
799  mpMenuBar->AddMenu("File",ID_MOLECULE_MENU_FILE);
800  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FILE,ID_MOLECULE_MENU_FILE_2ZMATRIX,"Export to Fenske-Hall Z-Matrix");
801  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FILE,ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED,"Export to Z-Matrix with atom names");
802  mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR);
803  mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all");
804  mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all");
805  mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_RANDOMIZE,
806  "Randomize Configuration");
807  mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_MOLECULE_MENU_PAR_MDTEST,
808  "Test Molecular Dynamics moves for 30s");
809  mpMenuBar->AddMenu("Formula && Restraints",ID_MOLECULE_MENU_FORMULA);
810  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION,
811  "Optimize Starting Conformation");
812  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA,
813  "Set Restraints delta && sigma for all bonds && angles");
814  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_STATUS,
815  "Print Detailed Restraint Values");
816  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_EXPORT_RESTRAINTS,
817  "Export Restraints in CVS File format");
818  mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator();
819  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_ATOM,
820  "Add an Atom");
821  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_BOND,
822  "Add Bond Restraint");
823  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_ANGLE,
824  "Add Bond Angle Restraint");
825  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL,
826  "Add Dihedral Angle Restraint");
827  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP,
828  "Add Rigid Group");
829  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM,
830  "Add Non-Flip Atom");
831  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES,
832  "Rigidify with Dihedral Angles");
833  mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator();
834  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM,
835  "Remove an Atom");
836  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_BOND,
837  "Remove a Bond Restraint");
838  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE,
839  "Remove a Bond Angle Restraint");
840  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL,
841  "Remove a Dihedral Angle Restraint");
842  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP,
843  "Remove Rigid Group");
844  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM,
845  "Remove Non-Flip Atom");
846 
847  mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator();
848  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT,
849  "Show Restraint Window");
850  //#ifdef __DEBUG__
851  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_TEST,"Debug Test");
852  //#endif
853  mpMenuBar->AddMenu("Manipulate Geometry",ID_MOLECULE_MENU_GEOMETRY);
854  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_GEOMETRY,ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND,
855  "Rotate around bond");
856  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_GEOMETRY,ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED,
857  "Set dihedral angle");
858  //mpSizer->SetItemMinSize(mpMenuBar,
859  // mpMenuBar->GetSize().GetWidth(),
860  // mpMenuBar->GetSize().GetHeight());
861  WXFieldPar<REAL> *pLLKScale= new WXFieldPar<REAL>(this,"Log(likelihood) scale",-1,&(mpMolecule->mLogLikelihoodScale));
862  mList.Add(pLLKScale);
863  mpSizer->Add(pLLKScale,0,wxALIGN_LEFT);
864  pLLKScale->SetToolTip(_T("The log(likelihood) of the molecule, i.e. the sum\n")
865  _T("of the restraints costs for all bonds and angles \n")
866  _T("are multiplied by this scale.\n\n")
867  _T("The default value is 1.\n\n")
868  _T("Multiplying this value by 4 is equivalent to dividing the\n")
869  _T("sigma of all bonds and angles by a factor 2.\n")
870  _T("This can be increased if the molecule presents too\n")
871  _T("much distortion.\n\n")
872  _T("Note that a too large value (e.g.>100) will decrease the\n")
873  _T("convergence speed of the algorithm, as distortion of the\n")
874  _T("structure is necessary for an efficient minimisation."));
875 
876  // Molecular Dynamics move parameters
877  wxBoxSizer* pMDSizer=new wxBoxSizer(wxHORIZONTAL);
878  WXFieldPar<REAL> *pWXFieldMDEnergy=
879  new WXFieldPar<REAL>(this,"MD moves Energy",-1,&(mpMolecule->mMDMoveEnergy));
880  WXFieldPar<REAL> *pWXFieldMDFrequency=
881  new WXFieldPar<REAL>(this,"MD moves frequency",-1,&(mpMolecule->mMDMoveFreq));
882  pMDSizer->Add(pWXFieldMDFrequency);
883  pMDSizer->Add(pWXFieldMDEnergy);
884  mpSizer->Add(pMDSizer,0,wxALIGN_LEFT);
885  mList.Add(pWXFieldMDEnergy);
886  mList.Add(pWXFieldMDFrequency);
887 
888  pWXFieldMDFrequency->SetToolTip(_T("Frequency of Molecular Dynamics Moves (0.0-1.0)\n\n")
889  _T("MD moves are used to alter the conformation of atom groups \n")
890  _T("which cannot be changed by simple bond distance\n")
891  _T("or bond angle changes.\n\n")
892  _T("MD moves are CPU intensive, so a slow value (0.05) is recommended\n")
893  _T("Larger frequencies can be used for constrained molecules,\n")
894  _T("e.g. with large, flexible cycles."));
895  pWXFieldMDEnergy->SetToolTip(_T("Energy of Molecule for Molecular Dynamics Moves\n\n")
896  _T("Standard amplitude=40. \n")
897  _T("Small amplitude=10. (small distortion of the Molecule)\n")
898  _T("Large amplitude=400. (large distortion of the Molecule)"));
899  //Center atom
900  mpFieldCenterAtom=new WXFieldChoice(this,ID_MOLECULE_CHANGE_CENTER_ATOM,"Center Atom:",240);
901  if(mpMolecule->GetCenterAtom()!=0)
902  mpFieldCenterAtom->SetValue(mpMolecule->GetCenterAtom()->GetName());
903  else mpFieldCenterAtom->SetValue("Click to choose an atom !");
904  mpSizer->Add(mpFieldCenterAtom,0,wxALIGN_LEFT);
905  mList.Add(mpFieldCenterAtom);
906  // Atom list
907  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
908  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
909  cellAttrName->SetEditor(new wxGridCellTextEditor);
910  wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
911  cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(6,3));
912  cellAttrFloat->SetEditor(new wxGridCellFloatEditor(6,3));
913 
914  mpAtomWin= new WXMolScrolledWindow(this,this,ID_WINDOW_ATOM);
915  //mpAtomWin->SetSize(800,300);
916  mpAtomWin->EnableScrolling(true,true);
917  //mpAtomWin->SetSizeHints(-1,300,-1,300);
918  mpAtomWin->CreateGrid(0,6);
919  mpAtomWin->SetRowLabelSize(40);
920  mpAtomWin->SetDefaultColSize(60);
921  mpAtomWin->SetColAttr(0,cellAttrName);
922  mpAtomWin->SetColAttr(1,cellAttrName->Clone());
923  mpAtomWin->SetColAttr(2,cellAttrFloat);
924  mpAtomWin->SetColAttr(3,cellAttrFloat->Clone());
925  mpAtomWin->SetColAttr(4,cellAttrFloat->Clone());
926  mpAtomWin->SetColAttr(5,cellAttrFloat->Clone());
927  mpAtomWin->SetColLabelValue(0,_T("Name"));
928  mpAtomWin->SetColLabelValue(1,_T("Type"));
929  mpAtomWin->SetColLabelValue(2,_T("X"));
930  mpAtomWin->SetColLabelValue(3,_T("Y"));
931  mpAtomWin->SetColLabelValue(4,_T("Z"));
932  mpAtomWin->SetColLabelValue(5,_T("Occup"));
933  mpAtomWin->AutoSizeRows();
934  mpSizer->Add(mpAtomWin,0,wxALIGN_LEFT);
935  this->CrystUpdate(true);
936  VFN_DEBUG_EXIT("WXMolecule::WXMolecule():"<<mol->GetName(),6)
937 }
938 
939 WXMolecule::~WXMolecule()
940 {
941  VFN_DEBUG_ENTRY("WXMolecule::~WXMolecule()",10)
942  if(0!=mpBondWin) mpBondWin->GetParent()->Destroy();
943  VFN_DEBUG_EXIT("WXMolecule::~WXMolecule()",10)
944 }
945 
946 void WXMolecule::OnMenuOptimizeConformation(wxCommandEvent & WXUNUSED(event))
947 {
948  VFN_DEBUG_ENTRY("WXMolecule::OnMenuOptimizeConformation()",5)
950  mpMolecule->OptimizeConformation(20000,mpMolecule->GetAtomList().size());
951  mpMolecule->OptimizeConformationSteepestDescent(0.01,100);
952  mpMolecule->RestraintStatus(cout);
953 
954  LSQNumObj lsq;
955  lsq.SetRefinedObj(*mpMolecule);
956  lsq.PrepareRefParList(true);
957  lsq.SetParIsUsed(gpRefParTypeObjCryst,false);
958  lsq.SetParIsUsed(gpRefParTypeScattConform,true);
959  try {lsq.Refine(10,true,false);}
960  catch(const ObjCrystException &except){}
961  mpMolecule->GetCrystal().UpdateDisplay();
962  mpMolecule->RestraintStatus(cout);
963 
964  mpMolecule->GetCrystal().UpdateDisplay();
965 
966  VFN_DEBUG_EXIT("WXMolecule::OnMenuOptimizeConformation()",5)
967 }
968 void WXMolecule::OnMenuExportRestraints(wxCommandEvent & WXUNUSED(event))
969 {
970  VFN_DEBUG_ENTRY("WXMolecule::OnMenuExportRestraints()",5)
972 
973  stringstream ss;
974  mpMolecule->RestraintExport(ss);
975 
976  wxFileDialog open(this,_T("Choose File to save restraints:"),
977  _T(""),_T(""),_T("*.csv"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
978  if(open.ShowModal() != wxID_OK) return;
979  wxString name=open.GetPath();
980  if(name.substr(name.size()-4,4)!=_T(".csv"))
981  {
982  cout<<name<<" -> "<<name+_T(".csv")<<endl;
983  name=name+_T(".csv");
984  }
985 
986  wxFileOutputStream ostream(name.c_str());
987  ostream.Write(ss.str().c_str(),ss.str().size());
988 
989  VFN_DEBUG_EXIT("WXMolecule::OnMenuExportRestraints()",5)
990 }
991 void WXMolecule::OnMenuPrintRestraintStatus(wxCommandEvent & WXUNUSED(event))
992 {
993  VFN_DEBUG_ENTRY("WXMolecule::OnMenuPrintRestraintStatus()",5)
995  mpMolecule->RestraintStatus(cout);
996  VFN_DEBUG_EXIT("WXMolecule::OnMenuPrintRestraintStatus()",5)
997 }
998 
999 void WXMolecule::OnMenuAddAtom(wxCommandEvent & WXUNUSED(event))
1000 {
1001  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddAtom()",6)
1003  int choice;
1004  const ScatteringPower *scatt=WXDialogChooseFromRegistry(
1005  mpMolecule->GetCrystal().GetScatteringPowerRegistry(),
1006  (wxWindow*)this,"Choose a new Scattering Power",choice);
1007  if(0==scatt) return;
1008  long num=mpMolecule->GetAtomList().size();
1009  if(num>0)
1010  {
1011  wxString lastAtom=wxString::FromAscii(mpMolecule->GetAtom(num-1).GetName().c_str());
1012  for(;;)
1013  {
1014  if(lastAtom.size()==0) break;
1015  if(lastAtom.IsNumber())
1016  {
1017  lastAtom.ToLong(&num);
1018  break;
1019  }
1020  lastAtom.erase(0,1);
1021  }
1022  }
1023  stringstream st;
1024  st<<num+1;
1025  mpMolecule->AddAtom(0.,0.,0.,scatt,scatt->GetName()+st.str());
1026  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddAtom()",6)
1027 }
1028 
1029 void WXMolecule::OnMenuAddBond(wxCommandEvent & WXUNUSED(event))
1030 {
1031  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddBond()",6)
1033  int choice;
1034  vector<MolAtom*> v=mpMolecule->GetAtomList();
1035  MolAtom *at1=WXDialogChooseFromVector(v,
1036  (wxWindow*)this,"Choose the first Atom",choice);
1037  if(0==at1) return;
1038  MolAtom *at2=WXDialogChooseFromVector(v,
1039  (wxWindow*)this,"Choose the second Atom",choice);
1040  if(0==at2) return;
1041 
1042  if(at1==at2)
1043  {
1044  wxMessageDialog dumbUser(this,_T("The two atoms must be different !"),
1045  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1046  dumbUser.ShowModal();
1047  return;
1048  }
1049  static double d=1.5;//static so that last entered value will be used next time
1050  wxString s;
1051  s.Printf(_T("%6.3f"),d);
1052  // if((at1->IsDummy())||(at2->IsDummy())) d=1.5;
1053  // else d= (at1->GetScatteringPower().GetRadius()+at2->GetScatteringPower().GetRadius())*0.9;
1054  string mes="Enter bond distance (Angstroems) for "+at1->GetName()+"-"+at2->GetName();
1055  wxTextEntryDialog dialog(this,wxString::FromAscii(mes.c_str()),
1056  _T("Bond distance"),s,wxOK | wxCANCEL);
1057  if(wxID_OK!=dialog.ShowModal())
1058  {
1059  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond():Canceled",6)
1060  return;
1061  }
1062  dialog.GetValue().ToDouble(&d);
1063 
1064  mpMolecule->AddBond(*at1,*at2,d,.01,.02,1.);
1065  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond()",6)
1066 }
1067 
1068 void WXMolecule::OnMenuAddAngle(wxCommandEvent & WXUNUSED(event))
1069 {
1070  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddBond()",6)
1072  int choice;
1073  vector<MolAtom*> v=mpMolecule->GetAtomList();
1074  MolAtom *at1=WXDialogChooseFromVector(v,
1075  (wxWindow*)this,"Choose the first Atom",choice);
1076  if(0==at1) return;
1077  MolAtom *at2=WXDialogChooseFromVector(v,
1078  (wxWindow*)this,"Choose the second Atom",choice);
1079  if(0==at2) return;
1080 
1081  MolAtom *at3=WXDialogChooseFromVector(v,
1082  (wxWindow*)this,"Choose the third Atom",choice);
1083  if(0==at2) return;
1084 
1085  if( (at1==at2) || (at1==at3) ||(at2==at3))
1086  {
1087  wxMessageDialog dumbUser(this,_T("The three atoms must be different !"),
1088  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1089  dumbUser.ShowModal();
1090  return;
1091  }
1092 
1093  static double a=109.5;//static so that last entered value will be used next time
1094  wxString s;
1095  s.Printf(_T("%6.2f"),a);
1096  string mes="Enter bond angle (degrees) for "+at1->GetName()
1097  +"-"+at2->GetName()
1098  +"-"+at3->GetName();
1099  wxTextEntryDialog dialog(this,wxString::FromAscii(mes.c_str()),
1100  _T("Bond angle"),s,wxOK | wxCANCEL);
1101  if(wxID_OK!=dialog.ShowModal())
1102  {
1103  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddAngle():Canceled",6)
1104  return;
1105  }
1106  dialog.GetValue().ToDouble(&a);
1107 
1108  mpMolecule->AddBondAngle(*at1,*at2,*at3,a*DEG2RAD,.01,0.02);
1109  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond()",6)
1110 }
1111 
1112 void WXMolecule::OnMenuAddDihedralAngle(wxCommandEvent & WXUNUSED(event))
1113 {
1114  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddDihedralAngle()",6)
1116  int choice;
1117  vector<MolAtom*> v=mpMolecule->GetAtomList();
1118  MolAtom *at1=WXDialogChooseFromVector(v,
1119  (wxWindow*)this,"Choose the first Atom",choice);
1120  if(0==at1) return;
1121  MolAtom *at2=WXDialogChooseFromVector(v,
1122  (wxWindow*)this,"Choose the second Atom",choice);
1123  if(0==at2) return;
1124 
1125  MolAtom *at3=WXDialogChooseFromVector(v,
1126  (wxWindow*)this,"Choose the third Atom",choice);
1127  if(0==at3) return;
1128 
1129  MolAtom *at4=WXDialogChooseFromVector(v,
1130  (wxWindow*)this,"Choose the fourth Atom",choice);
1131  if(0==at4) return;
1132 
1133  if( (at1==at2) || (at1==at3) || (at1==at4) || (at2==at3) || (at2==at4) || (at3==at4))
1134  {
1135  wxMessageDialog dumbUser(this,_T("The atoms must be different !"),
1136  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1137  dumbUser.ShowModal();
1138  return;
1139  }
1140 
1141  static double a=180;
1142  wxString s;
1143  s.Printf(_T("%6.2f"),a);
1144  string mes="Enter dihedral angle (degrees) for "+at1->GetName()
1145  +"-"+at2->GetName()
1146  +"-"+at3->GetName()
1147  +"-"+at4->GetName();
1148  wxTextEntryDialog dialog(this,_T("Enter dihedral angle (degrees)"),
1149  _T("Bond angle"),s,wxOK | wxCANCEL);
1150  if(wxID_OK!=dialog.ShowModal())
1151  {
1152  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddDihedralAngle():Canceled",6)
1153  return;
1154  }
1155  dialog.GetValue().ToDouble(&a);
1156 
1157  mpMolecule->AddDihedralAngle(*at1,*at2,*at3,*at4,a*DEG2RAD,.01,.02);
1158  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddDihedralAngle()",6)
1159 }
1160 
1161 void WXMolecule::OnMenuAddRigidGroup(wxCommandEvent & WXUNUSED(event))
1162 {
1163  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddRigidGroup()",6)
1165  list<MolAtom*> l=WXDialogChooseMultipleFromVector(mpMolecule->GetAtomList(),this,
1166  "Choose atoms in the rigid group");
1167  RigidGroup s;
1168  for(list<MolAtom*>::const_iterator pos=l.begin();pos!=l.end();++pos) s.insert(*pos);
1169  mpMolecule->AddRigidGroup(s);
1170  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddRigidGroup()",6)
1171 }
1172 void WXMolecule::OnMenuAddNonFlipAtom(wxCommandEvent & WXUNUSED(event))
1173 {
1174  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddNonFlipAtom()",6)
1176  int choice;
1177  vector<MolAtom*> v=mpMolecule->GetAtomList();
1178  vector<MolAtom*> nf = mpMolecule->getNonFlipAtomList();
1179  for(vector<MolAtom*>::iterator pos=v.begin();pos!=v.end();) {
1180  bool erase=false;
1181  for(int i=0;i<nf.size();i++) {
1182  if(nf[i]->GetName().compare((*pos)->GetName())==0) {
1183  erase=true;
1184  break;
1185  }
1186  }
1187  if(erase) {
1188  pos=v.erase(pos);
1189  } else {
1190  pos++;
1191  }
1192  }
1193 
1194  MolAtom *at1=WXDialogChooseFromVector(v,
1195  (wxWindow*)this,"Choose the Optically active Atom",choice);
1196 
1197  if(0==at1) {
1198  wxMessageDialog dumbUser(this,_T("Atom not selected !"),
1199  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1200  dumbUser.ShowModal();
1201  return;
1202  }
1203 
1204  mpMolecule->AddNonFlipAtom(*at1);
1205  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddNonFlipAtom()",6)
1206 }
1207 void WXMolecule::OnMenuRemoveAtom(wxCommandEvent & WXUNUSED(event))
1208 {
1209  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveAtom()",6)
1210  vector<MolAtom*> v=mpMolecule->GetAtomList();
1211  list<MolAtom*> vAt=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1212  "Choose the Atom(s) to be removed");
1213  if(0==vAt.size()) return;
1214  for(list<MolAtom*>::iterator pos=vAt.begin();pos!=vAt.end();++pos) mpMolecule->RemoveAtom(**pos);
1215  this->CrystUpdate(true);
1216  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveAtom()",6)
1217 }
1218 
1219 void WXMolecule::OnMenuRemoveBond(wxCommandEvent & WXUNUSED(event))
1220 {
1221  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveBond()",6)
1222  vector<MolBond*> v=mpMolecule->GetBondList();
1223  list<MolBond*> vBond=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1224  "Choose the Bond(s) to be removed");
1225  if(0==vBond.size()) return;
1226  const int answer =wxMessageBox
1227  (_T("Remove Bond and Dihedral Angles involving the deleted Bond(s) (if any) ?"),
1228  _T("Delete related Restraints ?"),wxYES_NO, this);
1229  for(list<MolBond*>::iterator pos=vBond.begin();pos!=vBond.end();++pos)
1230  {
1231  if(answer==wxYES)
1232  {
1233  const MolAtom *pAtom1= &((*pos)->GetAtom1());
1234  const MolAtom *pAtom2= &((*pos)->GetAtom2());
1235  for(vector<MolBondAngle*>::iterator posb=mpMolecule->GetBondAngleList().begin();
1236  posb!=mpMolecule->GetBondAngleList().end();)
1237  {
1238  if( ( (pAtom1==&((*posb)->GetAtom1())) && (pAtom2==&((*posb)->GetAtom2())) )
1239  ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom1())) )
1240  ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom3())) )
1241  ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom2())) ))
1242  posb=mpMolecule->RemoveBondAngle(**posb);
1243  else ++posb;
1244  }
1245  for(vector<MolDihedralAngle*>::iterator posb=mpMolecule->GetDihedralAngleList().begin();
1246  posb!=mpMolecule->GetDihedralAngleList().end();)
1247  {
1248  if( ( (pAtom1==&((*posb)->GetAtom1())) && (pAtom2==&((*posb)->GetAtom2())) )
1249  ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom1())) )
1250  ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom3())) )
1251  ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom2())) )
1252  ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom4())) )
1253  ||( (pAtom1==&((*posb)->GetAtom4())) && (pAtom2==&((*posb)->GetAtom3())) ))
1254  posb=mpMolecule->RemoveDihedralAngle(**posb);
1255  else ++posb;
1256  }
1257  }
1258  mpMolecule->RemoveBond(**pos);
1259  }
1260  this->CrystUpdate(true);
1261  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveBond()",6)
1262 }
1263 
1264 void WXMolecule::OnMenuRemoveAngle(wxCommandEvent & WXUNUSED(event))
1265 {
1266  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveAngle()",6)
1267  vector<MolBondAngle*> v=mpMolecule->GetBondAngleList();
1268  list<MolBondAngle*> vAngle=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1269  "Choose the Bond Angle(s) to be removed");
1270  if(0==vAngle.size()) return;
1271  for(list<MolBondAngle*>::iterator pos=vAngle.begin();pos!=vAngle.end();++pos)
1272  mpMolecule->RemoveBondAngle(**pos);
1273  this->CrystUpdate(true);
1274  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveAngle()",6)
1275 }
1276 
1277 void WXMolecule::OnMenuRemoveDihedralAngle(wxCommandEvent & WXUNUSED(event))
1278 {
1279  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveDihedralAngle()",6)
1280  vector<MolDihedralAngle*> v=mpMolecule->GetDihedralAngleList();
1281  list<MolDihedralAngle*> vAngle=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1282  "Choose the Dihedral Angle(s) to be removed");
1283  if(0==vAngle.size()) return;
1284  for(list<MolDihedralAngle*>::iterator pos=vAngle.begin();pos!=vAngle.end();++pos)
1285  mpMolecule->RemoveDihedralAngle(**pos);
1286  this->CrystUpdate(true);
1287  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveDihedralAngle()",6)
1288 }
1289 void WXMolecule::OnMenuRemoveNonFlipAtom(wxCommandEvent & WXUNUSED(event))
1290 {
1291  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveNonFlipAtom()",6)
1292  int choice;
1293  vector<MolAtom*> v = mpMolecule->getNonFlipAtomList();
1294 
1295  if(v.size()==0) {
1296  wxMessageDialog dumbUser(this,_T("The list of optically active atoms is empty !"),
1297  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1298  dumbUser.ShowModal();
1299  return;
1300  }
1301  MolAtom *at1=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the Optically active Atom to be removed",choice);
1302  if(0==at1) {
1303  wxMessageDialog dumbUser(this,_T("Atom not selected !"),
1304  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1305  dumbUser.ShowModal();
1306  return;
1307  }
1308 
1309  mpMolecule->removeNonFlipAtom(*at1);
1310  this->CrystUpdate(true);
1311  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveNonFlipAtom()",6)
1312 }
1313 void WXMolecule::OnMenuRemoveRigidGroup(wxCommandEvent & WXUNUSED(event))
1314 {
1315  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveRigidGroup()",6)
1317  vector<RigidGroup*> v=mpMolecule->GetRigidGroupList();
1318  list<RigidGroup*> vGroup=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1319  "Choose the Rigid Group(s) to be removed");
1320  if(0==vGroup.size()) return;
1321  for(list<RigidGroup*>::iterator pos=vGroup.begin();pos!=vGroup.end();++pos)
1322  mpMolecule->RemoveRigidGroup(**pos);
1323  this->CrystUpdate(true);
1324  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveRigidGroup()",6)
1325 }
1326 /*
1327 void WXMolecule::OnMenuRemoveFlipGroup(wxCommandEvent & WXUNUSED(event))
1328 {
1329  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveFlipGroup()",6)
1330  WXCrystValidateAllUserInput();
1331  mpMolecule->BuildFlipGroup();
1332  list<Molecule::FlipGroup> v = mpMolecule->GetFlipGroupList();
1333 
1334  wxString *choices = new wxString[v.size()];
1335  int i=0;
1336  for(list<Molecule::FlipGroup>::iterator pos=v.begin();pos!=v.end();++pos) {
1337  if(pos->mvRotatedChainList.begin()->first==pos->mpAtom0) {
1338  choices[i] = pos->mpAtom0->GetName();
1339  choices[i] += ": ";
1340  choices[i] += pos->mpAtom1->GetName();
1341  choices[i] += " <-> ";
1342  choices[i] += pos->mpAtom2->GetName();
1343  } else {
1344  choices[i] = pos->mpAtom0->GetName();
1345  for(list<pair<const MolAtom *,set<MolAtom*> > >::const_iterator chain=pos->mvRotatedChainList.begin(); chain!=pos->mvRotatedChainList.end();++chain) {
1346  choices[i] += chain->first->GetName();
1347  choices[i] += " <-> ";
1348  }
1349  choices[i].Remove(choices[i].size()-5, choices[i].size());
1350  }
1351  i++;
1352  }
1353 
1354  wxMultiChoiceDialog_ListBox dialog ((wxWindow*)this, "Choose the Flip Group(s) to be removed",_T("Choose"),v.size(),choices);
1355  dialog.ShowModal();
1356  wxArrayInt choice=dialog.GetSelections();
1357 
1358  delete[] choices;
1359 
1360  this->CrystUpdate(true);
1361  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveFlipGroup()",6)
1362 }
1363 */
1364 void WXMolecule::OnEditGridAtom(wxGridEvent &e)
1365 {
1366  if(mIsSelfUpdating) return;
1367  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridAtom():"<<e.GetRow()<<","<<e.GetCol(),10)
1368  const long r=e.GetRow();
1369  const long c=e.GetCol();
1370  if(c==0)
1371  {
1372  wxString s=mpAtomWin->GetCellValue(r,c);
1373  if(s!=_T(""))
1374  mpMolecule->GetAtomList()[r]->SetName(string(s.ToAscii()));
1375  }
1376  if(c==1)
1377  {
1378  wxString s=mpAtomWin->GetCellValue(r,c);
1379  if(s!=_T(""))
1380  {
1381  try
1382  {
1383  long p=mpMolecule->GetCrystal().GetScatteringPowerRegistry().Find(string(s.ToAscii()));
1384  if(p>=0) mpMolecule->GetAtomList()[r]->SetScatteringPower(
1385  mpMolecule->GetCrystal().GetScatteringPowerRegistry().GetObj(p));
1386  }
1387  catch(ObjCrystException){};
1388  }
1389  }
1390  if(c==2)
1391  {
1392  wxString s=mpAtomWin->GetCellValue(r,c);
1393  if(s!=_T(""))
1394  {
1395  double d;
1396  if(s.ToDouble(&d))
1397  mpMolecule->GetAtomList()[r]->SetX(d);
1398  }
1399  }
1400  if(c==3)
1401  {
1402  wxString s=mpAtomWin->GetCellValue(r,c);
1403  if(s!=_T(""))
1404  {
1405  double d;
1406  if(s.ToDouble(&d))
1407  mpMolecule->GetAtomList()[r]->SetY(d);
1408  }
1409  }
1410  if(c==4)
1411  {
1412  wxString s=mpAtomWin->GetCellValue(r,c);
1413  if(s!=_T(""))
1414  {
1415  double d;
1416  if(s.ToDouble(&d))
1417  mpMolecule->GetAtomList()[r]->SetZ(d);
1418  }
1419  }
1420  if(c==5)
1421  {
1422  wxString s=mpAtomWin->GetCellValue(r,c);
1423  if(s!=_T(""))
1424  {
1425  double d;
1426  if(s.ToDouble(&d))
1427  {
1428  if(d>1)d=1;
1429  else if(d<0)d=0;
1430  mpMolecule->GetAtomList()[r]->SetOccupancy(d);
1431  }
1432  }
1433  }
1434  mpMolecule->GetCrystal().UpdateDisplay();
1435  VFN_DEBUG_EXIT("WXMolecule::OnEditGridAtom():"<<e.GetRow()<<","<<e.GetCol(),10)
1436 }
1437 
1438 void WXMolecule::OnEditGridBondLength(wxGridEvent &e)
1439 {
1440  if(mIsSelfUpdating) return;
1441  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridBondLength():"<<e.GetRow()<<","<<e.GetCol(),10)
1442  const long r=e.GetRow();
1443  const long c=e.GetCol();
1444  if(c==0)
1445  {
1446  wxString s=mpBondWin->GetCellValue(r,c);
1447  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1448  if(at!=mpMolecule->GetAtomList().rend())
1449  {
1450  if(*at!=&(mpMolecule->GetBondList()[r]->GetAtom2()))
1451  mpMolecule->GetBondList()[r]->SetAtom1(**at);
1452  else
1453  mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom1().GetName().c_str()));
1454  }
1455  else
1456  mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom1().GetName().c_str()));
1457  }
1458  if(c==1)
1459  {
1460  wxString s=mpBondWin->GetCellValue(r,c);
1461  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1462  if(at!=mpMolecule->GetAtomList().rend())
1463  {
1464  if(*at!=&(mpMolecule->GetBondList()[r]->GetAtom1()))
1465  mpMolecule->GetBondList()[r]->SetAtom2(**at);
1466  else
1467  mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom2().GetName().c_str()));
1468  }
1469  else
1470  mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom2().GetName().c_str()));
1471  }
1472  if(c==3)
1473  {
1474  wxString s=mpBondWin->GetCellValue(r,c);
1475  if(s!=_T(""))
1476  {
1477  double d;
1478  if(s.ToDouble(&d))
1479  if(d>0) mpMolecule->GetBondList()[r]->SetLength0(d);
1480  }
1481  }
1482  if(c==4)
1483  {
1484  wxString s=mpBondWin->GetCellValue(r,c);
1485  if(s!=_T(""))
1486  {
1487  double d;
1488  if(s.ToDouble(&d))
1489  if(d>0) mpMolecule->GetBondList()[r]->SetLengthSigma(d);
1490  }
1491  }
1492  if(c==5)
1493  {
1494  wxString s=mpBondWin->GetCellValue(r,c);
1495  if(s!=_T(""))
1496  {
1497  double d;
1498  if(s.ToDouble(&d))
1499  if(d>0) mpMolecule->GetBondList()[r]->SetLengthDelta(d);
1500  }
1501  }
1502  this->CrystUpdate(true);
1503  VFN_DEBUG_EXIT("WXMolecule::OnEditGridBondLength():"<<e.GetRow()<<","<<e.GetCol(),10)
1504 }
1505 
1506 void WXMolecule::OnEditGridBondAngle(wxGridEvent &e)
1507 {
1508  if(mIsSelfUpdating) return;
1509  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridBondAngle():"<<e.GetRow()<<","<<e.GetCol(),10)
1510  const long r=e.GetRow();
1511  const long c=e.GetCol();
1512  if(c==0)
1513  {
1514  wxString s=mpAngleWin->GetCellValue(r,c);
1515  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1516  if(at!=mpMolecule->GetAtomList().rend())
1517  {
1518  if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom2()))
1519  &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom3())))
1520  mpMolecule->GetBondAngleList()[r]->SetAtom1(**at);
1521  else
1522  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom1().GetName().c_str()));
1523  }
1524  else
1525  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom1().GetName().c_str()));
1526  }
1527  if(c==1)
1528  {
1529  wxString s=mpAngleWin->GetCellValue(r,c);
1530  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1531  if(at!=mpMolecule->GetAtomList().rend())
1532  {
1533  if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom1()))
1534  &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom3())))
1535  mpMolecule->GetBondAngleList()[r]->SetAtom2(**at);
1536  else
1537  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str()));
1538  }
1539  else
1540  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str()));
1541  }
1542  if(c==2)
1543  {
1544  wxString s=mpAngleWin->GetCellValue(r,c);
1545  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1546  if(at!=mpMolecule->GetAtomList().rend())
1547  {
1548  if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom1()))
1549  &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom2())))
1550  mpMolecule->GetBondAngleList()[r]->SetAtom3(**at);
1551  else
1552  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom3().GetName().c_str()));
1553  }
1554  else
1555  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str()));
1556  }
1557  if(c==4)
1558  {
1559  wxString s=mpAngleWin->GetCellValue(r,c);
1560  if(s!=_T(""))
1561  {
1562  double d;
1563  if(s.ToDouble(&d))
1564  if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngle0(d*DEG2RAD);
1565  }
1566  }
1567  if(c==5)
1568  {
1569  wxString s=mpAngleWin->GetCellValue(r,c);
1570  if(s!=_T(""))
1571  {
1572  double d;
1573  if(s.ToDouble(&d))
1574  if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngleSigma(d*DEG2RAD);
1575  }
1576  }
1577  if(c==6)
1578  {
1579  wxString s=mpAngleWin->GetCellValue(r,c);
1580  if(s!=_T(""))
1581  {
1582  double d;
1583  if(s.ToDouble(&d))
1584  if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngleDelta(d*DEG2RAD);
1585  }
1586  }
1587  this->CrystUpdate(true);
1588  VFN_DEBUG_EXIT("WXMolecule::OnEditGridBondAngle():"<<e.GetRow()<<","<<e.GetCol(),10)
1589 }
1590 
1591 void WXMolecule::OnEditGridDihedralAngle(wxGridEvent &e)
1592 {
1593  if(mIsSelfUpdating) return;
1594  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridDihedralAngle():"<<e.GetRow()<<","<<e.GetCol(),10)
1595  const long r=e.GetRow();
1596  const long c=e.GetCol();
1597  if(c==0)
1598  {
1599  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1600  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1601  if(at!=mpMolecule->GetAtomList().rend())
1602  {
1603  if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2()))
1604  &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom3())))
1605  mpMolecule->GetDihedralAngleList()[r]->SetAtom1(**at);
1606  else
1607  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom1().GetName().c_str()));
1608  }
1609  else
1610  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom1().GetName().c_str()));
1611  }
1612  if(c==1)
1613  {
1614  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1615  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1616  if(at!=mpMolecule->GetAtomList().rend())
1617  {
1618  if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1()))
1619  &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom3())))
1620  mpMolecule->GetDihedralAngleList()[r]->SetAtom2(**at);
1621  else
1622  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom2().GetName().c_str()));
1623  }
1624  else
1625  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom2().GetName().c_str()));
1626  }
1627  if(c==2)
1628  {
1629  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1630  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1631  if(at!=mpMolecule->GetAtomList().rend())
1632  {
1633  if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1()))
1634  &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2())))
1635  mpMolecule->GetDihedralAngleList()[r]->SetAtom3(**at);
1636  else
1637  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom3().GetName().c_str()));
1638  }
1639  else
1640  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom3().GetName().c_str()));
1641  }
1642  if(c==3)
1643  {
1644  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1645  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1646  if(at!=mpMolecule->GetAtomList().rend())
1647  {
1648  if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1()))
1649  &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2())))
1650  mpMolecule->GetDihedralAngleList()[r]->SetAtom4(**at);
1651  else
1652  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom4().GetName().c_str()));
1653  }
1654  else
1655  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom4().GetName().c_str()));
1656  }
1657  if(c==5)
1658  {
1659  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1660  if(s!=_T(""))
1661  {
1662  double d;
1663  if(s.ToDouble(&d))
1664  mpMolecule->GetDihedralAngleList()[r]->SetAngle0(d*DEG2RAD);
1665  }
1666  }
1667  if(c==6)
1668  {
1669  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1670  if(s!=_T(""))
1671  {
1672  double d;
1673  if(s.ToDouble(&d))
1674  if(d>0) mpMolecule->GetDihedralAngleList()[r]->SetAngleSigma(d*DEG2RAD);
1675  }
1676  }
1677  if(c==7)
1678  {
1679  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1680  if(s!=_T(""))
1681  {
1682  double d;
1683  if(s.ToDouble(&d))
1684  if(d>0) mpMolecule->GetDihedralAngleList()[r]->SetAngleDelta(d*DEG2RAD);
1685  }
1686  }
1687  this->CrystUpdate(true);
1688  VFN_DEBUG_EXIT("WXMolecule::OnEditGridDihedralAngle():"<<e.GetRow()<<","<<e.GetCol(),10)
1689 }
1690 
1691 void WXMolecule::OnEditGridRigidGroup(wxGridEvent &e)
1692 {
1693  if(mIsSelfUpdating) return;
1694  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridRigidGroup():"<<e.GetRow()<<","<<e.GetCol(),10)
1695 
1696  const long r=e.GetRow();
1697  const long c=e.GetCol();
1698  wxString s=mpRigidGroupWin->GetCellValue(r,c);
1699  list<string> l=SplitString(CompressString(string(s.ToAscii())," "),",");
1700  RigidGroup rg;
1701  for(list<string>::const_iterator pos=l.begin();pos!=l.end();++pos)
1702  {
1703  vector<MolAtom*>::reverse_iterator rpos=mpMolecule->FindAtom(*pos);
1704  if(rpos!=mpMolecule->GetAtomList().rend()) rg.insert(*rpos);
1705  else cout<<*pos<<" : NOT FOUND"<<endl;;
1706  }
1707  set<MolAtom *> *pold=(set<MolAtom *>*) mpMolecule->GetRigidGroupList()[r];
1708  set<MolAtom *> *pnew=(set<MolAtom *>*) &rg;
1709 
1710  if( *pold != *pnew)
1711  {
1712  *pold = *pnew;
1713  mpMolecule->GetRigidGroupClock().Click();
1714  }
1715  this->CrystUpdate(true);
1716  VFN_DEBUG_EXIT("WXMolecule::OnEditGridRigidGroup():"<<e.GetRow()<<","<<e.GetCol(),10)
1717 }
1718 
1719 void WXMolecule::OnMenuExport2ZMatrix(wxCommandEvent &event)
1720 {
1721  VFN_DEBUG_MESSAGE("WXMolecule::OnMenuExport2ZMatrix()",6)
1722  const vector<MolZAtom> *pz=&(mpMolecule->AsZMatrix(true));
1723 
1724  if(event.GetId()==ID_MOLECULE_MENU_FILE_2ZMATRIX)
1725  {
1726  wxFileDialog open(this,_T("Choose a file to save the Z-matrix to"),_T(""),_T(""),_T("*.fhz"),
1727  wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1728  if(open.ShowModal() != wxID_OK) return;
1729  ofstream fout (open.GetPath().ToAscii());
1730  if(fout)
1731  {
1732  wxString tmp;
1733 
1734  fout<<mpMolecule->GetName()<<endl<<pz->size()<<endl;
1735  long i=0;
1736  for(vector<MolZAtom>::const_iterator pos=pz->begin();pos!=pz->end();++pos)
1737  {
1738  tmp.Printf(_T("%-2s %2lu"),pos->mpPow->GetSymbol().c_str(),pos->mBondAtom+1);
1739  fout<<tmp;
1740  if(i>0)
1741  {
1742  tmp.Printf(_T("%6.3f"),pos->mBondLength);
1743  fout<<tmp;
1744  if(i>1)
1745  {
1746  tmp.Printf(_T(" %2lu%8.3f"),pos->mBondAngleAtom+1,pos->mBondAngle*RAD2DEG);
1747  fout<<tmp;
1748  if(i>2)
1749  {
1750  tmp.Printf(_T(" %2lu%8.3f"),pos->mDihedralAtom+1,pos->mDihedralAngle*RAD2DEG);
1751  fout<<tmp;
1752  }
1753  }
1754  }
1755  fout<<endl;
1756  i++;
1757  }
1758  }
1759  fout.close();
1760  }
1761  else
1762  {
1763  wxFileDialog open(this,_T("Choose a file to save the (named) Z-matrix to"),_T(""),_T(""),_T("*.zmat"),
1764  wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1765 
1766  if(open.ShowModal() != wxID_OK) return;
1767 
1768  unsigned long nbchar=0;
1769  for(vector<MolAtom*>::const_iterator pos=mpMolecule->GetAtomList().begin();
1770  pos!=mpMolecule->GetAtomList().end();++pos)
1771  if(nbchar<(*pos)->GetName().size()) nbchar=(*pos)->GetName().size();
1772 
1773  ofstream fout (open.GetPath().ToAscii());
1774  if(fout)
1775  {
1776  wxString tmp;
1777 
1778  fout<<mpMolecule->GetName()<<endl<<pz->size()<<endl;
1779  long i=0;
1780  for(vector<MolZAtom>::const_iterator pos=pz->begin();pos!=pz->end();++pos)
1781  {
1782  fout.width(nbchar);
1783  fout<<mpMolecule->GetAtomList()[i]->GetName();
1784  tmp.Printf(_T(" %2s "),pos->mpPow->GetSymbol().c_str());
1785  fout<<tmp;
1786  fout.width(nbchar);
1787  fout<<mpMolecule->GetAtomList()[pos->mBondAtom]->GetName();
1788  if(i>0)
1789  {
1790  tmp.Printf(_T("%6.3f "),pos->mBondLength);
1791  fout<<tmp;
1792  if(i>1)
1793  {
1794  fout.width(nbchar);
1795  fout<<mpMolecule->GetAtomList()[pos->mBondAngleAtom]->GetName();
1796  tmp.Printf(_T(" %8.3f "),pos->mBondAngle*RAD2DEG);
1797  fout<<tmp;
1798  if(i>2)
1799  {
1800  fout.width(nbchar);
1801  fout<<mpMolecule->GetAtomList()[pos->mDihedralAtom]->GetName();
1802  tmp.Printf(_T(" %8.3f"),pos->mDihedralAngle*RAD2DEG);
1803  fout<<tmp;
1804  }
1805  }
1806  }
1807  fout<<endl;
1808  i++;
1809  }
1810  }
1811  fout.close();
1812  }
1813 }
1814 
1815 void WXMolecule::OnMenuTest(wxCommandEvent & WXUNUSED(event))
1816 {
1817  VFN_DEBUG_ENTRY("WXMolecule::OnMenuTest()",6)
1818  #if 1
1819  mpMolecule->BuildRingList();
1820  mpMolecule->BuildStretchModeBondLength();
1821  mpMolecule->BuildStretchModeBondAngle();
1822  mpMolecule->BuildStretchModeTorsion();
1823  mpMolecule->BuildStretchModeTwist();
1824 
1825  //mpMolecule->BuildRotorGroup();
1826  mpMolecule->BuildFlipGroup();
1827  mpMolecule->TuneGlobalOptimRotationAmplitude();
1828  //mpMolecule->FlipAtomGroup(*(mpMolecule->mvFlipGroup.begin()));
1829  //mpMolecule->GlobalOptRandomMove(0.1,gpRefParTypeObjCryst);
1830  mpMolecule->BuildStretchModeGroups();
1831  #else
1832  for(list<StretchModeTorsion>::iterator pos=mpMolecule->GetStretchModeTorsionList().begin();
1833  pos!=mpMolecule->GetStretchModeTorsionList().end();++pos)
1834  {
1835  if((pos->mpAtom1->GetName()=="C12")&&(pos->mpAtom2->GetName()=="N13"))
1836  {
1837  //mpMolecule->DihedralAngleRandomChange(*pos,0.01,true);
1838  cout<<pos->mpDihedralAngle->GetAngle()*RAD2DEG;
1839  mpMolecule->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),pos->mvRotatedAtomList,2*M_PI/10,true);
1840  cout<<" -> "<<pos->mpDihedralAngle->GetAngle()*RAD2DEG
1841  <<", llk="<<pos->mpDihedralAngle->GetLogLikelihood()<<endl;
1842  }
1843  }
1844  mpMolecule->GetCrystal().UpdateDisplay();
1845  #endif
1846  #if 0
1847  mpMolecule->BeginOptimization(true);
1848  for(REAL amplitude=0.1;amplitude<10;amplitude*=1.5)
1849  {
1850  REAL maxLLK=0,llk,ave=0.0;
1851  for(unsigned long i=0;i<1000;i++)
1852  {
1853  mpMolecule->BeginGlobalOptRandomMove();
1854  mpMolecule->GlobalOptRandomMove(amplitude,gpRefParTypeObjCryst);
1855  llk=mpMolecule->GetLogLikelihood();
1856  //cout<<" "<<llk<<endl;
1857  if(llk>maxLLK) maxLLK=llk;
1858  ave+=llk;
1859  mpMolecule->GetCrystal().UpdateDisplay();
1860  }
1861  cout<<"Amplitude="<<amplitude<<", <LLK>= "<<ave/1000<<", Max LLK= "<<maxLLK<<endl;
1862  }
1863  mpMolecule->EndOptimization();
1864  #endif
1865  VFN_DEBUG_EXIT("WXMolecule::OnMenuTest()",6)
1866 }
1867 
1868 class MoleculeMDTestThread: public wxThread
1869 {
1870 public:
1871  MoleculeMDTestThread(Molecule &mol,float seconds):
1872  wxThread(wxTHREAD_DETACHED),mpMolecule(&mol),mSeconds(seconds){};
1873  virtual void *Entry()
1874  {
1875  cout<<endl<<"Entering refinement thread "<<endl<<endl;
1876  const map<MolAtom *,set<MolAtom *> > *pConnect=&(mpMolecule-> GetConnectivityTable());
1877  Chronometer chrono;
1878  float dt0=chrono.seconds();
1879  unsigned long ct=0;
1880  while(chrono.seconds()<30)
1881  {
1882  cout<<"MD Test, cycle #"<<ct++<<endl;
1883  // Use Same procedure as in Molecule::GLobalOptRandomMove
1884  #if 0
1885  // Use one center for the position of an impulsion, applied to all atoms with an exponential decrease
1886  REAL xmin=(*mpMolecule->mvMDFullAtomGroup.begin())->GetX();
1887  REAL xmax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetX();
1888  REAL ymin=(*mpMolecule->mvMDFullAtomGroup.begin())->GetY();
1889  REAL ymax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetY();
1890  REAL zmin=(*mpMolecule->mvMDFullAtomGroup.begin())->GetZ();
1891  REAL zmax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetZ();
1892  for(set<MolAtom*>::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at)
1893  {
1894  if((*at)->GetX()<xmin) xmin=(*at)->GetX();
1895  if((*at)->GetX()>xmax) xmax=(*at)->GetX();
1896  if((*at)->GetY()<ymin) ymin=(*at)->GetY();
1897  if((*at)->GetY()>ymax) ymax=(*at)->GetY();
1898  if((*at)->GetZ()<zmin) zmin=(*at)->GetZ();
1899  if((*at)->GetZ()>zmax) zmax=(*at)->GetZ();
1900  }
1901  // Apply a gaussian impulsion to part of the atom group (FWHM=1/5 of group size)
1902  REAL dx=(xmax-xmin)/5.,dy=(ymax-ymin)/5.,dz=(zmax-zmin)/5.;
1903  if(dx<2) dx=2;
1904  if(dy<2) dy=2;
1905  if(dz<2) dz=2;
1906  const REAL xc=xmin+rand()/(REAL)RAND_MAX*(xmax-xmin);
1907  const REAL yc=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin);
1908  const REAL zc=zmin+rand()/(REAL)RAND_MAX*(zmax-zmin);
1909  map<MolAtom*,XYZ> v0;
1910  const REAL ax=-4.*log(2.)/(dx*dx);
1911  const REAL ay=-4.*log(2.)/(dy*dy);
1912  const REAL az=-4.*log(2.)/(dz*dz);
1913  REAL ux,uy,uz,n=0;
1914  while(n<1)
1915  {
1916  ux=REAL(rand()-RAND_MAX/2);
1917  uy=REAL(rand()-RAND_MAX/2);
1918  uz=REAL(rand()-RAND_MAX/2);
1919  n=sqrt(ux*ux+uy*uy+uz*uz);
1920  }
1921  ux=ux/n;uy=uy/n;uz=uz/n;
1922  if(rand()%2==0)
1923  for(set<MolAtom*>::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at)
1924  v0[*at]=XYZ(ux*exp(ax*((*at)->GetX()-xc)*((*at)->GetX()-xc)),
1925  uy*exp(ay*((*at)->GetY()-yc)*((*at)->GetY()-yc)),
1926  uz*exp(az*((*at)->GetZ()-zc)*((*at)->GetZ()-zc)));
1927  else
1928  for(set<MolAtom*>::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at)
1929  v0[*at]=XYZ(((*at)->GetX()-xc)*ux*exp(ax*((*at)->GetX()-xc)*((*at)->GetX()-xc)),
1930  ((*at)->GetY()-yc)*uy*exp(ay*((*at)->GetY()-yc)*((*at)->GetY()-yc)),
1931  ((*at)->GetZ()-zc)*uz*exp(az*((*at)->GetZ()-zc)*((*at)->GetZ()-zc)));
1932  #else
1933  map<MolAtom*,XYZ> v0;
1934  // Use one atom for the center of the impulsion, 'push' atoms depending on distance & connectivity table
1935  for(set<MolAtom*>::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at)
1936  v0[*at]=XYZ(0,0,0);
1937  map<MolAtom*,unsigned long> pushedAtoms;
1938  unsigned long idx=rand()%v0.size();
1939  set<MolAtom*>::iterator at0=mpMolecule->mvMDFullAtomGroup.begin();
1940  for(unsigned int i=0;i<idx;i++) at0++;
1941  const REAL xc=(*at0)->GetX();
1942  const REAL yc=(*at0)->GetY();
1943  const REAL zc=(*at0)->GetZ();
1944  ExpandAtomGroupRecursive(*at0,*pConnect,pushedAtoms,3);
1945  REAL ux,uy,uz,n=0;
1946  while(n<1)
1947  {
1948  ux=REAL(rand()-RAND_MAX/2);
1949  uy=REAL(rand()-RAND_MAX/2);
1950  uz=REAL(rand()-RAND_MAX/2);
1951  n=sqrt(ux*ux+uy*uy+uz*uz);
1952  }
1953  ux=ux/n;uy=uy/n;uz=uz/n;
1954  const REAL a=-4.*log(2.)/(2*2);//FWHM=2 Angstroems
1955  if(rand()%2==0)
1956  for(map<MolAtom*,unsigned long>::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at)
1957  v0[at->first]=XYZ(ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)),
1958  uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)),
1959  uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc)));
1960  else
1961  for(map<MolAtom*,unsigned long>::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at)
1962  v0[at->first]=XYZ((at->first->GetX()-xc)*ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)),
1963  (at->first->GetY()-yc)*uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)),
1964  (at->first->GetZ()-zc)*uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc)));
1965 
1966  #endif
1967  const REAL nrj0=40*( mpMolecule->GetBondList().size()
1968  +mpMolecule->GetBondAngleList().size()
1969  +mpMolecule->GetDihedralAngleList().size());
1970  map<RigidGroup*,std::pair<XYZ,XYZ> > vr;
1971  mpMolecule->MolecularDynamicsEvolve(v0, 200,0.004,
1972  mpMolecule->GetBondList(),
1973  mpMolecule->GetBondAngleList(),
1974  mpMolecule->GetDihedralAngleList(),
1975  vr,nrj0);
1976 
1977  // Display
1978  wxMilliSleep(1);// Slow down display for simple structures
1979  if((chrono.seconds()-dt0)>0.05) {mpMolecule->GetCrystal().UpdateDisplay();dt0=chrono.seconds();}
1980  }
1981  return NULL;
1982  };
1983  virtual void OnExit()
1984  {
1985  cout <<endl<<"Exiting refinement thread "<<endl<<endl;
1986  };
1987 private:
1989  Molecule *mpMolecule;
1991  float mSeconds;
1992 };
1993 
1994 void WXMolecule::OnMenuMDTest(wxCommandEvent & WXUNUSED(event))
1995 {
1996  VFN_DEBUG_ENTRY("WXMolecule::OnMenuMDTest()",6)
1997  {
1998  wxProgressDialog dlgProgress(_T("Beginning MD Test..."),_T("Building Flip Groups"),
1999  7,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME);//|wxPD_CAN_ABORT
2000  mpMolecule->BuildFlipGroup();
2001  dlgProgress.Update(0,_T("Build Ring List")) ;
2002  mpMolecule->BuildRingList();
2003  dlgProgress.Update(1,_T("Build Stretch Modes: Bond Length")) ;
2004  mpMolecule->BuildStretchModeBondLength();
2005  dlgProgress.Update(2,_T("Build Stretch Modes: Bond Angle")) ;
2006  mpMolecule->BuildStretchModeBondAngle();
2007  dlgProgress.Update(3,_T("Build Stretch Modes: Torsion")) ;
2008  mpMolecule->BuildStretchModeTorsion();
2009  //mpMolecule->BuildStretchModeTwist();
2010  dlgProgress.Update(4,_T("Build Stretch Modes: Optimize Rotation Amplitudes")) ;
2011  mpMolecule->TuneGlobalOptimRotationAmplitude();
2012  dlgProgress.Update(5,_T("Build Stretch Modes Groups")) ;
2013  mpMolecule->BuildStretchModeGroups();
2014  dlgProgress.Update(6,_T("Build MD Atom Groups")) ;
2015  mpMolecule->BuildMDAtomGroups();
2016  }
2017 
2018  MoleculeMDTestThread *pTest = new MoleculeMDTestThread(*mpMolecule,30);
2019  if(pTest->Create() != wxTHREAD_NO_ERROR)
2020  wxLogError(_T("Can't create test optimization thread"));
2021  else pTest->Run();
2022  VFN_DEBUG_EXIT("WXMolecule::OnMenuMDTest()",6)
2023 }
2024 
2025 static const long ID_MOLECULE_ROTATE_BOND_GO =WXCRYST_ID();
2026 static const long ID_MOLECULE_ROTATE_BOND_ATOMS=WXCRYST_ID();
2027 
2028 class WXMoleculeRotation:public wxWindow
2029 {
2030  public:
2031  WXMoleculeRotation(wxWindow *parent, Molecule &mol):
2032  wxWindow(parent,-1),mBondListClock(mol.GetBondListClock()),mpMol(&mol)
2033  {
2034  VFN_DEBUG_ENTRY("WXMoleculeRotation::WXMoleculeRotation()",10)
2035  this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
2036 
2037  wxArrayString choices;
2038  for(vector<MolBond*>::const_iterator pos=mol.GetBondList().begin();pos!=mol.GetBondList().end();++pos)
2039  choices.Add(wxString::FromAscii((*pos)->GetName().c_str()));
2040 
2041  wxBoxSizer* pSizer=new wxBoxSizer(wxHORIZONTAL);
2042 
2043  wxBoxSizer* pSizer1=new wxBoxSizer(wxVERTICAL);
2044  pSizer1->Add(new wxStaticText(this,-1,_T("Select bond:")),0,wxALIGN_CENTER);
2045  mpBond= new wxChoice(this,ID_MOLECULE_ROTATE_BOND_ATOMS,wxDefaultPosition,wxDefaultSize,choices);
2046  mpBond->SetSelection(0);
2047  pSizer1->Add(mpBond,0,wxALIGN_CENTER);
2048  pSizer->Add(pSizer1,0,wxALIGN_CENTER);
2049 
2050  wxBoxSizer* pSizer2=new wxBoxSizer(wxVERTICAL);
2051  pSizer2->Add(new wxStaticText(this,-1,_T("Atoms to rotate:")),0,wxALIGN_CENTER);
2052  mpRotatedAtoms= new wxListBox(this,-1,wxDefaultPosition,wxSize(150,60));
2053  pSizer2->Add(mpRotatedAtoms,0,wxALIGN_CENTER);
2054  pSizer->Add(pSizer2,0,wxALIGN_CENTER);
2055 
2056  wxBoxSizer* pSizer3=new wxBoxSizer(wxVERTICAL);
2057  pSizer3->Add(new wxStaticText(this,-1,_T("Amplitude:")),0,wxALIGN_CENTER);
2058  mpAngle=new wxTextCtrl(this,-1,_T("10"));
2059  pSizer3->Add(mpAngle,0,wxALIGN_CENTER);
2060  pSizer->Add(pSizer3,0,wxALIGN_CENTER);
2061 
2062  wxButton *pButtonRotate=new wxButton(this,ID_MOLECULE_ROTATE_BOND_GO,_T("Rotate !"));
2063  pSizer->Add(pButtonRotate,0,wxALIGN_CENTER);
2064 
2065  this->SetSizer(pSizer);
2066  this->SetAutoLayout(true);
2067  pSizer->SetSizeHints(this);
2068  pSizer->SetSizeHints(parent);
2069  this->Layout();
2070  wxCommandEvent ev(wxEVT_COMMAND_CHOICE_SELECTED,ID_MOLECULE_ROTATE_BOND_ATOMS);
2071  wxPostEvent(this,ev);
2072  VFN_DEBUG_EXIT("WXMoleculeRotation::WXMoleculeRotation()",10)
2073  }
2074 
2075  void OnRotate(wxCommandEvent &event)
2076  {
2077  if(mBondListClock<mpMol->GetBondListClock())
2078  {
2079  cout<<" The bond list has changed !"<<endl;
2080  this->GetParent()->Destroy();
2081  return;
2082  }
2083  VFN_DEBUG_MESSAGE("WXMoleculeRotation::OnRotate()",10)
2084  unsigned int bond=mpBond->GetSelection();
2085  unsigned int choice=mpRotatedAtoms->GetSelection();
2086  double angle;
2087  mpAngle->GetValue().ToDouble(&angle);
2088  mpMol->RotateAtomGroup(mpMol->GetBondList()[bond]->GetAtom1(),
2089  mpMol->GetBondList()[bond]->GetAtom2(),
2090  mvpRotatedAtoms[choice], angle*DEG2RAD, true);
2091  mpMol->GetCrystal().UpdateDisplay();
2092  }
2093  void OnSelectBond(wxCommandEvent &event)
2094  {
2095  if(mBondListClock<mpMol->GetBondListClock())
2096  {
2097  cout<<" The bond list has changed !"<<endl;
2098  this->GetParent()->Destroy();
2099  return;
2100  }
2101  VFN_DEBUG_MESSAGE("WXMoleculeRotation::OnSelectBond()",10)
2102  const unsigned int choice=mpBond->GetSelection();
2103  MolAtom *pAt1=&(mpMol->GetBondList()[choice]->GetAtom1());
2104  MolAtom *pAt2=&(mpMol->GetBondList()[choice]->GetAtom2());
2105  mpMol->BuildConnectivityTable();
2106 
2107  mvpRotatedAtoms.clear();
2108  mvpRotatedAtoms.resize(2);
2109  mvpRotatedAtoms[0].insert(pAt1);
2110  ExpandAtomGroupRecursive(pAt2,mpMol->GetConnectivityTable(),mvpRotatedAtoms[0]);
2111 
2112  mvpRotatedAtoms[1].insert(pAt2);
2113  ExpandAtomGroupRecursive(pAt1,mpMol->GetConnectivityTable(),mvpRotatedAtoms[1]);
2114 
2115  wxArrayString choices;
2116 
2117  set<MolAtom *>::const_iterator pos=mvpRotatedAtoms[0].begin();
2118  wxString choice1(wxString::FromAscii((*pos++)->GetName().c_str()));
2119  for(;pos!=mvpRotatedAtoms[0].end();++pos)
2120  choice1 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str());
2121  choices.Add(choice1);
2122 
2123  pos=mvpRotatedAtoms[1].begin();
2124  wxString choice2(wxString::FromAscii((*pos++)->GetName().c_str()));
2125  for(;pos!=mvpRotatedAtoms[1].end();++pos)
2126  choice2 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str());
2127  choices.Add(choice2);
2128 
2129  mpRotatedAtoms->Set(choices);
2130  mpRotatedAtoms->SetSelection(0);
2131  }
2132  private:
2134  const RefinableObjClock& mBondListClock;
2135  Molecule *mpMol;
2136  wxChoice *mpBond;
2137  wxListBox *mpRotatedAtoms;
2138  vector<set<MolAtom *> > mvpRotatedAtoms;
2139  wxTextCtrl *mpAngle;
2140  DECLARE_EVENT_TABLE()
2141 };
2142 BEGIN_EVENT_TABLE(WXMoleculeRotation,wxWindow)
2143  EVT_BUTTON(ID_MOLECULE_ROTATE_BOND_GO, WXMoleculeRotation::OnRotate)
2144  EVT_CHOICE(ID_MOLECULE_ROTATE_BOND_ATOMS, WXMoleculeRotation::OnSelectBond)
2145 END_EVENT_TABLE()
2146 
2147 static const long ID_MOLECULE_ROTATE_DIHED_GO =WXCRYST_ID();
2148 static const long ID_MOLECULE_ROTATE_DIHED_ATOMS=WXCRYST_ID();
2149 
2150 class WXMoleculeRotationDihed:public wxWindow
2151 {
2152  public:
2153  WXMoleculeRotationDihed(wxWindow *parent, Molecule &mol):
2154  wxWindow(parent,-1),mBondListClock(mol.GetBondListClock()),mpMol(&mol)
2155  {
2156  VFN_DEBUG_ENTRY("WXMoleculeRotationDihed::WXMoleculeRotationDihed()",10)
2157  this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
2158 
2159  wxArrayString choices;
2160  // Use existing angle restraints to generate dihedral angles
2161  for(vector<MolBondAngle*>::const_iterator pos=mol.GetBondAngleList().begin();pos!=mol.GetBondAngleList().end();++pos)
2162  {
2163  MolAtom *pAt1=&((*pos)->GetAtom1());
2164  MolAtom *pAt2=&((*pos)->GetAtom2());
2165  MolAtom *pAt3=&((*pos)->GetAtom3());
2166  const set<MolAtom * > *pConn=&(mpMol->GetConnectivityTable().find(pAt3)->second);
2167  for(set<MolAtom * >::const_iterator neigh=pConn->begin();neigh!=pConn->end();++neigh)
2168  {
2169  if( (*neigh==pAt1) || (*neigh==pAt2) ) continue;
2170  mvDihed.push_back(MolDihedralAngle(*pAt1,*pAt2,*pAt3,**neigh,0,.001,.001,*mpMol));
2171  choices.Add(wxString::FromAscii(mvDihed.back().GetName().c_str()));
2172  }
2173  }
2174 
2175  wxBoxSizer* pSizer=new wxBoxSizer(wxHORIZONTAL);
2176 
2177  wxBoxSizer* pSizer1=new wxBoxSizer(wxVERTICAL);
2178  pSizer1->Add(new wxStaticText(this,-1,_T("Dihedral Angle:")),0,wxALIGN_CENTER);
2179  mpDihed= new wxChoice(this,ID_MOLECULE_ROTATE_DIHED_ATOMS,wxDefaultPosition,wxDefaultSize,choices);
2180  mpDihed->SetSelection(0);
2181  pSizer1->Add(mpDihed,0,wxALIGN_CENTER);
2182  pSizer->Add(pSizer1,0,wxALIGN_CENTER);
2183 
2184  wxBoxSizer* pSizer2=new wxBoxSizer(wxVERTICAL);
2185  pSizer2->Add(new wxStaticText(this,-1,_T("Atoms to rotate:")),0,wxALIGN_CENTER);
2186  mpRotatedAtoms= new wxListBox(this,-1,wxDefaultPosition,wxSize(150,60));
2187  pSizer2->Add(mpRotatedAtoms,0,wxALIGN_CENTER);
2188  pSizer->Add(pSizer2,0,wxALIGN_CENTER);
2189 
2190  wxBoxSizer* pSizer3=new wxBoxSizer(wxVERTICAL);
2191  pSizer3->Add(new wxStaticText(this,-1,_T("Angle:")),0,wxALIGN_CENTER);
2192  mpAngle=new wxTextCtrl(this,-1,_T("10"));
2193  pSizer3->Add(mpAngle,0,wxALIGN_CENTER);
2194  pSizer->Add(pSizer3,0,wxALIGN_CENTER);
2195 
2196  wxButton *pButtonRotate=new wxButton(this,ID_MOLECULE_ROTATE_DIHED_GO,_T("Set angle !"));
2197  pSizer->Add(pButtonRotate,0,wxALIGN_CENTER);
2198 
2199  this->SetSizer(pSizer);
2200  this->SetAutoLayout(true);
2201  pSizer->SetSizeHints(this);
2202  pSizer->SetSizeHints(parent);
2203  this->Layout();
2204  wxCommandEvent ev(wxEVT_COMMAND_CHOICE_SELECTED,ID_MOLECULE_ROTATE_DIHED_ATOMS);
2205  wxPostEvent(this,ev);
2206  VFN_DEBUG_EXIT("WXMoleculeRotationDihed::WXMoleculeRotationDihed()",10)
2207  }
2208 
2209  void OnRotate(wxCommandEvent &event)
2210  {
2211  if(mBondListClock<mpMol->GetBondListClock())
2212  {
2213  cout<<" The bond list has changed !"<<endl;
2214  this->GetParent()->Destroy();
2215  return;
2216  }
2217  VFN_DEBUG_MESSAGE("WXMoleculeRotationDihed::OnRotate()",10)
2218  MolDihedralAngle *pDihed=&mvDihed[mpDihed->GetSelection()];
2219  unsigned int choice=mpRotatedAtoms->GetSelection();
2220  double angle;
2221  mpAngle->GetValue().ToDouble(&angle);
2222  angle*=DEG2RAD;
2223  angle-=pDihed->GetAngle();
2224 
2225  if(mvpRotatedAtoms[choice].find(&(pDihed->GetAtom1()))!=mvpRotatedAtoms[choice].end()) angle*=-1;
2226 
2227  mpMol->RotateAtomGroup(pDihed->GetAtom2(),
2228  pDihed->GetAtom3(),
2229  mvpRotatedAtoms[choice], angle, true);
2230  mpMol->GetCrystal().UpdateDisplay();
2231  }
2232  void OnSelectDihed(wxCommandEvent &event)
2233  {
2234  if(mBondListClock<mpMol->GetBondListClock())
2235  {
2236  cout<<" The bond list has changed !"<<endl;
2237  this->GetParent()->Destroy();
2238  return;
2239  }
2240  VFN_DEBUG_MESSAGE("WXMoleculeRotationDihed::OnSelectBond()",10)
2241  MolDihedralAngle *pDihed=&mvDihed[mpDihed->GetSelection()];
2242  MolAtom *pAt1=&(pDihed->GetAtom1());
2243  MolAtom *pAt2=&(pDihed->GetAtom2());
2244  MolAtom *pAt3=&(pDihed->GetAtom3());
2245  MolAtom *pAt4=&(pDihed->GetAtom4());
2246  mpMol->BuildConnectivityTable();
2247 
2248  mvpRotatedAtoms.clear();
2249  mvpRotatedAtoms.resize(2);
2250 
2251  mvpRotatedAtoms[0].insert(pAt1);
2252  mvpRotatedAtoms[0].insert(pAt2);
2253  ExpandAtomGroupRecursive(pAt3,mpMol->GetConnectivityTable(),mvpRotatedAtoms[0]);
2254  mvpRotatedAtoms[0].erase(pAt1);
2255  mvpRotatedAtoms[0].erase(pAt2);
2256 
2257  mvpRotatedAtoms[1].insert(pAt4);
2258  mvpRotatedAtoms[1].insert(pAt3);
2259  ExpandAtomGroupRecursive(pAt2,mpMol->GetConnectivityTable(),mvpRotatedAtoms[1]);
2260  mvpRotatedAtoms[1].erase(pAt4);
2261  mvpRotatedAtoms[1].erase(pAt3);
2262 
2263  wxArrayString choices;
2264 
2265  set<MolAtom *>::const_iterator pos=mvpRotatedAtoms[0].begin();
2266  wxString choice1(wxString::FromAscii((*pos++)->GetName().c_str()));
2267  for(;pos!=mvpRotatedAtoms[0].end();++pos)
2268  choice1 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str());
2269  choices.Add(choice1);
2270 
2271  pos=mvpRotatedAtoms[1].begin();
2272  wxString choice2(wxString::FromAscii((*pos++)->GetName().c_str()));
2273  for(;pos!=mvpRotatedAtoms[1].end();++pos)
2274  choice2 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str());
2275  choices.Add(choice2);
2276 
2277  mpRotatedAtoms->Set(choices);
2278  mpRotatedAtoms->SetSelection(0);
2279  mpAngle->SetValue(wxString::Format(_T("%6.2f"),pDihed->GetAngle()*RAD2DEG));
2280  }
2281  private:
2283  const RefinableObjClock& mBondListClock;
2284  Molecule *mpMol;
2285  vector<MolDihedralAngle > mvDihed;
2286  wxChoice *mpDihed;
2287  wxListBox *mpRotatedAtoms;
2288  vector<set<MolAtom *> > mvpRotatedAtoms;
2289  wxTextCtrl *mpAngle;
2290  DECLARE_EVENT_TABLE()
2291 };
2292 BEGIN_EVENT_TABLE(WXMoleculeRotationDihed,wxWindow)
2293  EVT_BUTTON(ID_MOLECULE_ROTATE_DIHED_GO, WXMoleculeRotationDihed::OnRotate)
2294  EVT_CHOICE(ID_MOLECULE_ROTATE_DIHED_ATOMS, WXMoleculeRotationDihed::OnSelectDihed)
2295 END_EVENT_TABLE()
2296 
2297 void WXMolecule::OnMenuRotate(wxCommandEvent &event)
2298 {
2299  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRotate()",10)
2300  if(event.GetId()==ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND)
2301  {
2302  #ifdef __WXGTK__
2303  wxFrame *frame= new wxMiniFrame(this,-1,_T("Rotate around bond"),wxDefaultPosition,
2304  wxDefaultSize,wxCLOSE_BOX|wxSTAY_ON_TOP|wxCAPTION);
2305  #else
2306  wxFrame *frame= new wxFrame(this,-1,_T("Rotate around bond"),wxDefaultPosition,
2307  wxDefaultSize);
2308  #endif
2309  WXMoleculeRotation * wxMolRot;
2310  wxMolRot=new WXMoleculeRotation(frame,*mpMolecule);
2311  frame->Show(true);
2312  }
2313  if(event.GetId()==ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED)
2314  {
2315  #ifdef __WXGTK__
2316  wxFrame *frame= new wxMiniFrame(this,-1,_T("Change dihedral angle"),wxDefaultPosition,
2317  wxDefaultSize,wxCLOSE_BOX|wxSTAY_ON_TOP|wxCAPTION);
2318  #else
2319  wxFrame *frame= new wxFrame(this,-1,_T("Change dihedral angle"),wxDefaultPosition,
2320  wxDefaultSize);
2321  #endif
2322  WXMoleculeRotationDihed * wxMolRot;
2323  wxMolRot=new WXMoleculeRotationDihed(frame,*mpMolecule);
2324  frame->Show(true);
2325  }
2326  VFN_DEBUG_EXIT("WXMolecule::OnMenuRotate()",10)
2327 }
2328 
2329 
2330 void WXMolecule::OnMenuSetLimits(wxCommandEvent &event)
2331 {
2332 }
2333 
2334 void WXMolecule::CrystUpdate(const bool uui,const bool lock)
2335 {
2336  VFN_DEBUG_ENTRY("WXMolecule::CrystUpdate()",6)
2337  if(lock) mMutex.Lock();
2338  if(false==mpMolecule->IsBeingRefined())
2339  {
2340  //Remove any atom, bond, bond angle or dihedral angle that could have been removed
2341  {
2342  unsigned long i=0;
2343  for(list<CellAtom>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();)
2344  {
2345  if(i>=mpMolecule->GetAtomList().size())
2346  {
2347  pos=mvpAtom.erase(pos);
2348  mpAtomWin->DeleteRows(i);
2349  }
2350  else
2351  {
2352  if(pos->mpAtom!=mpMolecule->GetAtomList()[i])
2353  {
2354  pos=mvpAtom.erase(pos);
2355  mpAtomWin->DeleteRows(i);
2356  }
2357  else
2358  {
2359  ++pos;
2360  ++i;
2361  }
2362  }
2363  }
2364  }
2365  if(0!=mpBondWin)
2366  {
2367  unsigned long i=0;
2368  for(list<CellBond>::iterator pos=mvpBond.begin();pos!=mvpBond.end();)
2369  {
2370  if(i>=mpMolecule->GetBondList().size())
2371  {
2372  pos=mvpBond.erase(pos);
2373  mpBondWin->DeleteRows(i);
2374  }
2375  else
2376  {
2377  if(pos->mpBond!=mpMolecule->GetBondList()[i])
2378  {
2379  pos=mvpBond.erase(pos);
2380  mpBondWin->DeleteRows(i);
2381  }
2382  else
2383  {
2384  ++pos;
2385  ++i;
2386  }
2387  }
2388  }
2389  }
2390  if(0!=mpAngleWin)
2391  {
2392  unsigned long i=0;
2393  for(list<CellBondAngle>::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();)
2394  {
2395  if(i>=mpMolecule->GetBondAngleList().size())
2396  {
2397  pos=mvpBondAngle.erase(pos);
2398  mpAngleWin->DeleteRows(i);
2399  }
2400  else
2401  {
2402  if(pos->mpBondAngle!=mpMolecule->GetBondAngleList()[i])
2403  {
2404  pos=mvpBondAngle.erase(pos);
2405  mpAngleWin->DeleteRows(i);
2406  }
2407  else
2408  {
2409  ++pos;
2410  ++i;
2411  }
2412  }
2413  }
2414  }
2415  if(0!=mpDihedralAngleWin)
2416  {
2417  unsigned long i=0;
2418  for(list<CellDihedralAngle>::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();)
2419  {
2420  if(i>=mpMolecule->GetDihedralAngleList().size())
2421  {
2422  pos=mvpDihedralAngle.erase(pos);
2423  mpDihedralAngleWin->DeleteRows(i);
2424  }
2425  else
2426  {
2427  if(pos->mpDihedralAngle!=mpMolecule->GetDihedralAngleList()[i])
2428  {
2429  pos=mvpDihedralAngle.erase(pos);
2430  mpDihedralAngleWin->DeleteRows(i);
2431  }
2432  else
2433  {
2434  ++pos;
2435  ++i;
2436  }
2437  }
2438  }
2439  }
2440  if(0!=mpRigidGroupWin)
2441  {
2442  unsigned long i=0;
2443  for(list<CellRigidGroup>::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();)
2444  {
2445  if(i>=mpMolecule->GetRigidGroupList().size())
2446  {
2447  pos=mvpRigidGroup.erase(pos);
2448  mpRigidGroupWin->DeleteRows(i);
2449  }
2450  else
2451  {
2452  if(pos->mpGroup!=mpMolecule->GetRigidGroupList()[i])
2453  {
2454  pos=mvpRigidGroup.erase(pos);
2455  mpRigidGroupWin->DeleteRows(i);
2456  }
2457  else
2458  {
2459  ++pos;
2460  ++i;
2461  }
2462  }
2463  }
2464  }
2465  if(0!=mpNonFlipAtomWin)
2466  {
2467  if(mpNonFlipAtomWin->GetNumberRows()>0)
2468  mpNonFlipAtomWin->DeleteRows(0, mpNonFlipAtomWin->GetRows(), true);
2469  }
2470  //Add any atom, bond, bond angle or dihedral angle that could have been added
2471  {
2472  bool needLayout=false;
2473  for(unsigned long i=mvpAtom.size();i<mpMolecule->GetAtomList().size();++i)
2474  {
2475  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Atom not found",5)
2476  mpAtomWin->AppendRows();
2477  mvpAtom.push_back(CellAtom());
2478  mvpAtom.back().mpAtom=mpMolecule->GetAtomList()[i];
2479  needLayout=true;
2480  }
2481  if(needLayout)
2482  {
2483  //mpAtomWin->Layout();
2484  //mpAtomWin->SetScrollRate(20,20);
2485  mpAtomWin->FitInside();
2486  //mpAtomWin->EnableScrolling(true,true);
2487  }
2488  }
2489  if(0!=mpBondWin)
2490  {
2491  for(unsigned long i=mvpBond.size();i<mpMolecule->GetBondList().size();++i)
2492  {
2493  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Bond not found",5)
2494  mpBondWin->AppendRows();
2495  mvpBond.push_back(CellBond());
2496  mvpBond.back().mpBond=mpMolecule->GetBondList()[i];
2497  }
2498  }
2499  if(0!=mpAngleWin)
2500  {
2501  for(unsigned long i=mvpBondAngle.size();i<mpMolecule->GetBondAngleList().size();++i)
2502  {
2503  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Bond Angle not found",5)
2504  mpAngleWin->AppendRows();
2505  mvpBondAngle.push_back(CellBondAngle());
2506  mvpBondAngle.back().mpBondAngle=mpMolecule->GetBondAngleList()[i];
2507  }
2508  }
2509  if(0!=mpDihedralAngleWin)
2510  {
2511  for(unsigned long i=mvpDihedralAngle.size();i<mpMolecule->GetDihedralAngleList().size();++i)
2512  {
2513  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Dihedral Angle not found",5)
2514  mpDihedralAngleWin->AppendRows();
2515  mvpDihedralAngle.push_back(CellDihedralAngle());
2516  mvpDihedralAngle.back().mpDihedralAngle=mpMolecule->GetDihedralAngleList()[i];
2517  }
2518  }
2519  if(0!=mpRigidGroupWin)
2520  {
2521  for(unsigned long i=mvpRigidGroup.size();i<mpMolecule->GetRigidGroupList().size();++i)
2522  {
2523  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Rigid Group not found",5)
2524  mpRigidGroupWin->AppendRows();
2525  mvpRigidGroup.push_back(CellRigidGroup());
2526  mvpRigidGroup.back().mpGroup=mpMolecule->GetRigidGroupList()[i];
2527  }
2528  // Update list of atoms, if necessary
2529  for(list<CellRigidGroup>::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();++pos)
2530  {
2531  if(*(pos->mpGroup) != pos->mGroupCopy)
2532  {
2533  pos->mGroupCopy=*(pos->mpGroup);
2534  pos->mNeedUpdateUI=true;
2535  }
2536  }
2537  }
2538  if(0!=mpNonFlipAtomWin)
2539  {
2540  vector<MolAtom*> v = mpMolecule->getNonFlipAtomList();
2541  for(unsigned long i=0;i<v.size();i++)
2542  {
2543  mpNonFlipAtomWin->AppendRows(1, true);
2544  mpNonFlipAtomWin->SetCellValue(i, 0, v[i]->GetName());
2545  }
2546  }
2547  }
2548  // Update values
2549  {
2550  for(list<CellAtom>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
2551  {
2552  const string name=pos->mpAtom->GetName();
2553  const ScatteringPower* pow=&(pos->mpAtom->GetScatteringPower());
2554  const REAL x=pos->mpAtom->X();
2555  const REAL y=pos->mpAtom->Y();
2556  const REAL z=pos->mpAtom->Z();
2557  const REAL occ=pos->mpAtom->GetOccupancy();
2558  if( (name !=pos->mName)
2559  ||(pow !=pos->mpScatteringPower)
2560  ||(x !=pos->mX)
2561  ||(y !=pos->mY)
2562  ||(z !=pos->mZ)
2563  ||(occ !=pos->mOcc))
2564  {
2565  pos->mName =name;
2566  pos->mpScatteringPower =pow;
2567  pos->mX =x;
2568  pos->mY =y;
2569  pos->mZ =z;
2570  pos->mOcc =occ;
2571  pos->mNeedUpdateUI=true;
2572  }
2573  }
2574  }
2575  if(0!=mpBondWin)
2576  {
2577  for(list<CellBond>::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
2578  {
2579  const string atom1=pos->mpBond->GetAtom1().GetName();
2580  const string atom2=pos->mpBond->GetAtom2().GetName();
2581  const REAL length =pos->mpBond->GetLength();
2582  const REAL length0 =pos->mpBond->GetLength0();
2583  const REAL sigma =pos->mpBond->GetLengthSigma();
2584  const REAL delta =pos->mpBond->GetLengthDelta();
2585  if( (atom1 !=pos->mAtom1)
2586  ||(atom2 !=pos->mAtom2)
2587  ||(length !=pos->mLength)
2588  ||(length0!=pos->mLength0)
2589  ||(sigma !=pos->mSigma)
2590  ||(delta !=pos->mDelta))
2591  {
2592  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():"<<atom1<<"-"<<atom2<<":"<<length,4)
2593  pos->mAtom1 =atom1;
2594  pos->mAtom2 =atom2;
2595  pos->mLength =length;
2596  pos->mLength0=length0;
2597  pos->mSigma =sigma;
2598  pos->mDelta =delta;
2599  pos->mNeedUpdateUI=true;
2600  }
2601  }
2602  }
2603  if(0!=mpAngleWin)
2604  {
2605  for(list<CellBondAngle>::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
2606  {
2607  const string atom1=pos->mpBondAngle->GetAtom1().GetName();
2608  const string atom2=pos->mpBondAngle->GetAtom2().GetName();
2609  const string atom3=pos->mpBondAngle->GetAtom3().GetName();
2610  const REAL angle =pos->mpBondAngle->GetAngle();
2611  const REAL angle0 =pos->mpBondAngle->GetAngle0();
2612  const REAL sigma =pos->mpBondAngle->GetAngleSigma();
2613  const REAL delta =pos->mpBondAngle->GetAngleDelta();
2614  if( (atom1 !=pos->mAtom1)
2615  ||(atom2 !=pos->mAtom2)
2616  ||(atom3 !=pos->mAtom3)
2617  ||(angle !=pos->mAngle)
2618  ||(angle0!=pos->mAngle0)
2619  ||(sigma !=pos->mSigma)
2620  ||(delta !=pos->mDelta))
2621  {
2622  pos->mAtom1 =atom1;
2623  pos->mAtom2 =atom2;
2624  pos->mAtom3 =atom3;
2625  pos->mAngle =angle;
2626  pos->mAngle0=angle0;
2627  pos->mSigma =sigma;
2628  pos->mDelta =delta;
2629  pos->mNeedUpdateUI=true;
2630  }
2631  }
2632  }
2633  if(0!=mpDihedralAngleWin)
2634  {
2635  for(list<CellDihedralAngle>::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
2636  {
2637  const string atom1=pos->mpDihedralAngle->GetAtom1().GetName();
2638  const string atom2=pos->mpDihedralAngle->GetAtom2().GetName();
2639  const string atom3=pos->mpDihedralAngle->GetAtom3().GetName();
2640  const string atom4=pos->mpDihedralAngle->GetAtom4().GetName();
2641  const REAL angle =pos->mpDihedralAngle->GetAngle();
2642  const REAL angle0 =pos->mpDihedralAngle->GetAngle0();
2643  const REAL sigma =pos->mpDihedralAngle->GetAngleSigma();
2644  const REAL delta =pos->mpDihedralAngle->GetAngleDelta();
2645  if( (atom1 !=pos->mAtom1)
2646  ||(atom2 !=pos->mAtom2)
2647  ||(atom3 !=pos->mAtom3)
2648  ||(atom4 !=pos->mAtom4)
2649  ||(angle !=pos->mAngle)
2650  ||(angle0!=pos->mAngle0)
2651  ||(sigma !=pos->mSigma)
2652  ||(delta !=pos->mDelta))
2653  {
2654  pos->mAtom1 =atom1;
2655  pos->mAtom2 =atom2;
2656  pos->mAtom3 =atom3;
2657  pos->mAtom4 =atom4;
2658  pos->mAngle =angle;
2659  pos->mAngle0=angle0;
2660  pos->mSigma =sigma;
2661  pos->mDelta =delta;
2662  pos->mNeedUpdateUI=true;
2663  }
2664  }
2665  }
2666  if(0!=mpNonFlipAtomWin)
2667  {
2668 
2669  }
2670  this->WXRefinableObj::CrystUpdate(uui,false);
2671  if(lock) mMutex.Unlock();
2672  VFN_DEBUG_EXIT("WXMolecule::CrystUpdate()",6)
2673 }
2674 
2675 void WXMolecule::OnMenuShowRestraintWindow(wxCommandEvent &event)
2676 {
2677  if(0!=mpBondWin) return;
2678 
2679  // Frame with notebook
2680  wxFrame *frame= new wxFrame(this,-1,_T("Restraints for: ")+wxString::FromAscii(mpMolecule->GetName().c_str()),
2681  wxDefaultPosition,wxSize(800,300));
2682 
2683  wxNotebook *notebook = new wxNotebook(frame, -1);
2684  // Bond lengths
2685  {
2686  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2687  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2688  cellAttrName->SetEditor(new wxGridCellTextEditor);
2689  wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
2690  cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2691  cellAttrFloat->SetEditor(new wxGridCellFloatEditor);
2692  wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr;
2693  cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2694  cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor);
2695  cellAttrFloatReadOnly->SetReadOnly();
2696 
2697  mpBondWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_BONDLENGTH);
2698  notebook->AddPage(mpBondWin, _T("Bond Lengths"), true);
2699  mpBondWin->CreateGrid(0,6);
2700  mpBondWin->SetColSize(0,80);
2701  mpBondWin->SetColAttr(0,cellAttrName);
2702  mpBondWin->SetColAttr(1,cellAttrName->Clone());
2703  mpBondWin->SetColAttr(2,cellAttrFloatReadOnly);
2704  mpBondWin->SetColAttr(3,cellAttrFloat);
2705  mpBondWin->SetColAttr(4,cellAttrFloat->Clone());
2706  mpBondWin->SetColAttr(5,cellAttrFloat->Clone());
2707  mpBondWin->SetColLabelValue(0,_T("Atom1"));
2708  mpBondWin->SetColLabelValue(1,_T("Atom2"));
2709  mpBondWin->SetColLabelValue(2,_T("Length"));
2710  mpBondWin->SetColLabelValue(3,_T("Restraint"));
2711  mpBondWin->SetColLabelValue(4,_T("Sigma"));
2712  mpBondWin->SetColLabelValue(5,_T("Delta"));
2713  mpBondWin->AutoSizeRows();
2714  }
2715  // Bond angles
2716  {
2717  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2718  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2719  cellAttrName->SetEditor(new wxGridCellTextEditor);
2720  wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
2721  cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2722  cellAttrFloat->SetEditor(new wxGridCellFloatEditor);
2723  wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr;
2724  cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2725  cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor);
2726  cellAttrFloatReadOnly->SetReadOnly();
2727 
2728  mpAngleWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_BONDANGLE);
2729  notebook->AddPage(mpAngleWin, _T("Bond Angles"), true);
2730  mpAngleWin->CreateGrid(0,7);
2731  mpAngleWin->SetColSize(0,80);
2732  mpAngleWin->SetColAttr(0,cellAttrName);
2733  mpAngleWin->SetColAttr(1,cellAttrName->Clone());
2734  mpAngleWin->SetColAttr(2,cellAttrName->Clone());
2735  mpAngleWin->SetColAttr(3,cellAttrFloatReadOnly);
2736  mpAngleWin->SetColAttr(4,cellAttrFloat);
2737  mpAngleWin->SetColAttr(5,cellAttrFloat->Clone());
2738  mpAngleWin->SetColAttr(6,cellAttrFloat->Clone());
2739  mpAngleWin->SetColLabelValue(0,_T("Atom1"));
2740  mpAngleWin->SetColLabelValue(1,_T("Atom2"));
2741  mpAngleWin->SetColLabelValue(2,_T("Atom3"));
2742  mpAngleWin->SetColLabelValue(3,_T("Angle"));
2743  mpAngleWin->SetColLabelValue(4,_T("Restraint"));
2744  mpAngleWin->SetColLabelValue(5,_T("Sigma"));
2745  mpAngleWin->SetColLabelValue(6,_T("Delta"));
2746  mpAngleWin->AutoSizeRows();
2747  }
2748  // Dihedral angles
2749  {
2750  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2751  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2752  cellAttrName->SetEditor(new wxGridCellTextEditor);
2753  wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
2754  cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2755  cellAttrFloat->SetEditor(new wxGridCellFloatEditor);
2756  wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr;
2757  cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2758  cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor);
2759  cellAttrFloatReadOnly->SetReadOnly();
2760 
2761  mpDihedralAngleWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_DIHEDRALANGLE);
2762  notebook->AddPage(mpDihedralAngleWin, _T("Dihedral Angles"), true);
2763  mpDihedralAngleWin->CreateGrid(0,8);
2764  mpDihedralAngleWin->SetColSize(0,80);
2765  mpDihedralAngleWin->SetColAttr(0,cellAttrName);
2766  mpDihedralAngleWin->SetColAttr(1,cellAttrName->Clone());
2767  mpDihedralAngleWin->SetColAttr(2,cellAttrName->Clone());
2768  mpDihedralAngleWin->SetColAttr(3,cellAttrName->Clone());
2769  mpDihedralAngleWin->SetColAttr(4,cellAttrFloatReadOnly);
2770  mpDihedralAngleWin->SetColAttr(5,cellAttrFloat);
2771  mpDihedralAngleWin->SetColAttr(6,cellAttrFloat->Clone());
2772  mpDihedralAngleWin->SetColAttr(7,cellAttrFloat->Clone());
2773  mpDihedralAngleWin->SetColLabelValue(0,_T("Atom1"));
2774  mpDihedralAngleWin->SetColLabelValue(1,_T("Atom2"));
2775  mpDihedralAngleWin->SetColLabelValue(2,_T("Atom3"));
2776  mpDihedralAngleWin->SetColLabelValue(3,_T("Atom4"));
2777  mpDihedralAngleWin->SetColLabelValue(4,_T("Angle"));
2778  mpDihedralAngleWin->SetColLabelValue(5,_T("Restraint"));
2779  mpDihedralAngleWin->SetColLabelValue(6,_T("Sigma"));
2780  mpDihedralAngleWin->SetColLabelValue(7,_T("Delta"));
2781  mpDihedralAngleWin->AutoSizeRows();
2782  }
2783  // Rigid groups
2784  {
2785  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2786  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2787  cellAttrName->SetEditor(new wxGridCellTextEditor);
2788 
2789  mpRigidGroupWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_RIGIDGROUP);
2790  notebook->AddPage(mpRigidGroupWin, _T("Rigid Groups"), true);
2791  mpRigidGroupWin->CreateGrid(0,1);
2792  mpRigidGroupWin->SetColMinimalWidth(0,600);
2793  mpRigidGroupWin->SetColSize(0,600);
2794  mpRigidGroupWin->SetColAttr(0,cellAttrName);
2795  mpRigidGroupWin->SetColLabelValue(0,_T("Atoms in Rigid Group"));
2796  //mpRigidGroupWin->ForceRefresh();
2797  //mpRigidGroupWin->AutoSizeRows();
2798  }
2799 
2800  //non-flip atoms
2801  {
2802  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2803  cellAttrName->SetReadOnly();
2804  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2805  cellAttrName->SetEditor(new wxGridCellTextEditor);
2806 
2807  mpNonFlipAtomWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_NONFLIPATOM);
2808  notebook->AddPage(mpNonFlipAtomWin, _T("Optically active atoms"), true);
2809  mpNonFlipAtomWin->CreateGrid(0,1);
2810  mpNonFlipAtomWin->SetColMinimalWidth(0,600);
2811  mpNonFlipAtomWin->SetColSize(0,600);
2812  mpNonFlipAtomWin->SetColAttr(0,cellAttrName);
2813  mpNonFlipAtomWin->SetColLabelValue(0,_T("Optically active atom"));
2814  }
2815  notebook->SetSelection(0);
2816  this->CrystUpdate(true);
2817  frame->Show(true);
2818  frame->Layout();
2819 }
2820 
2821 void WXMolecule::OnMenuRigidfyWithDihedralAngles(wxCommandEvent & WXUNUSED(event))
2822 {
2823  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRigidfyWithDihedralAngles()",6)
2824  wxString msg;
2825  msg.Printf( _T("This will add all possible dihedral angles,\n")
2826  _T("in practice making the Molecule rigid\n\n")
2827  _T("Are you sure you want to proceed ?")
2828  );
2829 
2830  wxMessageDialog w(this,msg,_T("Warning !"),wxYES_NO|wxNO_DEFAULT|wxICON_EXCLAMATION);
2831  int result=w.ShowModal();
2832  if(wxID_YES==result) mpMolecule->RigidifyWithDihedralAngles();
2833 
2834  VFN_DEBUG_EXIT("WXMolecule::OnMenuRigidfyWithDihedralAngles()",6)
2835 }
2836 
2837 void WXMolecule::OnMenuSetDeltaSigma(wxCommandEvent &event)
2838 {
2839  VFN_DEBUG_ENTRY("WXMolecule::OnMenuSetDeltaSigma()",6)
2841  double sigma=0.01,delta=0.02;
2842  {
2843  wxString s;
2844  s.Printf(_T("%f"),delta);
2845  wxString title=_T("Choose 'delta' value");
2846  wxString info;
2847  info.Printf(_T("The 'delta' value is the allowed range \n")
2848  _T("(without penalty) around the expected value.\n\n")
2849  _T("It is by default equal to 0.02, in Angstroems for bond lengths,\n")
2850  _T("and in radians for angles (0.02rad = 1.15deg)\n\n")
2851  _T("DO NOT TRY TO CHANGE THE DEFAULT VALUE\n")
2852  _T("UNLESS YOU REALLY KNOW WHAT YOU ARE DOING\n")
2853  _T("Fox has been optimized with the default values...")
2854  );
2855  wxTextEntryDialog dialog(this,info,title,s,wxOK|wxCANCEL);
2856  if(wxID_OK!=dialog.ShowModal())
2857  {
2858  VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma():Canceled",6)
2859  return;
2860  }
2861  dialog.GetValue().ToDouble(&delta);
2862  }
2863  {
2864  wxString s;
2865  s.Printf(_T("%f"),sigma);
2866  wxString title=_T("Choose 'sigma' value");
2867  wxString info;
2868  info.Printf(_T("The 'sigma' value is used to compute \n")
2869  _T("penalty)around the expected value\n\n")
2870  _T("It is by default equal to 0.01, in Angstroems for bond angles,\n")
2871  _T("and in radians for angles (0.01rad = 0.57deg)\n\n")
2872  _T("DO NOT TRY TO CHANGE THE DEFAULT VALUE\n")
2873  _T("UNLESS YOU REALLY KNOW WHAT YOU ARE DOING\n")
2874  _T("Fox has been optimized with the default values...")
2875  );
2876  wxTextEntryDialog dialog(this,info,title.c_str(),s,wxOK|wxCANCEL);
2877  if(wxID_OK!=dialog.ShowModal())
2878  {
2879  VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma():Canceled",6)
2880  return;
2881  }
2882  dialog.GetValue().ToDouble(&sigma);
2883  }
2884  for(vector<MolBond*>::iterator pos=mpMolecule->GetBondList().begin();
2885  pos != mpMolecule->GetBondList().end();++pos)
2886  {
2887  (*pos)->SetLengthDelta(delta);
2888  (*pos)->SetLengthSigma(sigma);
2889  }
2890  for(vector<MolBondAngle*>::iterator pos=mpMolecule->GetBondAngleList().begin();
2891  pos != mpMolecule->GetBondAngleList().end();++pos)
2892  {
2893  (*pos)->SetAngleDelta(delta*DEG2RAD);
2894  (*pos)->SetAngleSigma(sigma*DEG2RAD);
2895  }
2896  for(vector<MolDihedralAngle*>::iterator pos=mpMolecule->GetDihedralAngleList().begin();
2897  pos != mpMolecule->GetDihedralAngleList().end();++pos)
2898  {
2899  //(*pos)->AngleDelta()=delta;
2900  //(*pos)->AngleSigma()=sigma;
2901  }
2902  mpMolecule->GetBondListClock().Click();
2903  this->CrystUpdate(true);
2904  VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma()",6)
2905 }
2906 
2907 void WXMolecule::OnChangeCenterAtom(wxCommandEvent &event)
2908 {
2910  int choice;
2911  MolAtom *const at=WXDialogChooseFromVector(mpMolecule->GetAtomList(),
2912  (wxWindow*)this,"Choose a new Atom",choice);
2913  if(0==at) return;
2914  mpMolecule->SetCenterAtom(*at);
2915 }
2916 
2918 {
2919  VFN_DEBUG_ENTRY("WXMolecule::NotifyDeleteListWin()",6)
2920  if(win==mpBondWin)
2921  {
2922  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Bond List window",5)
2923  mpBondWin=0;
2924  mvpBond.clear();
2925  }
2926  if(win==mpAngleWin)
2927  {
2928  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Angle List window",5)
2929  mpAngleWin=0;
2930  mvpBondAngle.clear();
2931  }
2932  if(win==mpDihedralAngleWin)
2933  {
2934  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Dihedral Angle List window",5)
2935  mpDihedralAngleWin=0;
2936  mvpDihedralAngle.clear();
2937  }
2938  if(win==mpRigidGroupWin)
2939  {
2940  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Dihedral Angle List window",5)
2941  mpRigidGroupWin=0;
2942  mvpRigidGroup.clear();
2943  }
2944  VFN_DEBUG_EXIT("WXMolecule::NotifyDeleteListWin()",6)
2945 }
2946 void WXMolecule::UpdateUI(const bool lock)
2947 {
2948  if(lock) mMutex.Lock();
2949  VFN_DEBUG_ENTRY("WXMolecule::UpdateUI()",5)
2950  {
2951  unsigned long i=0;
2952  for(list<CellAtom>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
2953  {
2954  if(pos->mNeedUpdateUI==true)
2955  {
2956  mIsSelfUpdating=true;
2957  mpAtomWin->SetCellValue(i, 0, wxString::FromAscii(pos->mName.c_str()));
2958  mpAtomWin->SetCellValue(i, 1, wxString::FromAscii(pos->mpScatteringPower->GetName().c_str()));
2959  wxString tmp;
2960  tmp.Printf(_T("%.3f"),pos->mX);
2961  mpAtomWin->SetCellValue(i, 2, tmp);
2962  tmp.Printf(_T("%.3f"),pos->mY);
2963  mpAtomWin->SetCellValue(i, 3, tmp);
2964  tmp.Printf(_T("%.3f"),pos->mZ);
2965  mpAtomWin->SetCellValue(i, 4, tmp);
2966  tmp.Printf(_T("%.3f"),pos->mOcc);
2967  mpAtomWin->SetCellValue(i, 5, tmp);
2968  mIsSelfUpdating=false;
2969  }
2970  ++i;
2971  }
2972  }
2973  if(0!=mpBondWin)
2974  {
2975  unsigned long i=0;
2976  for(list<CellBond>::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
2977  {
2978  if(pos->mNeedUpdateUI==true)
2979  {
2980  mIsSelfUpdating=true;
2981  mpBondWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str()));
2982  mpBondWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str()));
2983  wxString tmp;
2984  tmp.Printf(_T("%f"),pos->mLength);
2985  mpBondWin->SetCellValue(i, 2, tmp);
2986  tmp.Printf(_T("%f"),pos->mLength0);
2987  mpBondWin->SetCellValue(i, 3, tmp);
2988  tmp.Printf(_T("%f"),pos->mSigma);
2989  mpBondWin->SetCellValue(i, 4, tmp);
2990  tmp.Printf(_T("%f"),pos->mDelta);
2991  mpBondWin->SetCellValue(i, 5, tmp);
2992  mIsSelfUpdating=false;
2993  }
2994  ++i;
2995  }
2996  }
2997  if(0!=mpAngleWin)
2998  {
2999  unsigned long i=0;
3000  for(list<CellBondAngle>::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
3001  {
3002  if(pos->mNeedUpdateUI==true)
3003  {
3004  mIsSelfUpdating=true;
3005  mpAngleWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str()));
3006  mpAngleWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str()));
3007  mpAngleWin->SetCellValue(i, 2, wxString::FromAscii(pos->mAtom3.c_str()));
3008  wxString tmp;
3009  tmp.Printf(_T("%f"),pos->mAngle*RAD2DEG);
3010  mpAngleWin->SetCellValue(i, 3, tmp);
3011  tmp.Printf(_T("%f"),pos->mAngle0*RAD2DEG);
3012  mpAngleWin->SetCellValue(i, 4, tmp);
3013  tmp.Printf(_T("%f"),pos->mSigma*RAD2DEG);
3014  mpAngleWin->SetCellValue(i, 5, tmp);
3015  tmp.Printf(_T("%f"),pos->mDelta*RAD2DEG);
3016  mpAngleWin->SetCellValue(i, 6, tmp);
3017  mIsSelfUpdating=false;
3018  }
3019  ++i;
3020  }
3021  }
3022  if(0!=mpDihedralAngleWin)
3023  {
3024  unsigned long i=0;
3025  for(list<CellDihedralAngle>::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
3026  {
3027  if(pos->mNeedUpdateUI==true)
3028  {
3029  mIsSelfUpdating=true;
3030  mpDihedralAngleWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str()));
3031  mpDihedralAngleWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str()));
3032  mpDihedralAngleWin->SetCellValue(i, 2, wxString::FromAscii(pos->mAtom3.c_str()));
3033  mpDihedralAngleWin->SetCellValue(i, 3, wxString::FromAscii(pos->mAtom4.c_str()));
3034  wxString tmp;
3035  tmp.Printf(_T("%f"),pos->mAngle*RAD2DEG);
3036  mpDihedralAngleWin->SetCellValue(i, 4, tmp);
3037  tmp.Printf(_T("%f"),pos->mAngle0*RAD2DEG);
3038  mpDihedralAngleWin->SetCellValue(i, 5, tmp);
3039  tmp.Printf(_T("%f"),pos->mSigma*RAD2DEG);
3040  mpDihedralAngleWin->SetCellValue(i, 6, tmp);
3041  tmp.Printf(_T("%f"),pos->mDelta*RAD2DEG);
3042  mpDihedralAngleWin->SetCellValue(i, 7, tmp);
3043  mIsSelfUpdating=false;
3044  }
3045  ++i;
3046  }
3047  }
3048  if(0!=mpRigidGroupWin)
3049  {
3050  unsigned long i=0;
3051  for(list<CellRigidGroup>::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();++pos)
3052  {
3053  if(pos->mNeedUpdateUI==true)
3054  {
3055  mIsSelfUpdating=true;
3056  mpRigidGroupWin->SetCellValue(i, 0, wxString::FromAscii(pos->mpGroup->GetName().c_str()));
3057  mIsSelfUpdating=false;
3058  }
3059  ++i;
3060  }
3061  }
3062  if(0!=mpNonFlipAtomWin)
3063  {
3064  //for(unsigned long i=0;i<
3065  // mpNonFlipAtomWin->SetCellValue(v[i]->GetName(), i, 1);
3066  }
3067  if(mpMolecule->GetCenterAtom()!=0)
3068  mpFieldCenterAtom->SetValue(mpMolecule->GetCenterAtom()->GetName());
3069  else mpFieldCenterAtom->SetValue("No atom !");
3070 
3071  //if(mpMolecule->GetOption(3).GetChoice()==0) mpFieldCenterAtom->Enable(false);
3072  //else mpFieldCenterAtom->Enable(true);
3073 
3074  if(lock) mMutex.Unlock();
3075  this->WXRefinableObj::UpdateUI(lock);
3076  VFN_DEBUG_EXIT("WXMolecule::UpdateUI()",5)
3077 }
3078 
3079 bool WXMolecule::Enable(bool e)
3080 {
3081  if(0!=mpAtomWin) mpAtomWin ->Enable(e);
3082  if(0!=mpBondWin) mpBondWin ->Enable(e);
3083  if(0!=mpAngleWin) mpAngleWin ->Enable(e);
3084  if(0!=mpDihedralAngleWin)mpDihedralAngleWin->Enable(e);
3085  if(0!=mpRigidGroupWin) mpRigidGroupWin ->Enable(e);
3086  return this->::wxWindow::Enable(e);
3087 }
3088 } //namespace
void SetHumanValueScale(const T s)
Set Coefficient between the value used by ObjCryst++ and the one to be displayed to the user...
Definition: wxCryst.cpp:697
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
Definition: wxMolecule.cpp:446
T * WXDialogChooseFromRegistry(ObjRegistry< T > &reg, wxWindow *parent, const string &message, int &choice)
This function allows to pick up one object in a registry.
Bond angle restraint between 3 atoms.
Definition: Molecule.h:256
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
Definition: wxMolecule.cpp:209
void SetValue(const string &)
This actually posts an UpdateUI event, so that it is safe to call it from a non-graphic thread...
Definition: wxCryst.cpp:346
void WXCrystValidateAllUserInput()
This function validates all user input (in a WXField) not yet taken into account, if needs be...
Definition: wxCryst.cpp:257
CrystMutex mMutex
Mutex used to lock data when preparing to update the UI in non-main thread.
Definition: wxCryst.h:189
Class to pick one choice...
Definition: wxCryst.h:482
void Add(WXCrystObjBasic *)
Add an object to the list.
Definition: wxCryst.cpp:199
bool mNeedUpdateUI
Do we need to update the display ?
Definition: wxCryst.h:187
Simple chronometer class, with microsecond precision.
Definition: Chronometer.h:33
void SetValue(const string &)
Used by the owner to change the name of the choice.
Definition: wxCryst.cpp:759
std::list< CellDihedralAngle > mvpDihedralAngle
Displayed list of Dihedral angles.
Definition: wxMolecule.h:243
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
Bond between two atoms, also a restraint on the associated bond length.
Definition: Molecule.h:152
Structure to store the bond current values.
Definition: wxMolecule.h:191
void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Forces all objects in the list to update.
Definition: wxCryst.cpp:223
std::list< CellAtom > mvpAtom
Displayed list of atoms.
Definition: wxMolecule.h:188
void OnToggleFree(wxCommandEvent &WXUNUSED(event))
Toggle the 'free' status of the bond.
Definition: wxMolecule.cpp:369
Abstract base class for all objects in wxCryst.
Definition: wxCryst.h:127
The basic atom scatterer, in a crystal.
Definition: Atom.h:57
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
Definition: wxMolecule.cpp:311
std::list< CellBondAngle > mvpBondAngle
Displayed list of bond angle.
Definition: wxMolecule.h:224
Structure to store the Atom parameters.
Definition: wxMolecule.h:176
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
Structure to store the dihedral angles current values.
Definition: wxMolecule.h:226
WXCrystObjBasic(wxWindow *parent)
Constructor.
Definition: wxCryst.cpp:129
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
MolAtom : atom inside a Molecule.
Definition: Molecule.h:58
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
wx class for MolBond objects
Definition: wxMolecule.h:61
WXMolecule * mpWXMolecule
The WXMolecule window which created this window, and who should be told if it is destroyed.
Definition: wxMolecule.h:39
A field for a parameter.
Definition: wxCryst.h:452
Class to automatically assign a unique wxID to each window.
Definition: wxCryst.h:74
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: Atom.cpp:47
std::list< CellBond > mvpBond
Displayed list of bonds, in the order they appear.
Definition: wxMolecule.h:206
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
Definition: wxMolecule.cpp:321
virtual const string & GetName() const
Name of the object.
void ExpandAtomGroupRecursive(MolAtom *atom, const map< MolAtom *, set< MolAtom * > > &connect, set< MolAtom * > &atomlist, const MolAtom *finalAtom)
Build recursively a list of atoms, starting from a one atom, and given a connectivity table...
Definition: Molecule.cpp:151
bool mIsSelfUpdating
Flag to indicate whether we are updating values in the wxGrid data.
Definition: wxMolecule.h:259
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
Definition: wxMolecule.cpp:592
wx class for MolBondAngle objects
Definition: wxMolecule.h:84
void NotifyDeleteListWin(WXMolScrolledWindow *win)
Notify that either the bond, bond angle or dihedral angle list window has been destroyed.
std::list< CellRigidGroup > mvpRigidGroup
Displayed list of Dihedral angles.
Definition: wxMolecule.h:256
wx class for MolAtom objects
Definition: wxMolecule.h:43
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
Definition: wxMolecule.cpp:456
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
Definition: wxMolecule.cpp:218
const RefParType * gpRefParTypeObjCryst
Top RefParType for the ObjCryst++ library.
WXFieldChoice * mpFieldCenterAtom
Center atom.
Definition: wxMolecule.h:261
Structure to store the bond angles current values.
Definition: wxMolecule.h:208
bool IsDummy() const
Returns true if this is a dummy atom, i.e.
Definition: Molecule.cpp:249
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
Definition: wxMolecule.cpp:602
void UpdateUI(const bool mutexlock=false)
Forces all objects in the list to update.
Definition: wxCryst.cpp:233
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal...