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