aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/windows/areadraw.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/areadraw.cpp
parent81747d6c34eb159481a6ca3f283d065fa3568617 (diff)
another UI attempt, I guess.
sorry.
Diffstat (limited to 'src/libui_sdl/libui/windows/areadraw.cpp')
-rw-r--r--src/libui_sdl/libui/windows/areadraw.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/windows/areadraw.cpp b/src/libui_sdl/libui/windows/areadraw.cpp
new file mode 100644
index 0000000..7b3dc69
--- /dev/null
+++ b/src/libui_sdl/libui/windows/areadraw.cpp
@@ -0,0 +1,137 @@
+// 8 september 2015
+#include "uipriv_windows.hpp"
+#include "area.hpp"
+
+static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *clip)
+{
+ uiAreaHandler *ah = a->ah;
+ uiAreaDrawParams dp;
+ COLORREF bgcolorref;
+ D2D1_COLOR_F bgcolor;
+ D2D1_MATRIX_3X2_F scrollTransform;
+
+ // no need to save or restore the graphics state to reset transformations; it's handled by resetTarget() in draw.c, called during the following
+ dp.Context = newContext(rt);
+
+ loadAreaSize(a, rt, &(dp.AreaWidth), &(dp.AreaHeight));
+
+ dp.ClipX = clip->left;
+ dp.ClipY = clip->top;
+ dp.ClipWidth = clip->right - clip->left;
+ dp.ClipHeight = clip->bottom - clip->top;
+ if (a->scrolling) {
+ dp.ClipX += a->hscrollpos;
+ dp.ClipY += a->vscrollpos;
+ }
+
+ rt->BeginDraw();
+
+ if (a->scrolling) {
+ ZeroMemory(&scrollTransform, sizeof (D2D1_MATRIX_3X2_F));
+ scrollTransform._11 = 1;
+ scrollTransform._22 = 1;
+ // negative because we want nonzero scroll positions to move the drawing area up/left
+ scrollTransform._31 = -a->hscrollpos;
+ scrollTransform._32 = -a->vscrollpos;
+ rt->SetTransform(&scrollTransform);
+ }
+
+ // TODO push axis aligned clip
+
+ // TODO only clear the clip area
+ // TODO clear with actual background brush
+ bgcolorref = GetSysColor(COLOR_BTNFACE);
+ bgcolor.r = ((float) GetRValue(bgcolorref)) / 255.0;
+ // due to utter apathy on Microsoft's part, GetGValue() does not work with MSVC's Run-Time Error Checks
+ // it has not worked since 2008 and they have *never* fixed it
+ // TODO now that -RTCc has just been deprecated entirely, should we switch back?
+ bgcolor.g = ((float) ((BYTE) ((bgcolorref & 0xFF00) >> 8))) / 255.0;
+ bgcolor.b = ((float) GetBValue(bgcolorref)) / 255.0;
+ bgcolor.a = 1.0;
+ rt->Clear(&bgcolor);
+
+ (*(ah->Draw))(ah, a, &dp);
+
+ freeContext(dp.Context);
+
+ // TODO pop axis aligned clip
+
+ return rt->EndDraw(NULL, NULL);
+}
+
+static void onWM_PAINT(uiArea *a)
+{
+ RECT clip;
+ HRESULT hr;
+
+ // do not clear the update rect; we do that ourselves in doPaint()
+ if (GetUpdateRect(a->hwnd, &clip, FALSE) == 0) {
+ // set a zero clip rect just in case GetUpdateRect() didn't change clip
+ clip.left = 0;
+ clip.top = 0;
+ clip.right = 0;
+ clip.bottom = 0;
+ }
+ hr = doPaint(a, a->rt, &clip);
+ switch (hr) {
+ case S_OK:
+ if (ValidateRect(a->hwnd, NULL) == 0)
+ logLastError(L"error validating rect");
+ break;
+ case D2DERR_RECREATE_TARGET:
+ // DON'T validate the rect
+ // instead, simply drop the render target
+ // we'll get another WM_PAINT and make the render target again
+ // TODO would this require us to invalidate the entire client area?
+ a->rt->Release();;
+ a->rt = NULL;
+ break;
+ default:
+ logHRESULT(L"error painting", hr);
+ }
+}
+
+static void onWM_PRINTCLIENT(uiArea *a, HDC dc)
+{
+ ID2D1DCRenderTarget *rt;
+ RECT client;
+ HRESULT hr;
+
+ uiWindowsEnsureGetClientRect(a->hwnd, &client);
+ rt = makeHDCRenderTarget(dc, &client);
+ hr = doPaint(a, rt, &client);
+ if (hr != S_OK)
+ logHRESULT(L"error printing uiArea client area", hr);
+ rt->Release();
+}
+
+BOOL areaDoDraw(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
+{
+ switch (uMsg) {
+ case WM_PAINT:
+ onWM_PAINT(a);
+ *lResult = 0;
+ return TRUE;
+ case WM_PRINTCLIENT:
+ onWM_PRINTCLIENT(a, (HDC) wParam);
+ *lResult = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// TODO only if the render target wasn't just created?
+void areaDrawOnResize(uiArea *a, RECT *newClient)
+{
+ D2D1_SIZE_U size;
+
+ size.width = newClient->right - newClient->left;
+ size.height = newClient->bottom - newClient->top;
+ // don't track the error; we'll get that in EndDraw()
+ // see https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx
+ a->rt->Resize(&size);
+
+ // according to Rick Brewster, we must always redraw the entire client area after calling ID2D1RenderTarget::Resize() (see http://stackoverflow.com/a/33222983/3408572)
+ // we used to have a uiAreaHandler.RedrawOnResize() method to decide this; now you know why we don't anymore
+ invalidateRect(a->hwnd, NULL, TRUE);
+}