📄 wg_application.cpp
字号:
// wg_application.cpp//// CApplication interface////// Copyright (c) 2002 Rob Wiskow// rob-dev@boxedchaos.com//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//#include "wgui_include_config.h"#include "wg_application.h"#include "wg_error.h"#include "wg_debug.h"#include "std_ex.h"#include <iostream>#include <fstream>namespace wGui{// Static membersCApplication* CApplication::m_pInstance = 0;void CApplication::HandleSDLEvent(SDL_Event Event){ // this will turn an SDL event into a wGui message switch (Event.type) { case SDL_VIDEORESIZE: CMessageServer::Instance().QueueMessage(new TPointMessage( CMessage::CTRL_RESIZE, 0, 0, CPoint(Event.resize.w, Event.resize.h))); break; case SDL_KEYDOWN: CMessageServer::Instance().QueueMessage(new CKeyboardMessage( CMessage::KEYBOARD_KEYDOWN, CApplication::Instance()->GetKeyFocus(), this, Event.key.keysym.scancode, Event.key.keysym.mod, Event.key.keysym.sym, Event.key.keysym.unicode)); break; case SDL_KEYUP: CMessageServer::Instance().QueueMessage(new CKeyboardMessage( CMessage::KEYBOARD_KEYUP, CApplication::Instance()->GetKeyFocus(), this, Event.key.keysym.scancode, Event.key.keysym.mod, Event.key.keysym.sym, Event.key.keysym.unicode)); break; case SDL_MOUSEBUTTONDOWN: CMessageServer::Instance().QueueMessage(new CMouseMessage( CMessage::MOUSE_BUTTONDOWN, CApplication::Instance()->GetMouseFocus(), this, CPoint(Event.button.x, Event.button.y), CPoint(), CMouseMessage::TranslateSDLButton(Event.button.button))); break; case SDL_MOUSEBUTTONUP: CMessageServer::Instance().QueueMessage(new CMouseMessage( CMessage::MOUSE_BUTTONUP, CApplication::Instance()->GetMouseFocus(), this, CPoint(Event.button.x, Event.button.y), CPoint(), CMouseMessage::TranslateSDLButton(Event.button.button))); break; case SDL_MOUSEMOTION: CMessageServer::Instance().QueueMessage(new CMouseMessage( CMessage::MOUSE_MOVE, CApplication::Instance()->GetMouseFocus(), this, CPoint(Event.motion.x, Event.motion.y), CPoint(Event.motion.xrel, Event.motion.yrel), CMouseMessage::TranslateSDLButtonState(Event.motion.state))); break; case SDL_QUIT: CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_EXIT, 0, this)); break; }}CApplication::CApplication(int argc, char** argv, std::string sFontFileName, bool bHandleExceptionsInternally) : m_argc(argc), m_argv(argv), m_sFontFileName(sFontFileName), m_iExitCode(EXIT_FAILURE), m_bRunning(false), m_bInited(false), m_pKeyFocusWindow(0), m_pMouseFocusWindow(0), m_pDefaultFontEngine(0), m_bHandleExceptionsInternally(bHandleExceptionsInternally), m_bResourcePoolEnabled(true), m_pCurrentCursorResourceHandle(0), m_pSystemDefaultCursor(0){ if (m_pInstance) { throw(Wg_Ex_App("CApplication::CApplication : An instance of the CApplication already exists.")); } m_pInstance = this; if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) == -1) { throw(Wg_Ex_SDL(std::string("CApplication::CApplication : Could not initialize SDL: ") + SDL_GetError())); } //Setting the keyboard repeat rate using the SDL Default rates if(SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL) == -1) { throw(Wg_Ex_SDL(std::string("CApplication::Capplication : Error setting SDL keyboard repeat rate."))); } m_pSystemDefaultCursor = SDL_GetCursor(); atexit(SDL_Quit);}CApplication::~CApplication(void){ if (m_pInstance == this) { m_pInstance = 0; } for(std::map<std::pair<std::string, unsigned char>, CFontEngine*>::iterator iter = m_FontEngines.begin(); iter != m_FontEngines.end(); ++iter) { delete iter->second; iter->second = 0; }}void CApplication::SetKeyFocus(CWindow* pWindow){ // notify the window that's losing focus to repaint itself if (m_pKeyFocusWindow) { CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, m_pKeyFocusWindow, this)); } m_pKeyFocusWindow = pWindow;}void CApplication::SetMouseFocus(CWindow* pWindow){ // notify the window that's losing focus to repaint itself if (m_pMouseFocusWindow) { CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, m_pMouseFocusWindow, this)); } m_pMouseFocusWindow = pWindow;}void CApplication::Init(void){ CMessageServer::Instance().RegisterMessageClient(this, CMessage::APP_EXIT, CMessageServer::PRIORITY_LAST); SDL_EnableUNICODE(1); // Now we have to find the wGui.conf file and load it into the Global Config // Our ordered search path is (so the current directory will overwrite any common settings with the other directories): // <global directory> // <home directory> // <current directory> // global directory first m_GlobalConfig.ReadFromFile(GLOBAL_CONFIG_PATH + "wgui.conf"); // now the home directory m_GlobalConfig.ReadFromFile(USER_CONFIG_PATH + "wgui.conf"); // and finally the current directory m_GlobalConfig.ReadFromFile("wgui.conf"); if (m_GlobalConfig.EntryExists("DEFAULTFONT")) { if (m_GlobalConfig.EntryExists("DEFAULTFONTSIZE")) { m_pDefaultFontEngine = GetFontEngine(m_GlobalConfig.GetStringEntry("DEFAULTFONT").second, static_cast<unsigned char>(m_GlobalConfig.GetLongIntEntry("DEFAULTFONTSIZE").second)); } else { m_pDefaultFontEngine = GetFontEngine(m_GlobalConfig.GetStringEntry("DEFAULTFONT").second); } } m_bInited = true;}void CApplication::Exec(void){ try { if (!m_bInited) { throw(Wg_Ex_App("CApplication::Exec : Application Init() was not called!")); } m_bRunning = true; SDL_Event event; CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, 0, this)); while (m_bRunning) { while (SDL_PollEvent(&event)) { HandleSDLEvent(event); } while (!CMessageServer::Instance().MessageAvailable()) { while (SDL_PollEvent(&event)) { HandleSDLEvent(event); } SDL_Delay(5); } try { CMessageServer::Instance().DeliverMessage(); } catch (Wg_Ex_Base& DEBUG_ONLY(e)) { if (!m_bHandleExceptionsInternally) { throw; } // Since we're handling exceptions internally, and it's one of our own exceptions, we're just going to // send something to the debug output and then continue processing the message queue Trace("wGui exception while delivering message : " + e.std_what()); } } } catch (Wg_Ex_Base& DEBUG_ONLY(e)) { if (!m_bHandleExceptionsInternally) { throw; } // We are supposed to handle all exceptions internally, but something hasn't been handled at this point, so we need to exit gracefully Trace("Unhandled wGui exception : " + e.std_what()); } catch (std::exception& DEBUG_ONLY(e)) { if (!m_bHandleExceptionsInternally) { throw; } // We are supposed to handle all exceptions internally, but something hasn't been handled at this point, so we need to exit gracefully Trace("Unhandled std exception : " + std::string(e.what())); } catch (...) { if (!m_bHandleExceptionsInternally) { throw; } // We are supposed to handle all exceptions internally, but something hasn't been handled at this point, so we need to exit gracefully Trace("Unhandled exception"); }}void CApplication::ApplicationExit(int iExitCode){ // push an event into the SDL queue so the SDLEventLoopThread can exit // the actual contents of the event are not a concern as it serves just to trigger the SDL_WaitEvent SDL_Event user_event; user_event.type=SDL_USEREVENT; user_event.user.code=0; user_event.user.data1=0; user_event.user.data2=0; DEBUG_ONLY(int iResult =) SDL_PushEvent(&user_event); TraceIf(iResult == -1, "CApplication::ApplicationExit - Unable to push SDL user_event."); m_iExitCode = iExitCode; m_bRunning = false;}CFontEngine* CApplication::GetFontEngine(std::string sFontFileName, unsigned char iFontSize){ // First search to see if the requested font engine already exists t_FontEngineMap::iterator iterFontEngine = m_FontEngines.find(std::make_pair(sFontFileName, iFontSize)); CFontEngine* pFontEngine = 0; if (iterFontEngine == m_FontEngines.end()) { // Requested font engine doesn't exist, so create one and add it to the map try { if (sFontFileName.find_first_of("\\/") != std::string::npos) { // if the Font File name that was passed in includes a path, just check there std::ifstream FileTest(sFontFileName.c_str()); bool bFileExists = FileTest.is_open(); FileTest.close(); if (bFileExists) { pFontEngine = new CFontEngine(sFontFileName, iFontSize); } } else { // otherwise check the Font Path from the global config std::list<std::string> FontPaths = stdex::DetokenizeString(m_GlobalConfig.GetStringEntry("FONTPATH").second, ";"); for(std::list<std::string>::iterator iter = FontPaths.begin(); iter != FontPaths.end(); ++iter) { std::string sFullPath = *iter; if (!iter->empty() && (*iter)[iter->length()] != '\\' && (*iter)[iter->length()] != '/') { sFullPath += "/"; } sFullPath += sFontFileName; std::ifstream FileTest(sFullPath.c_str()); bool bFileExists = FileTest.is_open(); FileTest.close(); if (bFileExists) { pFontEngine = new CFontEngine(sFullPath, iFontSize); } } } if (pFontEngine) { m_FontEngines.insert(std::make_pair(std::make_pair(sFontFileName, iFontSize), pFontEngine)); } } catch (Wg_Ex_FreeType& DEBUG_ONLY(e)) { if (!m_bHandleExceptionsInternally) { throw; } Trace("CApplication::GetFontEngine - Exception thrown while creating Font Engine : " + e.std_what()); } } else { pFontEngine = iterFontEngine->second; } return pFontEngine;}void CApplication::EnableResourcePool(bool bEnable){ m_bResourcePoolEnabled = bEnable; if (bEnable == false) { m_ResourceHandlePool.clear(); }}bool CApplication::AddToResourcePool(CResourceHandle& ResourceHandle){ bool bSuccess = false; if (m_bResourcePoolEnabled) { m_ResourceHandlePool.push_back(ResourceHandle); } return bSuccess;}void CApplication::SetMouseCursor(CCursorResourceHandle* pCursorResourceHandle){ // The auto pointer is used to make sure that the cursor handle is valid until we're done using the cursor if (pCursorResourceHandle && pCursorResourceHandle != m_pCurrentCursorResourceHandle.get()) { std::auto_ptr<CCursorResourceHandle> pNewCursorResourceHandle(new CCursorResourceHandle(*pCursorResourceHandle)); m_pCurrentCursorResourceHandle = pNewCursorResourceHandle; SDL_SetCursor(m_pCurrentCursorResourceHandle->Cursor()); } else { if( m_pCurrentCursorResourceHandle.get() ) { #ifdef MSVC6 // VC6's auto pointers are really broken delete m_pCurrentCursorResourceHandle.release(); m_pCurrentCursorResourceHandle = std::auto_ptr<CCursorResourceHandle>(0); #else m_pCurrentCursorResourceHandle.reset(0); #endif // MSVC6 SDL_SetCursor(m_pSystemDefaultCursor); } }}bool CApplication::HandleMessage(CMessage* pMessage){ bool bHandled = false; if (pMessage) { switch (pMessage->MessageType()) { case CMessage::APP_EXIT : ApplicationExit(); bHandled = true; break; default: break; } } return bHandled;}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -