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 <cstring>
00030 #include <stdarg.h>
00031
00032 #include "pgwidget.h"
00033 #include "pgapplication.h"
00034 #include "pglog.h"
00035 #include "pgdraw.h"
00036 #include "pglayout.h"
00037 #include "pgtheme.h"
00038 #include "pgeventsupplier.h"
00039
00040 #include "propstrings_priv.h"
00041
00042 #define TXT_HEIGHT_UNDEF 0xFFFF
00043
00044
00045
00046 PG_RectList PG_Widget::widgetList;
00047 int PG_Widget::my_ObjectCounter = 0;
00048
00049 class PG_WidgetDataInternal {
00050 public:
00051 PG_WidgetDataInternal() : modalstatus(0), inDestruct(false), inMouseLeave(false), font(NULL), dirtyUpdate(false), id(-1),
00052 transparency(0), quitModalLoop(false), visible(false), hidden(false), firstredraw(true),
00053 childList(NULL), haveTooltip(false), fadeSteps(10), mouseInside(false), userdata(NULL),
00054 userdatasize(0), widthText(TXT_HEIGHT_UNDEF), heightText(TXT_HEIGHT_UNDEF), widgetParent(NULL), hotkeyModifier(-1), hotkey(0) {
00055 updateOverlappingSiblings = PG_Application::GetUpdateOverlappingSiblings();
00056 };
00057
00058 int modalstatus;
00059 bool inDestruct;
00060 bool inMouseLeave;
00061 PG_Font* font;
00062 bool dirtyUpdate;
00063 int id;
00064 Uint8 transparency;
00065 bool quitModalLoop;
00066 bool visible;
00067 bool hidden;
00068 bool firstredraw;
00069 PG_RectList* childList;
00070 bool haveTooltip;
00071 int fadeSteps;
00072 bool mouseInside;
00073 char* userdata;
00074 int userdatasize;
00075 Uint16 widthText;
00076 Uint16 heightText;
00077
00078 PG_Widget* widgetParent;
00079 PG_Point ptDragStart;
00080 PG_Rect rectClip;
00081 bool havesurface;
00082 std::string name;
00083 bool updateOverlappingSiblings;
00084 int hotkeyModifier;
00085 PG_Char hotkey;
00086
00087 };
00088
00089 PG_Widget::PG_Widget(PG_Widget* parent, const PG_Rect& rect, bool bObjectSurface) :
00090 PG_Rect(rect), my_srfObject(NULL), _mid(new PG_WidgetDataInternal) {
00091
00092 _mid->havesurface = bObjectSurface;
00093
00094
00095 if(PG_Application::DefaultFont != NULL) {
00096 _mid->font = new PG_Font(
00097 PG_Application::DefaultFont->GetName(),
00098 PG_Application::DefaultFont->GetSize());
00099 } else {
00100 PG_LogWRN("Unable to get default font! Did you load a theme ?");
00101 }
00102
00103
00104
00105 if(_mid->havesurface) {
00106 my_srfObject = PG_Draw::CreateRGBSurface(w, h);
00107 }
00108
00109
00110 char buffer[15];
00111 sprintf(buffer, "Object%d", ++my_ObjectCounter);
00112 _mid->name = buffer;
00113
00114
00115 my_colorBorder[0][0].r = 255;
00116 my_colorBorder[0][0].g = 255;
00117 my_colorBorder[0][0].b = 255;
00118
00119 my_colorBorder[0][1].r = 239;
00120 my_colorBorder[0][1].g = 239;
00121 my_colorBorder[0][1].b = 239;
00122
00123 my_colorBorder[1][0].r = 89;
00124 my_colorBorder[1][0].g = 89;
00125 my_colorBorder[1][0].b = 89;
00126
00127 my_colorBorder[1][1].r = 134;
00128 my_colorBorder[1][1].g = 134;
00129 my_colorBorder[1][1].b = 134;
00130
00131 if (parent) {
00132
00133
00134 parent->AddChild(this);
00135 } else {
00136 AddToWidgetList();
00137 }
00138
00139 }
00140
00141 void PG_Widget::RemoveAllChilds() {
00142
00143
00144 if(_mid->childList != NULL) {
00145
00146 PG_Widget* i = _mid->childList->first();
00147 while(i != NULL) {
00148 PG_Widget* w = i;
00149 i = i->next();
00150
00151 RemoveChild(w);
00152 delete w;
00153 }
00154 _mid->childList->clear();
00155 }
00156
00157 }
00158
00159 PG_Widget::~PG_Widget() {
00160
00161 _mid->inDestruct = true;
00162
00163 if(!_mid->havesurface && my_srfObject) {
00164 PG_LogWRN("DrawObject declared without a surface has unexpectedly born one ?");
00165 }
00166 PG_Application::UnloadSurface(my_srfObject);
00167 my_srfObject = NULL;
00168
00169 Hide();
00170
00171 RemoveAllChilds();
00172
00173
00174
00175 if (GetParent() != NULL) {
00176 GetParent()->RemoveChild(this);
00177 } else {
00178 RemoveFromWidgetList();
00179 }
00180
00181
00182 delete _mid->childList;
00183 _mid->childList = NULL;
00184
00185 if (_mid->userdata != NULL) {
00186 delete[] _mid->userdata;
00187 }
00188
00189
00190 delete _mid->font;
00191
00192
00193 delete _mid;
00194
00195
00196 }
00197
00198 void PG_Widget::RemoveFromWidgetList() {
00199 widgetList.Remove(this);
00200 }
00201
00202 void PG_Widget::AddToWidgetList() {
00203 if(!GetParent()) {
00204 widgetList.Add(this);
00205 }
00206 }
00207
00210 bool PG_Widget::AcceptEvent(const SDL_Event * event) {
00211
00212 if (!IsVisible() || IsHidden()) {
00213 return false;
00214 }
00215
00216 switch (event->type) {
00217 case SDL_MOUSEMOTION:
00218 if ((event->motion.x < _mid->rectClip.my_xpos) ||
00219 (event->motion.x > (_mid->rectClip.my_xpos + _mid->rectClip.my_width - 1))) {
00220 if (_mid->mouseInside) {
00221 eventMouseLeave();
00222 }
00223 return false;
00224 }
00225 if ((event->motion.y < _mid->rectClip.my_ypos) ||
00226 (event->motion.y > (_mid->rectClip.my_ypos + _mid->rectClip.my_height - 1))) {
00227 if (_mid->mouseInside) {
00228 eventMouseLeave();
00229 }
00230 return false;
00231 }
00232 if (!_mid->mouseInside) {
00233 _mid->mouseInside = true;
00234 eventMouseEnter();
00235 return true;
00236 }
00237 break;
00238
00239 case SDL_MOUSEBUTTONUP:
00240 case SDL_MOUSEBUTTONDOWN:
00241 if ((event->button.x < _mid->rectClip.my_xpos) ||
00242 (event->button.x > (_mid->rectClip.my_xpos + _mid->rectClip.my_width - 1)))
00243 return false;
00244
00245 if ((event->button.y < _mid->rectClip.my_ypos) ||
00246 (event->button.y > (_mid->rectClip.my_ypos + _mid->rectClip.my_height - 1)))
00247 return false;
00248
00249 break;
00250 }
00251
00252 return true;
00253 }
00254
00255
00257 void PG_Widget::eventMouseEnter() {
00258 sigMouseEnter();
00259 }
00260
00261
00263 void PG_Widget::eventMouseLeave() {
00264 _mid->mouseInside = false;
00265
00266 if(GetParent() != NULL && !GetParent()->IsMouseInside()) {
00267 GetParent()->eventMouseLeave();
00268 }
00269
00270 sigMouseLeave();
00271
00272
00273
00274 }
00275
00277 void PG_Widget::eventShow() {}
00278
00280 void PG_Widget::eventHide() {}
00281
00283 PG_Point PG_Widget::ClientToScreen(int sx, int sy) {
00284 return PG_Point(sx + my_xpos, sy + my_ypos);
00285 }
00286
00287 PG_Point PG_Widget::ScreenToClient(int x, int y) {
00288 return PG_Point(x - my_xpos, y - my_ypos);
00289 }
00290
00291 void PG_Widget::AddChild(PG_Widget * child) {
00292
00293 if (!child)
00294 return;
00295
00296
00297 if(child->GetParent()) {
00298 child->GetParent()->RemoveChild(child);
00299 } else {
00300 child->RemoveFromWidgetList();
00301 }
00302
00303 child->MoveRect(child->my_xpos + my_xpos, child->my_ypos + my_ypos);
00304 child->_mid->widgetParent = this;
00305
00306 if (_mid->childList == NULL) {
00307 _mid->childList = new PG_RectList;
00308 }
00309
00310 _mid->childList->Add(child);
00311 }
00312
00313 bool PG_Widget::MoveWidget(int x, int y, bool update) {
00314 SDL_Surface* screen = PG_Application::GetScreen();
00315
00316 if (GetParent() != NULL) {
00317 x += GetParent()->my_xpos;
00318 y += GetParent()->my_ypos;
00319 }
00320 if(x == my_xpos && y == my_ypos) {
00321
00322 return false;
00323 }
00324
00325 if(!IsVisible() || IsHidden() || !update) {
00326 MoveRect(x, y);
00327 return true;
00328 }
00329
00330
00331 int dx = x - my_xpos;
00332 int dy = y - my_ypos;
00333
00334
00335
00336 PG_Rect vertical(0, 0, abs(dx), my_height + abs(dy));
00337
00338 if(dx >= 0) {
00339 vertical.my_xpos = my_xpos;
00340 } else {
00341 vertical.my_xpos = my_xpos + my_width + dx;
00342 }
00343
00344 vertical.my_ypos = my_ypos;
00345
00346
00347
00348 PG_Rect horizontal(0, 0, my_width + abs(dx), abs(dy));
00349
00350 horizontal.my_xpos = my_xpos;
00351
00352 if(dy >= 0) {
00353 horizontal.my_ypos = my_ypos;
00354 } else {
00355 horizontal.my_ypos = my_ypos + my_height + dy;
00356 }
00357
00358
00359 MoveRect(x, y);
00360
00361 if(vertical.my_xpos + vertical.my_width > screen->w) {
00362 vertical.my_width = screen->w - vertical.my_xpos;
00363 }
00364 if(vertical.my_ypos + vertical.my_height > screen->h) {
00365 vertical.my_height = screen->h - vertical.my_ypos;
00366 }
00367
00368 if(horizontal.my_xpos + horizontal.my_width > screen->w) {
00369 horizontal.my_width = screen->w- horizontal.my_xpos;
00370 }
00371 if(horizontal.my_ypos + horizontal.my_height > screen->h) {
00372 horizontal.my_height = screen->h - horizontal.my_ypos;
00373 }
00374
00375 if(!PG_Application::GetBulkMode()) {
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 int minx, maxx;
00389 int miny, maxy;
00390 minx = PG_MIN(vertical.x, horizontal.x);
00391 minx = PG_MIN(minx, _mid->rectClip.x);
00392 maxx = PG_MAX(vertical.x+vertical.w, horizontal.x+horizontal.w);
00393 maxx = PG_MAX(maxx, _mid->rectClip.x+_mid->rectClip.w);
00394
00395 miny = PG_MIN(vertical.y, horizontal.y);
00396 miny = PG_MIN(miny, _mid->rectClip.y);
00397 maxy = PG_MAX(vertical.y+vertical.h, horizontal.y+horizontal.h);
00398 maxy = PG_MAX(maxy, _mid->rectClip.y+_mid->rectClip.h);
00399
00400 PG_Application::ScreenLocker locker(true);
00401 PG_Rect rect(minx,miny,maxx-minx,maxy-miny);
00402 UpdateRect(rect);
00403 PG_Application::UpdateRects(screen, 1, &rect);
00404 }
00405
00406 return true;
00407 }
00408
00409 bool PG_Widget::MoveWidget(const PG_Rect& r, bool update) {
00410 SizeWidget(r.w, r.h, update);
00411 MoveWidget(r.x, r.y, update);
00412
00413 return true;
00414 }
00415
00416 bool PG_Widget::SizeWidget(Uint16 w, Uint16 h, bool update) {
00417 Uint16 old_w = my_width;
00418 Uint16 old_h = my_height;
00419
00420 if(my_width == w && my_height == h) {
00421 return false;
00422 }
00423
00424
00425 if(my_srfObject) {
00426 PG_Application::UnloadSurface(my_srfObject);
00427
00428 if(w > 0 && h > 0) {
00429 my_srfObject = PG_Draw::CreateRGBSurface(w, h);
00430 } else {
00431 my_srfObject = NULL;
00432 }
00433 }
00434
00435 eventSizeWidget(w, h);
00436
00437 my_width = w;
00438 my_height = h;
00439
00440 if(!IsVisible() || IsHidden() || !update) {
00441 return true;
00442 }
00443
00444 if(my_srfObject) {
00445 Redraw();
00446 } else {
00447 if(old_w > w || old_h > h) {
00448 PG_Rect u(
00449 my_xpos,
00450 my_ypos,
00451 (old_w > w) ? old_w : w,
00452 (old_h > h) ? old_h : h);
00453
00454
00455
00456
00457
00458 if (my_xpos + old_w >= PG_Application::GetScreenWidth())
00459 u.my_width = PG_Application::GetScreenWidth() - my_xpos;
00460
00461 if (my_ypos + old_h >= PG_Application::GetScreenHeight())
00462 u.my_height = PG_Application::GetScreenHeight() - my_ypos;
00463
00464 UpdateRect(u);
00465 PG_Application::UpdateRects(PG_Application::GetScreen(), 1, &u);
00466 } else {
00467 Update();
00468 }
00469 }
00470
00471 return true;
00472 }
00473
00475 bool PG_Widget::ProcessEvent(const SDL_Event * event, bool bModal) {
00476
00477 bool processed = false;
00478
00479 if(bModal) {
00480
00481
00482 if(_mid->childList != NULL) {
00483 PG_Widget* list = _mid->childList->first();
00484
00485 while (!processed && (list != NULL)) {
00486 processed = list->ProcessEvent(event, true);
00487 list = list->next();
00488 }
00489 }
00490
00491 if(processed) {
00492 return processed;
00493 }
00494 }
00495
00496
00497
00498 if(PG_MessageObject::ProcessEvent(event)) {
00499 return true;
00500 }
00501
00502 if(bModal) {
00503 return processed;
00504 }
00505
00506
00507
00508 if(GetParent()) {
00509 if(GetParent()->ProcessEvent(event)) {
00510 return true;
00511 }
00512 }
00513
00514 return false;
00515 }
00516
00517 bool PG_Widget::RemoveChild(PG_Widget * child) {
00518 if(_mid->childList == NULL || child == NULL) {
00519 return false;
00520 }
00521
00522 if(_mid->childList->Remove(child)) {
00523 child->MoveRect(child->my_xpos - my_xpos, child->my_ypos - my_ypos);
00524 return true;
00525 }
00526
00527 return false;
00528 }
00529
00530 bool PG_Widget::IsMouseInside() {
00531 int x, y;
00532 PG_Application::GetEventSupplier()->GetMouseState(x, y);
00533 PG_Point p(x, y);
00534 _mid->mouseInside = IsInside(p);
00535
00536 return _mid->mouseInside;
00537 }
00538
00540 bool PG_Widget::Redraw(bool update) {
00541 PG_Rect r(0, 0, my_width, my_height);
00542
00543 if(my_srfObject != NULL) {
00544 eventDraw(my_srfObject, r);
00545 }
00546
00547 if(_mid->childList != NULL) {
00548 for(PG_Widget* i = _mid->childList->first(); i != NULL; i = i->next()) {
00549 i->Redraw(false);
00550 }
00551 }
00552
00553 if (update) {
00554 Update();
00555 }
00556 return true;
00557 }
00558
00559 void PG_Widget::SetVisible(bool visible) {
00560
00561 if(IsHidden()) {
00562 return;
00563 }
00564
00565
00566 if(visible) {
00567 if(_mid->visible) {
00568 return;
00569 } else {
00570 _mid->visible = visible;
00571 if(_mid->firstredraw) {
00572 Redraw(false);
00573 _mid->firstredraw = false;
00574 }
00575 }
00576
00577 }
00578
00579
00580 if(!visible) {
00581 if(!_mid->visible) {
00582 return;
00583 } else {
00584
00585 _mid->visible = visible;
00586 }
00587 }
00588
00589 if(_mid->childList != NULL) {
00590 for(PG_Widget* i = _mid->childList->first(); i != NULL; i = i->next()) {
00591 i->SetVisible(visible);
00592 if(!i->IsHidden()) {
00593 if(visible) {
00594 i->eventShow();
00595 } else {
00596 i->eventHide();
00597 }
00598 }
00599 }
00600 }
00601 }
00602
00604 void PG_Widget::Show(bool fade) {
00605
00606 if(fade && IsVisible() && !IsHidden()) {
00607 fade = false;
00608 }
00609
00610 PG_Widget* parent = GetParent();
00611 if(parent == NULL) {
00612 widgetList.BringToFront(this);
00613 } else {
00614 parent->GetChildList()->BringToFront(this);
00615 }
00616
00617 SetHidden(false);
00618
00619 if(parent != NULL && (!parent->IsVisible() || parent->IsHidden())) {
00620 return;
00621 }
00622
00623 SetVisible(true);
00624 eventShow();
00625
00626 if (fade) {
00627 FadeIn();
00628 }
00629
00630 if(IsMouseInside()) {
00631 eventMouseEnter();
00632 }
00633
00634
00635 Update();
00636
00637 return;
00638 }
00639
00641 void PG_Widget::Hide(bool fade) {
00642 SDL_Surface* screen = PG_Application::GetScreen();
00643
00644 if(!IsVisible()) {
00645 SetHidden(true);
00646 eventHide();
00647 return;
00648 }
00649
00650 RecalcClipRect();
00651
00652 if(!_mid->inDestruct && !_mid->inMouseLeave) {
00653 _mid->inMouseLeave = true;
00654 eventMouseLeave();
00655 _mid->inMouseLeave = false;
00656 }
00657
00658 if (fade) {
00659 FadeOut();
00660 }
00661
00662 SetVisible(false);
00663 eventHide();
00664
00665 ReleaseCapture();
00666 ReleaseInputFocus();
00667
00668 SDL_SetClipRect(screen, NULL);
00669
00670 if(!PG_Application::GetBulkMode()) {
00671 UpdateRect(_mid->rectClip);
00672
00673 PG_Application::ScreenLocker locker(true);
00674 PG_Application::UpdateRects(screen, 1, &_mid->rectClip);
00675 }
00676
00677 SetHidden(true);
00678
00679 return;
00680 }
00681
00683 void PG_Widget::MoveRect(int x, int y) {
00684 int dx = x - my_xpos;
00685 int dy = y - my_ypos;
00686
00687 my_xpos = x;
00688 my_ypos = y;
00689 _mid->rectClip.my_xpos += dx;
00690 _mid->rectClip.my_ypos += dy;
00691
00692
00693 RecalcClipRect();
00694
00695 if(_mid->childList != NULL) {
00696 for(PG_Widget* i = _mid->childList->first(); i != NULL; i = i->next()) {
00697 i->MoveRect(i->my_xpos + dx, i->my_ypos + dy);
00698 }
00699 }
00700
00701 eventMoveWidget(x, y);
00702 }
00703
00704 void PG_Widget::Blit(bool recursive, bool restore) {
00705
00706 if(!_mid->visible || _mid->hidden) {
00707 return;
00708 }
00709
00710
00711 RecalcClipRect();
00712
00713
00714 if(_mid->rectClip.w == 0 || _mid->rectClip.h == 0) {
00715 return;
00716 }
00717
00718 PG_Rect src;
00719 PG_Rect dst;
00720 PG_Application::ScreenLocker locker(true);
00721
00722
00723 if(restore) {
00724 RestoreBackground(&_mid->rectClip);
00725 }
00726
00727
00728 src.SetRect(_mid->rectClip.x - my_xpos, _mid->rectClip.y - my_ypos, _mid->rectClip.w, _mid->rectClip.h);
00729 dst = _mid->rectClip;
00730
00731
00732 eventBlit(my_srfObject, src, dst);
00733
00734
00735 if(recursive) {
00736
00737 if(_mid->childList != NULL) {
00738 _mid->childList->Blit(_mid->rectClip);
00739 }
00740 }
00741 }
00742
00744 void PG_Widget::Update(bool doBlit) {
00745 static PG_Rect src;
00746 static PG_Rect dst;
00747
00748 if(PG_Application::GetBulkMode()) {
00749 return;
00750 }
00751
00752 if(!_mid->visible || _mid->hidden) {
00753 return;
00754 }
00755
00756
00757 RecalcClipRect();
00758
00759 if(_mid->rectClip.w == 0 || _mid->rectClip.h == 0) {
00760 return;
00761 }
00762
00763 PG_Application::ScreenLocker locker(true);
00764
00765
00766 if(doBlit) {
00767
00768 SDL_SetClipRect(PG_Application::GetScreen(), &_mid->rectClip);
00769 RestoreBackground(&_mid->rectClip);
00770
00771 src.SetRect(_mid->rectClip.x - my_xpos, _mid->rectClip.y - my_ypos, _mid->rectClip.w, _mid->rectClip.h);
00772 dst = _mid->rectClip;
00773
00774 if(GetParent() != NULL && _mid->updateOverlappingSiblings )
00775 if( !_mid->dirtyUpdate || (_mid->transparency > 0) ) {
00776 PG_RectList* children = GetParent()->GetChildList();
00777 if(children) {
00778 children->Blit(_mid->rectClip, GetParent()->GetChildList()->first(), this);
00779 }
00780 }
00781
00782 eventBlit(my_srfObject, src, dst);
00783
00784 if(_mid->childList != NULL) {
00785 _mid->childList->Blit(_mid->rectClip);
00786 }
00787
00788 if(GetParent() != NULL && _mid->updateOverlappingSiblings ) {
00789 PG_RectList* children = GetParent()->GetChildList();
00790 if(children) {
00791 children->Blit(_mid->rectClip, this->next() );
00792 }
00793 }
00794
00795
00796 PG_Widget* obj = GetToplevelWidget();
00797 widgetList.Blit(_mid->rectClip, obj->next());
00798
00799 }
00800
00801
00802 #ifdef DEBUG
00803 PG_LogDBG("UPD: x:%d y:%d w:%d h:%d",dst.x,dst.y,dst.w,dst.h);
00804 #endif // DEBUG
00805
00806 PG_Application::UpdateRects(PG_Application::GetScreen(), 1, &_mid->rectClip);
00807
00808 SDL_SetClipRect(PG_Application::GetScreen(), NULL);
00809 }
00810
00812 void PG_Widget::SetChildTransparency(Uint8 t) {
00813 if(_mid->childList == NULL) {
00814 return;
00815 }
00816
00817 for(PG_Widget* i = _mid->childList->first(); i != NULL; i = i->next()) {
00818 i->SetTransparency(t, true);
00819 }
00820 Update();
00821 }
00822
00823 void PG_Widget::StartWidgetDrag() {
00824 int x, y;
00825
00826 PG_Application::GetEventSupplier()->GetMouseState(x, y);
00827 _mid->ptDragStart.x = static_cast<Sint16>(x) - my_xpos;
00828 _mid->ptDragStart.y = static_cast<Sint16>(y) - my_ypos;
00829 }
00830
00831 void PG_Widget::WidgetDrag(int x, int y) {
00832
00833 x -= _mid->ptDragStart.x;
00834 y -= _mid->ptDragStart.y;
00835
00836 if(x < 0)
00837 x=0;
00838 if(y < 0)
00839 y=0;
00840 if(x > (PG_Application::GetScreenWidth() - my_width -1))
00841 x = (PG_Application::GetScreenWidth() - my_width -1);
00842 if(y > (PG_Application::GetScreenHeight() - my_height -1))
00843 y = (PG_Application::GetScreenHeight() - my_height -1);
00844
00845 MoveWidget(x,y);
00846 }
00847
00848 void PG_Widget::EndWidgetDrag(int x, int y) {
00849 WidgetDrag(x,y);
00850 _mid->ptDragStart.x = 0;
00851 _mid->ptDragStart.y = 0;
00852 }
00853
00854 void PG_Widget::HideAll() {
00855 for(PG_Widget* i = widgetList.first(); i != NULL; i = i->next()) {
00856 i->Hide();
00857 }
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 void PG_Widget::BulkBlit() {
00873
00874 widgetList.Blit();
00875 PG_Application::DrawCursor();
00876
00877 }
00878
00879 void PG_Widget::LoadThemeStyle(const std::string& widgettype, const std::string& objectname) {
00880 PG_Theme* t = PG_Application::GetTheme();
00881 PG_Color c;
00882
00883 const std::string& font = t->FindFontName(widgettype, objectname);
00884 int fontsize = t->FindFontSize(widgettype, objectname);
00885 PG_Font::Style fontstyle = t->FindFontStyle(widgettype, objectname);
00886
00887 if(!font.empty()) {
00888 SetFontName(font, true);
00889 }
00890
00891 if (fontsize > 0)
00892 SetFontSize(fontsize, true);
00893
00894 if (fontstyle >= 0)
00895 SetFontStyle(fontstyle, true);
00896
00897 c = GetFontColor();
00898 t->GetColor(widgettype, objectname, PG_PropStr::textcolor, c);
00899 SetFontColor(c);
00900
00901 c = GetFontHighlightColor();
00902 t->GetColor(widgettype, objectname, PG_PropStr::texthighlightcolor, c);
00903 SetFontHighlightColor(c);
00904
00905
00906 t->GetColor(widgettype, objectname, PG_PropStr::bordercolor0, my_colorBorder[0][0]);
00907 t->GetColor(widgettype, objectname, PG_PropStr::bordercolor1, my_colorBorder[1][0]);
00908 t->GetColor(widgettype, objectname, PG_PropStr::bordercolor0i, my_colorBorder[0][1]);
00909 t->GetColor(widgettype, objectname, PG_PropStr::bordercolor1i, my_colorBorder[1][1]);
00910 }
00911
00912 void PG_Widget::LoadThemeStyle(const std::string& widgettype) {}
00913
00914 void PG_Widget::FadeOut() {
00915 PG_Rect r(0, 0, my_width, my_height);
00916
00917
00918 Blit();
00919
00920
00921 SDL_Surface* srfFade = PG_Draw::CreateRGBSurface(my_width, my_height);
00922 SDL_Surface* screen = PG_Application::GetScreen();
00923
00924 int d = (255-_mid->transparency)/ _mid->fadeSteps;
00925 if(!d) {
00926 d = 1;
00927 }
00928
00929 PG_Application::ScreenLocker locker(true);
00930
00931
00932 PG_Draw::BlitSurface(screen, *this, srfFade, r);
00933
00934 for(int i=_mid->transparency; i<255; i += d) {
00935 RestoreBackground(NULL, true);
00936 SDL_SetAlpha(srfFade, SDL_SRCALPHA, 255-i);
00937 SDL_BlitSurface(srfFade, NULL, screen, this);
00938 PG_Application::UpdateRects(screen, 1, &_mid->rectClip);
00939 }
00940
00941 RestoreBackground(NULL, true);
00942 SDL_SetAlpha(srfFade, SDL_SRCALPHA, 0);
00943 SDL_BlitSurface(srfFade, NULL, screen, this);
00944 SetVisible(false);
00945 locker.unlock();
00946
00947 Update(false);
00948
00949 PG_Application::UnloadSurface(srfFade);
00950 }
00951
00952 void PG_Widget::FadeIn() {
00953 SDL_Surface* screen = PG_Application::GetScreen();
00954
00955
00956 SDL_SetClipRect(screen, NULL);
00957 Blit();
00958
00959 PG_Rect src(
00960 0,
00961 0,
00962 (my_xpos < 0) ? my_width + my_xpos : my_width,
00963 (my_ypos < 0) ? my_height + my_ypos : my_height);
00964
00965
00966 SDL_Surface* srfFade = PG_Draw::CreateRGBSurface(w, h);
00967
00968 PG_Application::ScreenLocker locker(true);
00969
00970
00971 PG_Draw::BlitSurface(screen, _mid->rectClip, srfFade, src);
00972
00973 int d = (255-_mid->transparency)/ _mid->fadeSteps;
00974
00975 if(!d) {
00976 d = 1;
00977 }
00978 for(int i=255; i>_mid->transparency; i -= d) {
00979 RestoreBackground(NULL, true);
00980 SDL_SetAlpha(srfFade, SDL_SRCALPHA, 255-i);
00981 PG_Draw::BlitSurface(srfFade, src, screen, _mid->rectClip);
00982 PG_Application::UpdateRects(screen, 1, &_mid->rectClip);
00983 }
00984
00985 locker.unlock();
00986
00987 Update();
00988
00989 PG_Application::UnloadSurface(srfFade);
00990 }
00991
00992 void PG_Widget::SetFadeSteps(int steps) {
00993 _mid->fadeSteps = steps;
00994 }
00995
00996 bool PG_Widget::Action(KeyAction action) {
00997 int x = my_xpos + my_width / 2;
00998 int y = my_ypos + my_height / 2;
00999
01000 switch(action) {
01001 case ACT_ACTIVATE:
01002 SDL_WarpMouse(x,y);
01003 eventMouseEnter();
01004 break;
01005
01006 case ACT_DEACTIVATE:
01007 eventMouseLeave();
01008 break;
01009
01010 case ACT_OK:
01011 SDL_MouseButtonEvent button;
01012 button.button = 1;
01013 button.x = x;
01014 button.y = y;
01015 eventMouseButtonDown(&button);
01016 SDL_Delay(200);
01017 eventMouseButtonUp(&button);
01018 Action(ACT_ACTIVATE);
01019 break;
01020
01021 default:
01022 break;
01023 }
01024
01025 return false;
01026 }
01027
01028 bool PG_Widget::RestoreBackground(PG_Rect* clip, bool force) {
01029
01030 if(_mid->dirtyUpdate && (_mid->transparency == 0) && !force) {
01031 return false;
01032 }
01033
01034 if(PG_Application::GetBulkMode()) {
01035 return false;
01036 }
01037
01038 if(clip == NULL) {
01039 clip = &_mid->rectClip;
01040 }
01041
01042 if(GetParent() == NULL) {
01043 PG_Application::RedrawBackground(*clip);
01044
01045 if(widgetList.first() != this) {
01046 SDL_SetClipRect(PG_Application::GetScreen(), clip);
01047 widgetList.Blit(*clip, widgetList.first(), this);
01048 SDL_SetClipRect(PG_Application::GetScreen(), NULL);
01049 }
01050 return true;
01051 }
01052
01053 GetParent()->RestoreBackground(clip);
01054 SDL_SetClipRect(PG_Application::GetScreen(), clip);
01055 GetParent()->Blit(false, false);
01056 SDL_SetClipRect(PG_Application::GetScreen(), NULL);
01057
01058 return true;
01059 }
01060
01061 PG_Widget* PG_Widget::FindWidgetFromPos(int x, int y) {
01062 PG_Point p;
01063 p.x = x;
01064 p.y = y;
01065 bool finished = false;
01066
01067 PG_Widget* toplevel = widgetList.IsInside(p);
01068 PG_Widget* child = NULL;
01069
01070 if(!toplevel) {
01071 return NULL;
01072 }
01073
01074 while(!finished) {
01075
01076 if(toplevel->GetChildList()) {
01077 child = toplevel->GetChildList()->IsInside(p);
01078
01079 if(child) {
01080 toplevel = child;
01081 child = NULL;
01082 } else {
01083 finished = true;
01084 }
01085
01086 } else {
01087 finished = true;
01088 }
01089 }
01090
01091 return toplevel;
01092 }
01093
01094 void PG_Widget::UpdateRect(const PG_Rect& r) {
01095 if(PG_Application::GetBulkMode()) {
01096 return;
01097 }
01098
01099 SDL_Surface* screen = PG_Application::GetScreen();
01100
01101 PG_Application::ScreenLocker locker(true);
01102 PG_Application::RedrawBackground(r);
01103 SDL_SetClipRect(screen, (PG_Rect*)&r);
01104 widgetList.Blit(r);
01105 SDL_SetClipRect(screen, NULL);
01106 }
01107
01108 void PG_Widget::UpdateScreen() {
01109 UpdateRect( PG_Rect(0, 0, PG_Application::GetScreenWidth(), PG_Application::GetScreenHeight()) );
01110 PG_Application::UpdateRect( PG_Application::GetScreen(), 0, 0, 0, 0 );
01111 }
01112
01113 bool PG_Widget::IsInFrontOf(PG_Widget* widget) {
01114 PG_Widget* w1 = NULL;
01115 PG_Widget* w2 = NULL;
01116 PG_RectList* list = &widgetList;
01117
01118
01119 if((GetParent() != NULL) && (GetParent() == widget->GetParent())) {
01120 w1 = this;
01121 w2 = widget;
01122 list = GetParent()->GetChildList();
01123 } else {
01124 w1 = this->GetToplevelWidget();
01125 w2 = widget->GetToplevelWidget();
01126 }
01127
01128 return (w1->index > w2->index);
01129 }
01130
01131 PG_Widget* PG_Widget::GetToplevelWidget() {
01132 if(GetParent() == NULL) {
01133 return this;
01134 }
01135
01136 return GetParent()->GetToplevelWidget();
01137 }
01138
01139 void PG_Widget::SendToBack() {
01140 if(GetParent() == NULL) {
01141 widgetList.SendToBack(this);
01142 } else {
01143 GetParent()->GetChildList()->SendToBack(this);
01144 }
01145 Update();
01146 }
01147
01148 void PG_Widget::BringToFront() {
01149 if(GetParent() == NULL) {
01150 widgetList.BringToFront(this);
01151 } else {
01152 GetParent()->GetChildList()->BringToFront(this);
01153 }
01154 Update();
01155 }
01156
01157 void PG_Widget::RecalcClipRect() {
01158 PG_Rect pr;
01159
01160 if (_mid->widgetParent != NULL) {
01161 pr = *(_mid->widgetParent->GetClipRect());
01162 } else {
01163 pr.SetRect(
01164 0,
01165 0,
01166 PG_Application::GetScreenWidth(),
01167 PG_Application::GetScreenHeight());
01168 }
01169
01170 PG_Rect ir = IntersectRect(pr);
01171 SetClipRect(ir);
01172 }
01173
01174 bool PG_Widget::LoadLayout(const std::string& name) {
01175 bool rc = PG_Layout::Load(this, name, NULL, NULL);
01176 Update();
01177 return rc;
01178 }
01179
01180 bool PG_Widget::LoadLayout(const std::string& name, void (* WorkCallback)(int now, int max)) {
01181 bool rc = PG_Layout::Load(this, name, WorkCallback, NULL);
01182 Update();
01183 return rc;
01184
01185 }
01186
01187 bool PG_Widget::LoadLayout(const std::string& name, void (* WorkCallback)(int now, int max),void *UserSpace) {
01188 bool rc = PG_Layout::Load(this, name, WorkCallback, UserSpace);
01189 Update();
01190 return rc;
01191 }
01192
01193 void PG_Widget::SetUserData(void *userdata, int size) {
01194 _mid->userdata = new char[size];
01195 memcpy(_mid->userdata, userdata, size);
01196 _mid->userdatasize = size;
01197 }
01198
01199 int PG_Widget::GetUserDataSize() {
01200 return _mid->userdatasize;
01201 }
01202
01203 void PG_Widget::GetUserData(void *userdata) {
01204 if (_mid->userdata == NULL)
01205 return;
01206
01207 memcpy(userdata, _mid->userdata, _mid->userdatasize);
01208 }
01209
01210 void PG_Widget::ReleaseUserData() {
01211 if (_mid->userdata != NULL)
01212 delete[] _mid->userdata;
01213 _mid->userdatasize = 0;
01214 }
01215
01216 void PG_Widget::AddText(const std::string& text, bool update) {
01217 my_text += text;
01218 _mid->widthText = TXT_HEIGHT_UNDEF;
01219 _mid->heightText = TXT_HEIGHT_UNDEF;
01220
01221
01222 if (update) {
01223 SetText(GetText());
01224 }
01225 }
01226
01227 void PG_Widget::SetText(const std::string& text) {
01228
01229 _mid->widthText = TXT_HEIGHT_UNDEF;
01230 _mid->heightText = TXT_HEIGHT_UNDEF;
01231
01232 my_text = text;
01233 Update();
01234 }
01235
01236 void PG_Widget::SetTextFormat(const char* text, ...) {
01237 va_list ap;
01238 va_start(ap, text);
01239 char temp[256];
01240
01241 if(text == NULL) {
01242 my_text = "";
01243 return;
01244 }
01245
01246 if(text[0] == 0) {
01247 my_text = "";
01248 return;
01249 }
01250
01251 vsprintf(temp, text, ap);
01252 SetText(temp);
01253 va_end(ap);
01254 }
01255
01256 void PG_Widget::SetFontColor(const PG_Color& Color, bool bRecursive) {
01257 _mid->font->SetColor(Color);
01258
01259 if(!bRecursive || (GetChildList() == NULL)) {
01260 return;
01261 }
01262
01263 for(PG_Widget* i = GetChildList()->first(); i != NULL; i = i->next()) {
01264 i->SetFontColor(Color, true);
01265 }
01266 }
01267
01268 void PG_Widget::SetFontHighlightColor(const PG_Color& Color, bool bRecursive) {
01269 _mid->font->SetHighlightColor(Color);
01270
01271 if(!bRecursive || (GetChildList() == NULL)) {
01272 return;
01273 }
01274
01275 for(PG_Widget* i = GetChildList()->first(); i != NULL; i = i->next()) {
01276 i->SetFontHighlightColor(Color, true);
01277 }
01278 }
01279
01280
01281 void PG_Widget::SetFontAlpha(int Alpha, bool bRecursive) {
01282 _mid->font->SetAlpha(Alpha);
01283
01284 if(!bRecursive || (GetChildList() == NULL)) {
01285 return;
01286 }
01287
01288 for(PG_Widget* i = GetChildList()->first(); i != NULL; i = i->next()) {
01289 i->SetFontAlpha(Alpha, true);
01290 }
01291 }
01292
01293 void PG_Widget::SetFontStyle(PG_Font::Style Style, bool bRecursive) {
01294 _mid->font->SetStyle(Style);
01295
01296 if(!bRecursive || (GetChildList() == NULL)) {
01297 return;
01298 }
01299
01300 for(PG_Widget* i = GetChildList()->first(); i != NULL; i = i->next()) {
01301 i->SetFontStyle(Style, true);
01302 }
01303 }
01304
01305 int PG_Widget::GetFontSize() {
01306 return _mid->font->GetSize();
01307 }
01308
01309 void PG_Widget::SetFontSize(int Size, bool bRecursive) {
01310 _mid->font->SetSize(Size);
01311
01312 if(!bRecursive || (GetChildList() == NULL)) {
01313 return;
01314 }
01315
01316 for(PG_Widget* i = GetChildList()->first(); i != NULL; i = i->next()) {
01317 i->SetFontSize(Size, true);
01318 }
01319
01320 }
01321
01322 void PG_Widget::SetFontIndex(int Index, bool bRecursive) {
01323
01324 }
01325
01326 void PG_Widget::SetFontName(const std::string& Name, bool bRecursive) {
01327 _mid->font->SetName(Name);
01328
01329 if(!bRecursive || (GetChildList() == NULL)) {
01330 return;
01331 }
01332
01333 for(PG_Widget* i = GetChildList()->first(); i != NULL; i = i->next()) {
01334 i->SetFontName(Name, true);
01335 }
01336
01337 }
01338
01339 void PG_Widget::SetSizeByText(int Width, int Height, const std::string& Text) {
01340 Uint16 w,h;
01341 int baselineY;
01342
01343 if (Text.empty()) {
01344 if (!PG_FontEngine::GetTextSize(my_text, _mid->font, &w, &h, &baselineY)) {
01345 return;
01346 }
01347 } else {
01348 PG_String ytext = Text;
01349 if (!PG_FontEngine::GetTextSize(ytext, _mid->font, &w, &h, &baselineY)) {
01350 return;
01351 }
01352 }
01353
01354 if (my_width == 0 && my_height > 0 && Width == 0) {
01355 my_width = w;
01356 my_ypos += (my_height - h - baselineY) >> 1;
01357 my_height = h + baselineY;
01358 } else if (my_height == 0 && my_width > 0 && Height == 0) {
01359 my_xpos += (my_width - w) >> 1;
01360 my_width = w;
01361 my_height = h + baselineY;
01362 } else {
01363 my_width = w + Width;
01364 my_height = h + Height + baselineY;
01365 }
01366
01367 }
01368
01369 void PG_Widget::SetFont(PG_Font* font) {
01370 if(_mid->font != NULL) {
01371 delete _mid->font;
01372 }
01373
01374 _mid->font = new PG_Font(font->GetName(), font->GetSize());
01375 }
01376
01377 void PG_Widget::GetTextSize(Uint16& w, Uint16& h, const std::string& text) {
01378 if(text.empty()) {
01379 if(_mid->widthText != TXT_HEIGHT_UNDEF) {
01380 w = _mid->widthText;
01381 h = _mid->heightText;
01382 return;
01383 }
01384 GetTextSize(w, h, my_text, _mid->font);
01385 _mid->widthText = w;
01386 _mid->heightText = h;
01387 return;
01388 }
01389
01390 GetTextSize(w, h, text, _mid->font);
01391 }
01392
01393 void PG_Widget::GetTextSize(Uint16& w, Uint16& h, const PG_String& text, PG_Font* font) {
01394 PG_Char c = PG_Application::GetHighlightingTag();
01395 if ( !c || text.find( c) == PG_String::npos )
01396 PG_FontEngine::GetTextSize(text, font, &w);
01397 else {
01398 PG_String t = text;
01399 PG_String::size_type pos = t.find( c);
01400 while ( pos != PG_String::npos ) {
01401 t.erase( pos, 1 );
01402 pos = t.find( c);
01403 }
01404 PG_FontEngine::GetTextSize(t, font, &w);
01405 }
01406
0