summaryrefslogtreecommitdiff
path: root/alf
diff options
context:
space:
mode:
authorJonas Kümmerlin <jonas@kuemmerlin.eu>2020-05-26 18:27:26 +0200
committerJonas Kümmerlin <jonas@kuemmerlin.eu>2020-05-26 18:27:26 +0200
commitffb723122057e30244cab59ea07b18ae71104359 (patch)
treef350ca04d4a64d681e98a19c86ca7c5a8369eb98 /alf
parent3289498e9dc55cef26f41576f2f765d2b3fe6ad3 (diff)
layout: support for spanning cells
mostly untested for now
Diffstat (limited to 'alf')
-rw-r--r--alf/alf.cpp19
-rw-r--r--alf/alf.h8
-rw-r--r--alf/alflayout.cpp177
-rw-r--r--alf/alflayout.h3
4 files changed, 181 insertions, 26 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 };
diff --git a/alf/alf.h b/alf/alf.h
index fc17ec8..2e07736 100644
--- a/alf/alf.h
+++ b/alf/alf.h
@@ -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 {