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:
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user