diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2019-01-05 22:07:51 +0100 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2019-01-05 22:07:51 +0100 |
| commit | db2f529599cea4c86481ed6ca650a5b069c003b0 (patch) | |
| tree | 7f7f6c3449d8811fdf68f28f761efcc9fa4e9b9d /alf/alf.cpp | |
| parent | cd7552ae1ce7f6c92d03b7d0a83fe4aec073aeff (diff) | |
move layout into own file, implement expand flag
Diffstat (limited to 'alf/alf.cpp')
| -rw-r--r-- | alf/alf.cpp | 318 |
1 files changed, 28 insertions, 290 deletions
diff --git a/alf/alf.cpp b/alf/alf.cpp index 03c0fbf..5ee591d 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -10,8 +10,8 @@ ALF_InitializeWindowPriv(HWND hwnd, ALFWindowPriv *priv, void *closure) priv->vtbl = (ALFWindowVTable*)GetClassLongPtr(hwnd, 0); priv->app = (ALFAPP)GetClassLongPtr(hwnd, sizeof(void*)); priv->closure = closure; - ALF_ListInit(&priv->widgets); priv->defid = (WORD)-1; + ALF_Layout_Init(&priv->layout); } static void @@ -20,10 +20,7 @@ ALF_DestroyWindowPriv(ALFWindowPriv *priv) if (priv->vtbl->postdestroy) priv->vtbl->postdestroy(priv->closure); - ALF_FOR_LIST(ALFWidgetPriv, list, &priv->widgets, w) { - HeapFree(GetProcessHeap(), 0, w); - } - ALF_ListInit(&priv->widgets); + ALF_Layout_Clear(&priv->layout); if (priv->fonts.hMessageFont) DeleteObject(priv->fonts.hMessageFont); @@ -39,18 +36,6 @@ ALF_CentipointsToPxPriv(ALFWindowPriv *priv, int cptValue) return MulDiv(cptValue, priv->fonts.dpi, 7200); } -static void -ALF_UpdateFontForWidget(ALFWindowPriv *priv, ALFWidgetPriv *widget) -{ - if (widget->hwnd && (widget->flags & ALF_MESSAGEFONT) == ALF_MESSAGEFONT) { - SendMessage(widget->hwnd, WM_SETFONT, (WPARAM)priv->fonts.hMessageFont, (LPARAM)NULL); - - // XXX: Invalidating should IMHO be the decision of the control, but at - // least the commctl32 V5 static control doesn't do it. - InvalidateRect(widget->hwnd, NULL, TRUE); - } -} - void ALF_UpdateFonts(HWND win) { @@ -89,9 +74,7 @@ ALF_UpdateFontsPriv(HWND win, ALFWindowPriv *priv) priv->fonts.hMessageFont = CreateFontIndirect(&priv->fonts.lfMessageFont); } - ALF_FOR_LIST(ALFWidgetPriv, list, &priv->widgets, i) { - ALF_UpdateFontForWidget(priv, i); - } + ALF_Layout_UpdateFonts(&priv->layout, win, &priv->fonts); if (priv->vtbl->updatefonts) { priv->vtbl->updatefonts(priv->closure, win, &priv->fonts); @@ -107,264 +90,6 @@ ALF_RecalculateLayout(HWND hwnd) } static void -ALF_CalculateSizes(ALFWindowPriv *win) -{ - for (int i = 0; i < win->layout.nColumns; ++i) { - ZeroMemory(&win->layout.columns[i], sizeof(win->layout.columns[i])); - } - for (int i = 0; i < win->layout.nRows; ++i) { - ZeroMemory(&win->layout.rows[i], sizeof(win->layout.rows[i])); - } - - ALF_FOR_LIST(ALFWidgetPriv, list, &win->widgets, c) { - while ((int)c->x >= win->layout.nColumns) { - // FIXME! overflow, use reallocarray(2) equivalent - if (win->layout.nColumns == 0) { - win->layout.nColumns = 1; - win->layout.columns = (ALFRowOrColumn*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, win->layout.nColumns*sizeof(win->layout.columns[0])); - } else { - win->layout.nColumns *= 2; - win->layout.columns = (ALFRowOrColumn*)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, win->layout.columns, win->layout.nColumns*sizeof(win->layout.columns[0])); - } - } - while ((int)c->y >= win->layout.nRows) { - // FIXME! overflow, use reallocarray(2) equivalent - if (win->layout.nRows == 0) { - win->layout.nRows = 1; - win->layout.rows = (ALFRowOrColumn*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, win->layout.nRows*sizeof(win->layout.rows[0])); - } else { - win->layout.nRows *= 2; - win->layout.rows = (ALFRowOrColumn*)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, win->layout.rows, win->layout.nRows*sizeof(win->layout.rows[0])); - } - } - - // TODO: ignore spanning cell - - SIZE qs = { ALF_CentipointsToPxPriv(win, c->cptWidth), - ALF_CentipointsToPxPriv(win, c->cptHeight) }; - if ((c->flags & ALF_QUERYSIZE) == ALF_QUERYSIZE) { - SendMessage(c->hwnd, ALF_WM_QUERYSIZE, 0, (LPARAM)&qs); - } - - qs.cx += ALF_CentipointsToPxPriv(win, c->cptMarginLeft); - qs.cx += ALF_CentipointsToPxPriv(win, c->cptMarginRight); - qs.cy += ALF_CentipointsToPxPriv(win, c->cptMarginTop); - qs.cy += ALF_CentipointsToPxPriv(win, c->cptMarginBottom); - - if (qs.cx > win->layout.columns[c->x].minWidth) - win->layout.columns[c->x].minWidth = qs.cx; - if (qs.cy > win->layout.rows[c->y].minWidth) - win->layout.rows[c->y].minWidth = qs.cy; - - // TODO: expand flag - } - - // TODO: second pass for spanning cells - - // update min width bookkeeping - win->layout.totalMinWidth = 0; - win->layout.occupiedColumnCount = 0; - for (int i = 0; i < win->layout.nColumns; ++i) { - if (win->layout.columns[i].minWidth > 0) { - win->layout.totalMinWidth += win->layout.columns[i].minWidth; - win->layout.occupiedColumnCount++; - // TODO: expand flag - } - } - win->layout.totalMinHeight = 0; - win->layout.occupiedRowCount = 0; - for (int i = 0; i < win->layout.nRows; ++i) { - if (win->layout.rows[i].minWidth > 0) { - win->layout.totalMinHeight += win->layout.rows[i].minWidth; - win->layout.occupiedRowCount++; - // TODO: expand flag - } - } - - // TODO: split here into allocation function -} - -static void -ALF_ApplyLayout(HWND hwnd, ALFWindowPriv *win) -{ - // allocate cell positions - // distribute free space - int extraWidth = 0; - int extraHeight = 0; - RECT client; - if (GetClientRect(hwnd, &client)) { - if (client.right - client.left > win->layout.totalMinWidth) - extraWidth = client.right - client.left - win->layout.totalMinWidth; - if (client.bottom - client.top > win->layout.totalMinHeight) - extraHeight = client.bottom - client.top - win->layout.totalMinHeight; - } - - int extraWidthPart = 0; - int extraWidthError = 0; - if (win->layout.occupiedColumnCount) { - extraWidthPart = extraWidth / win->layout.occupiedColumnCount; - extraWidthError = extraWidth - extraWidthPart * win->layout.occupiedColumnCount; - } - - for (int i = 0; i < win->layout.nColumns; ++i) { - win->layout.columns[i].allocatedWidth = win->layout.columns[i].minWidth; - - if (win->layout.columns[i].minWidth > 0) { - win->layout.columns[i].allocatedWidth += extraWidthPart; - if (extraWidthError) { - win->layout.columns[i].allocatedWidth++; - extraWidthError--; - } - } - - if (i == 0) { - win->layout.columns[i].allocatedPosition = 0; - } else { - win->layout.columns[i].allocatedPosition = - win->layout.columns[i-1].allocatedPosition + win->layout.columns[i-1].allocatedWidth; - } - } - - - int extraHeightPart = 0; - int extraHeightError = 0; - if (win->layout.occupiedRowCount) { - extraHeightPart = extraHeight / win->layout.occupiedRowCount; - extraHeightError = extraHeight - extraHeightPart * win->layout.occupiedRowCount; - } - - for (int i = 0; i < win->layout.nRows; ++i) { - win->layout.rows[i].allocatedWidth = win->layout.rows[i].minWidth; - - if (win->layout.rows[i].minWidth > 0) { - win->layout.rows[i].allocatedWidth += extraHeightPart; - if (extraHeightError) { - win->layout.rows[i].allocatedWidth++; - extraHeightError--; - } - } - - if (i == 0) { - win->layout.rows[i].allocatedPosition = 0; - } else { - win->layout.rows[i].allocatedPosition = - win->layout.rows[i-1].allocatedPosition + win->layout.rows[i-1].allocatedWidth; - } - } - - HDWP hdwp = BeginDeferWindowPos(win->layout.occupiedColumnCount * win->layout.occupiedRowCount); - - ALF_FOR_LIST(ALFWidgetPriv, list, &win->widgets, c) { - if ((int)c->x >= win->layout.nColumns || (int)c->y >= win->layout.nRows) - continue; - - int marginleft = ALF_CentipointsToPxPriv(win, c->cptMarginLeft); - int marginright = ALF_CentipointsToPxPriv(win, c->cptMarginRight); - int margintop = ALF_CentipointsToPxPriv(win, c->cptMarginTop); - int marginbottom = ALF_CentipointsToPxPriv(win, c->cptMarginBottom); - - RECT r = { 0,0,0,0 }; - r.left = win->layout.columns[c->x].allocatedPosition + marginleft; - r.right = r.left + win->layout.columns[c->x].allocatedWidth - marginleft - marginright; - r.top = win->layout.rows[c->y].allocatedPosition + margintop; - r.bottom = r.top + win->layout.rows[c->y].allocatedWidth - margintop - marginbottom; - - if (c->flags & ALF_APPLYSIZE) { - hdwp = (HDWP)SendMessage(c->hwnd, ALF_WM_APPLYSIZE, (WPARAM)hdwp, (LPARAM)&r); - } else { - hdwp = DeferWindowPos(hdwp, - c->hwnd, 0, - r.left, r.top, r.right - r.left, r.bottom - r.top, - SWP_NOACTIVATE | SWP_NOZORDER); - } - } - - EndDeferWindowPos(hdwp); -} - -static void -ALF_InternalAddWidget(HWND hwnd, ALFWindowPriv *priv, ALFWidgetLayoutParams *params) -{ - ALFWidgetPriv *w = (ALFWidgetPriv*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, sizeof(ALFWidgetPriv)); - w->hwnd = params->hwnd; - w->x = params->x; - w->y = params->y; - w->cptWidth = params->width; - w->cptHeight = params->height; - w->flags = params->flags; - w->cptMarginTop = params->margins[0]; - w->cptMarginRight = params->margins[1]; - w->cptMarginBottom = params->margins[2]; - w->cptMarginLeft = params->margins[3]; - - if (GetParent(w->hwnd) != hwnd) - SetParent(w->hwnd, hwnd); - - // TODO: QUERYUISTATE on parent, then replicate in child. But wait, XP appears to do this automatically!?? - - ALF_ListInsert(priv->widgets.prev, &w->list); - ALF_UpdateFontForWidget(priv, w); -} - -static BOOL -ALF_InternalSetLayoutParams(ALFWindowPriv *priv, HWND widget, const ALFWidgetLayoutParams *params) -{ - ALF_FOR_LIST(ALFWidgetPriv, list, &priv->widgets, w) { - if (w->hwnd == widget) { - w->hwnd = params->hwnd; - w->x = params->x; - w->y = params->y; - w->cptWidth = params->width; - w->cptHeight = params->height; - w->flags = params->flags; - w->cptMarginTop = params->margins[0]; - w->cptMarginRight = params->margins[1]; - w->cptMarginBottom = params->margins[2]; - w->cptMarginLeft = params->margins[3]; - - return TRUE; - } - } - - return FALSE; -} - -static BOOL -ALF_InternalGetLayoutParams(ALFWindowPriv *priv, HWND widget, ALFWidgetLayoutParams *params) -{ - ALF_FOR_LIST(ALFWidgetPriv, list, &priv->widgets, w) { - if (w->hwnd == widget) { - params->hwnd = w->hwnd; - params->x = w->x; - params->y = w->y; - params->width = w->cptWidth; - params->height = w->cptHeight; - params->flags = w->flags; - params->margins[0] = w->cptMarginTop; - params->margins[1] = w->cptMarginRight; - params->margins[2] = w->cptMarginBottom; - params->margins[3] = w->cptMarginLeft; - - return TRUE; - } - } - - return FALSE; -} - -static HWND -ALF_InternalGetWidgetAtPos(ALFWindowPriv *priv, UINT x, UINT y) -{ - ALF_FOR_LIST(ALFWidgetPriv, list, &priv->widgets, w) { - if (w->x == x && w->y == y) { - return w->hwnd; - } - } - - return NULL; -} - -static void ALF_ApplyFocus(HWND hwnd, ALFWindowPriv *priv, BOOL restoringFocus) { if (priv->hwndFocus) { @@ -386,7 +111,7 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) ALFWindowPriv *priv = (ALFWindowPriv*)GetWindowLongPtr(hwnd, 0); if (msg == ALF_WM_QUERYSIZE) { - ALF_CalculateSizes(priv); + ALF_Layout_CalcSizes(&priv->layout, hwnd); SIZE *ps = (SIZE*)lparam; ps->cx = priv->layout.totalMinWidth; ps->cy = priv->layout.totalMinHeight; @@ -394,7 +119,7 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } if (msg == ALF_WM_APPLYLAYOUT) { - ALF_ApplyLayout(hwnd, priv); + ALF_Layout_Apply(&priv->layout, hwnd); return 0; } @@ -411,20 +136,20 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } if (msg == ALF_WM_ADDWIDGET) { - ALF_InternalAddWidget(hwnd, priv, (ALFWidgetLayoutParams *)lparam); + ALF_Layout_AddWidget(&priv->layout, hwnd, (ALFWidgetLayoutParams *)lparam); return 0; } if (msg == ALF_WM_GETLAYOUTPARAMS) { - return (LRESULT)ALF_InternalGetLayoutParams(priv, (HWND)wparam, (ALFWidgetLayoutParams *)lparam); + return (LRESULT)ALF_Layout_GetWidgetParams(&priv->layout, (ALFWidgetLayoutParams *)lparam, (HWND)wparam); } if (msg == ALF_WM_SETLAYOUTPARAMS) { - return (LRESULT)ALF_InternalSetLayoutParams(priv, (HWND)wparam, (const ALFWidgetLayoutParams *)lparam); + return (LRESULT)ALF_Layout_SetWidgetParams(&priv->layout, (const ALFWidgetLayoutParams *)lparam, (HWND)wparam); } if (msg == ALF_WM_GETWIDGETATPOS) { - return (LRESULT)ALF_InternalGetWidgetAtPos(priv, ((UINT*)lparam)[0], ((UINT*)lparam)[1]); + return (LRESULT)ALF_Layout_WidgetAtPos(&priv->layout, ((UINT*)lparam)[0], ((UINT*)lparam)[1]); } if (msg == ALF_WM_SETFOCUS) { @@ -442,6 +167,11 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) return 0; } + if (msg == ALF_WM_GETWINDOWFONTS) { + *((ALFWindowFonts *)lparam) = priv->fonts; + return TRUE; + } + if (msg == WM_COMMAND) { HWND source = (HWND)lparam; WORD code = HIWORD(wparam); @@ -481,7 +211,7 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } if (msg == WM_SIZE) { - ALF_ApplyLayout(hwnd, priv); + ALF_Layout_Apply(&priv->layout, hwnd); return 0; } @@ -514,8 +244,8 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) SendMessage(hwnd, WM_UPDATEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0); } ALF_UpdateFontsPriv(hwnd, priv); - ALF_CalculateSizes(priv); - ALF_ApplyLayout(hwnd, priv); + ALF_Layout_CalcSizes(&priv->layout, hwnd); + ALF_Layout_Apply(&priv->layout, hwnd); } if (msg == WM_DESTROY && priv->vtbl->destroy) { @@ -537,15 +267,15 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) if (msg == WM_DPICHANGED) { ALF_UpdateFontsPriv(hwnd, priv); - ALF_CalculateSizes(priv); + ALF_Layout_CalcSizes(&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_CalculateSizes(priv); - ALF_ApplyLayout(hwnd, priv); + ALF_Layout_CalcSizes(&priv->layout, hwnd); + ALF_Layout_Apply(&priv->layout, hwnd); } if (msg == DM_GETDEFID) { @@ -979,3 +709,11 @@ ALF_WidgetAtLayoutPosition(HWND parent, UINT x, UINT y) return (HWND)SendMessage(parent, ALF_WM_GETWIDGETATPOS, 0, (LPARAM)&xy); } + + +BOOL +ALF_WindowFonts(HWND window, ALFWindowFonts *fonts) +{ + return (BOOL)SendMessage(window, ALF_WM_GETWINDOWFONTS, 0, (LPARAM)fonts); +} + |
