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://mrpt.sourceforge.net/                            |
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                   */
00125                 class GUI_IMPEXP WxSubsystem
00126                 {
00127         #if MRPT_HAS_WXWIDGETS
00128 
00129                 public:
00130 
00131                         /** 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.
00132                           */
00133                         static void waitWxShutdownsIfNoWindows();
00134 
00135                         /** Will be set to true at runtime if it's not detected a running wxApp instance.
00136                           *  For console apps, we'll create a new thread and run wxEntry from there.
00137                           *  For GUI apps (MRPT-based Windows are a part of a user wxWidget apps), we must leave the control of
00138                           *   message dispatching to the current main loop, so we cannot create a different threads, making things a little different (hence this variable).
00139                           */
00140                         static volatile bool isConsoleApp;
00141 
00142                         /** An auxiliary global object used just to launch a final request to the wxSubsystem for shutdown:
00143                           */
00144                         class CAuxWxSubsystemShutdowner
00145                         {
00146                         public:
00147                                 CAuxWxSubsystemShutdowner();
00148                                 ~CAuxWxSubsystemShutdowner();
00149                         };
00150 
00151                         static CAuxWxSubsystemShutdowner  global_wxsubsystem_shutdown;
00152 
00153 
00154                         /** The main frame of the wxWidgets application
00155                           */
00156                         class CWXMainFrame: public wxFrame
00157                         {
00158                         friend  void WxSubsystem::waitWxShutdownsIfNoWindows();
00159 
00160                                 public:
00161                                         CWXMainFrame(wxWindow* parent,wxWindowID id = -1);
00162                                         virtual ~CWXMainFrame();
00163 
00164                                         /** Atomically increments the number of windows created with the main frame as parent.
00165                                           * \return The updated number of windows.
00166                                           */
00167                                         static int notifyWindowCreation();
00168 
00169                                         /** Atomically decrements the number of windows created with the main frame as parent.
00170                                           * \return The updated number of windows (0 if the calling was the last one).
00171                                           */
00172                                         static int notifyWindowDestruction();
00173 
00174                                         static volatile CWXMainFrame* oneInstance;
00175 
00176 
00177                                 private:
00178 
00179                                         static synch::CCriticalSection     cs_windowCount;
00180                                         static int                         m_windowCount;
00181 
00182                                         wxTimer                         *m_theTimer;
00183 
00184                                         void OnTimerProcessRequests(wxTimerEvent& event);
00185 
00186                                         DECLARE_EVENT_TABLE()
00187 
00188                         }; // end class CWXMainFrame
00189 
00190                         struct TWxMainThreadData
00191                         {
00192                                 TWxMainThreadData();
00193 
00194                                 /** The thread ID of wxMainThread, or 0 if it is not running.
00195                                   */
00196                                 TThreadHandle  m_wxMainThreadId;
00197 
00198                                 /** This is signaled when wxMainThread is ready.
00199                                   */
00200                                 synch::CSemaphore m_semWxMainThreadReady;
00201 
00202                                 /** The critical section for accessing "m_wxMainThreadId"
00203                                   */
00204                                 synch::CCriticalSection m_csWxMainThreadId;
00205                         };
00206 
00207                         static TWxMainThreadData& GetWxMainThreadInstance();
00208 
00209 
00210                         /**  This will be the "MAIN" of wxWidgets: It starts an application object and does not end until all the windows are closed.
00211                           *   Only one instance of this thread can be running at a given instant, no matter how many windows are open.
00212                           */
00213                         static void     wxMainThread();
00214 
00215                         /** The data structure for each inter-thread request:
00216                           */
00217                         struct GUI_IMPEXP TRequestToWxMainThread
00218                         {
00219                         TRequestToWxMainThread() :
00220                                         source2D                ( NULL ),
00221                                         source3D                ( NULL ),
00222                                         sourcePlots             ( NULL ),
00223                                         sourceCameraSelectDialog(false),
00224                                         voidPtr                 (NULL),
00225                                         voidPtr2                (NULL),
00226                                         x                               (400),
00227                                         y                               (400),
00228                                         boolVal                 (false)
00229                         { }
00230 
00231                                 /** Only one of source* can be non-NULL, indicating the class that generated the request. */
00232                                 gui::CDisplayWindow    *source2D;
00233 
00234                                 /** Only one of source* can be non-NULL, indicating the class that generated the request. */
00235                                 gui::CDisplayWindow3D  *source3D;
00236 
00237                                 /** Only one of source* can be non-NULL, indicating the class that generated the request. */
00238                                 gui::CDisplayWindowPlots *sourcePlots;
00239 
00240                                 /** Only one of source* can be non-NULL, indicating the class that generated the request. */
00241                                 bool sourceCameraSelectDialog;
00242 
00243                                 /** Parameters, depending on OPCODE.
00244                                   */
00245                                 std::string  str;
00246 
00247                                 /** Parameters, depending on OPCODE.
00248                                   */
00249                                 void         *voidPtr, *voidPtr2;
00250                                 int          x,y;
00251                                 bool         boolVal;
00252                                 vector_float vector_x,vector_y;
00253                                 std::string  plotName;
00254 
00255                                 /** Valid codes are:
00256                                   *  For CDisplayWindow:
00257                                   *     - 200: Create a new 2D window, with caption "str" and initial size "x" & "y", and save the "wxFrame*" in the "void**" passed in voidPtr.
00258                                   *     - 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.
00259                                   *     - 202: Set position to x,y
00260                                   *     - 203: Change size to x,y
00261                                   *     - 204: Change title to "str"
00262                                   *     - 299: Delete the window associated with this source object.
00263                                   *
00264                                   *  For CDisplayWindow3D:
00265                                   *     - 300: Create a new 3D window, with caption "str" and initial size "x" & "y", and save the "wxFrame*" in the "void**" passed in voidPtr.
00266                                   *     - 302: Set position to x,y
00267                                   *     - 303: Change size to x,y
00268                                   *     - 304: Change title to "str"
00269                                   *             - 350: Force refresh
00270                                   *             - 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.
00271                                   *             - 361: Clear all 2D text messages.
00272                                   *             - 370: Change min/max range: min=vector_x[0], max=vector_x[1]
00273                                   *     - 399: Delete the window associated with this source object.
00274                                   *
00275                                   *  For CDisplayWindowPlots:
00276                                   *     - 400: Create a new Plots window, with caption "str" and initial size "x" & "y",and save the "wxFrame*" in the "void**" passed in voidPtr.
00277                                   *     - 402: Set position to x,y
00278                                   *     - 403: Change size to x,y
00279                                   *     - 404: Change title to "str"
00280                                   *     - 499: Delete the window associated with this source object.
00281                                   *             - 410: Depending on "boolVal", enable/disable the mouse-zoom & pan
00282                                   *             - 411: Depending on "boolVal", enable/disable the aspect ratio fix
00283                                   *             - 412: Zoom over a rectangle vectorx[0-1] & vectory[0-1]
00284                                   *             - 413: Axis fit, with aspect ratio fix to boolVal.
00285                                   *             - 414: Clear all plot objects.
00286                                   *             - 420: Add/update a 2D line/points plot: x/y data= vector_x/vector_y, format string=str, plot name =plotName.
00287                                   *             - 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?
00288                                   *             - 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.
00289                                   *             - 440: Insert submenu in the popup menu. plotName=menu label, x=user-defined ID.
00290                                   *             - 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)
00291                                   *
00292                                   */
00293                                 int  OPCODE;
00294 
00295                         };
00296 
00297                         /** Thread-safe method to return the next pending request, or NULL if there is none (After usage, FREE the memory!)
00298                           */
00299                         static TRequestToWxMainThread  * popPendingWxRequest();
00300 
00301                         /** Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "new T[1]", will be freed by receiver.)
00302                           */
00303                         static void pushPendingWxRequest( TRequestToWxMainThread *data );
00304 
00305                         /** 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.
00306                           */
00307                         static bool createOneInstanceMainThread();
00308 
00309 
00310                         static wxBitmap getMRPTDefaultIcon();
00311                 private:
00312                         /** Do not access directly to this, use the thread-safe functions
00313                           */
00314                         static std::queue<TRequestToWxMainThread*>  *listPendingWxRequests;
00315                         static synch::CCriticalSection              *cs_listPendingWxRequests;
00316         #endif
00317                 }; // End of class def.
00318 
00319 
00320         #if MRPT_HAS_WXWIDGETS
00321 
00322                 /** The wx dialog for gui::CDisplayWindow
00323                   */
00324                 class CWindowDialog: public wxFrame
00325                 {
00326                 public:
00327                         /** A custom control to display the bitmap and avoid flicker
00328                           */
00329                         class wxMRPTImageControl : public wxPanel
00330                         {
00331                         protected:
00332                                 wxBitmap *m_img;
00333                                 mrpt::synch::CCriticalSection   m_img_cs;
00334                                 CDisplayWindow *m_win2D;
00335 
00336                         public:
00337                                 wxMRPTImageControl(     wxWindow *parent,wxWindowID winID,int x, int y, int width, int height);
00338                                 virtual ~wxMRPTImageControl();
00339 
00340                                 wxPoint m_last_mouse_point, m_last_mouse_click;
00341                                 //mrpt::synch::CCriticalSection m_mouse_cs;
00342 
00343                                 void AssignImage(wxBitmap *img); //!< Assigns this image. This object has the ownship of the image and will delete it when appropriate.
00344                                 void GetBitmap(wxBitmap &bmp);
00345 
00346                                 void OnPaint(wxPaintEvent &ev);
00347                                 void OnMouseMove(wxMouseEvent& ev);
00348                                 void OnMouseClick(wxMouseEvent& ev);
00349                                 void OnChar(wxKeyEvent& ev);
00350 
00351                                 void OnEraseBackground(wxEraseEvent &ev) { /* Do nothing */ }
00352                         };
00353 
00354 
00355 
00356                         public:
00357                                 CWindowDialog( CDisplayWindow *win2D, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindow]"), wxSize initialSize = wxDefaultSize );
00358                                 virtual ~CWindowDialog();
00359 
00360                                 CDisplayWindow *m_win2D;
00361                                 WxSubsystem::CWXMainFrame   *m_mainFrame;
00362 
00363                                 //wxStaticBitmap      *m_image;
00364                                 wxMRPTImageControl    *m_image;
00365 
00366                                 static const long         ID_IMAGE_BITMAP;
00367 
00368                         private:
00369 
00370                                 void OnClose (wxCloseEvent& event);
00371                                 void OnMenuClose(wxCommandEvent& event);
00372                                 void OnMenuAbout(wxCommandEvent& event);
00373                                 void OnMenuSave(wxCommandEvent& event);
00374                                 void OnChar(wxKeyEvent& event);
00375                                 void OnKeyDown(wxKeyEvent& event);
00376                                 void OnResize(wxSizeEvent& event);
00377                                 void OnMouseDown(wxMouseEvent& event);
00378 
00379                                 DECLARE_EVENT_TABLE()
00380                 }; // end class CWindowDialog
00381 
00382                 class C3DWindowDialog: public wxFrame
00383                 {
00384                         friend class gui::CMyGLCanvas_DisplayWindow3D;
00385 
00386                         public:
00387 
00388                                 C3DWindowDialog(CDisplayWindow3D *win3D, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindow3D]"), wxSize initialSize = wxDefaultSize );
00389                                 virtual ~C3DWindowDialog();
00390 
00391                                 CDisplayWindow3D *m_win3D;
00392                                 WxSubsystem::CWXMainFrame   *m_mainFrame;
00393 
00394                                 CMyGLCanvas_DisplayWindow3D     *m_canvas;
00395 
00396                                 void clearTextMessages();
00397                                 void addTextMessage(
00398                                         const double x_frac,
00399                                         const double y_frac,
00400                                         const std::string &text,
00401                                         const mrpt::utils::TColorf &color,
00402                                         const size_t unique_index,
00403                                         const mrpt::opengl::TOpenGLFont font
00404                                         );
00405 
00406                         private:
00407 
00408                                 void OnClose (wxCloseEvent& event);
00409                                 void OnMenuClose(wxCommandEvent& event);
00410                                 void OnMenuAbout(wxCommandEvent& event);
00411                                 void OnChar(wxKeyEvent& event);
00412                                 void OnResize(wxSizeEvent& event);
00413 
00414                                 static const long ID_MENUITEM1;
00415                                 static const long ID_MENUITEM2;
00416 
00417                                 DECLARE_EVENT_TABLE()
00418                 };
00419 
00420                 /** The wx dialog for gui::CDisplayWindowPlots
00421                   */
00422                 class CWindowDialogPlots: public wxFrame
00423                 {
00424                         public:
00425                                 CWindowDialogPlots( CDisplayWindowPlots *winPlots, WxSubsystem::CWXMainFrame* parent,wxWindowID id = -1, const std::string &caption = std::string("[MRPT-CDisplayWindowPlots]"), wxSize initialSize = wxDefaultSize );
00426                                 virtual ~CWindowDialogPlots();
00427 
00428                                 CDisplayWindowPlots             *m_winPlots;
00429                                 WxSubsystem::CWXMainFrame   *m_mainFrame;
00430 
00431                                 mpWindow                                        *m_plot;
00432                                 // wxChartPanel                         *m_chartPanel;
00433                                 static const long           ID_PLOT;
00434                                 static const long           ID_MENU_PRINT;
00435                                 bool                        m_firstSubmenu; //!< to know whether to insert a separator the first time.
00436                                 std::map<long,long>                     m_ID2ID; //!< wxIDs to user IDs for submenus.
00437                                 mrpt::math::TPoint2D            m_curCursorPos;  //!< In graph coords
00438                                 wxPoint                                         m_last_mouse_point; //!< In pixels
00439 
00440                                 void OnMenuSelected(wxCommandEvent& ev);
00441                                 void OnMouseMove(wxMouseEvent& event);
00442 
00443 
00444                                 /** Redirected from CDisplayWindowPlots::plot
00445                                   */
00446                                 void plot(
00447                                         const vector_float &x,
00448                                         const vector_float &y,
00449                                         const std::string  &lineFormat,
00450                                         const std::string  &plotName);
00451 
00452                                 /** Redirected from CDisplayWindowPlots::plotEllipse
00453                                   */
00454                                 void plotEllipse(
00455                                         const vector_float &x,
00456                                         const vector_float &y,
00457                                         const std::string  &lineFormat,
00458                                         const std::string  &plotName,
00459                                         bool showName = false);
00460 
00461                                 /** Redirected from CDisplayWindowPlots::image
00462                                   */
00463                                 void image(
00464                                         void *theWxImage,
00465                                         const float &x0,
00466                                         const float &y0,
00467                                         const float &w,
00468                                         const float &h,
00469                                         const std::string &plotName);
00470 
00471                         private:
00472 
00473                                 void OnClose (wxCloseEvent& event);
00474                                 void OnMenuPrint(wxCommandEvent& event);
00475                                 void OnMenuClose(wxCommandEvent& event);
00476                                 void OnMenuAbout(wxCommandEvent& event);
00477                                 void OnChar(wxKeyEvent& event);
00478                                 void OnResize(wxSizeEvent& event);
00479                                 void OnMouseDown(wxMouseEvent& event);
00480 
00481                                 DECLARE_EVENT_TABLE()
00482                 }; // end class CWindowDialog
00483 
00484                 #ifndef _U
00485                         #ifdef wxUSE_UNICODE
00486                         #define _U(x) wxString((x),wxConvUTF8)
00487                         #define _UU(x,y) wxString((x),y)
00488                         #else
00489                         #define _U(x) (x)
00490                         #define _UU(x,y) (x)
00491                         #endif
00492                 #endif
00493 
00494 
00495         #endif
00496 
00497         } // End of namespace
00498 } // End of namespace
00499 
00500 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN: at Sat Mar 26 06:40:17 UTC 2011