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