aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/wnd/wndclass/scrollbar.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/wnd/wndclass/scrollbar.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/wnd/wndclass/scrollbar.cpp')
-rw-r--r--Src/Wasabi/api/wnd/wndclass/scrollbar.cpp679
1 files changed, 679 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/wndclass/scrollbar.cpp b/Src/Wasabi/api/wnd/wndclass/scrollbar.cpp
new file mode 100644
index 00000000..ce3e5b03
--- /dev/null
+++ b/Src/Wasabi/api/wnd/wndclass/scrollbar.cpp
@@ -0,0 +1,679 @@
+#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();
+}
+