Main MRPT website > C++ reference
MRPT logo
WxSubsystem.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef  MRPT_WX_SUBSYSTEM_H
00029 #define  MRPT_WX_SUBSYSTEM_H
00030 
00031 #include <mrpt/opengl/opengl_fonts.h>
00032 #include <mrpt/utils/utils_defs.h>
00033 #include <mrpt/system/threads.h>
00034 #include <mrpt/config.h>
00035 #include <mrpt/synch.h>
00036 #include <mrpt/math/lightweight_geom_data.h>
00037 
00038 #include <mrpt/gui/link_pragmas.h>
00039 
00040 #include <queue>
00041 
00042 #if MRPT_HAS_WXWIDGETS
00043 
00044 // This is to prevent wxWidgets to include winsock.h, and
00045 //  later the user to include winsock2.h, what leads to conflicts:
00046 //#ifdef HAVE_WINSOCK2_H
00047 //# include <winsock2.h>
00048 //#endif
00049 
00050 #include <wx/sizer.h>
00051 #include <wx/statbmp.h>
00052 #include <wx/menu.h>
00053 #include <wx/toolbar.h>
00054 #include <wx/frame.h>
00055 #include <wx/timer.h>
00056 #include <wx/statusbr.h>
00057 #include <wx/msgdlg.h>
00058 #include <wx/artprov.h>
00059 #include <wx/bitmap.h>
00060 #include <wx/intl.h>
00061 #include <wx/image.h>
00062 #include <wx/string.h>
00063 #include <wx/msgdlg.h>
00064 #include <wx/filedlg.h>
00065 #include <wx/progdlg.h>
00066 #include <wx/imaglist.h>
00067 #include <wx/busyinfo.h>
00068 #include <wx/log.h>
00069 #include <wx/textdlg.h>
00070 #include <wx/dirdlg.h>
00071 #include <wx/colordlg.h>
00072 #include <wx/dcmemory.h>
00073 #include <wx/app.h>
00074 #include <wx/pen.h>
00075 
00076 // The wxMathPlot library
00077 #include <mrpt/otherlibs/mathplot/mathplot.h>
00078 
00079 #if 0
00080 // The wxFreeChart library
00081 #include <wx/chartpanel.h>
00082 #include <wx/bars/barplot.h>
00083 
00084 #include <wx/axis/numberaxis.h>
00085 #include <wx/axis/categoryaxis.h>
00086 #include <wx/axis/dateaxis.h>
00087 
00088 #include <wx/xy/xyhistorenderer.h>
00089 #include <wx/xy/xydataset.h>
00090 #include <wx/xy/xylinerenderer.h>
00091 #include <wx/xy/xyplot.h>
00092 #include <wx/xy/xysimpledataset.h>
00093 
00094 #include <wx/xyz/xyzdataset.h>
00095 #include <wx/xyz/bubbleplot.h>
00096 
00097 #include <wx/category/categorydataset.h>
00098 #include <wx/category/categorysimpledataset.h>
00099 #endif
00100 
00101 #endif
00102 
00103 namespace mrpt
00104 {
00105         namespace gui
00106         {
00107                 using namespace mrpt::system;
00108 
00109                 class CDisplayWindow;
00110                 class CDisplayWindow3D;
00111                 class CDisplayWindowPlots;
00112                 class CMyGLCanvas_DisplayWindow3D;
00113 
00114                 /** This class implements the GUI thread required for the wxWidgets-based GUI.
00115                   *  This system is employed internally by gui::CDisplayWindow and gui::CDisplayWindow3D, and must be not used in any way directly by the MRPT user.
00116                   *
00117                   *  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
00118                   *   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
00119                   *   is initialized and clean-up correctly.
00120                   *
00121                   *  This header should be included just from the implementation files of CDisplayWindow and CDisplayWindow3D, since it uses wxWidgets classes.
00122                   *
00123                   *  \sa gui::CDisplayWindow, gui::CDisplayWindow3D
00124                   * \ingroup mrpt_gui_grp
00125                   */
00126                 class GUI_IMPEXP WxSubsystem
00127                 {
00128         #if MRPT_HAS_WXWIDGETS
00129 
00130                 public:
00131 
00132                         /** 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.
00133                           */
00134                         static void waitWxShutdownsIfNoWindows();
00135 
00136                         /** Will be set to true at runtime if it's not detected a running wxApp instance.
00137                           *  For console apps, we'll create a new thread and run wxEntry from there.
00138                           *  For GUI apps (MRPT-based Windows are a part of a user wxWidget apps), we must leave the control of
00139                           *   message dispatching to the current main loop, so we cannot create a different threads, making things a little different (hence this variable).
00140                           */
00141                         static volatile bool isConsoleApp;
00142 
00143                         /** An auxiliary global object used just to launch a final request to the wxSubsystem for shutdown:
00144                           */
00145                         class CAuxWxSubsystemShutdowner
00146                         {
00147                         public:
00148                                 CAuxWxSubsystemShutdowner();
00149                                 ~CAuxWxSubsystemShutdowner();
00150                         };
00151 
00152                         static CAuxWxSubsystemShutdowner  global_wxsubsystem_shutdown;
00153 
00154 
00155                         /** The main frame of the wxWidgets application
00156                           */
00157                         class CWXMainFrame: public wxFrame
00158                         {
00159                         friend  void WxSubsystem::waitWxShutdownsIfNoWindows();
00160 
00161                                 public:
00162                                         CWXMainFrame(wxWindow* parent,wxWindowID id = -1);
00163                                         virtual ~CWXMainFrame();
00164 
00165                                         /** Atomically increments the number of windows created with the main frame as parent.
00166                                           * \return The updated number of windows.
00167                                           */
00168                                         static int notifyWindowCreation();
00169 
00170                                         /** Atomically decrements the number of windows created with the main frame as parent.
00171                                           * \return The updated number of windows (0 if the calling was the last one).
00172                                           */
00173                                         static int notifyWindowDestruction();
00174 
00175                                         static volatile CWXMainFrame* oneInstance;
00176 
00177 
00178                                 private:
00179 
00180                                         static synch::CCriticalSection     cs_windowCount;
00181                                         static int                         m_windowCount;
00182 
00183                                         wxTimer                         *m_theTimer;
00184 
00185                                         void OnTimerProcessRequests(wxTimerEvent& event);
00186 
00187                                         DECLARE_EVENT_TABLE()
00188 
00189                         }; // end class CWXMainFrame
00190 
00191                         struct TWxMainThreadData
00192                         {
00193                                 TWxMainThreadData();
00194 
00195                                 /** The thread ID of wxMainThread, or 0 if it is not running.
00196                                   */
00197                                 TThreadHandle  m_wxMainThreadId;
00198 
00199                                 /** This is signaled when wxMainThread is ready.
00200                                   */
00201                                 synch::CSemaphore m_semWxMainThreadReady;
00202 
00203                                 /** The critical section for accessing "m_wxMainThreadId"
00204                                   */
00205                                 synch::CCriticalSection m_csWxMainThreadId;
00206                         };
00207 
00208                         static TWxMainThreadData& GetWxMainThreadInstance();
00209 
00210 
00211                         /**  This will be the "MAIN" of wxWidgets: It starts an application object and does not end until all the windows are closed.
00212                           *   Only one instance of this thread can be running at a given instant, no matter how many windows are open.
00213                           */
00214                         static void     wxMainThread();
00215 
00216                         /** The data structure for each inter-thread request:
00217                           */
00218                         struct GUI_IMPEXP TRequestToWxMainThread
00219                         {
00220                         TRequestToWxMainThread() :
00221                                         source2D                ( NULL ),
00222                                         source3D                ( NULL ),
00223                                         sourcePlots             ( NULL ),
00224                                         sourceCameraSelectDialog(false),
00225                                         voidPtr                 (NULL),
00226                                         voidPtr2                (NULL),
00227                                         x                               (400),
00228                                         y                               (400),
00229                                         boolVal                 (false)
00230                         { }
00231 
00232                                 /** Only one of source* can be non-NULL, indicating the class that generated the request. */
00233                                 gui::CDisplayWindow    *source2D;
00234 
00235                                 /** Only one of source* can be non-NULL, indicating the class that generated the request. */
00236                                 gui::CDisplayWindow3D  *source3D;
00237 
00238                                 /** Only one of source* can be non-NULL, indicating the class that generated the request. */
00239                                 gui::CDisplayWindowPlots *sourcePlots;
00240 
00241                                 /** Only one of source* can be non-NULL, indicating the class that generated the request. */
00242                                 bool sourceCameraSelectDialog;
00243 
00244                                 /** Parameters, depending on OPCODE.
00245                                   */
00246                                 std::string  str;
00247 
00248                                 /** Parameters, depending on OPCODE.
00249                                   */
00250                                 void         *voidPtr, *voidPtr2;
00251                                 int          x,y;
00252                                 bool         boolVal;
00253                                 vector_float vector_x,vector_y;
00254                                 std::string  plotName;
00255 
00256                                 /** Valid codes are:
00257                                   *  For CDisplayWindow:
00258                                   *     - 200: Create a new 2D window, with caption "str" and initial size "x" & "y", and save the "wxFrame*" in the "void**" passed in voidPtr.
00259                                   *     - 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.
00260                                   *     - 202: Set position to x,y
00261                                   *     - 203: Change size to x,y
00262                                   *     - 204: Change title to "str"
00263                                   *     - 299: Delete the window associated with this source object.
00264                                   *
00265                                   *  For CDisplayWindow3D:
00266                                   *     - 300: Create a new 3D window, with caption "str" and initial size "x" & "y", and save the "wxFrame*" in the "void**" passed in voidPtr.
00267                                   *     - 302: Set position to x,y
00268                                   *     - 303: Change size to x,y
00269                                   *     - 304: Change title to "str"
00270                                   *             - 350: Force refresh
00271                                   *             - 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.
00272                                   *             - 361: Clear all 2D text messages.
00273                                   *             - 362: Add a 2D text message (vectorized fonts)
00274                                   *             - 370: Change min/max range: min=vector_x[0], max=vector_x[1]
00275                                   *     - 399: Delete the window associated with this source object.
00276                                   *
00277                                   *  For CDisplayWindowPlots:
00278                                   *     - 400: Create a new Plots window, with caption "str" and initial size "x" & "y",and save the "wxFrame*" in the "void**" passed in voidPtr.
00279                                   *     - 402: Set position to x,y
00280                                   *     - 403: Change size to x,y
00281                                   *     - 404: Change title to "str"
00282                                   *     - 499: Delete the window associated with this source object.
00283                                   *             - 410: Depending on "boolVal", enable/disable the mouse-zoom & pan
00284                                   *             - 411: Depending on "boolVal", enable/disable the aspect ratio fix
00285                                   *             - 412: Zoom over a rectangle vectorx[0-1] & vectory[0-1]
00286                                   *             - 413: Axis fit, with aspect ratio fix to boolVal.
00287                                   *             - 414: Clear all plot objects.
00288                                   *             - 420: Add/update a 2D line/points plot: x/y data= vector_x/vector_y, format string=str, plot name =plotName.
00289                                   *             - 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?
00290                                   *             - 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.
00291                                   *             - 440: Insert submenu in the popup menu. plotName=menu label, x=user-defined ID.
00292                                   *             - 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)
00293                                   *
00294                                   */
00295                                 int  OPCODE;
00296 
00297                         };
00298 
00299                         /** Thread-safe method to return the next pending request, or NULL if there is none (After usage, FREE the memory!)
00300                           */
00301                         static TRequestToWxMainThread  * popPendingWxRequest();
00302 
00303                         /** Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "new T[1]", will be freed by receiver.)
00304                           */
00305                         static void pushPendingWxRequest( TRequestToWxMainThread *data );
00306 
00307                         /** 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.
00308                           */
00309                         static bool createOneInstanceMainThread();
00310 
00311 
00312                         static wxBitmap getMRPTDefaultIcon();
00313                 private:
00314                         /** Do not access directly to this, use the thread-safe functions
00315                           */
00316                         static std::queue<TRequestToWxMainThread*>  *listPendingWxRequests;
00317                         static synch::CCriticalSection              *cs_listPendingWxRequests;
00318         #endif
00319                 }; // End of class def.
00320 
00321 
00322         #if MRPT_HAS_WXWIDGETS
00323 
00324                 /** The wx dialog for gui::CDisplayWindow
00325                   */
00326                 class CWindowDialog: public wxFrame
00327                 {
00328                 public:
00329                         /** A custom control to display the bitmap and avoid flicker
00330                           */
00331                         class wxMRPTImageControl : public wxPanel
00332                         {
00333                         protected:
00334                                 wxBitmap *m_img;
00335                                 mrpt::synch::CCriticalSection   m_img_cs;
00336                                 CDisplayWindow *m_win2D;
00337 
00338                         public:
00339                                 wxMRPTImageControl(     wxWindow *parent,wxWindowID winID,int x, int y, int width, int height);
00340                                 virtual ~wxMRPTImageControl();
00341 
00342                                 wxPoint m_last_mouse_point, m_last_mouse_click;
00343                                 //mrpt::synch::CCriticalSection m_mouse_cs;
00344 
00345                                 void AssignImage(wxBitmap *img); //!< Assigns this image. This object has the ownship of the image and will delete it when appropriate.
00346                                 void GetBitmap(wxBitmap &bmp);
00347 
00348                                 void OnPaint(wxPaintEvent &ev);
00349                                 void OnMouseMove(wxMouseEvent& ev);
00350                                 void OnMouseClick(wxMouseEvent& ev);
00351                                 void OnChar(wxKeyEvent& ev);
00352 
00353                                 void OnEraseBackground(wxEraseEvent &ev) { /* Do nothing */ }
00354                         };
00355 
00356 
00357 
00358                         public:
00359                                 CWindowDialog( CDisplayWindow *win2D, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindow]"), wxSize initialSize = wxDefaultSize );
00360                                 virtual ~CWindowDialog();
00361 
00362                                 CDisplayWindow *m_win2D;
00363                                 WxSubsystem::CWXMainFrame   *m_mainFrame;
00364 
00365                                 //wxStaticBitmap      *m_image;
00366                                 wxMRPTImageControl    *m_image;
00367 
00368                                 static const long         ID_IMAGE_BITMAP;
00369 
00370                         private:
00371 
00372                                 void OnClose (wxCloseEvent& event);
00373                                 void OnMenuClose(wxCommandEvent& event);
00374                                 void OnMenuAbout(wxCommandEvent& event);
00375                                 void OnMenuSave(wxCommandEvent& event);
00376                                 void OnChar(wxKeyEvent& event);
00377                                 void OnKeyDown(wxKeyEvent& event);
00378                                 void OnResize(wxSizeEvent& event);
00379                                 void OnMouseDown(wxMouseEvent& event);
00380 
00381                                 DECLARE_EVENT_TABLE()
00382                 }; // end class CWindowDialog
00383 
00384                 class C3DWindowDialog: public wxFrame
00385                 {
00386                         friend class gui::CMyGLCanvas_DisplayWindow3D;
00387 
00388                         public:
00389 
00390                                 C3DWindowDialog(CDisplayWindow3D *win3D, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindow3D]"), wxSize initialSize = wxDefaultSize );
00391                                 virtual ~C3DWindowDialog();
00392 
00393                                 CDisplayWindow3D *m_win3D;
00394                                 WxSubsystem::CWXMainFrame   *m_mainFrame;
00395 
00396                                 CMyGLCanvas_DisplayWindow3D     *m_canvas;
00397 
00398                                 void clearTextMessages();
00399                                 void addTextMessage(
00400                                         const double x_frac,
00401                                         const double y_frac,
00402                                         const std::string &text,
00403                                         const mrpt::utils::TColorf &color,
00404                                         const size_t unique_index,
00405                                         const mrpt::opengl::TOpenGLFont font
00406                                         );
00407                                 void addTextMessage(
00408                                         const double x_frac,
00409                                         const double y_frac,
00410                                         const std::string &text,
00411                                         const mrpt::utils::TColorf &color,
00412                                         const std::string  &font_name,
00413                                         const double  font_size,
00414                                         const mrpt::opengl::TOpenGLFontStyle font_style,
00415                                         const size_t  unique_index,
00416                                         const double  font_spacing,
00417                                         const double  font_kerning
00418                                         );
00419 
00420                         private:
00421 
00422                                 void OnClose (wxCloseEvent& event);
00423                                 void OnMenuClose(wxCommandEvent& event);
00424                                 void OnMenuAbout(wxCommandEvent& event);
00425                                 void OnChar(wxKeyEvent& event);
00426                                 void OnResize(wxSizeEvent& event);
00427 
00428                                 static const long ID_MENUITEM1;
00429                                 static const long ID_MENUITEM2;
00430 
00431                                 DECLARE_EVENT_TABLE()
00432                 };
00433 
00434                 /** The wx dialog for gui::CDisplayWindowPlots
00435                   */
00436                 class CWindowDialogPlots: public wxFrame
00437                 {
00438                         public:
00439                                 CWindowDialogPlots( CDisplayWindowPlots *winPlots, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindowPlots]"), wxSize initialSize = wxDefaultSize );
00440                                 virtual ~CWindowDialogPlots();
00441 
00442                                 CDisplayWindowPlots             *m_winPlots;
00443                                 WxSubsystem::CWXMainFrame   *m_mainFrame;
00444 
00445                                 mpWindow                                        *m_plot;
00446                                 // wxChartPanel                         *m_chartPanel;
00447                                 static const long           ID_PLOT;
00448                                 static const long           ID_MENU_PRINT;
00449                                 bool                        m_firstSubmenu; //!< to know whether to insert a separator the first time.
00450                                 std::map<long,long>                     m_ID2ID; //!< wxIDs to user IDs for submenus.
00451                                 mrpt::math::TPoint2D            m_curCursorPos;  //!< In graph coords
00452                                 wxPoint                                         m_last_mouse_point; //!< In pixels
00453 
00454                                 void OnMenuSelected(wxCommandEvent& ev);
00455                                 void OnMouseMove(wxMouseEvent& event);
00456 
00457 
00458                                 /** Redirected from CDisplayWindowPlots::plot
00459                                   */
00460                                 void plot(
00461                                         const vector_float &x,
00462                                         const vector_float &y,
00463                                         const std::string  &lineFormat,
00464                                         const std::string  &plotName);
00465 
00466                                 /** Redirected from CDisplayWindowPlots::plotEllipse
00467                                   */
00468                                 void plotEllipse(
00469                                         const vector_float &x,
00470                                         const vector_float &y,
00471                                         const std::string  &lineFormat,
00472                                         const std::string  &plotName,
00473                                         bool showName = false);
00474 
00475                                 /** Redirected from CDisplayWindowPlots::image
00476                                   */
00477                                 void image(
00478                                         void *theWxImage,
00479                                         const float &x0,
00480                                         const float &y0,
00481                                         const float &w,
00482                                         const float &h,
00483                                         const std::string &plotName);
00484 
00485                         private:
00486 
00487                                 void OnClose (wxCloseEvent& event);
00488                                 void OnMenuPrint(wxCommandEvent& event);
00489                                 void OnMenuClose(wxCommandEvent& event);
00490                                 void OnMenuAbout(wxCommandEvent& event);
00491                                 void OnChar(wxKeyEvent& event);
00492                                 void OnResize(wxSizeEvent& event);
00493                                 void OnMouseDown(wxMouseEvent& event);
00494 
00495                                 DECLARE_EVENT_TABLE()
00496                 }; // end class CWindowDialog
00497 
00498                 #ifndef _U
00499                         #ifdef wxUSE_UNICODE
00500                         #define _U(x) wxString((x),wxConvUTF8)
00501                         #define _UU(x,y) wxString((x),y)
00502                         #else
00503                         #define _U(x) (x)
00504                         #define _UU(x,y) (x)
00505                         #endif
00506                 #endif
00507 
00508 
00509         #endif
00510 
00511         } // End of namespace
00512 } // End of namespace
00513 
00514 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011