diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 8d98f71601..c1c2ac74d8 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -532,6 +532,8 @@ gtk_column_view_column_set_sorter gtk_column_view_column_get_sorter gtk_column_view_column_set_visible gtk_column_view_column_get_visible +gtk_column_view_column_set_fixed_width +gtk_column_view_column_get_fixed_width GTK_COLUMN_VIEW_COLUMN GTK_COLUMN_VIEW_COLUMN_CLASS diff --git a/gtk/gtkcolumnview.c b/gtk/gtkcolumnview.c index 503c4c41b1..e190b812bc 100644 --- a/gtk/gtkcolumnview.c +++ b/gtk/gtkcolumnview.c @@ -35,6 +35,7 @@ #include "gtkscrollable.h" #include "gtkwidgetprivate.h" #include "gtksizerequest.h" +#include "gtkadjustment.h" /** * SECTION:gtkcolumnview @@ -64,6 +65,8 @@ struct _GtkColumnView GtkColumnListItemFactory *factory; GtkSorter *sorter; + + GtkAdjustment *hadjustment; }; struct _GtkColumnViewClass @@ -170,7 +173,7 @@ gtk_column_view_allocate_columns (GtkColumnView *self, int width) { GtkScrollablePolicy scroll_policy; - int col_min, col_nat, widget_min, widget_nat, extra, col_size, x; + int col_min, col_nat, extra, col_size, x; guint i; int n; GtkRequestedSize *sizes; @@ -228,8 +231,9 @@ gtk_column_view_allocate (GtkWidget *widget, int baseline) { GtkColumnView *self = GTK_COLUMN_VIEW (widget); - int full_width, header_height, min, nat; + int full_width, header_height, min, nat, x; + x = gtk_adjustment_get_value (self->hadjustment); full_width = gtk_column_view_allocate_columns (self, width); gtk_widget_measure (self->header, GTK_ORIENTATION_VERTICAL, full_width, &min, &nat, NULL, NULL); @@ -237,11 +241,14 @@ gtk_column_view_allocate (GtkWidget *widget, header_height = min; else header_height = nat; - gtk_widget_allocate (self->header, full_width, header_height, -1, NULL); + gtk_widget_allocate (self->header, full_width, header_height, -1, + gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (-x, 0))); gtk_widget_allocate (GTK_WIDGET (self->listview), full_width, height - header_height, -1, - gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (0, header_height))); + gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (-x, header_height))); + + gtk_adjustment_configure (self->hadjustment, x, 0, full_width, width * 0.1, width * 0.9, width); } static void @@ -252,6 +259,23 @@ gtk_column_view_activate_cb (GtkListView *listview, g_signal_emit (self, signals[ACTIVATE], 0, pos); } +static void +adjustment_value_changed_cb (GtkAdjustment *adjustment, + GtkColumnView *self) +{ + gtk_widget_queue_allocate (GTK_WIDGET (self)); +} + +static void +clear_adjustment (GtkColumnView *self) +{ + if (self->hadjustment == NULL) + return; + + g_signal_handlers_disconnect_by_func (self->hadjustment, adjustment_value_changed_cb, self); + g_clear_object (&self->hadjustment); +} + static void gtk_column_view_dispose (GObject *object) { @@ -270,6 +294,7 @@ gtk_column_view_dispose (GObject *object) g_clear_object (&self->factory); g_clear_object (&self->sorter); + clear_adjustment (self); G_OBJECT_CLASS (gtk_column_view_parent_class)->dispose (object); } @@ -299,7 +324,7 @@ gtk_column_view_get_property (GObject *object, break; case PROP_HADJUSTMENT: - g_value_set_object (value, gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (self->listview))); + g_value_set_object (value, self->hadjustment); break; case PROP_HSCROLL_POLICY: @@ -343,13 +368,24 @@ gtk_column_view_set_property (GObject *object, GParamSpec *pspec) { GtkColumnView *self = GTK_COLUMN_VIEW (object); + GtkAdjustment *adjustment; switch (property_id) { case PROP_HADJUSTMENT: - if (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (self->listview)) != g_value_get_object (value)) + adjustment = g_value_get_object (value); + if (adjustment == NULL) + adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + g_object_ref_sink (adjustment); + + if (self->hadjustment != adjustment) { - gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (self->listview), g_value_get_object (value)); + clear_adjustment (self); + + self->hadjustment = adjustment; + + g_signal_connect (adjustment, "value-changed", G_CALLBACK (adjustment_value_changed_cb), self); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HADJUSTMENT]); } break; diff --git a/gtk/gtkcolumnviewcell.c b/gtk/gtkcolumnviewcell.c index 4df02a0194..4088222359 100644 --- a/gtk/gtkcolumnviewcell.c +++ b/gtk/gtkcolumnviewcell.c @@ -53,10 +53,18 @@ gtk_column_view_cell_measure (GtkWidget *widget, int *minimum_baseline, int *natural_baseline) { + GtkColumnViewCell *cell = GTK_COLUMN_VIEW_CELL (widget); GtkWidget *child = gtk_widget_get_first_child (widget); if (child) gtk_widget_measure (child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + int fixed_width = gtk_column_view_column_get_fixed_width (cell->column); + if (fixed_width > -1) + *minimum = *natural = fixed_width; + } } static void diff --git a/gtk/gtkcolumnviewcolumn.c b/gtk/gtkcolumnviewcolumn.c index 09ddbbcb72..170e039c6a 100644 --- a/gtk/gtkcolumnviewcolumn.c +++ b/gtk/gtkcolumnviewcolumn.c @@ -61,6 +61,8 @@ struct _GtkColumnViewColumn int allocation_offset; int allocation_size; + int fixed_width; + gboolean visible; /* This list isn't sorted - this is just caching for performance */ @@ -80,6 +82,7 @@ enum PROP_TITLE, PROP_SORTER, PROP_VISIBLE, + PROP_FIXED_WIDTH, N_PROPS }; @@ -133,6 +136,10 @@ gtk_column_view_column_get_property (GObject *object, g_value_set_boolean (value, self->visible); break; + case PROP_FIXED_WIDTH: + g_value_set_int (value, self->fixed_width); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -165,6 +172,10 @@ gtk_column_view_column_set_property (GObject *object, gtk_column_view_column_set_visible (self, g_value_get_boolean (value)); break; + case PROP_FIXED_WIDTH: + gtk_column_view_column_set_fixed_width (self, g_value_get_int (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -240,6 +251,19 @@ gtk_column_view_column_class_init (GtkColumnViewColumnClass *klass) TRUE, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + /** + * GtkColumnViewColumn:fixed-width: + * + * If not -1, this is the width that the column is allocated, + * regardless of the size of its content. + */ + properties[PROP_FIXED_WIDTH] = + g_param_spec_int ("fixed-width", + P_("Fixed width"), + P_("Fixed width of this column"), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (gobject_class, N_PROPS, properties); } @@ -249,6 +273,7 @@ gtk_column_view_column_init (GtkColumnViewColumn *self) self->minimum_size_request = -1; self->natural_size_request = -1; self->visible = TRUE; + self->fixed_width = -1; } /** @@ -357,6 +382,12 @@ gtk_column_view_column_measure (GtkColumnViewColumn *self, int *minimum, int *natural) { + if (self->fixed_width > -1) + { + self->minimum_size_request = self->fixed_width; + self->natural_size_request = self->fixed_width; + } + if (self->minimum_size_request < 0) { GtkColumnViewCell *cell; @@ -721,3 +752,66 @@ gtk_column_view_column_get_visible (GtkColumnViewColumn *self) return self->visible; } + +/** + * gtk_column_view_column_set_fixed_width: + * @self: a #GtkColumnViewColumn + * @fixed_width: the new fixed width, or -1 + * + * If @fixed_width is not -1, sets the fixed width of @column; + * otherwise unsets it. + * + * Setting a fixed width overrides the automatically calculated + * width. Interactive resizing also sets the “fixed-width” property. + */ +void +gtk_column_view_column_set_fixed_width (GtkColumnViewColumn *self, + int fixed_width) +{ + GtkOverflow overflow; + GtkColumnViewCell *cell; + + g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self)); + g_return_if_fail (fixed_width >= -1); + + if (self->fixed_width == fixed_width) + return; + + self->fixed_width = fixed_width; + + if (fixed_width > -1) + overflow = GTK_OVERFLOW_HIDDEN; + else + overflow = GTK_OVERFLOW_VISIBLE; + + if (overflow != gtk_widget_get_overflow (GTK_WIDGET (self->header))) + { + if (self->header) + gtk_widget_set_overflow (GTK_WIDGET (self->header), overflow); + + for (cell = self->first_cell; cell; cell = gtk_column_view_cell_get_next (cell)) + { + gtk_widget_set_overflow (GTK_WIDGET (cell), overflow); + } + } + + gtk_column_view_column_queue_resize (self); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FIXED_WIDTH]); +} + +/** + * gtk_column_view_column_get_fixed_width: + * @self: a #GtkColumnViewColumn + * + * Gets the fixed width of the column. + * + * Returns: the fixed with of the column + */ +int +gtk_column_view_column_get_fixed_width (GtkColumnViewColumn *self) +{ + g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self), -1); + + return self->fixed_width; +} diff --git a/gtk/gtkcolumnviewcolumn.h b/gtk/gtkcolumnviewcolumn.h index f0005809be..32392612b2 100644 --- a/gtk/gtkcolumnviewcolumn.h +++ b/gtk/gtkcolumnviewcolumn.h @@ -78,6 +78,12 @@ void gtk_column_view_column_set_visible (GtkColu GDK_AVAILABLE_IN_ALL gboolean gtk_column_view_column_get_visible (GtkColumnViewColumn *self); +GDK_AVAILABLE_IN_ALL +void gtk_column_view_column_set_fixed_width (GtkColumnViewColumn *self, + int fixed_width); +GDK_AVAILABLE_IN_ALL +int gtk_column_view_column_get_fixed_width (GtkColumnViewColumn *self); + G_END_DECLS #endif /* __GTK_COLUMN_VIEW_COLUMN_H__ */ diff --git a/gtk/gtkcolumnviewtitle.c b/gtk/gtkcolumnviewtitle.c index 306064bcd8..e6bcf0ef5f 100644 --- a/gtk/gtkcolumnviewtitle.c +++ b/gtk/gtkcolumnviewtitle.c @@ -58,10 +58,18 @@ gtk_column_view_title_measure (GtkWidget *widget, int *minimum_baseline, int *natural_baseline) { + GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget); GtkWidget *child = gtk_widget_get_first_child (widget); if (child) gtk_widget_measure (child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + int fixed_width = gtk_column_view_column_get_fixed_width (self->column); + if (fixed_width > -1) + *minimum = *natural = fixed_width; + } } static void