aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/windows/areascroll.cpp
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-09-09 02:30:51 +0200
committerStapleButter <thetotalworm@gmail.com>2017-09-09 02:30:51 +0200
commit70e4841d311d68689724768157cc9cbfbde7a9fc (patch)
treeba9499f77d1258530a7e60aa6e1732c41d98161c /src/libui_sdl/libui/windows/areascroll.cpp
parent81747d6c34eb159481a6ca3f283d065fa3568617 (diff)
another UI attempt, I guess.
sorry.
Diffstat (limited to 'src/libui_sdl/libui/windows/areascroll.cpp')
-rw-r--r--src/libui_sdl/libui/windows/areascroll.cpp247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/windows/areascroll.cpp b/src/libui_sdl/libui/windows/areascroll.cpp
new file mode 100644
index 0000000..f18d0ad
--- /dev/null
+++ b/src/libui_sdl/libui/windows/areascroll.cpp
@@ -0,0 +1,247 @@
+// 8 september 2015
+#include "uipriv_windows.hpp"
+#include "area.hpp"
+
+// TODO
+// - move from pixels to points somehow
+// - add a function to offset points and rects by scrolling amounts; call it from doPaint() in areadraw.c
+// - recalculate scrolling after:
+// - creation?
+// - resize?
+// - recreating the render target? (after moving to points)
+// - error if these are called without scrollbars?
+
+struct scrollParams {
+ int *pos;
+ int pagesize;
+ int length;
+ int *wheelCarry;
+ UINT wheelSPIAction;
+};
+
+static void scrollto(uiArea *a, int which, struct scrollParams *p, int pos)
+{
+ SCROLLINFO si;
+
+ // note that the pos < 0 check is /after/ the p->length - p->pagesize check
+ // it used to be /before/; this was actually a bug in Raymond Chen's original algorithm: if there are fewer than a page's worth of items, p->length - p->pagesize will be negative and our content draw at the bottom of the window
+ // this SHOULD have the same effect with that bug fixed and no others introduced... (thanks to devin on irc.badnik.net for confirming this logic)
+ if (pos > p->length - p->pagesize)
+ pos = p->length - p->pagesize;
+ if (pos < 0)
+ pos = 0;
+
+ // Direct2D doesn't have a method for scrolling the existing contents of a render target.
+ // We'll have to just invalidate everything and hope for the best.
+ invalidateRect(a->hwnd, NULL, FALSE);
+
+ *(p->pos) = pos;
+
+ // now commit our new scrollbar setup...
+ ZeroMemory(&si, sizeof (SCROLLINFO));
+ si.cbSize = sizeof (SCROLLINFO);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
+ si.nPage = p->pagesize;
+ si.nMin = 0;
+ si.nMax = p->length - 1; // endpoint inclusive
+ si.nPos = *(p->pos);
+ SetScrollInfo(a->hwnd, which, &si, TRUE);
+}
+
+static void scrollby(uiArea *a, int which, struct scrollParams *p, int delta)
+{
+ scrollto(a, which, p, *(p->pos) + delta);
+}
+
+static void scroll(uiArea *a, int which, struct scrollParams *p, WPARAM wParam, LPARAM lParam)
+{
+ int pos;
+ SCROLLINFO si;
+
+ pos = *(p->pos);
+ switch (LOWORD(wParam)) {
+ case SB_LEFT: // also SB_TOP
+ pos = 0;
+ break;
+ case SB_RIGHT: // also SB_BOTTOM
+ pos = p->length - p->pagesize;
+ break;
+ case SB_LINELEFT: // also SB_LINEUP
+ pos--;
+ break;
+ case SB_LINERIGHT: // also SB_LINEDOWN
+ pos++;
+ break;
+ case SB_PAGELEFT: // also SB_PAGEUP
+ pos -= p->pagesize;
+ break;
+ case SB_PAGERIGHT: // also SB_PAGEDOWN
+ pos += p->pagesize;
+ break;
+ case SB_THUMBPOSITION:
+ ZeroMemory(&si, sizeof (SCROLLINFO));
+ si.cbSize = sizeof (SCROLLINFO);
+ si.fMask = SIF_POS;
+ if (GetScrollInfo(a->hwnd, which, &si) == 0)
+ logLastError(L"error getting thumb position for area");
+ pos = si.nPos;
+ break;
+ case SB_THUMBTRACK:
+ ZeroMemory(&si, sizeof (SCROLLINFO));
+ si.cbSize = sizeof (SCROLLINFO);
+ si.fMask = SIF_TRACKPOS;
+ if (GetScrollInfo(a->hwnd, which, &si) == 0)
+ logLastError(L"error getting thumb track position for area");
+ pos = si.nTrackPos;
+ break;
+ }
+ scrollto(a, which, p, pos);
+}
+
+static void wheelscroll(uiArea *a, int which, struct scrollParams *p, WPARAM wParam, LPARAM lParam)
+{
+ int delta;
+ int lines;
+ UINT scrollAmount;
+
+ delta = GET_WHEEL_DELTA_WPARAM(wParam);
+ if (SystemParametersInfoW(p->wheelSPIAction, 0, &scrollAmount, 0) == 0)
+ // TODO use scrollAmount == 3 (for both v and h) instead?
+ logLastError(L"error getting area wheel scroll amount");
+ if (scrollAmount == WHEEL_PAGESCROLL)
+ scrollAmount = p->pagesize;
+ if (scrollAmount == 0) // no mouse wheel scrolling (or t->pagesize == 0)
+ return;
+ // the rest of this is basically http://blogs.msdn.com/b/oldnewthing/archive/2003/08/07/54615.aspx and http://blogs.msdn.com/b/oldnewthing/archive/2003/08/11/54624.aspx
+ // see those pages for information on subtleties
+ delta += *(p->wheelCarry);
+ lines = delta * ((int) scrollAmount) / WHEEL_DELTA;
+ *(p->wheelCarry) = delta - lines * WHEEL_DELTA / ((int) scrollAmount);
+ scrollby(a, which, p, -lines);
+}
+
+static void hscrollParams(uiArea *a, struct scrollParams *p)
+{
+ RECT r;
+
+ ZeroMemory(p, sizeof (struct scrollParams));
+ p->pos = &(a->hscrollpos);
+ // TODO get rid of these and replace with points
+ uiWindowsEnsureGetClientRect(a->hwnd, &r);
+ p->pagesize = r.right - r.left;
+ p->length = a->scrollWidth;
+ p->wheelCarry = &(a->hwheelCarry);
+ p->wheelSPIAction = SPI_GETWHEELSCROLLCHARS;
+}
+
+static void hscrollto(uiArea *a, int pos)
+{
+ struct scrollParams p;
+
+ hscrollParams(a, &p);
+ scrollto(a, SB_HORZ, &p, pos);
+}
+
+static void hscrollby(uiArea *a, int delta)
+{
+ struct scrollParams p;
+
+ hscrollParams(a, &p);
+ scrollby(a, SB_HORZ, &p, delta);
+}
+
+static void hscroll(uiArea *a, WPARAM wParam, LPARAM lParam)
+{
+ struct scrollParams p;
+
+ hscrollParams(a, &p);
+ scroll(a, SB_HORZ, &p, wParam, lParam);
+}
+
+static void hwheelscroll(uiArea *a, WPARAM wParam, LPARAM lParam)
+{
+ struct scrollParams p;
+
+ hscrollParams(a, &p);
+ wheelscroll(a, SB_HORZ, &p, wParam, lParam);
+}
+
+static void vscrollParams(uiArea *a, struct scrollParams *p)
+{
+ RECT r;
+
+ ZeroMemory(p, sizeof (struct scrollParams));
+ p->pos = &(a->vscrollpos);
+ uiWindowsEnsureGetClientRect(a->hwnd, &r);
+ p->pagesize = r.bottom - r.top;
+ p->length = a->scrollHeight;
+ p->wheelCarry = &(a->vwheelCarry);
+ p->wheelSPIAction = SPI_GETWHEELSCROLLLINES;
+}
+
+static void vscrollto(uiArea *a, int pos)
+{
+ struct scrollParams p;
+
+ vscrollParams(a, &p);
+ scrollto(a, SB_VERT, &p, pos);
+}
+
+static void vscrollby(uiArea *a, int delta)
+{
+ struct scrollParams p;
+
+ vscrollParams(a, &p);
+ scrollby(a, SB_VERT, &p, delta);
+}
+
+static void vscroll(uiArea *a, WPARAM wParam, LPARAM lParam)
+{
+ struct scrollParams p;
+
+ vscrollParams(a, &p);
+ scroll(a, SB_VERT, &p, wParam, lParam);
+}
+
+static void vwheelscroll(uiArea *a, WPARAM wParam, LPARAM lParam)
+{
+ struct scrollParams p;
+
+ vscrollParams(a, &p);
+ wheelscroll(a, SB_VERT, &p, wParam, lParam);
+}
+
+BOOL areaDoScroll(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
+{
+ switch (uMsg) {
+ case WM_HSCROLL:
+ hscroll(a, wParam, lParam);
+ *lResult = 0;
+ return TRUE;
+ case WM_MOUSEHWHEEL:
+ hwheelscroll(a, wParam, lParam);
+ *lResult = 0;
+ return TRUE;
+ case WM_VSCROLL:
+ vscroll(a, wParam, lParam);
+ *lResult = 0;
+ return TRUE;
+ case WM_MOUSEWHEEL:
+ vwheelscroll(a, wParam, lParam);
+ *lResult = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void areaScrollOnResize(uiArea *a, RECT *client)
+{
+ areaUpdateScroll(a);
+}
+
+void areaUpdateScroll(uiArea *a)
+{
+ // use a no-op scroll to simulate scrolling
+ hscrollby(a, 0);
+ vscrollby(a, 0);
+}