Main MRPT website > C++ reference for MRPT 1.9.9
WxSubsystem.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "gui-precomp.h" // Precompiled headers
11 
12 #include <mrpt/config.h>
13 
17 
18 #include <mrpt/system/os.h>
19 
20 #include <mrpt/gui/WxSubsystem.h>
21 #include <mrpt/gui/WxUtils.h>
22 
23 //#define WXSUBSYSTEM_VERBOSE
24 
25 // ------------------------------------------------------------------------
26 // Defined: Try to wait for all windows & the thread to exit cleanly.
27 // Undefined: Just to a std::this_thread::sleep_for(ms) and quit crossing our
28 // fingers.
29 //
30 // Problem with the "clean way" is: As of feb/2011, I get this error
31 // at the end:
32 // ** (MRPT:11711): CRITICAL **: giop_thread_request_push: assertion `tdata !=
33 // NULL' failed
34 // ------------------------------------------------------------------------
35 //#define WXSHUTDOWN_DO_IT_CLEAN
36 
37 #if MRPT_HAS_WXWIDGETS
38 
39 using namespace mrpt;
40 using namespace mrpt::gui;
41 using namespace std;
42 
45 
46 std::queue<WxSubsystem::TRequestToWxMainThread*>*
48 std::mutex* WxSubsystem::cs_listPendingWxRequests = nullptr;
49 
51  nullptr;
52 bool isConsoleApp_value = true;
55 
56 // Auxiliary class implementation:
59 {
61  {
62 #ifdef WXSUBSYSTEM_VERBOSE
63  printf("[~CAuxWxSubsystemShutdowner] Sending 999...\n");
64 #endif
65  // Shut down:
66  try
67  {
70  REQ->OPCODE = 999;
72 
73  // std::this_thread::sleep_for(100ms); // JL: I found no better way
74  // of doing this, sorry :-( See
75  // WxSubsystem::waitWxShutdownsIfNoWindows()
77  }
78  catch (...)
79  {
80  } // Just in case we got an out-of-mem error.
81  } // is console app.
82 
83 #ifdef WXSUBSYSTEM_VERBOSE
84  printf("[~CAuxWxSubsystemShutdowner] Deleting static objects.\n");
85 #endif
86  // This is the final point where all dynamic memory must be deleted:
87  // delete &WxSubsystem::GetWxMainThreadInstance(); // may cause crashes at
88  // app end...
91 }
92 
93 // ---------------------------------------------------------------------------------------
94 // Auxiliary dialog class for the "ask user to open a camera":
95 // ---------------------------------------------------------------------------------------
96 class CDialogAskUserForCamera : public wxDialog
97 {
98  public:
100 
101  static const long ID_BTN_OK;
102  static const long ID_BTN_CANCEL;
103 
105  : wxDialog(
106  nullptr, wxID_ANY, wxT("Select image source"), wxDefaultPosition,
107  wxDefaultSize, wxDEFAULT_DIALOG_STYLE, wxDialogNameStr)
108  {
109  wxFlexGridSizer* f1 = new wxFlexGridSizer(2, 1, 0, 0);
110  panel = new mrpt::gui::CPanelCameraSelection(this, wxID_ANY);
111  f1->Add(
112  panel, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
113 
114  wxFlexGridSizer* f2 = new wxFlexGridSizer(1, 2, 0, 0);
115  wxButton* btnOk = new wxButton(
116  this, ID_BTN_OK, wxT("Ok"), wxDefaultPosition, wxDefaultSize);
117  wxButton* btnCancel = new wxButton(
118  this, ID_BTN_CANCEL, wxT("Cancel"), wxDefaultPosition,
119  wxDefaultSize);
120  f1->Add(f2, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
121 
122  f2->Add(
123  btnOk, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
124  f2->Add(
125  btnCancel, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL,
126  5);
127 
128  Connect(
129  ID_BTN_OK, wxEVT_COMMAND_BUTTON_CLICKED,
130  (wxObjectEventFunction)&CDialogAskUserForCamera::OnBtnOk);
131  Connect(
132  ID_BTN_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED,
133  (wxObjectEventFunction)&CDialogAskUserForCamera::OnBtnCancel);
134 
135  SetSizer(f1);
136  Fit();
137 
138  btnOk->SetFocus(); // So the default params can be accepted by just
139  // pressing ENTER.
140  }
141 
143  void OnBtnOk(wxCommandEvent& event) { EndModal(wxID_OK); }
144  void OnBtnCancel(wxCommandEvent& event) { EndModal(wxID_CANCEL); }
145 };
146 
147 const long CDialogAskUserForCamera::ID_BTN_OK = wxNewId();
148 const long CDialogAskUserForCamera::ID_BTN_CANCEL = wxNewId();
149 
150 // ---------------------------------------------------------------------------------------
151 // The wx dummy frame:
152 // ---------------------------------------------------------------------------------------
153 BEGIN_EVENT_TABLE(WxSubsystem::CWXMainFrame, wxFrame)
154 
155 END_EVENT_TABLE()
156 
157 const long ID_TIMER_WX_PROCESS_REQUESTS = wxNewId();
158 
159 WxSubsystem::CWXMainFrame::CWXMainFrame(wxWindow* parent, wxWindowID id)
160 {
161  Create(
162  parent, id, _("MRPT-dummy frame window"), wxDefaultPosition,
163  wxSize(1, 1),
164  0, // wxDEFAULT_FRAME_STYLE,
165  _T("id"));
166 
167  if (oneInstance)
168  {
169  cerr << "[CWXMainFrame] More than one instance running!" << endl;
170  }
171  oneInstance = this;
172 
173  // ------------------------------------------------------------------------------------------
174  // Create a timer so requests from the main application thread can be
175  // processed regularly:
176  // ------------------------------------------------------------------------------------------
177  Connect(
178  ID_TIMER_WX_PROCESS_REQUESTS, wxEVT_TIMER,
179  (wxObjectEventFunction)&CWXMainFrame::OnTimerProcessRequests);
180  m_theTimer = new wxTimer(this, ID_TIMER_WX_PROCESS_REQUESTS);
181 
182  m_theTimer->Start(10, true); // One-shot
183 }
184 
186 {
187 #ifdef WXSUBSYSTEM_VERBOSE
188  cout << "[CWXMainFrame] Destructor." << endl;
189 #endif
190  delete m_theTimer;
191  oneInstance = nullptr;
192 
193  // Purge all pending requests:
195  while (nullptr != (msg = popPendingWxRequest())) delete[] msg;
196 }
197 
199 {
200  std::lock_guard<std::mutex> lock(cs_windowCount);
201  return ++m_windowCount;
202 }
203 
205 {
206  int ret;
207  {
208  std::lock_guard<std::mutex> lock(cs_windowCount);
209  ret = --m_windowCount;
210  }
211 
212  if (ret == 0)
213  {
214  // That was the last window... we should close the wx subsystem:
215  if (oneInstance)
216  {
217 #ifdef WXSHUTDOWN_DO_IT_CLEAN
218  CWXMainFrame* me =
219  (CWXMainFrame*)(oneInstance); // cast away the "volatile".
220  me->Close();
221 #endif
222 
223 #ifdef WXSUBSYSTEM_VERBOSE
224  cout << "[CWXMainFrame::notifyWindowDestruction] numWindows=0. "
225  "me->Close() called."
226  << endl;
227 #endif
228  }
229  }
230 
231  return ret;
232 }
233 
234 /** Thread-safe method to return the next pending request, or nullptr if there
235  * is none (After usage, FREE the memory!)
236  */
238 {
239  if (!cs_listPendingWxRequests)
240  {
241  cs_listPendingWxRequests = new std::mutex();
242  listPendingWxRequests = new std::queue<TRequestToWxMainThread*>;
243  }
244 
245  std::lock_guard<std::mutex> locker(*cs_listPendingWxRequests);
246 
247  // Is empty?
248  if (listPendingWxRequests->empty()) return nullptr;
249 
250  TRequestToWxMainThread* ret = listPendingWxRequests->front();
251  listPendingWxRequests->pop(); // Remove from the queue
252 
253  return ret;
254 }
255 
256 /** Thread-safe method to insert a new pending request (The memory must be
257  * dinamically allocated with "new T[1]", will be freed by receiver.)
258  */
261 {
263  {
264 #ifdef WXSUBSYSTEM_VERBOSE
265  cout << "[WxSubsystem::pushPendingWxRequest] IGNORING request since "
266  "app seems already closed.\n";
267 #endif
268  delete[] data;
269  return; // wx subsystem already closed, ignore.
270  }
271 
272  if (!cs_listPendingWxRequests)
273  {
274  cs_listPendingWxRequests = new std::mutex();
275  listPendingWxRequests = new std::queue<TRequestToWxMainThread*>;
276  }
277 
278  std::lock_guard<std::mutex> locker(*cs_listPendingWxRequests);
279  listPendingWxRequests->push(data);
280 }
281 
282 /** This method processes the pending requests from the main MRPT application
283  * thread.
284  * The requests may be to create a new window, close another one, change
285  * title, etc...
286  */
288 {
289  bool app_closed = false;
290  try
291  {
293 
294 #ifdef WXSUBSYSTEM_VERBOSE
295  cout << "[OnTimerProcessRequests] Entering" << endl;
296 #endif
297 
298  // For each pending request:
299  while (nullptr != (msg = popPendingWxRequest()))
300  {
301  // Process it:
302  switch (msg->OPCODE)
303  {
304  // CREATE NEW WINDOW
305  case 200:
306  if (msg->source2D)
307  {
308  CWindowDialog* wnd = new CWindowDialog(
309  msg->source2D, this, (wxWindowID)-1, msg->str,
310  wxSize(msg->x, msg->y));
311 
312  // Set the "m_hwnd" member of the window:
313  *((void**)msg->voidPtr) = (void*)wnd;
314 
315  // Signal to the constructor (still waiting) that the
316  // window is now ready so it can continue:
318 
319  wnd->Show();
320  }
321  break;
322  // UPDATE IMAGE
323  case 201:
324  if (msg->source2D)
325  {
326  CWindowDialog* wnd =
327  (CWindowDialog*)
328  msg->voidPtr; // msg->source2D->getWxObject();
329  if (!wnd) break;
330  wxImage* img = (wxImage*)msg->voidPtr2;
331  if (!img) break;
332 
333  wnd->m_image->AssignImage(
334  new wxBitmap(
335  *img)); // Memory will be freed by the object.
336 
337  if (wnd->m_image->GetSize().GetX() != img->GetWidth() &&
338  wnd->m_image->GetSize().GetY() != img->GetHeight())
339  {
340  wnd->m_image->SetSize(
341  img->GetWidth(), img->GetHeight());
342  wnd->m_image->SetMinSize(
343  wxSize(img->GetWidth(), img->GetHeight()));
344  wnd->m_image->SetMaxSize(
345  wxSize(img->GetWidth(), img->GetHeight()));
346  wnd->Fit();
347  // wnd->SetClientSize(img->GetWidth(),
348  // img->GetHeight());
349  }
350  delete img;
351  wnd->m_image->Refresh(false); // false: Do NOT erase
352  // background: avoid
353  // flickering
354  }
355  break;
356  // Set position
357  case 202:
358  if (msg->source2D)
359  {
360  CWindowDialog* wnd =
362  if (wnd)
363  wnd->SetSize(
364  msg->x, msg->y, wxDefaultCoord, wxDefaultCoord);
365  }
366  break;
367  // Set size
368  case 203:
369  if (msg->source2D)
370  {
371  CWindowDialog* wnd =
373  if (wnd) wnd->SetClientSize(msg->x, msg->y);
374  }
375  break;
376  // Set window's title:
377  case 204:
378  if (msg->source2D)
379  {
380  CWindowDialog* wnd =
382  if (wnd) wnd->SetTitle(_U(msg->str.c_str()));
383  }
384  break;
385  // DESTROY EXISTING WINDOW:
386  case 299:
387  if (msg->source2D)
388  {
389  CWindowDialog* wnd =
391  if (wnd)
392  {
393  // delete wnd;
394  wnd->Close();
395  }
396  }
397  break;
398 
399  // CREATE NEW WINDOW
400  case 300:
401  if (msg->source3D)
402  {
403  C3DWindowDialog* wnd = new C3DWindowDialog(
404  msg->source3D, this, (wxWindowID)-1, msg->str,
405  wxSize(msg->x, msg->y));
406 
407  // Set the "m_hwnd" member of the window:
408  *((void**)msg->voidPtr) = (void*)wnd;
409 
410  // Signal to the constructor (still waiting) that the
411  // window is now ready so it can continue:
413 
414  wnd->Show();
415  }
416  break;
417  // Set position
418  case 302:
419  if (msg->source3D)
420  {
421  C3DWindowDialog* wnd =
423  if (wnd)
424  wnd->SetSize(
425  msg->x, msg->y, wxDefaultCoord, wxDefaultCoord);
426  }
427  break;
428  // Set size
429  case 303:
430  if (msg->source3D)
431  {
432  C3DWindowDialog* wnd =
434  if (wnd) wnd->SetClientSize(msg->x, msg->y);
435  }
436  break;
437  // Set window's title:
438  case 304:
439  if (msg->source3D)
440  {
441  C3DWindowDialog* wnd =
443  if (wnd) wnd->SetTitle(_U(msg->str.c_str()));
444  }
445  break;
446  // FORCE REPAINT
447  case 350:
448  if (msg->source3D)
449  {
450  C3DWindowDialog* wnd =
452  if (wnd)
453  {
454  wnd->Refresh(false);
455  }
456  }
457  break;
458  // Add a 2D text message: vector_x: [0]:x, [1]:y, [2,3,4]:R G B,
459  // "x": enum of desired font. "y": unique index, "str": String.
460  case 360:
461  if (msg->source3D)
462  {
463  C3DWindowDialog* wnd =
465  if (wnd)
466  {
467  wnd->addTextMessage(
468  msg->vector_x[0], msg->vector_x[1], msg->str,
470  msg->vector_x[2], msg->vector_x[3],
471  msg->vector_x[4]),
472  size_t(msg->y),
474  }
475  }
476  break;
477  // Clear 2D text messages
478  case 361:
479  if (msg->source3D)
480  {
481  C3DWindowDialog* wnd =
483  if (wnd)
484  {
485  wnd->clearTextMessages();
486  }
487  }
488  break;
489  // Add a 2D text message: vector_x: [0]:x, [1]:y, [2,3,4]:R G B,
490  // "x": enum of desired font. "y": unique index, "str": String.
491  case 362:
492  if (msg->source3D)
493  {
494  C3DWindowDialog* wnd =
496  if (wnd)
497  {
498  wnd->addTextMessage(
499  msg->vector_x[0], msg->vector_x[1], msg->str,
501  msg->vector_x[2], msg->vector_x[3],
502  msg->vector_x[4]),
503  msg->plotName, msg->vector_x[5],
505  size_t(msg->y), msg->vector_x[6],
506  msg->vector_x[7], msg->vector_x[8] != 0,
508  msg->vector_x[9], msg->vector_x[10],
509  msg->vector_x[11]));
510  }
511  }
512  break;
513 
514  // DESTROY EXISTING WINDOW:
515  case 399:
516  if (msg->source3D)
517  {
518  C3DWindowDialog* wnd =
520  if (wnd)
521  {
522  // delete wnd;
523  wnd->Close();
524  }
525  }
526  break;
527 
528  // CREATE NEW WINDOW
529  case 400:
530  if (msg->sourcePlots)
531  {
533  msg->sourcePlots, this, (wxWindowID)-1, msg->str,
534  wxSize(msg->x, msg->y));
535 
536  // Set the "m_hwnd" member of the window:
537  *((void**)msg->voidPtr) = (void*)wnd;
538 
539  // Signal to the constructor (still waiting) that the
540  // window is now ready so it can continue:
542 
543  wnd->Show();
544  }
545  break;
546  // Set position
547  case 402:
548  if (msg->sourcePlots)
549  {
550  CWindowDialogPlots* wnd =
552  msg->sourcePlots->getWxObject();
553  if (wnd)
554  wnd->SetSize(
555  msg->x, msg->y, wxDefaultCoord, wxDefaultCoord);
556  }
557  break;
558  // Set size
559  case 403:
560  if (msg->sourcePlots)
561  {
562  CWindowDialogPlots* wnd =
564  msg->sourcePlots->getWxObject();
565  if (wnd) wnd->SetClientSize(msg->x, msg->y);
566  }
567  break;
568  // Set window's title:
569  case 404:
570  if (msg->sourcePlots)
571  {
572  CWindowDialogPlots* wnd =
574  msg->sourcePlots->getWxObject();
575  if (wnd) wnd->SetTitle(_U(msg->str.c_str()));
576  }
577  break;
578  // Mouse pan
579  case 410:
580  if (msg->sourcePlots)
581  {
582  CWindowDialogPlots* wnd =
584  msg->sourcePlots->getWxObject();
585  if (wnd) wnd->m_plot->EnableMousePanZoom(msg->boolVal);
586  }
587  break;
588  // Aspect ratio
589  case 411:
590  if (msg->sourcePlots)
591  {
592  CWindowDialogPlots* wnd =
594  msg->sourcePlots->getWxObject();
595  if (wnd) wnd->m_plot->LockAspect(msg->boolVal);
596  }
597  break;
598 
599  // Zoom over a rectangle vectorx[0-1] & vectory[0-1]
600  case 412:
601  if (msg->sourcePlots)
602  {
603  CWindowDialogPlots* wnd =
605  msg->sourcePlots->getWxObject();
606  if (wnd)
607  {
608  if (msg->vector_x.size() == 2 &&
609  msg->vector_y.size() == 2)
610  {
611  wnd->m_plot->Fit(
612  msg->vector_x[0], msg->vector_x[1],
613  msg->vector_y[0], msg->vector_y[1]);
614  wnd->m_plot->LockAspect(msg->boolVal);
615  }
616  }
617  }
618  break;
619  // Axis fit, with aspect ratio fix to boolVal.
620  case 413:
621  if (msg->sourcePlots)
622  {
623  CWindowDialogPlots* wnd =
625  msg->sourcePlots->getWxObject();
626  if (wnd)
627  {
628  wnd->m_plot->LockAspect(msg->boolVal);
629  wnd->m_plot->Fit();
630  }
631  }
632  break;
633  // Clear all objects:
634  case 414:
635  if (msg->sourcePlots)
636  {
637  CWindowDialogPlots* wnd =
639  msg->sourcePlots->getWxObject();
640  if (wnd)
641  {
642  wnd->m_plot->DelAllLayers(true, true);
643  wnd->m_plot->AddLayer(new mpScaleX());
644  wnd->m_plot->AddLayer(new mpScaleY());
645  }
646  }
647  break;
648 
649  // Create/modify 2D plot
650  case 420:
651  if (msg->sourcePlots)
652  {
653  CWindowDialogPlots* wnd =
655  msg->sourcePlots->getWxObject();
656  if (wnd)
657  wnd->plot(
658  msg->vector_x, msg->vector_y, msg->str,
659  msg->plotName);
660  }
661  break;
662 
663  // Create/modify 2D ellipse
664  case 421:
665  if (msg->sourcePlots)
666  {
667  CWindowDialogPlots* wnd =
669  msg->sourcePlots->getWxObject();
670  if (wnd)
671  wnd->plotEllipse(
672  msg->vector_x, msg->vector_y, msg->str,
673  msg->plotName, msg->boolVal);
674  }
675  break;
676 
677  // Create/modify bitmap image
678  case 422:
679  if (msg->sourcePlots)
680  {
681  CWindowDialogPlots* wnd =
683  msg->sourcePlots->getWxObject();
684  if (wnd)
685  wnd->image(
686  msg->voidPtr2, msg->vector_x[0],
687  msg->vector_x[1], msg->vector_x[2],
688  msg->vector_x[3], msg->plotName);
689  }
690  break;
691 
692  // 440: Insert submenu in the popup menu. name=menu label, x=ID
693  case 440:
694  if (msg->sourcePlots)
695  {
696  CWindowDialogPlots* wnd =
698  msg->sourcePlots->getWxObject();
699  if (wnd)
700  {
701  const long MENUITEM_ID = wxNewId();
702  // Remember the association between this ID and the
703  // user ID:
704  wnd->m_ID2ID[MENUITEM_ID] = msg->x;
705 
706  wxMenu* popupMnu = wnd->m_plot->GetPopupMenu();
707  if (wnd->m_firstSubmenu)
708  {
709  wnd->m_firstSubmenu = false;
710  popupMnu->InsertSeparator(0);
711  }
712  wxMenuItem* mnuTarget = new wxMenuItem(
713  popupMnu, MENUITEM_ID,
714  _U(msg->plotName.c_str()), wxEmptyString,
715  wxITEM_NORMAL);
716  popupMnu->Insert(0, mnuTarget);
717 
718  wnd->Connect(
719  MENUITEM_ID, wxEVT_COMMAND_MENU_SELECTED,
720  (wxObjectEventFunction)&CWindowDialogPlots::
721  OnMenuSelected);
722  }
723  }
724  break;
725 
726  // DESTROY EXISTING WINDOW:
727  case 499:
728  if (msg->sourcePlots)
729  {
730  CWindowDialogPlots* wnd =
732  msg->sourcePlots->getWxObject();
733  if (wnd)
734  {
735  // delete wnd;
736  wnd->Close();
737  }
738  }
739  break;
740 
741  // CREATE NEW WINDOW
742  case 700:
743  if (msg->sourceCameraSelectDialog)
744  {
745  std::promise<void>* sem =
746  reinterpret_cast<std::promise<void>*>(msg->voidPtr);
747 
750  // Signal that the window is ready:
751  sem->set_value();
752 
753  // Show
754  const bool wasOk = (dlg->ShowModal() == wxID_OK);
755 
756  // send selection to caller:
757  std::promise<
759  promise = reinterpret_cast<std::promise<
761  msg->voidPtr2);
763 
764  // Parse selection as a config text block:
765  dlg->panel->writeConfigFromVideoSourcePanel(
766  "CONFIG", &ret.selectedConfig);
767  ret.accepted_by_user = wasOk;
768 
769  promise->set_value(ret);
770 
771  delete dlg;
772 
773  sem->set_value();
774  }
775  break;
776 
777  // wxSubsystem shutdown:
778  case 999:
779  {
780 #ifdef WXSUBSYSTEM_VERBOSE
781  cout << "[WxSubsystem:999] Shutdown" << endl;
782 #endif
783  app_closed = true; // Do NOT launch a timer again
785  ((WxSubsystem::
787  ->Close();
788 #ifdef WXSUBSYSTEM_VERBOSE
789  cout << "[WxSubsystem:999] Shutdown done" << endl;
790 #endif
791  }
792  break;
793 
794  } // end switch OPCODE
795 
796  // Free the memory:
797  delete[] msg;
798  } // end while
799  }
800  catch (...)
801  {
802  }
803 
804  if (!app_closed) m_theTimer->Start(10, true); // One-shot
805 }
806 
807 // ---------------------------------------------------------------------------------------
808 // MRPT Icons
809 // ---------------------------------------------------------------------------------------
810 const char* mrpt_default_icon_xpm[] = {"32 32 2 1",
811  " c None",
812  ". c #000000",
813  " ",
814  " ",
815  " ",
816  " ..... ..... ......... ",
817  " .... .... ... .... ",
818  " ..... .... ... ... ",
819  " . ... . ... ... ... ",
820  " . ... . ... ... ... ",
821  " . ... . ... ... ... ",
822  " . ... . ... ........ ",
823  " . ..... ... ... .... ",
824  " . ... ... ... .... ",
825  " . ... ... ... .... ",
826  " . .. ... ... .... ",
827  " ... . ..... ..... ..... ",
828  " ",
829  " ",
830  " ........ ........... ",
831  " ... .... .. ... .. ",
832  " ... ... . ... . ",
833  " ... ... ... ",
834  " ... ... ... ",
835  " ... ... ... ",
836  " ....... ... ",
837  " ... ... ",
838  " ... ... ",
839  " ... ... ",
840  " ... ... ",
841  " ..... ..... ",
842  " ",
843  " ",
844  " "};
845 
847 {
848 // To avoid an error in wx, always resize the icon to the expected size:
849 #ifdef _WIN32
850  const wxSize iconsSize(
851  ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
852  return wxBitmap(
853  wxBitmap(mrpt_default_icon_xpm)
854  .ConvertToImage()
855  .Scale(iconsSize.x, iconsSize.y));
856 #else
857  return wxBitmap(mrpt_default_icon_xpm);
858 #endif
859 }
860 
861 // ---------------------------------------------------------------------------------------
862 // The wx app:
863 // ---------------------------------------------------------------------------------------
864 class CDisplayWindow_WXAPP : public wxApp
865 {
866  public:
867  virtual bool OnInit();
868  virtual int OnExit();
869 };
870 
872 {
873  // Starting in wxWidgets 2.9.0, we must reset numerics locale to "C",
874  // if we want numbers to use "." in all countries. The App::OnInit() is a
875  // perfect place to undo
876  // the default wxWidgets settings. (JL @ Sep-2009)
877  wxSetlocale(LC_NUMERIC, wxString(wxT("C")));
878 
879  wxInitAllImageHandlers();
880 
881  // cout << "[wxApp::OnInit] wxApplication OnInit called." << endl;
882 
883  // Create a dummy frame:
885  Frame->Hide();
886 
887  // We are ready!!
888  // cout << "[wxMainThread] Signaling semaphore." << endl;
890 
891  return true;
892 }
893 
894 // This will be called when all the windows / frames are closed.
896 {
897 #ifdef WXSUBSYSTEM_VERBOSE
898  cout << "[wxApp::OnExit] wxApplication OnExit called." << endl;
899 #endif
900 
901  std::lock_guard<std::mutex> lock(
902  WxSubsystem::GetWxMainThreadInstance().m_csWxMainThreadId);
903 
904  wxApp::OnExit();
905  CleanUp();
906  return 0;
907 }
908 
909 /** This method must be called in the destructor of the user class FROM THE MAIN
910  * THREAD, in order to wait for the shutdown of the wx thread if this was the
911  * last open window.
912  */
914 {
915 #ifndef WXSHUTDOWN_DO_IT_CLEAN
916 
917 #ifdef WXSUBSYSTEM_VERBOSE
918  cout << "[WxSubsystem::waitWxShutdownsIfNoWindows] Doing a quick "
919  "std::this_thread::sleep_for(ms) and returning.\n";
920 #endif
921  std::this_thread::sleep_for(100ms);
922  return;
923 #else
924  // Just let know a global object that, at its destruction, it must ....
925  // Any open windows?
926  int nOpenWnds;
927  {
928  std::lock_guard<std::mutex> lock(CWXMainFrame::cs_windowCount);
929  nOpenWnds = CWXMainFrame::m_windowCount;
930  }
931 
932  if (!nOpenWnds && WxSubsystem::isConsoleApp())
933  {
934 #ifdef WXSUBSYSTEM_VERBOSE
935  cout << "[WxSubsystem::waitWxShutdownsIfNoWindows] Waiting for "
936  "WxWidgets thread to shutdown...\n";
937 #endif
938 
939  // Then we must be shutting down in the wx thread (we are in the main
940  // MRPT application thread)...
941  // Wait until wx is safely shut down:
942  bool done = false;
943  int maxTimeout =
944 #ifdef _DEBUG
945  30000;
946 #else
947  5000;
948 #endif
949  if (m_done.wait_for(std::chrono::milliseconds(maxTimeout)) ==
950  std::future_status::timeout)
951  {
952  cerr << "[WxSubsystem::waitWxShutdownsIfNoWindows] Timeout waiting "
953  "for WxWidgets thread to shutdown!"
954  << endl;
955  }
956  }
957 #endif
958 }
959 
960 wxAppConsole* mrpt_wxCreateApp()
961 {
962  wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "your program");
963  return new CDisplayWindow_WXAPP;
964 }
965 
966 // DECLARE_APP(CDisplayWindow_WXAPP)
968 
969 // Aux. funcs used in WxSubsystem::wxMainThread
970 // --------------------------------------------------
971 int mrpt_wxEntryReal(int argc, char** argv)
972 {
973  // library initialization
974  if (!wxEntryStart(argc, argv))
975  {
976 #if wxUSE_LOG
977  // flush any log messages explaining why we failed
978  delete wxLog::SetActiveTarget(nullptr);
979 #endif
980  return -1;
981  }
982 
983  // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
984  // below returns or throws
985  try
986  {
987  // app initialization
988  if (!wxTheApp->CallOnInit())
989  return -1; // don't call OnExit() if OnInit() failed
990 
991  // app execution
992  int ret = wxTheApp->OnRun();
993 
994  {
995  wxLogNull logNo; // Skip any warning in this scope.
996 
997  wxTheApp->OnExit(); // This replaces the above callOnExit class
998  wxEntryCleanup();
999  }
1000 
1001  return ret;
1002  }
1003  catch (...)
1004  {
1005  wxTheApp->OnUnhandledException();
1006  wxEntryCleanup();
1007  return -1;
1008  }
1009 }
1010 
1011 /*---------------------------------------------------------------
1012  wxMainThread
1013  This will be the "MAIN" of wxWidgets: It starts an application
1014  object and does not end until all the windows are closed.
1015  Only for console apps, not for user GUI apps already with wx.
1016  ---------------------------------------------------------------*/
1018 {
1019  MRPT_START
1020 
1021  // Prepare wxWidgets:
1022  int argc = 1;
1023  static const char* dummy_prog_name = "./MRPT";
1024  char* argv[2] = {const_cast<char*>(dummy_prog_name), nullptr};
1025 
1026 #ifdef WXSUBSYSTEM_VERBOSE
1027  cout << "[wxMainThread] Starting..." << endl;
1028 #endif
1029 
1030  // Are we in a console or wxGUI application????
1031  wxAppConsole* app_gui = wxApp::GetInstance();
1032  if (!app_gui)
1033  {
1034 // We are NOT in a wx application (it's a console program)
1035 // ---------------------------------------------------------
1036 #ifdef WXSUBSYSTEM_VERBOSE
1037  cout << "[wxMainThread] I am in a console app" << endl;
1038 #endif
1039  // Start a new wx application object:
1040 
1041  // JLBC OCT2008: wxWidgets little hack to enable console/gui mixed
1042  // applications:
1043  wxApp::SetInitializerFunction(
1044  (wxAppInitializerFunction)mrpt_wxCreateApp);
1045  mrpt_wxEntryReal(argc, argv);
1046 
1047 #ifdef WXSUBSYSTEM_VERBOSE
1048  cout << "[wxMainThread] Finished" << endl;
1049 #endif
1050 
1051  // Now this thread is ready. The main thread is free to end now:
1053  }
1054  else
1055  {
1056 // We are ALREADY in a wx application:
1057 // ---------------------------------------------------------
1058 #ifdef WXSUBSYSTEM_VERBOSE
1059  cout << "[wxMainThread] I am in a GUI app" << endl;
1060 #endif
1061  wxWindow* topWin = static_cast<wxApp*>(app_gui)->GetTopWindow();
1062 
1063  WxSubsystem::CWXMainFrame* Frame =
1064  new WxSubsystem::CWXMainFrame(topWin);
1065  Frame->Hide();
1066 
1067 // We are ready!!
1068 #ifdef WXSUBSYSTEM_VERBOSE
1069  cout << "[wxMainThread] Signaling semaphore." << endl;
1070 #endif
1072  .m_semWxMainThreadReady.set_value();
1073  }
1074 
1075  MRPT_END
1076 }
1077 
1079 {
1080  // static TWxMainThreadData dat;
1081  // Create as dynamic memory, since it'll be deleted in
1082  // CAuxWxSubsystemShutdowner:
1083  static TWxMainThreadData* dat = nullptr;
1084  static bool first_creat = true;
1085  if (!dat && first_creat)
1086  {
1087  first_creat = false;
1088  dat = new TWxMainThreadData;
1089  }
1090  return *dat;
1091 }
1092 
1093 /*---------------------------------------------------------------
1094  createOneInstanceMainThread
1095  ---------------------------------------------------------------*/
1097 {
1100  std::lock_guard<std::mutex> lock(wxmtd.m_csWxMainThreadId);
1101 
1102  wxAppConsole* app_con = wxApp::GetInstance();
1103  if (app_con && wxmtd.m_wxMainThreadId.get_id() == std::thread::id())
1104  {
1105  // We are NOT in a console application: There is already a wxApp
1106  // instance running and it's not us.
1107  isConsoleApp_value = false;
1108  // cout << "[createOneInstanceMainThread] Mode: User GUI." << endl;
1110  {
1111  // Create our main hidden frame:
1112  wxWindow* topWin = static_cast<wxApp*>(app_con)->GetTopWindow();
1113 
1114  WxSubsystem::CWXMainFrame* Frame =
1115  new WxSubsystem::CWXMainFrame(topWin);
1116  // Frame->Show();
1117  // SetTopWindow(Frame);
1118  Frame->Hide();
1119  }
1120  }
1121  else
1122  {
1123  // cout << "[createOneInstanceMainThread] Mode: Console." << endl;
1124  isConsoleApp_value = true;
1125  if (wxmtd.m_wxMainThreadId.get_id() == std::thread::id())
1126  {
1127 #ifdef WXSUBSYSTEM_VERBOSE
1128  printf(
1129  "[WxSubsystem::createOneInstanceMainThread] Launching "
1130  "wxMainThread() thread...\n");
1131 #endif
1132  // Create a thread for message processing there:
1133  wxmtd.m_wxMainThreadId = std::thread(wxMainThread);
1134 
1135  int maxTimeout =
1136 #ifdef _DEBUG
1137  30000;
1138 #else
1139  5000;
1140 #endif
1141 
1142  // If we have an "MRPT_WXSUBSYS_TIMEOUT_MS" environment variable,
1143  // use that timeout instead:
1144  const char* envVal = getenv("MRPT_WXSUBSYS_TIMEOUT_MS");
1145  if (envVal) maxTimeout = atoi(envVal);
1146 
1147  if (wxmtd.m_semWxMainThreadReady.get_future().wait_for(
1148  std::chrono::milliseconds(maxTimeout)) ==
1149  std::future_status::timeout) // A few secs should be enough...
1150  {
1151  cerr << "[WxSubsystem::createOneInstanceMainThread] Timeout "
1152  "waiting wxApplication to start up!"
1153  << endl;
1154  return false;
1155  }
1156  }
1157  }
1158 
1159  return true; // OK
1160 }
1161 
1162 #endif // MRPT_HAS_WXWIDGETS
mrpt::opengl::TOpenGLFont
TOpenGLFont
Existing fonts for 2D texts in mrpt::opengl methods.
Definition: opengl_fonts.h:25
mrpt_default_icon_xpm
const char * mrpt_default_icon_xpm[]
Definition: WxSubsystem.cpp:810
os.h
mrpt::gui::WxSubsystem::TRequestToWxMainThread::sourcePlots
mrpt::gui::CDisplayWindowPlots * sourcePlots
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:217
mrpt::gui::WxSubsystem::TRequestToWxMainThread::voidPtr
void * voidPtr
Parameters, depending on OPCODE.
Definition: WxSubsystem.h:229
mrpt_wxEntryReal
int mrpt_wxEntryReal(int argc, char **argv)
Definition: WxSubsystem.cpp:971
mrpt::gui::CPanelCameraSelection
A panel to select the camera input from all the formats supported by MRPT.
Definition: WxUtils.h:171
mrpt::gui::WxSubsystem::createOneInstanceMainThread
static bool createOneInstanceMainThread()
Thread-safe method to create one single instance of the main wxWidgets thread: it will create the thr...
Definition: WxSubsystem.cpp:1096
mrpt::gui::CWindowDialog
The wx dialog for gui::CDisplayWindow.
Definition: WxSubsystem.h:331
CDialogAskUserForCamera::CDialogAskUserForCamera
CDialogAskUserForCamera()
Definition: WxSubsystem.cpp:104
CDialogAskUserForCamera::ID_BTN_CANCEL
static const long ID_BTN_CANCEL
Definition: WxSubsystem.cpp:102
mrpt::opengl::TOpenGLFontStyle
TOpenGLFontStyle
Different style for vectorized font rendering.
Definition: opengl_fonts.h:36
mrpt::gui::WxSubsystem::pushPendingWxRequest
static void pushPendingWxRequest(TRequestToWxMainThread *data)
Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "ne...
Definition: WxSubsystem.cpp:259
WxSubsystem.h
mrpt::gui::detail::TReturnAskUserOpenCamera
Definition: WxUtils.h:295
CDialogAskUserForCamera::panel
mrpt::gui::CPanelCameraSelection * panel
Definition: WxSubsystem.cpp:99
mrpt::gui::WxSubsystem::CWXMainFrame::m_windowCount
static int m_windowCount
Definition: WxSubsystem.h:160
mrpt::gui::CWindowDialogPlots::plotEllipse
void plotEllipse(const mrpt::math::CVectorFloat &x, const mrpt::math::CVectorFloat &y, const std::string &lineFormat, const std::string &plotName, bool showName=false)
Redirected from CDisplayWindowPlots::plotEllipse.
Definition: CDisplayWindowPlots.cpp:469
mrpt::gui::WxSubsystem::listPendingWxRequests
static std::queue< TRequestToWxMainThread * > * listPendingWxRequests
Do not access directly to this, use the thread-safe functions.
Definition: WxSubsystem.h:322
mrpt::gui::CWindowDialogPlots::plot
void plot(const mrpt::math::CVectorFloat &x, const mrpt::math::CVectorFloat &y, const std::string &lineFormat, const std::string &plotName)
Redirected from CDisplayWindowPlots::plot.
Definition: CDisplayWindowPlots.cpp:313
mrpt::gui::WxSubsystem::CAuxWxSubsystemShutdowner
An auxiliary global object used just to launch a final request to the wxSubsystem for shutdown:
Definition: WxSubsystem.h:124
mrpt::gui::WxSubsystem::TWxMainThreadData::m_done
std::promise< void > m_done
Definition: WxSubsystem.h:176
mrpt
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
Definition: CKalmanFilterCapable.h:30
mrpt::gui::CWindowDialogPlots::m_firstSubmenu
bool m_firstSubmenu
to know whether to insert a separator the first time.
Definition: WxSubsystem.h:458
mrpt::gui::WxSubsystem::wxMainThread
static void wxMainThread()
This will be the "MAIN" of wxWidgets: It starts an application object and does not end until all the ...
Definition: WxSubsystem.cpp:1017
CDialogAskUserForCamera::OnBtnOk
void OnBtnOk(wxCommandEvent &event)
Definition: WxSubsystem.cpp:143
mrpt::gui::WxSubsystem::isConsoleApp
static bool isConsoleApp()
Will be set to true at runtime if it's not detected a running wxApp instance.
Definition: WxSubsystem.cpp:53
CDialogAskUserForCamera::OnBtnCancel
void OnBtnCancel(wxCommandEvent &event)
Definition: WxSubsystem.cpp:144
CDialogAskUserForCamera
Definition: WxSubsystem.cpp:96
CDisplayWindow3D.h
mrpt::gui::WxSubsystem::TWxMainThreadData::m_semWxMainThreadReady
std::promise< void > m_semWxMainThreadReady
This is signaled when wxMainThread is ready.
Definition: WxSubsystem.h:175
mrpt::gui::WxSubsystem
This class implements the GUI thread required for the wxWidgets-based GUI.
Definition: WxSubsystem.h:99
mrpt::gui::WxSubsystem::GetWxMainThreadInstance
static TWxMainThreadData & GetWxMainThreadInstance()
Definition: WxSubsystem.cpp:1078
WxUtils.h
mrpt::gui::WxSubsystem::TRequestToWxMainThread::vector_x
mrpt::math::CVectorFloat vector_x
Definition: WxSubsystem.h:232
mrpt::gui::C3DWindowDialog::addTextMessage
void addTextMessage(const double x_frac, const double y_frac, const std::string &text, const mrpt::img::TColorf &color, const size_t unique_index, const mrpt::opengl::TOpenGLFont font)
Definition: CDisplayWindow3D.cpp:402
mrpt::gui::WxSubsystem::getMRPTDefaultIcon
static wxBitmap getMRPTDefaultIcon()
Definition: WxSubsystem.cpp:846
mrpt::gui::WxSubsystem::CWXMainFrame::notifyWindowCreation
static int notifyWindowCreation()
Atomically increments the number of windows created with the main frame as parent.
Definition: WxSubsystem.cpp:198
mrpt::gui::WxSubsystem::TRequestToWxMainThread::source2D
mrpt::gui::CDisplayWindow * source2D
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:209
CDialogAskUserForCamera::~CDialogAskUserForCamera
virtual ~CDialogAskUserForCamera()
Definition: WxSubsystem.cpp:142
mrpt::gui::CBaseGUIWindow::notifySemThreadReady
void notifySemThreadReady()
Called by wx main thread to signal the semaphore that the wx window is built and ready.
Definition: CBaseGUIWindow.cpp:217
mrpt::gui::WxSubsystem::CWXMainFrame::notifyWindowDestruction
static int notifyWindowDestruction()
Atomically decrements the number of windows created with the main frame as parent.
Definition: WxSubsystem.cpp:204
mrpt::gui::WxSubsystem::CAuxWxSubsystemShutdowner::~CAuxWxSubsystemShutdowner
~CAuxWxSubsystemShutdowner()
Definition: WxSubsystem.cpp:58
mrpt::gui::WxSubsystem::TRequestToWxMainThread::str
std::string str
Parameters, depending on OPCODE.
Definition: WxSubsystem.h:225
data
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3547
mrpt::gui::WxSubsystem::TRequestToWxMainThread
The data structure for each inter-thread request:
Definition: WxSubsystem.h:192
CDisplayWindow_WXAPP::OnExit
virtual int OnExit()
Definition: WxSubsystem.cpp:895
wxGetApp
CDisplayWindow_WXAPP & wxGetApp()
mrpt::gui::CWindowDialogPlots::m_ID2ID
std::map< long, long > m_ID2ID
wxIDs to user IDs for submenus.
Definition: WxSubsystem.h:460
mrpt::gui::WxSubsystem::TWxMainThreadData
Definition: WxSubsystem.h:170
mrpt::gui::WxSubsystem::TRequestToWxMainThread::boolVal
bool boolVal
Definition: WxSubsystem.h:231
mrpt::gui::WxSubsystem::CAuxWxSubsystemShutdowner::CAuxWxSubsystemShutdowner
CAuxWxSubsystemShutdowner()
Definition: WxSubsystem.cpp:57
MRPT_START
#define MRPT_START
Definition: exceptions.h:262
mrpt::gui::CWindowDialog::m_image
wxMRPTImageControl * m_image
Definition: WxSubsystem.h:377
CDialogAskUserForCamera::ID_BTN_OK
static const long ID_BTN_OK
Definition: WxSubsystem.cpp:101
mrpt::gui::WxSubsystem::popPendingWxRequest
static TRequestToWxMainThread * popPendingWxRequest()
Thread-safe method to return the next pending request, or nullptr if there is none (After usage,...
Definition: WxSubsystem.cpp:237
mrpt::gui::WxSubsystem::CWXMainFrame::OnTimerProcessRequests
void OnTimerProcessRequests(wxTimerEvent &event)
This method processes the pending requests from the main MRPT application thread.
Definition: WxSubsystem.cpp:287
mrpt::gui::WxSubsystem::TRequestToWxMainThread::OPCODE
int OPCODE
Valid codes are: For CDisplayWindow:
Definition: WxSubsystem.h:299
id
GLuint id
Definition: glext.h:3909
mrpt::gui::WxSubsystem::global_wxsubsystem_shutdown
static CAuxWxSubsystemShutdowner global_wxsubsystem_shutdown
Definition: WxSubsystem.h:131
mrpt::gui::C3DWindowDialog
Definition: WxSubsystem.h:395
mrpt::gui::WxSubsystem::TRequestToWxMainThread::y
int y
Definition: WxSubsystem.h:230
mrpt::img::TColorf
A RGB color - floats in the range [0,1].
Definition: TColor.h:79
mrpt::gui::WxSubsystem::TRequestToWxMainThread::plotName
std::string plotName
Definition: WxSubsystem.h:233
mrpt::gui::WxSubsystem::TWxMainThreadData::m_csWxMainThreadId
std::mutex m_csWxMainThreadId
The critical section for accessing "m_wxMainThreadId".
Definition: WxSubsystem.h:178
gui-precomp.h
mrpt::gui::WxSubsystem::cs_listPendingWxRequests
static std::mutex * cs_listPendingWxRequests
Definition: WxSubsystem.h:323
mrpt::gui::CWindowDialog::wxMRPTImageControl::AssignImage
void AssignImage(wxBitmap *img)
Assigns this image.
Definition: CDisplayWindow.cpp:88
mrpt_wxCreateApp
wxAppConsole * mrpt_wxCreateApp()
Definition: WxSubsystem.cpp:960
mrpt::gui
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:16
mrpt::gui::WxSubsystem::CWXMainFrame
The main frame of the wxWidgets application.
Definition: WxSubsystem.h:135
mrpt::gui::WxSubsystem::TRequestToWxMainThread::sourceCameraSelectDialog
bool sourceCameraSelectDialog
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:221
mrpt::gui::detail::TReturnAskUserOpenCamera::accepted_by_user
bool accepted_by_user
Definition: WxUtils.h:298
mrpt::gui::WxSubsystem::waitWxShutdownsIfNoWindows
static void waitWxShutdownsIfNoWindows()
This method must be called in the destructor of the user class FROM THE MAIN THREAD,...
Definition: WxSubsystem.cpp:913
img
GLint GLvoid * img
Definition: glext.h:3763
mrpt::gui::WxSubsystem::CWXMainFrame::cs_windowCount
static std::mutex cs_windowCount
Definition: WxSubsystem.h:159
MRPT_END
#define MRPT_END
Definition: exceptions.h:266
mrpt::gui::CWindowDialogPlots::m_plot
mpWindow * m_plot
Definition: WxSubsystem.h:453
CDisplayWindow_WXAPP
Definition: WxSubsystem.cpp:864
mrpt::gui::WxSubsystem::TRequestToWxMainThread::x
int x
Definition: WxSubsystem.h:230
mrpt::gui::WxSubsystem::TRequestToWxMainThread::vector_y
mrpt::math::CVectorFloat vector_y
Definition: WxSubsystem.h:232
mrpt::gui::C3DWindowDialog::clearTextMessages
void clearTextMessages()
Definition: CDisplayWindow3D.cpp:395
mrpt::gui::CWindowDialogPlots::image
void image(void *theWxImage, const float &x0, const float &y0, const float &w, const float &h, const std::string &plotName)
Redirected from CDisplayWindowPlots::image.
Definition: CDisplayWindowPlots.cpp:627
mrpt::gui::CBaseGUIWindow::getWxObject
void * getWxObject()
Read-only access to the wxDialog object.
Definition: CBaseGUIWindow.h:79
CDisplayWindowPlots.h
mrpt::gui::WxSubsystem::TRequestToWxMainThread::source3D
mrpt::gui::CDisplayWindow3D * source3D
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:213
isConsoleApp_value
bool isConsoleApp_value
Definition: WxSubsystem.cpp:52
ID_TIMER_WX_PROCESS_REQUESTS
const long ID_TIMER_WX_PROCESS_REQUESTS
Definition: WxSubsystem.cpp:157
mrpt::gui::WxSubsystem::CWXMainFrame::oneInstance
static volatile CWXMainFrame * oneInstance
Definition: WxSubsystem.h:156
CDisplayWindow.h
mrpt::gui::CWindowDialogPlots
The wx dialog for gui::CDisplayWindowPlots.
Definition: WxSubsystem.h:440
mrpt::gui::detail::TReturnAskUserOpenCamera::selectedConfig
mrpt::config::CConfigFileMemory selectedConfig
Definition: WxUtils.h:297
mrpt::gui::WxSubsystem::CWXMainFrame::~CWXMainFrame
virtual ~CWXMainFrame()
Definition: WxSubsystem.cpp:185
_U
#define _U(x)
Definition: WxSubsystem.h:505
CDisplayWindow_WXAPP::OnInit
virtual bool OnInit()
Definition: WxSubsystem.cpp:871
mrpt::gui::WxSubsystem::TRequestToWxMainThread::voidPtr2
void * voidPtr2
Definition: WxSubsystem.h:229
mrpt::gui::WxSubsystem::TWxMainThreadData::m_wxMainThreadId
std::thread m_wxMainThreadId
The thread ID of wxMainThread, or 0 if it is not running.
Definition: WxSubsystem.h:173



Page generated by Doxygen 1.8.17 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at miƩ 12 jul 2023 10:03:34 CEST