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
00026
00027
00028
00029 #include "pgapplication.h"
00030 #include "pgwidget.h"
00031 #include "pglayout.h"
00032 #include "pglog.h"
00033 #include "pgdraw.h"
00034 #include "pgtheme.h"
00035 #include "pgeventsupplier.h"
00036 #include "pgsdleventsupplier.h"
00037
00038 #include <iostream>
00039 #include <cstring>
00040 #include <cassert>
00041 #include <cmath>
00042
00043
00044
00045
00046 #ifndef PARAGUI_THEMEDIR
00047 #ifdef __MACOS__
00048 #define PARAGUI_THEMEDIR ""
00049 #else
00050 #define PARAGUI_THEMEDIR "./"
00051 #endif // macintosh
00052 #endif // PARAGUI_THEMEDIR
00053
00054 SDL_mutex* PG_Application::mutexScreen = NULL;
00055 PG_Application* PG_Application::pGlobalApp = NULL;
00056 SDL_Surface* PG_Application::screen = NULL;
00057
00058 PG_Theme* PG_Application::my_Theme = NULL;
00059 bool PG_Application::bulkMode = false;
00060
00061
00062 bool PG_Application::enableBackground = true;
00063
00064 SDL_Surface *PG_Application::my_mouse_pointer = NULL;
00065 SDL_Surface *PG_Application::my_mouse_backingstore = NULL;
00066 PG_Rect PG_Application::my_mouse_position = PG_Rect(0,0,0,0);
00067 PG_Application::CursorMode PG_Application::my_mouse_mode = PG_Application::HARDWARE;
00068 PG_Font* PG_Application::DefaultFont = NULL;
00069 SDL_Surface* PG_Application::my_background = NULL;
00070 SDL_Surface* PG_Application::my_scaled_background = NULL;
00071 PG_Color PG_Application::my_backcolor;
00072 PG_Draw::BkMode PG_Application::my_backmode = PG_Draw::TILE;
00073 bool PG_Application::disableDirtyUpdates = false;
00074
00075 PG_EventSupplier* PG_Application::my_eventSupplier = NULL;
00076 PG_EventSupplier* PG_Application::my_defaultEventSupplier = NULL;
00077 bool PG_Application::defaultUpdateOverlappingSiblings = true;
00078 PG_Char PG_Application::highlightingTag = 0;
00079
00083 void PARAGUI_ShutDownCode() {
00084
00085
00086 SDL_Quit();
00087 }
00088
00089
00090 PG_Application::PG_Application()
00091 : my_quitEventLoop(false), emergencyQuit(false), enableAppIdleCalls(false) {
00092
00093
00094
00095
00096
00097 #ifdef ENABLE_UNICODE
00098 setlocale(LC_CTYPE, "C.UTF-8");
00099 #endif
00100
00101 if(pGlobalApp != NULL) {
00102 PG_LogWRN("PG_Application Object already exists !");
00103 exit(-1);
00104 }
00105
00106 atexit(PARAGUI_ShutDownCode);
00107
00108
00109
00110
00111
00112 #ifdef WIN32
00113 #ifndef __GNUC__
00114
00115 SDL_RegisterApp("ParaGUI", 0, GetModuleHandle(NULL));
00116 #endif
00117 #endif
00118
00119
00120
00121
00122 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
00123 std::cerr << "Could not initialize SDL: " << SDL_GetError() << std::endl;
00124 exit(-1);
00125 }
00126
00127 pGlobalApp = this;
00128 screen = NULL;
00129
00130 mutexScreen = SDL_CreateMutex();
00131 my_background = NULL;
00132 my_freeBackground = false;
00133 my_backmode = PG_Draw::TILE;
00134 my_defaultEventSupplier = new PG_SDLEventSupplier;
00135 my_eventSupplier = my_defaultEventSupplier;
00136
00137
00138 AddArchive(GetBaseDir());
00139 }
00140
00141 PG_Application::~PG_Application() {
00142
00143 PG_LogConsole::Done();
00144
00145
00146 Shutdown();
00147
00148 pGlobalApp = NULL;
00149 delete my_defaultEventSupplier;
00150 my_defaultEventSupplier = NULL;
00151
00152
00153 PG_FileArchive::RemoveAllArchives();
00154 SDL_Quit();
00155
00156 }
00157
00159 bool PG_Application::InitScreen(int w, int h, int depth, Uint32 flags) {
00160
00161 if(depth == 0) {
00162 const SDL_VideoInfo* info = SDL_GetVideoInfo();
00163 if ( info->vfmt->BitsPerPixel > 8 ) {
00164 depth = info->vfmt->BitsPerPixel;
00165 }
00166 }
00167
00168
00169
00170
00171
00172 PG_Application::screen = SDL_SetVideoMode(w, h, depth, flags);
00173 if (PG_Application::screen == NULL) {
00174 PG_LogERR("Could not set video mode: %s", SDL_GetError());
00175 return false;
00176 }
00177
00178 #ifdef DEBUG
00179 PrintVideoTest();
00180 #endif // DEBUG
00181
00182 SetScreen(screen);
00183
00184 eventInit();
00185
00186 PG_LogConsole::SetMethod( PG_LogConsole::GetMethod() |PG_LOGMTH_CONSOLE);
00187 PG_LogDBG("Screen initialized !");
00188
00189 return true;
00190 }
00191
00193 void PG_Application::Run() {
00194 RunEventLoop();
00195 }
00196
00197 void PG_Application::EnableAppIdleCalls(bool enable) {
00198 enableAppIdleCalls = enable;
00199 }
00200
00201 bool PG_Application::GetAppIdleCallsEnabled() {
00202 return enableAppIdleCalls;
00203 }
00204
00207 void PG_Application::RunEventLoop() {
00208 SDL_Event event;
00209 my_quitEventLoop = false;
00210
00211 FlushEventQueue();
00212
00213 while(!my_quitEventLoop) {
00214 ClearOldMousePosition();
00215
00216 if(enableAppIdleCalls) {
00217 if ( my_eventSupplier->PollEvent(&event) == 0) {
00218 eventIdle();
00219 } else {
00220 PumpIntoEventQueue(&event);
00221 }
00222 } else {
00223 if(my_eventSupplier->WaitEvent(&event) != 1) {
00224 SDL_Delay(10);
00225 continue;
00226 }
00227 PumpIntoEventQueue(&event);
00228 }
00229
00230 DrawCursor();
00231 }
00232 }
00233
00234
00235 void PG_Application::SetEventSupplier( PG_EventSupplier* eventSupplier ) {
00236 if ( eventSupplier )
00237 my_eventSupplier = eventSupplier;
00238 else
00239 my_eventSupplier = my_defaultEventSupplier;
00240 }
00241
00242 PG_EventSupplier* PG_Application::GetEventSupplier() {
00243 return my_eventSupplier;
00244 }
00245
00246
00247 void PG_Application::ClearOldMousePosition() {
00248 if(!my_mouse_position.my_width) {
00249 return;
00250 }
00251
00252 if(GetBulkMode() || my_mouse_backingstore==NULL || my_mouse_mode != SOFTWARE ) {
00253 return;
00254 }
00255
00256 SDL_BlitSurface(my_mouse_backingstore, NULL, GetScreen(), &my_mouse_position);
00257
00258 return;
00259 }
00260
00261 void PG_Application::DrawCursor(bool update) {
00262 int x, y;
00263
00264 if(!my_mouse_pointer || my_mouse_mode != SOFTWARE) {
00265 return;
00266 }
00267
00268 if(SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) {
00269
00270 SDL_ShowCursor(SDL_DISABLE);
00271 }
00272
00273 my_eventSupplier->GetMouseState(x, y);
00274
00275 Sint16 dx = x - my_mouse_position.my_xpos;
00276 Sint16 dy = y - my_mouse_position.my_ypos;
00277
00278
00279 PG_Rect vertical(0, my_mouse_position.my_ypos, abs(dx), my_mouse_pointer->h + abs(dy));
00280 if(dx >= 0) {
00281 vertical.my_xpos = my_mouse_position.my_xpos;
00282 } else {
00283 vertical.my_xpos = my_mouse_position.my_xpos + my_mouse_pointer->w + dx;
00284 }
00285
00286
00287 PG_Rect horizontal(my_mouse_position.my_xpos, 0, my_mouse_pointer->w + abs(dx), abs(dy));
00288 if(dy >= 0) {
00289 horizontal.my_ypos = my_mouse_position.my_ypos;
00290 } else {
00291 horizontal.my_ypos = my_mouse_position.my_ypos + my_mouse_pointer->h + dy;
00292 }
00293
00294
00295 if(vertical.my_xpos + vertical.my_width > screen->w) {
00296 if(vertical.my_xpos >= screen->w) {
00297 vertical.my_xpos = screen->w - 1;
00298 }
00299 vertical.my_width = screen->w - vertical.my_xpos;
00300 }
00301 if(vertical.my_ypos + vertical.my_height > screen->h) {
00302 if(vertical.my_ypos >= screen->h) {
00303 vertical.my_ypos = screen->h - 1;
00304 }
00305 vertical.my_height = screen->h - vertical.my_ypos;
00306 }
00307
00308 if(horizontal.my_xpos + horizontal.my_width > screen->w) {
00309 if(horizontal.my_xpos >= screen->w) {
00310 horizontal.my_xpos = screen->w - 1;
00311 }
00312 horizontal.my_width = screen->w - horizontal.my_xpos;
00313 }
00314 if(horizontal.my_ypos + horizontal.my_height > screen->h) {
00315 if(horizontal.my_ypos >= screen->h) {
00316 horizontal.my_ypos = screen->h - 1;
00317 }
00318 horizontal.my_height = screen->h - horizontal.my_ypos;
00319 }
00320
00321 my_mouse_position.my_xpos = x;
00322 my_mouse_position.my_ypos = y;
00323 my_mouse_position.my_width = my_mouse_pointer->w;
00324 my_mouse_position.my_height = my_mouse_pointer->h;
00325
00326
00327 if(my_mouse_backingstore == NULL) {
00328 my_mouse_backingstore = PG_Draw::CreateRGBSurface(my_mouse_pointer->w, my_mouse_pointer->h);
00329 }
00330 SDL_BlitSurface(GetScreen(), &my_mouse_position, my_mouse_backingstore, NULL);
00331
00332
00333 SDL_BlitSurface(my_mouse_pointer, 0, screen, &my_mouse_position);
00334
00335 if(!GetBulkMode() && update) {
00336 SDL_Rect rects[3] = {horizontal, vertical, my_mouse_position};
00337 UpdateRects(screen, 3, rects);
00338 }
00339 }
00340
00341 void PG_Application::Quit() {
00342 sigQuit(this);
00343 eventQuit(0, this, 0);
00344 }
00345
00347 bool PG_Application::eventKeyDown(const SDL_KeyboardEvent* key) {
00348 SDLKey ckey = PG_LogConsole::GetConsoleKey();
00349
00350 if(ckey == 0) {
00351 return false;
00352 }
00353
00354 if (key->keysym.sym == ckey) {
00355 PG_LogConsole::Update();
00356 PG_LogConsole::Toggle();
00357 return true;
00358 }
00359
00360 return false;
00361 }
00362
00363 bool PG_Application::eventKeyUp(const SDL_KeyboardEvent* key) {
00364
00365 if((key->keysym.sym == SDLK_ESCAPE) && emergencyQuit) {
00366 Quit();
00367 return true;
00368 }
00369
00370 return false;
00371 }
00372
00373 bool PG_Application::eventResize(const SDL_ResizeEvent* event) {
00374 if (!event)
00375 return false;
00376
00377 screen = SDL_SetVideoMode(
00378 event->w, event->h,
00379 screen->format->BitsPerPixel,
00380 screen->flags);
00381
00382 PG_Widget::UpdateRect(PG_Rect(0,0,event->w,event->h));
00383 UpdateRect(screen,0,0,event->w,event->h);
00384 sigVideoResize(this, event);
00385
00386 return true;
00387 }
00388
00389 void PG_Application::SetCursor(SDL_Surface *image) {
00390 if(image == 0) {
00391 if(!my_mouse_pointer) {
00392 return;
00393 }
00394 UnloadSurface(my_mouse_backingstore);
00395 my_mouse_backingstore = NULL;
00396 UnloadSurface(my_mouse_pointer);
00397 my_mouse_pointer = NULL;
00398 ClearOldMousePosition();
00399 UpdateRects(screen, 1, &my_mouse_position);
00400 SDL_ShowCursor(SDL_ENABLE);
00401 return;
00402 }
00403 if(!my_mouse_pointer) {
00404 my_mouse_pointer = image;
00405 } else {
00406 UnloadSurface(my_mouse_pointer);
00407 my_mouse_pointer = image;
00408 }
00409
00410 UnloadSurface(my_mouse_backingstore);
00411 my_mouse_backingstore = NULL;
00412 image->refcount++;
00413 DrawCursor();
00414 }
00415
00416 PG_Application::CursorMode PG_Application::ShowCursor(CursorMode mode) {
00417 switch(mode) {
00418 case NONE:
00419 SDL_ShowCursor(SDL_DISABLE);
00420 break;
00421 case HARDWARE:
00422 SDL_ShowCursor(SDL_ENABLE);
00423 break;
00424 case SOFTWARE:
00425 DrawCursor();
00426 break;
00427 case QUERY:
00428 return my_mouse_mode;
00429
00430 }
00431 CursorMode orig = my_mouse_mode;
00432 if(mode != SOFTWARE && my_mouse_mode == SOFTWARE) {
00433 ClearOldMousePosition();
00434 UpdateRects(screen, 1, &my_mouse_position);
00435 }
00436 my_mouse_mode = mode;
00437 return orig;
00438 }
00439
00440
00441 #include "../../../../sdl/graphicsqueue.h"
00442
00443 void PG_Application::UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h)
00444 {
00445 #ifdef WIN32
00446 queueOperation( new UpdateRectOp( screen, x, y, w, h ));
00447 #else
00448 SDL_UpdateRect( screen,x,y,w,h);
00449 postScreenUpdate(screen);
00450 #endif
00451 }
00452
00453 void PG_Application::UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects)
00454 {
00455 #ifdef WIN32
00456 queueOperation( new UpdateRectsOp( screen, numrects, rects ));
00457 #else
00458 SDL_UpdateRects( screen, numrects, rects );
00459 postScreenUpdate(screen);
00460 #endif
00461 }
00462
00463
00465 SDL_Surface* PG_Application::SetScreen(SDL_Surface* surf, bool initialize ) {
00466 if (!surf)
00467 return PG_Application::screen;
00468
00469 PG_Application::screen = surf;
00470
00471 if ( initialize ) {
00472
00473
00474
00475 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
00476 SDL_EnableUNICODE(true);
00477
00478 PG_Widget::UpdateRect(PG_Rect(0,0,screen->w,screen->h));
00479 UpdateRect(screen, 0,0,screen->w,screen->h);
00480 }
00481
00482 return PG_Application::screen;
00483 }
00484
00486 bool PG_Application::SetBackground(const std::string& filename, PG_Draw::BkMode mode) {
00487 if (filename.empty()) {
00488 return false;
00489 }
00490
00491 if ( !SetBackground ( LoadSurface(filename), mode, true ))
00492 PG_LogWRN("Failed to load '%s'",(char*)filename.c_str());
00493
00494 return false;
00495 }
00496
00498 bool PG_Application::SetBackground(SDL_Surface* surface, PG_Draw::BkMode mode, bool freeBackground ) {
00499 if(surface == NULL)
00500 return false;
00501
00502 if(my_scaled_background) {
00503
00504 SDL_FreeSurface(my_scaled_background);
00505 my_scaled_background = 0;
00506 }
00507 if(my_freeBackground && my_background) {
00508 UnloadSurface(my_background);
00509 my_freeBackground = freeBackground;
00510 }
00511
00512 my_background = surface;
00513 my_backmode = mode;
00514
00515 RedrawBackground(PG_Rect(0,0,screen->w,screen->h));
00516 PG_Widget::GetWidgetList()->Blit();
00517 if(!GetBulkMode() )
00518 UpdateRect(screen,0,0,GetScreen()->w,GetScreen()->h);
00519 return true;
00520 }
00521
00523 void PG_Application::RedrawBackground(const PG_Rect& rect) {
00524 if(GetBulkMode()) {
00525 return;
00526 }
00527
00528 PG_Rect fillrect = rect;
00529
00530 if(!my_background || !enableBackground) {
00531 SDL_FillRect(screen, const_cast<PG_Rect*>(&fillrect), my_backcolor.MapRGB(screen->format));
00532 return;
00533 }
00534 if(my_backmode == PG_Draw::STRETCH &&
00535 (my_background->w != screen->w ||
00536 my_background->h != screen->h)) {
00537 if(my_scaled_background &&
00538 (my_scaled_background->w != screen->w ||
00539 my_scaled_background->h != screen->h)) {
00540 UnloadSurface(my_scaled_background);
00541 my_scaled_background = NULL;
00542 }
00543 if(!my_scaled_background) {
00544 SDL_Surface* temp = PG_Draw::ScaleSurface(my_background, static_cast<Uint16>(screen->w), static_cast<Uint16>(screen->h));
00545 my_scaled_background = SDL_DisplayFormat(temp);
00546 UnloadSurface(temp);
00547
00548
00549 }
00550 SDL_GetClipRect(screen, const_cast<PG_Rect*>(&fillrect));
00551 SDL_SetClipRect(screen, const_cast<PG_Rect*>(&rect));
00552 SDL_SetAlpha(my_scaled_background, 0, 0);
00553 SDL_BlitSurface(my_scaled_background, const_cast<PG_Rect*>(&rect), screen, const_cast<PG_Rect*>(&rect));
00554 SDL_SetClipRect(screen, const_cast<PG_Rect*>(&fillrect));
00555
00556 } else {
00557 SDL_SetAlpha(my_background, 0, 0);
00558 PG_Draw::DrawTile(screen, PG_Rect(0,0,screen->w,screen->h), rect, my_background);
00559 }
00560 }
00561
00563 const std::string& PG_Application::GetRelativePath(const std::string& file) {
00564 static std::string buffer = "";
00565
00566 if(Exists(file)) {
00567 buffer = (std::string)GetRealDir(file) + file;
00568 }
00569
00570 return buffer;
00571 }
00572
00573 void PG_Application::FlipPage() {
00574 SDL_Flip(screen);
00575 }
00576
00577 #ifdef DEBUG
00578
00579 void PG_Application::PrintVideoTest() {
00580 const SDL_VideoInfo *info;
00581 int i;
00582 SDL_Rect **modes;
00583
00584 info = SDL_GetVideoInfo();
00585 PG_LogDBG("Current display: %d bits-per-pixel", info->vfmt->BitsPerPixel);
00586
00587 if ( info->vfmt->palette == NULL ) {
00588
00589 PG_LogDBG(" - Red Mask = 0x%x", info->vfmt->Rmask);
00590 PG_LogDBG(" - Green Mask = 0x%x", info->vfmt->Gmask);
00591 PG_LogDBG(" - Blue Mask = 0x%x", info->vfmt->Bmask);
00592 }
00593
00594 modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
00595 if ( modes == (SDL_Rect **)0 ) {
00596 PG_LogDBG("No available fullscreen video modes");
00597 } else
00598 if ( modes == (SDL_Rect **)-1 ) {
00599 PG_LogDBG("No special fullscreen video modes");
00600 } else {
00601 PG_LogDBG("Fullscreen video modes:");
00602 for ( i=0; modes[i]; ++i ) {
00603 PG_LogDBG(" - %d x %d", modes[i]->w, modes[i]->h);
00604 }
00605 }
00606 if ( info->wm_available ) {
00607 PG_LogDBG("A window manager is available");
00608 }
00609 if ( info->hw_available ) {
00610 PG_LogDBG("Hardware surfaces are available (%d K video memory)", info->video_mem);
00611 }
00612 if ( info->blit_hw ) {
00613 PG_LogDBG("Copy blits between hardware surfaces are accelerated");
00614 }
00615 if ( info->blit_hw_CC ) {
00616 PG_LogDBG("Colorkey blits between hardware surfaces are accelerated");
00617 }
00618 if ( info->blit_hw_A ) {
00619 PG_LogDBG("Alpha blits between hardware surfaces are accelerated");
00620 }
00621 if ( info->blit_sw ) {
00622 PG_LogDBG("Copy blits from software surfaces to hardware surfaces are accelerated");
00623 }
00624 if ( info->blit_sw_CC ) {
00625 PG_LogDBG("Colorkey blits from software surfaces to hardware surfaces are accelerated");
00626 }
00627 if ( info->blit_sw_A ) {
00628 PG_LogDBG("Alpha blits from software surfaces to hardware surfaces are accelerated");
00629 }
00630 if ( info->blit_fill ) {
00631 PG_LogDBG("Color fills on hardware surfaces are accelerated");
00632 }
00633 }
00634 #endif // DEBUG
00635
00636 void PG_Application::eventInit() {}
00637
00638 PG_Theme* PG_Application::LoadTheme(const std::string& xmltheme, bool asDefault, const std::string& searchpath) {
00639 PG_Theme* theme = NULL;
00640
00641 PG_LogDBG("Locating theme '%s' ...", xmltheme.c_str());
00642
00643 if(!searchpath.empty()) {
00644 if(AddArchive(searchpath)) {
00645 PG_LogDBG("'%s' added to searchpath", searchpath.c_str());
00646 }
00647 }
00648
00649 #ifdef __MACOS__
00650
00651 if(AddArchive("")) {
00652 PG_LogDBG("'' added to searchpath");
00653 }
00654
00655 if(AddArchive(":")) {
00656 PG_LogDBG("':' added to searchpath");
00657 }
00658
00659 if(AddArchive(":data:")) {
00660 PG_LogDBG("':data:' added to searchpath");
00661 }
00662
00663 if(AddArchive("::data:")) {
00664 PG_LogDBG("'::data:' added to searchpath");
00665 }
00666
00667 if(PARAGUI_THEMEDIR != NULL) {
00668 PG_LogDBG("'"PARAGUI_THEMEDIR"' added to searchpath");
00669 }
00670
00671 #else
00672
00673 if(AddArchive("./")) {
00674 PG_LogDBG("'./' added to searchpath");
00675 }
00676
00677 if(AddArchive("../")) {
00678 PG_LogDBG("'../' added to searchpath");
00679 }
00680
00681 if(AddArchive("./data/")) {
00682 PG_LogDBG("'./data/' added to searchpath");
00683 }
00684
00685 if(AddArchive("../data/")) {
00686 PG_LogDBG("'../data/' added to searchpath");
00687 }
00688
00689 if(getenv("PARAGUIDIR") != NULL) {
00690 if(AddArchive(getenv("PARAGUIDIR"))) {
00691 PG_LogDBG("'%s' added to searchpath", getenv("PARAGUIDIR"));
00692 }
00693 }
00694
00695 #endif // __MACOS__
00696
00697 if(AddArchive(PARAGUI_THEMEDIR)) {
00698 PG_LogDBG("'"PARAGUI_THEMEDIR "' added to searchpath");
00699 }
00700
00701 theme = PG_Theme::Load(xmltheme);
00702
00703 if(theme && asDefault) {
00704
00705 const std::string& c = theme->FindDefaultFontName();
00706 if(c.empty()) {
00707 PG_LogWRN("Unable to load default font ...");
00708 delete theme;
00709 return NULL;
00710 }
00711
00712 DefaultFont = new PG_Font(c, theme->FindDefaultFontSize());
00713 DefaultFont->SetStyle(theme->FindDefaultFontStyle());
00714
00715 PG_LogMSG("defaultfont: %s", c.c_str());
00716 PG_LogMSG("size: %i", DefaultFont->GetSize());
00717
00718 my_background = theme->FindSurface("Background", "Background", "background");
00719 theme->GetProperty("Background", "Background", "backmode", my_backmode);
00720 theme->GetColor("Background", "Background", "backcolor", my_backcolor);
00721
00722 if(my_scaled_background) {
00723
00724 SDL_FreeSurface(my_scaled_background);
00725 my_scaled_background = 0;
00726 }
00727 } else {
00728
00729 PG_LogWRN("Failed to load !");
00730 }
00731
00732 if((my_Theme != NULL) && asDefault) {
00733 delete my_Theme;
00734 my_Theme = NULL;
00735 }
00736
00737 if(asDefault && theme) {
00738 my_Theme = theme;
00739 }
00740
00741 return theme;
00742 }
00743
00744 bool PG_Application::eventQuit(int id, PG_MessageObject* widget, unsigned long data) {
00745 if(GetBulkMode()) {
00746 return false;
00747 }
00748
00749 my_quitEventLoop = true;
00750
00751 if(my_mouse_pointer) {
00752 UnloadSurface(my_mouse_pointer);
00753 my_mouse_pointer = 0;
00754 SDL_ShowCursor(SDL_ENABLE);
00755 }
00756
00757 return true;
00758 }
00759
00760 void PG_Application::SetBulkMode(bool bulk) {
00761 bulkMode = bulk;
00762 }
00763
00764 void PG_Application::Shutdown() {
00765 DeleteBackground();
00766
00767
00768 PG_Widget* list = PG_Widget::GetWidgetList()->first();
00769
00770 while((list = PG_Widget::GetWidgetList()->first()) != NULL) {
00771 delete list;
00772 }
00773
00774
00775 if(my_Theme) {
00776 delete my_Theme;
00777 my_Theme = NULL;
00778 }
00779
00780
00781 SDL_DestroyMutex(mutexScreen);
00782
00783
00784 delete DefaultFont;
00785 DefaultFont = NULL;
00786
00787
00788 UnloadSurface(my_mouse_backingstore);
00789 my_mouse_backingstore = NULL;
00790 }
00791
00792 void PG_Application::SetEmergencyQuit(bool esc) {
00793 emergencyQuit = esc;
00794 }
00795
00796 void PG_Application::SetIcon(const std::string& filename) {
00797 SDL_Surface* icon;
00798 Uint8* pixels;
00799 Uint8* mask;
00800 int mlen, i;
00801
00802
00803 icon = LoadSurface(filename);
00804 if ( icon == NULL ) {
00805 PG_LogWRN("Failed to load icon!");
00806 return;
00807 }
00808
00809
00810 if ( (icon->w%8) != 0 ) {
00811 PG_LogWRN("Icon width must be a multiple of 8!");
00812 UnloadSurface(icon);
00813 return;
00814 }
00815
00816
00817 if ( icon->format->palette == NULL ) {
00818 PG_LogWRN("Icon must have a palette!");
00819 UnloadSurface(icon);
00820 return;
00821 }
00822
00823
00824 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *)icon->pixels));
00825
00826
00827 pixels = (Uint8 *)icon->pixels;
00828 mlen = icon->w*icon->h;
00829 mask = new Uint8[mlen/8];
00830
00831 if ( mask == NULL ) {
00832 PG_LogWRN("Out of memory when allocating mask for icon !");
00833 UnloadSurface(icon);
00834 return;
00835 }
00836
00837 memset(mask, 0, mlen/8);
00838 for ( i=0; i<mlen; ) {
00839 if ( pixels[i] != *pixels ) {
00840 mask[i/8] |= 0x01;
00841 }
00842
00843 ++i;
00844 if ( (i%8) != 0 ) {
00845 mask[i/8] <<= 1;
00846 }
00847 }
00848
00849
00850 if ( icon != NULL ) {
00851 SDL_WM_SetIcon(icon, mask);
00852 }
00853
00854
00855 delete[] mask;
00856 }
00857
00858 void PG_Application::SetCaption(const std::string& title, const std::string& icon) {
00859 SDL_WM_SetCaption(title.c_str(), NULL);
00860 if (!icon.empty()) {
00861 SetIcon(icon);
00862 }
00863 }
00864
00865 void PG_Application::GetCaption(std::string& title, std::string& icon) {
00866 char** t = NULL;
00867 char** i = NULL;
00868 SDL_WM_GetCaption(t, i);
00869 title = *t;
00870 icon = *i;
00871 }
00872
00873 int PG_Application::Iconify(void) {
00874 return SDL_WM_IconifyWindow();
00875 }
00876
00877
00878 bool PG_Application::LoadLayout(const std::string& name) {
00879 return PG_Layout::Load(NULL, name, NULL, NULL);
00880 }
00881
00882 bool PG_Application::LoadLayout(const std::string& name, void (* WorkCallback)(int now, int max)) {
00883 return PG_Layout::Load(NULL, name, WorkCallback, NULL);
00884 }
00885
00886 bool PG_Application::LoadLayout(const std::string& name, void (* WorkCallback)(int now, int max), void *UserSpace) {
00887 return PG_Layout::Load(NULL, name, WorkCallback, UserSpace);
00888 }
00889
00890 static PG_Widget *FindInChildObjects(PG_RectList *RectList, const std::string& Name) {
00891 PG_Widget *retWidget = NULL;
00892
00893 if (RectList == NULL) {
00894 return NULL;
00895 }
00896
00897 if(Name.empty()) {
00898 return NULL;
00899 }
00900
00901 PG_Widget* list = RectList->first();
00902
00903 while(list != NULL) {
00904 if(list->GetName() == Name) {
00905 return list;
00906 }
00907
00908 PG_Widget* result = list->FindChild(Name);
00909 if(result != NULL) {
00910 return result;
00911 }
00912
00913 retWidget = FindInChildObjects(list->GetChildList(), Name);
00914 if (retWidget != NULL) {
00915 return retWidget;
00916 }
00917
00918 list = list->next();
00919 }
00920
00921 return NULL;
00922 }
00923
00924 static inline PG_Widget *FindInChildObjects(PG_RectList *RectList, int id) {
00925 PG_Widget *retWidget = NULL;
00926
00927 if (RectList == NULL) {
00928 return NULL;
00929 }
00930
00931 if (id < 0)
00932 return 0;
00933
00934 PG_Widget* list = RectList->first();
00935
00936 while(list != NULL) {
00937 if (list->GetID() == id) {
00938 return list;
00939 }
00940
00941
00942 PG_Widget* result = list->FindChild(id);
00943 if(result != NULL) {
00944 return result;
00945 }
00946
00947 retWidget = FindInChildObjects(list->GetChildList(), id);
00948 if (retWidget != NULL) {
00949 return retWidget;
00950 }
00951
00952 list = list->next();
00953 }
00954
00955 return NULL;
00956 }
00957
00958 PG_Widget* PG_Application::GetWidgetByName(const std::string& Name) {
00959 return (FindInChildObjects(PG_Widget::GetWidgetList(), Name));
00960 }
00961
00962 PG_Widget *PG_Application::GetWidgetById(int id) {
00963 return (FindInChildObjects(PG_Widget::GetWidgetList(), id));
00964 }
00965
00966 void PG_Application::SetFontColor(const PG_Color& Color) {
00967 DefaultFont->SetColor(Color);
00968 }
00969
00970 void PG_Application::SetFontAlpha(int Alpha) {
00971 DefaultFont->SetAlpha(Alpha);
00972 }
00973
00974 void PG_Application::SetFontStyle(PG_Font::Style Style) {
00975 DefaultFont->SetStyle(Style);
00976 }
00977
00978 void PG_Application::SetFontSize(int Size) {
00979 DefaultFont->SetSize(Size);
00980 }
00981
00982 void PG_Application::SetFontIndex(int Index) {
00983
00984 }
00985
00986 void PG_Application::SetFontName(const std::string& Name) {
00987 DefaultFont->SetName(Name);
00988 }
00989
00990
00991
00992
00993
00994 int PG_Application::GetScreenHeight() {
00995 return screen->h;
00996 }
00997
00998 int PG_Application::GetScreenWidth() {
00999 return screen->w;
01000 }
01001
01002 PG_Theme* PG_Application::GetTheme() {
01003 return my_Theme;
01004 }
01005
01006 bool PG_Application::GetBulkMode() {
01007 return bulkMode;
01008 }
01009
01010
01011
01012
01013
01014 void PG_Application::EnableBackground(bool enable) {
01015 enableBackground = enable;
01016 }
01017
01018 void PG_Application::DeleteBackground() {
01019 enableBackground = false;
01020
01021 if(my_scaled_background) {
01022
01023 SDL_FreeSurface(my_scaled_background);
01024 my_scaled_background = 0;
01025 }
01026 if(my_freeBackground && my_background) {
01027 UnloadSurface(my_background);
01028 my_freeBackground = false;
01029 }
01030
01031 my_background = 0;
01032 }
01033
01034 void PG_Application::DisableDirtyUpdates(bool disable) {
01035 disableDirtyUpdates = disable;
01036 }
01037
01038 bool PG_Application::GetDirtyUpdatesDisabled() {
01039 return disableDirtyUpdates;
01040 }
01041
01042 PG_Application* PG_Application::GetApp() {
01043 return pGlobalApp;
01044 }
01045
01046 void PG_Application::FlushEventQueue() {
01047 SDL_Event event;
01048
01049 while(my_eventSupplier->PollEvent(&event)) {
01050
01051
01052
01053 }
01054 }
01055
01056 void PG_Application::eventIdle() {
01057 sigAppIdle(this);
01058 SDL_Delay(1);
01059 }
01060
01061 void PG_Application::TranslateNumpadKeys(SDL_KeyboardEvent *key) {
01062
01063
01064
01065 if (key->keysym.unicode==0) {
01066 if (key->keysym.mod & KMOD_NUM) {
01067
01068 switch (key->keysym.sym) {
01069 case SDLK_KP0 :
01070 key->keysym.sym = SDLK_0;
01071 key->keysym.unicode = SDLK_0;
01072 break;
01073 case SDLK_KP1 :
01074 key->keysym.sym = SDLK_1;
01075 key->keysym.unicode = SDLK_1;
01076 break;
01077 case SDLK_KP2 :
01078 key->keysym.sym = SDLK_2;
01079 key->keysym.unicode = SDLK_2;
01080 break;
01081 case SDLK_KP3 :
01082 key->keysym.sym = SDLK_3;
01083 key->keysym.unicode = SDLK_3;
01084 break;
01085 case SDLK_KP4 :
01086 key->keysym.sym = SDLK_4;
01087 key->keysym.unicode = SDLK_4;
01088 break;
01089 case SDLK_KP5 :
01090 key->keysym.sym = SDLK_5;
01091 key->keysym.unicode = SDLK_5;
01092 break;
01093 case SDLK_KP6 :
01094 key->keysym.sym = SDLK_6;
01095 key->keysym.unicode = SDLK_6;
01096 break;
01097 case SDLK_KP7 :
01098 key->keysym.sym = SDLK_7;
01099 key->keysym.unicode = SDLK_7;
01100 break;
01101 case SDLK_KP8 :
01102 key->keysym.sym = SDLK_8;
01103 key->keysym.unicode = SDLK_8;
01104 break;
01105 case SDLK_KP9 :
01106 key->keysym.sym = SDLK_9;
01107 key->keysym.unicode = SDLK_9;
01108 break;
01109 case SDLK_KP_PERIOD :
01110 key->keysym.sym = SDLK_PERIOD;
01111 key->keysym.unicode = SDLK_PERIOD;
01112 break;
01113 case SDLK_KP_DIVIDE :
01114 key->keysym.sym = SDLK_BACKSLASH;
01115 key->keysym.unicode = SDLK_BACKSLASH;
01116 break;
01117 case SDLK_KP_MULTIPLY:
01118 key->keysym.sym = SDLK_ASTERISK;
01119 key->keysym.unicode = SDLK_ASTERISK;
01120 break;
01121 case SDLK_KP_MINUS :
01122 key->keysym.sym = SDLK_MINUS;
01123 key->keysym.unicode = SDLK_MINUS;
01124 break;
01125 case SDLK_KP_PLUS :
01126 key->keysym.sym = SDLK_PLUS;
01127 key->keysym.unicode = SDLK_PLUS;
01128 break;
01129 case SDLK_KP_ENTER :
01130 key->keysym.sym = SDLK_RETURN;
01131 key->keysym.unicode = SDLK_RETURN;
01132 break;
01133 case SDLK_KP_EQUALS :
01134 key->keysym.sym = SDLK_EQUALS;
01135 key->keysym.unicode = SDLK_EQUALS;
01136 break;
01137
01138 default:
01139 break;
01140 }
01141 } else {
01142
01143 switch (key->keysym.sym) {
01144 case SDLK_KP0 :
01145 key->keysym.sym = SDLK_INSERT;
01146 key->keysym.unicode = 0;
01147 break;
01148 case SDLK_KP1 :
01149 key->keysym.sym = SDLK_END;
01150 key->keysym.unicode = 0;
01151 break;
01152 case SDLK_KP2 :
01153 key->keysym.sym = SDLK_DOWN;
01154 key->keysym.unicode = 0;
01155 break;
01156 case SDLK_KP3 :
01157 key->keysym.sym = SDLK_PAGEDOWN;
01158 key->keysym.unicode = 0;
01159 break;
01160 case SDLK_KP4 :
01161 key->keysym.sym = SDLK_LEFT;
01162 key->keysym.unicode = 0;
01163 break;
01164 case SDLK_KP6 :
01165 key->keysym.sym = SDLK_RIGHT;
01166 key->keysym.unicode = 0;
01167 break;
01168 case SDLK_KP7 :
01169 key->keysym.sym = SDLK_HOME;
01170 key->keysym.unicode = 0;
01171 break;
01172 case SDLK_KP8 :
01173 key->keysym.sym = SDLK_UP;
01174 key->keysym.unicode = 0;
01175 break;
01176 case SDLK_KP9 :
01177 key->keysym.sym = SDLK_PAGEUP;
01178 key->keysym.unicode = 0;
01179 break;
01180 case SDLK_KP_PERIOD :
01181 key->keysym.sym = SDLK_DELETE;
01182 key->keysym.unicode = 0;
01183 break;
01184 case SDLK_KP_DIVIDE :
01185 key->keysym.sym = SDLK_BACKSLASH;
01186 key->keysym.unicode = SDLK_BACKSLASH;
01187 break;
01188 case SDLK_KP_MULTIPLY:
01189 key->keysym.sym = SDLK_ASTERISK;
01190 key->keysym.unicode = SDLK_ASTERISK;
01191 break;
01192 case SDLK_KP_MINUS :
01193 key->keysym.sym = SDLK_MINUS;
01194 key->keysym.unicode = SDLK_MINUS;
01195 break;
01196 case SDLK_KP_PLUS :
01197 key->keysym.sym = SDLK_PLUS;
01198 key->keysym.unicode = SDLK_PLUS;
01199 break;
01200 case SDLK_KP_ENTER :
01201 key->keysym.sym = SDLK_RETURN;
01202 key->keysym.unicode = SDLK_RETURN;
01203 break;
01204 case SDLK_KP_EQUALS :
01205 key->keysym.sym = SDLK_EQUALS;
01206 key->keysym.unicode = SDLK_EQUALS;
01207 break;
01208
01209 default:
01210 break;
01211 }
01212 }
01213 }
01214 }
01215
01216 bool PG_Application::PumpIntoEventQueue(const SDL_Event* event) {
01217 PG_Widget* widget = NULL;
01218
01219
01220 if((event->type != SDL_USEREVENT) && (event->type != SDL_VIDEORESIZE)) {
01221 if(captureObject) {
01222 return captureObject->ProcessEvent(event);
01223 }
01224 }
01225
01226 switch(event->type) {
01227
01228 case SDL_KEYDOWN:
01229 case SDL_KEYUP:
01230 if(inputFocusObject) {
01231
01232 if(inputFocusObject->ProcessEvent(event)) {
01233 return true;
01234 }
01235
01236 }
01237 break;
01238
01239 case SDL_MOUSEMOTION:
01240 widget = PG_Widget::FindWidgetFromPos(event->motion.x, event->motion.y);
01241
01242 if(lastwidget && (lastwidget != widget)) {
01243 lastwidget->eventMouseLeave();
01244 lastwidget = NULL;
01245 }
01246
01247 if(widget) {
01248 lastwidget = widget;
01249 widget->ProcessEvent(event);
01250 return true;
01251 }
01252 return true;
01253
01254 case SDL_MOUSEBUTTONUP:
01255 case SDL_MOUSEBUTTONDOWN:
01256 widget = PG_Widget::FindWidgetFromPos(event->button.x, event->button.y);
01257 if(widget) {
01258 widget->ProcessEvent(event);
01259 return true;
01260 }
01261 break;
01262 }
01263
01264
01265 if(ProcessEvent(event)) {
01266 return true;
01267 }
01268
01269
01270 bool processed = false;
01271 PG_Widget* list = PG_Widget::GetWidgetList()->first();
01272
01273 PG_Widget* o = NULL;
01274 while(list != NULL) {
01275 o = list;
01276
01277
01278
01279
01280
01281 if(o->ProcessEvent(event)) {
01282 processed = true;
01283 break;
01284 }
01285 list = list->next();
01286 }
01287
01288 return processed;
01289 }
01290
01291 void PG_Application::SetUpdateOverlappingSiblings(bool update) {
01292 defaultUpdateOverlappingSiblings = update;
01293 }
01294
01295 bool PG_Application::GetUpdateOverlappingSiblings() {
01296 return defaultUpdateOverlappingSiblings;
01297 }
01298
01299 volatile int lockCount = 0;
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320 void PG_Application::SetHighlightingTag( PG_Char c )
01321 {
01322 highlightingTag = c;
01323 }
01324
01325 PG_Char PG_Application::GetHighlightingTag()
01326 {
01327 return highlightingTag;
01328 }
01329
01330
01331
01332
01333
01334
01335