svn update: 51469 (latest:51480)
[framework/uifw/elementary.git] / src / lib / elm_animator.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @addtogroup Animator Animator
6  * @ingroup Elementary
7  *
8  * Support normalized frame value for animation.  
9 */
10
11 struct _Animator
12 {
13    Evas_Object *parent;
14    Ecore_Animator *animator;
15    double begin_time;
16    double cur_time;
17    double duration;
18    unsigned int repeat_cnt;
19    unsigned int cur_repeat_cnt;
20    double (*curve_op) (double frame);
21    void (*animator_op) (void *data, Elm_Animator *animator, double frame);
22    void *animator_arg;
23    void (*completion_op) (void *data);
24    void *completion_arg;
25    Eina_Bool auto_reverse:1;
26    Eina_Bool on_animating:1;
27 };
28
29 static double _animator_curve_linear(double frame);
30 static double _animator_curve_in_out(double frame);
31 static double _animator_curve_in(double frame);
32 static double _animator_curve_out(double frame);
33 static unsigned int _animator_compute_reverse_repeat_count(unsigned int cnt);
34 static unsigned int _animator_compute_no_reverse_repeat_count(unsigned int cnt);
35 static Eina_Bool _animator_animate_cb(void *data);
36 static void _delete_animator(Elm_Animator *animator);
37 static void _animator_parent_del(void *data, Evas *evas, Evas_Object *obj, void *event);
38
39 static unsigned int
40 _animator_compute_reverse_repeat_count(unsigned int cnt)
41 {
42    return ((cnt + 1) * 2) - 1;
43 }
44
45 static unsigned int
46 _animator_compute_no_reverse_repeat_count(unsigned int cnt)
47 {
48    return cnt / 2;
49 }
50
51 static double
52 _animator_curve_linear(double frame)
53 {
54    return frame;
55 }
56
57 static double
58 _animator_curve_in_out(double frame)
59 {
60    if (frame < 0.5)
61      return _animator_curve_out(frame * 2) * 0.5;
62    else
63      return (_animator_curve_in(frame * 2 - 1) * 0.5) + 0.5;
64 }
65
66 static double
67 _animator_curve_in(double frame)
68 {
69    return sqrt(1 - pow(frame - 1, 2));
70 }
71
72 static double
73 _animator_curve_out(double frame)
74 {
75    return 1 - sqrt(1 - pow(frame, 2));
76 }
77
78 static void
79 _delete_animator(Elm_Animator *animator)
80 {
81    if (animator->animator)
82      {
83         ecore_animator_del(animator->animator);
84         animator->animator = NULL;
85      }
86 }
87
88 static Eina_Bool
89 _animator_animate_cb(void *data)
90 {
91    Elm_Animator *animator = (Elm_Animator *) data;
92
93    animator->cur_time = ecore_loop_time_get();
94    double elapsed_time = animator->cur_time - animator->begin_time;
95
96    if (elapsed_time > animator->duration)
97      elapsed_time = animator->duration;
98
99    double frame = animator->curve_op(elapsed_time / animator->duration);
100
101    //Reverse?
102    if (animator->auto_reverse)
103      {
104         if ((animator->cur_repeat_cnt % 2) == 0)
105           frame = 1 - frame;
106      }
107
108    if (animator->duration > 0)
109      animator->animator_op(animator->animator_arg, animator, frame);
110
111    //Not end. Keep going.
112    if (elapsed_time < animator->duration)
113      return ECORE_CALLBACK_RENEW;
114
115    //Repeat and reverse and time done! 
116    if (animator->cur_repeat_cnt == 0)
117      {
118         animator->on_animating = EINA_FALSE;
119         _delete_animator(animator);
120         if (animator->completion_op)
121           animator->completion_op(animator->completion_arg);
122         return ECORE_CALLBACK_CANCEL;
123      }
124
125    //Repeat Case
126    --animator->cur_repeat_cnt;
127    animator->begin_time = ecore_loop_time_get();
128
129    return ECORE_CALLBACK_RENEW;
130 }
131
132 static void 
133 _animator_parent_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
134 {
135    elm_animator_del(data);
136 }
137
138 /**
139  * Get the value of reverse mode. 
140  *
141  * @param animator Animator object
142  * @return EINA_TRUE is reverse mode 
143  *
144  * @ingroup Animator 
145  */
146 EAPI Eina_Bool
147 elm_animator_auto_reverse_get(Elm_Animator *animator)
148 {
149    if (!animator) return EINA_FALSE;
150    return animator->auto_reverse;
151 }
152
153 /**
154  * Get the value of repeat count.
155  *
156  * @param animator Animator object
157  * @return Repeat count
158  *
159  * @ingroup Animator 
160  */
161 EAPI unsigned int
162 elm_animator_repeat_get(Elm_Animator *animator)
163 {
164    if (!animator) return EINA_FALSE;
165    return animator->repeat_cnt;
166 }
167
168 /**
169  * Set auto reverse function.  
170  *
171  * @param animator Animator object
172  * @param reverse Reverse or not
173  * 
174  * @ingroup Animator 
175  */
176 EAPI void
177 elm_animator_auto_reverse_set(Elm_Animator *animator, Eina_Bool reverse)
178 {
179    if (!animator) return;
180    if (animator->auto_reverse == reverse) return;
181    animator->auto_reverse = reverse;
182    if (reverse) 
183      {
184         animator->repeat_cnt =
185           _animator_compute_reverse_repeat_count(animator->repeat_cnt);
186      }
187    else 
188      {
189         animator->repeat_cnt =
190           _animator_compute_no_reverse_repeat_count(animator->repeat_cnt);
191      }
192 }
193
194 /**
195  * Set the animation acceleration style. 
196  *
197  * @param animator Animator object
198  * @param cs Curve style. Default is ELM_ANIMATOR_CURVE_LINEAR 
199  *
200  * @ingroup Animator
201  */
202 EAPI void
203 elm_animator_curve_style_set(Elm_Animator *animator, Elm_Animator_Curve_Style cs)
204 {
205    if (!animator) return;
206    switch (cs)
207      {
208       case ELM_ANIMATOR_CURVE_LINEAR:
209         animator->curve_op = _animator_curve_linear;
210         break;
211       case ELM_ANIMATOR_CURVE_IN_OUT:
212         animator->curve_op = _animator_curve_in_out;
213         break;
214       case ELM_ANIMATOR_CURVE_IN:
215         animator->curve_op = _animator_curve_in;
216         break;
217       case ELM_ANIMATOR_CURVE_OUT:
218         animator->curve_op = _animator_curve_out;
219         break;
220       default:
221         animator->curve_op = _animator_curve_linear;
222         break;
223      }
224 }
225
226 /**
227  * Set the operation duration.  
228  *
229  * @param animator Animator object
230  * @param duration Duration in second 
231  *
232  * @ingroup Animator
233  */
234 EAPI void
235 elm_animator_duration_set(Elm_Animator *animator, double duration)
236 {
237    if (!animator) return;
238    if (animator->on_animating) return;
239    animator->duration = duration;
240 }
241
242 /**
243  * Set the callback function for animator operation.  
244  * The range of callback function frame data is to 0 ~ 1
245  * User can refer this frame value for one's animation frame data. 
246  * @param animator Animator object
247  * @param op Callback function pointer 
248  * @param data Callback function user argument 
249  *
250  * @ingroup Animator
251  */
252 EAPI void
253 elm_animator_operation_callback_set(Elm_Animator *animator,
254                                     void (*func) (void *data,
255                                                   Elm_Animator *animator,
256                                                   double frame), void *data)
257 {
258    if (!animator) return;
259    if (animator->on_animating) return;
260    animator->animator_op = func;
261    animator->animator_arg = data;
262 }
263
264 /**
265  * Add new animator. 
266  *
267  * @param parent Parent object
268  * @return animator object 
269  *
270  * @ingroup Animator
271  */
272 EAPI Elm_Animator *
273 elm_animator_add(Evas_Object *parent)
274 {
275    Elm_Animator *animator = calloc(1, sizeof(Elm_Animator));
276
277    if (!animator) return NULL;
278    elm_animator_auto_reverse_set(animator, EINA_FALSE);
279    elm_animator_curve_style_set(animator, ELM_ANIMATOR_CURVE_LINEAR);
280
281    if (parent)
282      evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
283                                     _animator_parent_del, animator);
284
285    animator->parent = parent;
286
287    return animator;
288 }
289
290 /**
291  * Get the status for the animator operation.
292  *
293  * @param animator Animator object 
294  * @return EINA_TRUE is animator is operating. 
295  *
296  * @ingroup Animator
297  */
298 EAPI Eina_Bool
299 elm_animator_operating_get(Elm_Animator *animator)
300 {
301    if (!animator) return EINA_FALSE;
302    return animator->on_animating;
303 }
304
305 /**
306  * Delete animator. 
307  *
308  * @param animator Animator object 
309  *
310  * @ingroup Animator
311  */
312 EAPI void
313 elm_animator_del(Elm_Animator *animator)
314 {
315    if (!animator) return;
316    _delete_animator(animator);
317
318    if(animator->parent) 
319      evas_object_event_callback_del(animator->parent, EVAS_CALLBACK_DEL, 
320                                     _animator_parent_del);
321    free(animator);
322 }
323
324 /**
325  * Set the callback function for the animator end.  
326  *
327  * @param  animator Animator object 
328  * @param  op Callback function pointer
329  * @param  data Callback function user argument 
330  *
331  * @ingroup Animator
332  */
333 EAPI void
334 elm_animator_completion_callback_set(Elm_Animator *animator, 
335                                      void (*func) (void *data), void *data)
336 {
337    if (!animator) return;
338    if (animator->on_animating) return;
339    animator->completion_op = func;
340    animator->completion_arg = data;
341 }
342
343 /**
344  * Stop animator.
345  *
346  * @param animator Animator object 
347  *
348  * @ingroup Animator
349  */
350 EAPI void
351 elm_animator_stop(Elm_Animator *animator)
352 {
353    if (!animator) return;
354    animator->on_animating = EINA_FALSE;
355    _delete_animator(animator);
356 }
357
358 /**
359  * Set the animator repeat count.
360  *
361  * @param  animator Animator object
362  * @param  repeat_cnt Repeat count
363  *
364  * @ingroup Animator
365  */
366 EAPI void
367 elm_animator_repeat_set(Elm_Animator *animator, unsigned int repeat_cnt)
368 {
369    if (!animator) return;
370    if (!animator->auto_reverse)
371       animator->repeat_cnt = repeat_cnt;
372    else 
373      {
374         animator->repeat_cnt = 
375           _animator_compute_reverse_repeat_count(repeat_cnt);
376      }
377 }
378
379 /**
380  * Animate now.
381  *
382  * @param animator Animator object
383  *
384  * @ingroup Animator
385  */
386 EAPI void
387 elm_animator_animate(Elm_Animator *animator)
388 {
389    if (!animator) return;
390    if (!animator->animator_op) return;
391    animator->begin_time = ecore_loop_time_get();
392    animator->on_animating = EINA_TRUE;
393    animator->cur_repeat_cnt = animator->repeat_cnt;
394    if (!animator->animator) 
395      animator->animator = ecore_animator_add(_animator_animate_cb, animator);
396    if (!animator->animator)
397      animator->on_animating = EINA_FALSE;
398 }