MRPT  2.0.0
CBaseGUIWindow.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "gui-precomp.h" // Precompiled headers
11 
13 #include <mrpt/gui/WxSubsystem.h>
14 #include <mrpt/system/os.h>
15 #include <iostream>
16 
17 using namespace mrpt;
18 using namespace mrpt::gui;
19 using namespace mrpt::system;
20 using namespace std;
21 
22 /*---------------------------------------------------------------
23  Ctor
24  ---------------------------------------------------------------*/
26  void* winobj_voidptr, int CMD_CREATE_WIN, int CMD_DESTROY_WIN,
27  const std::string& initial_caption)
28  : m_CMD_CREATE_WIN(CMD_CREATE_WIN),
29  m_CMD_DESTROY_WIN(CMD_DESTROY_WIN),
30  m_winobj_voidptr(winobj_voidptr),
31  m_caption(initial_caption),
32  m_hwnd(nullptr),
33  m_keyPushed(false),
34  m_keyPushedCode(0),
35  m_keyPushedModifier(MRPTKMOD_NONE)
36 {
37 }
38 
39 /*---------------------------------------------------------------
40  Create the wx Window
41  ---------------------------------------------------------------*/
43  [[maybe_unused]] unsigned int initialWidth,
44  [[maybe_unused]] unsigned int initialHeight)
45 {
47 #if MRPT_HAS_WXWIDGETS
48  // Create the main wxThread:
49  // -------------------------------
50  if (!WxSubsystem::createOneInstanceMainThread()) return; // Error!
51 
52  // Create window:
53  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
54  REQ->source2D = static_cast<gui::CDisplayWindow*>(m_winobj_voidptr);
55  REQ->source3D = static_cast<gui::CDisplayWindow3D*>(m_winobj_voidptr);
56  REQ->sourcePlots = static_cast<gui::CDisplayWindowPlots*>(m_winobj_voidptr);
57  REQ->str = m_caption;
58  REQ->OPCODE = m_CMD_CREATE_WIN;
59  REQ->voidPtr = m_hwnd.getPtrToPtr();
60  REQ->x = initialWidth;
61  REQ->y = initialHeight;
62 
64 
65  // Wait for the window to realize and signal it's alive:
67  {
68  std::this_thread::sleep_for(
69  20ms); // Force at least 1-2 timer ticks for processing the event:
70  wxApp::GetInstance()->Yield(true);
71  }
72  int maxTimeout =
73 #ifdef _DEBUG
74  30000;
75 #else
76  6000;
77 #endif
78  // If we have an "MRPT_WXSUBSYS_TIMEOUT_MS" environment variable, use that
79  // timeout instead:
80  const char* envVal = getenv("MRPT_WXSUBSYS_TIMEOUT_MS");
81  if (envVal) maxTimeout = atoi(envVal);
82 
83  auto future = m_threadReady.get_future();
84  if (future.wait_for(std::chrono::milliseconds(maxTimeout)) ==
85  std::future_status::timeout) // 2 secs should be enough...
86  {
87  cerr << "[CBaseGUIWindow::ctor] Timeout waiting window creation."
88  << endl;
89  }
90 #else
91  THROW_EXCEPTION("MRPT compiled without wxWidgets!");
92 #endif
93  MRPT_END
94 }
95 
96 /*---------------------------------------------------------------
97  Dtor
98  ---------------------------------------------------------------*/
100 /*---------------------------------------------------------------
101  destroyWxWindow
102  ---------------------------------------------------------------*/
104 {
105  MRPT_START
106 #if MRPT_HAS_WXWIDGETS
107  // Send close request:
108  if (m_hwnd.get())
109  {
110  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
111  REQ->OPCODE = m_CMD_DESTROY_WIN;
112  REQ->source2D = static_cast<gui::CDisplayWindow*>(m_winobj_voidptr);
113  REQ->source3D = static_cast<gui::CDisplayWindow3D*>(m_winobj_voidptr);
114  REQ->sourcePlots =
116 
118 
119  // Wait until the thread ends:
121  {
122  std::this_thread::sleep_for(20ms); // Force at least 1-2 timer
123  // ticks for processing the
124  // event:
125  wxApp::GetInstance()->Yield(true);
126  }
127  const int maxTimeout =
128 #ifdef _DEBUG
129  30000;
130 #else
131  6000;
132 #endif
133  if (m_windowDestroyed.get_future().wait_for(std::chrono::milliseconds(
134  maxTimeout)) == std::future_status::timeout)
135  {
136  cerr << "[CBaseGUIWindow::dtor] Timeout waiting window destruction."
137  << endl;
138  }
139  }
141 #endif
142  MRPT_END
143 }
144 
145 /*---------------------------------------------------------------
146  notifyChildWindowDestruction
147  ---------------------------------------------------------------*/
149 /*---------------------------------------------------------------
150  waitForKey
151  ---------------------------------------------------------------*/
153  bool ignoreControlKeys, mrptKeyModifier* out_pushModifier)
154 {
155  int k = 0;
156  if (out_pushModifier) *out_pushModifier = MRPTKMOD_NONE;
157  m_keyPushed = false;
158 
159  for (;;)
160  {
161  if (os::kbhit())
162  {
163  k = os::getch();
164  return k;
165  }
166  if (m_keyPushed)
167  {
168  k = m_keyPushedCode;
169  m_keyPushed = false;
170  if (m_keyPushedCode < 256 || !ignoreControlKeys)
171  {
172  if (out_pushModifier) *out_pushModifier = m_keyPushedModifier;
173  return k;
174  }
175  // Ignore and keep waiting
176  }
177  std::this_thread::sleep_for(10ms);
178  // Are we still alive?
179  if (!isOpen()) return 0;
180  }
181 }
182 
183 /*---------------------------------------------------------------
184  getPushedKey
185  ---------------------------------------------------------------*/
187 {
188  if (out_pushModifier) *out_pushModifier = MRPTKMOD_NONE;
189 
190  if (!m_keyPushed) return 0;
191 
192  int k = m_keyPushedCode;
193  m_keyPushed = false;
194  if (out_pushModifier) *out_pushModifier = m_keyPushedModifier;
195  return k;
196 }
197 
198 /*---------------------------------------------------------------
199  isOpen
200  ---------------------------------------------------------------*/
201 bool CBaseGUIWindow::isOpen() { return m_hwnd != nullptr; }
202 /*---------------------------------------------------------------
203  notifySemThreadReady
204  ---------------------------------------------------------------*/
static void pushPendingWxRequest(TRequestToWxMainThread *data)
Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "ne...
const int m_CMD_CREATE_WIN
can be 200,300,400...
std::atomic_int m_keyPushedCode
#define MRPT_START
Definition: exceptions.h:241
int getPushedKey(mrptKeyModifier *out_pushModifier=nullptr)
Returns the latest pushed key, or 0 if there is no new key stroke.
The data structure for each inter-thread request:
Definition: WxSubsystem.h:189
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
Create a GUI window and display plots with MATLAB-like interfaces and commands.
int getch() noexcept
An OS-independent version of getch, which waits until a key is pushed.
Definition: os.cpp:370
mrpt::void_ptr_noncopy m_hwnd
The window handle.
std::string m_caption
The caption of the window.
int waitForKey(bool ignoreControlKeys=true, mrptKeyModifier *out_pushModifier=nullptr)
Waits for any key to be pushed on the image or the console, and returns the key code.
CBaseGUIWindow(void *winobj_voidptr, int CMD_CREATE_WIN, int CMD_DESTROY_WIN, const std::string &initial_caption=std::string())
CMD_DESTROY_WIN can be 299,399,499...
mrptKeyModifier
Definition: keycodes.h:156
STL namespace.
int OPCODE
Valid codes are: For CDisplayWindow:
Definition: WxSubsystem.h:283
void notifyChildWindowDestruction()
Called by wx main thread to set m_hwnd to NULL.
This class creates a window as a graphical user interface (GUI) for displaying images to the user...
bool isOpen()
Returns false if the user has already closed the window.
std::atomic< mrptKeyModifier > m_keyPushedModifier
const int m_CMD_DESTROY_WIN
can be 299,399,499...
std::promise< void > m_threadReady
This semaphore will be signaled when the wx window is built and ready.
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.
std::atomic_bool m_keyPushed
#define MRPT_END
Definition: exceptions.h:245
bool kbhit() noexcept
An OS-independent version of kbhit, which returns true if a key has been pushed.
Definition: os.cpp:392
void destroyWxWindow()
Must be called by child classes in their destructors.
static bool isConsoleApp()
Will be set to true at runtime if it&#39;s not detected a running wxApp instance.
Definition: WxSubsystem.cpp:53
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:14
void createWxWindow(unsigned int initialWidth, unsigned int initialHeight)
Must be called by child classes just within the constructor.
mrpt::gui::CDisplayWindow * source2D
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:195
void notifySemThreadReady()
Called by wx main thread to signal the semaphore that the wx window is built and ready.
std::promise< void > m_windowDestroyed
This semaphore will be signaled when the wx window is destroyed.
static bool createOneInstanceMainThread()
Thread-safe method to create one single instance of the main wxWidgets thread: it will create the thr...
A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.



Page generated by Doxygen 1.8.14 for MRPT 2.0.0 Git: b38439d21 Tue Mar 31 19:58:06 2020 +0200 at miƩ abr 1 00:50:30 CEST 2020