From 120723bf4011f492163a489cb530c149d09c92cf Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 21 Dec 2021 10:53:41 +0000 Subject: [PATCH] GTK: allow Event Log list box to grow vertically. Now, when you resize the Event Log window, the list box grows in both directions. Previously, as a side effect of the Columns-based layout, it grew only horizontally. I've arranged this by adding an extra wrinkle to the Columns layout system, which allows you to tag _exactly one_ widget in the whole container as the 'vexpand' widget. When the Columns is size-allocated taller than its minimum height, the vexpand widget is given all the extra space. This technique ports naturally across all versions of GTK (since the hard part is done in my own code). But it's limited: you can't set more than one widget to be vexpand (which saves having to figure out whether they're side by side and can expand in parallel, or vertically separated and each have to get half the available extra space, etc). And in complex layouts where the widget you really want to expand is in a sub-Columns, there's no system for recursively searching down to find it. In other words, this is a one-shot bodge for the Event Log, and it will want more work if we ever plan to extend it to list boxes in the main config dialog. --- unix/columns.c | 29 +++++++++++++++++++++++++++-- unix/columns.h | 2 ++ unix/dialog.c | 4 ++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/unix/columns.c b/unix/columns.c index d1c0cb28..e53d4a06 100644 --- a/unix/columns.c +++ b/unix/columns.c @@ -358,6 +358,9 @@ static void columns_remove(GtkContainer *container, GtkWidget *widget) gtk_widget_queue_resize(GTK_WIDGET(container)); } + if (cols->vexpand == child) + cols->vexpand = NULL; + g_free(child); if (was_visible) gtk_widget_queue_resize(GTK_WIDGET(container)); @@ -555,6 +558,18 @@ void columns_taborder_last(Columns *cols, GtkWidget *widget) } } +void columns_vexpand(Columns *cols, GtkWidget *widget) +{ + g_return_if_fail(cols != NULL); + g_return_if_fail(IS_COLUMNS(cols)); + g_return_if_fail(widget != NULL); + + ColumnsChild *child = columns_find_child(cols, widget); + g_return_if_fail(child != NULL); + + cols->vexpand = child; +} + /* * Override GtkContainer's focus movement so the user can * explicitly specify the tab order. @@ -873,7 +888,14 @@ static void columns_alloc_vert(Columns *cols, gint ourheight, { ColumnsChild *child; GList *children; - gint i, ncols, colspan, *colypos, realheight, fakeheight; + gint i, ncols, colspan, *colypos, realheight, fakeheight, vexpand_extra; + + if (cols->vexpand) { + gint minheight = columns_compute_height(cols, get_height); + vexpand_extra = ourheight - minheight; + } else { + vexpand_extra = 0; + } ncols = 1; /* As in size_request, colypos is the lowest y reached in each column. */ @@ -900,7 +922,10 @@ static void columns_alloc_vert(Columns *cols, gint ourheight, if (!gtk_widget_get_visible(child->widget)) continue; - realheight = fakeheight = get_height(child); + realheight = get_height(child); + if (child == cols->vexpand) + realheight += vexpand_extra; + fakeheight = realheight; if (child->same_height_as) { gint childheight2 = get_height(child->same_height_as); if (fakeheight < childheight2) diff --git a/unix/columns.h b/unix/columns.h index a850a166..d2d58c4a 100644 --- a/unix/columns.h +++ b/unix/columns.h @@ -30,6 +30,7 @@ struct Columns_tag { /* private after here */ GList *children; /* this holds ColumnsChild structures */ GList *taborder; /* this just holds GtkWidgets */ + ColumnsChild *vexpand; gint spacing; }; @@ -57,6 +58,7 @@ void columns_add(Columns *cols, GtkWidget *child, void columns_taborder_last(Columns *cols, GtkWidget *child); void columns_force_left_align(Columns *cols, GtkWidget *child); void columns_force_same_height(Columns *cols, GtkWidget *ch1, GtkWidget *ch2); +void columns_vexpand(Columns *cols, GtkWidget *child); #ifdef __cplusplus } diff --git a/unix/dialog.c b/unix/dialog.c index 9ba1e164..84a5762f 100644 --- a/unix/dialog.c +++ b/unix/dialog.c @@ -4050,6 +4050,10 @@ void showeventlog(eventlog_stuff *es, void *parentwin) "QUITE LONG 'COS SSH LOG ENTRIES ARE WIDE"), -1); our_dialog_add_to_content_area(GTK_WINDOW(window), w1, true, true, 0); + { + struct uctrl *uc = dlg_find_byctrl(&es->dp, es->listctrl); + columns_vexpand(COLUMNS(w1), uc->toplevel); + } gtk_widget_show(w1); es->dp.data = es;