23 #include "wx/wxprec.h"
31 #include "ObjCryst/wxCryst/wxRefinableObj.h"
33 #include "ObjCryst/wxCryst/wxRefinableObj.h"
34 #include "ObjCryst/Quirks/VFNStreamFormat.h"
36 #include "ObjCryst/RefinableObj/GlobalOptimObj.h"
39 #include "ObjCryst/ObjCryst/Atom.h"
40 #include "ObjCryst/ObjCryst/Crystal.h"
41 #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h"
42 #include "ObjCryst/ObjCryst/PowderPattern.h"
43 #include "ObjCryst/ObjCryst/ScatteringPower.h"
44 #include "ObjCryst/ObjCryst/ZScatterer.h"
45 #include "ObjCryst/ObjCryst/ScatteringCorr.h"
46 #include "ObjCryst/ObjCryst/ReflectionProfile.h"
47 #include "ObjCryst/Quirks/Chronometer.h"
72 static const long ID_WXFIELD_REFPAR =WXCRYST_ID();
73 static const long ID_WXFIELD_REFPAR_FIXBUTTON =WXCRYST_ID();
74 static const long ID_WXFIELD_REFPAR_LIMITEDBUTTON=WXCRYST_ID();
75 static const long ID_REFPAR_POPUP_SET_LIMITS =WXCRYST_ID();
77 BEGIN_EVENT_TABLE(WXFieldRefPar,wxWindow)
78 EVT_TEXT_ENTER(ID_WXFIELD, WXFieldRefPar::OnEnter)
86 WXFieldRefPar::WXFieldRefPar(wxWindow *parent,const
string& label,
87 RefinablePar *par, const
int hsize,
88 const
bool enableFixButton, const
bool enableLimitedButton):
89 WXField(parent,label,ID_WXFIELD_REFPAR),mValue(0.),mpRefPar(par),mIsSelfUpdating(false),mFormat(_T("%8f"))
91 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::WXFieldName():End", 6)
93 mpLabel->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this);
96 this->SetLabel(label+
":R");
97 mpButtonFix=
new wxCheckBox(
this,ID_WXFIELD_REFPAR_FIXBUTTON,_T(
"L"),wxDefaultPosition, wxDefaultSize);
99 mpButtonFix->SetToolTip(_T(
"Check this box to enable optimizing this parameter.\n")
100 _T(
"(some parameters may be automatically fixed for global optimization)"));
101 mpSizer->Add(mpButtonFix,0,wxALIGN_CENTER);
104 else mpButtonFix = 0;
105 if(enableLimitedButton)
107 mpButtonLimited=
new wxCheckBox(
this,ID_WXFIELD_REFPAR_LIMITEDBUTTON,_T(
""),
108 wxDefaultPosition, wxSize(16,20));
109 mpButtonLimited->SetToolTip(_T(
"Check this box to use limits for this parameter"));
110 mpSizer->Add(mpButtonLimited,0,wxALIGN_CENTER);
113 else mpButtonLimited = 0;
115 mpField=
new wxTextCtrl(
this,ID_WXFIELD,_T(
""),
116 wxDefaultPosition,wxSize(hsize,-1),wxTE_PROCESS_ENTER,
117 wxTextValidator(wxFILTER_NUMERIC));
118 mpSizer->Add(mpField,0,wxALIGN_CENTER);
124 mpRefPar->WXNotifyDelete();
127 void WXFieldRefPar::OnEnter(wxCommandEvent & WXUNUSED(event))
129 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::OnEnter()",6)
135 if(
true==mIsSelfUpdating)
return;
136 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::OnEnter()",6)
146 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::OnToggleFix()",6)
147 if(0!=mpButtonFix) mpRefPar->SetIsFixed(!(mpButtonFix->GetValue()));
153 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::OnToggleLimited()",6)
154 if(0!=mpButtonLimited) mpRefPar->SetIsLimited(mpButtonLimited->GetValue());
160 static wxMenu sWXFieldRefParPopupMenu;
161 static bool needInitMenu=
true;
165 sWXFieldRefParPopupMenu.Append(ID_REFPAR_POPUP_SET_LIMITS, _T(
"Change Limits"));
167 this->PopupMenu(&sWXFieldRefParPopupMenu,0,0);
172 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::OnPopupMenuChoice()",7)
173 if(event.GetId()== ID_REFPAR_POPUP_SET_LIMITS)
179 wxTextEntryDialog limitDialog(
this,_T(
"Enter the minimum value"),
180 _T(
"Minimum"),str,wxOK | wxCANCEL);
181 limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
182 if(wxID_OK!=limitDialog.ShowModal())
184 VFN_DEBUG_EXIT(
"WXFieldRefPar::OnPopupMenuChoice():Cancelled",6)
187 limitDialog.GetValue().ToDouble(&min);
192 wxTextEntryDialog limitDialog(
this,_T(
"Enter the maximum value"),
193 _T(
"Maximum"),str,wxOK | wxCANCEL);
194 limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
195 if(wxID_OK!=limitDialog.ShowModal())
197 VFN_DEBUG_EXIT(
"WXFieldRefPar::OnPopupMenuChoice():Cancelled",6)
200 limitDialog.GetValue().ToDouble(&max);
204 wxMessageDialog dumbUser(
this,_T(
"max <= min !!!"),
205 _T(
"Whooops"),wxOK|wxICON_EXCLAMATION);
206 dumbUser.ShowModal();
211 mpRefPar->SetIsLimited(
true);
218 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::CrystUpdate()",6)
220 bool needUpdate=
false;
221 if(wxThread::IsMain())
223 if(mpRefPar->
IsUsed()!=this->IsShown()) needUpdate=
true;
224 if(0!=mpButtonFix)
if(mpButtonFix->GetValue()==mpRefPar->IsFixed()) needUpdate=
true;
225 if(0!=mpButtonLimited)
if(mpButtonLimited->GetValue()==mpRefPar->IsLimited()) needUpdate=
true;
242 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::UpdateUI("<<lock<<
")"<<
"MainThread="<<wxThread::IsMain(),3)
249 if(
false==mpRefPar->
IsUsed()) this->Show(
false);
250 else this->Show(
true);
262 mIsSelfUpdating=
true;
263 mpField->SetValue(tmp);
264 mIsSelfUpdating=
false;
265 if(0!=mpButtonFix) mpButtonFix->SetValue(!(mpRefPar->IsFixed()));
266 if(0!=mpButtonLimited) mpButtonLimited->SetValue(mpRefPar->IsLimited());
273 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::Revert()",6)
274 wxMutexLocker mlock(
mMutex);
280 VFN_DEBUG_MESSAGE(
"WXFieldRefPar::ValidateUserInput()",6)
281 wxMutexLocker mlock(
mMutex);
283 wxString s=mpField->GetValue();
308 WXField(parent,option->GetName(),field_id),
309 mChoice(-1),mChoiceOld(-1),mpOption(option),mpList(0)
311 wxString choices[20];
312 for(
int i=0;i<mpOption->GetNbChoice();i++)
313 choices[i]=wxString::FromAscii(mpOption->GetChoiceName(i).c_str());
315 mpList=
new wxChoice(
this,ID_WXFIELD,wxDefaultPosition,wxDefaultSize,
316 mpOption->GetNbChoice(),choices);
317 mpSizer->Add(mpList,0,wxALIGN_CENTER);
319 WXFieldOption::~WXFieldOption()
321 mpOption->WXNotifyDelete();
325 if(mChoice==mpList->GetSelection())
return;
327 mChoice=mpList->GetSelection();
328 mpOption->SetChoice(mChoice);
333 VFN_DEBUG_MESSAGE(
"WXFieldOption::CrystUpdate("<<uui<<lock<<
")",6)
335 if(mChoice==mpOption->GetChoice())
340 mChoice=mpOption->GetChoice();
347 VFN_DEBUG_MESSAGE(
"WXFieldOption::UpdateUI("<<lock<<
")"<<
"MainThread="<<wxThread::IsMain(),6)
354 mpList->SetSelection(mChoice);
361 wxMutexLocker mlock(
mMutex);
378 WXCrystObj(parent,wxHORIZONTAL,false),mpRegistry(reg)
380 VFN_DEBUG_ENTRY(
"WXCrystRegistry::WXCrystRegistry(wxWindow*)",6)
381 #ifdef VFN_CRYST_MUTEX
382 cout <<
"new CrystMutex("<<&
mMutex<<
")for WXCrystRegistry:"<<reg->GetName()<<endl;
384 wxStaticText*
mpLabel=
new wxStaticText(
this,-1,wxString::FromAscii(reg->GetName().c_str()));
386 mpLabel->SetForegroundColour(wxColour(0,0,255));
387 VFN_DEBUG_EXIT(
"WXCrystRegistry::WXCrystRegistry(wxWindow*):End",6)
389 template<
class T> WXRegistry<T>::~WXRegistry()
391 mpRegistry->WXNotifyDelete();
392 #ifdef VFN_CRYST_MUTEX
393 cout <<
"Deleting CrystMutex("<<&mMutex<<
")for WXCrystRegistry:"<<mpRegistry->GetName()<<endl;
396 template<
class T>
void WXRegistry<T>::Add(WXCrystObjBasic *obj)
398 VFN_DEBUG_ENTRY(
"WXCrystRegistry::AddWXCrystObj(WXCrystObj*)",6)
400 obj->Show(mIsExpanded);
402 VFN_DEBUG_EXIT("WXCrystRegistry::AddWXCrystObj(WXCrystObj*)",6)
404 template<class T>
void WXRegistry<T>::Remove(WXCrystObjBasic *obj)
407 VFN_DEBUG_ENTRY(
"WXCrystRegistry::RemoveWXCrystObj(WXCrystObj*)",6)
411 this->BottomLayout(0);
412 VFN_DEBUG_EXIT("WXCrystRegistry::RemoveWXCrystObj(WXCrystObj*):End",6)
415 template<class T>
bool WXRegistry<T>::OnChangeName(const
int id)
417 VFN_DEBUG_MESSAGE(
"WXRegistry<T>::OnChangeName()",6)
418 if(
id==ID_WXOBJ_NAME)
420 mpRegistry->SetName(mpWXTitle->GetValue());
450 const string &message,
int &choice)
452 wxString* choices=
new wxString[reg.
GetNb()];
453 for(
int i=0;i<reg.
GetNb();i++)
454 *(choices+i)=wxString::FromAscii((reg.
GetObj(i).GetClassName()+
":"+reg.
GetObj(i).GetName()).c_str());
455 #if wxCHECK_VERSION( 2, 9, 4 )
456 wxSingleChoiceDialog dialog
457 (parent,wxString::FromAscii(message.c_str()),_T(
"Choose"),reg.
GetNb(),choices,(
void**)NULL,wxOK | wxCANCEL);
459 wxSingleChoiceDialog dialog
460 (parent,wxString::FromAscii(message.c_str()),_T(
"Choose"),reg.
GetNb(),choices,NULL,wxOK | wxCANCEL);
462 dialog.SetSize(300,300);
463 if(wxID_OK!=dialog.ShowModal())
468 choice=dialog.GetSelection();
469 if(dialog.GetSelection()<0)
475 return &(reg.
GetObj(choice));
478 template RefinableObj*
484 template ScatteringPower*
486 template ScatteringPowerAtom*
488 const string &,
int &);
491 template PowderPattern*
493 template PowderPatternComponent*
495 const string&,
int &);
496 template DiffractionDataSingleCrystal*
498 const string &,
int &);
499 template OptimizationObj*
501 template XMLCrystTag*
506 wxWindow*parent,
const string &message
509 wxString* choices=
new wxString[reg.
GetNb()];
510 for(
int i=0;i<reg.
GetNb();i++)
511 *(choices+i)=wxString::FromAscii((reg.
GetObj(i).GetClassName()+
":"+reg.
GetObj(i).GetName()).c_str());
512 #if wxCHECK_VERSION( 2, 9, 4 )
513 wxSingleChoiceDialog dialog
514 (parent,wxString::FromAscii(message.c_str()),_T(
"Choose"),reg.
GetNb(),choices,(
void**)NULL,wxOK | wxCANCEL);
516 wxSingleChoiceDialog dialog
517 (parent,wxString::FromAscii(message.c_str()),_T(
"Choose"),reg.
GetNb(),choices,NULL,wxOK | wxCANCEL);
519 dialog.SetSize(300,300);
520 if(wxID_OK!=dialog.ShowModal())
526 choice=dialog.GetSelection();
527 return &(reg.
GetObj(choice));
530 template const RefinableObj*
533 template const Crystal*
536 template const Scatterer*
539 template const ScatteringPower*
541 const string &,
int &);
543 template const ScatteringPowerAtom*
545 const string &,
int &);
547 template const ZAtom*
550 template const PowderPattern*
552 const string &,
int &);
554 template const PowderPatternComponent*
556 const string&,
int &);
558 template const DiffractionDataSingleCrystal*
560 const string &,
int &);
562 template const OptimizationObj*
564 const string &,
int &);
566 template const XMLCrystTag*
568 const string &,
int &);
575 BEGIN_EVENT_TABLE(WXRefinableObj,wxWindow)
576 EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXRefinableObj::OnMenuSave)
577 EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXRefinableObj::OnMenuLoad)
578 EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar)
579 EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar)
580 EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize)
581 EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI)
584 WXRefinableObj::WXRefinableObj(wxWindow* parent, RefinableObj*obj):
585 WXCrystObj(parent,wxHORIZONTAL),mpRefinableObj(obj)
587 VFN_DEBUG_ENTRY(
"WXRefinableObj::WXRefinableObj():"<<obj->GetName(),6)
588 #ifdef VFN_CRYST_MUTEX
589 cout <<
"new CrystMutex("<<&mMutex<<
")for :"<<obj->GetClassName()<<
":"<<obj->GetName()<<endl;
591 mpWXTitle->SetLabel(mpRefinableObj->GetClassName());
594 mpMenuBar=
new WXCrystMenuBar(
this,
this);
596 mpSizer->Add(mpMenuBar);
597 mList.Add(mpMenuBar);
599 for(
unsigned int i=0;i<mpRefinableObj->GetNbOption();i++)
601 VFN_DEBUG_MESSAGE(
"WXRefinableObj::WXRefinableObj():Adding option "<<i,6)
602 WXCrystObjBasic *opt=mpRefinableObj->GetOption(i).WXCreate(this);
603 mpSizer->Add(opt,0,wxALIGN_LEFT);
608 VFN_DEBUG_EXIT("WXRefinableObj::WXRefinableObj()",6)
611 WXRefinableObj::~WXRefinableObj()
613 VFN_DEBUG_MESSAGE(
"WXRefinableObj::~WXRefinableObj():"<<mpRefinableObj->GetName(),6)
614 mpRefinableObj->WXNotifyDelete();
615 #ifdef VFN_CRYST_MUTEX
616 cout <<
"Deleting CrystMutex("<<&mMutex<<
")for :"<<mpRefinableObj->GetClassName()
617 <<
":"<<mpRefinableObj->GetName()<<endl;
623 VFN_DEBUG_ENTRY(
"WXRefinableObj::CrystUpdate("<<uui<<lock<<
"):"<<mpRefinableObj->
GetName(),6)
629 if(
true==wxThread::IsMain()) this->
UpdateUI(lock);
632 wxUpdateUIEvent event(ID_CRYST_UPDATEUI);
633 wxPostEvent(
this,event);
636 VFN_DEBUG_EXIT(
"WXRefinableObj::CrystUpdate():"<<mpRefinableObj->
GetName(),6)
641 VFN_DEBUG_MESSAGE(
"WXRefinableObj::OnChangeName()",6)
642 if(
id==ID_WXOBJ_NAME)
644 VFN_DEBUG_MESSAGE(
"WXRefinableObj::OnChangeName():Changing RefinableObj Name",6)
651 void WXRefinableObj::OnMenuSave(wxCommandEvent & WXUNUSED(event))
653 VFN_DEBUG_MESSAGE(
"WXRefinableObj::OnButtonSave()",6)
654 wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.xml"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
655 if(save.ShowModal() != wxID_OK) return;
657 ofstream out(save.GetPath().ToAscii());
660 out.imbue(std::locale::classic());
666 void WXRefinableObj::OnMenuLoad(wxCommandEvent & WXUNUSED(event))
668 VFN_DEBUG_MESSAGE(
"WXRefinableObj::OnButtonLoad()",6)
669 wxFileDialog *open= new wxFileDialog(this,_T("Choose a file"),_T(""),_T(""),_T("*.xml"),
670 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
671 if(open->ShowModal() != wxID_OK) return;
673 ifstream fin(open->GetPath().ToAscii());
676 XMLCrystTag tag(fin);
683 void WXRefinableObj::OnMenuFixAllPar(wxCommandEvent & WXUNUSED(event))
689 void WXRefinableObj::OnMenuUnFixAllPar(wxCommandEvent & WXUNUSED(event))
695 void WXRefinableObj::OnMenuParRandomize(wxCommandEvent & WXUNUSED(event))
697 (*fpObjCrystInformUser)(
"Randomizing object:"+mpRefinableObj->
GetName());
703 sprintf(buf,
"Finished randomizing object: %s, dt=%6.2fs",mpRefinableObj->
GetName().c_str(),chrono.seconds());
704 (*fpObjCrystInformUser)(buf);
707 void WXRefinableObj::OnUpdateUI(wxUpdateUIEvent& event)
714 VFN_DEBUG_ENTRY(
"WXRefinableObj::UpdateUI("<<lock<<
")"<<
"MainThread="<<wxThread::IsMain()<<
":"<<mpRefinableObj->
GetName(),6)
726 VFN_DEBUG_EXIT(
"WXRefinableObj::UpdateUI()"<<mpRefinableObj->
GetName(),6)
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.
WXField * spLastWXFieldInputNotValidated
This pointer records the last wxField in which something was enetered, so that it can be validated wh...
T * WXDialogChooseFromRegistry(ObjRegistry< T > ®, wxWindow *parent, const string &message, int &choice)
This function allows to pick up one object in a registry.
REAL GetHumanMin() const
Get the minimum value allowed (if limited)
void SetHumanValue(const REAL &)
Current value of parameter, scaled if necessary (for angles) to a human-understandable value.
REAL GetHumanMax() const
Get the maximum value allowed (if limited)
bool IsUsed() const
Is the parameter used (if not, it is simply irrelevant in the model) ?
const REAL & GetHumanValue() const
Current value of parameter, scaled if necessary (for angles) to a human-understandable value.
void SetHumanMin(const REAL)
Set the minimum value allowed (if limited)
void SetHumanMax(const REAL)
Get the maximum value allowed (if limited)
T & GetObj(const unsigned int i)
Get object #i in the registry.
long GetNb() const
Get the index of an object in the registry, from its name Warning: it can change if an object is remo...
bool IsBeingRefined() const
Is the object being refined ? (Can be refined by one algorithm at a time only.)
virtual void SetName(const string &name)
Name of the object.
virtual void XMLOutput(ostream &os, int indent=0) const
Output to stream in well-formed XML.
virtual const string & GetName() const
Name of the object.
virtual void XMLInput(istream &is, const XMLCrystTag &tag)
Input From stream.
void UnFixAllPar()
UnFix All parameters.
void FixAllPar()
Fix All parameters.
virtual void RandomizeConfiguration()
Randomize Configuration (before a global optimization).
Simple chronometer class, with microsecond precision.
CrystMutex mMutex
Mutex used to lock data when preparing to update the UI in non-main thread.
bool mNeedUpdateUI
Do we need to update the display ?
Base class for all displayed ObjCryst objects (with a title, and a sizer to stack objects).
WXFieldName * mpWXTitle
The title.
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...
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
This is the abstract base class for all fields, wether they contain a floating-point parameter,...
wxStaticText * mpLabel
The label.
wxBoxSizer * mpSizer
The horizontal sizer in which the title, button, fields, are put.
void SetValue(const string &)
This actually posts an UpdateUI event, so that it is safe to call it from a non-graphic thread.
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
const string GetValue() const
Get the current name.
This displays all components of a ObjCryst++ Registry.
A field for a RefinablePar.
virtual void ValidateUserInput()
This function shall be called when a new value has been entered.
void OnText(wxCommandEvent &WXUNUSED(event))
Records when text is entered (either from self-updating or user input)
void OnPopupMenu(wxMouseEvent &event)
Opens the popu menu, to allow changing limits.
void OnPopupMenuChoice(wxCommandEvent &event)
Opens the popu menu, to allow changing limits.
~WXFieldRefPar()
When a new value is entered (must type it and then hit the 'enter' key).
wxString mFormat
Format to be used, default = _T("%8f")
void SetFormat(const wxString &format)
Set Format.
void OnToggleFix(wxCommandEvent &WXUNUSED(event))
Toggle the 'fixed' status of the parameter.
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...
void OnToggleLimited(wxCommandEvent &WXUNUSED(event))
Toggle the 'limited' status of the parameter.
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
void Revert()
After a user entry, this allows to go back to the last value, if for some reason the entry was reject...
virtual void SetToolTip(const wxString &tip)
Set tooltip for this window. It will be activated when going over the entry field.
WX representation of a RefObj option. This displays the names of the different choices.
virtual void SetToolTip(const wxString &tip)
Set tooltip for this window. It will be activated when going over the choice field.
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...
void OnChoice(wxCommandEvent &WXUNUSED(event))
When a new value is entered.
virtual void ValidateUserInput()
Does nothing. Any user input is directly validated (OnChoice).
void Revert()
After a user entry, this allows to go back to the last value, if for some reason the entry was reject...
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
virtual bool OnChangeName(const int id)
When a WXFieldName has been changed by the user, it is handled here.
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...
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.