12 #include <mrpt/config.h>    37 #if MRPT_HAS_WXWIDGETS    46 std::queue<WxSubsystem::TRequestToWxMainThread*>*
    62 #ifdef WXSUBSYSTEM_VERBOSE    63         printf(
"[~CAuxWxSubsystemShutdowner] Sending 999...\n");
    82 #ifdef WXSUBSYSTEM_VERBOSE    83     printf(
"[~CAuxWxSubsystemShutdowner] Deleting static objects.\n");
   105               nullptr, wxID_ANY, wxT(
"Select image source"), wxDefaultPosition,
   106               wxDefaultSize, wxDEFAULT_DIALOG_STYLE, wxDialogNameStr)
   108         auto* f1 = 
new wxFlexGridSizer(2, 1, 0, 0);
   111             panel, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
   113         auto* f2 = 
new wxFlexGridSizer(1, 2, 0, 0);
   114         wxButton* btnOk = 
new wxButton(
   115             this, ID_BTN_OK, wxT(
"Ok"), wxDefaultPosition, wxDefaultSize);
   116         wxButton* btnCancel = 
new wxButton(
   117             this, ID_BTN_CANCEL, wxT(
"Cancel"), wxDefaultPosition,
   119         f1->Add(f2, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
   122             btnOk, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
   124             btnCancel, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL,
   140     void OnBtnOk(wxCommandEvent& event) { EndModal(wxID_OK); }
   141     void OnBtnCancel(wxCommandEvent& event) { EndModal(wxID_CANCEL); }
   159         parent, 
id, _(
"MRPT-dummy frame window"), wxDefaultPosition,
   166         cerr << 
"[CWXMainFrame] More than one instance running!" << endl;
   175         wxEVT_TIMER, &CWXMainFrame::OnTimerProcessRequests, 
this,
   179     m_theTimer->Start(10, 
true);  
   184 #ifdef WXSUBSYSTEM_VERBOSE   185     cout << 
"[CWXMainFrame] Destructor." << endl;
   188     oneInstance = 
nullptr;
   192     while (
nullptr != (msg = popPendingWxRequest())) 
delete[] msg;
   197     std::lock_guard<std::mutex> lock(cs_windowCount);
   198     return ++m_windowCount;
   205         std::lock_guard<std::mutex> lock(cs_windowCount);
   206         ret = --m_windowCount;
   214 #ifdef WXSHUTDOWN_DO_IT_CLEAN   220 #ifdef WXSUBSYSTEM_VERBOSE   221             cout << 
"[CWXMainFrame::notifyWindowDestruction] numWindows=0. "   222                     "me->Close() called."   236     if (!cs_listPendingWxRequests)
   238         cs_listPendingWxRequests = 
new std::mutex();
   239         listPendingWxRequests = 
new std::queue<TRequestToWxMainThread*>;
   242     std::lock_guard<std::mutex> locker(*cs_listPendingWxRequests);
   245     if (listPendingWxRequests->empty()) 
return nullptr;
   248     listPendingWxRequests->pop();  
   261 #ifdef WXSUBSYSTEM_VERBOSE   262         cout << 
"[WxSubsystem::pushPendingWxRequest] IGNORING request since "   263                 "app seems already closed.\n";
   269     if (!cs_listPendingWxRequests)
   271         cs_listPendingWxRequests = 
new std::mutex();
   272         listPendingWxRequests = 
new std::queue<TRequestToWxMainThread*>;
   275     std::lock_guard<std::mutex> locker(*cs_listPendingWxRequests);
   276     listPendingWxRequests->push(
data);
   286     bool app_closed = 
false;
   291 #ifdef WXSUBSYSTEM_VERBOSE   292         cout << 
"[OnTimerProcessRequests] Entering" << endl;
   296         while (
nullptr != (msg = popPendingWxRequest()))
   307                             wxSize(msg->
x, msg->
y));
   310                         *((
void**)msg->
voidPtr) = (
void*)wnd;
   327                         auto* img = (wxImage*)msg->
voidPtr2;
   330                         wnd->m_image->AssignImage(
new wxBitmap(
   333                         if (wnd->m_image->GetSize().GetX() != img->GetWidth() &&
   334                             wnd->m_image->GetSize().GetY() != img->GetHeight())
   336                             wnd->m_image->SetSize(
   337                                 img->GetWidth(), img->GetHeight());
   338                             wnd->m_image->SetMinSize(
   339                                 wxSize(img->GetWidth(), img->GetHeight()));
   340                             wnd->m_image->SetMaxSize(
   341                                 wxSize(img->GetWidth(), img->GetHeight()));
   347                         wnd->m_image->Refresh(
false);  
   360                                 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
   369                         if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
   378                         if (wnd) wnd->SetTitle(msg->
str.c_str());
   401                             wxSize(msg->
x, msg->
y));
   404                         *((
void**)msg->
voidPtr) = (
void*)wnd;
   421                                 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
   430                         if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
   439                         if (wnd) wnd->SetTitle(msg->
str.c_str());
   475                             wxSize(msg->
x, msg->
y));
   478                         *((
void**)msg->
voidPtr) = (
void*)wnd;
   495                                 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
   504                         if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
   513                         if (wnd) wnd->SetTitle(msg->
str.c_str());
   522                         if (wnd) wnd->m_plot->EnableMousePanZoom(msg->
boolVal);
   531                         if (wnd) wnd->m_plot->LockAspect(msg->
boolVal);
   549                                 wnd->m_plot->LockAspect(msg->
boolVal);
   562                             wnd->m_plot->LockAspect(msg->
boolVal);
   575                             wnd->m_plot->DelAllLayers(
true, 
true);
   576                             wnd->m_plot->AddLayer(
new mpScaleX());
   577                             wnd->m_plot->AddLayer(
new mpScaleY());
   630                             const long MENUITEM_ID = wxNewId();
   633                             wnd->m_ID2ID[MENUITEM_ID] = msg->
x;
   635                             wxMenu* popupMnu = wnd->m_plot->GetPopupMenu();
   636                             if (wnd->m_firstSubmenu)
   638                                 wnd->m_firstSubmenu = 
false;
   639                                 popupMnu->InsertSeparator(0);
   641                             wxMenuItem* mnuTarget = 
new wxMenuItem(
   642                                 popupMnu, MENUITEM_ID, msg->
plotName.c_str(),
   643                                 wxEmptyString, wxITEM_NORMAL);
   644                             popupMnu->Insert(0, mnuTarget);
   672                             reinterpret_cast<std::promise<void>*
>(msg->
voidPtr);
   674                         auto dlg = std::make_unique<CDialogAskUserForCamera>();
   680                         const bool wasOk = (dlg->ShowModal() == wxID_OK);
   683                         auto* promise = 
reinterpret_cast<std::promise<
   690                         dlg->panel->writeConfigFromVideoSourcePanel(
   695                         promise->set_value(std::move(ret));
   703 #ifdef WXSUBSYSTEM_VERBOSE   704                     cout << 
"[WxSubsystem:999] Shutdown" << endl;
   712 #ifdef WXSUBSYSTEM_VERBOSE   713                     cout << 
"[WxSubsystem:999] Shutdown done" << endl;
   728     if (!app_closed) m_theTimer->Start(10, 
true);  
   740                                        " .....     ..... .........      ",
   741                                        "  ....     ....   ...   ....    ",
   742                                        "  .....    ....   ...    ...    ",
   743                                        "  . ...   . ...   ...    ...    ",
   744                                        "  . ...   . ...   ...    ...    ",
   745                                        "  .  ... .  ...   ...   ...     ",
   746                                        "  .  ... .  ...   ........      ",
   747                                        "  .  .....  ...   ... ....      ",
   748                                        "  .   ...   ...   ...  ....     ",
   749                                        "  .   ...   ...   ...   ....    ",
   750                                        "  .   ..    ...   ...    ....   ",
   751                                        " ...   .   ..... .....    ..... ",
   754                                        "    ........     ...........    ",
   755                                        "     ...  ....   ..  ...  ..    ",
   774     const wxSize iconsSize(
   775         ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
   778                         .Scale(iconsSize.x, iconsSize.y));
   790     bool OnInit() 
override;
   791     int OnExit() 
override;
   800     wxSetlocale(LC_NUMERIC, wxString(wxT(
"C")));
   802     wxInitAllImageHandlers();
   820 #ifdef WXSUBSYSTEM_VERBOSE   821     cout << 
"[wxApp::OnExit] wxApplication OnExit called." << endl;
   824     std::lock_guard<std::mutex> lock(
   838 #ifndef WXSHUTDOWN_DO_IT_CLEAN   840 #ifdef WXSUBSYSTEM_VERBOSE   841     cout << 
"[WxSubsystem::waitWxShutdownsIfNoWindows] Doing a quick "   842             "std::this_thread::sleep_for(ms) and returning.\n";
   844     std::this_thread::sleep_for(100ms);
   851         std::lock_guard<std::mutex> lock(CWXMainFrame::cs_windowCount);
   852         nOpenWnds = CWXMainFrame::m_windowCount;
   857 #ifdef WXSUBSYSTEM_VERBOSE   858         cout << 
"[WxSubsystem::waitWxShutdownsIfNoWindows] Waiting for "   859                 "WxWidgets thread to shutdown...\n";
   872         if (m_done.wait_for(std::chrono::milliseconds(maxTimeout)) ==
   873             std::future_status::timeout)
   875             cerr << 
"[WxSubsystem::waitWxShutdownsIfNoWindows] Timeout waiting "   876                     "for WxWidgets thread to shutdown!"   885     wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, 
"your program");
   901         delete wxLog::SetActiveTarget(
nullptr);
   911         if (!wxTheApp->CallOnInit())
   915         int ret = wxTheApp->OnRun();
   928         wxTheApp->OnUnhandledException();
   946     static const char* dummy_prog_name = 
"./MRPT";
   947     char* 
argv[2] = {
const_cast<char*
>(dummy_prog_name), 
nullptr};
   949 #ifdef WXSUBSYSTEM_VERBOSE   950     cout << 
"[wxMainThread] Starting..." << endl;
   954     wxAppConsole* app_gui = wxApp::GetInstance();
   959 #ifdef WXSUBSYSTEM_VERBOSE   960         cout << 
"[wxMainThread] I am in a console app" << endl;
   966         wxApp::SetInitializerFunction(
   970 #ifdef WXSUBSYSTEM_VERBOSE   971         cout << 
"[wxMainThread] Finished" << endl;
   981 #ifdef WXSUBSYSTEM_VERBOSE   982         cout << 
"[wxMainThread] I am in a GUI app" << endl;
   984         wxWindow* topWin = 
static_cast<wxApp*
>(app_gui)->GetTopWindow();
   990 #ifdef WXSUBSYSTEM_VERBOSE   991         cout << 
"[wxMainThread] Signaling semaphore." << endl;
  1006     static bool first_creat = 
true;
  1007     if (!dat && first_creat)
  1009         first_creat = 
false;
  1024     wxAppConsole* app_con = wxApp::GetInstance();
  1034             wxWindow* topWin = 
static_cast<wxApp*
>(app_con)->GetTopWindow();
  1048 #ifdef WXSUBSYSTEM_VERBOSE  1050                 "[WxSubsystem::createOneInstanceMainThread] Launching "  1051                 "wxMainThread() thread...\n");
  1065             const char* envVal = getenv(
"MRPT_WXSUBSYS_TIMEOUT_MS");
  1066             if (envVal) maxTimeout = atoi(envVal);
  1069                     std::chrono::milliseconds(maxTimeout)) ==
  1070                 std::future_status::timeout)  
  1072                 cerr << 
"[WxSubsystem::createOneInstanceMainThread] Timeout "  1073                         "waiting wxApplication to start up!"  1083 #endif  // MRPT_HAS_WXWIDGETS An auxiliary global object used just to launch a final request to the wxSubsystem for shutdown: ...
 
static void pushPendingWxRequest(TRequestToWxMainThread *data)
Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "ne...
 
void * voidPtr
Parameters, depending on OPCODE. 
 
This class implements a config file-like interface over a memory-stored string list. 
 
static const long ID_BTN_CANCEL
 
static TRequestToWxMainThread * popPendingWxRequest()
Thread-safe method to return the next pending request, or nullptr if there is none (After usage...
 
mrpt::gui::CDisplayWindow3D * source3D
Only one of source* can be non-nullptr, indicating the class that generated the request. 
 
The data structure for each inter-thread request: 
 
~CAuxWxSubsystemShutdowner()
 
static std::mutex cs_windowCount
 
static int notifyWindowCreation()
Atomically increments the number of windows created with the main frame as parent. 
 
void OnTimerProcessRequests(wxTimerEvent &event)
This method processes the pending requests from the main MRPT application thread. ...
 
static std::mutex * cs_listPendingWxRequests
 
std::thread m_wxMainThreadId
The thread ID of wxMainThread, or 0 if it is not running. 
 
mrpt::gui::CPanelCameraSelection * panel
 
size_type size() const
Get a 2-vector with [NROWS NCOLS] (as in MATLAB command size(x)) 
 
The wx dialog for gui::CDisplayWindowPlots. 
 
static wxBitmap getMRPTDefaultIcon()
 
std::promise< void > m_done
 
const char * mrpt_default_icon_xpm[]
 
CDialogAskUserForCamera()
 
static volatile CWXMainFrame * oneInstance
 
std::mutex m_csWxMainThreadId
The critical section for accessing "m_wxMainThreadId". 
 
static TWxMainThreadData & GetWxMainThreadInstance()
 
void OnBtnOk(wxCommandEvent &event)
 
int mrpt_wxEntryReal(int argc, char **argv)
 
int OPCODE
Valid codes are: For CDisplayWindow: 
 
const long ID_TIMER_WX_PROCESS_REQUESTS
 
static std::queue< TRequestToWxMainThread * > * listPendingWxRequests
Do not access directly to this, use the thread-safe functions. 
 
static const long ID_BTN_OK
 
void OnMenuSelected(wxCommandEvent &ev)
 
wxAppConsole * mrpt_wxCreateApp()
 
std::promise< void > m_semWxMainThreadReady
This is signaled when wxMainThread is ready. 
 
void * getWxObject()
Read-only access to the wxDialog object. 
 
mrpt::math::CVectorFloat vector_y
 
The main frame of the wxWidgets application. 
 
The wx dialog for gui::CDisplayWindow. 
 
void OnBtnCancel(wxCommandEvent &event)
 
bool sourceCameraSelectDialog
Only one of source* can be non-nullptr, indicating the class that generated the request. 
 
static void wxMainThread()
This will be the "MAIN" of wxWidgets: It starts an application object and does not end until all the ...
 
static void waitWxShutdownsIfNoWindows()
This method must be called in the destructor of the user class FROM THE MAIN THREAD, in order to wait for the shutdown of the wx thread if this was the last open window. 
 
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries. 
 
This class implements the GUI thread required for the wxWidgets-based GUI. 
 
CDisplayWindow_WXAPP & wxGetApp()
 
CAuxWxSubsystemShutdowner()
 
void getContent(std::string &str) const
Return the current contents of the virtual "config file". 
 
static CAuxWxSubsystemShutdowner global_wxsubsystem_shutdown
 
A panel to select the camera input from all the formats supported by MRPT. 
 
mrpt::gui::CDisplayWindowPlots * sourcePlots
Only one of source* can be non-nullptr, indicating the class that generated the request. 
 
static bool isConsoleApp()
Will be set to true at runtime if it's not detected a running wxApp instance. 
 
Classes for creating GUI windows for 2D and 3D visualization. 
 
mrpt::math::CVectorFloat vector_x
 
mrpt::gui::CDisplayWindow * source2D
Only one of source* can be non-nullptr, indicating the class that generated the request. 
 
std::string str
Parameters, depending on OPCODE. 
 
void notifySemThreadReady()
Called by wx main thread to signal the semaphore that the wx window is built and ready. 
 
static bool createOneInstanceMainThread()
Thread-safe method to create one single instance of the main wxWidgets thread: it will create the thr...
 
static int notifyWindowDestruction()
Atomically decrements the number of windows created with the main frame as parent. 
 
std::string selectedConfig
 
static struct FontData data