summaryrefslogtreecommitdiff
path: root/alf/alf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alf/alf.cpp')
-rw-r--r--alf/alf.cpp318
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);
+}
+