Compare commits

...

3 Commits

Author SHA1 Message Date
Matthias Clasen
64591e0fbd checkbutton: Make the child expand
This is the proper behavior for check buttons -
the indicator is fixed size, and the child takes
all the remaining space.
2020-05-05 22:59:43 -04:00
Matthias Clasen
73df127928 spinbutton: Use the layout expand flag
It does not make a difference in practice here,
since we don't propagate expand flags from the text
to the spin button, but we can just as well use
the layout expand flag here.
2020-05-05 22:39:12 -04:00
Matthias Clasen
f923e24c72 boxlayout: Add GtkBoxLayoutChild
Add a layout child for GtkBoxLayout, with an expand
property that can be used to control local expansion
without the propagation of GtkWidget:h/vexpand getting
in the way.
2020-05-05 20:40:41 -04:00
5 changed files with 205 additions and 12 deletions

View File

@@ -6668,6 +6668,11 @@ gtk_box_layout_get_spacing
gtk_box_layout_set_baseline_position
gtk_box_layout_get_baseline_position
<SUBSECTION>
GtkBoxLayoutChild
gtk_box_layout_child_set_expand
gtk_box_layout_child_get_expand
<SUBSECTION Standard>
GTK_TYPE_BOX_LAYOUT
gtk_box_layout_get_type

View File

@@ -49,6 +49,139 @@
* you can use the #GtkBoxLayout:spacing property.
*/
struct _GtkBoxLayoutChild
{
GtkLayoutChild parent_instance;
gboolean expand;
};
enum {
PROP_CHILD_EXPAND = 1,
N_CHILD_PROPERTIES
};
static GParamSpec *child_props[N_CHILD_PROPERTIES];
G_DEFINE_TYPE (GtkBoxLayoutChild, gtk_box_layout_child, GTK_TYPE_LAYOUT_CHILD)
static void
gtk_box_layout_child_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkBoxLayoutChild *self = GTK_BOX_LAYOUT_CHILD (gobject);
switch (prop_id)
{
case PROP_CHILD_EXPAND:
gtk_box_layout_child_set_expand (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gtk_box_layout_child_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkBoxLayoutChild *self = GTK_BOX_LAYOUT_CHILD (gobject);
switch (prop_id)
{
case PROP_CHILD_EXPAND:
g_value_set_boolean (value, self->expand);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gtk_box_layout_child_class_init (GtkBoxLayoutChildClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gtk_box_layout_child_set_property;
gobject_class->get_property = gtk_box_layout_child_get_property;
/**
* GtkBoxLayoutChild:expand:
*
* Whether the child should receive extra space when the parent grows.
*
* Note that the effective expand value for a child also takes
* the #GtkWidget:hexpand or #GtkWidget:vexpand property into account.
*/
child_props[PROP_CHILD_EXPAND] =
g_param_spec_boolean ("expand",
P_("xpand"),
P_("Whether the child should receive extra space when the parent grows"),
FALSE,
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (gobject_class, N_CHILD_PROPERTIES, child_props);
}
static void
gtk_box_layout_child_init (GtkBoxLayoutChild *self)
{
}
/**
* gtk_box_layout_child_set_expand:
* @self: a #GtkBoxLayoutChild
* @expand: whether this child should receive extra space when the parent grows
*
* Sets whether the child should receive extra space (beyond its
* natural size) when the parent grows.
*
* Note that the effective expand is determined from this property
* and the #GtkWidget:hexpand or #GtkWidget:vexpand property of the
* child's widget.
*/
void
gtk_box_layout_child_set_expand (GtkBoxLayoutChild *self,
gboolean expand)
{
g_return_if_fail (GTK_IS_BOX_LAYOUT_CHILD (self));
if (self->expand == expand)
return;
self->expand = expand;
gtk_layout_manager_layout_changed (gtk_layout_child_get_layout_manager (GTK_LAYOUT_CHILD (self)));
g_object_notify_by_pspec (G_OBJECT (self), child_props[PROP_CHILD_EXPAND]);
}
/**
* gtk_box_layout_child_get_expand:
* @self: a #GtkBoxLayoutChild
*
* Determines whether the child should receive extra space (beyond its
* natural size) when the parent grows.
*
* Returns: %TRUE if the child is set to expand
*/
gboolean
gtk_box_layout_child_get_expand (GtkBoxLayoutChild *self)
{
g_return_val_if_fail (GTK_IS_BOX_LAYOUT_CHILD (self), FALSE);
return self->expand;
}
struct _GtkBoxLayout
{
GtkLayoutManager parent_instance;
@@ -160,11 +293,27 @@ gtk_box_layout_get_property (GObject *gobject,
}
}
static gboolean
child_should_expand (GtkBoxLayout *self,
GtkWidget *widget)
{
GtkLayoutManager *layout;
GtkLayoutChild *child;
if (gtk_widget_compute_expand (widget, self->orientation))
return TRUE;
layout = GTK_LAYOUT_MANAGER (self);
child = gtk_layout_manager_get_layout_child (layout, widget);
return GTK_BOX_LAYOUT_CHILD (child)->expand;
}
static void
count_expand_children (GtkWidget *widget,
GtkOrientation orientation,
gint *visible_children,
gint *expand_children)
count_expand_children (GtkBoxLayout *self,
GtkWidget *widget,
int *visible_children,
int *expand_children)
{
GtkWidget *child;
@@ -179,7 +328,7 @@ count_expand_children (GtkWidget *widget,
*visible_children += 1;
if (gtk_widget_compute_expand (child, orientation))
if (child_should_expand (self, child))
*expand_children += 1;
}
}
@@ -281,7 +430,7 @@ gtk_box_layout_compute_opposite_size (GtkBoxLayout *self,
int spacing;
gboolean have_baseline;
count_expand_children (widget, self->orientation, &nvis_children, &nexpand_children);
count_expand_children (self, widget, &nvis_children, &nexpand_children);
if (nvis_children <= 0)
return;
@@ -361,7 +510,7 @@ gtk_box_layout_compute_opposite_size (GtkBoxLayout *self,
{
child_size = sizes[i].minimum_size;
if (gtk_widget_compute_expand (child, self->orientation))
if (child_should_expand (self, child))
{
child_size += size_given_to_child;
@@ -482,7 +631,7 @@ gtk_box_layout_allocate (GtkLayoutManager *layout_manager,
gint child_size;
gint spacing;
count_expand_children (widget, self->orientation, &nvis_children, &nexpand_children);
count_expand_children (self, widget, &nvis_children, &nexpand_children);
/* If there is no visible child, simply return. */
if (nvis_children <= 0)
@@ -575,7 +724,7 @@ gtk_box_layout_allocate (GtkLayoutManager *layout_manager,
{
child_size = sizes[i].minimum_size;
if (gtk_widget_compute_expand (child, self->orientation))
if (child_should_expand (self, child))
{
child_size += size_given_to_child;
@@ -701,6 +850,7 @@ gtk_box_layout_class_init (GtkBoxLayoutClass *klass)
gobject_class->set_property = gtk_box_layout_set_property;
gobject_class->get_property = gtk_box_layout_get_property;
layout_manager_class->layout_child_type = GTK_TYPE_BOX_LAYOUT_CHILD;
layout_manager_class->measure = gtk_box_layout_measure;
layout_manager_class->allocate = gtk_box_layout_allocate;

View File

@@ -27,7 +27,8 @@
G_BEGIN_DECLS
#define GTK_TYPE_BOX_LAYOUT (gtk_box_layout_get_type())
#define GTK_TYPE_BOX_LAYOUT (gtk_box_layout_get_type())
#define GTK_TYPE_BOX_LAYOUT_CHILD (gtk_box_layout_child_get_type())
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkBoxLayout, gtk_box_layout, GTK, BOX_LAYOUT, GtkLayoutManager)
@@ -51,4 +52,12 @@ void gtk_box_layout_set_baseline_position (GtkBoxLayout
GDK_AVAILABLE_IN_ALL
GtkBaselinePosition gtk_box_layout_get_baseline_position (GtkBoxLayout *box_layout);
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkBoxLayoutChild, gtk_box_layout_child, GTK, BOX_LAYOUT_CHILD, GtkLayoutChild)
void gtk_box_layout_child_set_expand (GtkBoxLayoutChild *child,
gboolean expand);
GDK_AVAILABLE_IN_ALL
gboolean gtk_box_layout_child_get_expand (GtkBoxLayoutChild *child);
G_END_DECLS

View File

@@ -171,6 +171,30 @@ gtk_check_button_get_property (GObject *object,
}
}
static void
gtk_check_button_notify (GObject *object,
GParamSpec *pspec)
{
if (strcmp (pspec->name, "child") == 0)
{
GtkWidget *child;
child = gtk_button_get_child (GTK_BUTTON (object));
if (child)
{
GtkLayoutManager *layout;
GtkLayoutChild *layout_child;
layout = gtk_widget_get_layout_manager (GTK_WIDGET (object));
layout_child = gtk_layout_manager_get_layout_child (layout, child);
gtk_box_layout_child_set_expand (GTK_BOX_LAYOUT_CHILD (layout_child), TRUE);
}
}
if (G_OBJECT_CLASS (gtk_check_button_parent_class)->notify)
G_OBJECT_CLASS (gtk_check_button_parent_class)->notify (object, pspec);
}
static void
gtk_check_button_class_init (GtkCheckButtonClass *class)
{
@@ -180,6 +204,7 @@ gtk_check_button_class_init (GtkCheckButtonClass *class)
object_class->finalize = gtk_check_button_finalize;
object_class->set_property = gtk_check_button_set_property;
object_class->get_property = gtk_check_button_get_property;
object_class->notify = gtk_check_button_notify;
widget_class->state_flags_changed = gtk_check_button_state_flags_changed;

View File

@@ -906,6 +906,8 @@ gtk_spin_button_init (GtkSpinButton *spin_button)
{
GtkEventController *controller;
GtkGesture *gesture;
GtkLayoutManager *layout;
GtkLayoutChild *child;
spin_button->adjustment = NULL;
spin_button->timer = 0;
@@ -928,11 +930,13 @@ gtk_spin_button_init (GtkSpinButton *spin_button)
gtk_editable_init_delegate (GTK_EDITABLE (spin_button));
gtk_editable_set_width_chars (GTK_EDITABLE (spin_button->entry), 0);
gtk_editable_set_max_width_chars (GTK_EDITABLE (spin_button->entry), 0);
gtk_widget_set_hexpand (spin_button->entry, TRUE);
gtk_widget_set_vexpand (spin_button->entry, TRUE);
g_signal_connect (spin_button->entry, "activate", G_CALLBACK (gtk_spin_button_activate), spin_button);
gtk_widget_set_parent (spin_button->entry, GTK_WIDGET (spin_button));
layout = gtk_widget_get_layout_manager (GTK_WIDGET (spin_button));
child = gtk_layout_manager_get_layout_child (layout, spin_button->entry);
gtk_box_layout_child_set_expand (GTK_BOX_LAYOUT_CHILD (child), TRUE);
spin_button->down_button = gtk_button_new_from_icon_name ("value-decrease-symbolic");
gtk_widget_add_css_class (spin_button->down_button, "down");
gtk_widget_set_can_focus (spin_button->down_button, FALSE);