diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-04-30 22:11:34 +0200 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-04-30 22:11:34 +0200 |
| commit | 5a3b46ee43fc601121a85d910d044033d891748f (patch) | |
| tree | 661fafdc6c4c6a99a360e8b101adfa1c1c6ed949 /alf/alfpanel.cpp | |
| parent | d28cd7fb71a6fe56a04d4e21f2b95907a1ec105c (diff) | |
panel: support edge (like delphi)
mainly to force me to implement layout margins
Diffstat (limited to 'alf/alfpanel.cpp')
| -rw-r--r-- | alf/alfpanel.cpp | 110 |
1 files changed, 105 insertions, 5 deletions
diff --git a/alf/alfpanel.cpp b/alf/alfpanel.cpp index 2f2ee68..31c485f 100644 --- a/alf/alfpanel.cpp +++ b/alf/alfpanel.cpp @@ -6,12 +6,16 @@ typedef struct { ALFLayout layout; const ALFPanelVTable *vtbl; void *closure; + DWORD edge; } ALFPanelPriv; +static void ALF_Panel_CalculateContainerMetrics(ALFLayout *layout, HWND hwnd, RECT *margins, SIZE *minSize); + static void ALF_Panel_IntializePriv(ALFPanelPriv *priv) { ALF_Layout_Init(&priv->layout); + priv->layout.calculateContainerMetrics = ALF_Panel_CalculateContainerMetrics; } static void @@ -23,10 +27,17 @@ ALF_Panel_ClearPriv(ALFPanelPriv *priv) static void ALF_Panel_InternalDefPaint(ALFPanelPriv *priv, HWND hwnd, HDC dc, RECT *r) { + RECT r2; + GetClientRect(hwnd, &r2); + if (priv->edge) { + DrawEdge(dc, &r2, priv->edge, BF_ADJUST|BF_RECT); + } + + IntersectRect(&r2, &r2, r); if (priv->layout.bgcolor == ALF_COLOR_TRANSPARENT) { - ALF_Compat_DrawThemeParentBackground(hwnd, dc, r); + ALF_Compat_DrawThemeParentBackground(hwnd, dc, &r2); } else { - ALF_FillRect(dc, r, priv->layout.bgcolor); + ALF_FillRect(dc, &r2, priv->layout.bgcolor); } } @@ -48,13 +59,42 @@ ALF_Panel_Paint(ALFPanelPriv *priv, HWND hwnd, HDC dc, RECT *r) } } +static void +ALF_Panel_InternalSetEdge(ALFPanelPriv *priv, HWND hwnd, DWORD edge) +{ + if (priv->edge == edge) + return; + + priv->edge = edge; + ALF_Layout_Invalidate(&priv->layout, hwnd); + InvalidateRect(hwnd, NULL, TRUE); +} + void -ALF_Panel_SetVTable(HWND panel, const ALFPanelVTable *vtbl, void *closure) +ALF_PanelSetVTable(HWND panel, const ALFPanelVTable *vtbl, void *closure) { ALFPanelSetVtblParams p = { vtbl, closure }; SendMessage(panel, ALF_WM_PANEL_SETVTABLE, 0, (LPARAM)&p); } +static void +ALF_Panel_CalculateContainerMetrics(ALFLayout *layout, HWND hwnd, RECT *margins, SIZE *minSize) +{ + (void)hwnd; + ALFPanelPriv *priv = (ALFPanelPriv *)layout; + + int w = 0; + + if (priv->edge & BDR_INNER) + w++; + + if (priv->edge & BDR_OUTER) + w++; + + margins->left = margins->right = margins->top = margins->bottom = w; + minSize->cx = minSize->cy = 2*w; +} + LRESULT ALF_Panel_DefWindowProc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) { @@ -102,10 +142,58 @@ ALF_Panel_DefWindowProc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) return TRUE; } + if (msg == ALF_WM_PANEL_GETEDGE) { + return (LRESULT)priv->edge; + } + + if (msg == ALF_WM_PANEL_SETEDGE) { + ALF_Panel_InternalSetEdge(priv, window, (DWORD)lparam); + return TRUE; + } + if (ALF_ShouldMessageBubble(window, msg, wparam, lparam)) return SendMessage(GetParent(window), msg, wparam, lparam); if (msg == WM_SIZE) { + // if we have a border, invalidate that (and only that) when resizing + if (priv->edge) { + RECT c; + GetClientRect(window, &c); + + if (c.right > priv->layout.allocatedWidgetRect.right + priv->layout.containerMargins.right) { + // enlarged to the right -> invalidate place occupied by old border + RECT i = { priv->layout.allocatedWidgetRect.right, + 0, + c.right, + c.bottom }; + InvalidateRect(window, &i, TRUE); + } + if (c.bottom > priv->layout.allocatedWidgetRect.bottom + priv->layout.containerMargins.bottom) { + // enlarged to the bottom -> invalidate place occupied by old border + RECT i = { 0, + priv->layout.allocatedWidgetRect.bottom, + c.right, + c.bottom }; + InvalidateRect(window, &i, TRUE); + } + if (c.right < priv->layout.allocatedWidgetRect.right + priv->layout.containerMargins.right) { + // shrunk horizontally -> invalidate place now occupied by new border + RECT i = { c.right - priv->layout.containerMargins.right, + 0, + c.right, + c.bottom }; + InvalidateRect(window, &i, TRUE); + } + if (c.bottom < priv->layout.allocatedWidgetRect.bottom + priv->layout.containerMargins.bottom) { + // shrunk vertically -> invalidate place now ocuupied by new border + RECT i = { 0, + c.bottom - priv->layout.containerMargins.bottom, + c.right, + c.bottom }; + InvalidateRect(window, &i, TRUE); + } + } + ALF_Layout_Apply(&priv->layout, window); } @@ -116,8 +204,20 @@ ALF_Panel_DefWindowProc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) return DefWindowProc(window, msg, wparam, lparam); } +DWORD +ALF_PanelEdge(HWND panel) +{ + return (DWORD)SendMessage(panel, ALF_WM_PANEL_GETEDGE, 0, 0); +} + +void +ALF_PanelSetEdge(HWND panel, DWORD edge) +{ + SendMessage(panel, ALF_WM_PANEL_SETEDGE, 0, (LPARAM)edge); +} + static LRESULT WINAPI -ALF__PanelWindowProc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) +ALF_Panel_WindowProc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) { if (msg == WM_NCCREATE) { ALFPanelPriv *p = ALF_New(ALFPanelPriv, 1); @@ -160,7 +260,7 @@ ALF_RegisterPanelClass(void) cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW); cls.lpszClassName = classNameBuf; cls.cbWndExtra = sizeof(void*); - cls.lpfnWndProc = ALF__PanelWindowProc; + cls.lpfnWndProc = ALF_Panel_WindowProc; ATOM classatom = RegisterClass(&cls); if (!classatom) |
