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 <cmath>
00030
00031 #include "pgscrollbar.h"
00032 #include "pgapplication.h"
00033 #include "pgeventsupplier.h"
00034
00035 #include "propstrings_priv.h"
00036
00037 PG_ScrollBar::PG_ScrollBar(PG_Widget* parent, const PG_Rect& r, ScrollDirection direction, int id, const std::string& style) : PG_ThemeWidget(parent, r, style) {
00038 sb_direction = direction;
00039
00040 SetID(id);
00041
00042 scroll_min = 0;
00043 scroll_max = 4;
00044 scroll_current = 0;
00045
00046 my_linesize = 1;
00047 my_pagesize = 1;
00048
00049 scrollbutton[0] = new PG_Button(this);
00050 scrollbutton[0]->SetID((direction == VERTICAL) ? IDSCROLLBAR_UP : IDSCROLLBAR_LEFT);
00051 scrollbutton[0]->sigClick.connect(slot(*this, &PG_ScrollBar::handleButtonClick));
00052
00053 scrollbutton[1] = new PG_Button(this);
00054 scrollbutton[1]->SetID((direction == VERTICAL) ? IDSCROLLBAR_DOWN : IDSCROLLBAR_RIGHT);
00055 scrollbutton[1]->sigClick.connect(slot(*this, &PG_ScrollBar::handleButtonClick));
00056
00057 dragbutton = new ScrollButton(this);
00058 dragbutton->SetID(IDSCROLLBAR_DRAG);
00059 dragbutton->sigClick.connect(slot(*this, &PG_ScrollBar::handleButtonClick));
00060
00061 if(style != PG_PropStr::Scrollbar) {
00062 LoadThemeStyle(PG_PropStr::Scrollbar);
00063 }
00064 LoadThemeStyle(style);
00065 SetPosition(0);
00066 }
00067
00068 PG_ScrollBar::~PG_ScrollBar() {}
00069
00070 void PG_ScrollBar::LoadThemeStyle(const std::string& widgettype) {
00071
00072 PG_ThemeWidget::LoadThemeStyle(widgettype, PG_PropStr::Scrollbar);
00073
00074 if(sb_direction == VERTICAL) {
00075 scrollbutton[0]->LoadThemeStyle(widgettype, PG_PropStr::ScrollbarUp);
00076 scrollbutton[1]->LoadThemeStyle(widgettype, PG_PropStr::ScrollbarDown);
00077 } else {
00078 scrollbutton[0]->LoadThemeStyle(widgettype, PG_PropStr::ScrollbarLeft);
00079 scrollbutton[1]->LoadThemeStyle(widgettype, PG_PropStr::ScrollbarRight);
00080 }
00081
00082 dragbutton->LoadThemeStyle(widgettype, PG_PropStr::ScrollbarDrag);
00083
00084 if(sb_direction == VERTICAL) {
00085 dragbutton->LoadThemeStyle(widgettype, PG_PropStr::ScrollbarDragV);
00086 PG_ThemeWidget::LoadThemeStyle(widgettype, PG_PropStr::ScrollbarV);
00087 } else {
00088 dragbutton->LoadThemeStyle(widgettype, PG_PropStr::ScrollbarDragH);
00089 PG_ThemeWidget::LoadThemeStyle(widgettype, PG_PropStr::ScrollbarH);
00090 }
00091 RecalcPositions();
00092 }
00093
00094 void PG_ScrollBar::RecalcPositions() {
00095
00096 if(sb_direction == VERTICAL) {
00097 position[0].x = 0;
00098 position[0].y = 0;
00099 position[0].w = w;
00100 position[0].h = w;
00101
00102 position[1].x = 0;
00103 position[1].y = abs(h-w);
00104 position[1].w = w;
00105 position[1].h = w;
00106
00107 position[2].x = 0;
00108 position[2].y = w;
00109 position[2].w = w;
00110 position[2].h = abs(h-(w*2));
00111
00112 position[3].x = 0;
00113 position[3].w = w;
00114 position[3].h = position[2].h / 2;
00115
00116 if ( my_pagesize <= 0 || scroll_max - scroll_min <= 0 )
00117 position[3].h = position[2].h;
00118 else {
00119 position[3].h = (position[2].h * my_pagesize ) / (scroll_max - scroll_min + my_pagesize );
00120 if ( position[3].h < position[3].w * 3 / 2)
00121 position[3].h = position[3].w * 3 / 2 ;
00122 }
00123 } else {
00124 position[0].x = 0;
00125 position[0].y = 0;
00126 position[0].w = h;
00127 position[0].h = h;
00128
00129 position[1].x = abs(w - h);
00130 position[1].y = 0;
00131 position[1].w = h;
00132 position[1].h = h;
00133
00134 position[2].x = h;
00135 position[2].y = 0;
00136 position[2].w = abs(w-(h*2));
00137 position[2].h = h;
00138
00139 position[3].y = 0;
00140 position[3].w = (Uint16)((double)position[2].w / 2.0);
00141 position[3].h = h;
00142
00143 if ( my_pagesize <= 0 || scroll_max - scroll_min <= 0 )
00144 position[3].w = position[2].w;
00145 else {
00146 position[3].w = (position[2].w * my_pagesize ) / (scroll_max - scroll_min + my_pagesize );
00147 if ( position[3].w < position[3].h * 3 / 2)
00148 position[3].w = position[3].h * 3 / 2;
00149 }
00150 }
00151
00152 int pos = scroll_current - scroll_min;
00153
00154 if(sb_direction == VERTICAL) {
00155 position[3].x = 0;
00156 if ( (scroll_max - scroll_min) * pos <= 0 )
00157 position[3].y = position[0].h;
00158 else
00159 position[3].y = (Uint16)(position[0].h + (((double)position[2].h - (double)position[3].h) / (double)(scroll_max - scroll_min)) * (double)pos);
00160 } else {
00161 position[3].y = 0;
00162 if ( (scroll_max - scroll_min) * pos <= 0 )
00163 position[3].x = position[0].w;
00164 else
00165 position[3].x = (Uint16)(position[0].w + (((double)position[2].w - (double)position[3].w) / (double)(scroll_max - scroll_min)) * (double)pos);
00166 }
00167
00168
00169 for(int i=0; i<4; i++) {
00170 if(i == 3 || i == 2) {
00171 if(sb_direction == VERTICAL) {
00172 position[i].x += my_bordersize;
00173 if(position[i].w > 2*my_bordersize) {
00174 position[i].w -= 2*my_bordersize;
00175 }
00176 } else {
00177 position[i].y += my_bordersize;
00178 if(position[i].h > 2*my_bordersize) {
00179 position[i].h -= 2*my_bordersize;
00180 }
00181 }
00182 continue;
00183 }
00184 position[i].x += my_bordersize;
00185 position[i].y += my_bordersize;
00186 if(position[i].w > 2*my_bordersize) {
00187 position[i].w -= 2*my_bordersize;
00188 }
00189 if(position[i].h > 2*my_bordersize) {
00190 position[i].h -= 2*my_bordersize;
00191 }
00192 }
00193 if(scrollbutton[0] != NULL) {
00194 scrollbutton[0]->MoveWidget(position[0]);
00195 }
00196 if(scrollbutton[1] != NULL) {
00197 scrollbutton[1]->MoveWidget(position[1]);
00198 }
00199 dragbutton->MoveWidget(position[3]);
00200 }
00201
00202 void PG_ScrollBar::eventSizeWidget(Uint16 w, Uint16 h) {
00203
00204 PG_ThemeWidget::eventSizeWidget(w, h);
00205
00206 my_height = h;
00207 my_width = w;
00208
00209 RecalcPositions();
00210 SetPosition(scroll_current);
00211 return;
00212 }
00213
00215 bool PG_ScrollBar::eventMouseMotion(const SDL_MouseMotionEvent* motion) {
00216 return PG_ThemeWidget::eventMouseMotion(motion);
00217 }
00218
00220 bool PG_ScrollBar::eventMouseButtonUp(const SDL_MouseButtonEvent* button) {
00221 int x;
00222 int y;
00223 int mx = dragbutton->my_xpos + dragbutton->my_width / 2;
00224 int my = dragbutton->my_ypos + dragbutton->my_height / 2;
00225
00226 PG_Application::GetEventSupplier()->GetMouseState(x,y);
00227
00228 switch (button->button) {
00229 case 1:
00230 if(sb_direction == VERTICAL) {
00231 if(y < my) {
00232 SetPosition(scroll_current - my_pagesize);
00233 } else {
00234 SetPosition(scroll_current + my_pagesize);
00235 }
00236 } else {
00237 if(x < mx) {
00238 SetPosition(scroll_current - my_pagesize);
00239 } else {
00240 SetPosition(scroll_current + my_pagesize);
00241 }
00242 }
00243
00244 sigScrollPos(this, scroll_current);
00245 return true;
00246
00247 case 4:
00248 if(scroll_current <= scroll_min + my_linesize) {
00249 SetPosition(scroll_min);
00250 } else {
00251 SetPosition(scroll_current - my_linesize);
00252 }
00253 sigScrollPos(this, scroll_current);
00254 return true;
00255
00256 case 5:
00257 SetPosition(scroll_current + my_linesize);
00258 sigScrollPos(this, scroll_current);
00259 return true;
00260 }
00261
00262 return PG_ThemeWidget::eventMouseButtonUp(button);
00263 }
00264
00265
00266 PG_ScrollBar::ScrollButton::ScrollButton(PG_ScrollBar* parent, const PG_Rect& r) : PG_Button(parent, r) {
00267 SetID(IDSCROLLBAR_DRAG);
00268 my_tickMode = false;
00269 }
00270
00271 PG_ScrollBar::ScrollButton::~ScrollButton() {}
00272
00274 bool PG_ScrollBar::ScrollButton::eventMouseMotion(const SDL_MouseMotionEvent* motion) {
00275 PG_Point p;
00276
00277 if(GetPressed()) {
00278
00279 p = GetParent()->ScreenToClient(motion->x, motion->y);
00280
00281 if(GetParent()->sb_direction == VERTICAL) {
00282 p.y -= offset.y;
00283
00284 if(p.y < GetParent()->position[2].y) {
00285 p.y = GetParent()->position[2].y;
00286 }
00287
00288 int maxy;
00289 if(!my_tickMode) {
00290 maxy = GetParent()->position[2].y + (GetParent()->position[2].h) - my_height;
00291 } else {
00292 maxy = GetParent()->my_height - my_height;
00293 }
00294
00295 if(p.y > maxy) {
00296 p.y = maxy;
00297 }
00298
00299 MoveWidget(GetParent()->position[2].x, p.y);
00300 } else {
00301 p.x -= offset.x;
00302
00303 if(p.x < GetParent()->position[2].x) {
00304 p.x = GetParent()->position[2].x;
00305 }
00306
00307 int maxx;
00308 if(!my_tickMode) {
00309 maxx = GetParent()->position[2].x + (GetParent()->position[2].w) - (my_width);
00310 } else {
00311 maxx = GetParent()->my_width - my_width;
00312 }
00313
00314 if(p.x > maxx) {
00315 p.x = maxx;
00316 }
00317
00318 MoveWidget(p.x, GetParent()->position[2].y);
00319 }
00320
00321 int pos = GetPosFromPoint(p);
00322 if(GetParent()->scroll_current != pos || my_tickMode) {
00323 GetParent()->scroll_current = pos;
00324 GetParent()->sigScrollTrack(GetParent(), pos);
00325 }
00326
00327 }
00328
00329 return true;
00330 }
00331
00333 bool PG_ScrollBar::ScrollButton::eventMouseButtonDown(const SDL_MouseButtonEvent* button) {
00334 int x,y;
00335
00336 if(button->button == 1) {
00337 PG_Application::GetEventSupplier()->GetMouseState(x,y);
00338 offset = ScreenToClient(x, y);
00339 }
00340
00341 return PG_Button::eventMouseButtonDown(button);
00342 }
00343
00345 PG_ScrollBar* PG_ScrollBar::ScrollButton::GetParent() {
00346 return (PG_ScrollBar*)PG_Button::GetParent();
00347 }
00348
00350 void PG_ScrollBar::SetPosition(int pos) {
00351
00352 if(pos < scroll_min) {
00353 pos = scroll_min;
00354 }
00355
00356 if(pos > scroll_max) {
00357 pos = scroll_max;
00358 }
00359
00360 scroll_current = pos;
00361 pos -= scroll_min;
00362
00363
00364 if(dragbutton->GetPressed()) {
00365 return;
00366 }
00367
00368 RecalcPositions();
00369 }
00370
00371 int PG_ScrollBar::GetPosition() {
00372 return scroll_current;
00373 }
00374
00376 bool PG_ScrollBar::handleButtonClick(PG_Button* button) {
00377
00378 if(button == scrollbutton[0]) {
00379 if(scroll_current == scroll_min) {
00380 return false;
00381 }
00382 SetPosition(scroll_current - my_linesize);
00383 sigScrollPos(this, scroll_current);
00384 return true;
00385 }
00386
00387 if(button == scrollbutton[1]) {
00388 if(scroll_current == scroll_max) {
00389 return false;
00390 }
00391 SetPosition(scroll_current + my_linesize);
00392 sigScrollPos(this, scroll_current);
00393 return true;
00394
00395 }
00396
00397 return false;
00398 }
00399
00401 bool PG_ScrollBar::eventMouseButtonDown(const SDL_MouseButtonEvent* button) {
00402 return false;
00403 }
00404
00406 bool PG_ScrollBar::ScrollButton::eventMouseButtonUp(const SDL_MouseButtonEvent* button) {
00407 int pos = GetParent()->scroll_current;
00408
00409 if(button->button != 1) {
00410 return false;
00411 }
00412
00413 PG_Button::eventMouseButtonUp(button);
00414
00415
00416 GetParent()->sigScrollPos(GetParent(), pos);
00417
00418 return true;
00419 }
00420
00421 void PG_ScrollBar::ScrollButton::SetTickMode(bool on) {
00422 my_tickMode = on;
00423 }
00424
00426 void PG_ScrollBar::SetRange(Uint32 min, Uint32 max) {
00427 scroll_min = min;
00428 scroll_max = max;
00429
00430
00431 SetPosition( scroll_current );
00432 }
00433
00434 int PG_ScrollBar::GetMinRange() {
00435 return scroll_min;
00436 }
00437
00439 int PG_ScrollBar::GetMaxRange() {
00440 return scroll_max;
00441 }
00442
00443 int intround( double f)
00444 {
00445 return (int)(std::floor(f + 0.5));
00446 }
00447
00448
00450 int PG_ScrollBar::ScrollButton::GetPosFromPoint(PG_Point p) {
00451 Uint32 range = (GetParent()->scroll_max - GetParent()->scroll_min);
00452 int pos = 0;
00453
00454 if(p.x < 0)
00455 p.x = 0;
00456 if(p.y < 0)
00457 p.y = 0;
00458
00459
00460 if(GetParent()->sb_direction == VERTICAL) {
00461 pos = intround((double)(p.y - GetParent()->position[2].y) / (((double)GetParent()->position[2].h - (double)GetParent()->position[3].h) / (double)range));
00462 } else {
00463 pos = intround((double)(p.x - GetParent()->position[2].x) / (((double)GetParent()->position[2].w - (double)GetParent()->position[3].w) / (double)range));
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 if(pos < 0)
00474 pos = 0;
00475
00476 pos = GetParent()->scroll_min+pos;
00477
00478 if(pos > GetParent()->scroll_max) {
00479 pos = GetParent()->scroll_max;
00480 }
00481
00482 if(pos < GetParent()->scroll_min) {
00483 pos = GetParent()->scroll_min;
00484 }
00485
00486 return pos;
00487 }
00488
00489 void PG_ScrollBar::SetLineSize(int ls) {
00490 my_linesize = ls;
00491 }
00492
00493 int PG_ScrollBar::GetLineSize()
00494 {
00495 return my_linesize;
00496 }
00497
00498
00499 void PG_ScrollBar::SetPageSize(int ps) {
00500 my_pagesize = ps;
00501 RecalcPositions();
00502 }