Main MRPT website > C++ reference
MRPT logo
WxSubsystem.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2014, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+ */
9 #ifndef MRPT_WX_SUBSYSTEM_H
10 #define MRPT_WX_SUBSYSTEM_H
11 
13 #include <mrpt/utils/utils_defs.h>
14 #include <mrpt/system/threads.h>
15 #include <mrpt/config.h>
16 #include <mrpt/synch.h>
18 #include <mrpt/utils/types_math.h>
19 
20 #include <mrpt/gui/link_pragmas.h>
21 
22 #include <queue>
23 #include <map>
24 
25 #if MRPT_HAS_WXWIDGETS
26 
27 // This is to prevent wxWidgets to include winsock.h, and
28 // later the user to include winsock2.h, what leads to conflicts:
29 //#ifdef HAVE_WINSOCK2_H
30 //# include <winsock2.h>
31 //#endif
32 
33 #include <wx/sizer.h>
34 #include <wx/statbmp.h>
35 #include <wx/menu.h>
36 #include <wx/toolbar.h>
37 #include <wx/frame.h>
38 #include <wx/timer.h>
39 #include <wx/statusbr.h>
40 #include <wx/msgdlg.h>
41 #include <wx/artprov.h>
42 #include <wx/bitmap.h>
43 #include <wx/intl.h>
44 #include <wx/image.h>
45 #include <wx/string.h>
46 #include <wx/msgdlg.h>
47 #include <wx/filedlg.h>
48 #include <wx/progdlg.h>
49 #include <wx/imaglist.h>
50 #include <wx/busyinfo.h>
51 #include <wx/log.h>
52 #include <wx/textdlg.h>
53 #include <wx/dirdlg.h>
54 #include <wx/colordlg.h>
55 #include <wx/dcmemory.h>
56 #include <wx/app.h>
57 #include <wx/pen.h>
58 
59 // The wxMathPlot library
61 
62 #if 0
63 // The wxFreeChart library
64 #include <wx/chartpanel.h>
65 #include <wx/bars/barplot.h>
66 
67 #include <wx/axis/numberaxis.h>
68 #include <wx/axis/categoryaxis.h>
69 #include <wx/axis/dateaxis.h>
70 
71 #include <wx/xy/xyhistorenderer.h>
72 #include <wx/xy/xydataset.h>
73 #include <wx/xy/xylinerenderer.h>
74 #include <wx/xy/xyplot.h>
75 #include <wx/xy/xysimpledataset.h>
76 
77 #include <wx/xyz/xyzdataset.h>
78 #include <wx/xyz/bubbleplot.h>
79 
80 #include <wx/category/categorydataset.h>
81 #include <wx/category/categorysimpledataset.h>
82 #endif
83 
84 #endif
85 
86 namespace mrpt
87 {
88  namespace gui
89  {
90  using namespace mrpt::system;
91 
92  class CDisplayWindow;
93  class CDisplayWindow3D;
94  class CDisplayWindowPlots;
95  class CMyGLCanvas_DisplayWindow3D;
96 
97  /** This class implements the GUI thread required for the wxWidgets-based GUI.
98  * This system is employed internally by gui::CDisplayWindow and gui::CDisplayWindow3D, and must be not used in any way directly by the MRPT user.
99  *
100  * The system works by creating a invisible wxFrame that process timer events where it checks a queue of requests sent from the main MRPT thread. The
101  * requests include the creation, deletion,... of windows (2D/3D). In that way, just one thread is required for all the GUI windows, and the wxWidgets
102  * is initialized and clean-up correctly.
103  *
104  * This header should be included just from the implementation files of CDisplayWindow and CDisplayWindow3D, since it uses wxWidgets classes.
105  *
106  * \sa gui::CDisplayWindow, gui::CDisplayWindow3D
107  * \ingroup mrpt_gui_grp
108  */
110  {
111  #if MRPT_HAS_WXWIDGETS
112 
113  public:
114 
115  /** 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.
116  */
117  static void waitWxShutdownsIfNoWindows();
118 
119  /** Will be set to true at runtime if it's not detected a running wxApp instance.
120  * For console apps, we'll create a new thread and run wxEntry from there.
121  * For GUI apps (MRPT-based Windows are a part of a user wxWidget apps), we must leave the control of
122  * message dispatching to the current main loop, so we cannot create a different threads, making things a little different (hence this variable).
123  */
124  static volatile bool isConsoleApp;
125 
126  /** An auxiliary global object used just to launch a final request to the wxSubsystem for shutdown:
127  */
128  class CAuxWxSubsystemShutdowner
129  {
130  public:
131  CAuxWxSubsystemShutdowner();
132  ~CAuxWxSubsystemShutdowner();
133  };
134 
135  static CAuxWxSubsystemShutdowner global_wxsubsystem_shutdown;
136 
137 
138  /** The main frame of the wxWidgets application
139  */
140  class CWXMainFrame: public wxFrame
141  {
142  friend void WxSubsystem::waitWxShutdownsIfNoWindows();
143 
144  public:
145  CWXMainFrame(wxWindow* parent,wxWindowID id = -1);
146  virtual ~CWXMainFrame();
147 
148  /** Atomically increments the number of windows created with the main frame as parent.
149  * \return The updated number of windows.
150  */
151  static int notifyWindowCreation();
152 
153  /** Atomically decrements the number of windows created with the main frame as parent.
154  * \return The updated number of windows (0 if the calling was the last one).
155  */
156  static int notifyWindowDestruction();
157 
158  static volatile CWXMainFrame* oneInstance;
159 
160 
161  private:
162 
163  static synch::CCriticalSection cs_windowCount;
164  static int m_windowCount;
165 
166  wxTimer *m_theTimer;
167 
168  void OnTimerProcessRequests(wxTimerEvent& event);
169 
170  DECLARE_EVENT_TABLE()
171 
172  }; // end class CWXMainFrame
173 
174  struct TWxMainThreadData
175  {
176  TWxMainThreadData();
177 
178  /** The thread ID of wxMainThread, or 0 if it is not running.
179  */
180  TThreadHandle m_wxMainThreadId;
181 
182  /** This is signaled when wxMainThread is ready.
183  */
184  synch::CSemaphore m_semWxMainThreadReady;
185 
186  /** The critical section for accessing "m_wxMainThreadId"
187  */
188  synch::CCriticalSection m_csWxMainThreadId;
189  };
190 
191  static TWxMainThreadData& GetWxMainThreadInstance();
192 
193 
194  /** This will be the "MAIN" of wxWidgets: It starts an application object and does not end until all the windows are closed.
195  * Only one instance of this thread can be running at a given instant, no matter how many windows are open.
196  */
197  static void wxMainThread();
198 
199  /** The data structure for each inter-thread request:
200  */
201  struct GUI_IMPEXP TRequestToWxMainThread
202  {
203  TRequestToWxMainThread() :
204  source2D ( NULL ),
205  source3D ( NULL ),
206  sourcePlots ( NULL ),
207  sourceCameraSelectDialog(false),
208  voidPtr (NULL),
209  voidPtr2 (NULL),
210  x (400),
211  y (400),
212  boolVal (false)
213  { }
214 
215  /** Only one of source* can be non-NULL, indicating the class that generated the request. */
216  gui::CDisplayWindow *source2D;
217 
218  /** Only one of source* can be non-NULL, indicating the class that generated the request. */
219  gui::CDisplayWindow3D *source3D;
220 
221  /** Only one of source* can be non-NULL, indicating the class that generated the request. */
222  gui::CDisplayWindowPlots *sourcePlots;
223 
224  /** Only one of source* can be non-NULL, indicating the class that generated the request. */
225  bool sourceCameraSelectDialog;
226 
227  /** Parameters, depending on OPCODE.
228  */
229  std::string str;
230 
231  /** Parameters, depending on OPCODE.
232  */
233  void *voidPtr, *voidPtr2;
234  int x,y;
235  bool boolVal;
236  mrpt::math::CVectorFloat vector_x,vector_y;
237  std::string plotName;
238 
239  /** Valid codes are:
240  * For CDisplayWindow:
241  * - 200: Create a new 2D window, with caption "str" and initial size "x" & "y", and save the "wxFrame*" in the "void**" passed in voidPtr.
242  * - 201: Updates the image shown in the window, from a "wxImage*" passed in voidPtr2. The wxImage object will be freed with delete after that. voidPtr must be a "wxFrame*", a "CWindowDialog*" actually.
243  * - 202: Set position to x,y
244  * - 203: Change size to x,y
245  * - 204: Change title to "str"
246  * - 299: Delete the window associated with this source object.
247  *
248  * For CDisplayWindow3D:
249  * - 300: Create a new 3D window, with caption "str" and initial size "x" & "y", and save the "wxFrame*" in the "void**" passed in voidPtr.
250  * - 302: Set position to x,y
251  * - 303: Change size to x,y
252  * - 304: Change title to "str"
253  * - 350: Force refresh
254  * - 360: Add a 2D text message: vector_x: [0]:x, [1]:y, [2,3,4]:R G B, "x": enum of desired font. "y": unique index, "str": String.
255  * - 361: Clear all 2D text messages.
256  * - 362: Add a 2D text message (vectorized fonts)
257  * - 370: Change min/max range: min=vector_x[0], max=vector_x[1]
258  * - 399: Delete the window associated with this source object.
259  *
260  * For CDisplayWindowPlots:
261  * - 400: Create a new Plots window, with caption "str" and initial size "x" & "y",and save the "wxFrame*" in the "void**" passed in voidPtr.
262  * - 402: Set position to x,y
263  * - 403: Change size to x,y
264  * - 404: Change title to "str"
265  * - 499: Delete the window associated with this source object.
266  * - 410: Depending on "boolVal", enable/disable the mouse-zoom & pan
267  * - 411: Depending on "boolVal", enable/disable the aspect ratio fix
268  * - 412: Zoom over a rectangle vectorx[0-1] & vectory[0-1]
269  * - 413: Axis fit, with aspect ratio fix to boolVal.
270  * - 414: Clear all plot objects.
271  * - 420: Add/update a 2D line/points plot: x/y data= vector_x/vector_y, format string=str, plot name =plotName.
272  * - 421: Add/update a 2D ellipse: format string=str, plot name =plotName, vector_x[0,1]:X/Y center, vector_x[2]:quantiles, vector_y[0,1,2]: Covariance matrix entries 00,11,01, boolVal=showName?
273  * - 422: Add/update a bitmap: plot name =plotName, vector_x[0,1]:X/Y corner, vector_x[2,3]: X/Y widths, voidPtr2: pointer to a newly created wxImage with the bitmap.
274  * - 440: Insert submenu in the popup menu. plotName=menu label, x=user-defined ID.
275  * - 700: Shows a camera-pick-dialog and wait for user selection. "voidPtr" must point to a CSemaphore, which will be signaled twice (1st upon construction, 2nd upon dialog close); voidPtr2 must point to a "mrpt::gui::CPanelCameraSelection*" which will be filled with the selection (the panel must be deleted by the caller)
276  *
277  */
278  int OPCODE;
279 
280  };
281 
282  /** Thread-safe method to return the next pending request, or NULL if there is none (After usage, FREE the memory!)
283  */
284  static TRequestToWxMainThread * popPendingWxRequest();
285 
286  /** Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "new T[1]", will be freed by receiver.)
287  */
288  static void pushPendingWxRequest( TRequestToWxMainThread *data );
289 
290  /** Thread-safe method to create one single instance of the main wxWidgets thread: it will create the thread only if it is not running yet.
291  */
292  static bool createOneInstanceMainThread();
293 
294 
295  static wxBitmap getMRPTDefaultIcon();
296  private:
297  /** Do not access directly to this, use the thread-safe functions
298  */
299  static std::queue<TRequestToWxMainThread*> *listPendingWxRequests;
300  static synch::CCriticalSection *cs_listPendingWxRequests;
301  #endif
302  }; // End of class def.
303 
304 
305  #if MRPT_HAS_WXWIDGETS
306 
307  /** The wx dialog for gui::CDisplayWindow
308  */
309  class CWindowDialog: public wxFrame
310  {
311  public:
312  /** A custom control to display the bitmap and avoid flicker
313  */
314  class wxMRPTImageControl : public wxPanel
315  {
316  protected:
317  wxBitmap *m_img;
319  CDisplayWindow *m_win2D;
320 
321  public:
322  wxMRPTImageControl( wxWindow *parent,wxWindowID winID,int x, int y, int width, int height);
323  virtual ~wxMRPTImageControl();
324 
325  wxPoint m_last_mouse_point, m_last_mouse_click;
326  //mrpt::synch::CCriticalSection m_mouse_cs;
327 
328  void AssignImage(wxBitmap *img); //!< Assigns this image. This object has the ownship of the image and will delete it when appropriate.
329  void GetBitmap(wxBitmap &bmp);
330 
331  void OnPaint(wxPaintEvent &ev);
332  void OnMouseMove(wxMouseEvent& ev);
333  void OnMouseClick(wxMouseEvent& ev);
334  void OnChar(wxKeyEvent& ev);
335 
336  void OnEraseBackground(wxEraseEvent &ev) { /* Do nothing */ }
337  };
338 
339 
340 
341  public:
342  CWindowDialog( CDisplayWindow *win2D, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindow]"), wxSize initialSize = wxDefaultSize );
343  virtual ~CWindowDialog();
344 
345  CDisplayWindow *m_win2D;
346  WxSubsystem::CWXMainFrame *m_mainFrame;
347 
348  //wxStaticBitmap *m_image;
349  wxMRPTImageControl *m_image;
350 
351  static const long ID_IMAGE_BITMAP;
352 
353  private:
354 
355  void OnClose (wxCloseEvent& event);
356  void OnMenuClose(wxCommandEvent& event);
357  void OnMenuAbout(wxCommandEvent& event);
358  void OnMenuSave(wxCommandEvent& event);
359  void OnChar(wxKeyEvent& event);
360  void OnKeyDown(wxKeyEvent& event);
361  void OnResize(wxSizeEvent& event);
362  void OnMouseDown(wxMouseEvent& event);
363 
364  DECLARE_EVENT_TABLE()
365  }; // end class CWindowDialog
366 
367  class C3DWindowDialog: public wxFrame
368  {
369  friend class gui::CMyGLCanvas_DisplayWindow3D;
370 
371  public:
372 
373  C3DWindowDialog(CDisplayWindow3D *win3D, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindow3D]"), wxSize initialSize = wxDefaultSize );
374  virtual ~C3DWindowDialog();
375 
376  CDisplayWindow3D *m_win3D;
377  WxSubsystem::CWXMainFrame *m_mainFrame;
378 
379  CMyGLCanvas_DisplayWindow3D *m_canvas;
380 
381  void clearTextMessages();
382  void addTextMessage(
383  const double x_frac,
384  const double y_frac,
385  const std::string &text,
386  const mrpt::utils::TColorf &color,
387  const size_t unique_index,
388  const mrpt::opengl::TOpenGLFont font
389  );
390  void addTextMessage(
391  const double x_frac,
392  const double y_frac,
393  const std::string &text,
394  const mrpt::utils::TColorf &color,
395  const std::string &font_name,
396  const double font_size,
397  const mrpt::opengl::TOpenGLFontStyle font_style,
398  const size_t unique_index,
399  const double font_spacing,
400  const double font_kerning,
401  const bool has_shadow,
402  const mrpt::utils::TColorf &shadow_color
403  );
404 
405  private:
406 
407  void OnClose (wxCloseEvent& event);
408  void OnMenuClose(wxCommandEvent& event);
409  void OnMenuAbout(wxCommandEvent& event);
410  void OnChar(wxKeyEvent& event);
411  void OnResize(wxSizeEvent& event);
412 
413  static const long ID_MENUITEM1;
414  static const long ID_MENUITEM2;
415 
416  DECLARE_EVENT_TABLE()
417  };
418 
419  /** The wx dialog for gui::CDisplayWindowPlots
420  */
421  class CWindowDialogPlots: public wxFrame
422  {
423  public:
424  CWindowDialogPlots( CDisplayWindowPlots *winPlots, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindowPlots]"), wxSize initialSize = wxDefaultSize );
425  virtual ~CWindowDialogPlots();
426 
427  CDisplayWindowPlots *m_winPlots;
428  WxSubsystem::CWXMainFrame *m_mainFrame;
429 
430  mpWindow *m_plot;
431  // wxChartPanel *m_chartPanel;
432  static const long ID_PLOT;
433  static const long ID_MENU_PRINT;
434  bool m_firstSubmenu; //!< to know whether to insert a separator the first time.
435  std::map<long,long> m_ID2ID; //!< wxIDs to user IDs for submenus.
436  mrpt::math::TPoint2D m_curCursorPos; //!< In graph coords
437  wxPoint m_last_mouse_point; //!< In pixels
438 
439  void OnMenuSelected(wxCommandEvent& ev);
440  void OnMouseMove(wxMouseEvent& event);
441 
442 
443  /** Redirected from CDisplayWindowPlots::plot
444  */
445  void plot(
446  const mrpt::math::CVectorFloat &x,
447  const mrpt::math::CVectorFloat &y,
448  const std::string &lineFormat,
449  const std::string &plotName);
450 
451  /** Redirected from CDisplayWindowPlots::plotEllipse
452  */
453  void plotEllipse(
454  const mrpt::math::CVectorFloat &x,
455  const mrpt::math::CVectorFloat &y,
456  const std::string &lineFormat,
457  const std::string &plotName,
458  bool showName = false);
459 
460  /** Redirected from CDisplayWindowPlots::image
461  */
462  void image(
463  void *theWxImage,
464  const float &x0,
465  const float &y0,
466  const float &w,
467  const float &h,
468  const std::string &plotName);
469 
470  private:
471 
472  void OnClose (wxCloseEvent& event);
473  void OnMenuPrint(wxCommandEvent& event);
474  void OnMenuClose(wxCommandEvent& event);
475  void OnMenuAbout(wxCommandEvent& event);
476  void OnChar(wxKeyEvent& event);
477  void OnResize(wxSizeEvent& event);
478  void OnMouseDown(wxMouseEvent& event);
479 
480  DECLARE_EVENT_TABLE()
481  }; // end class CWindowDialog
482 
483  #ifndef _U
484  #ifdef wxUSE_UNICODE
485  #define _U(x) wxString((x),wxConvUTF8)
486  #define _UU(x,y) wxString((x),y)
487  #else
488  #define _U(x) (x)
489  #define _UU(x,y) (x)
490  #endif
491  #endif
492 
493  #endif
494 
495  } // End of namespace
496 } // End of namespace
497 
498 #endif
This class provides simple critical sections functionality.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:30
Create a GUI window and display plots with MATLAB-like interfaces and commands.
Canvas for plotting mpLayer implementations.
Definition: mathplot.h:841
TOpenGLFont
Existing fonts for 2D texts in mrpt::opengl methods.
Definition: opengl_fonts.h:26
TOpenGLFontStyle
Different style for vectorized font rendering.
Definition: opengl_fonts.h:37
This class creates a window as a graphical user interface (GUI) for displaying images to the user...
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:51
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.
Definition: WxSubsystem.h:109
This structure contains the information needed to interface the threads API on each platform: ...
Definition: threads.h:25
A RGB color - floats in the range [0,1].
Definition: TColor.h:52
Lightweight 2D point.
A semaphore for inter-thread synchronization.
Definition: CSemaphore.h:31
A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.



Page generated by Doxygen 1.8.8 for MRPT 1.2.2 SVN:Unversioned directory at Tue Oct 14 02:14:08 UTC 2014