00001 #ifndef OglGui_ScrollBar_h
00002 #define OglGui_ScrollBar_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef OglGui_DirectionButton_h
00013 #include "OglGui/DirectionButton.h"
00014 #endif
00015
00016 #ifndef OglGui_ScrollBarListener_h
00017 #include "OglGui/ScrollBarListener.h"
00018 #endif
00019
00020 namespace OglGui
00021 {
00022
00023 class ScrollBar : public Window, RepeatTimer, ButtonListener
00024 {
00025 public:
00026 ScrollBar(Window* parent, int w, int h, bool horizontal) :
00027 Window(parent, w, h, true)
00028 {
00029 Init(horizontal, horizontal ? h : w);
00030 }
00031
00032 ScrollBar(Window* parent, int x, int y, int w, int h, bool horizontal) :
00033 Window(parent, x, y, w, h, true)
00034 {
00035 Init(horizontal, horizontal ? h : w);
00036 }
00037
00038 virtual int
00039 SetState(int nState)
00040 {
00041 mButIncr->SetState(nState ? 1 : 0);
00042 mButDecr->SetState(nState ? 1 : 0);
00043 mButThumb->SetState(nState ? 1 : 0);
00044 return Window::SetState(nState);
00045 }
00046
00047
00048
00049
00050
00051
00052
00053 DirectionButton* ButIncr()
00054 {
00055 return mButIncr;
00056 }
00057
00058 DirectionButton* ButDecr()
00059 {
00060 return mButDecr;
00061 }
00062
00063 Button* ButThumb()
00064 {
00065 return mButThumb;
00066 }
00067
00068
00069
00070 enum Comp {
00071 Incr, Thumb, Decr, All
00072 };
00073
00074 void SetCompBorderType(Comp comp, int type)
00075 {
00076 Window *wnd = 0;
00077 switch(comp)
00078 {
00079 case All:
00080 mButIncr->SetBorderType(type);
00081 mButDecr->SetBorderType(type);
00082 mButThumb->SetBorderType(type);
00083 break;
00084 case Incr: wnd = mButIncr; break;
00085 case Thumb: wnd = mButThumb; break;
00086 case Decr: wnd = mButDecr; break;
00087 }
00088 if (wnd && comp != All)
00089 wnd->SetBorderType(type);
00090 }
00091
00092 void SetCompRoundness(Comp comp, float r0, float r1, float r2, float r3)
00093 {
00094 Window *wnd = 0;
00095 switch(comp)
00096 {
00097 case All:
00098 mButIncr->SetRoundness(r0, r1, r2, r3);
00099 mButDecr->SetRoundness(r0, r1, r2, r3);
00100 mButThumb->SetRoundness(r0, r1, r2, r3);
00101 break;
00102 case Incr: wnd = mButIncr; break;
00103 case Thumb: wnd = mButThumb; break;
00104 case Decr: wnd = mButDecr; break;
00105 }
00106 if (wnd && comp != All)
00107 wnd->SetRoundness(r0, r1, r2, r3);
00108 }
00109
00110 void SetScrollBarListener(ScrollBarListener* listener, void* data=0)
00111 {
00112 mListener = listener;
00113 mListenerData = data;
00114 }
00115 void SetScrollBarListener(ScrollBarListener* listener, int data)
00116 {
00117 SetScrollBarListener(listener, (void*) data);
00118 }
00119
00120 void ScrollKeyHandling(bool mode) { mScrollKeyHandling = mode; }
00121 bool ScrollKeyHandling() { return mScrollKeyHandling; }
00122
00123
00124 void SetLineIncrement(int incr)
00125 {
00126 mScrollLine = incr;
00127 }
00128
00129 void LineIncrement(int incr)
00130 {
00131 mScrollLine = incr;
00132 }
00133 int LineIncrement()
00134 {
00135 return mScrollLine;
00136 }
00137
00138 void SetRange(int totalRange, int pageSize)
00139 {
00140 bool tooSmall = (mHorizontal && mOglWnd->width < 40) ||
00141 (!mHorizontal && mOglWnd->height < 40);
00142
00143 mScrollRange = totalRange;
00144 mScrollPage = pageSize;
00145
00146
00147 if(totalRange > pageSize && pageSize > 0 && !tooSmall &&
00148 mScrollRange!=0)
00149 {
00150 mButThumb->SetVisible(true);
00151 mButIncr->SetVisible(true);
00152 mButDecr->SetVisible(true);
00153 if (mHorizontal)
00154 mPixelPage = ((mOglWnd->width - (2*cSbW)) * mScrollPage) /
00155 mScrollRange;
00156 else
00157 mPixelPage = ((mOglWnd->height - (2*cSbW)) * mScrollPage) /
00158 mScrollRange;
00159
00160 if (mPixelPage < 12)
00161 mPixelPage = 12;
00162
00163
00164 if (mPixelPage + mPixelPos > mPixelRange)
00165 {
00166 mPixelPos = mPixelRange - mPixelPage;
00167
00168
00169
00170
00171
00172
00173
00174
00175 }
00176
00177 if (mHorizontal)
00178 oglSys.SetDimensions(mButThumb->GetOGLWND(), mPixelPos + cSbW,
00179 0, mPixelPage, cSbW);
00180 else
00181 {
00182 int y = mOglWnd->height - cSbW - mPixelPos - mPixelPage;
00183 oglSys.SetDimensions(mButThumb->GetOGLWND(), 0, y, cSbW,
00184 mPixelPage);
00185 }
00186 }
00187 else
00188 {
00189 mButThumb->SetVisible(false);
00190 mButIncr->SetVisible(false);
00191 mButDecr->SetVisible(false);
00192 }
00193 }
00194
00195 void GetRange(int& totalRange, int& pageSize)
00196 {
00197 totalRange = mScrollRange;
00198 pageSize = mScrollPage;
00199 }
00200
00201 void
00202 ChangePos(int change)
00203 {
00204 SetNewPos(mScrollPos + change);
00205 }
00206
00207
00208 void
00209 SetNewPos(int pos)
00210 {
00211 if (pos>=mScrollRange - mScrollPage)
00212 pos = mScrollRange - mScrollPage;
00213 if (pos<0)
00214 pos = 0;
00215 if (pos != mScrollPos)
00216 {
00217 mScrollPos = pos;
00218
00219
00220
00221
00222 int divider = mScrollRange - mScrollPage;
00223 if (!divider)
00224 divider = 1;
00225
00226 mPixelPos = ((mPixelRange - mPixelPage) / (double) divider) * mScrollPos;
00227 if(mListener)
00228 mListener->OnScroll(this, mScrollPos, mListenerData);
00229 oglSys.UpdateSceneFlag(GetOGLWND(), 1);
00230 }
00231 }
00232
00233 void
00234 MakeVisible(int pos)
00235 {
00236 if ((pos >= mScrollPos) && (pos < mScrollPos+mScrollPage))
00237 return;
00238 SetNewPos(pos);
00239 }
00240
00241
00242 void SetValue(int val)
00243 {
00244 SetNewPos(val);
00245 }
00246
00247 int GetValue()
00248 {
00249 return mScrollPos;
00250 }
00251
00252 void
00253 SetPosition(int x, int y, int w, int h)
00254 {
00255
00256
00257 mOglWnd->x = x;
00258 mOglWnd->y = y;
00259 mOglWnd->height = h;
00260 mOglWnd->width = w;
00261 if (mHorizontal)
00262 mPixelRange = mOglWnd->width - (2*cSbW);
00263 else
00264 mPixelRange = mOglWnd->height - (2*cSbW);
00265 SetRange(mScrollRange, mScrollPage);
00266 }
00267
00268
00269 void
00270 RepositionViewports()
00271 {
00272 OGLWND *oglWnd = GetOGLWND();
00273
00274 if (mHorizontal)
00275 {
00276 int h = oglWnd->height;
00277 if (mFixedWide)
00278 h = oglWnd->height = mWide;
00279 oglSys.SetDimensions(mButDecr->GetOGLWND(), 0, 0, cSbW, h);
00280 oglSys.SetDimensions(mButThumb->GetOGLWND(), mPixelPos + cSbW,
00281 0, mPixelPage, h);
00282 oglSys.SetDimensions(mButIncr->GetOGLWND(), mOglWnd->width - cSbW,
00283 0, cSbW, h);
00284 }
00285 else
00286 {
00287 int w = oglWnd->width;
00288 if (mFixedWide)
00289 w = oglWnd->width = mWide;
00290
00291 oglSys.SetDimensions(mButDecr->GetOGLWND(), 0,
00292 mOglWnd->height - cSbW, w, cSbW);
00293 oglSys.SetDimensions(mButThumb->GetOGLWND(), 0,
00294 mOglWnd->height - cSbW - mPixelPos - mPixelPage,
00295 w, mPixelPage);
00296 oglSys.SetDimensions(mButIncr->GetOGLWND(), 0, 0, w, cSbW);
00297 }
00298 }
00299
00300
00301 virtual void
00302 MouseFunc(INT msg, INT but, INT state, INT x, INT y)
00303 {
00304 if (!GetState() || (state & (oglShift|oglControl)))
00305 return;
00306
00307 Window::MouseFunc(msg, but, state, x, y);
00308
00309
00310 if ((msg==oglMouseDown || msg==oglMouseDblClick) && but==oglLeftButton)
00311 {
00312 if (mHorizontal)
00313 mMouseDownPos = x-cSbW;
00314 else
00315 mMouseDownPos = y-cSbW;
00316 PropagateScrolling();
00317 mPagePressed = true;
00318 StartRepeatTime();
00319 oglSys.SetAlwaysDraw(mOglWnd, true);
00320 }
00321
00322 if (msg == oglMouseWheelUp)
00323 ChangePos(-mScrollLine * ((state&oglShift) ? 5 : 1));
00324 if (msg == oglMouseWheelDown)
00325 ChangePos(mScrollLine * ((state&oglShift) ? 5 : 1));
00326
00327 if (msg == oglMouseMove)
00328 {
00329 if (mHorizontal)
00330 mMouseDownPos = x-cSbW;
00331 else
00332 mMouseDownPos = y-cSbW;
00333 }
00334
00335 if (msg == oglMouseUp && but == oglLeftButton)
00336 {
00337 mPagePressed = false;
00338 oglSys.SetAlwaysDraw(mOglWnd, false);
00339 }
00340
00341 }
00342
00343 virtual void
00344 InitDisplayFunc()
00345 {
00346 #ifdef ORG_STATEFEEDBACK
00347 if (GetState()==2 || mButThumb->GetState()==2 ||
00348 mButIncr->GetState()==2 || mButDecr->GetState()==2)
00349 {
00350 mOldBorderBg = GetBorderBackground();
00351 SetBorderBackground(mStateFeedbackColor);
00352 }
00353 #endif
00354
00355
00356 if (mHorizontal)
00357 mPixelRange = mOglWnd->width - (2*cSbW);
00358 else
00359 mPixelRange = mOglWnd->height - (2*cSbW);
00360 SetRange(mScrollRange, mScrollPage);
00361
00362 if (mScrollRange == mScrollPage){
00363
00364 mScrollPage--;
00365 }
00366
00367 mPixelPos = (mPixelRange - mPixelPage) * (double) mScrollPos /
00368 (mScrollRange - mScrollPage);
00369
00370 RepositionViewports();
00371
00372 Window::InitDisplayFunc();
00373 }
00374
00375 virtual void
00376 DisplayFunc()
00377 {
00378 if (mPagePressed && RepeatTime())
00379 PropagateScrolling();
00380
00381 Window::DisplayFunc();
00382 }
00383
00384 void
00385 PropagateScrolling()
00386 {
00387 if (mHorizontal)
00388 {
00389 if (mMouseDownPos - mPixelPos < 0)
00390 SetNewPos(mScrollPos - mScrollPage);
00391 else
00392 if(mMouseDownPos - mPixelPos > mPixelPage)
00393 SetNewPos(mScrollPos + mScrollPage);
00394 }
00395 else
00396 {
00397 if (mMouseDownPos - mPixelRange + mPixelPos < -mPixelPage)
00398 SetNewPos(mScrollPos + mScrollPage);
00399 else
00400 if (mMouseDownPos - mPixelRange + mPixelPos > 0)
00401 SetNewPos(mScrollPos - mScrollPage);
00402 }
00403 }
00404
00405 void
00406 ButtonSelectionEvent(Button *src, void* vdata)
00407 {
00408 int data = (long long) vdata;
00409 switch (data)
00410 {
00411 case 1:
00412 SetNewPos(mScrollPos-mScrollLine);
00413 break;
00414 case 3:
00415 SetNewPos(mScrollPos+mScrollLine);
00416 break;
00417 }
00418 }
00419
00420 virtual void
00421 KeyboardFunc(INT c, int state)
00422 {
00423 Window::KeyboardFunc(c, state);
00424 if (!mMapKeysTarget && mScrollKeyHandling)
00425 ScrollKeys(c, state);
00426 }
00427
00428 void
00429 ScrollKeys(INT c, int state)
00430 {
00431 if (state & (oglControl|oglAlt))
00432 return;
00433
00434 switch(c)
00435 {
00436 case oglLEFT:
00437 case oglUP:
00438 ChangePos(-mScrollLine * ((state&oglShift) ? 5 : 1));
00439 break;
00440 case oglDOWN:
00441 case oglRIGHT:
00442 ChangePos(mScrollLine * ((state&oglShift) ? 5 : 1));
00443 break;
00444 case oglPAGEUP:
00445 ChangePos(-mScrollPage);
00446 break;
00447 case oglPAGEDOWN:
00448 ChangePos(mScrollPage);
00449 break;
00450 case oglHOME:
00451 SetNewPos(0);
00452 break;
00453 case oglEND:
00454 SetNewPos(mScrollRange);
00455 break;
00456 }
00457 }
00458
00459 void SetFixedWide(bool mode) { mFixedWide = mode; }
00460 bool GetFixedWide() { return mFixedWide; }
00461
00462 class ScrollThumb : public Button
00463 {
00464 public:
00465 ScrollThumb(ScrollBar* parent, int width, int height, std::string label) :
00466 Button(parent, width, height, label)
00467 {
00468 mParent = parent;
00469 SetRoundness(0, 0, 0, 0);
00470 SetBorderType(BEV_ETCHED);
00471 SetBackground(0x0);
00472 #ifdef OGL_USING_GLUT
00473 SetAlignOffsets(0,-1);
00474 #endif
00475 }
00476
00477 virtual void
00478 MouseFunc(INT msg, INT but, INT state, INT x, INT y)
00479 {
00480 if (!GetState() || (state & (oglShift|oglControl)))
00481 return;
00482
00483 Button::MouseFunc(msg, but, state, x, y);
00484 if (msg == oglMouseDown && but == oglLeftButton)
00485 {
00486 mDragging = true;
00487 mClickX = x;
00488 mClickY = y;
00489 }
00490
00491 if (msg == oglMouseUp && but == oglLeftButton)
00492 mDragging = false;
00493 if (msg == oglMouseMove)
00494 {
00495 if (mDragging)
00496 {
00497 if (mParent->mHorizontal)
00498 {
00499 mOglWnd->x += x - mClickX;
00500
00501 if (mOglWnd->x < cSbW)
00502 mOglWnd->x = cSbW;
00503 int max = mParent->mPixelRange + cSbW - mOglWnd->width;
00504 if (mOglWnd->x > max)
00505 mOglWnd->x = max;
00506
00507 mParent->OnScrollThumb(mOglWnd->x - cSbW);
00508 }
00509 else
00510 {
00511 mOglWnd->y += y - mClickY;
00512
00513 if (mOglWnd->y < cSbW)
00514 mOglWnd->y = cSbW;
00515 int max = mParent->mPixelRange + cSbW - mOglWnd->height;
00516 if (mOglWnd->y > max)
00517 mOglWnd->y = max;
00518
00519 mParent->OnScrollThumb(mParent->mPixelRange + cSbW -
00520 mOglWnd->height - mOglWnd->y);
00521 }
00522 }
00523 }
00524 }
00525 private:
00526 ScrollBar* mParent;
00527 bool mDragging;
00528 int mClickX;
00529 int mClickY;
00530 };
00531
00532 protected:
00533 bool mHorizontal;
00534 bool mFixedWide;
00535 bool mScrollKeyHandling;
00536 ULONG mOldBorderBg;
00537 int mWide;
00538 ScrollBarListener* mListener;
00539 void* mListenerData;
00540 DirectionButton* mButIncr;
00541 DirectionButton* mButDecr;
00542 ScrollThumb* mButThumb;
00543 int mMouseDownPos;
00544 bool mPagePressed;
00545
00546
00547 int mScrollRange, mScrollPage, mScrollPos;
00548 int mPixelRange, mPixelPage, mPixelPos;
00549 int mScrollLine;
00550
00551
00552 void
00553 OnScrollThumb(int pos)
00554 {
00555 mPixelPos = pos;
00556
00557 if (mPixelRange == mPixelPage){
00558
00559 mPixelPage--;
00560 }
00561 double p = (double)pos/(double)(mPixelRange-mPixelPage);
00562 mScrollPos = (int) (p * (mScrollRange-mScrollPage));
00563 if(mListener)
00564 mListener->OnScroll(this, mScrollPos, mListenerData);
00565 }
00566
00567 friend class ScrollThumb;
00568
00569
00570 private:
00571 static const int cSbW = 16;
00572
00573 void
00574 Init(bool isHor, int wide)
00575 {
00576 GuiGeneralName("ScrollBar");
00577 GuiName("ScrollBar");
00578 mHorizontal = isHor;
00579 mScrollKeyHandling = true;
00580 mFixedWide = false;
00581 mWide = wide;
00582 mPixelRange = (isHor ? mOglWnd->width : mOglWnd->height) - (2*cSbW);
00583 mScrollRange = 0;
00584 mScrollPage = 0;
00585 mScrollPos = 0;
00586 mScrollLine = 1;
00587 mPixelPos = 0;
00588 mListener = 0;
00589 mListenerData = 0;
00590 mPagePressed = false;
00591
00592 mButDecr = new DirectionButton(this, cSbW, cSbW, isHor?2.f:1.f);
00593 mButDecr->GuiName("Decr");
00594 mButDecr->MapKeysTo(this);
00595 mButDecr->SetClosed(false);
00596 mButDecr->SetDirectionFeedback(true);
00597 mButDecr->SetFilled(false);
00598 mButDecr->SetFixedArrowSize(7);
00599
00600 mButDecr->SetRoundness(0, 0, 0, 0);
00601 mButDecr->SetBorderType(BEV_ETCHED);
00602 mButDecr->SetButtonListener(this, (void*)1);
00603 mButDecr->SetRepeatMode(true);
00604
00605 mButThumb = new ScrollThumb(this, cSbW, cSbW, "=");
00606 mButThumb->GuiName("Thumb");
00607 mButThumb->MapKeysTo(this);
00608 mButThumb->SetButtonListener(this, (void*)2);
00609 mButThumb->SetShowCancelState(false);
00610
00611 mButIncr = new DirectionButton(this, cSbW, cSbW, isHor?0.f:3.f);
00612 mButIncr->GuiName("Incr");
00613 mButIncr->MapKeysTo(this);
00614 mButIncr->SetClosed(false);
00615 mButIncr->SetDirectionFeedback(true);
00616 mButIncr->SetFilled(false);
00617 mButIncr->SetFixedArrowSize(7);
00618
00619 mButIncr->SetButtonListener(this, (void*)3);
00620 mButIncr->SetRepeatMode(true);
00621 mButIncr->SetRoundness(0, 0, 0, 0);
00622 mButIncr->SetBorderType(BEV_ETCHED);
00623
00624 SetBorderType(BEV_ETCHED);
00625
00626 SetDisableOGLViewKeys(true);
00627 SetDisableOGLViewMouse(true);
00628 }
00629 };
00630
00631 }
00632 #endif // ScrollBar_h