FOX/ObjCryst++  2022
wxRefinableObj.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 //#include <sstream> //for stringstream
20 #include <fstream>
21 
22 // wx headers, with or without precompilation
23 #include "wx/wxprec.h"
24 #ifdef __BORLANDC__
25  #pragma hdrstop
26 #endif
27 #ifndef WX_PRECOMP
28  #include "wx/wx.h"
29 #endif
30 
31 #include "ObjCryst/wxCryst/wxRefinableObj.h"
32 
33 #include "ObjCryst/wxCryst/wxRefinableObj.h"
34 #include "ObjCryst/Quirks/VFNStreamFormat.h"
35 
36 #include "ObjCryst/RefinableObj/GlobalOptimObj.h"
37 
38 //These are only for explicit instantiation
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"
48 
49 //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers
50 #ifdef max
51 #undef max
52 #endif
53 #ifdef min
54 #undef min
55 #endif
56 #ifdef DrawText
57 #undef DrawText
58 #endif
59 
60 namespace ObjCryst
61 {
66 extern WXField *spLastWXFieldInputNotValidated;
68 //
69 // WXFieldRefPar
70 //
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();
76 
77 BEGIN_EVENT_TABLE(WXFieldRefPar,wxWindow)
78  EVT_TEXT_ENTER(ID_WXFIELD, WXFieldRefPar::OnEnter)
79  EVT_TEXT(ID_WXFIELD, WXFieldRefPar::OnText)
80  EVT_CHECKBOX(ID_WXFIELD_REFPAR_FIXBUTTON, WXFieldRefPar::OnToggleFix)
81  EVT_CHECKBOX(ID_WXFIELD_REFPAR_LIMITEDBUTTON,WXFieldRefPar::OnToggleLimited)
82  EVT_RIGHT_DOWN( WXFieldRefPar::OnPopupMenu)
83  EVT_MENU(ID_REFPAR_POPUP_SET_LIMITS, WXFieldRefPar::OnPopupMenuChoice)
84 END_EVENT_TABLE()
85 
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"))
90 {
91  VFN_DEBUG_MESSAGE("WXFieldRefPar::WXFieldName():End", 6)
92 
93  mpLabel->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this);
94  if (enableFixButton)
95  {
96  this->SetLabel(label+":R");
97  mpButtonFix=new wxCheckBox(this,ID_WXFIELD_REFPAR_FIXBUTTON,_T("L"),wxDefaultPosition, wxDefaultSize);
98  //mpButtonFix->Fit();
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);
102  mpButtonFix->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this);
103  }
104  else mpButtonFix = 0;
105  if(enableLimitedButton)
106  {
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);
111  mpButtonLimited->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this);
112  }
113  else mpButtonLimited = 0;
114 
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);
119  mpField->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this);
120 }
121 
123 {
124  mpRefPar->WXNotifyDelete();
125 }
126 
127 void WXFieldRefPar::OnEnter(wxCommandEvent & WXUNUSED(event))
128 {
129  VFN_DEBUG_MESSAGE("WXFieldRefPar::OnEnter()",6)
131 }
132 
133 void WXFieldRefPar::OnText(wxCommandEvent & WXUNUSED(event))
134 {
135  if(true==mIsSelfUpdating) return;
136  VFN_DEBUG_MESSAGE("WXFieldRefPar::OnEnter()",6)
138  {
141  }
142 }
143 
144 void WXFieldRefPar::OnToggleFix(wxCommandEvent & WXUNUSED(event))
145 {
146  VFN_DEBUG_MESSAGE("WXFieldRefPar::OnToggleFix()",6)
147  if(0!=mpButtonFix) mpRefPar->SetIsFixed(!(mpButtonFix->GetValue()));
148  mpRefPar->Print();
149 }
150 
151 void WXFieldRefPar::OnToggleLimited(wxCommandEvent & WXUNUSED(event))
152 {
153  VFN_DEBUG_MESSAGE("WXFieldRefPar::OnToggleLimited()",6)
154  if(0!=mpButtonLimited) mpRefPar->SetIsLimited(mpButtonLimited->GetValue());
155  mpRefPar->Print();
156 }
157 
158 void WXFieldRefPar::OnPopupMenu(wxMouseEvent & WXUNUSED(event))
159 {
160  static wxMenu sWXFieldRefParPopupMenu;//("Refinable Parameter");
161  static bool needInitMenu=true;
162  if(needInitMenu)
163  {
164  needInitMenu=false;
165  sWXFieldRefParPopupMenu.Append(ID_REFPAR_POPUP_SET_LIMITS, _T("Change Limits"));
166  }
167  this->PopupMenu(&sWXFieldRefParPopupMenu,0,0);
168 }
169 
170 void WXFieldRefPar::OnPopupMenuChoice(wxCommandEvent& event)
171 {
172  VFN_DEBUG_MESSAGE("WXFieldRefPar::OnPopupMenuChoice()",7)
173  if(event.GetId()== ID_REFPAR_POPUP_SET_LIMITS)
174  {
175  double min,max;
176  {
177  wxString str;
178  str << mpRefPar->GetHumanMin();
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())
183  {
184  VFN_DEBUG_EXIT("WXFieldRefPar::OnPopupMenuChoice():Cancelled",6)
185  return;
186  }
187  limitDialog.GetValue().ToDouble(&min);
188  }
189  {
190  wxString str;
191  str << mpRefPar->GetHumanMax();
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())
196  {
197  VFN_DEBUG_EXIT("WXFieldRefPar::OnPopupMenuChoice():Cancelled",6)
198  return;
199  }
200  limitDialog.GetValue().ToDouble(&max);
201  }
202  if(max<=min)
203  {
204  wxMessageDialog dumbUser(this,_T("max <= min !!!"),
205  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
206  dumbUser.ShowModal();
207  return;
208  }
209  mpRefPar->SetHumanMin(min);
210  mpRefPar->SetHumanMax(max);
211  mpRefPar->SetIsLimited(true);
212  mpRefPar->Print();
213  }
214 }
215 
216 void WXFieldRefPar::CrystUpdate(const bool uui,const bool lock)
217 {
218  VFN_DEBUG_MESSAGE("WXFieldRefPar::CrystUpdate()",6)
219  if(lock) mMutex.Lock();
220  bool needUpdate=false;
221  if(wxThread::IsMain())
222  {
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;
226  }
227  if(mValue!=mpRefPar->GetHumanValue()) needUpdate=true;
228  if(!needUpdate)
229  {
230  if(lock) mMutex.Unlock();
231  return;
232  }
233  mValueOld=mValue;
234  mValue=mpRefPar->GetHumanValue();
235  mNeedUpdateUI=true;
236  if(lock) mMutex.Unlock();
237  if(mNeedUpdateUI && wxThread::IsMain()) this->UpdateUI(lock);
238 }
239 
240 void WXFieldRefPar::UpdateUI(const bool lock)
241 {
242  VFN_DEBUG_MESSAGE("WXFieldRefPar::UpdateUI("<<lock<<")"<<"MainThread="<<wxThread::IsMain(),3)
243  if(lock) mMutex.Lock();
244  if(mNeedUpdateUI==false)
245  {
246  if(lock) mMutex.Unlock();
247  return;
248  }
249  if(false==mpRefPar->IsUsed()) this->Show(false);
250  else this->Show(true);
251 
252  if(mpField==0)
253  {
254  if(lock) mMutex.Unlock();
255  return;
256  }
257 
258  //mpField->SetValue(wxString::Printf("%f",mValue));
259  wxString tmp;
260  //if((abs(mValue)<100)&&(abs(mValue)>0.01)) tmp.Printf(_T("%6.4f"),mValue);
261  tmp.Printf(mFormat,mValue);
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());
267  mNeedUpdateUI=false;
268  if(lock) mMutex.Unlock();
269 }
270 
272 {
273  VFN_DEBUG_MESSAGE("WXFieldRefPar::Revert()",6)
274  wxMutexLocker mlock(mMutex);
275  mValue=mValueOld;
276  mNeedUpdateUI=true;
277 }
279 {
280  VFN_DEBUG_MESSAGE("WXFieldRefPar::ValidateUserInput()",6)
281  wxMutexLocker mlock(mMutex);
282  mValueOld=mValue;
283  wxString s=mpField->GetValue();
284  double tmp;
285  s.ToDouble(&tmp);
286  mValue=tmp;
287  mpRefPar->SetHumanValue(mValue);
288 }
289 
290 void WXFieldRefPar::SetToolTip(const wxString& tip){mpField->SetToolTip(tip);}
291 
292 void WXFieldRefPar::SetFormat(const wxString &format)
293 {
294  mFormat=format;
295 }
296 
298 //
299 // WXFieldOption
300 //
302 BEGIN_EVENT_TABLE(WXFieldOption,wxWindow)
303  EVT_CHOICE(ID_WXFIELD,WXFieldOption::OnChoice)
304 END_EVENT_TABLE()
305 
306 WXFieldOption::WXFieldOption(wxWindow *parent,
307  const int field_id,RefObjOpt* option):
308 WXField(parent,option->GetName(),field_id),
309 mChoice(-1),mChoiceOld(-1),mpOption(option),mpList(0)
310 {
311  wxString choices[20];//:TODO: dynamically choose correct number
312  for(int i=0;i<mpOption->GetNbChoice();i++)
313  choices[i]=wxString::FromAscii(mpOption->GetChoiceName(i).c_str());
314 
315  mpList= new wxChoice(this,ID_WXFIELD,wxDefaultPosition,wxDefaultSize,
316  mpOption->GetNbChoice(),choices);
317  mpSizer->Add(mpList,0,wxALIGN_CENTER);
318 }
319 WXFieldOption::~WXFieldOption()
320 {
321  mpOption->WXNotifyDelete();
322 }
323 void WXFieldOption::OnChoice(wxCommandEvent & WXUNUSED(event))
324 {
325  if(mChoice==mpList->GetSelection()) return;
326  mChoiceOld=mChoice;
327  mChoice=mpList->GetSelection();
328  mpOption->SetChoice(mChoice);
329 }
330 
331 void WXFieldOption::CrystUpdate(const bool uui,const bool lock)
332 {
333  VFN_DEBUG_MESSAGE("WXFieldOption::CrystUpdate("<<uui<<lock<<")",6)
334  if(lock) mMutex.Lock();
335  if(mChoice==mpOption->GetChoice())
336  {
337  if(lock) mMutex.Unlock();
338  return;
339  }
340  mChoice=mpOption->GetChoice();
341  mNeedUpdateUI=true;
342  if(lock) mMutex.Unlock();
343 }
344 
345 void WXFieldOption::UpdateUI(const bool lock)
346 {
347  VFN_DEBUG_MESSAGE("WXFieldOption::UpdateUI("<<lock<<")"<<"MainThread="<<wxThread::IsMain(),6)
348  if(lock) mMutex.Lock();
349  if(mNeedUpdateUI==false)
350  {
351  if(lock) mMutex.Unlock();
352  return;
353  }
354  mpList->SetSelection(mChoice);
355  mNeedUpdateUI=false;
356  if(lock) mMutex.Unlock();
357 }
358 
360 {
361  wxMutexLocker mlock(mMutex);
362  mChoice=mChoiceOld;
363  mNeedUpdateUI=true;
364 }
366 {
367 }
368 
369 void WXFieldOption::SetToolTip(const wxString& tip){mpList->SetToolTip(tip);}
370 
372 //
373 // WXRegistry
374 //
376 
377 template<class T> WXRegistry<T>::WXRegistry(wxWindow *parent,ObjRegistry<T>* reg):
378 WXCrystObj(parent,wxHORIZONTAL,false),mpRegistry(reg)
379 {
380  VFN_DEBUG_ENTRY("WXCrystRegistry::WXCrystRegistry(wxWindow*)",6)
381  #ifdef VFN_CRYST_MUTEX
382  cout <<"new CrystMutex("<<&mMutex<<")for WXCrystRegistry:"<<reg->GetName()<<endl;
383  #endif
384  wxStaticText* mpLabel=new wxStaticText(this,-1,wxString::FromAscii(reg->GetName().c_str()));
385  mpSizer->Add(mpLabel,0,wxALIGN_LEFT);
386  mpLabel->SetForegroundColour(wxColour(0,0,255));
387  VFN_DEBUG_EXIT("WXCrystRegistry::WXCrystRegistry(wxWindow*):End",6)
388 }
389 template<class T> WXRegistry<T>::~WXRegistry()
390 {
391  mpRegistry->WXNotifyDelete();
392  #ifdef VFN_CRYST_MUTEX
393  cout <<"Deleting CrystMutex("<<&mMutex<<")for WXCrystRegistry:"<<mpRegistry->GetName()<<endl;
394  #endif
395 }
396 template<class T> void WXRegistry<T>::Add(WXCrystObjBasic *obj)
397 {
398  VFN_DEBUG_ENTRY("WXCrystRegistry::AddWXCrystObj(WXCrystObj*)",6)
399  mList.Add(obj);
400  obj->Show(mIsExpanded);
401  this->AddChild(obj);
402  VFN_DEBUG_EXIT("WXCrystRegistry::AddWXCrystObj(WXCrystObj*)",6)
403 }
404 template<class T> void WXRegistry<T>::Remove(WXCrystObjBasic *obj)
405 {
406  if(obj==0) return;
407  VFN_DEBUG_ENTRY("WXCrystRegistry::RemoveWXCrystObj(WXCrystObj*)",6)
408  mList.Remove(obj);
409  //mpSizer->Detach((wxWindow*)obj);
410  obj->Destroy();
411  this->BottomLayout(0);
412  VFN_DEBUG_EXIT("WXCrystRegistry::RemoveWXCrystObj(WXCrystObj*):End",6)
413 }
414 
415 template<class T> bool WXRegistry<T>::OnChangeName(const int id)
416 {
417  VFN_DEBUG_MESSAGE("WXRegistry<T>::OnChangeName()",6)
418  if(id==ID_WXOBJ_NAME)
419  {
420  mpRegistry->SetName(mpWXTitle->GetValue());
421  return true;
422  }
423  return false;
424 }
425 
426 
427 //Explicit instantiation
428 template class WXRegistry<RefinableObj>;
429 template class WXRegistry<RefObjOpt>;
430 template class WXRegistry<Crystal>;
431 template class WXRegistry<Scatterer>;
432 template class WXRegistry<ScatteringPower>;
433 template class WXRegistry<ScatteringPowerAtom>;
434 template class WXRegistry<PowderPattern>;
437 template class WXRegistry<OptimizationObj>;
438 template class WXRegistry<XMLCrystTag>;
439 //template class WXRegistry<IOCrystTag>;//to be removed
440 template class WXRegistry<ZAtom>;
442 template class WXRegistry<TextureEllipsoid>;
443 template class WXRegistry<ReflectionProfile>;
445 //
446 // WXDialogChooseFromRegistry
447 //
449 template<class T> T* WXDialogChooseFromRegistry(ObjRegistry<T> &reg,wxWindow*parent,
450  const string &message,int &choice)
451 {
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);
458  #else
459  wxSingleChoiceDialog dialog
460  (parent,wxString::FromAscii(message.c_str()),_T("Choose"),reg.GetNb(),choices,NULL,wxOK | wxCANCEL);
461  #endif
462  dialog.SetSize(300,300);
463  if(wxID_OK!=dialog.ShowModal())
464  {
465  delete[] choices;
466  return 0;
467  }
468  choice=dialog.GetSelection();
469  if(dialog.GetSelection()<0)
470  {
471  delete[] choices;
472  return 0;
473  }
474  delete[] choices;
475  return &(reg.GetObj(choice));
476 }
477 
478 template RefinableObj*
479  WXDialogChooseFromRegistry(ObjRegistry<RefinableObj> &,wxWindow*,const string &,int &);
480 template Crystal*
481  WXDialogChooseFromRegistry(ObjRegistry<Crystal> &,wxWindow*,const string &,int &);
482 template Scatterer*
483  WXDialogChooseFromRegistry(ObjRegistry<Scatterer> &,wxWindow*,const string &,int &);
484 template ScatteringPower*
485  WXDialogChooseFromRegistry(ObjRegistry<ScatteringPower> &,wxWindow*,const string &,int &);
486 template ScatteringPowerAtom*
487  WXDialogChooseFromRegistry(ObjRegistry<ScatteringPowerAtom> &,wxWindow*,
488  const string &,int &);
489 template ZAtom*
490  WXDialogChooseFromRegistry(ObjRegistry<ZAtom> &,wxWindow*,const string &,int &);
491 template PowderPattern*
492  WXDialogChooseFromRegistry(ObjRegistry<PowderPattern> &,wxWindow*,const string &,int &);
493 template PowderPatternComponent*
494  WXDialogChooseFromRegistry(ObjRegistry<PowderPatternComponent>&,wxWindow*,
495  const string&,int &);
496 template DiffractionDataSingleCrystal*
497  WXDialogChooseFromRegistry(ObjRegistry<DiffractionDataSingleCrystal>&,wxWindow*,
498  const string &,int &);
499 template OptimizationObj*
500  WXDialogChooseFromRegistry(ObjRegistry<OptimizationObj> &,wxWindow*,const string &,int &);
501 template XMLCrystTag*
502  WXDialogChooseFromRegistry(ObjRegistry<XMLCrystTag> &,wxWindow*,const string &,int &);
503 
504 
505 template<class T> const T* WXDialogChooseFromRegistry(const ObjRegistry<T> &reg,
506  wxWindow*parent,const string &message
507  ,int &choice)
508 {
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);
515  #else
516  wxSingleChoiceDialog dialog
517  (parent,wxString::FromAscii(message.c_str()),_T("Choose"),reg.GetNb(),choices,NULL,wxOK | wxCANCEL);
518  #endif
519  dialog.SetSize(300,300);
520  if(wxID_OK!=dialog.ShowModal())
521  {
522  delete[] choices;
523  return 0;
524  }
525  delete[] choices;
526  choice=dialog.GetSelection();
527  return &(reg.GetObj(choice));
528 }
529 
530 template const RefinableObj*
531  WXDialogChooseFromRegistry(const ObjRegistry<RefinableObj> &,wxWindow*,const string &,int &);
532 
533 template const Crystal*
534  WXDialogChooseFromRegistry(const ObjRegistry<Crystal> &,wxWindow*,const string &,int &);
535 
536 template const Scatterer*
537  WXDialogChooseFromRegistry(const ObjRegistry<Scatterer> &,wxWindow*,const string &,int &);
538 
539 template const ScatteringPower*
540  WXDialogChooseFromRegistry(const ObjRegistry<ScatteringPower> &,wxWindow*,
541  const string &,int &);
542 
543 template const ScatteringPowerAtom*
544  WXDialogChooseFromRegistry(const ObjRegistry<ScatteringPowerAtom> &,wxWindow*,
545  const string &,int &);
546 
547 template const ZAtom*
548  WXDialogChooseFromRegistry(const ObjRegistry<ZAtom> &,wxWindow*,const string &,int &);
549 
550 template const PowderPattern*
551  WXDialogChooseFromRegistry(const ObjRegistry<PowderPattern> &,wxWindow*,
552  const string &,int &);
553 
554 template const PowderPatternComponent*
555  WXDialogChooseFromRegistry(const ObjRegistry<PowderPatternComponent>&,wxWindow*,
556  const string&,int &);
557 
558 template const DiffractionDataSingleCrystal*
559  WXDialogChooseFromRegistry(const ObjRegistry<DiffractionDataSingleCrystal>&,wxWindow*,
560  const string &,int &);
561 
562 template const OptimizationObj*
563  WXDialogChooseFromRegistry(const ObjRegistry<OptimizationObj> &,wxWindow*,
564  const string &,int &);
565 
566 template const XMLCrystTag*
567  WXDialogChooseFromRegistry(const ObjRegistry<XMLCrystTag> &,wxWindow*,
568  const string &,int &);
569 
571 //
572 // WXRefinableObj
573 //
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)
582 END_EVENT_TABLE()
583 
584 WXRefinableObj::WXRefinableObj(wxWindow* parent, RefinableObj*obj):
585 WXCrystObj(parent,wxHORIZONTAL),mpRefinableObj(obj)
586 {
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;
590  #endif
591  mpWXTitle->SetLabel(mpRefinableObj->GetClassName());
592 
593  // Menu
594  mpMenuBar=new WXCrystMenuBar(this,this);
595 
596  mpSizer->Add(mpMenuBar);
597  mList.Add(mpMenuBar);
598  //:TODO: Rather use a WXRegistry for the options ?
599  for(unsigned int i=0;i<mpRefinableObj->GetNbOption();i++)
600  {
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);
604  mList.Add(opt);
605  }
606  //this->BottomLayout(0);
607  //this->CrystUpdate(true,true);
608  VFN_DEBUG_EXIT("WXRefinableObj::WXRefinableObj()",6)
609 }
610 
611 WXRefinableObj::~WXRefinableObj()
612 {
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;
618  #endif
619 }
620 
621 void WXRefinableObj::CrystUpdate(const bool uui,const bool lock)
622 {
623  VFN_DEBUG_ENTRY("WXRefinableObj::CrystUpdate("<<uui<<lock<<"):"<<mpRefinableObj->GetName(),6)
624  //if(lock) mMutex.Lock();
625  this->WXCrystObj::CrystUpdate(false,lock);
626  //if(lock) mMutex.Unlock();
627  if(uui)
628  {
629  if(true==wxThread::IsMain()) this->UpdateUI(lock);
630  else
631  {
632  wxUpdateUIEvent event(ID_CRYST_UPDATEUI);
633  wxPostEvent(this,event);
634  }
635  }
636  VFN_DEBUG_EXIT("WXRefinableObj::CrystUpdate():"<<mpRefinableObj->GetName(),6)
637 }
638 
640 {
641  VFN_DEBUG_MESSAGE("WXRefinableObj::OnChangeName()",6)
642  if(id==ID_WXOBJ_NAME)
643  {
644  VFN_DEBUG_MESSAGE("WXRefinableObj::OnChangeName():Changing RefinableObj Name",6)
645  mpRefinableObj->SetName(mpWXTitle->GetValue());
646  return true;
647  }
648  return false;
649 }
650 
651 void WXRefinableObj::OnMenuSave(wxCommandEvent & WXUNUSED(event))
652 {
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;
656 
657  ofstream out(save.GetPath().ToAscii());
658  if(!out) return;//:TODO:
659  {
660  out.imbue(std::locale::classic());
661  mpRefinableObj->XMLOutput(out);
662  }
663  out.close();
664 }
665 
666 void WXRefinableObj::OnMenuLoad(wxCommandEvent & WXUNUSED(event))
667 {
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;
672 
673  ifstream fin(open->GetPath().ToAscii());
674  if(!fin) return;//:TODO:
675  {
676  XMLCrystTag tag(fin);//:TODO: load all tags and find the right ones for this class
677  mpRefinableObj->XMLInput(fin,tag);
678  }
679  fin.close();
680  open->Destroy();
681 }
682 
683 void WXRefinableObj::OnMenuFixAllPar(wxCommandEvent & WXUNUSED(event))
684 {
685  mpRefinableObj->FixAllPar();
686  this->CrystUpdate(true);
687 }
688 
689 void WXRefinableObj::OnMenuUnFixAllPar(wxCommandEvent & WXUNUSED(event))
690 {
691  mpRefinableObj->UnFixAllPar();
692  this->CrystUpdate(true);
693 }
694 
695 void WXRefinableObj::OnMenuParRandomize(wxCommandEvent & WXUNUSED(event))
696 {
697  (*fpObjCrystInformUser)("Randomizing object:"+mpRefinableObj->GetName());
698  Chronometer chrono;
699  chrono.start();
700  mpRefinableObj->RandomizeConfiguration();
701  this->CrystUpdate(true);
702  char buf [200];
703  sprintf(buf,"Finished randomizing object: %s, dt=%6.2fs",mpRefinableObj->GetName().c_str(),chrono.seconds());
704  (*fpObjCrystInformUser)(buf);
705 }
706 
707 void WXRefinableObj::OnUpdateUI(wxUpdateUIEvent& event)
708 {
709  this->UpdateUI(true);
710  event.Skip();
711 }
712 void WXRefinableObj::UpdateUI(const bool lock)
713 {
714  VFN_DEBUG_ENTRY("WXRefinableObj::UpdateUI("<<lock<<")"<<"MainThread="<<wxThread::IsMain()<<":"<<mpRefinableObj->GetName(),6)
715  if(!mpRefinableObj->IsBeingRefined())
716  {
717  if(lock) mMutex.Lock();
718  mpWXTitle->SetValue(mpRefinableObj->GetName());
719  mpWXTitle->UpdateUI(false);
720  //mpSizer->SetItemMinSize
721  // (mpWXTitle, mpWXTitle->GetSize().GetWidth(),mpWXTitle->GetSize().GetHeight());
722  //mpWXTitle->Layout();
723  if(lock) mMutex.Unlock();
724  }
725  this->WXCrystObj::UpdateUI(lock);
726  VFN_DEBUG_EXIT("WXRefinableObj::UpdateUI()"<<mpRefinableObj->GetName(),6)
727 }
728 
729 }// namespace
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: doc-main.h:25
void WXCrystValidateAllUserInput()
This function validates all user input (in a WXField) not yet taken into account, if needs be.
Definition: wxCryst.cpp:258
WXField * spLastWXFieldInputNotValidated
This pointer records the last wxField in which something was enetered, so that it can be validated wh...
Definition: wxCryst.cpp:256
T * WXDialogChooseFromRegistry(ObjRegistry< T > &reg, 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)
Base class for options.
Definition: RefinableObj.h:552
Object Registry.
Definition: RefinableObj.h:645
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.
Definition: Chronometer.h:35
CrystMutex mMutex
Mutex used to lock data when preparing to update the UI in non-main thread.
Definition: wxCryst.h:189
bool mNeedUpdateUI
Do we need to update the display ?
Definition: wxCryst.h:187
Base class for all displayed ObjCryst objects (with a title, and a sizer to stack objects).
Definition: wxCryst.h:249
WXFieldName * mpWXTitle
The title.
Definition: wxCryst.h:273
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: wxCryst.cpp:831
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
Definition: wxCryst.cpp:839
This is the abstract base class for all fields, wether they contain a floating-point parameter,...
Definition: wxCryst.h:292
wxStaticText * mpLabel
The label.
Definition: wxCryst.h:314
wxBoxSizer * mpSizer
The horizontal sizer in which the title, button, fields, are put.
Definition: wxCryst.h:312
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:472
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
Definition: wxCryst.cpp:496
const string GetValue() const
Get the current name.
Definition: wxCryst.cpp:486
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.