core/vgui/impl/wx/vgui_wx.cxx
Go to the documentation of this file.
00001 // This is core/vgui/impl/wx/vgui_wx.cxx
00002 //=========================================================================
00003 //:
00004 // \file
00005 // \brief  wxWidgets implementation of vgui_toolkit.
00006 //
00007 // See vgui_wx.h for details.
00008 //=========================================================================
00009 
00010 #include "vgui_wx.h"
00011 #include "vgui_wx_window.h"
00012 #include "vgui_wx_dialog_impl.h"
00013 #include <vgui/vgui_gl.h>
00014 
00015 #include <vcl_cstdlib.h> // for vcl_exit()
00016 #include <vcl_cstddef.h> // for vcl_size_t
00017 #include <vcl_cassert.h>
00018 #include <vcl_iostream.h>
00019 
00020 #include <wx/app.h>
00021 #include <wx/log.h>
00022 #include <wx/wxchar.h>
00023 #include <wx/strconv.h>
00024 #ifdef __WXMSW__
00025 #include <wx/msw/private.h>
00026 #endif
00027 
00028 //-------------------------------------------------------------------------
00029 // Private helpers - declarations.
00030 //-------------------------------------------------------------------------
00031 namespace
00032 {
00033   class vgui_wx_app;
00034   wxAppConsole* vgui_wx_create_app(void);
00035   wxChar** g_wxCharArgv = NULL;
00036   int g_Argc = 0;
00037 }
00038 
00039 //-------------------------------------------------------------------------
00040 // vgui_wx implementation - construction & destruction.
00041 //-------------------------------------------------------------------------
00042 //: Singleton method instance.
00043 vgui_wx* vgui_wx::instance()
00044 {
00045   static vgui_wx* instance_ = new vgui_wx;
00046   return instance_;
00047 }
00048 
00049 //: Returns the name of the GUI toolkit ("wx").
00050 vcl_string vgui_wx::name(void) const { return "wx"; }
00051 
00052 //: Constructor - default.
00053 vgui_wx::vgui_wx(void)
00054   : adaptor_embedded_(true)
00055 {
00056 #ifdef DEBUG
00057   vcl_cout << "vgui_wx::vgui_wx() - Constructor" << vcl_endl;
00058 #endif
00059 }
00060 
00061 //: Destructor.
00062 vgui_wx::~vgui_wx(void)
00063 {
00064 #ifdef DEBUG
00065   vcl_cout << "vgui_wx::~vgui_wx() - Destructor" << vcl_endl;
00066 #endif
00067 }
00068 
00069 //: Initialize the wxWidgets GUI framework.
00070 void vgui_wx::init(int& argc, char** argv)
00071 {
00072   // ***** ensure this is only entered once...
00073 
00074 #ifdef DEBUG
00075   vcl_cout << "vgui_wx::init()" << vcl_endl;
00076 #endif
00077 
00078   if (wxTheApp)
00079   {
00080     // if we are here, then we aren't trying to use vgui in a wxWidgets App
00081     vcl_cerr << "vgui_wx::init(): wxApp object already exists!\n";
00082     // ***** exit here... or can we recover from this?
00083     vcl_exit(-1);
00084   }
00085 
00086   // Set the app initializer so that we can create the vgui_wx_app.
00087   wxAppInitializer vgui_wx_app_initializer(
00088     static_cast<wxAppInitializerFunction>(vgui_wx_create_app));
00089 
00090 #ifdef __WXMSW__
00091   wxSetInstance(GetModuleHandle(0));
00092   wxApp::m_nCmdShow = 0;
00093 #endif
00094 
00095   // If necessary, convert the char** argv to the Unicode wxChar**
00096   // version.
00097   wxChar** wxArgv;
00098 #if wxUSE_UNICODE
00099   g_Argc = argc;
00100   g_wxCharArgv = new wxChar*[argc+1];
00101   for ( int cnt = 0; cnt < argc; ++cnt ) {
00102     vcl_size_t len = wxConvLocal.MB2WC( NULL, argv[cnt], 0 );
00103     g_wxCharArgv[cnt] = new wxChar[len+1];
00104     wxConvLocal.MB2WC( g_wxCharArgv[cnt], argv[cnt], len+1 );
00105   }
00106   g_wxCharArgv[argc] = NULL;
00107   wxArgv = g_wxCharArgv;
00108 #else
00109   wxArgv = argv;
00110 #endif
00111 
00112   // wxWidgets initialization
00113   if (!wxInitialize(argc, wxArgv))
00114   {
00115     vcl_cerr << "vgui_wx::init(): wxInitialize failed!\n";
00116     // ***** exit here... or can we recover from this?
00117     vcl_exit(-1);
00118   }
00119 
00120   // wxApp initialization
00121   if (!wxTheApp->CallOnInit())
00122   {
00123     vcl_cerr << "vgui_wx::init(): wxTheApp->OnInit failed!\n";
00124     // ***** exit here... or can we recover from this?
00125     // ***** do we need to call wxUninitialize (or uninit) before exit?
00126     vcl_exit(-1);
00127   }
00128 
00129   // adaptor is being extended (i.e., vgui is controlling the event loop)
00130   adaptor_embedded_ = false;
00131 
00132   // ***** Conditionally set these logging levels?
00133   //wxLog* logger = new wxLogStderr;
00134   //wxLog::SetActiveTarget(logger);
00135   wxLog::AddTraceMask(wxTRACE_RefCount);
00136 }
00137 
00138 void vgui_wx::uninit(void)
00139 {
00140 #ifdef DEBUG
00141   vcl_cout << "vgui_wx::uninit()" << vcl_endl;
00142 #endif
00143 
00144   // not controlling the main loop from vgui_wx
00145   if (adaptor_embedded_)
00146   {
00147     vcl_cerr << __FILE__ ":embedding adaptor; don't call uninit!\n";
00148     return;
00149   }
00150 
00151   // ***** This should only be called if OnInit was called.
00152   wxTheApp->OnExit();
00153 
00154   // ***** This call is causing system crashes, in WinXP?!?
00155   //wxUninitialize();
00156 
00157   // ***** Memory should be managed elsewhere... smart_ptr's???
00158   //for (unsigned int i = 0; i < windows_to_delete_.size(); i++)
00159   //{
00160   //  delete windows_to_delete_[i]; // ***** what if user deleted it???
00161   //  windows_to_delete_.clear();
00162   //}
00163 
00164   // If we convert the char** argv to a wxChar** version, free our
00165   // conversion now.
00166 #if wxUSE_UNICODE
00167   for ( int cnt = 0; cnt < g_Argc; ++cnt ) {
00168     delete[] g_wxCharArgv[cnt];
00169   }
00170   delete g_wxCharArgv;
00171   g_wxCharArgv = NULL;
00172   g_Argc = 0;
00173 #endif
00174 }
00175 
00176 //-------------------------------------------------------------------------
00177 // vgui_wx implementation - event handling.
00178 // - These should only be called if creating the application in vgui_wx
00179 //   (i.e., we are extending the adaptor instead of embedding it).
00180 //
00181 // - ***** ensure that these are only called if not embedding...
00182 //-------------------------------------------------------------------------
00183 //: Run the event loop.
00184 void vgui_wx::run(void)
00185 {
00186 #ifdef DEBUG
00187   vcl_cout << "vgui_wx::run()" << vcl_endl;
00188 #endif
00189 
00190   // not controlling the main loop from vgui_wx
00191   if (adaptor_embedded_)
00192   {
00193     vcl_cerr << __FILE__ ":embedding adaptor; don't call run!\n";
00194     return;
00195   }
00196 
00197   wxTheApp->OnRun();
00198 }
00199 
00200 //: Run the next event.
00201 void vgui_wx::run_one_event(void)
00202 {
00203   wxTheApp->Dispatch();
00204 }
00205 
00206 //: Run until event queue is empty.
00207 void vgui_wx::run_till_idle(void)
00208 {
00209   while (wxTheApp->Pending())
00210   {
00211     wxTheApp->Dispatch();
00212     glFlush();
00213   }
00214   wxTheApp->ProcessIdle();
00215 }
00216 
00217 //: Clear all events from the queue.
00218 void vgui_wx::flush(void)
00219 {
00220   glFlush();
00221   run_till_idle();
00222 }
00223 
00224 //: Add an event to the queue.
00225 void vgui_wx::add_event(const vgui_event&)
00226 {
00227   // ***** not implemented, yet
00228   assert(false);
00229 }
00230 
00231 //: Quit the application.
00232 void vgui_wx::quit(void)
00233 {
00234 #ifdef DEBUG
00235   vcl_cout << "vgui_wx::quit()" << vcl_endl;
00236 #endif
00237 
00238   // not controlling the main loop from vgui_wx
00239   if (adaptor_embedded_) { return; }
00240 
00241   if (wxTheApp->IsMainLoopRunning()) { wxTheApp->ExitMainLoop(); }
00242 }
00243 
00244 //-------------------------------------------------------------------------
00245 // vgui_wx implementation - window creation.
00246 // ***** all of these should return smart pointers???
00247 //-------------------------------------------------------------------------
00248 //: Create a new window with a menubar.
00249 vgui_window* vgui_wx::produce_window(int width, int height,
00250                                      const vgui_menu& menubar,
00251                                      const char* title)
00252 {
00253   vgui_window* win_tmp = new vgui_wx_window(width, height, menubar, title);
00254   windows_to_delete_.push_back(win_tmp);
00255   return win_tmp;
00256 }
00257 
00258 //: Create a new window.
00259 vgui_window* vgui_wx::produce_window(int width, int height,
00260                                      const char* title)
00261 {
00262   vgui_window* win_tmp = new vgui_wx_window(width, height, title);
00263   windows_to_delete_.push_back(win_tmp);
00264   return win_tmp;
00265 }
00266 
00267 //: Create a new dialog window.
00268 vgui_dialog_impl* vgui_wx::produce_dialog(const char* name)
00269 {
00270   return new vgui_wx_dialog_impl(name);
00271 }
00272 
00273 //-------------------------------------------------------------------------
00274 // Private helpers - definitions.
00275 //-------------------------------------------------------------------------
00276 namespace
00277 {
00278   class vgui_wx_app : public wxApp
00279   {
00280    public:
00281     //: Constructor - default.
00282     vgui_wx_app()
00283     {
00284 #ifdef DEBUG
00285       vcl_cout << "vgui_wx_app: Constructor" << vcl_endl;
00286 #endif
00287     }
00288 
00289     //: Destructor.
00290     virtual ~vgui_wx_app()
00291     {
00292 #ifdef DEBUG
00293       vcl_cout << "vgui_wx_app: Destructor" << vcl_endl;
00294 #endif
00295     }
00296 
00297     //: Called on app initialization.
00298     bool OnInit()
00299     {
00300 #ifdef DEBUG
00301       vcl_cout << "vgui_wx_app: OnInit()" << vcl_endl;
00302 #endif
00303 
00304       // ***** wxApp's OnInit command parser usually gets in the way...
00305       return true; //wxApp::OnInit();
00306     }
00307 
00308     //: Called on app exit.
00309     virtual int OnExit()
00310     {
00311 #ifdef DEBUG
00312       vcl_cout << "vgui_wx_app: OnExit()" << vcl_endl;
00313 #endif
00314 
00315       return wxApp::OnExit();
00316     }
00317 
00318     //: Called if unhandled exception occurs inside main event loop.
00319     // Return true to ignore the exception and false to exit the loop.
00320     virtual bool OnExceptionInMainLoop()
00321     {
00322 #ifdef DEBUG
00323       vcl_cout << "vgui_wx_app: OnExceptionInMainLoop()" << vcl_endl;
00324 #endif
00325 
00326       return false;
00327     }
00328   };
00329 
00330   //IMPLEMENT_APP_NO_MAIN(vgui_wx_app)
00331   wxAppConsole* vgui_wx_create_app(void)
00332   {
00333     wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,
00334                                     "your program");
00335     return new vgui_wx_app;
00336   }
00337 
00338   //static vgui_wx_app& wxGetApp() { return *(vgui_wx_app *)wxTheApp; }
00339 
00340 } // unnamed namespace