From db45c0920b902a7c034b2fc0b7d2adae6b8c330e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 25 May 2010 20:07:39 +0200 Subject: [PATCH] [StWidget] Support style transitions It is sometimes desirable to fade smoothly between two styles instead of changing it abruptly. Add transitions controlled by the transition-duration CSS property. https://bugzilla.gnome.org/show_bug.cgi?id=619025 --- src/st/st-widget.c | 56 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/st/st-widget.c b/src/st/st-widget.c index e3b0547b7..d90586826 100644 --- a/src/st/st-widget.c +++ b/src/st/st-widget.c @@ -41,6 +41,7 @@ #include "st-texture-cache.h" #include "st-theme-context.h" #include "st-tooltip.h" +#include "st-theme-node-transition.h" /* * Forward declaration for sake of StWidgetChild @@ -53,6 +54,8 @@ struct _StWidgetPrivate gchar *style_class; gchar *inline_style; + StThemeNodeTransition *transition_animation; + gboolean is_stylable : 1; gboolean has_tooltip : 1; gboolean is_style_dirty : 1; @@ -236,6 +239,13 @@ st_widget_dispose (GObject *gobject) priv->theme_node = NULL; } + if (priv->transition_animation) + { + g_object_run_dispose (G_OBJECT (priv->transition_animation)); + g_object_unref (priv->transition_animation); + priv->transition_animation = NULL; + } + if (priv->tooltip) { ClutterContainer *parent; @@ -349,12 +359,20 @@ st_widget_paint (ClutterActor *actor) StWidget *self = ST_WIDGET (actor); StThemeNode *theme_node; ClutterActorBox allocation; + guint8 opacity; theme_node = st_widget_get_theme_node (self); clutter_actor_get_allocation_box (actor, &allocation); - st_theme_node_paint (theme_node, &allocation, clutter_actor_get_paint_opacity (actor)); + opacity = clutter_actor_get_paint_opacity (actor); + + if (self->priv->transition_animation) + st_theme_node_transition_paint (self->priv->transition_animation, + &allocation, + opacity); + else + st_theme_node_paint (theme_node, &allocation, opacity); } static void @@ -1185,21 +1203,57 @@ st_widget_init (StWidget *actor) actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor); priv->is_stylable = TRUE; + priv->transition_animation = NULL; /* connect style changed */ g_signal_connect (actor, "notify::name", G_CALLBACK (st_widget_name_notify), NULL); } +static void +on_transition_completed (StThemeNodeTransition *transition, + StWidget *widget) +{ + g_object_run_dispose (G_OBJECT (widget->priv->transition_animation)); + g_object_unref (widget->priv->transition_animation); + widget->priv->transition_animation = NULL; +} + static void st_widget_recompute_style (StWidget *widget, StThemeNode *old_theme_node) { StThemeNode *new_theme_node = st_widget_get_theme_node (widget); + int transition_duration; if (!old_theme_node || !st_theme_node_geometry_equal (old_theme_node, new_theme_node)) clutter_actor_queue_relayout ((ClutterActor *) widget); + transition_duration = st_theme_node_get_transition_duration (new_theme_node); + + if (transition_duration > 0) + { + if (widget->priv->transition_animation != NULL) + { + st_theme_node_transition_update (widget->priv->transition_animation, + new_theme_node); + } + else if (old_theme_node) + { + widget->priv->transition_animation = + st_theme_node_transition_new (old_theme_node, + new_theme_node, + transition_duration); + + g_signal_connect (widget->priv->transition_animation, "completed", + G_CALLBACK (on_transition_completed), widget); + g_signal_connect_swapped (widget->priv->transition_animation, + "new-frame", + G_CALLBACK (clutter_actor_queue_redraw), + widget); + } + } + g_signal_emit (widget, signals[STYLE_CHANGED], 0); widget->priv->is_style_dirty = FALSE; }