diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-05-26 18:27:26 +0200 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-05-26 18:27:26 +0200 |
| commit | ffb723122057e30244cab59ea07b18ae71104359 (patch) | |
| tree | f350ca04d4a64d681e98a19c86ca7c5a8369eb98 | |
| parent | 3289498e9dc55cef26f41576f2f765d2b3fe6ad3 (diff) | |
layout: support for spanning cells
mostly untested for now
| -rw-r--r-- | alf/alf.cpp | 19 | ||||
| -rw-r--r-- | alf/alf.h | 8 | ||||
| -rw-r--r-- | alf/alflayout.cpp | 177 | ||||
| -rw-r--r-- | alf/alflayout.h | 3 | ||||
| -rw-r--r-- | widgetfactory.cpp | 12 |
5 files changed, 186 insertions, 33 deletions
diff --git a/alf/alf.cpp b/alf/alf.cpp index 7047e89..717bd18 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -328,6 +328,25 @@ ALF_SetWidgetLayoutPosition(HWND parent, HWND widget, int x, int y) } BOOL +ALF_WidgetLayoutSpan(HWND parent, HWND widget, int *pXspan, int *pYspan) +{ + POINT p = { 0, 0 }; + + LRESULT r = SendMessage(parent, ALF_WM_LYT_GETWDGTSPAN, (WPARAM)widget, (LPARAM)&p); + *pXspan = p.x; + *pYspan = p.y; + return (BOOL)r; +} + +BOOL +ALF_SetWidgetLayoutSpan(HWND parent, HWND widget, int xspan, int yspan) +{ + POINT p = { xspan, yspan }; + return (BOOL)SendMessage(parent, ALF_WM_LYT_SETWDGTSPAN, (WPARAM)widget, (LPARAM)&p); +} + + +BOOL ALF_WidgetLayoutMinSize(HWND parent, HWND widget, int *pWidth, int *pHeight) { SIZE s = { 0, 0 }; @@ -108,6 +108,8 @@ typedef struct { #define ALF_WM_GETTEXTCOLOR (ALF_WM__BASE + 37) #define ALF_WM_SETTEXTCOLOR (ALF_WM__BASE + 38) #define ALF_WM_DPICHANGE (ALF_WM__BASE + 39) +#define ALF_WM_LYT_GETWDGTSPAN (ALF_WM__BASE + 40) +#define ALF_WM_LYT_SETWDGTSPAN (ALF_WM__BASE + 41) #define ALF_WM_LBL_GETSTYLE (ALF_WM__BASE + 201) #define ALF_WM_LBL_SETSTYLE (ALF_WM__BASE + 202) @@ -288,6 +290,12 @@ BOOL ALF_SetWidgetLayoutPosition(HWND parent, HWND widget, int x, int y); BOOL +ALF_WidgetLayoutSpan(HWND parent, HWND widget, int *pXspan, int *pYspan); + +BOOL +ALF_SetWidgetLayoutSpan(HWND parent, HWND widget, int xspan, int yspan); + +BOOL ALF_WidgetLayoutMinSize(HWND parent, HWND widget, int *pWidth, int *pheight); BOOL diff --git a/alf/alflayout.cpp b/alf/alflayout.cpp index 974cd78..a390890 100644 --- a/alf/alflayout.cpp +++ b/alf/alflayout.cpp @@ -297,14 +297,14 @@ ALF_Layout_CalcButtonSize(HWND hwndWindow, ALFLayout *layout, HWND hwndButton, S } static void -ALF_Layout_CalcMinWidgetSize(ALFLayout *layout, ALFWidgetPriv *c, HWND window, SIZE *s) +ALF_Layout_CalcMinWidgetSize(ALFLayout *layout, ALFWidgetPriv *c, HWND window) { if (c->flags & ALF_LAYOUT_SIZE_PX) { - s->cx = c->width; - s->cy = c->height; + c->calculatedSize.cx = c->width; + c->calculatedSize.cy = c->height; } else { - s->cx = ALF_CentipointsToPixels(c->width, layout->dpi); - s->cy = ALF_CentipointsToPixels(c->height, layout->dpi); + c->calculatedSize.cx = ALF_CentipointsToPixels(c->width, layout->dpi); + c->calculatedSize.cy = ALF_CentipointsToPixels(c->height, layout->dpi); } switch (c->flags & ALF_LAYOUT_SIZETYPE_MASK) { @@ -312,16 +312,16 @@ ALF_Layout_CalcMinWidgetSize(ALFLayout *layout, ALFWidgetPriv *c, HWND window, S // already done break; case ALF_LAYOUT_SIZE_QUERY: - SendMessage(c->hwnd, ALF_WM_QUERYSIZE, 0, (LPARAM)s); + SendMessage(c->hwnd, ALF_WM_QUERYSIZE, 0, (LPARAM)&c->calculatedSize); break; case ALF_LAYOUT_SIZE_EDIT: - ALF_Layout_CalcEditSize(window, layout, c->hwnd, s); + ALF_Layout_CalcEditSize(window, layout, c->hwnd, &c->calculatedSize); break; case ALF_LAYOUT_SIZE_CHECKBOX: - ALF_Layout_CalcCheckboxSize(window, layout, c->hwnd, s); + ALF_Layout_CalcCheckboxSize(window, layout, c->hwnd, &c->calculatedSize); break; case ALF_LAYOUT_SIZE_PUSHBUTTON: - ALF_Layout_CalcButtonSize(window, layout, c->hwnd, s); + ALF_Layout_CalcButtonSize(window, layout, c->hwnd, &c->calculatedSize); break; default: // FIXME! unimplemented @@ -367,27 +367,103 @@ ALF_Layout_CalcSizes(ALFLayout* layout, HWND window) } ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, c) { - int col = c->x; // TODO: skip spanning cells - int row = c->y; - - SIZE qs = { 0, 0 }; - ALF_Layout_CalcMinWidgetSize(layout, c, window, &qs); + ALF_Layout_CalcMinWidgetSize(layout, c, window); - if (col < 0 || row < 0) { + if (c->x < 0 || c->y < 0) { if (layout->handleContainerWidgetSize) - layout->handleContainerWidgetSize(layout, window, c->hwnd, &qs); + layout->handleContainerWidgetSize(layout, window, c->hwnd, &c->calculatedSize); } else { - ALF_Layout_EnsureColumnExists(layout, col); - ALF_Layout_EnsureRowExists(layout, row); + if (c->xspan <= 1) { + ALF_Layout_EnsureColumnExists(layout, c->x); + + if (c->calculatedSize.cx > layout->columns[c->x].calculatedMinWidth) + layout->columns[c->x].calculatedMinWidth = c->calculatedSize.cx; + } - if (qs.cx > layout->columns[col].calculatedMinWidth) - layout->columns[col].calculatedMinWidth = qs.cx; - if (qs.cy > layout->rows[row].calculatedMinWidth) - layout->rows[row].calculatedMinWidth = qs.cy; + if (c->yspan <= 1) { + ALF_Layout_EnsureRowExists(layout, c->y); + + if (c->calculatedSize.cy > layout->rows[c->y].calculatedMinWidth) + layout->rows[c->y].calculatedMinWidth = c->calculatedSize.cy; + } } } - // TODO: second pass for spanning cells + // second pass for spanning cells + ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, c) { + if (c->xspan > 1) { + ALF_Layout_EnsureColumnExists(layout, c->x + c->xspan - 1); + + // check for extra size we need to distribute + int xextra = c->calculatedSize.cx; + int xexpandosum = 0; + for (int i = c->x; i < c->x + c->xspan; ++i) { + xextra -= layout->columns[i].calculatedMinWidth; + xexpandosum += layout->columns[i].calculatedExpandNumerator; + } + if (xextra > 0) { + // distribute the extra size based on expand flags + int xextraleft = xextra; + int biggestColumnNo = c->x; + for (int i = c->x; i < c->x + c->xspan; ++i) { + int a; + + if (xexpandosum > 0) + a = MulDiv(xextra, layout->columns[i].calculatedExpandNumerator, xexpandosum); + else + a = MulDiv(xextra, 1, c->xspan); + + if (a > xextraleft) + a = xextraleft; + + layout->columns[i].calculatedMinWidth += a; + xextraleft -= a; + + if (layout->columns[i].calculatedMinWidth > layout->columns[biggestColumnNo].calculatedMinWidth) + biggestColumnNo = i; + } + + if (xextraleft > 0) + layout->columns[biggestColumnNo].calculatedMinWidth += xextraleft; + + } + } + + if (c->yspan > 1) { + ALF_Layout_EnsureRowExists(layout, c->y + c->yspan - 1); + int yextra = c->calculatedSize.cy; + int yexpandosum = 0; + for (int i = c->y; i < c->y + c->yspan; ++i) { + yextra -= layout->rows[i].calculatedMinWidth; + yexpandosum += layout->rows[i].calculatedExpandNumerator; + } + if (yextra > 0) { + // distribute the extra size based on expand flags + int yextraleft = yextra; + int biggestRowNo = c->y; + for (int i = c->y; i < c->y + c->yspan; ++i) { + int a; + + if (yexpandosum > 0) + a = MulDiv(yextra, layout->rows[i].calculatedExpandNumerator, yexpandosum); + else + a = MulDiv(yextra, 1, c->yspan); + + if (a > yextraleft) + a = yextraleft; + + layout->rows[i].calculatedMinWidth += a; + yextraleft -= a; + + if (layout->rows[i].calculatedMinWidth > layout->rows[biggestRowNo].calculatedMinWidth) + biggestRowNo = i; + } + + if (yextraleft > 0) + layout->rows[biggestRowNo].calculatedMinWidth += yextraleft; + } + } + } // total minimum bookkeeping layout->totalMinWidth = 0; @@ -522,7 +598,13 @@ ALF_Layout_Apply(ALFLayout* layout, HWND window) ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, c) { int col = c->x; int row = c->y; - if (col >= layout->nColumns || row >= layout->nRows) + int colspan = c->xspan; + int rowspan = c->yspan; + + if (colspan < 1) colspan = 1; + if (rowspan < 1) rowspan = 1; + + if (col+colspan > layout->nColumns || row+rowspan > layout->nRows) continue; // FIXME: wat? RECT r = { 0,0,0,0 }; @@ -531,9 +613,9 @@ ALF_Layout_Apply(ALFLayout* layout, HWND window) layout->preApplyLayoutToContainerWidget(layout, window, c->hwnd, &r); } else { r.left = layout->columns[col].allocatedPosition; - r.right = r.left + layout->columns[col].allocatedWidth; + r.right = layout->columns[col+colspan-1].allocatedPosition + layout->columns[col+colspan-1].allocatedWidth; r.top = layout->rows[row].allocatedPosition; - r.bottom = r.top + layout->rows[row].allocatedWidth; + r.bottom = layout->rows[row+rowspan-1].allocatedPosition + layout->rows[row+rowspan-1].allocatedWidth; } if (c->flags & ALF_LAYOUT_CUSTOMPOS) { @@ -693,6 +775,39 @@ ALF_Layout_SetWidgetPos(ALFLayout *layout, HWND window, HWND needle, POINT *p) return FALSE; } +BOOL +ALF_Layout_GetWidgetSpan(ALFLayout *layout, HWND window, HWND needle, POINT *p) +{ + (void)window; + + ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { + if (w->hwnd == needle) { + p->x = w->xspan; + p->y = w->yspan; + return TRUE; + } + } + + return FALSE; +} + +static BOOL +ALF_Layout_SetWidgetSpan(ALFLayout *layout, HWND window, HWND needle, POINT *p) +{ + ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { + if (w->hwnd == needle) { + w->xspan = p->x; + w->yspan = p->y; + + ALF_Layout_Invalidate(layout, window); + + return TRUE; + } + } + + return FALSE; +} + static BOOL ALF_Layout_GetWidgetSize(ALFLayout *layout, HWND window, HWND needle, SIZE *s) { @@ -1007,6 +1122,16 @@ ALF_Layout_HandleMessage(ALFLayout *layout, HWND hwnd, UINT msg, WPARAM wparam, return TRUE; } + if (msg == ALF_WM_LYT_GETWDGTSPAN) { + *pRet = (LRESULT)ALF_Layout_GetWidgetSpan(layout, hwnd, (HWND)wparam, (POINT *)lparam); + return TRUE; + } + + if (msg == ALF_WM_LYT_SETWDGTSPAN) { + *pRet = (LRESULT)ALF_Layout_SetWidgetSpan(layout, hwnd, (HWND)wparam, (POINT *)lparam); + return TRUE; + } + if (msg == ALF_WM_LYT_GETWIDGTSIZE) { *pRet = (LRESULT)ALF_Layout_GetWidgetSize(layout, hwnd, (HWND)wparam, (SIZE *)lparam); return TRUE; diff --git a/alf/alflayout.h b/alf/alflayout.h index 183c336..8bcc592 100644 --- a/alf/alflayout.h +++ b/alf/alflayout.h @@ -10,7 +10,10 @@ typedef struct { int y; int width; int height; + int xspan; + int yspan; DWORD flags; + SIZE calculatedSize; } ALFWidgetPriv; typedef struct { diff --git a/widgetfactory.cpp b/widgetfactory.cpp index 20a56c5..315a95c 100644 --- a/widgetfactory.cpp +++ b/widgetfactory.cpp @@ -843,6 +843,7 @@ WinMain ALF_SetText(win, TEXT("Widget Factory")); HWND hwndNtbk = ALF_AddNotebook(win, ID_NOTEBOOK, 1, 1); + ALF_SetWidgetLayoutSpan(win, hwndNtbk, 4, 1); addPaneToNotebook(hwndNtbk, PANE_BUTTONS); addPaneToNotebook(hwndNtbk, PANE_LABEL); @@ -851,20 +852,17 @@ WinMain addPaneToNotebook(hwndNtbk, PANE_COMBO); addPaneToNotebook(hwndNtbk, PANE_GROUPBOX); - HWND btnpanel = ALF_AddPanel(win, (WORD)-1, 1, 3); - ALF_AddNativeButton(btnpanel, ID_HELLO, 1, 3, TEXT("&Hello World!")); - ALF_AddNativeButton(btnpanel, (WORD)-1, 3, 3, TEXT("Goodbye, World")); + ALF_AddNativeButton(win, ID_HELLO, 1, 3, TEXT("&Hello World!")); + ALF_AddNativeButton(win, (WORD)-1, 3, 3, TEXT("Goodbye, World")); ALF_LayoutSetRowMinSize(win, 2, 525); ALF_LayoutSetRowMinSize(win, 0, 525); ALF_LayoutSetRowMinSize(win, 4, 525); ALF_LayoutSetColumnMinSize(win, 0, 525); ALF_LayoutSetColumnMinSize(win, 2, 525); + ALF_LayoutSetColumnMinSize(win, 5, 525); ALF_LayoutSetRowExpandNumerator(win, 1, 1); - ALF_LayoutSetColumnExpandNumerator(win, 1, 1); - - ALF_LayoutSetColumnExpandNumerator(btnpanel, 9, 1); - ALF_LayoutSetColumnMinSize(btnpanel, 2, 525); + ALF_LayoutSetColumnExpandNumerator(win, 4, 1); ALF_SetDefaultButton(win, ID_HELLO); |
