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 "pgthemewidget.h"
00030 #include "pgdraw.h"
00031 #include "pgapplication.h"
00032 #include "pglog.h"
00033 #include "pgtheme.h"
00034
00035 #include "propstrings_priv.h"
00036
00037 static PG_SurfaceCache my_SurfaceCache;
00038
00039 class PG_ThemeWidgetDataInternal {
00040 public:
00041 PG_ThemeWidgetDataInternal() :
00042 cachesurface(NULL),
00043 backgroundcolor(128,128,128),
00044 freeimage(false),
00045 simplebackground(false),
00046 nocache(false) {}
00047 ;
00048
00049 SDL_Surface* cachesurface;
00050 PG_Color backgroundcolor;
00051
00052 bool freeimage;
00053 bool simplebackground;
00054 bool nocache;
00055
00056 };
00057
00058 PG_ThemeWidget::PG_ThemeWidget(PG_Widget* parent, const PG_Rect& r, const std::string& style) : PG_Widget(parent, r) {
00059 Init(style);
00060 }
00061
00062 PG_ThemeWidget::PG_ThemeWidget(PG_Widget* parent, const PG_Rect& r, bool bCreateSurface, const std::string& style) : PG_Widget(parent, r, bCreateSurface) {
00063 Init(style);
00064 }
00065
00066 void PG_ThemeWidget::Init(const std::string& style) {
00067 SetDirtyUpdate(true);
00068
00069 _mid = new PG_ThemeWidgetDataInternal;
00070
00071 my_backgroundFree = false;
00072 my_background = NULL;
00073 my_blendLevel = 0;
00074 my_backgroundMode = PG_Draw::TILE;
00075 my_bordersize = 0;
00076 my_has_gradient = false;
00077
00078 my_image = NULL;
00079
00080 LoadThemeStyle(style);
00081 }
00082
00083 PG_ThemeWidget::~PG_ThemeWidget() {
00084
00085
00086 FreeSurface();
00087 FreeImage();
00088
00089
00090 DeleteThemedSurface(_mid->cachesurface);
00091
00092
00093 delete _mid;
00094 }
00095
00096 void PG_ThemeWidget::LoadThemeStyle(const std::string& widgettype) {
00097 if(widgettype != PG_PropStr::ThemeWidget) {
00098 PG_ThemeWidget::LoadThemeStyle(PG_PropStr::ThemeWidget, PG_PropStr::ThemeWidget);
00099 }
00100 PG_ThemeWidget::LoadThemeStyle(widgettype, PG_PropStr::ThemeWidget);
00101 }
00102
00103 void PG_ThemeWidget::LoadThemeStyle(const std::string& widgettype, const std::string& objectname) {
00104
00105 PG_Theme* t = PG_Application::GetTheme();
00106
00107 if(my_srfObject == NULL) {
00108 if(objectname != PG_PropStr::ThemeWidget) {
00109 PG_ThemeWidget::LoadThemeStyle(widgettype, PG_PropStr::ThemeWidget);
00110 }
00111
00112 t->GetProperty(widgettype, objectname, PG_PropStr::simplebackground, _mid->simplebackground);
00113 t->GetProperty(widgettype, objectname, PG_PropStr::nocache, _mid->nocache);
00114 t->GetColor(widgettype, objectname, PG_PropStr::backgroundcolor, _mid->backgroundcolor);
00115 }
00116
00117 const std::string& font = t->FindFontName(widgettype, objectname);
00118 int fontsize = t->FindFontSize(widgettype, objectname);
00119 PG_Font::Style fontstyle = t->FindFontStyle(widgettype, objectname);
00120
00121 if(!font.empty()) {
00122 SetFontName(font);
00123 }
00124
00125 if(fontsize > 0) {
00126 SetFontSize(fontsize);
00127 }
00128
00129 if(fontstyle >= 0) {
00130 SetFontStyle(fontstyle);
00131 }
00132
00133 SetBackground(t->FindSurface(widgettype, objectname, PG_PropStr::background));
00134
00135 t->GetProperty(widgettype, objectname, PG_PropStr::blend, my_blendLevel);
00136 t->GetProperty(widgettype, objectname, PG_PropStr::bordersize, my_bordersize);
00137 t->GetProperty(widgettype, objectname, PG_PropStr::backmode, my_backgroundMode);
00138
00139 PG_Gradient* g = t->FindGradient(widgettype, objectname, PG_PropStr::gradient);
00140
00141 if(g) {
00142 SetGradient(*g);
00143 }
00144
00145 Uint8 trans = GetTransparency();
00146 t->GetProperty(widgettype, objectname, PG_PropStr::transparency, trans);
00147 SetTransparency(trans);
00148
00149 PG_Widget::LoadThemeStyle(widgettype, objectname);
00150
00151 int w = Width();
00152 t->GetProperty(widgettype, objectname, PG_PropStr::width, w);
00153 int h = Height();
00154 t->GetProperty(widgettype, objectname, PG_PropStr::height, h);
00155
00156 if((w != Width()) || (h != Height())) {
00157 SizeWidget(w, h);
00158 }
00159 }
00160
00161 void PG_ThemeWidget::eventDraw(SDL_Surface* surface, const PG_Rect& rect) {
00162 if(my_srfObject == NULL) {
00163 return;
00164 }
00165
00166 PG_Draw::DrawThemedSurface(
00167 surface,
00168 rect,
00169 my_has_gradient ? &my_gradient : 0,
00170 my_background,
00171 my_backgroundMode,
00172 my_blendLevel);
00173
00174 if(my_bordersize > 0) {
00175 DrawBorder(rect, my_bordersize);
00176 }
00177 }
00178
00179 bool PG_ThemeWidget::SetBackground(const std::string& filename, PG_Draw::BkMode mode, const PG_Color &colorkey) {
00180
00181 SDL_Surface* temp = PG_Application::LoadSurface(filename, true);
00182
00183
00184 if(!temp) {
00185 return false;
00186 }
00187
00188
00189 FreeSurface();
00190
00191
00192 my_backgroundFree = true;
00193 my_backgroundMode = mode;
00194 my_background = temp;
00195
00196 if(my_background == NULL) {
00197 return false;
00198 }
00199
00200 Uint32 c = colorkey.MapRGB(my_background->format);
00201 SDL_SetColorKey(my_background, SDL_SRCCOLORKEY, c);
00202
00203 if(my_srfObject == NULL) {
00204 CreateSurface();
00205 }
00206
00207 return (my_background != NULL);
00208 }
00209
00210 bool PG_ThemeWidget::SetBackground(const std::string& filename, PG_Draw::BkMode mode) {
00211
00212
00213 SDL_Surface* temp = PG_Application::LoadSurface(filename, true);
00214
00215
00216 if(!temp) {
00217 return false;
00218 }
00219
00220
00221 FreeSurface();
00222
00223
00224 my_backgroundFree = true;
00225 my_backgroundMode = mode;
00226 my_background = temp;
00227
00228 if(my_background == NULL) {
00229 return false;
00230 }
00231
00232 if(my_srfObject == NULL) {
00233 CreateSurface();
00234 }
00235
00236 return (my_background != NULL);
00237 }
00238
00239
00240 bool PG_ThemeWidget::SetBackground(SDL_Surface* surface, PG_Draw::BkMode mode) {
00241
00242 if(!surface) {
00243 return false;
00244 }
00245
00246 FreeSurface();
00247
00248 my_background = surface;
00249 my_backgroundFree = false;
00250 my_backgroundMode = mode;
00251
00252 if(my_srfObject == NULL) {
00253 CreateSurface();
00254 }
00255
00256 return true;
00257 }
00258
00259 void PG_ThemeWidget::SetBackgroundBlend(Uint8 backblend) {
00260 my_blendLevel = backblend;
00261 }
00262
00263 void PG_ThemeWidget::FreeSurface() {
00264
00265
00266
00267 if (my_backgroundFree && my_background != NULL) {
00268 PG_Application::UnloadSurface(my_background);
00269 my_background = NULL;
00270 my_backgroundFree = false;
00271 }
00272 }
00273
00274 void PG_ThemeWidget::SetGradient(const PG_Gradient& grad) {
00275 my_gradient = grad;
00276 my_has_gradient = true;
00277 DeleteThemedSurface(_mid->cachesurface);
00278 _mid->cachesurface = NULL;
00279 Redraw();
00280 }
00281
00282 PG_Gradient PG_ThemeWidget::GetGradient() {
00283 return my_gradient;
00284 }
00285
00286 void PG_ThemeWidget::FreeImage() {
00287
00288 if(_mid->freeimage) {
00289 PG_Application::UnloadSurface(my_image);
00290 }
00291
00292 _mid->freeimage = false;
00293 my_image = NULL;
00294 return;
00295 }
00296
00297 bool PG_ThemeWidget::SetImage(SDL_Surface* image, bool bFreeImage) {
00298 if(image == NULL) {
00299 return false;
00300 }
00301
00302 if(image == my_image) {
00303 return true;
00304 }
00305
00306 FreeImage();
00307 _mid->freeimage = bFreeImage;
00308 my_image = image;
00309
00310 Update();
00311 return true;
00312 }
00313
00314 bool PG_ThemeWidget::LoadImage(const std::string& filename, const PG_Color& key) {
00315 if(LoadImage(filename)) {
00316 SDL_SetColorKey(my_image, SDL_SRCCOLORKEY, key);
00317 return true;
00318 }
00319
00320 return false;
00321 }
00322
00323 bool PG_ThemeWidget::LoadImage(const std::string& filename) {
00324 SDL_Surface* image = PG_Application::LoadSurface(filename);
00325 return SetImage(image, true);
00326 }
00327
00328 void PG_ThemeWidget::eventSizeWidget(Uint16 w, Uint16 h) {
00329 DeleteThemedSurface(_mid->cachesurface);
00330 _mid->cachesurface = NULL;
00331 }
00332
00333 void PG_ThemeWidget::CreateSurface(Uint16 w, Uint16 h) {
00334 if(_mid->simplebackground) {
00335 return;
00336 }
00337
00338 DeleteThemedSurface(_mid->cachesurface);
00339
00340 if(w == 0 || h == 0) {
00341 _mid->cachesurface = NULL;
00342 return;
00343 }
00344
00345 PG_Rect r(my_xpos, my_ypos, w, h);
00346
00347 _mid->cachesurface = CreateThemedSurface(
00348 r,
00349 my_has_gradient ? &my_gradient : 0,
00350 my_background,
00351 my_backgroundMode,
00352 my_blendLevel);
00353 }
00354
00355 void PG_ThemeWidget::eventBlit(SDL_Surface* srf, const PG_Rect& src, const PG_Rect& dst) {
00356
00357 if(my_srfObject != NULL) {
00358 PG_Widget::eventBlit(srf, src, dst);
00359 return;
00360 }
00361
00362 if(!_mid->simplebackground && !_mid->nocache) {
00363 if(_mid->cachesurface == NULL) {
00364 CreateSurface(Width(), Height());
00365 }
00366 PG_Widget::eventBlit(_mid->cachesurface, src, dst);
00367 } else if (_mid->simplebackground) {
00368 if(GetTransparency() < 255) {
00369 Uint32 c = _mid->backgroundcolor.MapRGBA(
00370 PG_Application::GetScreen()->format,
00371 255-GetTransparency());
00372 SDL_FillRect(PG_Application::GetScreen(), const_cast<PG_Rect*>(&dst), c);
00373 }
00374 } else if (_mid->nocache) {
00375 _mid->cachesurface = CreateThemedSurface(
00376 *this,
00377 my_has_gradient ? &my_gradient : 0,
00378 my_background,
00379 my_backgroundMode,
00380 my_blendLevel);
00381 PG_Widget::eventBlit(_mid->cachesurface, src, dst);
00382 DeleteThemedSurface(_mid->cachesurface);
00383 _mid->cachesurface = NULL;
00384 }
00385
00386 if(my_bordersize > 0) {
00387 DrawBorder(PG_Rect(0, 0, Width(), Height()), my_bordersize, true);
00388 }
00389
00390 if(my_image != NULL) {
00391 PG_Rect my_src;
00392 PG_Rect my_dst;
00393
00394 GetClipRects(my_src, my_dst, *this);
00395 PG_Widget::eventBlit(my_image, my_src, my_dst);
00396 }
00397 }
00398
00399 void PG_ThemeWidget::SetTransparency(Uint8 t, bool bRecursive) {
00400 if(_mid->simplebackground || _mid->nocache) {
00401 PG_Widget::SetTransparency(t, bRecursive);
00402 return;
00403 }
00404
00405 if(t == 255) {
00406 DeleteThemedSurface(_mid->cachesurface);
00407 _mid->cachesurface = NULL;
00408 } else if(GetTransparency() == 255) {
00409 CreateSurface();
00410 }
00411 PG_Widget::SetTransparency(t, bRecursive);
00412 }
00413
00414 SDL_Surface* PG_ThemeWidget::CreateThemedSurface(const PG_Rect& r, PG_Gradient* gradient, SDL_Surface* background, PG_Draw::BkMode bkmode, Uint8 blend) {
00415 SDL_Surface* cache_surface = NULL;
00416 SDL_Surface* screen = PG_Application::GetScreen();
00417 std::string key;
00418
00419 if(r.w == 0 || r.h == 0) {
00420 return NULL;
00421 }
00422
00423
00424 my_SurfaceCache.CreateKey(key, r.my_width, r.my_height, gradient, background, bkmode, blend);
00425
00426
00427 cache_surface = my_SurfaceCache.FindSurface(key);
00428
00429
00430 if(cache_surface != NULL) {
00431
00432 my_SurfaceCache.IncRef(key);
00433 return cache_surface;
00434 }
00435
00436 Uint8 bpp = screen->format->BitsPerPixel;
00437 Uint32 Rmask = screen->format->Rmask;
00438 Uint32 Gmask = screen->format->Gmask;
00439 Uint32 Bmask = screen->format->Bmask;
00440 Uint32 Amask = 0;
00441
00442 if(background != NULL) {
00443 if((background->format->Amask != 0) || ((bpp < background->format->BitsPerPixel) && (bpp <= 8))) {
00444 bpp = background->format->BitsPerPixel;
00445 Rmask = background->format->Rmask;
00446 Gmask = background->format->Gmask;
00447 Bmask = background->format->Bmask;
00448 Amask = background->format->Amask;
00449 }
00450 }
00451
00452 SDL_Surface *surface = SDL_CreateRGBSurface(
00453 SDL_HWSURFACE,
00454 r.my_width,
00455 r.my_height,
00456 bpp,
00457 Rmask,
00458 Gmask,
00459 Bmask,
00460 Amask
00461 );
00462
00463
00464 if(SDL_MUSTLOCK(surface)) {
00465 SDL_LockSurface(surface);
00466 }
00467
00468 if ( bpp == 8 )
00469 SDL_SetPalette ( surface, SDL_LOGPAL, screen->format->palette->colors, 0, 256 );
00470
00471 if(surface) {
00472 if(background || gradient) {
00473 PG_Draw::DrawThemedSurface(surface, PG_Rect(0, 0, r.my_width, r.my_height), gradient, background, bkmode, blend);
00474 } else {
00475 SDL_SetColorKey(surface, SDL_SRCCOLORKEY, 0);
00476 }
00477 }
00478
00479 if(SDL_MUSTLOCK(surface)) {
00480 SDL_UnlockSurface(surface);
00481 }
00482
00483 my_SurfaceCache.AddSurface(key, surface);
00484 return surface;
00485 }
00486
00487 void PG_ThemeWidget::DeleteThemedSurface(SDL_Surface* surface) {
00488 if(surface == NULL) {
00489 return;
00490 }
00491 my_SurfaceCache.DeleteSurface(surface);
00492 }
00493
00494 void PG_ThemeWidget::SetSimpleBackground(bool simple) {
00495 _mid->simplebackground = simple;
00496 DeleteThemedSurface(_mid->cachesurface);
00497 _mid->cachesurface = NULL;
00498 Redraw();
00499 }
00500
00501 void PG_ThemeWidget::SetBackgroundColor(const PG_Color& c) {
00502 _mid->backgroundcolor = c;
00503 }