Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CPListFrame.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
27 #include "hugin_config.h"
28 #include "panoinc_WX.h"
29 #include "panoinc.h"
30 
31 #include <algorithm>
32 #include <utility>
33 #include <functional>
34 
35 #include "base_wx/wxPlatform.h"
36 #include "hugin/CPListFrame.h"
37 #include "hugin/MainFrame.h"
38 #include "base_wx/CommandHistory.h"
39 #include "base_wx/PanoCommand.h"
40 #include "base_wx/wxutils.h"
41 #include "hugin/huginApp.h"
42 #include "hugin/config_defaults.h"
45 
46 std::string makePairId(unsigned int id1, unsigned int id2)
47 {
48  // Control points from same image pair, regardless of which is left or right
49  // are counted the same so return the identical hash id.
50  std::ostringstream oss;
51 
52  if (id1 < id2) {
53  oss << id1 << "_" << id2;
54  }
55  else if (id2 < id1) {
56  oss << id2 << "_" << id1;
57  }
58  else {
59  // Control points are from same image.
60  oss << id1;
61  }
62  return oss.str();
63 }
64 
65 CPListCtrl::CPListCtrl() : m_pano(NULL)
66 {
67  m_sortCol = 0;
68  m_sortAscend = true;
69 };
70 
72 {
73  wxConfigBase* config = wxConfig::Get();
74  config->Write(wxT("/CPListFrame/SortColumn"), m_sortCol);
75  config->Write(wxT("/CPListFrame/SortAscending"), m_sortAscend ? 1 : 0);
76  config->Flush();
77  if (m_pano)
78  {
79  m_pano->removeObserver(this);
80  };
81 };
82 
83 bool CPListCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos,
84  const wxSize& size, long style, const wxValidator& validator, const wxString& name)
85 {
86  if (!wxListCtrl::Create(parent, id, pos, size, style))
87  {
88  return false;
89  };
90  InsertColumn(0, _("G CP#"), wxLIST_FORMAT_RIGHT, 25);
91  InsertColumn(1, _("Left Img."), wxLIST_FORMAT_RIGHT, 65);
92  InsertColumn(2, _("Right Img."), wxLIST_FORMAT_RIGHT, 65);
93  InsertColumn(3, _("P CP#"), wxLIST_FORMAT_RIGHT, 25);
94  InsertColumn(4, _("Alignment"), wxLIST_FORMAT_LEFT, 80);
95  InsertColumn(5, MainFrame::Get()->IsShowingCorrelation() ? _("Correlation") : _("Distance"), wxLIST_FORMAT_RIGHT, 80);
96 
97  //get saved width
98  for (int j = 0; j < GetColumnCount(); j++)
99  {
100  // -1 is auto
101  int width = wxConfigBase::Get()->Read(wxString::Format(wxT("/CPListFrame/ColumnWidth%d"), j), -1);
102  if (width != -1)
103  {
104  SetColumnWidth(j, width);
105  };
106  };
107  EnableAlternateRowColours(true);
108 
109  wxConfigBase* config = wxConfig::Get();
110  m_sortCol=config->Read(wxT("/CPListFrame/SortColumn"), 0l);
111  m_sortAscend = config->Read(wxT("/CPListFrame/SortAscending"), 1l) == 1;
112  config->Flush();
113  ShowSortIndicator(m_sortCol, m_sortAscend);
114  // bind event handler
115  Bind(wxEVT_CHAR, &CPListCtrl::OnChar, this);
116  Bind(wxEVT_LIST_ITEM_SELECTED, &CPListCtrl::OnCPListSelectionChanged, this);
117  Bind(wxEVT_LIST_ITEM_DESELECTED, &CPListCtrl::OnCPListSelectionChanged, this);
118  Bind(wxEVT_LIST_COL_CLICK, &CPListCtrl::OnCPListHeaderClick, this);
119  Bind(wxEVT_LIST_COL_END_DRAG, &CPListCtrl::OnColumnWidthChange, this);
120  return true;
121 };
122 
124 {
125  m_pano = pano;
126  m_pano->addObserver(this);
127  panoramaChanged(*pano);
128 };
129 
130 wxString CPListCtrl::OnGetItemText(long item, long column) const
131 {
132  if (item > m_internalCPList.size())
133  {
134  return wxEmptyString;
135  };
136  const HuginBase::ControlPoint& cp = m_pano->getCtrlPoint(m_internalCPList[item].globalIndex);
137  switch (column)
138  {
139  case 0:
140  return wxString::Format(wxT("%lu"), static_cast<unsigned long>(m_internalCPList[item].globalIndex));
141  break;
142  case 1:
143  return wxString::Format(wxT("%u"), cp.image1Nr);
144  break;
145  case 2:
146  return wxString::Format(wxT("%u"), cp.image2Nr);
147  break;
148  case 3:
149  return wxString::Format(wxT("%lu"), static_cast<unsigned long>(m_internalCPList[item].localNumber));
150  break;
151  case 4:
152  switch (cp.mode)
153  {
155  return wxString(_("normal"));
156  break;
158  return wxString(_("vert. Line"));
159  break;
161  return wxString(_("horiz. Line"));
162  break;
163  default:
164  return wxString::Format(_("Line %d"), cp.mode);
165  break;
166  };
167  break;
168  case 5:
169  return wxString::Format(wxT("%.2f"), cp.error);
170  break;
171  default:
172  return wxEmptyString;
173  };
174  return wxEmptyString;
175 };
176 
177 int CPListCtrl::OnGetItemImage(long item) const
178 {
179  return -1;
180 };
181 
183 {
185  const bool isShowingCorrelation = MainFrame::Get()->IsShowingCorrelation();
186  wxListItem item;
187  if (GetColumn(5, item))
188  {
189  if (isShowingCorrelation)
190  {
191  item.SetText(_("Correlation"));
192  }
193  else
194  {
195  item.SetText(_("Distance"));
196  }
197  SetColumn(5, item);
198  };
199  XRCCTRL(*GetParent(), "cp_list_select", wxButton)->SetLabel(isShowingCorrelation ? _("Select by Correlation") : _("Select by Distance"));
201  SetItemCount(m_internalCPList.size());
202  Refresh();
203 };
204 
206 {
207  const HuginBase::CPVector& cps = m_pano->getCtrlPoints();
208  const HuginBase::UIntSet activeImgs = m_pano->getActiveImages();
209  // Rebuild the global->local CP map on each update as CPs might have been
210  // removed.
211  m_localIds.clear();
212  m_internalCPList.clear();
213  m_internalCPList.reserve(cps.size());
214  for (size_t i = 0; i < cps.size(); i++)
215  {
216  const HuginBase::ControlPoint& cp = cps[i];
217  if (m_onlyActiveImages && (!set_contains(activeImgs, cp.image1Nr) || !set_contains(activeImgs, cp.image2Nr)))
218  {
219  continue;
220  };
221  CPListItem cpListItem;
222  cpListItem.globalIndex = i;
223  std::string pairId = makePairId(cp.image1Nr, cp.image2Nr);
224  std::map<std::string, int>::iterator it = m_localIds.find(pairId);
225  if (it != m_localIds.end())
226  {
227  ++(it->second);
228  }
229  else
230  {
231  m_localIds[pairId] = 0;
232  }
233  cpListItem.localNumber=m_localIds[pairId];
234  m_internalCPList.push_back(cpListItem);
235  };
236  SortInternalList(true);
237 };
238 
239 // sort helper function
240 // sort by global or local number only
241 #define CompareStruct(VAR, TYPESUFFIX, OP) \
242 struct Compare##TYPESUFFIX\
243 {\
244  bool operator()(const CPListItem& item1, const CPListItem& item2)\
245  {\
246  return item1.VAR OP item2.VAR;\
247  };\
248 };
249 CompareStruct(globalIndex, globalIndex, <)
250 CompareStruct(globalIndex, globalIndexGreater, >)
251 CompareStruct(localNumber, localNumber, <)
252 CompareStruct(localNumber, localNumberGreater, >)
253 #undef CompareStruct
254 
255 // sort by image number, take second image number as second criterion and local number as third
256 #define CompareStruct(VAR1, VAR2, TYPESUFFIX, OP)\
257 struct Compare##TYPESUFFIX\
258 {\
259  explicit Compare##TYPESUFFIX(const HuginBase::CPVector& cps) : m_cps(cps) {};\
260  bool operator()(const CPListItem& item1, const CPListItem& item2)\
261  {\
262  return m_cps[item1.globalIndex].VAR1 * 1e4 + m_cps[item1.globalIndex].VAR2 + item1.localNumber * 1.0 / m_cps.size() OP\
263  m_cps[item2.globalIndex].VAR1 * 1e4 + m_cps[item2.globalIndex].VAR2 + item2.localNumber * 1.0 / m_cps.size();\
264  }\
265 private:\
266  const HuginBase::CPVector& m_cps;\
267 };
268 CompareStruct(image1Nr, image2Nr, image1Nr, <)
269 CompareStruct(image1Nr, image2Nr, image1NrGreater, >)
270 CompareStruct(image2Nr, image1Nr, image2Nr, <)
271 CompareStruct(image2Nr, image1Nr, image2NrGreater, >)
272 #undef CompareStruct
273 
274 // sort by mode or error
275 #define CompareStruct(VAR, TYPESUFFIX, OP)\
276 struct Compare##TYPESUFFIX\
277 {\
278  explicit Compare##TYPESUFFIX(const HuginBase::CPVector& cps) : m_cps(cps) {};\
279  bool operator()(const CPListItem& item1, const CPListItem& item2)\
280  {\
281  return m_cps[item1.globalIndex].VAR OP m_cps[item2.globalIndex].VAR;\
282  }\
283 private:\
284  const HuginBase::CPVector& m_cps;\
285 };
286 CompareStruct(mode, mode, <)
287 CompareStruct(mode, modeGreater, >)
288 CompareStruct(error, error, <)
289 CompareStruct(error, errorGreater, >)
290 #undef CompareStruct
291 
292 void CPListCtrl::SortInternalList(bool isAscending)
293 {
294  // nothing to sort
295  if (m_internalCPList.empty())
296  {
297  return;
298  };
299 
300  switch (m_sortCol)
301  {
302  case 0:
303  if (m_sortAscend)
304  {
305  if (!isAscending)
306  {
307  std::sort(m_internalCPList.begin(), m_internalCPList.end(), CompareglobalIndex());
308  };
309  }
310  else
311  {
312  std::sort(m_internalCPList.begin(), m_internalCPList.end(), CompareglobalIndexGreater());
313  };
314  break;
315  case 1:
316  if (m_sortAscend)
317  {
318  std::sort(m_internalCPList.begin(), m_internalCPList.end(), Compareimage1Nr(m_pano->getCtrlPoints()));
319  }
320  else
321  {
322  std::sort(m_internalCPList.begin(), m_internalCPList.end(), Compareimage1NrGreater(m_pano->getCtrlPoints()));
323  };
324  break;
325  case 2:
326  if (m_sortAscend)
327  {
328  std::sort(m_internalCPList.begin(), m_internalCPList.end(), Compareimage2Nr(m_pano->getCtrlPoints()));
329  }
330  else
331  {
332  std::sort(m_internalCPList.begin(), m_internalCPList.end(), Compareimage2NrGreater(m_pano->getCtrlPoints()));
333  };
334  break;
335  case 3:
336  if (m_sortAscend)
337  {
338  std::sort(m_internalCPList.begin(), m_internalCPList.end(), ComparelocalNumber());
339  }
340  else
341  {
342  std::sort(m_internalCPList.begin(), m_internalCPList.end(), ComparelocalNumberGreater());
343  };
344  break;
345  case 4:
346  if (m_sortAscend)
347  {
348  std::sort(m_internalCPList.begin(), m_internalCPList.end(), Comparemode(m_pano->getCtrlPoints()));
349  }
350  else
351  {
352  std::sort(m_internalCPList.begin(), m_internalCPList.end(), ComparemodeGreater(m_pano->getCtrlPoints()));
353  };
354  break;
355  case 5:
356  if (m_sortAscend)
357  {
358  std::sort(m_internalCPList.begin(), m_internalCPList.end(), Compareerror(m_pano->getCtrlPoints()));
359  }
360  else
361  {
362  std::sort(m_internalCPList.begin(), m_internalCPList.end(), CompareerrorGreater(m_pano->getCtrlPoints()));
363  };
364  break;
365  };
366 };
367 
369 {
370  if (GetSelectedItemCount() == 1)
371  {
372  if (e.GetIndex() < m_internalCPList.size())
373  {
374  MainFrame::Get()->ShowCtrlPoint(m_internalCPList[e.GetIndex()].globalIndex);
375  };
376  };
377 };
378 
380 {
381  const int newCol = e.GetColumn();
382  if (m_sortCol == newCol)
383  {
385  }
386  else
387  {
388  m_sortCol = newCol;
389  m_sortAscend = true;
390  };
391  ShowSortIndicator(m_sortCol, m_sortAscend);
392  SortInternalList(false);
393  Refresh();
394 };
395 
397 {
398  const int colNum = e.GetColumn();
399  wxConfigBase::Get()->Write(wxString::Format(wxT("/CPListFrame/ColumnWidth%d"), colNum), GetColumnWidth(colNum));
400 };
401 
403 {
404  // no selected item.
405  const int nSelected = GetSelectedItemCount();
406  if (nSelected == 0)
407  {
408  wxBell();
409  return;
410  };
411 
412  HuginBase::UIntSet selected;
413  long item = GetFirstSelected();
414  long newSelection = -1;
415  if (m_internalCPList.size() - nSelected > 0)
416  {
417  newSelection = item;
418  if (item >= m_internalCPList.size() - nSelected)
419  {
420  newSelection = m_internalCPList.size() - nSelected - 1;
421  };
422  };
423  while (item>=0)
424  {
425  // deselect item
426  Select(item, false);
427  selected.insert(m_internalCPList[item].globalIndex);
428  item = GetNextSelected(item);
429  }
430  DEBUG_DEBUG("about to delete " << selected.size() << " points");
432 
433  if (newSelection >= 0)
434  {
435  MainFrame::Get()->ShowCtrlPoint(m_internalCPList[newSelection].globalIndex);
436  Select(newSelection, true);
437  };
438 };
439 
441 {
442  const bool invert = threshold < 0;
443  if (invert)
444  {
445  threshold = -threshold;
446  };
447  const HuginBase::CPVector& cps = m_pano->getCtrlPoints();
448  Freeze();
449  for (size_t i = 0; i < m_internalCPList.size(); i++)
450  {
451  const double error = cps[m_internalCPList[i].globalIndex].error;
452  Select(i, ((error > threshold) && (!invert)) || ((error < threshold) && (invert)));
453  };
454  Thaw();
455 };
456 
458 {
459  for (long i = 0; i < m_internalCPList.size(); i++)
460  {
461  Select(i, true);
462  };
463 };
464 
465 void CPListCtrl::OnChar(wxKeyEvent& e)
466 {
467  switch (e.GetKeyCode())
468  {
469  case WXK_DELETE:
470  case WXK_NUMPAD_DELETE:
471  DeleteSelected();
472  break;
473  case WXK_CONTROL_A:
474  SelectAll();
475  break;
476  default:
477  e.Skip();
478  };
479 };
480 
481 
483 
484 IMPLEMENT_DYNAMIC_CLASS(CPListCtrlXmlHandler, wxListCtrlXmlHandler)
485 
486 CPListCtrlXmlHandler::CPListCtrlXmlHandler()
487 : wxListCtrlXmlHandler()
488 {
489  AddWindowStyles();
490 }
491 
493 {
494  XRC_MAKE_INSTANCE(cp, CPListCtrl)
495  cp->Create(m_parentAsWindow, GetID(), GetPosition(), GetSize(), GetStyle(wxT("style")), wxDefaultValidator, GetName());
496  SetupWindow(cp);
497  return cp;
498 }
499 
500 bool CPListCtrlXmlHandler::CanHandle(wxXmlNode *node)
501 {
502  return IsOfClass(node, wxT("CPListCtrl"));
503 }
504 
505 CPListFrame::CPListFrame(wxWindow* parent, HuginBase::Panorama& pano) : m_pano(pano)
506 {
507  DEBUG_TRACE("");
508  bool ok = wxXmlResource::Get()->LoadDialog(this, parent, wxT("cp_list_frame"));
509  DEBUG_ASSERT(ok);
510  m_list = XRCCTRL(*this, "cp_list_frame_list", CPListCtrl);
512  m_list->Init(&m_pano);
513 
514  //set minumum size
515  SetSizeHints(200, 300);
516  //size
517  RestoreFramePosition(this, wxT("CPListFrame"));
518  Bind(wxEVT_CLOSE_WINDOW, &CPListFrame::OnClose, this);
519  Bind(wxEVT_BUTTON, &CPListFrame::OnDeleteButton, this, XRCID("cp_list_delete"));
520  Bind(wxEVT_BUTTON, &CPListFrame::OnSelectButton, this, XRCID("cp_list_select"));
521 }
522 
524 {
525  DEBUG_TRACE("dtor");
526  StoreFramePosition(this, wxT("CPListFrame"));
527  DEBUG_TRACE("dtor end");
528 }
529 
530 void CPListFrame::OnClose(wxCloseEvent& event)
531 {
532  DEBUG_DEBUG("OnClose");
534  DEBUG_DEBUG("closing");
535  Destroy();
536 }
537 
538 void CPListFrame::OnDeleteButton(wxCommandEvent & e)
539 {
541 }
542 
543 void CPListFrame::OnSelectButton(wxCommandEvent & e)
544 {
545  double threshold;
546  const bool isShowingCorrelation = MainFrame::Get()->IsShowingCorrelation();
547  if(isShowingCorrelation)
548  {
549  threshold = HUGIN_FT_CORR_THRESHOLD;
550  wxConfig::Get()->Read(wxT("/Finetune/CorrThreshold"), &threshold, HUGIN_FT_CORR_THRESHOLD);;
551  }
552  else
553  {
554  // calculate the mean error and the standard deviation
556  double min, max, mean, var;
558 
559  // select points whos distance is greater than the mean
560  // hmm, maybe some theory would be nice.. this is just a
561  // guess.
562  threshold = mean + sqrt(var);
563  };
564  wxString t;
565  do
566  {
567  t = wxGetTextFromUser(isShowingCorrelation ?
568  _("Enter minimum control point correlation.\nAll points with lower correlation will be selected.") :
569  _("Enter minimum control point error.\nAll points with a higher error will be selected"),
570  _("Select Control Points"),
571  hugin_utils::doubleTowxString(threshold, 2));
572  if (t == wxEmptyString) {
573  // do not select anything
574  return;
575  }
576  }
577  while (!hugin_utils::str2double(t, threshold));
578 
579  m_list->SelectDistanceThreshold(isShowingCorrelation ? -threshold : threshold);
580 };
const bool GetOptimizeOnlyActiveImages() const
Definition: MainFrame.cpp:1640
void OnColumnWidthChange(wxListEvent &e)
column width changed
void DeleteSelected()
Delete the selected points.
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxLC_REPORT|wxLC_VIRTUAL, const wxValidator &validator=wxDefaultValidator, const wxString &name=wxListCtrlNameStr)
Definition: CPListFrame.cpp:83
void UpdateInternalCPList()
helper class for virtual listview control
Definition: CPListFrame.h:33
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
virtual int OnGetItemImage(long item) const
show no images
std::vector< CPListItem > m_internalCPList
Definition: CPListFrame.h:87
#define DEBUG_TRACE(msg)
Definition: utils.h:67
CPListFrame(wxWindow *parent, HuginBase::Panorama &pano)
ctor.
int m_sortCol
Definition: CPListFrame.h:84
void OnDeleteButton(wxCommandEvent &e)
static void calcCtrlPntsErrorStats(const PanoramaData &pano, double &min, double &max, double &mean, double &var, const int &imgNr=-1, const bool onlyActive=false, const bool ignoreLineCp=false)
void Init(HuginBase::Panorama *pano)
void OnClose(wxCloseEvent &event)
void OnSelectButton(wxCommandEvent &e)
void SortInternalList(bool isAscending)
wxString doubleTowxString(double d, int digits)
Definition: wxPlatform.cpp:31
virtual wxString OnGetItemText(long item, long column) const
create labels for virtual list control
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
#define CompareStruct(VAR, TYPESUFFIX, OP)
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
include file for the hugin project
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition: Panorama.h:319
remove several control points
Definition: PanoCommand.h:307
represents a control point
Definition: ControlPoint.h:38
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
void OnChar(wxKeyEvent &e)
handle keystrokes
void ShowCtrlPoint(unsigned int cpNr)
Definition: MainFrame.cpp:2006
void calcCtrlPointErrors(PanoramaData &pano)
Update the Ctrl Point errors without optimizing.
Model for a panorama.
Definition: Panorama.h:152
void SelectAll()
select all items
List all control points of this project.
Definition: CPListFrame.h:43
static MainFrame * Get()
hack.. kind of a pseudo singleton...
Definition: MainFrame.cpp:2154
HuginBase::Panorama * m_pano
Definition: CPListFrame.h:82
void OnCPListFrameClosed()
Definition: MainFrame.cpp:1609
const ControlPoint & getCtrlPoint(std::size_t nr) const
get a control point, counting starts with 0
Definition: Panorama.h:312
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
evaluate x, points are on a vertical line
Definition: ControlPoint.h:47
xrc handler for CPImagesComboBox
Definition: CPListFrame.h:94
static GlobalCmdHist & getInstance()
void OnCPListSelectionChanged(wxListEvent &e)
selection event handler
size_t globalIndex
Definition: CPListFrame.h:35
virtual wxObject * DoCreateResource()
Create CPImagesComboBox from resource.
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Store window size and position in configfile/registry.
Definition: wxutils.cpp:133
virtual ~CPListFrame()
dtor.
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
bool m_sortAscend
Definition: CPListFrame.h:85
void SelectDistanceThreshold(double threshold)
select all cp with the given error bigger than the threshold
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
void OnCPListHeaderClick(wxListEvent &e)
sort criterium changed
Utility calls into PanoTools using CPP interface.
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition: threshold.h:41
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
CPListCtrl * m_list
Definition: CPListFrame.h:123
include file for the hugin project
#define HUGIN_FT_CORR_THRESHOLD
size_t localNumber
Definition: CPListFrame.h:36
static T max(T x, T y)
Definition: svm.cpp:65
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
std::string makePairId(unsigned int id1, unsigned int id2)
Definition: CPListFrame.cpp:46
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
platform/compiler specific stuff.
std::map< std::string, int > m_localIds
Definition: CPListFrame.h:88
bool m_onlyActiveImages
Definition: CPListFrame.h:86
virtual bool CanHandle(wxXmlNode *node)
Internal use to identify right xml handler.
bool IsShowingCorrelation() const
Definition: MainFrame.cpp:2170
virtual void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
evaluate y, points are on a horizontal line
Definition: ControlPoint.h:48
static T min(T x, T y)
Definition: svm.cpp:62
HuginBase::Panorama & m_pano
Definition: CPListFrame.h:124
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Restore window size and position from configfile/registry.
Definition: wxutils.cpp:65