Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

pgapplication.cpp

Go to the documentation of this file.
00001 /*
00002     ParaGUI - crossplatform widgetset
00003     Copyright (C) 2000,2001,2002  Alexander Pipelka
00004  
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009  
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014  
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  
00019     Alexander Pipelka
00020     pipelka@teleweb.at
00021  
00022     Last Update:      $Author: mbickel $
00023     Update Date:      $Date: 2008-04-20 16:44:33 $
00024     Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/core/pgapplication.cpp,v $
00025     CVS/RCS Revision: $Revision: 1.4 $
00026     Status:           $State: Exp $
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 // usually PARAGUI_THEMEDIR is defined by the configure script
00044 // or passed to the compiler. This is just a kind of last resort.
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 //std::string PG_Application::app_path = "";
00058 PG_Theme* PG_Application::my_Theme = NULL;
00059 bool PG_Application::bulkMode = false;
00060 //bool PG_Application::glMode = false;
00061 //bool PG_Application::emergencyQuit = false;
00062 bool PG_Application::enableBackground = true;
00063 //bool PG_Application::enableAppIdleCalls = false;
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 //bool PG_Application::my_quitEventLoop = false;
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         // shutdown SDL
00086         SDL_Quit();
00087 }
00088 
00089 
00090 PG_Application::PG_Application()
00091                 : my_quitEventLoop(false), emergencyQuit(false), enableAppIdleCalls(false) {
00092 
00093         // set UTF8 encoding if UNICODE support is enabled
00094         // we use the "C" locale because it's hard to get the current locale setting
00095         // in a portableway (Win32 doesn't support nl_langinfo).
00096         // The "C" locale is only set for character encoding.
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         /* We need to kludge a bit for keyboards work under windows */
00109         /* we'll call SDL_RegisterApp right before SDL_Init()       */
00110         /* Pete Shinners, Feb 1, 2001                               */
00111 
00112 #ifdef WIN32
00113 #ifndef __GNUC__
00114 
00115         SDL_RegisterApp("ParaGUI", 0, GetModuleHandle(NULL));
00116 #endif
00117 #endif
00118 
00119         // -- see above
00120 
00121         /* Initialize the SDL library */
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         // add our base dir to the searchpath
00138         AddArchive(GetBaseDir());
00139 }
00140 
00141 PG_Application::~PG_Application() {
00142         // shutdown log (before deleting all the widgets)
00143         PG_LogConsole::Done();
00144 
00145         // remove remaining widgets
00146         Shutdown();
00147 
00148         pGlobalApp = NULL;
00149         delete my_defaultEventSupplier;
00150         my_defaultEventSupplier = NULL;
00151 
00152         // remove all archives from PG_FileArchive
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         //if(SDL_VideoModeOK(w, h, depth, flags) == 0)
00169         //      return false;
00170 
00171         /* Initialize the display */
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                 // Hide hardware cursor if visible
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         // calculate vertical update rect
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         // calculate horizontal update rect
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         // clipping
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         // backup current cursor area
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         // draw cursor
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         //glMode = (surf->flags & SDL_OPENGLBLIT);
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                 // Destroyed scaled background if present
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); // size mismatch
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                         /*PG_Draw::ScaleSurface(my_background,
00548                                                       static_cast<Uint16>(screen->w), static_cast<Uint16>(screen->h));*/
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 // All calls to this are ifdefd out also
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                 // FIXME: did I screw this up? :) -Dave
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         /* Print available fullscreen video modes */
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                         // Destroyed scaled background if present
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         // destroy still existing objects
00768         PG_Widget* list = PG_Widget::GetWidgetList()->first();
00769 
00770         while((list = PG_Widget::GetWidgetList()->first()) != NULL) {
00771                 delete list;
00772         }
00773 
00774         // unload theme (and free the allocated mem)
00775         if(my_Theme) {
00776                 delete my_Theme;
00777                 my_Theme = NULL;
00778         }
00779 
00780         // destroy screen mutex
00781         SDL_DestroyMutex(mutexScreen);
00782 
00783         // delete the default font
00784         delete DefaultFont;
00785         DefaultFont = NULL;
00786 
00787         // remove cursor backing store
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         // Load the icon surface
00803         icon = LoadSurface(filename);
00804         if ( icon == NULL ) {
00805                 PG_LogWRN("Failed to load icon!");
00806                 return;
00807         }
00808 
00809         // Check width and height
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         //Check the palette
00817         if ( icon->format->palette == NULL ) {
00818                 PG_LogWRN("Icon must have a palette!");
00819                 UnloadSurface(icon);
00820                 return;
00821         }
00822 
00823         // Set the colorkey
00824         SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *)icon->pixels));
00825 
00826         // Create the mask
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         //Set icon
00850         if ( icon != NULL ) {
00851                 SDL_WM_SetIcon(icon, mask);
00852         }
00853 
00854         //Clean up
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         //DefaultFont->SetIndex(Index);
00984 }
00985 
00986 void PG_Application::SetFontName(const std::string& Name) {
00987         DefaultFont->SetName(Name);
00988 }
00989 
00990 /*SDL_Surface* PG_Application::GetScreen() {
00991         return screen;
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 /*bool PG_Application::GetGLMode() {
01011                 return glMode;
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                 // Destroyed scaled background if present
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                 /*if(event.type == SDL_USEREVENT) {
01051                         delete (MSG_MESSAGE*)(event.user.data1);
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         // note: works on WIN, test this on other platforms
01063 
01064         // numeric keypad translation
01065         if (key->keysym.unicode==0) {    // just optimalisation
01066                 if (key->keysym.mod & KMOD_NUM) {
01067                         // numeric keypad is enabled
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                         // numeric keypad is disabled
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         // do we have a capture hook?
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                                 // first send it to the focus object
01232                                 if(inputFocusObject->ProcessEvent(event)) {
01233                                         return true;
01234                                 }
01235                                 // if the focus object doesn't respond -> pump it into the queue
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         // first let's try to process the event ourself
01265         if(ProcessEvent(event)) {
01266                 return true;
01267         }
01268 
01269         // send to all receivers ( = all top level widgdets )
01270         bool processed = false;
01271         PG_Widget* list = PG_Widget::GetWidgetList()->first();
01272         //vector<PG_MessageObject*>::iterator list = objectList.begin();
01273         PG_Widget* o = NULL;
01274         while(list != NULL) {
01275                 o = list;
01276                 /*if(o == NULL) {
01277                         list = o->next();
01278                         PG_Widget::GetWidgetList()->Remove(o);
01279                         continue;
01280                 }*/
01281                 if(o->ProcessEvent(event)) {
01282                         processed = true;
01283                         break;          // exit loop if an object responds
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 bool PG_Application::LockScreen() {
01302    
01303    int res = SDL_mutexP(mutexScreen);
01304    ++lockCount;
01305    printf("Lock screen %d\n", lockCount);
01306    fflush(stdout);
01307    return (res == 0);
01308 }
01309 
01310 bool PG_Application::UnlockScreen() {
01311    printf("UnLock screen %d\n", lockCount);
01312    --lockCount;
01313    fflush(stdout);
01314    
01315    return (SDL_mutexV(mutexScreen) == 0);
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  * Local Variables:
01333  * c-basic-offset: 8
01334  * End:
01335  */

Generated on Tue Jun 24 01:27:47 2008 for Advanced Strategic Command by  doxygen 1.4.2