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,
128 ID_BTN_OK, wxEVT_COMMAND_BUTTON_CLICKED,
131 ID_BTN_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED,
142 void OnBtnOk(wxCommandEvent& event) { EndModal(wxID_OK); }
143 void OnBtnCancel(wxCommandEvent& event) { EndModal(wxID_CANCEL); }
161 parent,
id, _(
"MRPT-dummy frame window"), wxDefaultPosition,
168 cerr <<
"[CWXMainFrame] More than one instance running!" << endl;
178 (wxObjectEventFunction)&CWXMainFrame::OnTimerProcessRequests);
181 m_theTimer->Start(10,
true);
186 #ifdef WXSUBSYSTEM_VERBOSE 187 cout <<
"[CWXMainFrame] Destructor." << endl;
190 oneInstance =
nullptr;
194 while (
nullptr != (msg = popPendingWxRequest()))
delete[] msg;
199 std::lock_guard<std::mutex> lock(cs_windowCount);
200 return ++m_windowCount;
207 std::lock_guard<std::mutex> lock(cs_windowCount);
208 ret = --m_windowCount;
216 #ifdef WXSHUTDOWN_DO_IT_CLEAN 222 #ifdef WXSUBSYSTEM_VERBOSE 223 cout <<
"[CWXMainFrame::notifyWindowDestruction] numWindows=0. " 224 "me->Close() called." 238 if (!cs_listPendingWxRequests)
240 cs_listPendingWxRequests =
new std::mutex();
241 listPendingWxRequests =
new std::queue<TRequestToWxMainThread*>;
244 std::lock_guard<std::mutex> locker(*cs_listPendingWxRequests);
247 if (listPendingWxRequests->empty())
return nullptr;
250 listPendingWxRequests->pop();
263 #ifdef WXSUBSYSTEM_VERBOSE 264 cout <<
"[WxSubsystem::pushPendingWxRequest] IGNORING request since " 265 "app seems already closed.\n";
271 if (!cs_listPendingWxRequests)
273 cs_listPendingWxRequests =
new std::mutex();
274 listPendingWxRequests =
new std::queue<TRequestToWxMainThread*>;
277 std::lock_guard<std::mutex> locker(*cs_listPendingWxRequests);
278 listPendingWxRequests->push(
data);
288 bool app_closed =
false;
293 #ifdef WXSUBSYSTEM_VERBOSE 294 cout <<
"[OnTimerProcessRequests] Entering" << endl;
298 while (
nullptr != (msg = popPendingWxRequest()))
309 wxSize(msg->
x, msg->
y));
312 *((
void**)msg->
voidPtr) = (
void*)wnd;
332 wnd->m_image->AssignImage(
new wxBitmap(
335 if (wnd->m_image->GetSize().GetX() !=
img->GetWidth() &&
336 wnd->m_image->GetSize().GetY() !=
img->GetHeight())
338 wnd->m_image->SetSize(
339 img->GetWidth(),
img->GetHeight());
340 wnd->m_image->SetMinSize(
341 wxSize(
img->GetWidth(),
img->GetHeight()));
342 wnd->m_image->SetMaxSize(
343 wxSize(
img->GetWidth(),
img->GetHeight()));
349 wnd->m_image->Refresh(
false);
362 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
371 if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
380 if (wnd) wnd->SetTitle(msg->
str.c_str());
403 wxSize(msg->
x, msg->
y));
406 *((
void**)msg->
voidPtr) = (
void*)wnd;
423 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
432 if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
441 if (wnd) wnd->SetTitle(msg->
str.c_str());
483 wnd->clearTextMessages();
532 wxSize(msg->
x, msg->
y));
535 *((
void**)msg->
voidPtr) = (
void*)wnd;
552 msg->
x, msg->
y, wxDefaultCoord, wxDefaultCoord);
561 if (wnd) wnd->SetClientSize(msg->
x, msg->
y);
570 if (wnd) wnd->SetTitle(msg->
str.c_str());
579 if (wnd) wnd->m_plot->EnableMousePanZoom(msg->
boolVal);
588 if (wnd) wnd->m_plot->LockAspect(msg->
boolVal);
606 wnd->m_plot->LockAspect(msg->
boolVal);
619 wnd->m_plot->LockAspect(msg->
boolVal);
632 wnd->m_plot->DelAllLayers(
true,
true);
633 wnd->m_plot->AddLayer(
new mpScaleX());
634 wnd->m_plot->AddLayer(
new mpScaleY());
687 const long MENUITEM_ID = wxNewId();
690 wnd->m_ID2ID[MENUITEM_ID] = msg->
x;
692 wxMenu* popupMnu = wnd->m_plot->GetPopupMenu();
693 if (wnd->m_firstSubmenu)
695 wnd->m_firstSubmenu =
false;
696 popupMnu->InsertSeparator(0);
698 wxMenuItem* mnuTarget =
new wxMenuItem(
699 popupMnu, MENUITEM_ID, msg->
plotName.c_str(),
700 wxEmptyString, wxITEM_NORMAL);
701 popupMnu->Insert(0, mnuTarget);
704 MENUITEM_ID, wxEVT_COMMAND_MENU_SELECTED,
730 reinterpret_cast<std::promise<void>*
>(msg->
voidPtr);
732 auto dlg = std::make_unique<CDialogAskUserForCamera>();
738 const bool wasOk = (dlg->ShowModal() == wxID_OK);
741 auto* promise =
reinterpret_cast<std::promise<
748 dlg->panel->writeConfigFromVideoSourcePanel(
753 promise->set_value(std::move(ret));
761 #ifdef WXSUBSYSTEM_VERBOSE 762 cout <<
"[WxSubsystem:999] Shutdown" << endl;
770 #ifdef WXSUBSYSTEM_VERBOSE 771 cout <<
"[WxSubsystem:999] Shutdown done" << endl;
786 if (!app_closed) m_theTimer->Start(10,
true);
798 " ..... ..... ......... ",
799 " .... .... ... .... ",
800 " ..... .... ... ... ",
801 " . ... . ... ... ... ",
802 " . ... . ... ... ... ",
803 " . ... . ... ... ... ",
804 " . ... . ... ........ ",
805 " . ..... ... ... .... ",
806 " . ... ... ... .... ",
807 " . ... ... ... .... ",
808 " . .. ... ... .... ",
809 " ... . ..... ..... ..... ",
812 " ........ ........... ",
813 " ... .... .. ... .. ",
832 const wxSize iconsSize(
833 ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
836 .Scale(iconsSize.x, iconsSize.y));
848 bool OnInit()
override;
849 int OnExit()
override;
858 wxSetlocale(LC_NUMERIC, wxString(wxT(
"C")));
860 wxInitAllImageHandlers();
878 #ifdef WXSUBSYSTEM_VERBOSE 879 cout <<
"[wxApp::OnExit] wxApplication OnExit called." << endl;
882 std::lock_guard<std::mutex> lock(
896 #ifndef WXSHUTDOWN_DO_IT_CLEAN 898 #ifdef WXSUBSYSTEM_VERBOSE 899 cout <<
"[WxSubsystem::waitWxShutdownsIfNoWindows] Doing a quick " 900 "std::this_thread::sleep_for(ms) and returning.\n";
902 std::this_thread::sleep_for(100ms);
909 std::lock_guard<std::mutex> lock(CWXMainFrame::cs_windowCount);
910 nOpenWnds = CWXMainFrame::m_windowCount;
915 #ifdef WXSUBSYSTEM_VERBOSE 916 cout <<
"[WxSubsystem::waitWxShutdownsIfNoWindows] Waiting for " 917 "WxWidgets thread to shutdown...\n";
930 if (m_done.wait_for(std::chrono::milliseconds(maxTimeout)) ==
931 std::future_status::timeout)
933 cerr <<
"[WxSubsystem::waitWxShutdownsIfNoWindows] Timeout waiting " 934 "for WxWidgets thread to shutdown!" 943 wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,
"your program");
955 if (!wxEntryStart(argc, argv))
959 delete wxLog::SetActiveTarget(
nullptr);
969 if (!wxTheApp->CallOnInit())
973 int ret = wxTheApp->OnRun();
986 wxTheApp->OnUnhandledException();
1004 static const char* dummy_prog_name =
"./MRPT";
1005 char* argv[2] = {
const_cast<char*
>(dummy_prog_name),
nullptr};
1007 #ifdef WXSUBSYSTEM_VERBOSE 1008 cout <<
"[wxMainThread] Starting..." << endl;
1012 wxAppConsole* app_gui = wxApp::GetInstance();
1017 #ifdef WXSUBSYSTEM_VERBOSE 1018 cout <<
"[wxMainThread] I am in a console app" << endl;
1024 wxApp::SetInitializerFunction(
1028 #ifdef WXSUBSYSTEM_VERBOSE 1029 cout <<
"[wxMainThread] Finished" << endl;
1039 #ifdef WXSUBSYSTEM_VERBOSE 1040 cout <<
"[wxMainThread] I am in a GUI app" << endl;
1042 wxWindow* topWin =
static_cast<wxApp*
>(app_gui)->GetTopWindow();
1048 #ifdef WXSUBSYSTEM_VERBOSE 1049 cout <<
"[wxMainThread] Signaling semaphore." << endl;
1064 static bool first_creat =
true;
1065 if (!dat && first_creat)
1067 first_creat =
false;
1082 wxAppConsole* app_con = wxApp::GetInstance();
1092 wxWindow* topWin =
static_cast<wxApp*
>(app_con)->GetTopWindow();
1106 #ifdef WXSUBSYSTEM_VERBOSE 1108 "[WxSubsystem::createOneInstanceMainThread] Launching " 1109 "wxMainThread() thread...\n");
1123 const char* envVal = getenv(
"MRPT_WXSUBSYS_TIMEOUT_MS");
1124 if (envVal) maxTimeout = atoi(envVal);
1127 std::chrono::milliseconds(maxTimeout)) ==
1128 std::future_status::timeout)
1130 cerr <<
"[WxSubsystem::createOneInstanceMainThread] Timeout " 1131 "waiting wxApplication to start up!" 1141 #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
TOpenGLFont
Existing fonts for 2D texts in mrpt::opengl methods.
wxAppConsole * mrpt_wxCreateApp()
std::promise< void > m_semWxMainThreadReady
This is signaled when wxMainThread is ready.
TOpenGLFontStyle
Different style for vectorized font rendering.
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()
A RGB color - floats in the range [0,1].
CAuxWxSubsystemShutdowner()
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.
GLsizei GLsizei GLenum GLenum const GLvoid * data
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