Release Clutter 1.11.4 (snapshot)
[profile/ivi/clutter.git] / clutter / clutter-transition-group.c
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 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #include "clutter-transition-group.h"
45
46 #include "clutter-debug.h"
47 #include "clutter-private.h"
48
49 struct _ClutterTransitionGroupPrivate
50 {
51   GHashTable *transitions;
52 };
53
54 G_DEFINE_TYPE (ClutterTransitionGroup, clutter_transition_group, CLUTTER_TYPE_TRANSITION)
55
56 static void
57 clutter_transition_group_new_frame (ClutterTimeline *timeline,
58                                     gint             elapsed)
59 {
60   ClutterTransitionGroupPrivate *priv;
61   GHashTableIter iter;
62   gpointer element;
63   gint64 msecs;
64
65   priv = CLUTTER_TRANSITION_GROUP (timeline)->priv;
66
67   /* get the time elapsed since the last ::new-frame... */
68   msecs = clutter_timeline_get_delta (timeline);
69
70   g_hash_table_iter_init (&iter, priv->transitions);
71   while (g_hash_table_iter_next (&iter, &element, NULL))
72     {
73       ClutterTimeline *t = element;
74
75       /* ... and advance every timeline */
76       clutter_timeline_set_direction (t, clutter_timeline_get_direction (timeline));
77       clutter_timeline_set_duration (t, clutter_timeline_get_duration (timeline));
78
79       _clutter_timeline_advance (t, msecs);
80     }
81 }
82
83 static void
84 clutter_transition_group_attached (ClutterTransition *transition,
85                                    ClutterAnimatable *animatable)
86 {
87   ClutterTransitionGroupPrivate *priv;
88   GHashTableIter iter;
89   gpointer element;
90
91   priv = CLUTTER_TRANSITION_GROUP (transition)->priv;
92
93   g_hash_table_iter_init (&iter, priv->transitions);
94   while (g_hash_table_iter_next (&iter, &element, NULL))
95     {
96       ClutterTransition *t = element;
97
98       clutter_transition_set_animatable (t, animatable);
99     }
100 }
101
102 static void
103 clutter_transition_group_detached (ClutterTransition *transition,
104                                    ClutterAnimatable *animatable)
105 {
106   ClutterTransitionGroupPrivate *priv;
107   GHashTableIter iter;
108   gpointer element;
109
110   priv = CLUTTER_TRANSITION_GROUP (transition)->priv;
111
112   g_hash_table_iter_init (&iter, priv->transitions);
113   while (g_hash_table_iter_next (&iter, &element, NULL))
114     {
115       ClutterTransition *t = element;
116
117       clutter_transition_set_animatable (t, NULL);
118     }
119 }
120
121 static void
122 clutter_transition_group_started (ClutterTimeline *timeline)
123 {
124   ClutterTransitionGroupPrivate *priv;
125   GHashTableIter iter;
126   gpointer element;
127
128   priv = CLUTTER_TRANSITION_GROUP (timeline)->priv;
129
130   g_hash_table_iter_init (&iter, priv->transitions);
131   while (g_hash_table_iter_next (&iter, &element, NULL))
132     {
133       ClutterTransition *t = element;
134
135       g_signal_emit_by_name (t, "started");
136     }
137 }
138
139 static void
140 clutter_transition_group_finalize (GObject *gobject)
141 {
142   ClutterTransitionGroupPrivate *priv;
143
144   priv = CLUTTER_TRANSITION_GROUP (gobject)->priv;
145
146   g_hash_table_unref (priv->transitions);
147
148   G_OBJECT_CLASS (clutter_transition_group_parent_class)->finalize (gobject);
149 }
150
151 static void
152 clutter_transition_group_class_init (ClutterTransitionGroupClass *klass)
153 {
154   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
155   ClutterTimelineClass *timeline_class = CLUTTER_TIMELINE_CLASS (klass);
156   ClutterTransitionClass *transition_class = CLUTTER_TRANSITION_CLASS (klass);
157
158   g_type_class_add_private (klass, sizeof (ClutterTransitionGroupPrivate));
159
160   gobject_class->finalize = clutter_transition_group_finalize;
161
162   timeline_class->started = clutter_transition_group_started;
163   timeline_class->new_frame = clutter_transition_group_new_frame;
164
165   transition_class->attached = clutter_transition_group_attached;
166   transition_class->detached = clutter_transition_group_detached;
167 }
168
169 static void
170 clutter_transition_group_init (ClutterTransitionGroup *self)
171 {
172   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
173                                             CLUTTER_TYPE_TRANSITION_GROUP,
174                                             ClutterTransitionGroupPrivate);
175
176   self->priv->transitions =
177     g_hash_table_new_full (NULL, NULL, (GDestroyNotify) g_object_unref, NULL);
178 }
179
180 /**
181  * clutter_transition_group_new:
182  *
183  * Creates a new #ClutterTransitionGroup instance.
184  *
185  * Return value: the newly created #ClutterTransitionGroup. Use
186  *   g_object_unref() when done to deallocate the resources it
187  *   uses
188  *
189  * Since: 1.12
190  */
191 ClutterTransition *
192 clutter_transition_group_new (void)
193 {
194   return g_object_new (CLUTTER_TYPE_TRANSITION_GROUP, NULL);
195 }
196
197 /**
198  * clutter_transition_group_add_transition:
199  * @group: a #ClutterTransitionGroup
200  * @transition: a #ClutterTransition
201  *
202  * Adds @transition to @group.
203  *
204  * This function acquires a reference on @transition that will be released
205  * when calling clutter_transition_group_remove_transition().
206  *
207  * Since: 1.12
208  */
209 void
210 clutter_transition_group_add_transition (ClutterTransitionGroup *group,
211                                          ClutterTransition      *transition)
212 {
213   g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group));
214   g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
215
216   g_hash_table_add (group->priv->transitions, g_object_ref (transition));
217 }
218
219 /**
220  * clutter_transition_group_remove_transition:
221  * @group: a #ClutterTransitionGroup
222  * @transition: a #ClutterTransition
223  *
224  * Removes @transition from @group.
225  *
226  * This function releases the reference acquired on @transition when
227  * calling clutter_transition_group_add_transition().
228  *
229  * Since: 1.12
230  */
231 void
232 clutter_transition_group_remove_transition (ClutterTransitionGroup *group,
233                                             ClutterTransition      *transition)
234 {
235   g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group));
236
237   g_hash_table_remove (group->priv->transitions, transition);
238 }
239
240 /**
241  * clutter_transition_group_remove_all:
242  * @group: a #ClutterTransitionGroup
243  *
244  * Removes all transitions from @group.
245  *
246  * This function releases the reference acquired when calling
247  * clutter_transition_group_add_transition().
248  *
249  * Since: 1.12
250  */
251 void
252 clutter_transition_group_remove_all (ClutterTransitionGroup *group)
253 {
254   g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group));
255
256   g_hash_table_remove_all (group->priv->transitions);
257 }