12 #include <mrpt/config.h> 35 #if MRPT_HAS_WXWIDGETS 44 std::queue<WxSubsystem::TRequestToWxMainThread*>*
60 #ifdef WXSUBSYSTEM_VERBOSE 61 printf(
"[~CAuxWxSubsystemShutdowner] Sending 999...\n");
80 #ifdef WXSUBSYSTEM_VERBOSE 81 printf(
"[~CAuxWxSubsystemShutdowner] Deleting static objects.\n");
103 nullptr, wxID_ANY, wxT(
"Select image source"), wxDefaultPosition,
104 wxDefaultSize, wxDEFAULT_DIALOG_STYLE, wxDialogNameStr)
106 auto* f1 =
new wxFlexGridSizer(2, 1, 0, 0);
109 panel, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
111 auto* f2 =
new wxFlexGridSizer(1, 2, 0, 0);
112 wxButton* btnOk =
new wxButton(
113 this, ID_BTN_OK, wxT(
"Ok"), wxDefaultPosition, wxDefaultSize);
114 wxButton* btnCancel =
new wxButton(
115 this, ID_BTN_CANCEL, wxT(
"Cancel"), wxDefaultPosition,
117 f1->Add(f2, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
120 btnOk, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL, 5);
122 btnCancel, 1, wxALL | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL,
138 void OnBtnOk(wxCommandEvent& event) { EndModal(wxID_OK); }
139 void OnBtnCancel(wxCommandEvent& event) { EndModal(wxID_CANCEL); }
157 parent,
id, _(
"MRPT-dummy frame window"), wxDefaultPosition,
164 cerr <<
"[CWXMainFrame] More than one instance running!" << endl;
173 wxEVT_TIMER, &CWXMainFrame::OnTimerProcessRequests,
this,
177 m_theTimer->Start(10,
true);
182 #ifdef WXSUBSYSTEM_VERBOSE 183 cout <<
"[CWXMainFrame] Destructor." << endl;
186 oneInstance =
nullptr;
190 while (
nullptr != (msg = popPendingWxRequest()))
delete[] msg;
195 std::lock_guard<std::mutex> lock(cs_windowCount);
196 return ++m_windowCount;
203 std::lock_guard<std::mutex> lock(cs_windowCount);
204 ret = --m_windowCount;
212 #ifdef WXSHUTDOWN_DO_IT_CLEAN 218 #ifdef WXSUBSYSTEM_VERBOSE 219 cout <<
"[CWXMainFrame::notifyWindowDestruction] numWindows=0. " 220 "me->Close() called." 234 if (!cs_listPendingWxRequests)
236 cs_listPendingWxRequests =
new std::mutex();
237 listPendingWxRequests =
new std::queue<TRequestToWxMainThread*>;
240 std::lock_guard<std::mutex> locker(*cs_listPendingWxRequests);
243 if (listPendingWxRequests->empty())
return nullptr;
246 listPendingWxRequests->pop();
259 #ifdef WXSUBSYSTEM_VERBOSE 260 cout <<
"[WxSubsystem::pushPendingWxRequest] IGNORING request since " 261 "app seems already closed.\n";
267 if (!cs_listPendingWxRequests)
269 cs_listPendingWxRequests =
new std::mutex();
270 listPendingWxRequests =
new std::queue<TRequestToWxMainThread*>;
273 std::lock_guard<std::mutex> locker(*cs_listPendingWxRequests);
274 listPendingWxRequests->push(
data);
284 bool app_closed =
false;
289 #ifdef WXSUBSYSTEM_VERBOSE 290 cout <<
"[OnTimerProcessRequests] Entering" << endl;
294 while (
nullptr != (msg = popPendingWxRequest()))
305 wxSize(msg->
x, msg->
y));
308 *((
void**)msg->
voidPtr) = (
void*)wnd;
325 auto* img = (wxImage*)msg->
voidPtr2;
328 wnd->m_image->AssignImage(
new wxBitmap(
331 if (wnd->m_image->GetSize().GetX() != img->GetWidth() &&
332 wnd->m_image->GetSize().GetY() != img->GetHeight())
334 wnd->m_image->SetSize(
335 img->GetWidth(), img->GetHeight());
336 wnd->m_image->SetMinSize(
337 wxSize(img->GetWidth(), img->GetHeight()));
338 wnd->m_image->SetMaxSize(
339 wxSize(img->GetWidth(), img->GetHeight()));
345 wnd->m_image->Refresh(
false);
358 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
367 if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
376 if (wnd) wnd->SetTitle(msg->
str.c_str());
399 wxSize(msg->
x, msg->
y));
402 *((
void**)msg->
voidPtr) = (
void*)wnd;
419 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
428 if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
437 if (wnd) wnd->SetTitle(msg->
str.c_str());
473 wxSize(msg->
x, msg->
y));
476 *((
void**)msg->
voidPtr) = (
void*)wnd;
493 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
502 if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
511 if (wnd) wnd->SetTitle(msg->
str.c_str());
520 if (wnd) wnd->m_plot->EnableMousePanZoom(msg->
boolVal);
529 if (wnd) wnd->m_plot->LockAspect(msg->
boolVal);
547 wnd->m_plot->LockAspect(msg->
boolVal);
560 wnd->m_plot->LockAspect(msg->
boolVal);
573 wnd->m_plot->DelAllLayers(
true,
true);
574 wnd->m_plot->AddLayer(
new mpScaleX());
575 wnd->m_plot->AddLayer(
new mpScaleY());
628 const long MENUITEM_ID = wxNewId();
631 wnd->m_ID2ID[MENUITEM_ID] = msg->
x;
633 wxMenu* popupMnu = wnd->m_plot->GetPopupMenu();
634 if (wnd->m_firstSubmenu)
636 wnd->m_firstSubmenu =
false;
637 popupMnu->InsertSeparator(0);
639 wxMenuItem* mnuTarget =
new wxMenuItem(
640 popupMnu, MENUITEM_ID, msg->
plotName.c_str(),
641 wxEmptyString, wxITEM_NORMAL);
642 popupMnu->Insert(0, mnuTarget);
670 reinterpret_cast<std::promise<void>*
>(msg->
voidPtr);
672 auto dlg = std::make_unique<CDialogAskUserForCamera>();
678 const bool wasOk = (dlg->ShowModal() == wxID_OK);
681 auto* promise =
reinterpret_cast<std::promise<
688 dlg->panel->writeConfigFromVideoSourcePanel(
693 promise->set_value(std::move(ret));
701 #ifdef WXSUBSYSTEM_VERBOSE 702 cout <<
"[WxSubsystem:999] Shutdown" << endl;
710 #ifdef WXSUBSYSTEM_VERBOSE 711 cout <<
"[WxSubsystem:999] Shutdown done" << endl;
726 if (!app_closed) m_theTimer->Start(10,
true);
739 " ..... ..... ......... ",
740 " .... .... ... .... ",
741 " ..... .... ... ... ",
742 " . ... . ... ... ... ",
743 " . ... . ... ... ... ",
744 " . ... . ... ... ... ",
745 " . ... . ... ........ ",
746 " . ..... ... ... .... ",
747 " . ... ... ... .... ",
748 " . ... ... ... .... ",
749 " . .. ... ... .... ",
750 " ... . ..... ..... ..... ",
753 " ........ ........... ",
754 " ... .... .. ... .. ",
773 const wxSize iconsSize(
774 ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
777 .Scale(iconsSize.x, iconsSize.y));
789 bool OnInit()
override;
790 int OnExit()
override;
799 wxSetlocale(LC_NUMERIC, wxString(wxT(
"C")));
801 wxInitAllImageHandlers();
819 #ifdef WXSUBSYSTEM_VERBOSE 820 cout <<
"[wxApp::OnExit] wxApplication OnExit called." << endl;
823 std::lock_guard<std::mutex> lock(
837 #ifndef WXSHUTDOWN_DO_IT_CLEAN 839 #ifdef WXSUBSYSTEM_VERBOSE 840 cout <<
"[WxSubsystem::waitWxShutdownsIfNoWindows] Doing a quick " 841 "std::this_thread::sleep_for(ms) and returning.\n";
843 std::this_thread::sleep_for(100ms);
850 std::lock_guard<std::mutex> lock(CWXMainFrame::cs_windowCount);
851 nOpenWnds = CWXMainFrame::m_windowCount;
856 #ifdef WXSUBSYSTEM_VERBOSE 857 cout <<
"[WxSubsystem::waitWxShutdownsIfNoWindows] Waiting for " 858 "WxWidgets thread to shutdown...\n";
871 if (m_done.wait_for(std::chrono::milliseconds(maxTimeout)) ==
872 std::future_status::timeout)
874 cerr <<
"[WxSubsystem::waitWxShutdownsIfNoWindows] Timeout waiting " 875 "for WxWidgets thread to shutdown!" 884 wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,
"your program");
900 delete wxLog::SetActiveTarget(
nullptr);
910 if (!wxTheApp->CallOnInit())
914 int ret = wxTheApp->OnRun();
927 wxTheApp->OnUnhandledException();
945 static const char* dummy_prog_name =
"./MRPT";
946 char*
argv[2] = {
const_cast<char*
>(dummy_prog_name),
nullptr};
948 #ifdef WXSUBSYSTEM_VERBOSE 949 cout <<
"[wxMainThread] Starting..." << endl;
953 wxAppConsole* app_gui = wxApp::GetInstance();
958 #ifdef WXSUBSYSTEM_VERBOSE 959 cout <<
"[wxMainThread] I am in a console app" << endl;
965 wxApp::SetInitializerFunction(
969 #ifdef WXSUBSYSTEM_VERBOSE 970 cout <<
"[wxMainThread] Finished" << endl;
980 #ifdef WXSUBSYSTEM_VERBOSE 981 cout <<
"[wxMainThread] I am in a GUI app" << endl;
983 wxWindow* topWin =
static_cast<wxApp*
>(app_gui)->GetTopWindow();
989 #ifdef WXSUBSYSTEM_VERBOSE 990 cout <<
"[wxMainThread] Signaling semaphore." << endl;
1005 static bool first_creat =
true;
1006 if (!dat && first_creat)
1008 first_creat =
false;
1023 wxAppConsole* app_con = wxApp::GetInstance();
1033 wxWindow* topWin =
static_cast<wxApp*
>(app_con)->GetTopWindow();
1047 #ifdef WXSUBSYSTEM_VERBOSE 1049 "[WxSubsystem::createOneInstanceMainThread] Launching " 1050 "wxMainThread() thread...\n");
1066 const char* envVal = getenv(
"MRPT_WXSUBSYS_TIMEOUT_MS");
1067 if (envVal) maxTimeout = atoi(envVal);
1070 std::chrono::milliseconds(maxTimeout)) ==
1071 std::future_status::timeout)
1073 cerr <<
"[WxSubsystem::createOneInstanceMainThread] Timeout " 1074 "waiting wxApplication to start up!" 1084 #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)
void thread_name(const std::string &name, std::thread &theThread)
Sets the name of the given thread; useful for debuggers.
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