From 469db13b81699b7988aed7be6882b6a9b65f9e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sun, 19 Jul 2015 17:39:41 +0200 Subject: [PATCH] GtkStack: Add interpolate-size property And use it to determine whether we should actually interpolate between stack sizes or not. --- gtk/gtkstack.c | 96 +++++++++++++++++++++++++++++++++++++++++++------- gtk/gtkstack.h | 6 +++- 2 files changed, 88 insertions(+), 14 deletions(-) diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c index b2f265bcf2..789b480054 100644 --- a/gtk/gtkstack.c +++ b/gtk/gtkstack.c @@ -91,6 +91,7 @@ enum { PROP_TRANSITION_DURATION, PROP_TRANSITION_TYPE, PROP_TRANSITION_RUNNING, + PROP_INTERPOLATE_SIZE, LAST_PROP }; @@ -140,6 +141,8 @@ typedef struct { gint last_visible_widget_width; gint last_visible_widget_height; + gboolean interpolate_size; + GtkStackTransitionType active_transition_type; } GtkStackPrivate; @@ -266,6 +269,9 @@ gtk_stack_get_property (GObject *object, case PROP_TRANSITION_RUNNING: g_value_set_boolean (value, gtk_stack_get_transition_running (stack)); break; + case PROP_INTERPOLATE_SIZE: + g_value_set_boolean (value, gtk_stack_get_interpolate_size (stack)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -303,6 +309,9 @@ gtk_stack_set_property (GObject *object, case PROP_TRANSITION_TYPE: gtk_stack_set_transition_type (stack, g_value_get_enum (value)); break; + case PROP_INTERPOLATE_SIZE: + gtk_stack_set_interpolate_size (stack, g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -456,6 +465,11 @@ gtk_stack_class_init (GtkStackClass *klass) g_param_spec_boolean ("transition-running", P_("Transition running"), P_("Whether or not the transition is currently running"), FALSE, GTK_PARAM_READABLE); + stack_props[PROP_INTERPOLATE_SIZE] = + g_param_spec_boolean ("interpolate-size", P_("Interpolate size"), P_("Whether or not the size should smoothly change when changing between differently sized children"), + FALSE, + GTK_PARAM_READABLE); + g_object_class_install_properties (object_class, LAST_PROP, stack_props); @@ -1629,6 +1643,55 @@ gtk_stack_get_transition_running (GtkStack *stack) return (priv->tick_id != 0); } +/** + * gtk_stack_set_interpolate_size: + * @stack: A #GtkStack + * + * Sets whether or not @stack will interpolate its size when + * changing the visible child. If the interpolate-size property + * is set to %TRUE, @stack will interpolate its size between + * the current one and the one it'll take after changing the visible-child, + * according to the set transition-duration. + * + * Since: 3.18 + */ +void +gtk_stack_set_interpolate_size (GtkStack *stack, + gboolean interpolate_size) +{ + GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); + g_return_if_fail (GTK_IS_STACK (stack)); + + interpolate_size = !!interpolate_size; + + if (priv->interpolate_size == interpolate_size) + return; + + priv->interpolate_size = interpolate_size; + g_object_notify_by_pspec (G_OBJECT (stack), + stack_props[PROP_INTERPOLATE_SIZE]); +} + +/** + * gtk_stack_get_interpolate_size: + * @stack: A #GtkStack + * + * Returns: %TRUE If the #GtkStack is set up to interpolate between + * visible-child sizes, %FALSE otherwise. + * + * Since: 3.18 + */ +gboolean +gtk_stack_get_interpolate_size (GtkStack *stack) +{ + GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); + g_return_if_fail (GTK_IS_STACK (stack)); + + return priv->interpolate_size; +} + + + /** * gtk_stack_get_visible_child: * @stack: a #GtkStack @@ -2116,16 +2179,23 @@ gtk_stack_size_allocate (GtkWidget *widget, gtk_widget_get_preferred_height_for_width (priv->visible_child->widget, allocation->width, &min, &nat); - valign = gtk_widget_get_valign (priv->visible_child->widget); - child_allocation.height = MAX (nat, allocation->height); - if (valign == GTK_ALIGN_END && - child_allocation.height > allocation->height) - child_allocation.y -= nat - allocation->height; - else if (valign == GTK_ALIGN_CENTER && - child_allocation.height > allocation->height) - child_allocation.y -= (nat - allocation->height) / 2; + if (priv->interpolate_size) + { + valign = gtk_widget_get_valign (priv->visible_child->widget); + child_allocation.height = MAX (nat, allocation->height); + if (valign == GTK_ALIGN_END && + child_allocation.height > allocation->height) + child_allocation.y -= nat - allocation->height; + else if (valign == GTK_ALIGN_CENTER && + child_allocation.height > allocation->height) + child_allocation.y -= (nat - allocation->height) / 2; - gtk_widget_size_allocate (priv->visible_child->widget, &child_allocation); + gtk_widget_size_allocate (priv->visible_child->widget, &child_allocation); + } + else + { + gtk_widget_size_allocate (priv->visible_child->widget, &child_allocation); + } } if (gtk_widget_get_realized (widget)) @@ -2177,7 +2247,7 @@ gtk_stack_get_preferred_height (GtkWidget *widget, if (priv->last_visible_child != NULL && !priv->vhomogeneous) { - gdouble t = ease_out_cubic (priv->transition_pos); + gdouble t = priv->interpolate_size ? ease_out_cubic (priv->transition_pos) : 1.0; *minimum_height = LERP (*minimum_height, priv->last_visible_widget_height, t); *natural_height = LERP (*natural_height, priv->last_visible_widget_height, t); } @@ -2219,7 +2289,7 @@ gtk_stack_get_preferred_height_for_width (GtkWidget *widget, if (priv->last_visible_child != NULL && !priv->vhomogeneous) { - gdouble t = ease_out_cubic (priv->transition_pos); + gdouble t = priv->interpolate_size ? ease_out_cubic (priv->transition_pos) : 1.0; *minimum_height = LERP (*minimum_height, priv->last_visible_widget_height, t); *natural_height = LERP (*natural_height, priv->last_visible_widget_height, t); } @@ -2259,7 +2329,7 @@ gtk_stack_get_preferred_width (GtkWidget *widget, if (priv->last_visible_child != NULL && !priv->hhomogeneous) { - gdouble t = ease_out_cubic (priv->transition_pos); + gdouble t = priv->interpolate_size ? ease_out_cubic (priv->transition_pos) : 1.0; *minimum_width = LERP (*minimum_width, priv->last_visible_widget_width, t); *natural_width = LERP (*natural_width, priv->last_visible_widget_width, t); } @@ -2300,7 +2370,7 @@ gtk_stack_get_preferred_width_for_height (GtkWidget *widget, if (priv->last_visible_child != NULL && !priv->hhomogeneous) { - gdouble t = ease_out_cubic (priv->transition_pos); + gdouble t = priv->interpolate_size ? ease_out_cubic (priv->transition_pos) : 1.0; *minimum_width = LERP (*minimum_width, priv->last_visible_widget_width, t); *natural_width = LERP (*natural_width, priv->last_visible_widget_width, t); } diff --git a/gtk/gtkstack.h b/gtk/gtkstack.h index 887a224971..4823a29756 100644 --- a/gtk/gtkstack.h +++ b/gtk/gtkstack.h @@ -130,7 +130,11 @@ GDK_AVAILABLE_IN_3_10 GtkStackTransitionType gtk_stack_get_transition_type (GtkStack *stack); GDK_AVAILABLE_IN_3_12 gboolean gtk_stack_get_transition_running (GtkStack *stack); - +GDK_AVAILABLE_IN_3_18 +void gtk_stack_set_interpolate_size (GtkStack *stack, + gboolean interpolate_size); +GDK_AVAILABLE_IN_3_18 +gboolean gtk_stack_get_interpolate_size (GtkStack *stack); G_END_DECLS #endif