00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "wgui_include_config.h"
00026 #include "wg_application.h"
00027 #include "wg_error.h"
00028 #include "wutil_debug.h"
00029 #include <iostream>
00030 #include <fstream>
00031
00032
00033 namespace wGui
00034 {
00035
00036
00037 CApplication* CApplication::m_pInstance = 0;
00038
00039
00040 void CApplication::HandleSDLEvent(SDL_Event Event)
00041 {
00042
00043 switch (Event.type)
00044 {
00045 case SDL_VIDEORESIZE:
00046 CMessageServer::Instance().QueueMessage(new TPointMessage(
00047 CMessage::CTRL_RESIZE, 0, this, CPoint(Event.resize.w, Event.resize.h)));
00048 break;
00049 case SDL_KEYDOWN:
00050 CMessageServer::Instance().QueueMessage(new CKeyboardMessage(
00051 CMessage::KEYBOARD_KEYDOWN, CApplication::Instance()->GetKeyFocus(), this,
00052 Event.key.keysym.scancode, Event.key.keysym.mod,
00053 Event.key.keysym.sym, Event.key.keysym.unicode));
00054 break;
00055 case SDL_KEYUP:
00056 CMessageServer::Instance().QueueMessage(new CKeyboardMessage(
00057 CMessage::KEYBOARD_KEYUP, CApplication::Instance()->GetKeyFocus(), this,
00058 Event.key.keysym.scancode, Event.key.keysym.mod,
00059 Event.key.keysym.sym, Event.key.keysym.unicode));
00060 break;
00061 case SDL_MOUSEBUTTONDOWN:
00062 CMessageServer::Instance().QueueMessage(new CMouseMessage(
00063 CMessage::MOUSE_BUTTONDOWN, CApplication::Instance()->GetMouseFocus(), this,
00064 CPoint(Event.button.x, Event.button.y), CPoint(),
00065 CMouseMessage::TranslateSDLButton(Event.button.button)));
00066 break;
00067 case SDL_MOUSEBUTTONUP:
00068 CMessageServer::Instance().QueueMessage(new CMouseMessage(
00069 CMessage::MOUSE_BUTTONUP, CApplication::Instance()->GetMouseFocus(), this,
00070 CPoint(Event.button.x, Event.button.y), CPoint(),
00071 CMouseMessage::TranslateSDLButton(Event.button.button)));
00072 break;
00073 case SDL_MOUSEMOTION:
00074 CMessageServer::Instance().QueueMessage(new CMouseMessage(
00075 CMessage::MOUSE_MOVE, CApplication::Instance()->GetMouseFocus(), this,
00076 CPoint(Event.motion.x, Event.motion.y), CPoint(Event.motion.xrel, Event.motion.yrel),
00077 CMouseMessage::TranslateSDLButtonState(Event.motion.state)));
00078 break;
00079 case SDL_QUIT:
00080 CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_EXIT, 0, this));
00081 break;
00082 default:
00083 CMessageServer::Instance().QueueMessage(new CSDLMessage(CMessage::SDL, 0, this, Event));
00084 break;
00085 }
00086 }
00087
00088
00089 CApplication::CApplication(int argc, char** argv, std::wstring sFontFileName, bool bHandleExceptionsInternally) :
00090 m_argc(argc),
00091 m_argv(argv),
00092 m_sFontFileName(sFontFileName),
00093 m_iExitCode(EXIT_FAILURE),
00094 m_bRunning(false),
00095 m_bInited(false),
00096 m_pKeyFocusWindow(0),
00097 m_pMouseFocusWindow(0),
00098 m_pDefaultFontEngine(0),
00099 m_iBitsPerPixel(DEFAULT_BPP),
00100 m_DefaultBackgroundColor(DEFAULT_BACKGROUND_COLOR),
00101 m_DefaultForegroundColor(DEFAULT_FOREGROUND_COLOR),
00102 m_DefaultSelectionColor(DEFAULT_BACKGROUND_COLOR),
00103 m_bHandleExceptionsInternally(bHandleExceptionsInternally),
00104 m_bResourcePoolEnabled(true),
00105 m_pCurrentCursorResourceHandle(0),
00106 m_pSystemDefaultCursor(0)
00107 {
00108 if (m_pInstance)
00109 {
00110 throw(Wg_Ex_App(L"CApplication::CApplication : An instance of the CApplication already exists."));
00111 }
00112
00113 m_pInstance = this;
00114
00115 if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) == -1)
00116 {
00117 throw(Wg_Ex_SDL(L"CApplication::CApplication : Could not initialize SDL: " + stdex::ToWString(SDL_GetError())));
00118 }
00119
00120 if(SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL) == -1)
00121 {
00122 throw(Wg_Ex_SDL(L"CApplication::Capplication : Error setting SDL keyboard repeat rate."));
00123 }
00124
00125 m_pSystemDefaultCursor = SDL_GetCursor();
00126 m_AppLog.AddLogEntry(L"wGui Application starting", APP_LOG_INFO);
00127
00128 atexit(SDL_Quit);
00129 }
00130
00131
00132 CApplication::~CApplication(void)
00133 {
00134 if (m_pInstance == this)
00135 {
00136 m_pInstance = 0;
00137 }
00138
00139 for(std::map<std::pair<std::wstring, unsigned char>, CFontEngine*>::iterator iter = m_FontEngines.begin(); iter != m_FontEngines.end(); ++iter)
00140 {
00141 delete iter->second;
00142 iter->second = 0;
00143 }
00144
00145 m_AppLog.AddLogEntry(L"wGui Application closing", APP_LOG_INFO);
00146 m_AppLog.WriteToFile(L"wGui.log", false, std::wstring(L"wGui Application Log (version ") + stdex::ToWString(VERSION) + L")\nSeverity Levels : [1] Critical, [3] Error, [5] Warning, [8] Info");
00147 }
00148
00149
00150 void CApplication::SetKeyFocus(CWindow* pWindow)
00151 {
00152 if (m_pKeyFocusWindow != pWindow)
00153 {
00154
00155 if (m_pKeyFocusWindow)
00156 {
00157 CMessageServer::Instance().QueueMessage(new CMessage(CMessage::CTRL_LOSINGKEYFOCUS, m_pKeyFocusWindow, this));
00158 }
00159 m_pKeyFocusWindow = pWindow;
00160 CMessageServer::Instance().QueueMessage(new CMessage(CMessage::CTRL_GAININGKEYFOCUS, m_pKeyFocusWindow, this));
00161 }
00162 }
00163
00164
00165 void CApplication::SetMouseFocus(CWindow* pWindow)
00166 {
00167 if (m_pMouseFocusWindow != pWindow)
00168 {
00169
00170 if (m_pMouseFocusWindow)
00171 {
00172 CMessageServer::Instance().QueueMessage(new CMessage(CMessage::CTRL_LOSINGMOUSEFOCUS, m_pMouseFocusWindow, this));
00173 }
00174 m_pMouseFocusWindow = pWindow;
00175 CMessageServer::Instance().QueueMessage(new CMessage(CMessage::CTRL_GAININGMOUSEFOCUS, m_pMouseFocusWindow, this));
00176 }
00177 }
00178
00179
00180
00181 void CApplication::Init(void)
00182 {
00183 CMessageServer::Instance().RegisterMessageClient(this, CMessage::APP_EXIT, CMessageServer::PRIORITY_LAST);
00184 SDL_EnableUNICODE(1);
00185
00186
00187
00188
00189
00190
00191 bool bConfigLoaded = false;
00192
00193
00194 if (m_GlobalConfig.ReadFromFile(GLOBAL_CONFIG_PATH + L"wgui.conf"))
00195 {
00196 m_AppLog.AddLogEntry(L"wGui Application config read from Global directory.", APP_LOG_INFO);
00197 bConfigLoaded = true;
00198 }
00199
00200
00201 if (m_GlobalConfig.ReadFromFile(USER_CONFIG_PATH + L"wgui.conf"))
00202 {
00203 m_AppLog.AddLogEntry(L"wGui Application config read from User directory.", APP_LOG_INFO);
00204 bConfigLoaded = true;
00205 }
00206
00207
00208 if (m_GlobalConfig.ReadFromFile(L"wgui.conf"))
00209 {
00210 m_AppLog.AddLogEntry(L"wGui Application config read from Local directory.", APP_LOG_INFO);
00211 bConfigLoaded = true;
00212 }
00213
00214 if (!bConfigLoaded)
00215 {
00216 m_AppLog.AddLogEntry(L"wGui Application config was not found (see Global Config section of the docs).", APP_LOG_WARNING);
00217 }
00218
00219 if (m_GlobalConfig.EntryExists(L"DEFAULTFONT"))
00220 {
00221 if (m_GlobalConfig.EntryExists(L"DEFAULTFONTSIZE"))
00222 {
00223 m_pDefaultFontEngine = GetFontEngine(m_GlobalConfig.GetStringEntry(L"DEFAULTFONT").second,
00224 stdex::safe_static_cast<unsigned char>(m_GlobalConfig.GetLongIntEntry(L"DEFAULTFONTSIZE").second));
00225 }
00226 else
00227 {
00228 m_pDefaultFontEngine = GetFontEngine(m_GlobalConfig.GetStringEntry(L"DEFAULTFONT").second);
00229 }
00230 }
00231
00232 if (!m_pDefaultFontEngine)
00233 {
00234 m_AppLog.AddLogEntry(L"wGui Application was unable to load a default font from the global config. Check to see that the specified paths are correct.", APP_LOG_WARNING);
00235 }
00236
00237 if (m_GlobalConfig.EntryExists(L"BACKGROUNDCOLOR"))
00238 {
00239 m_DefaultBackgroundColor = CRGBColor(m_GlobalConfig.GetStringEntry(L"BACKGROUNDCOLOR").second);
00240 }
00241
00242 if (m_GlobalConfig.EntryExists(L"FOREGROUNDCOLOR"))
00243 {
00244 m_DefaultForegroundColor = CRGBColor(m_GlobalConfig.GetStringEntry(L"FOREGROUNDCOLOR").second);
00245 }
00246
00247 if (m_GlobalConfig.EntryExists(L"SELECTIONCOLOR"))
00248 {
00249 m_DefaultSelectionColor = CRGBColor(m_GlobalConfig.GetStringEntry(L"SELECTIONCOLOR").second);
00250 }
00251
00252 m_bInited = true;
00253 }
00254
00255
00256 void CApplication::Exec(void)
00257 {
00258 try
00259 {
00260 if (!m_bInited)
00261 {
00262 throw(Wg_Ex_App(L"CApplication::Exec : Application Init() was not called!"));
00263 }
00264
00265 m_bRunning = true;
00266 SDL_Event event;
00267 CMessageServer::Instance().IgnoreAllNewMessages(false);
00268 CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, 0, this));
00269 m_AppLog.AddLogEntry(L"wGui Application entering Exec loop", APP_LOG_INFO);
00270 while (m_bRunning)
00271 {
00272 while (SDL_PollEvent(&event))
00273 {
00274 HandleSDLEvent(event);
00275 }
00276 while (!CMessageServer::Instance().MessageAvailable())
00277 {
00278 while (SDL_PollEvent(&event))
00279 {
00280 HandleSDLEvent(event);
00281 }
00282 SDL_Delay(5);
00283 }
00284 try
00285 {
00286 CMessageServer::Instance().DeliverMessage();
00287 }
00288 catch (Wg_Ex_Base& e)
00289 {
00290 m_AppLog.AddLogEntry(L"Exception (wGui) : " + e.std_what(), APP_LOG_CRITICAL);
00291 if (!m_bHandleExceptionsInternally)
00292 {
00293 throw;
00294 }
00295
00296
00297 wUtil::Trace(L"wGui exception while delivering message : " + e.std_what());
00298 }
00299 }
00300 }
00301 catch (Wg_Ex_Base& e)
00302 {
00303 m_AppLog.AddLogEntry(L"Exception (wGui) : " + e.std_what(), APP_LOG_CRITICAL);
00304 m_AppLog.AddLogEntry(L"SDL Last Error = " + stdex::ToWString(SDL_GetError()), APP_LOG_ERROR);
00305 if (!m_bHandleExceptionsInternally)
00306 {
00307 throw;
00308 }
00309
00310 wUtil::Trace(L"Unhandled wGui exception : " + e.std_what());
00311 }
00312 catch (std::exception& e)
00313 {
00314 m_AppLog.AddLogEntry(L"Exception (std) : " + stdex::ToWString(e.what()), APP_LOG_CRITICAL);
00315 m_AppLog.AddLogEntry(L"SDL Last Error = " + stdex::ToWString(SDL_GetError()), APP_LOG_ERROR);
00316 if (!m_bHandleExceptionsInternally)
00317 {
00318 throw;
00319 }
00320
00321 wUtil::Trace(L"Unhandled std exception : " + stdex::ToWString(e.what()));
00322 }
00323 catch (...)
00324 {
00325 m_AppLog.AddLogEntry(L"Exception (non std)", APP_LOG_CRITICAL);
00326 m_AppLog.AddLogEntry(L"SDL Last Error = " + stdex::ToWString(SDL_GetError()), APP_LOG_ERROR);
00327 if (!m_bHandleExceptionsInternally)
00328 {
00329 throw;
00330 }
00331
00332 wUtil::Trace(L"Unhandled exception");
00333 }
00334 }
00335
00336
00337 void CApplication::ApplicationExit(int iExitCode)
00338 {
00339
00340
00341 SDL_Event user_event;
00342 user_event.type=SDL_USEREVENT;
00343 user_event.user.code=0;
00344 user_event.user.data1=0;
00345 user_event.user.data2=0;
00346 int iResult = SDL_PushEvent(&user_event);
00347 wUtil::TraceIf(iResult == -1, L"CApplication::ApplicationExit - Unable to push SDL user_event.");
00348 m_iExitCode = iExitCode;
00349 m_bRunning = false;
00350 }
00351
00352
00353 CFontEngine* CApplication::GetFontEngine(std::wstring sFontFileName, unsigned char iFontSize)
00354 {
00355
00356 t_FontEngineMap::iterator iterFontEngine = m_FontEngines.find(std::make_pair(sFontFileName, iFontSize));
00357 CFontEngine* pFontEngine = 0;
00358
00359 if (iterFontEngine == m_FontEngines.end())
00360 {
00361
00362 try
00363 {
00364 if (sFontFileName.find_first_of(L"\\/") != std::string::npos)
00365 {
00366
00367 std::wifstream FileTest(stdex::ToMbString(sFontFileName).c_str());
00368 bool bFileExists = FileTest.is_open();
00369 FileTest.close();
00370 if (bFileExists)
00371 {
00372 pFontEngine = new CFontEngine(sFontFileName, iFontSize);
00373 }
00374 }
00375 else
00376 {
00377
00378 std::vector<std::wstring> FontPaths = stdex::DetokenizeString(m_GlobalConfig.GetStringEntry(L"FONTPATH").second, L";");
00379 for(std::vector<std::wstring>::iterator iter = FontPaths.begin(); iter != FontPaths.end(); ++iter)
00380 {
00381 std::wstring sFullPath = *iter;
00382 if (!iter->empty() && (*iter)[iter->length()] != L'\\' && (*iter)[iter->length()] != L'/')
00383 {
00384 sFullPath += L"/";
00385 }
00386 sFullPath += sFontFileName;
00387 std::wifstream FileTest(stdex::ToMbString(sFullPath).c_str());
00388 bool bFileExists = FileTest.is_open();
00389 FileTest.close();
00390 if (bFileExists)
00391 {
00392 pFontEngine = new CFontEngine(sFullPath, iFontSize);
00393 }
00394 }
00395 }
00396 if (pFontEngine)
00397 {
00398 m_FontEngines.insert(std::make_pair(std::make_pair(sFontFileName, iFontSize), pFontEngine));
00399 }
00400 }
00401 catch (Wg_Ex_FreeType& e)
00402 {
00403 m_AppLog.AddLogEntry(L"CApplication::GetFontEngine - Exception thrown while creating Font Engine : " + e.std_what(), APP_LOG_ERROR);
00404 if (!m_bHandleExceptionsInternally)
00405 {
00406 throw;
00407 }
00408 }
00409 }
00410 else
00411 {
00412 pFontEngine = iterFontEngine->second;
00413 }
00414
00415 return pFontEngine;
00416 }
00417
00418
00419 void CApplication::EnableResourcePool(bool bEnable)
00420 {
00421 m_bResourcePoolEnabled = bEnable;
00422 if (bEnable == false)
00423 {
00424 m_ResourceHandlePool.clear();
00425 }
00426 }
00427
00428
00429 bool CApplication::AddToResourcePool(CResourceHandle& ResourceHandle)
00430 {
00431 bool bSuccess = false;
00432
00433 if (m_bResourcePoolEnabled)
00434 {
00435 m_ResourceHandlePool.push_back(ResourceHandle);
00436 bSuccess = true;
00437 }
00438
00439 return bSuccess;
00440 }
00441
00442
00443 void CApplication::SetMouseCursor(CCursorResourceHandle* pCursorResourceHandle)
00444 {
00445
00446 if (pCursorResourceHandle && pCursorResourceHandle != m_pCurrentCursorResourceHandle.get())
00447 {
00448 std::auto_ptr<CCursorResourceHandle> pNewCursorResourceHandle(new CCursorResourceHandle(*pCursorResourceHandle));
00449 m_pCurrentCursorResourceHandle = pNewCursorResourceHandle;
00450 SDL_SetCursor(m_pCurrentCursorResourceHandle->Cursor());
00451 }
00452 else
00453 {
00454 if( m_pCurrentCursorResourceHandle.get() )
00455 {
00456 #ifdef MSVC6
00457 delete m_pCurrentCursorResourceHandle.release();
00458 m_pCurrentCursorResourceHandle = std::auto_ptr<CCursorResourceHandle>(0);
00459 #else
00460 m_pCurrentCursorResourceHandle.reset(0);
00461 #endif // MSVC6
00462 SDL_SetCursor(m_pSystemDefaultCursor);
00463 }
00464 }
00465 }
00466
00467
00468 bool CApplication::HandleMessage(CMessage* pMessage)
00469 {
00470 bool bHandled = false;
00471
00472 if (pMessage)
00473 {
00474 switch (pMessage->MessageType())
00475 {
00476 case CMessage::APP_EXIT :
00477 ApplicationExit();
00478 bHandled = true;
00479 break;
00480 default:
00481 break;
00482 }
00483 }
00484
00485 return bHandled;
00486 }
00487
00488 }