Merge branch 'master' of wh0705.jung@165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL...
[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_out(frame * 2) * 0.5;
61    else
62       return (_animator_curve_in(frame * 2 - 1) * 0.5) + 0.5;
63 }
64
65 static double
66 _animator_curve_in(double frame)
67 {
68    return sqrt(1 - pow(frame - 1, 2));
69 }
70
71 static double
72 _animator_curve_out(double frame)
73 {
74    return 1 - sqrt(1 - pow(frame, 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
92    animator->cur_time = ecore_loop_time_get();
93    double elapsed_time = animator->cur_time - animator->begin_time;
94
95    if (elapsed_time > animator->duration)
96       elapsed_time = animator->duration;
97
98    double frame = animator->curve_op(elapsed_time / animator->duration);
99
100    //Reverse?
101    if (animator->auto_reverse)
102      {
103         if ((animator->cur_repeat_cnt % 2) == 0)
104            frame = 1 - frame;
105      }
106
107    if (animator->duration > 0)
108       animator->animator_op(animator->animator_arg, animator, frame);
109
110    //Not end. Keep going.
111    if (elapsed_time < animator->duration)
112       return ECORE_CALLBACK_RENEW;
113
114    //Repeat and reverse and time done! 
115    if (animator->cur_repeat_cnt == 0)
116      {
117         animator->on_animating = EINA_FALSE;
118         _delete_animator(animator);
119         if (animator->completion_op)
120            animator->completion_op(animator->completion_arg);
121         return ECORE_CALLBACK_CANCEL;
122      }
123
124    //Repeat Case
125    --animator->cur_repeat_cnt;
126    animator->begin_time = ecore_loop_time_get();
127
128    return ECORE_CALLBACK_RENEW;
129 }
130
131 static void
132 _animator_parent_del(void *data)
133 {
134    elm_animator_del(data);
135 }
136
137 /**
138  * Get the value of reverse mode. 
139  *
140  * @param animator Animator object
141  * @return EINA_TRUE is reverse mode 
142  *
143  * @ingroup Animator 
144  */
145 EAPI Eina_Bool
146 elm_animator_auto_reverse_get(Elm_Animator *animator)
147 {
148    if (!animator)
149       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)
165       return EINA_FALSE;
166    return animator->repeat_cnt;
167 }
168
169 /**
170  * Set auto reverse function.  
171  *
172  * @param animator Animator object
173  * @param reverse Reverse or not
174  * 
175  * @ingroup Animator 
176  */
177 EAPI void
178 elm_animator_auto_reverse_set(Elm_Animator *animator, Eina_Bool reverse)
179 {
180    if (!animator)
181       return;
182    if (animator->auto_reverse == reverse)
183       return;
184    animator->auto_reverse = reverse;
185    if (reverse)
186       animator->repeat_cnt =
187          _animator_compute_reverse_repeat_count(animator->repeat_cnt);
188    else
189       animator->repeat_cnt =
190          _animator_compute_no_reverse_repeat_count(animator->repeat_cnt);
191 }
192
193 /**
194  * Set the animation acceleration style. 
195  *
196  * @param animator Animator object
197  * @param cs Curve style. Default is ELM_ANIMATOR_CURVE_LINEAR 
198  *
199  * @ingroup Animator
200  */
201 EAPI void
202 elm_animator_curve_style_set(Elm_Animator *animator,
203                              Elm_Animator_Curve_Style cs)
204 {
205    if (!animator)
206       return;
207
208    switch (cs)
209      {
210      case ELM_ANIMATOR_CURVE_LINEAR:
211         animator->curve_op = _animator_curve_linear;
212         break;
213      case ELM_ANIMATOR_CURVE_IN_OUT:
214         animator->curve_op = _animator_curve_in_out;
215         break;
216      case ELM_ANIMATOR_CURVE_IN:
217         animator->curve_op = _animator_curve_in;
218         break;
219      case ELM_ANIMATOR_CURVE_OUT:
220         animator->curve_op = _animator_curve_out;
221         break;
222      default:
223         animator->curve_op = _animator_curve_linear;
224         break;
225      }
226 }
227
228 /**
229  * Set the operation duration.  
230  *
231  * @param animator Animator object
232  * @param duration Duration in second 
233  *
234  * @ingroup Animator
235  */
236 EAPI void
237 elm_animator_duration_set(Elm_Animator *animator, double duration)
238 {
239    if (!animator)
240       return;
241    if (animator->on_animating)
242       return;
243    animator->duration = duration;
244 }
245
246 /**
247  * Set the callback function for animator operation.  
248  * The range of callback function frame data is to 0 ~ 1
249  * User can refer this frame value for one's animation frame data. 
250  * @param animator Animator object
251  * @param op Callback function pointer 
252  * @param data Callback function user argument 
253  *
254  * @ingroup Animator
255  */
256 EAPI void
257 elm_animator_operation_callback_set(Elm_Animator *animator,
258                                     void (*func) (void *data,
259                                                   Elm_Animator *animator,
260                                                   double frame), void *data)
261 {
262    if (!animator)
263       return;
264    if (animator->on_animating)
265       return;
266    animator->animator_op = func;
267    animator->animator_arg = data;
268 }
269
270 /**
271  * Add new animator. 
272  *
273  * @param parent Parent object
274  * @return animator object 
275  *
276  * @ingroup Animator
277  */
278 EAPI Elm_Animator *
279 elm_animator_add(Evas_Object *parent)
280 {
281    Elm_Animator *animator = calloc(1, sizeof(Elm_Animator));
282
283    if (!animator)
284       return NULL;
285    elm_animator_auto_reverse_set(animator, EINA_FALSE);
286    elm_animator_curve_style_set(animator, ELM_ANIMATOR_CURVE_LINEAR);
287
288    if (parent)
289       evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
290                                      _animator_parent_del, animator);
291
292    animator->parent = parent;
293
294    return animator;
295 }
296
297 /**
298  * Get the status for the animator operation.
299  *
300  * @param animator Animator object 
301  * @return EINA_TRUE is animator is operating. 
302  *
303  * @ingroup Animator
304  */
305 EAPI Eina_Bool
306 elm_animator_operating_get(Elm_Animator *animator)
307 {
308    if (!animator)
309       return EINA_FALSE;
310    return animator->on_animating;
311 }
312
313 /**
314  * Delete animator. 
315  *
316  * @param animator Animator object 
317  *
318  * @ingroup Animator
319  */
320 EAPI void
321 elm_animator_del(Elm_Animator *animator)
322 {
323    if (!animator)
324       return;
325    _delete_animator(animator);
326    
327    if(animator->parent) 
328         evas_object_event_callback_del(animator->parent, EVAS_CALLBACK_DEL, _animator_parent_del);
329    free(animator);
330 }
331
332 /**
333  * Set the callback function for the animator end.  
334  *
335  * @param  animator Animator object 
336  * @param  op Callback function pointer
337  * @param  data Callback function user argument 
338  *
339  * @ingroup Animator
340  */
341 EAPI void
342 elm_animator_completion_callback_set(Elm_Animator *animator,
343                                      void (*func) (void *data), void *data)
344 {
345    if (!animator)
346       return;
347    if (animator->on_animating)
348       return;
349    animator->completion_op = func;
350    animator->completion_arg = data;
351 }
352
353 /**
354  * Stop animator.
355  *
356  * @param animator Animator object 
357  *
358  * @ingroup Animator
359  */
360 EAPI void
361 elm_animator_stop(Elm_Animator *animator)
362 {
363    if (!animator)
364       return;
365    animator->on_animating = EINA_FALSE;
366    _delete_animator(animator);
367 }
368
369 /**
370  * Set the animator repeat count.
371  *
372  * @param  animator Animator object
373  * @param  repeat_cnt Repeat count
374  *
375  * @ingroup Animator
376  */
377 EAPI void
378 elm_animator_repeat_set(Elm_Animator *animator, unsigned int repeat_cnt)
379 {
380    if (!animator)
381       return;
382    if (!animator->auto_reverse)
383       animator->repeat_cnt = repeat_cnt;
384    else
385       animator->repeat_cnt = _animator_compute_reverse_repeat_count(repeat_cnt);
386 }
387
388 /**
389  * Animate now.
390  *
391  * @param animator Animator object
392  *
393  * @ingroup Animator
394  */
395 EAPI void
396 elm_animator_animate(Elm_Animator *animator)
397 {
398    if (!animator)
399       return;
400    if (!animator->animator_op)
401       return;
402    animator->begin_time = ecore_loop_time_get();
403    animator->on_animating = EINA_TRUE;
404    animator->cur_repeat_cnt = animator->repeat_cnt;
405    if (!animator->animator) 
406       animator->animator = ecore_animator_add(_animator_animate_cb, animator);
407    if (!animator->animator)
408       animator->on_animating = EINA_FALSE;
409 }