I#2710 - EHeaderBar: Report correct minimum width

Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/2710
This commit is contained in:
Milan Crha
2024-04-09 18:47:18 +02:00
parent 2a7671bac6
commit ce17663bdb
2 changed files with 90 additions and 4 deletions

View File

@ -27,6 +27,8 @@ struct _EHeaderBarButtonPrivate {
GtkAction *action;
gchar *label;
gchar *prefer_item;
gint last_labeled_button_width;
gint last_icon_only_button_width;
};
enum {
@ -327,6 +329,18 @@ header_bar_button_add_action (EHeaderBarButton *header_bar_button,
*out_icon_only_button = icon_only_button;
}
static void
header_bar_button_style_updated (GtkWidget *widget)
{
EHeaderBarButton *self = E_HEADER_BAR_BUTTON (widget);
/* Chain up to parent's method. */
GTK_WIDGET_CLASS (e_header_bar_button_parent_class)->style_updated (widget);
self->priv->last_labeled_button_width = -1;
self->priv->last_icon_only_button_width = -1;
}
static void
header_bar_button_set_property (GObject *object,
guint property_id,
@ -421,6 +435,7 @@ static void
e_header_bar_button_class_init (EHeaderBarButtonClass *class)
{
GObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = G_OBJECT_CLASS (class);
object_class->set_property = header_bar_button_set_property;
@ -428,6 +443,9 @@ e_header_bar_button_class_init (EHeaderBarButtonClass *class)
object_class->constructed = header_bar_button_constructed;
object_class->finalize = header_bar_button_finalize;
widget_class = GTK_WIDGET_CLASS (class);
widget_class->style_updated = header_bar_button_style_updated;
g_object_class_install_property (
object_class,
PROP_PREFER_ITEM,
@ -467,6 +485,8 @@ e_header_bar_button_init (EHeaderBarButton *self)
self->priv->dropdown_button = NULL;
self->priv->prefer_item = NULL;
self->priv->label = NULL;
self->priv->last_labeled_button_width = -1;
self->priv->last_icon_only_button_width = -1;
}
/**
@ -656,6 +676,12 @@ e_header_bar_button_get_widths (EHeaderBarButton *self,
return;
}
if (self->priv->last_labeled_button_width > 0) {
*out_labeled_width = self->priv->last_labeled_button_width;
*out_icon_only_width = self->priv->last_icon_only_button_width;
return;
}
if (gtk_widget_get_visible (self->priv->labeled_button)) {
gtk_widget_get_preferred_width (self->priv->labeled_button, &labeled_width, NULL);
} else {
@ -679,6 +705,9 @@ e_header_bar_button_get_widths (EHeaderBarButton *self,
*out_labeled_width = current_width - icon_only_width + labeled_width;
*out_icon_only_width = current_width;
}
self->priv->last_labeled_button_width = *out_labeled_width;
self->priv->last_icon_only_button_width = *out_icon_only_width;
}
/**

View File

@ -96,7 +96,8 @@ header_bar_queue_resize_cb (gpointer user_data)
}
static void
header_bar_update_buttons (EHeaderBar *self)
header_bar_update_buttons (EHeaderBar *self,
gint for_width)
{
GtkAllocation allocation_start, allocation_end;
GSList *labeled_groups = NULL; /* GSList { GtkWidget * }; labeled widgets, divided by groups */
@ -141,6 +142,13 @@ header_bar_update_buttons (EHeaderBar *self)
available_width = MAX (allocation_end.x + allocation_end.width - allocation_start.x
- MIN_TITLE_WIDTH - (2 * BUTTON_SPACING), 0);
/* when making window smaller, calculate with the new size, to have buttons of the proper size */
if (for_width > 0) {
gint current_width = gtk_widget_get_allocated_width (GTK_WIDGET (self));
if (current_width > for_width)
available_width = MAX (0, available_width - (current_width - for_width));
}
for (ii = 0; ii < self->priv->priorities->len && available_width > 0; ii++) {
PriorityBasket *bt = g_ptr_array_index (self->priv->priorities, ii);
GSList *link;
@ -257,7 +265,7 @@ header_bar_update_buttons_idle_cb (gpointer user_data)
self->priv->update_buttons_id = 0;
header_bar_update_buttons (self);
header_bar_update_buttons (self, -1);
return FALSE;
}
@ -353,12 +361,17 @@ header_bar_size_allocate (GtkWidget *widget,
{
EHeaderBar *self = E_HEADER_BAR (widget);
/* prepare buttons for after-allocation size */
if (self->priv->allocated_width != allocation->width)
header_bar_update_buttons (self, allocation->width);
/* Chain up to parent's method. */
GTK_WIDGET_CLASS (e_header_bar_parent_class)->size_allocate (widget, allocation);
/* apply the new size */
if (self->priv->allocated_width != allocation->width) {
self->priv->allocated_width = allocation->width;
header_bar_update_buttons (self);
header_bar_update_buttons (self, -1);
}
}
@ -368,7 +381,50 @@ header_bar_realize (GtkWidget *widget)
/* Chain up to parent's method. */
GTK_WIDGET_CLASS (e_header_bar_parent_class)->realize (widget);
header_bar_update_buttons (E_HEADER_BAR (widget));
header_bar_update_buttons (E_HEADER_BAR (widget), -1);
}
static void
header_bar_get_preferred_width (GtkWidget *in_widget,
gint *minimum_width,
gint *natural_width)
{
EHeaderBar *self = E_HEADER_BAR (in_widget);
/* Chain up to parent's method. */
GTK_WIDGET_CLASS (e_header_bar_parent_class)->get_preferred_width (in_widget, minimum_width, natural_width);
if (!self->priv->force_icon_only_buttons) {
gint decrement_minimum = 0;
guint ii;
for (ii = 0; ii < self->priv->priorities->len; ii++) {
PriorityBasket *bt = g_ptr_array_index (self->priv->priorities, ii);
GSList *link;
for (link = bt->widgets; link; link = g_slist_next (link)) {
GtkWidget *widget = link->data;
if (gtk_widget_is_visible (widget) && E_IS_HEADER_BAR_BUTTON (widget)) {
EHeaderBarButton *button = E_HEADER_BAR_BUTTON (widget);
if (!e_header_bar_button_get_show_icon_only (button)) {
gint labeled_width = -1, icon_only_width = -1;
e_header_bar_button_get_widths (button, &labeled_width, &icon_only_width);
/* it's showing the labeled button now, and when it's switched
to the icon-only button, it'll use this less space, which can
be subtracted from the current minimum width */
if (icon_only_width > 0 && labeled_width > icon_only_width)
decrement_minimum += labeled_width - icon_only_width;
}
}
}
}
if (decrement_minimum > 0 && *minimum_width > decrement_minimum)
*minimum_width -= decrement_minimum;
}
}
static void
@ -425,6 +481,7 @@ e_header_bar_class_init (EHeaderBarClass *klass)
widget_class = GTK_WIDGET_CLASS (klass);
widget_class->size_allocate = header_bar_size_allocate;
widget_class->realize = header_bar_realize;
widget_class->get_preferred_width = header_bar_get_preferred_width;
object_class = G_OBJECT_CLASS (klass);
object_class->constructed = header_bar_constructed;