1 /*
2 * Clutter.
3 *
4 * An OpenGL based 'interactive canvas' library.
5 *
6 * Copyright (C) 2012 Intel Corporation
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * Author: Emmanuele Bassi <ebassi@linux.intel.com>
22 */
23
24 /**
25 * SECTION:clutter-transition-group
26 * @Title: ClutterTransitionGroup
27 * @Short_Description: Group transitions together
28 *
29 * The #ClutterTransitionGroup allows running multiple #ClutterTransition
30 * instances concurrently.
31 *
32 * The transitions inside a group will run within the boundaries of the
33 * group; for instance, if a transition has a duration of 10 seconds, and
34 * the group that contains it has a duration of 5 seconds, only the first
35 * 5 seconds of the transition will be played.
36 *
37 * #ClutterTransitionGroup is available since Clutter 1.12
38 */
39
40 #include "clutter-build-config.h"
41
42 #include "clutter-transition-group.h"
43
44 #include "clutter-debug.h"
45 #include "clutter-private.h"
46 #include "clutter-timeline-private.h"
47
48 struct _ClutterTransitionGroupPrivate
49 {
50 GHashTable *transitions;
51 };
52
G_DEFINE_TYPE_WITH_PRIVATE(ClutterTransitionGroup,clutter_transition_group,CLUTTER_TYPE_TRANSITION)53 G_DEFINE_TYPE_WITH_PRIVATE (ClutterTransitionGroup, clutter_transition_group, CLUTTER_TYPE_TRANSITION)
54
55 static void
56 clutter_transition_group_new_frame (ClutterTimeline *timeline,
57 gint elapsed)
58 {
59 ClutterTransitionGroupPrivate *priv;
60 GHashTableIter iter;
61 gpointer element;
62 gint64 msecs;
63
64 priv = CLUTTER_TRANSITION_GROUP (timeline)->priv;
65
66 /* get the time elapsed since the last ::new-frame... */
67 msecs = clutter_timeline_get_delta (timeline);
68
69 g_hash_table_iter_init (&iter, priv->transitions);
70 while (g_hash_table_iter_next (&iter, &element, NULL))
71 {
72 ClutterTimeline *t = element;
73
74 /* ... and advance every timeline */
75 clutter_timeline_set_direction (t, clutter_timeline_get_direction (timeline));
76 clutter_timeline_set_duration (t, clutter_timeline_get_duration (timeline));
77
78 _clutter_timeline_advance (t, msecs);
79 }
80 }
81
82 static void
clutter_transition_group_attached(ClutterTransition * transition,ClutterAnimatable * animatable)83 clutter_transition_group_attached (ClutterTransition *transition,
84 ClutterAnimatable *animatable)
85 {
86 ClutterTransitionGroupPrivate *priv;
87 GHashTableIter iter;
88 gpointer element;
89
90 priv = CLUTTER_TRANSITION_GROUP (transition)->priv;
91
92 g_hash_table_iter_init (&iter, priv->transitions);
93 while (g_hash_table_iter_next (&iter, &element, NULL))
94 {
95 ClutterTransition *t = element;
96
97 clutter_transition_set_animatable (t, animatable);
98 }
99 }
100
101 static void
clutter_transition_group_detached(ClutterTransition * transition,ClutterAnimatable * animatable)102 clutter_transition_group_detached (ClutterTransition *transition,
103 ClutterAnimatable *animatable)
104 {
105 ClutterTransitionGroupPrivate *priv;
106 GHashTableIter iter;
107 gpointer element;
108
109 priv = CLUTTER_TRANSITION_GROUP (transition)->priv;
110
111 g_hash_table_iter_init (&iter, priv->transitions);
112 while (g_hash_table_iter_next (&iter, &element, NULL))
113 {
114 ClutterTransition *t = element;
115
116 clutter_transition_set_animatable (t, NULL);
117 }
118 }
119
120 static void
clutter_transition_group_started(ClutterTimeline * timeline)121 clutter_transition_group_started (ClutterTimeline *timeline)
122 {
123 ClutterTransitionGroupPrivate *priv;
124 GHashTableIter iter;
125 gpointer element;
126
127 priv = CLUTTER_TRANSITION_GROUP (timeline)->priv;
128
129 g_hash_table_iter_init (&iter, priv->transitions);
130 while (g_hash_table_iter_next (&iter, &element, NULL))
131 {
132 ClutterTransition *t = element;
133
134 g_signal_emit_by_name (t, "started");
135 }
136 }
137
138 static void
clutter_transition_group_finalize(GObject * gobject)139 clutter_transition_group_finalize (GObject *gobject)
140 {
141 ClutterTransitionGroupPrivate *priv;
142
143 priv = CLUTTER_TRANSITION_GROUP (gobject)->priv;
144
145 g_hash_table_unref (priv->transitions);
146
147 G_OBJECT_CLASS (clutter_transition_group_parent_class)->finalize (gobject);
148 }
149
150 static void
clutter_transition_group_class_init(ClutterTransitionGroupClass * klass)151 clutter_transition_group_class_init (ClutterTransitionGroupClass *klass)
152 {
153 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
154 ClutterTimelineClass *timeline_class = CLUTTER_TIMELINE_CLASS (klass);
155 ClutterTransitionClass *transition_class = CLUTTER_TRANSITION_CLASS (klass);
156
157 gobject_class->finalize = clutter_transition_group_finalize;
158
159 timeline_class->started = clutter_transition_group_started;
160 timeline_class->new_frame = clutter_transition_group_new_frame;
161
162 transition_class->attached = clutter_transition_group_attached;
163 transition_class->detached = clutter_transition_group_detached;
164 }
165
166 static void
clutter_transition_group_init(ClutterTransitionGroup * self)167 clutter_transition_group_init (ClutterTransitionGroup *self)
168 {
169 self->priv = clutter_transition_group_get_instance_private (self);
170 self->priv->transitions =
171 g_hash_table_new_full (NULL, NULL, (GDestroyNotify) g_object_unref, NULL);
172 }
173
174 /**
175 * clutter_transition_group_new:
176 *
177 * Creates a new #ClutterTransitionGroup instance.
178 *
179 * Return value: the newly created #ClutterTransitionGroup. Use
180 * g_object_unref() when done to deallocate the resources it
181 * uses
182 *
183 * Since: 1.12
184 */
185 ClutterTransition *
clutter_transition_group_new(void)186 clutter_transition_group_new (void)
187 {
188 return g_object_new (CLUTTER_TYPE_TRANSITION_GROUP, NULL);
189 }
190
191 /**
192 * clutter_transition_group_add_transition:
193 * @group: a #ClutterTransitionGroup
194 * @transition: a #ClutterTransition
195 *
196 * Adds @transition to @group.
197 *
198 * This function acquires a reference on @transition that will be released
199 * when calling clutter_transition_group_remove_transition().
200 *
201 * Since: 1.12
202 */
203 void
clutter_transition_group_add_transition(ClutterTransitionGroup * group,ClutterTransition * transition)204 clutter_transition_group_add_transition (ClutterTransitionGroup *group,
205 ClutterTransition *transition)
206 {
207 g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group));
208 g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
209
210 g_hash_table_add (group->priv->transitions, g_object_ref (transition));
211 }
212
213 /**
214 * clutter_transition_group_remove_transition:
215 * @group: a #ClutterTransitionGroup
216 * @transition: a #ClutterTransition
217 *
218 * Removes @transition from @group.
219 *
220 * This function releases the reference acquired on @transition when
221 * calling clutter_transition_group_add_transition().
222 *
223 * Since: 1.12
224 */
225 void
clutter_transition_group_remove_transition(ClutterTransitionGroup * group,ClutterTransition * transition)226 clutter_transition_group_remove_transition (ClutterTransitionGroup *group,
227 ClutterTransition *transition)
228 {
229 g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group));
230
231 g_hash_table_remove (group->priv->transitions, transition);
232 }
233
234 /**
235 * clutter_transition_group_remove_all:
236 * @group: a #ClutterTransitionGroup
237 *
238 * Removes all transitions from @group.
239 *
240 * This function releases the reference acquired when calling
241 * clutter_transition_group_add_transition().
242 *
243 * Since: 1.12
244 */
245 void
clutter_transition_group_remove_all(ClutterTransitionGroup * group)246 clutter_transition_group_remove_all (ClutterTransitionGroup *group)
247 {
248 g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group));
249
250 g_hash_table_remove_all (group->priv->transitions);
251 }
252