24 #include "wx/wxprec.h"
32 #include "ObjCryst/wxCryst/wxZScatterer.h"
33 #include "ObjCryst/ObjCryst/Molecule.h"
54 static const long ID_ZATOM_NAME= WXCRYST_ID();
55 static const long ID_ZATOM_SCATTPOW=WXCRYST_ID();
56 static const long ID_ZATOM_BOND= WXCRYST_ID();
57 static const long ID_ZATOM_ANGLE= WXCRYST_ID();
58 static const long ID_ZATOM_DIHED= WXCRYST_ID();
60 BEGIN_EVENT_TABLE(WXZAtom,wxWindow)
61 EVT_BUTTON(ID_ZATOM_SCATTPOW, WXZAtom::OnChangeScattPow)
64 WXZAtom::WXZAtom(wxWindow* parent, ZAtom *obj):
65 WXCrystObjBasic(parent),mpZAtom(obj)
67 VFN_DEBUG_ENTRY(
"WXZAtom::WXZAtom()",6)
68 mpSizer=new wxBoxSizer(wxHORIZONTAL);
70 mpFieldName=new WXFieldString(this, mpZAtom->mName,ID_ZATOM_NAME,80,true);
71 mpSizer->Add(mpFieldName,0,wxALIGN_LEFT);
72 mpFieldScattPower=new WXFieldChoice(this,ID_ZATOM_SCATTPOW,"Type:",60);
73 mpSizer->Add(mpFieldScattPower,0,wxALIGN_LEFT);
74 mList.Add(mpFieldScattPower);
76 if(0<mpZAtom->GetZScatterer().GetZAtomRegistry().Find(*mpZAtom))
78 RefinablePar *par=&(mpZAtom->GetZScatterer().GetPar(&(mpZAtom->mBondLength)));
79 par->SetName(
"Bond(w/"+(mpZAtom->GetZScatterer().GetZAtomRegistry()
80 .GetObj(mpZAtom->GetZBondAtom())).GetName()+
")");
81 WXCrystObjBasic* pFieldBond=par->WXCreate(
this);
82 mpSizer->Add(pFieldBond,0,wxALIGN_LEFT);
83 mList.Add(pFieldBond);
86 if(1<mpZAtom->GetZScatterer().GetZAtomRegistry().Find(*mpZAtom))
88 RefinablePar *par=&(mpZAtom->GetZScatterer().GetPar(&(mpZAtom->mAngle)));
89 par->SetName(
"Angle(w/"+(mpZAtom->GetZScatterer().GetZAtomRegistry()
90 .GetObj(mpZAtom->GetZAngleAtom())).GetName()+
")");
91 WXCrystObjBasic* pFieldAngle
93 mpSizer->Add(pFieldAngle,0,wxALIGN_LEFT);
94 mList.Add(pFieldAngle);
96 if(2<mpZAtom->GetZScatterer().GetZAtomRegistry().Find(*mpZAtom))
98 RefinablePar *par=&(mpZAtom->GetZScatterer().GetPar(&(mpZAtom->mDihed)));
99 par->SetName(
"DihedralAngle(w/"+(mpZAtom->GetZScatterer().GetZAtomRegistry()
100 .GetObj(mpZAtom->GetZDihedralAngleAtom())).GetName()+
")");
101 WXCrystObjBasic* pFieldDihed=par->WXCreate(
this);
102 mpSizer->Add(pFieldDihed,0,wxALIGN_LEFT);
103 mList.Add(pFieldDihed);
106 RefinablePar *par=&(mpZAtom->GetZScatterer().GetPar(&(mpZAtom->mOccupancy)));
107 par->SetName(
"Occup.");
108 WXCrystObjBasic* pFieldOccup=par->WXCreate(
this);
109 mpSizer->Add(pFieldOccup,0,wxALIGN_LEFT);
110 mList.Add(pFieldOccup);
113 this->SetSizer(mpSizer);
115 this->BottomLayout(0);
116 this->CrystUpdate(
true);
117 VFN_DEBUG_EXIT(
"WXZAtom::WXZAtom()",6)
122 VFN_DEBUG_ENTRY(
"WXZAtom::CrystUpdate()",6)
126 VFN_DEBUG_EXIT(
"WXZAtom::CrystUpdate()",6)
131 VFN_DEBUG_ENTRY(
"WXZAtom::UpdateUI()",6)
134 mpFieldName->SetValue(mpZAtom->GetName().c_str());
135 if(0!=mpZAtom->GetScatteringPower())
136 mpFieldScattPower->SetValue(mpZAtom->GetScatteringPower()->GetName());
138 mpFieldScattPower->SetValue(
"Dummy");
140 VFN_DEBUG_EXIT(
"WXZAtom::UpdateUI()",6)
143 void WXZAtom::OnChangeScattPow(wxCommandEvent & WXUNUSED(event))
145 VFN_DEBUG_MESSAGE(
"WXAtom::OnChangeScattPow()",6)
149 mpZAtom->GetZScatterer().GetCrystal().GetScatteringPowerRegistry(),
150 (wxWindow*)this,"Choose a new Scattering Power",choice);
152 mpZAtom->SetScatteringPower(scatt);
161 static const
long ID_ZSCATTERER_MENU_ATOM=
WXCRYST_ID();
162 static const
long ID_ZSCATTERER_MENU_ATOM_ADD=
WXCRYST_ID();
163 static const
long ID_ZSCATTERER_MENU_ATOM_CHANGE_PIVOT=
WXCRYST_ID();
164 static const
long ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_BOND=
WXCRYST_ID();
165 static const
long ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_ANGLE=
WXCRYST_ID();
166 static const
long ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_DIHED=
WXCRYST_ID();
167 static const
long ID_ZSCATTERER_MENU_FILE=
WXCRYST_ID();
168 static const
long ID_ZSCATTERER_MENU_IMPORT_FHZ=
WXCRYST_ID();
169 static const
long ID_ZSCATTERER_MENU_EXPORT_FHZ=
WXCRYST_ID();
170 static const
long ID_ZSCATTERER_MENU_CONVERT2MOLECULE=
WXCRYST_ID();
172 EVT_BUTTON(ID_WXOBJ_COLLAPSE,
WXCrystObj::OnToggleCollapse)
173 EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL,
WXRefinableObj::OnMenuFixAllPar)
174 EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL,
WXRefinableObj::OnMenuUnFixAllPar)
175 EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE,
WXRefinableObj::OnMenuParRandomize)
176 EVT_MENU(ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_BOND,
WXZScatterer::OnMenuSetLimits)
177 EVT_MENU(ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_ANGLE,
WXZScatterer::OnMenuSetLimits)
178 EVT_MENU(ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_DIHED,
WXZScatterer::OnMenuSetLimits)
179 EVT_MENU(ID_ZSCATTERER_MENU_ATOM_ADD,
WXZScatterer::OnMenuAddZAtom)
180 EVT_MENU(ID_ZSCATTERER_MENU_ATOM_CHANGE_PIVOT,
WXZScatterer::OnMenuChangePivotAtom)
181 EVT_MENU(ID_ZSCATTERER_MENU_IMPORT_FHZ,
WXZScatterer::OnMenuImportZMatrix)
182 EVT_MENU(ID_ZSCATTERER_MENU_EXPORT_FHZ,
WXZScatterer::OnMenuExportZMatrix)
183 EVT_MENU(ID_ZSCATTERER_MENU_CONVERT2MOLECULE,
WXZScatterer::OnMenuConvert2Molecule)
189 VFN_DEBUG_MESSAGE(
"WXZScatterer::WXZScatterer()",6)
191 mpMenuBar->AddMenu("Import/Export",ID_ZSCATTERER_MENU_FILE);
192 mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_FILE,
193 ID_ZSCATTERER_MENU_IMPORT_FHZ,
194 "Import Fenske-Hall Zmatrix");
195 mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_FILE,
196 ID_ZSCATTERER_MENU_EXPORT_FHZ,
197 "Save as Fenske-Hall Zmatrix");
198 mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_FILE,
199 ID_ZSCATTERER_MENU_CONVERT2MOLECULE,
201 mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR);
202 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all");
203 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all");
204 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_RANDOMIZE,
205 "Randomize Configuration");
206 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_BOND,
207 "Set limits (relative) on all bondlengths");
208 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_ANGLE,
209 "Set limits (relative) on all bond angles");
210 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_DIHED,
211 "Set limits (relative) on all dihedral angles");
212 mpMenuBar->AddMenu("
Atom",ID_ZSCATTERER_MENU_ATOM);
213 mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_ATOM,ID_ZSCATTERER_MENU_ATOM_ADD,
215 mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_ATOM,ID_ZSCATTERER_MENU_ATOM_CHANGE_PIVOT,
216 "Change Pivot
Atom");
221 wxBoxSizer* sizer=new wxBoxSizer(wxHORIZONTAL);
223 WXCrystObjBasic* pFieldPhi =mpZScatterer->GetPar(&(mpZScatterer->mPhi)).WXCreate(this);
224 WXCrystObjBasic* pFieldChi =mpZScatterer->GetPar(&(mpZScatterer->mChi)).WXCreate(this);
225 WXCrystObjBasic* pFieldPsi =mpZScatterer->GetPar(&(mpZScatterer->mPsi)).WXCreate(this);
227 sizer->Add(pFieldPhi ,0,wxALIGN_CENTER);
228 sizer->Add(pFieldChi ,0,wxALIGN_CENTER);
229 sizer->Add(pFieldPsi ,0,wxALIGN_CENTER);
231 mpSizer->Add(sizer,0,wxALIGN_LEFT);
232 mList.Add(pFieldPhi);
233 mList.Add(pFieldChi);
234 mList.Add(pFieldPsi);
236 mpWXZAtomRegistry=mpZScatterer->mZAtomRegistry.WXCreate(this);
237 mpSizer->Add(mpWXZAtomRegistry,0,wxALIGN_LEFT);
238 mList.Add(mpWXZAtomRegistry);
240 this->BottomLayout(0);
244 void WXZScatterer::OnMenuAddZAtom(wxCommandEvent & WXUNUSED(event))
246 VFN_DEBUG_ENTRY(
"WXZScatterer::OnMenuAddZAtom()",6)
258 mpZScatterer->GetCrystal().GetScatteringPowerRegistry(),
262 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
266 if(0<mpZScatterer->GetZAtomRegistry().GetNb())
270 this,
"Choose the bonded atom",bondAtomId);
273 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
277 wxTextEntryDialog bondLengthDialog(this,_T("Enter bond length (Angstroems)"),
278 _T("Bond length"),_T("1.5"),wxOK | wxCANCEL);
279 bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
280 if(wxID_OK!=bondLengthDialog.ShowModal())
282 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
285 bondLengthDialog.GetValue().ToDouble(&bondLength);
288 if(1<mpZScatterer->GetZAtomRegistry().GetNb())
291 this,
"Angle Atom",angleAtomId);
294 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
298 wxTextEntryDialog angleDialog(this,_T("Enter bond angle (degrees)"),
299 _T("Bond Angle"),_T("110"),wxOK | wxCANCEL);
300 angleDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
301 if(wxID_OK!=angleDialog.ShowModal())
303 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
306 angleDialog.GetValue().ToDouble(&angle);
309 if(2<mpZScatterer->GetZAtomRegistry().GetNb())
312 this,
"Dihedral angle Atom",dihedAtomId);
315 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
319 wxTextEntryDialog dihedDialog(this,_T("Enter dihedral angle (degrees)"),
320 _T("Dihedral Angle"),_T("0"),wxOK | wxCANCEL);
321 dihedDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
322 if(wxID_OK!=dihedDialog.ShowModal())
324 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
327 dihedDialog.GetValue().ToDouble(&dihed);
330 if(1<mpZScatterer->GetZAtomRegistry().GetNb())
331 if(bondAtomId==angleAtomId)
333 wxMessageDialog dumbUser(
this,_T(
"Bond, angle an dihedral atoms *must* be different"),
334 _T(
"Whooops"),wxOK|wxICON_EXCLAMATION);
335 dumbUser.ShowModal();
338 if(2<mpZScatterer->GetZAtomRegistry().GetNb())
339 if((bondAtomId==angleAtomId)||(bondAtomId==dihedAtomId)||(angleAtomId==dihedAtomId))
341 wxMessageDialog dumbUser(
this,_T(
"Bond, angle an dihedral atoms *must* be different"),
342 _T(
"Whooops"),wxOK|wxICON_EXCLAMATION);
343 dumbUser.ShowModal();
347 sprintf(buf,
"%d",mpZScatterer->GetNbComponent()+1);
348 mpZScatterer->AddAtom (scattPow->GetName()+(
string)buf,
350 bondAtomId,bondLength,
351 angleAtomId,angle*DEG2RAD,
352 dihedAtomId,dihed*DEG2RAD,
355 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom()",6)
358 void WXZScatterer::OnMenuSetLimits(wxCommandEvent & event)
360 VFN_DEBUG_ENTRY(
"WXZScatterer::OnMenuSetLimits()",6)
362 if(event.GetId()==ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_BOND)
365 wxTextEntryDialog limitDialog(
this,_T(
"Enter maximum shift in Angstroems\n The limits are taken symmetrically around current position:\n X0-l < X < X0+l "),
366 _T(
"Set limits (relative) for bondlengths"),_T(
".1"),wxOK | wxCANCEL);
367 limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
368 if(wxID_OK!=limitDialog.ShowModal())
370 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuSetLimits():Cancelled",6)
373 limitDialog.GetValue().ToDouble(&limit);
376 wxMessageDialog dumbUser(
this,_T(
"Limit must be > 0 !"),
377 _T(
"Whooops"),wxOK|wxICON_EXCLAMATION);
378 dumbUser.ShowModal();
381 mpZScatterer->SetLimitsRelative(gpRefParTypeScattConformBondLength,-limit,limit);
383 if(event.GetId()==ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_ANGLE)
386 wxTextEntryDialog limitDialog(
this,_T(
"Enter maximum shift in Degrees\n The limits are taken symmetrically around current position:\n X0-l < X < X0+l "),
387 _T(
"Set limits (relative) for bond angles"),_T(
".1"),wxOK | wxCANCEL);
388 limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
389 if(wxID_OK!=limitDialog.ShowModal())
391 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuSetLimits():Cancelled",6)
394 limitDialog.GetValue().ToDouble(&limit);
397 wxMessageDialog dumbUser(
this,_T(
"Limit must be > 0 !"),
398 _T(
"Whooops"),wxOK|wxICON_EXCLAMATION);
399 dumbUser.ShowModal();
403 mpZScatterer->SetLimitsRelative(gpRefParTypeScattConformBondAngle,-limit,limit);
405 if(event.GetId()==ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_DIHED)
408 wxTextEntryDialog limitDialog(
this,_T(
"Enter maximum shift in Degrees\n The limits are taken symmetrically around current position:\n X0-l < X < X0+l "),
409 _T(
"Set limits (relative) for dihedral angles"),_T(
".1"),wxOK | wxCANCEL);
410 limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
411 if(wxID_OK!=limitDialog.ShowModal())
413 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuSetLimits():Cancelled",6)
416 limitDialog.GetValue().ToDouble(&limit);
419 wxMessageDialog dumbUser(
this,_T(
"Limit must be > 0 !"),
420 _T(
"Whooops"),wxOK|wxICON_EXCLAMATION);
421 dumbUser.ShowModal();
425 mpZScatterer->SetLimitsRelative(gpRefParTypeScattConformDihedAngle,-limit,limit);
429 void WXZScatterer::OnMenuChangePivotAtom(wxCommandEvent &WXUNUSED(event))
432 int pivot=mpZScatterer->mCenterAtomIndex;
434 this,
"Choose the new Pivot atom",pivot);
437 VFN_DEBUG_EXIT(
"WXZScatterer::OnMenuAddZAtom():Cancelled",6)
440 mpZScatterer->mCenterAtomIndex=pivot;
441 mpZScatterer->mClockScatterer.Click();
444 void WXZScatterer::OnMenuImportZMatrix(wxCommandEvent &WXUNUSED(event))
446 wxFileDialog open(
this,_T(
"Choose a file"),_T(
""),_T(
""),_T(
"*.fhz"),
447 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
448 if(open.ShowModal() != wxID_OK)
return;
449 ifstream fin (open.GetPath().ToAscii());
452 throw ObjCrystException(
"WXZScatterer::OnMenuImportZMatrix() : \
453 Error opening file for input:"+
string(open.GetPath().ToAscii()));
455 mpZScatterer->ImportFenskeHallZMatrix(fin);
458 void WXZScatterer::OnMenuExportZMatrix(wxCommandEvent &WXUNUSED(event))
460 wxFileDialog save(
this,_T(
"Choose a file"),_T(
""),_T(
""),_T(
"*.fhz"),wxFD_SAVE);
461 if(save.ShowModal() != wxID_OK)
return;
462 ofstream fout (save.GetPath().ToAscii());
465 throw ObjCrystException(
"WXZScatterer::OnMenuExportZMatrix() : \
466 Error opening file for input:"+
string(save.GetPath().ToAscii()));
468 fout.imbue(std::locale::classic());
469 mpZScatterer->ExportFenskeHallZMatrix(fout);
473 void WXZScatterer::OnMenuConvert2Molecule(wxCommandEvent &WXUNUSED(event))
476 mpZScatterer->GetCrystal().RemoveScatterer(mpZScatterer);
477 mol->GetCrystal().AddScatterer(mol);
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
void WXCrystValidateAllUserInput()
This function validates all user input (in a WXField) not yet taken into account, if needs be.
Molecule * ZScatterer2Molecule(ZScatterer *scatt)
Converter from ZScatterer to a Molecule object.
T * WXDialogChooseFromRegistry(ObjRegistry< T > ®, wxWindow *parent, const string &message, int &choice)
This function allows to pick up one object in a registry.
The basic atom scatterer, in a crystal.
Molecule : class for complex scatterer descriptions using cartesian coordinates with bond length/angl...
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal.
Class for individual atoms in a ZScatterer Object.
ZScatterer: the basic type of complex scatterers, where atom positions are defined using a standard "...
Class to automatically assign a unique wxID to each window.
Abstract base class for all objects in wxCryst.
CrystMutex mMutex
Mutex used to lock data when preparing to update the UI in non-main thread.
void UpdateUI(const bool mutexlock=false)
Forces all objects in the list to update.
void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Forces all objects in the list to update.
Base class for all displayed ObjCryst objects (with a title, and a sizer to stack objects).
The base wxCryst class for all RefinableObj objects.
base wxCryst class for Scatterers
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
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...
wxCryst class for ZScatterer objects