[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
This commit is contained in:
parent
d4a8c64d22
commit
db45c0920b
@ -41,6 +41,7 @@
|
|||||||
#include "st-texture-cache.h"
|
#include "st-texture-cache.h"
|
||||||
#include "st-theme-context.h"
|
#include "st-theme-context.h"
|
||||||
#include "st-tooltip.h"
|
#include "st-tooltip.h"
|
||||||
|
#include "st-theme-node-transition.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declaration for sake of StWidgetChild
|
* Forward declaration for sake of StWidgetChild
|
||||||
@ -53,6 +54,8 @@ struct _StWidgetPrivate
|
|||||||
gchar *style_class;
|
gchar *style_class;
|
||||||
gchar *inline_style;
|
gchar *inline_style;
|
||||||
|
|
||||||
|
StThemeNodeTransition *transition_animation;
|
||||||
|
|
||||||
gboolean is_stylable : 1;
|
gboolean is_stylable : 1;
|
||||||
gboolean has_tooltip : 1;
|
gboolean has_tooltip : 1;
|
||||||
gboolean is_style_dirty : 1;
|
gboolean is_style_dirty : 1;
|
||||||
@ -236,6 +239,13 @@ st_widget_dispose (GObject *gobject)
|
|||||||
priv->theme_node = NULL;
|
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)
|
if (priv->tooltip)
|
||||||
{
|
{
|
||||||
ClutterContainer *parent;
|
ClutterContainer *parent;
|
||||||
@ -349,12 +359,20 @@ st_widget_paint (ClutterActor *actor)
|
|||||||
StWidget *self = ST_WIDGET (actor);
|
StWidget *self = ST_WIDGET (actor);
|
||||||
StThemeNode *theme_node;
|
StThemeNode *theme_node;
|
||||||
ClutterActorBox allocation;
|
ClutterActorBox allocation;
|
||||||
|
guint8 opacity;
|
||||||
|
|
||||||
theme_node = st_widget_get_theme_node (self);
|
theme_node = st_widget_get_theme_node (self);
|
||||||
|
|
||||||
clutter_actor_get_allocation_box (actor, &allocation);
|
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
|
static void
|
||||||
@ -1185,21 +1203,57 @@ st_widget_init (StWidget *actor)
|
|||||||
|
|
||||||
actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor);
|
actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor);
|
||||||
priv->is_stylable = TRUE;
|
priv->is_stylable = TRUE;
|
||||||
|
priv->transition_animation = NULL;
|
||||||
|
|
||||||
/* connect style changed */
|
/* connect style changed */
|
||||||
g_signal_connect (actor, "notify::name", G_CALLBACK (st_widget_name_notify), NULL);
|
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
|
static void
|
||||||
st_widget_recompute_style (StWidget *widget,
|
st_widget_recompute_style (StWidget *widget,
|
||||||
StThemeNode *old_theme_node)
|
StThemeNode *old_theme_node)
|
||||||
{
|
{
|
||||||
StThemeNode *new_theme_node = st_widget_get_theme_node (widget);
|
StThemeNode *new_theme_node = st_widget_get_theme_node (widget);
|
||||||
|
int transition_duration;
|
||||||
|
|
||||||
if (!old_theme_node ||
|
if (!old_theme_node ||
|
||||||
!st_theme_node_geometry_equal (old_theme_node, new_theme_node))
|
!st_theme_node_geometry_equal (old_theme_node, new_theme_node))
|
||||||
clutter_actor_queue_relayout ((ClutterActor *) widget);
|
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);
|
g_signal_emit (widget, signals[STYLE_CHANGED], 0);
|
||||||
widget->priv->is_style_dirty = FALSE;
|
widget->priv->is_style_dirty = FALSE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user