Handle looping transition animations.

This commit is contained in:
Carlos Garnacho 2010-11-13 13:24:18 +01:00
parent 1123159dc9
commit bcf81a0e23
5 changed files with 42 additions and 20 deletions

View File

@ -25,19 +25,21 @@ struct GtkAnimationDescription
{
GtkTimelineProgressType progress_type;
gdouble duration;
guint loop : 1;
guint ref_count;
};
GtkAnimationDescription *
gtk_animation_description_new (gdouble duration,
GtkTimelineProgressType progress_type)
GtkTimelineProgressType progress_type,
gboolean loop)
{
GtkAnimationDescription *desc;
desc = g_slice_new (GtkAnimationDescription);
desc->duration = duration;
desc->progress_type = progress_type;
desc->loop = loop;
desc->ref_count = 1;
return desc;
@ -55,6 +57,12 @@ gtk_animation_description_get_progress_type (GtkAnimationDescription *desc)
return desc->progress_type;
}
gboolean
gtk_animation_description_get_loop (GtkAnimationDescription *desc)
{
return (desc->loop != 0);
}
GtkAnimationDescription *
gtk_animation_description_ref (GtkAnimationDescription *desc)
{
@ -75,18 +83,23 @@ GtkAnimationDescription *
gtk_animation_description_from_string (const gchar *str)
{
gchar timing_function[16] = { 0, };
gchar duration_measurement[3] = { 0, };
gchar duration_unit[3] = { 0, };
GtkTimelineProgressType progress_type;
guint duration = 0;
gboolean loop;
if (sscanf (str, "%d%2s %15s", &duration, duration_measurement, timing_function) != 3)
if (sscanf (str, "%d%2s %15s loop", &duration, duration_unit, timing_function) == 3)
loop = TRUE;
else if (sscanf (str, "%d%2s %15s", &duration, duration_unit, timing_function) == 3)
loop = FALSE;
else
return NULL;
if (strcmp (duration_measurement, "s") == 0)
if (strcmp (duration_unit, "s") == 0)
duration *= 1000;
else if (strcmp (duration_measurement, "ms") != 0)
else if (strcmp (duration_unit, "ms") != 0)
{
g_warning ("Unknown duration measurement: %s\n", duration_measurement);
g_warning ("Unknown duration unit: %s\n", duration_unit);
return NULL;
}
@ -106,7 +119,7 @@ gtk_animation_description_from_string (const gchar *str)
return NULL;
}
return gtk_animation_description_new ((gdouble) duration, progress_type);
return gtk_animation_description_new ((gdouble) duration, progress_type, loop);
}
GType

View File

@ -32,10 +32,12 @@ typedef struct GtkAnimationDescription GtkAnimationDescription;
GType gtk_animation_description_get_type (void) G_GNUC_CONST;
GtkAnimationDescription * gtk_animation_description_new (gdouble duration,
GtkTimelineProgressType progress_type);
GtkTimelineProgressType progress_type,
gboolean loop);
gdouble gtk_animation_description_get_duration (GtkAnimationDescription *desc);
GtkTimelineProgressType gtk_animation_description_get_progress_type (GtkAnimationDescription *desc);
gboolean gtk_animation_description_get_loop (GtkAnimationDescription *desc);
GtkAnimationDescription * gtk_animation_description_ref (GtkAnimationDescription *desc);
void gtk_animation_description_unref (GtkAnimationDescription *desc);

View File

@ -364,12 +364,12 @@
* </row>
* <row>
* <entry>transition</entry>
* <entry><programlisting>duration [s|ms] [linear|ease|ease-in|ease-out|ease-in-out]</programlisting></entry>
* <entry><programlisting>duration [s|ms] [linear|ease|ease-in|ease-out|ease-in-out] [loop]?</programlisting></entry>
* <entry></entry>
* <entry>
* <programlisting>
* transition: 150ms ease-in-out;
* transition: 1s linear;</programlisting>
* transition: 1s linear loop;</programlisting>
* </entry>
* </row>
* </tbody>

View File

@ -584,6 +584,7 @@ animation_info_new (GtkStyleContext *context,
gpointer region_id,
gdouble duration,
GtkTimelineProgressType progress_type,
gboolean loop,
GtkStateType state,
gboolean target_value,
GdkWindow *window)
@ -600,8 +601,9 @@ animation_info_new (GtkStyleContext *context,
info->region_id = region_id;
gtk_timeline_set_progress_type (info->timeline, progress_type);
gtk_timeline_set_loop (info->timeline, loop);
if (!target_value)
if (!loop && !target_value)
{
gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
gtk_timeline_rewind (info->timeline);
@ -2551,11 +2553,13 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
info = animation_info_lookup (context, region_id, state);
if (info)
if (info &&
info->target_value != state_value)
{
/* Reverse the animation if target values are the opposite */
if (info->target_value != state_value)
/* Target values are the opposite */
if (!gtk_timeline_get_loop (info->timeline))
{
/* Reverse the animation */
if (gtk_timeline_get_direction (info->timeline) == GTK_TIMELINE_DIRECTION_FORWARD)
gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
else
@ -2563,12 +2567,18 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
info->target_value = state_value;
}
}
else
{
/* Take it out of its looping state */
gtk_timeline_set_loop (info->timeline, FALSE);
}
}
else if (!info)
{
info = animation_info_new (context, region_id,
gtk_animation_description_get_duration (desc),
gtk_animation_description_get_progress_type (desc),
gtk_animation_description_get_loop (desc),
state, state_value, window);
priv->animations = g_slist_prepend (priv->animations, info);

View File

@ -102,10 +102,7 @@ gtk_style_properties_class_init (GtkStylePropertiesClass *klass)
gtk_style_properties_register_property ("engine", GTK_TYPE_THEMING_ENGINE, &val, NULL);
g_value_unset (&val);
g_value_init (&val, GTK_TYPE_ANIMATION_DESCRIPTION);
g_value_take_boxed (&val, gtk_animation_description_new (0, GTK_TIMELINE_PROGRESS_LINEAR));
gtk_style_properties_register_property ("transition", GTK_TYPE_ANIMATION_DESCRIPTION, &val, NULL);
g_value_unset (&val);
gtk_style_properties_register_property ("transition", GTK_TYPE_ANIMATION_DESCRIPTION, NULL, NULL);
g_type_class_add_private (object_class, sizeof (GtkStylePropertiesPrivate));
}