1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 11:32:48 -05:00

dialog system: add a side-by-side alignment feature.

This will let us put two controls side by side (e.g. in disjoint
columns of a multi-col layout) and indicate that instead of the
default behaviour of aligning their top edges, their centreline (or,
even better if available, font baseline) should be aligned.

NFC: nothing uses this yet.
This commit is contained in:
Simon Tatham
2021-04-03 17:45:31 +01:00
parent d33f889a56
commit 1276c13e6a
5 changed files with 103 additions and 4 deletions

View File

@ -1325,6 +1325,28 @@ struct winctrl *winctrl_findbyindex(struct winctrls *wc, int index)
return index234(wc->byid, index);
}
static void move_windows(HWND hwnd, int base_id, int num_ids, LONG dy)
{
if (!dy)
return;
for (int i = 0; i < num_ids; i++) {
HWND win = GetDlgItem(hwnd, base_id + i);
RECT rect;
if (!GetWindowRect(win, &rect))
continue;
POINT p;
p.x = rect.left;
p.y = rect.top + dy;
if (!ScreenToClient(hwnd, &p))
continue;
SetWindowPos(win, NULL, p.x, p.y, 0, 0,
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
}
}
void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
struct ctlpos *cp, struct controlset *s, int *id)
{
@ -1340,7 +1362,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
char shortcuts[MAX_SHORTCUTS_PER_CTRL];
int nshortcuts;
char *escaped;
int i, actual_base_id, base_id, num_ids;
int i, actual_base_id, base_id, num_ids, align_id_relative;
void *data;
base_id = *id;
@ -1349,7 +1371,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
if (s->boxname && *s->boxname) {
struct winctrl *c = snew(struct winctrl);
c->ctrl = NULL;
c->base_id = base_id;
c->base_id = c->align_id = base_id;
c->num_ids = 1;
c->data = NULL;
memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts));
@ -1362,7 +1384,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
if (!s->boxname && s->boxtitle) {
struct winctrl *c = snew(struct winctrl);
c->ctrl = NULL;
c->base_id = base_id;
c->base_id = c->align_id = base_id;
c->num_ids = 1;
c->data = dupstr(s->boxtitle);
memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts));
@ -1491,6 +1513,11 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
/* Almost all controls start at base_id. */
actual_base_id = base_id;
/* For vertical alignment purposes, the most relevant control
* in a group is usually the last one. But that can be
* overridden occasionally. */
align_id_relative = -1;
/*
* Now we're ready to actually create the control, by
* switching on its type.
@ -1659,6 +1686,10 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
unreachable("bad control type in winctrl_layout");
}
/* Translate the original align_id_relative of -1 into n-1 */
if (align_id_relative < 0)
align_id_relative += num_ids;
/*
* Create a `struct winctrl' for this control, and advance
* the dialog ID counter, if it's actually been created
@ -1669,6 +1700,7 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
c->ctrl = ctrl;
c->base_id = actual_base_id;
c->align_id = c->base_id + align_id_relative;
c->num_ids = num_ids;
c->data = data;
memcpy(c->shortcuts, shortcuts, sizeof(shortcuts));
@ -1676,6 +1708,31 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
winctrl_add_shortcuts(dp, c);
if (actual_base_id == base_id)
base_id += num_ids;
if (ctrl->generic.align_next_to) {
/*
* Implement align_next_to by looking at the y extents
* of the two controls now that both are created, and
* moving one or the other downwards so that they're
* centred on a common horizontal line.
*/
struct winctrl *c2 = winctrl_findbyctrl(
wc, ctrl->generic.align_next_to);
HWND win1 = GetDlgItem(pos.hwnd, c->align_id);
HWND win2 = GetDlgItem(pos.hwnd, c2->align_id);
RECT rect1, rect2;
if (win1 && win2 &&
GetWindowRect(win1, &rect1) &&
GetWindowRect(win2, &rect2)) {
LONG top = (rect1.top < rect2.top ? rect1.top : rect2.top);
LONG bottom = (rect1.bottom > rect2.bottom ?
rect1.bottom : rect2.bottom);
move_windows(pos.hwnd, c->base_id, c->num_ids,
(top + bottom - rect1.top - rect1.bottom)/2);
move_windows(pos.hwnd, c2->base_id, c2->num_ids,
(top + bottom - rect2.top - rect2.bottom)/2);
}
}
} else {
sfree(data);
}

View File

@ -491,6 +491,12 @@ struct winctrl {
*/
int base_id;
int num_ids;
/*
* For vertical alignment, the id of a particular representative
* control that has the y-extent of the sensible part of the
* control.
*/
int align_id;
/*
* Remember what keyboard shortcuts were used by this control,
* so that when we remove it again we can take them out of the