123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679 |
- #include <precomp.h>
- #include <bfc/wasabi_std.h>
- #include "scrollbar.h"
- #include <tataki/canvas/canvas.h>
- #include <api/wnd/notifmsg.h>
- #include <api/wnd/PaintCanvas.h>
- #define TIMER_ID 9871
- #define TIMER_ID2 9872
- #define FIRST_DELAY 350
- #define NEXT_DELAY 75
- ScrollBar::ScrollBar() {
- leftrgn = NULL;
- rightrgn = NULL;
- buttonrgn = NULL;
- position = 0;
- moving = 0;
- lefting = 0;
- righting = 0;
- clicked = 0;
- height = DEFAULT_HEIGHT;
- buttonx = 0;
- shiftleft = 0;
- shiftright = 0;
- curmouseposition = POS_NONE;
- clickmouseposition = POS_NONE;
- pageing = 0;
- timer = timer2 = 0;
- npages = 100;
- pageway = PAGE_NONE;
- updown = 256;
- insetpos = 0;
- clickbuttonx = 0;
- vertical = 0;
- firstdelay = 0;
- lastx = lasty = 0;
- }
- ScrollBar::~ScrollBar() {
- deleteResources();
- }
- void ScrollBar::deleteResources() {
- delete leftrgn; leftrgn = NULL;
- delete buttonrgn; buttonrgn = NULL;
- delete rightrgn; rightrgn = NULL;
- }
- // this one is inherited
- void ScrollBar::freeResources() {
- SCROLLBAR_PARENT::freeResources();
- deleteResources();
- }
- void ScrollBar::reloadResources() {
- SCROLLBAR_PARENT::reloadResources();
- loadBmps();
- }
- int ScrollBar::onMouseMove (int x, int y) {
- SCROLLBAR_PARENT::onMouseMove(x, y);
- lastx = x;
- lasty = y;
- if (clicked && clickmouseposition == POS_BUTTON) {
- POINT pt={x,y};
- int x;
- if (!vertical)
- x = pt.x - clickpos.x;
- else
- x = pt.y - clickpos.y;
- RECT r;
- getClientRect(&r);
- int maxwidth;
- if (!vertical)
- maxwidth = (r.right-r.left)-(shiftright+shiftleft+bmpbutton.getWidth())+1;
- else
- maxwidth = (r.bottom-r.top)-(shiftright+shiftleft+bmpbutton.getHeight())+1;
- buttonx = MIN(MAX(clickbuttonx + x, 0), maxwidth);
- calcPosition();
- invalidate();
- } else {
- int oldposition = curmouseposition;
- curmouseposition = getMousePosition();
- if (oldposition != curmouseposition) invalidate();
- if (curmouseposition != POS_NONE && !getCapture())
- beginCapture();
- if (curmouseposition == POS_NONE && getCapture() && !clicked && !pageing)
- endCapture();
- }
- return 1;
- }
- int ScrollBar::getWidth() {
- if (!bmpbutton) return 0;
- if (!vertical)
- return bmpbutton.getHeight();
- else
- return bmpbutton.getWidth();
- return 0;
- }
- int ScrollBar::getMousePosition() {
- int v = POS_NONE;
- POINT pt={lastx, lasty};
- RECT c;
- getClientRect(&c);
- pt.x -= c.left;
- pt.y -= c.top;
- api_region *l, *b, *r;
- l = leftrgn->clone();
- b = buttonrgn->clone();
- if (!vertical)
- b->offset(buttonx+shiftleft, 0);
- else
- b->offset(0, buttonx+shiftleft);
- r = rightrgn->clone();
- if (!vertical)
- r->offset(c.right-c.left-bmpleft.getWidth(), 0);
- else
- r->offset(0, c.bottom-c.top-bmpleft.getHeight());
- if (b->ptInRegion(&pt))
- v = POS_BUTTON;
- if (l->ptInRegion(&pt))
- v = POS_LEFT;
- if (r->ptInRegion(&pt))
- v = POS_RIGHT;
- leftrgn->disposeClone(l);
- buttonrgn->disposeClone(b);
- rightrgn->disposeClone(r);
- return v;
- }
- int ScrollBar::onLeftButtonDown(int x, int y) {
- clickmouseposition = getMousePosition();
- if (!pageing && clickmouseposition != POS_NONE) {
- clicked = 1;
- if (clickmouseposition == POS_LEFT || clickmouseposition == POS_RIGHT)
- handleUpDown();
- if (clickmouseposition) {
- clickpos.x = lastx;
- clickpos.y = lasty;
- clickbuttonx = buttonx;
- }
- } else {
- clicked = 0;
- pageing = 1;
- handlePageUpDown();
- }
- invalidate();
- return 1;
- }
- void ScrollBar::handleUpDown() {
- setTimer(TIMER_ID2, FIRST_DELAY);
- timer2 = 1;
- firstdelay = 1;
- checkUpDown();
- }
- int ScrollBar::checkUpDown() {
- if (!clicked) {
- if (timer2) {
- killTimer(TIMER_ID2);
- timer2 = 0;
- return 1;
- }
- }
- if (getMousePosition() == clickmouseposition)
- upDown(clickmouseposition);
- return 1;
- }
- void ScrollBar::handlePageUpDown() {
- setTimer(TIMER_ID, FIRST_DELAY);
- timer = 1;
- firstdelay = 1;
- checkPageUpDown();
- }
- int ScrollBar::checkPageUpDown() {
- if (!pageing) {
- if (timer) {
- killTimer(TIMER_ID);
- timer = 0;
- pageway = PAGE_NONE;
- return 1;
- }
- }
- POINT pt={lastx,lasty};
- RECT c;
- getClientRect(&c);
- pt.x -= c.left;
- pt.y -= c.top;
-
- if (!vertical) {
- int middlebutton = shiftleft + buttonx + bmpbutton.getWidth()/2;
- api_region *r = buttonrgn->clone();
- r->offset(buttonx+shiftleft, 0);
- if (pt.x > middlebutton && !r->ptInRegion(&pt) && pageway != PAGE_DOWN)
- pageUp();
- if (pt.x < middlebutton && !r->ptInRegion(&pt) && pageway != PAGE_UP)
- pageDown();
- buttonrgn->disposeClone(r);
- } else {
- int middlebutton = shiftleft + buttonx + bmpbutton.getHeight()/2;
- api_region *r = buttonrgn->clone();
- r->offset(0, buttonx+shiftleft);
- if (pt.y > middlebutton && !r->ptInRegion(&pt) && pageway != PAGE_DOWN)
- pageUp();
- if (pt.y < middlebutton && !r->ptInRegion(&pt) && pageway != PAGE_UP)
- pageDown();
- buttonrgn->disposeClone(r);
- }
- return 1;
- }
- int ScrollBar::onLeftButtonUp(int x, int y) {
- clicked = 0;
- clickmouseposition = POS_NONE;
- curmouseposition = POS_NONE;
- onMouseMove(x,y);
- if (pageing) {
- pageing = 0;
- checkPageUpDown();
- }
- onSetFinalPosition();
- invalidate();
- return 1;
- }
- int ScrollBar::onRightButtonDown(int x, int y) {
- return 1;
- }
- int ScrollBar::onRightButtonUp(int x, int y) {
- return 1;
- }
- int ScrollBar::onMouseWheelUp(int clicked, int lines) {
- return 1;
- }
- int ScrollBar::onMouseWheelDown(int clicked, int lines) {
- return 1;
- }
- int ScrollBar::onPaint(Canvas *canvas) {
- AutoSkinBitmap &thisleft = curmouseposition == POS_LEFT ? (clicked ? bmplpressed : bmplhilite) : bmpleft;
- AutoSkinBitmap &thisbutton = curmouseposition == POS_BUTTON ? (clicked ? bmpbpressed : bmpbhilite) : bmpbutton;
- AutoSkinBitmap &thisright = curmouseposition == POS_RIGHT ? (clicked ? bmprpressed : bmprhilite) : bmpright;
- if (curmouseposition != clickmouseposition && clicked) {
- thisleft = bmpleft;
- thisbutton = bmpbutton;
- thisright = bmpright;
- }
- RECT r;
- PaintBltCanvas paintcanvas;
- if (canvas == NULL) {
- if (!paintcanvas.beginPaint(this)) return 0;
- canvas = &paintcanvas;
- }
- SCROLLBAR_PARENT::onPaint(canvas);
- getClientRect(&r);
- renderBaseTexture(canvas, r);
- if (!vertical) {
- RECT c;
- c.left = r.left;
- c.right = r.left;
- c.top = r.top;
- c.bottom = r.bottom;
- if (bmpbackgroundleft.getBitmap()) {
- c.right = c.left + bmpbackgroundleft.getWidth();
- bmpbackgroundleft.getBitmap()->stretchToRectAlpha(canvas, &c);
- }
- int l = c.right;
- c.left = r.right;
- c.right = r.right;
- if (bmpbackgroundright.getBitmap()) {
- c.left = r.right - bmpbackgroundright.getWidth();
- bmpbackgroundright.getBitmap()->stretchToRectAlpha(canvas, &c);
- }
- c.right = c.left;
- c.left = l;
- if (bmpbackgroundmiddle.getBitmap()) {
- bmpbackgroundmiddle.getBitmap()->stretchToRectAlpha(canvas, &c);
- }
- c.left = r.left + buttonx+shiftleft;
- c.top = r.top + 0;
- c.right = r.left + buttonx+thisbutton.getWidth()+shiftleft;
- c.bottom = r.top + getWidth();
- thisbutton.stretchToRectAlpha(canvas, &c);
- c.left = r.left;
- c.top = r.top;
- c.right = r.left + thisleft.getWidth();
- c.bottom = r.top + getWidth();
- thisleft.stretchToRectAlpha(canvas, &c);
- c.left = r.right-thisright.getWidth();
- c.top = r.top;
- c.right = r.right;
- c.bottom = r.top+getWidth();
- thisright.stretchToRectAlpha(canvas, &c);
- } else {
- RECT c;
- c.top = r.top;
- c.bottom = r.top;
- c.left = r.left;
- c.right = r.right;
- if (bmpbackgroundleft.getBitmap()) {
- c.bottom = c.top + bmpbackgroundleft.getHeight();
- bmpbackgroundleft.getBitmap()->stretchToRectAlpha(canvas, &c);
- }
- int l = c.bottom;
- c.top = r.bottom;
- c.bottom = r.bottom;
- if (bmpbackgroundright.getBitmap()) {
- c.top = r.bottom - bmpbackgroundright.getHeight();
- bmpbackgroundright.getBitmap()->stretchToRectAlpha(canvas, &c);
- }
- c.bottom = c.top;
- c.top = l;
- if (bmpbackgroundmiddle.getBitmap()) {
- bmpbackgroundmiddle.getBitmap()->stretchToRectAlpha(canvas, &c);
- }
- c.left = r.right - thisleft.getWidth();
- c.top = r.top+buttonx + shiftleft;
- c.right = r.right;
- c.bottom = r.top+buttonx+thisbutton.getHeight() + shiftleft;
- thisbutton.stretchToRectAlpha(canvas, &c);
- c.left = r.right - thisleft.getWidth();
- c.top = r.top;
- c.right = r.right;
- c.bottom = r.top+thisleft.getHeight();
- thisleft.stretchToRectAlpha(canvas, &c);
- c.left = r.right-thisright.getWidth();
- c.top = r.bottom-thisright.getHeight();
- c.right = r.right;
- c.bottom = r.bottom;
- thisright.stretchToRectAlpha(canvas, &c);
- }
- return 1;
- }
- int ScrollBar::getHeight() {
- return height;
- }
- void ScrollBar::setHeight(int newheight) {
- height = newheight;
- }
- int ScrollBar::onResize() {
- calcXPosition();
- invalidate();
- return 1;
- }
- int ScrollBar::onInit() {
- SCROLLBAR_PARENT::onInit();
- return 1;
- }
- void ScrollBar::setBitmaps(wchar_t *left, wchar_t *lpressed, wchar_t *lhilite,
- wchar_t *right, wchar_t *rpressed, wchar_t *rhilite,
- wchar_t *button, wchar_t *bpressed, wchar_t *bhilite) {
- deleteResources();
- bmpleft = left;
- bmplpressed = lpressed;
- bmplhilite = lhilite;
- bmpright = right;
- bmprpressed = rpressed;
- bmprhilite = rhilite;
- bmpbutton = button;
- bmpbpressed = bpressed;
- bmpbhilite = bhilite;
- loadBmps();
- }
- void ScrollBar::setBackgroundBitmaps(const wchar_t *left, const wchar_t *middle, const wchar_t *right) {
- bmpbackgroundleft = left;
- bmpbackgroundmiddle = middle;
- bmpbackgroundright = right;
- }
- void ScrollBar::loadBmps() {
- if (bmpleft.getBitmap()) leftrgn = new RegionI(bmpleft);
- if (bmpbutton.getBitmap()) buttonrgn = new RegionI(bmpbutton);
- if (bmpright.getBitmap()) rightrgn = new RegionI(bmpright);
- calcOverlapping();
- calcXPosition();
- }
- void ScrollBar::setPosition(int pos) {
- setPrivatePosition(pos, FALSE);
- }
- void ScrollBar::setPrivatePosition(int pos, bool signal, bool smooth) {
- if (insetpos) return; // helps stupid people (like me)
- insetpos = 1;
- position = MIN(SCROLLBAR_FULL, pos);
- position = MAX(0, position);
- calcXPosition();
- if (signal) onSetPosition(smooth);
- if (isInited() && isVisible())
- invalidate();
- insetpos = 0;
- }
- int ScrollBar::getPosition() {
- return position;
- }
- int ScrollBar::onSetPosition(bool smooth) {
- notifyParent(ChildNotify::SCROLLBAR_SETPOSITION, smooth);
- return 1;
- }
- int ScrollBar::onSetFinalPosition() {
- notifyParent(ChildNotify::SCROLLBAR_SETFINALPOSITION);
- return 1;
- }
- void ScrollBar::calcOverlapping() {
- if (!vertical) {
- shiftleft = bmpleft.getWidth();
- if (leftrgn && buttonrgn) {
- int i;
- for (i=shiftleft;i>=0;i--) {
- api_region *reg = buttonrgn->clone();
- reg->offset(i, 0);
- if (leftrgn->doesIntersectRgn(reg)) {
- i++;
- buttonrgn->disposeClone(reg);
- break;
- }
- buttonrgn->disposeClone(reg);
- }
- if (i >= 0)
- shiftleft = i;
- }
- shiftright = bmpright.getWidth();
- if (rightrgn && buttonrgn) {
- int i;
- for (i=0;i>=-shiftright;i--) {
- api_region *reg = rightrgn->clone();
- reg->offset(i+bmpbutton.getWidth(), 0);
- if (reg->doesIntersectRgn(buttonrgn)) {
- i++;
- rightrgn->disposeClone(reg);
- break;
- }
- rightrgn->disposeClone(reg);
- }
- if (i >= -shiftright)
- shiftright += i;
- }
- } else {
- shiftleft = bmpleft.getHeight();
- if (leftrgn && buttonrgn) {
- int i;
- for (i=shiftleft;i>=0;i--) {
- api_region *reg = buttonrgn->clone();
- reg->offset(0, i);
- if (leftrgn->doesIntersectRgn(reg)) {
- i++;
- buttonrgn->disposeClone(reg);
- break;
- }
- buttonrgn->disposeClone(reg);
- }
- if (i >= 0)
- shiftleft = i;
- }
- shiftright = bmpright.getHeight();
- if (rightrgn && buttonrgn) {
- int i;
- for (i=0;i>=-shiftright;i--) {
- api_region *reg = rightrgn->clone();
- reg->offset(0, i+bmpbutton.getHeight());
- if (reg->doesIntersectRgn(buttonrgn)) {
- i++;
- rightrgn->disposeClone(reg);
- break;
- }
- rightrgn->disposeClone(reg);
- }
- if (i >= -shiftright)
- shiftright += i;
- }
- }
- }
- void ScrollBar::calcXPosition() {
- if (!isInited()) return;
- RECT r;
- getClientRect(&r);
- int maxwidth;
- if (!vertical)
- maxwidth = (r.right-r.left)-(bmpbutton.getWidth()+shiftleft+shiftright)+1;
- else
- maxwidth = (r.bottom-r.top)-(bmpbutton.getHeight()+shiftleft+shiftright)+1;
- int oldx = buttonx;
- buttonx = (int)(((float)getPosition() / SCROLLBAR_FULL) * maxwidth);
- if (buttonx != oldx)
- invalidate();
- }
- void ScrollBar::calcPosition() {
- if (!isInited()) return;
- RECT r;
- getClientRect(&r);
- int maxwidth;
- if (!vertical)
- maxwidth = r.right-r.left-(bmpbutton.getWidth()+shiftleft+shiftright)+1;
- else
- maxwidth = r.bottom-r.top-(bmpbutton.getHeight()+shiftleft+shiftright)+1;
- setPrivatePosition((int)((float)buttonx / maxwidth * SCROLLBAR_FULL));
- //invalidate();
- }
- void ScrollBar::timerCallback(int id) {
- switch (id) {
- case TIMER_ID:
- if (firstdelay) {
- killTimer(TIMER_ID);
- setTimer(TIMER_ID, NEXT_DELAY);
- timer = 1;
- firstdelay = 0;
- }
- checkPageUpDown();
- break;
- case TIMER_ID2:
- if (firstdelay) {
- killTimer(TIMER_ID2);
- setTimer(TIMER_ID2, NEXT_DELAY);
- timer2 = 1;
- firstdelay = 0;
- }
- checkUpDown();
- break;
- default:
- SCROLLBAR_PARENT::timerCallback(id);
- }
- }
- // FG> smooth scrolling forced on, sorry, microsoft does it too so the user perceives IE scrolling as faster than it actually is
- // eventho they tell you "The smooth-scrolling effect for list boxes should be disabled when this setting is FALSE. Your application must do this if it creates customized list boxes", they
- // break their own rule so people don't bitch too much. ergo there is no reason we should not do that too.
- int ScrollBar::pageUp() {
- pageway = PAGE_UP;
- setPrivatePosition((int)MAX(0.f, (float)getPosition() + (float)SCROLLBAR_FULL / (npages-1)), TRUE, 1/*Std::osparam_getSmoothScroll()*/);
- return 1;
- };
- int ScrollBar::pageDown() {
- pageway = PAGE_DOWN;
- setPrivatePosition((int)MIN((float)SCROLLBAR_FULL, (float)getPosition() - (float)SCROLLBAR_FULL / (npages-1)), TRUE, 1/*Std::osparam_getSmoothScroll()*/);
- return 1;
- };
- void ScrollBar::setNPages(int n) {
- //ASSERT(n >= 2);
- if (n < 2) n = 2;
- npages = n;
- }
- void ScrollBar::gotoPage(int page) {
- page = MIN(page, npages-1);
- page = MAX(page, 0);
- setPrivatePosition((int)((float)SCROLLBAR_FULL / (npages-1) * page), TRUE, FALSE);
- }
- void ScrollBar::setUpDownValue(int newupdown) {
- updown = newupdown;
- }
- int ScrollBar::upDown(int which) {
- switch (which) {
- case POS_LEFT:
- setPrivatePosition(getPosition()-updown);
- break;
- case POS_RIGHT:
- setPrivatePosition(getPosition()+updown);
- break;
- }
- return 1;
- }
- void ScrollBar::setVertical(bool isvertical) {
- vertical = isvertical;
- calcOverlapping();
- if (isInited())
- invalidate();
- }
|