summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Kümmerlin <jonas@kuemmerlin.eu>2020-04-16 13:12:32 +0200
committerJonas Kümmerlin <jonas@kuemmerlin.eu>2020-04-16 13:12:32 +0200
commit5cbb664bd49cd2b9c035ccfc3024aa436d28c36c (patch)
treee7f83c28b89b8597d38a6b5664ba2ff0afee852e
parentfc7b721e12b6a07cb2b6566c196b9a6c4265c2af (diff)
layout: invalidate and recalculate, automatically
-rw-r--r--alf/alf.cpp35
-rw-r--r--alf/alf.h10
-rw-r--r--alf/alfbutton.cpp4
-rw-r--r--alf/alfcombobox.cpp3
-rw-r--r--alf/alfedit.cpp2
-rw-r--r--alf/alflabel.cpp52
-rw-r--r--alf/alflayout.cpp82
-rw-r--r--alf/alflayout.h14
-rw-r--r--alf/alfnotebook.cpp7
-rw-r--r--widgetfactory.cpp1
10 files changed, 159 insertions, 51 deletions
diff --git a/alf/alf.cpp b/alf/alf.cpp
index 77fe344..f914e55 100644
--- a/alf/alf.cpp
+++ b/alf/alf.cpp
@@ -75,11 +75,9 @@ ALF_UpdateFontsPriv(HWND win, ALFWindowPriv *priv)
}
void
-ALF_RecalculateLayout(HWND hwnd)
+ALF_InvalidateLayout(HWND hwnd)
{
- SIZE dummy;
- SendMessage(hwnd, ALF_WM_QUERYSIZE, 0, (LPARAM)&dummy);
- SendMessage(hwnd, ALF_WM_APPLYLAYOUT, 0, 0);
+ SendMessage(hwnd, ALF_WM_INVALIDATELAYOUT, 0, 0);
}
static void
@@ -230,11 +228,21 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
ALF_Layout_Apply(&priv->layout, hwnd);
}
+ if (msg == WM_SHOWWINDOW) {
+ if (wparam)
+ ALF_Layout_Validate(&priv->layout, hwnd);
+ }
+
if (msg == WM_GETMINMAXINFO) {
RECT tmp;
ZeroMemory(&tmp, sizeof(tmp));
- tmp.right = priv->layout.totalMinWidth;
- tmp.bottom = priv->layout.totalMinHeight;
+
+ SIZE s;
+ ZeroMemory(&s, sizeof(s));
+ ALF_Layout_GetMinSize(&priv->layout, hwnd, &s);
+
+ tmp.right = s.cx;
+ tmp.bottom = s.cy;
if (ALF_Compat_AdjustWindowRectExForDpi(
&tmp,
@@ -259,7 +267,6 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
SendMessage(hwnd, WM_UPDATEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0);
}
ALF_UpdateFontsPriv(hwnd, priv);
- ALF_Layout_CalcSizes(&priv->layout, hwnd);
ALF_Layout_Apply(&priv->layout, hwnd);
}
@@ -282,15 +289,14 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
if (msg == WM_DPICHANGED) {
ALF_UpdateFontsPriv(hwnd, priv);
- ALF_Layout_CalcSizes(&priv->layout, hwnd);
+ ALF_Layout_Invalidate(&priv->layout, hwnd);
RECT *r = (RECT*)lparam;
SetWindowPos(hwnd, NULL, r->left, r->top, r->right-r->left, r->bottom-r->top, SWP_NOACTIVATE|SWP_NOZORDER);
}
if (msg == WM_THEMECHANGED || msg == WM_SETTINGCHANGE) {
ALF_UpdateFontsPriv(hwnd, priv);
- ALF_Layout_CalcSizes(&priv->layout, hwnd);
- ALF_Layout_Apply(&priv->layout, hwnd);
+ ALF_Layout_Invalidate(&priv->layout, hwnd);
}
if (msg == DM_GETDEFID) {
@@ -318,6 +324,15 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
LRESULT ret = 0;
if (ALF_Layout_HandleMessage(&priv->layout, hwnd, msg, wparam, lparam, &ret)) {
+ // if the layout was changed, our current size might be too small
+ // windows will call WM_GETMINMAXINFO and fix it
+ if (msg == ALF_WM_VALIDATELAYOUT) {
+ RECT r;
+ if (GetWindowRect(hwnd, &r)) {
+ SetWindowPos(hwnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
+ }
+ }
+
return ret;
}
diff --git a/alf/alf.h b/alf/alf.h
index d98dfef..a429472 100644
--- a/alf/alf.h
+++ b/alf/alf.h
@@ -61,6 +61,8 @@ typedef struct {
#define ALF_WM_SETLAYOUTPARAMS (ALF_WM__BASE + 14)
#define ALF_WM_GETWIDGETATPOS (ALF_WM__BASE + 15)
#define ALF_WM_PRETRANSLATEMSG (ALF_WM__BASE + 16)
+#define ALF_WM_INVALIDATELAYOUT (ALF_WM__BASE + 17)
+#define ALF_WM_VALIDATELAYOUT (ALF_WM__BASE + 18)
#define ALF_WM_LBL_GETSTYLE (ALF_WM__BASE + 201)
#define ALF_WM_LBL_SETSTYLE (ALF_WM__BASE + 202)
@@ -155,15 +157,11 @@ HWND
ALF_WidgetHwndById(HWND win, WORD id);
void
-ALF_RecalculateLayout(HWND win);
+ALF_InvalidateLayout(HWND win);
// Recalculates the window's DPI and all fonts and applies them to child widgets.
// ALF does this automatically on a DPI or settings change so you shouldn't have
-// to call ALF_UpdateFonts(). If you have added new widgets and want to set their
-// fonts, call ALF_ApplyFonts() instead.
-//
-// Since widget sizes depend on the assigned font, you should probably
-// call ALF_RecalculateLayout() afterwards.
+// to call ALF_UpdateFonts().
void
ALF_UpdateFonts(HWND win);
diff --git a/alf/alfbutton.cpp b/alf/alfbutton.cpp
index 582a90c..be9a276 100644
--- a/alf/alfbutton.cpp
+++ b/alf/alfbutton.cpp
@@ -475,6 +475,10 @@ ALF__ButtonSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT
ALF_Compat_RemoveWindowSubclass(hwnd, ALF__ButtonSubclassProc, 0);
} else if (uMsg == WM_ERASEBKGND) {
return TRUE;
+ } else if (uMsg == WM_SETTEXT) {
+ ALF_InvalidateLayout(GetParent(hwnd));
+ } else if (uMsg == WM_SETFONT) {
+ ALF_InvalidateLayout(GetParent(hwnd));
}
return ALF_Compat_DefSubclassProc(hwnd, uMsg, wParam, lParam);
diff --git a/alf/alfcombobox.cpp b/alf/alfcombobox.cpp
index 097e2a4..288e3a8 100644
--- a/alf/alfcombobox.cpp
+++ b/alf/alfcombobox.cpp
@@ -74,6 +74,7 @@ ALF__ComboWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
if (uMsg == WM_SETTEXT && hwndChild) {
SetWindowText(hwndChild, (TCHAR*)lParam);
+ ALF_InvalidateLayout(GetParent(hwnd));
}
if (uMsg == WM_GETTEXTLENGTH && hwndChild) {
return (LRESULT)GetWindowTextLength(hwndChild);
@@ -88,6 +89,8 @@ ALF__ComboWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (h)
SendMessage(hwndChild, CB_SETITEMHEIGHT, (WPARAM)0, h);
+ ALF_InvalidateLayout(GetParent(hwnd));
+
return 0;
}
if (uMsg == WM_GETFONT && hwndChild) {
diff --git a/alf/alfedit.cpp b/alf/alfedit.cpp
index c352a8b..ac12e38 100644
--- a/alf/alfedit.cpp
+++ b/alf/alfedit.cpp
@@ -44,6 +44,8 @@ ALF__EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_P
SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
} else if (uMsg == WM_DESTROY) {
ALF_Compat_RemoveWindowSubclass(hwnd, ALF__EditSubclassProc, 0);
+ } else if (uMsg == WM_SETFONT) {
+ ALF_InvalidateLayout(GetParent(hwnd));
}
return ALF_Compat_DefSubclassProc(hwnd, uMsg, wParam, lParam);
diff --git a/alf/alflabel.cpp b/alf/alflabel.cpp
index fd2cab7..f400f4f 100644
--- a/alf/alflabel.cpp
+++ b/alf/alflabel.cpp
@@ -69,6 +69,7 @@ ALF__LabelWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return TRUE;
} else if (uMsg == WM_SETTEXT) {
InvalidateRect(hwnd, NULL, TRUE);
+ ALF_InvalidateLayout(GetParent(hwnd));
} else if (uMsg == WM_GETDLGCODE) {
return DLGC_STATIC;
} else if (uMsg == WM_SETFONT) {
@@ -76,6 +77,8 @@ ALF__LabelWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (LOWORD(lParam) != 0)
InvalidateRect(hwnd, NULL, TRUE);
+ ALF_InvalidateLayout(GetParent(hwnd));
+
return 0;
} else if (uMsg == WM_GETFONT) {
return (LRESULT)priv->font;
@@ -167,40 +170,39 @@ ALF__LabelWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return TRUE;
} else if (uMsg == ALF_WM_QUERYSIZE) {
- HDC hdcLabel = GetDC(hwnd);
- HFONT oldFont = 0;
- if (priv->font)
- oldFont = SelectFont(hdcLabel, priv->font);
+ int textlen = GetWindowTextLength(hwnd);
+ SIZE *pSize = (SIZE*)(void*)lParam;
+ if (textlen) {
+ HDC hdcLabel = GetDC(hwnd);
+ HFONT oldFont = SelectFont(hdcLabel, priv->font);
- // calc drawtext style
- UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT;
+ // calc drawtext style
+ UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT;
- RECT r = { 0, 0, 100, 100 };
+ RECT r = { 0, 0, 100, 100 };
- int textlen = GetWindowTextLength(hwnd);
- TCHAR *textbuf = ALF_New(TCHAR, textlen + 1);
- GetWindowText(hwnd, textbuf, textlen+1);
+ TCHAR *textbuf = ALF_New(TCHAR, textlen + 1);
+ GetWindowText(hwnd, textbuf, textlen+1);
- DrawText(hdcLabel, textbuf, -1, &r, format);
+ DrawText(hdcLabel, textbuf, -1, &r, format);
- ALF_Free(textbuf);
+ ALF_Free(textbuf);
- SIZE *pSize = (SIZE*)(void*)lParam;
- if (pSize->cx == 0) {
- pSize->cx = r.right - r.left;
- if ((priv->style & ALF_LABEL_HALIGN_MASK) == ALF_LABEL_ALIGN_LEFT_LIKE_EDIT)
- pSize->cx += ALF__LabelLeftPadding(hwnd, hdcLabel);
- }
- if (pSize->cy == 0) {
- pSize->cy = r.bottom - r.top;
- if ((priv->style & ALF_LABEL_VALIGN_MASK) == ALF_LABEL_ALIGN_TOP_LIKE_EDIT)
- pSize->cy += ALF__LabelTopPadding(hwnd);
- }
+ if (pSize->cx == 0) {
+ pSize->cx = r.right - r.left;
+ if ((priv->style & ALF_LABEL_HALIGN_MASK) == ALF_LABEL_ALIGN_LEFT_LIKE_EDIT)
+ pSize->cx += ALF__LabelLeftPadding(hwnd, hdcLabel);
+ }
+ if (pSize->cy == 0) {
+ pSize->cy = r.bottom - r.top;
+ if ((priv->style & ALF_LABEL_VALIGN_MASK) == ALF_LABEL_ALIGN_TOP_LIKE_EDIT)
+ pSize->cy += ALF__LabelTopPadding(hwnd);
+ }
- if (oldFont)
SelectFont(hdcLabel, oldFont);
- ReleaseDC(hwnd, hdcLabel);
+ ReleaseDC(hwnd, hdcLabel);
+ }
} else if (uMsg == WM_DESTROY) {
ALF_Free(priv);
SetWindowLongPtr(hwnd, 0, 0);
diff --git a/alf/alflayout.cpp b/alf/alflayout.cpp
index 0cc6cdf..b98ae93 100644
--- a/alf/alflayout.cpp
+++ b/alf/alflayout.cpp
@@ -1,5 +1,8 @@
#include "alfpriv.h"
+static void
+ALF_Layout_CalcSizes(ALFLayout *layout, HWND window);
+
void
ALF_Layout_Init(ALFLayout *layout)
{
@@ -131,11 +134,16 @@ ALF_Layout_CalcSizes(ALFLayout* layout, HWND window)
}
}
}
+
+ layout->layoutValididityFlags &= ~ALF_LAYOUT_NEED_RECALC;
}
void
ALF_Layout_Apply(ALFLayout* layout, HWND window)
{
+ if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_RECALC)
+ ALF_Layout_CalcSizes(layout, window);
+
// allocate cell positions
// distribute free space
int extraWidth = 0;
@@ -229,6 +237,8 @@ ALF_Layout_Apply(ALFLayout* layout, HWND window)
}
EndDeferWindowPos(hdwp);
+
+ layout->layoutValididityFlags &= ~ALF_LAYOUT_NEED_REAPPLY;
}
void
@@ -254,10 +264,12 @@ ALF_Layout_AddWidget(ALFLayout* layout, HWND window, const ALFWidgetLayoutParams
}
ALF_ListInsert(layout->widgets.prev, &w->list);
+
+ ALF_InvalidateLayout(window);
}
BOOL
-ALF_Layout_SetWidgetParams(ALFLayout* layout, const ALFWidgetLayoutParams* params, HWND widget)
+ALF_Layout_SetWidgetParams(ALFLayout* layout, HWND window, const ALFWidgetLayoutParams* params, HWND widget)
{
ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) {
if (w->hwnd == widget) {
@@ -272,6 +284,11 @@ ALF_Layout_SetWidgetParams(ALFLayout* layout, const ALFWidgetLayoutParams* param
w->cptMarginBottom = params->margins[2];
w->cptMarginLeft = params->margins[3];
+ if (w->flags & ALF_INHERITFONT)
+ SendMessage(w->hwnd, WM_SETFONT, (WPARAM)SendMessage(window, WM_GETFONT, 0, 0), 0);
+
+ ALF_InvalidateLayout(window);
+
return TRUE;
}
}
@@ -314,6 +331,51 @@ ALF_Layout_WidgetAtPos(ALFLayout* layout, UINT x, UINT y)
return NULL;
}
+void
+ALF_Layout_Invalidate(ALFLayout *layout, HWND window)
+{
+ if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_RECALC)
+ return;
+
+ layout->layoutValididityFlags |= ALF_LAYOUT_NEED_RECALC | ALF_LAYOUT_NEED_REAPPLY;
+
+ HWND parent = GetParent(window);
+ if (parent) {
+ ALF_InvalidateLayout(parent);
+ } else {
+ PostMessage(window, ALF_WM_VALIDATELAYOUT, 0, 0);
+ }
+}
+
+
+BOOL
+ALF_Layout_Validate(ALFLayout *layout, HWND window)
+{
+ BOOL ret = FALSE;
+
+ if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_RECALC) {
+ ALF_Layout_CalcSizes(layout, window);
+ ret = TRUE;
+ }
+
+ if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_REAPPLY) {
+ ALF_Layout_Apply(layout, window);
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+void
+ALF_Layout_GetMinSize(ALFLayout *layout, HWND window, SIZE *size)
+{
+ if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_RECALC) {
+ ALF_Layout_CalcSizes(layout, window);
+ }
+
+ size->cx = layout->totalMinWidth;
+ size->cy = layout->totalMinHeight;
+}
BOOL
ALF_Layout_HandleMessage(ALFLayout *layout, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LRESULT *pRet)
@@ -321,10 +383,7 @@ ALF_Layout_HandleMessage(ALFLayout *layout, HWND hwnd, UINT msg, WPARAM wparam,
*pRet = 0;
if (msg == ALF_WM_QUERYSIZE) {
- ALF_Layout_CalcSizes(layout, hwnd);
- SIZE *ps = (SIZE*)lparam;
- ps->cx = layout->totalMinWidth;
- ps->cy = layout->totalMinHeight;
+ ALF_Layout_GetMinSize(layout, hwnd, (SIZE*)lparam);
return TRUE;
}
@@ -344,7 +403,7 @@ ALF_Layout_HandleMessage(ALFLayout *layout, HWND hwnd, UINT msg, WPARAM wparam,
}
if (msg == ALF_WM_SETLAYOUTPARAMS) {
- *pRet = (LRESULT)ALF_Layout_SetWidgetParams(layout, (const ALFWidgetLayoutParams *)lparam, (HWND)wparam);
+ *pRet = (LRESULT)ALF_Layout_SetWidgetParams(layout, hwnd, (const ALFWidgetLayoutParams *)lparam, (HWND)wparam);
return TRUE;
}
@@ -355,7 +414,16 @@ ALF_Layout_HandleMessage(ALFLayout *layout, HWND hwnd, UINT msg, WPARAM wparam,
if (msg == WM_SETFONT) {
ALF_Layout_ForwardFont(layout, hwnd, (HFONT)wparam, lparam);
- *pRet = 0;
+ return TRUE;
+ }
+
+ if (msg == ALF_WM_INVALIDATELAYOUT) {
+ ALF_Layout_Invalidate(layout, hwnd);
+ return TRUE;
+ }
+
+ if (msg == ALF_WM_VALIDATELAYOUT) {
+ ALF_Layout_Validate(layout, hwnd);
return TRUE;
}
diff --git a/alf/alflayout.h b/alf/alflayout.h
index c279afa..e326490 100644
--- a/alf/alflayout.h
+++ b/alf/alflayout.h
@@ -24,6 +24,9 @@ typedef struct {
int expand : 1;
} ALFLayoutRowOrColumn;
+#define ALF_LAYOUT_NEED_RECALC ((DWORD)1)
+#define ALF_LAYOUT_NEED_REAPPLY ((DWORD)2)
+
typedef struct {
ALFListHeader widgets;
ALFLayoutRowOrColumn *columns;
@@ -34,6 +37,7 @@ typedef struct {
int totalMinHeight;
int expandoColumnCount;
int expandoRowCount;
+ DWORD layoutValididityFlags;
} ALFLayout;
void
@@ -43,7 +47,7 @@ void
ALF_Layout_Clear(ALFLayout *layout);
void
-ALF_Layout_CalcSizes(ALFLayout *layout, HWND window);
+ALF_Layout_GetMinSize(ALFLayout *layout, HWND window, SIZE *size);
void
ALF_Layout_Apply(ALFLayout *layout, HWND window);
@@ -55,7 +59,7 @@ BOOL
ALF_Layout_RemoveWidget(ALFLayout *layout, HWND window, HWND widget, BOOL destroy);
BOOL
-ALF_Layout_SetWidgetParams(ALFLayout *layout, const ALFWidgetLayoutParams *params, HWND widget);
+ALF_Layout_SetWidgetParams(ALFLayout *layout, HWND window, const ALFWidgetLayoutParams *params, HWND widget);
BOOL
ALF_Layout_GetWidgetParams(ALFLayout *layout, ALFWidgetLayoutParams *params, HWND widget);
@@ -65,3 +69,9 @@ ALF_Layout_HandleMessage(ALFLayout *layout, HWND window, UINT msg, WPARAM wparam
HWND
ALF_Layout_WidgetAtPos(ALFLayout *layout, UINT x, UINT y);
+
+void
+ALF_Layout_Invalidate(ALFLayout *layout, HWND window);
+
+BOOL
+ALF_Layout_Validate(ALFLayout *layout, HWND window);
diff --git a/alf/alfnotebook.cpp b/alf/alfnotebook.cpp
index 3b60ba5..25e2904 100644
--- a/alf/alfnotebook.cpp
+++ b/alf/alfnotebook.cpp
@@ -89,6 +89,7 @@ ALF_Notebook_InternalHandleThemeChange(HWND hwndNotebook, ALFNotebookPriv *priv)
priv->hTheme = ALF_Compat_OpenThemeData(hwndNotebook, L"TAB");
InvalidateRect(hwndNotebook, NULL, TRUE);
+ ALF_InvalidateLayout(hwndNotebook);
}
@@ -115,6 +116,8 @@ ALF_Notebook_InternalAddTab(HWND notebook, HWND tabControl, const TCHAR *title)
TabCtrl_InsertItem(tabControl, ALF_Notebook_InternalTabCount(notebook, tabControl), &tie);
ALF_Notebook_InternalHandleTabChange(notebook, tabControl);
+ ALF_InvalidateLayout(notebook);
+
return hwndPanel;
}
@@ -208,6 +211,8 @@ ALF__NotebookWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
HWND p = ALF_Notebook_InternalTabPanel(hwnd, priv->hwndTabCtrl, i);
SendMessage(p, WM_SETFONT, wParam, lParam);
}
+
+ ALF_InvalidateLayout(hwnd);
} else if (uMsg == WM_GETFONT) {
return SendMessage(priv->hwndTabCtrl, WM_GETFONT, wParam, lParam);
} else if (uMsg == ALF_WM_QUERYSIZE) {
@@ -286,6 +291,8 @@ ALF__NotebookWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
EndPaint(hwnd, &ps);
return 0;
+ } else if (uMsg == ALF_WM_INVALIDATELAYOUT) {
+ ALF_InvalidateLayout(GetParent(hwnd));
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
diff --git a/widgetfactory.cpp b/widgetfactory.cpp
index 4de9936..eec3192 100644
--- a/widgetfactory.cpp
+++ b/widgetfactory.cpp
@@ -206,7 +206,6 @@ WinMain
ALF_SetText(hwndTabPanel2, TEXT("Panel Text Demo Test Test Test"));
- ALF_RecalculateLayout(win);
ALF_SetDefaultButton(win, ID_B2);
ALF_ComboBoxSetText(hwndCombo2, TEXT("Goodbye World!"));