[SLP Merge] Thu Jul 7 13:20:56 2011 +0900
[framework/uifw/elementary.git] / src / lib / elm_animator.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define ELM_ANIMATOR_CHECK_OR_RETURN(animator, ...) \
5    do { \
6       if (!animator) { \
7          CRITICAL("Elm_Animator " # animator " is NULL!"); \
8          return __VA_ARGS__; \
9       } \
10       if (!EINA_MAGIC_CHECK(animator, ELM_ANIMATOR_MAGIC)) { \
11          EINA_MAGIC_FAIL(animator, ELM_ANIMATOR_MAGIC); \
12          return __VA_ARGS__; \
13       } \
14    } while (0)
15
16
17 struct _Elm_Animator
18 {
19 #define ELM_ANIMATOR_MAGIC 0x40777770
20    EINA_MAGIC;
21
22    Evas_Object *parent;
23    Ecore_Animator *animator;
24    double begin_time;
25    double cur_time;
26    double duration;
27    unsigned int repeat_cnt;
28    unsigned int cur_repeat_cnt;
29    void (*animator_op) (void *data, Elm_Animator *animator, double frame);
30    void *animator_arg;
31    void (*completion_op) (void *data);
32    void *completion_arg;
33    Elm_Animator_Curve_Style curve_style;
34    Eina_Bool auto_reverse:1;
35    Eina_Bool on_animating:1;
36 };
37
38 static double _animator_curve_linear(double frame);
39 static double _animator_curve_in_out(double frame);
40 static double _animator_curve_in(double frame);
41 static double _animator_curve_out(double frame);
42 static unsigned int _animator_compute_reverse_repeat_count(unsigned int cnt);
43 static unsigned int _animator_compute_no_reverse_repeat_count(unsigned int cnt);
44 static Eina_Bool _animator_animate_cb(void *data);
45 static void _delete_animator(Elm_Animator *animator);
46 static void _animator_parent_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__);
47
48 static unsigned int
49 _animator_compute_reverse_repeat_count(unsigned int cnt)
50 {
51    return ((cnt + 1) * 2) - 1;
52 }
53
54 static unsigned int
55 _animator_compute_no_reverse_repeat_count(unsigned int cnt)
56 {
57    return cnt / 2;
58 }
59
60 static double
61 _animator_curve_linear(double frame)
62 {
63    return frame;
64 }
65
66 static double
67 _animator_curve_in_out(double frame)
68 {
69    if (frame < 0.5) return _animator_curve_in(frame * 2) * 0.5;
70    else return (_animator_curve_out(frame * 2 - 1) * 0.5) + 0.5;
71 }
72
73 static double
74 _animator_curve_in(double frame)
75 {
76    return 1 - sqrt(1 - pow(frame, 2));
77 }
78
79 static double
80 _animator_curve_out(double frame)
81 {
82    return sqrt(1 - pow(frame - 1, 2));
83 }
84
85 static void
86 _delete_animator(Elm_Animator *animator)
87 {
88    if (!animator->animator) return;
89    ecore_animator_del(animator->animator);
90    animator->animator = NULL;
91 }
92
93 static Eina_Bool
94 _animator_animate_cb(void *data)
95 {
96    double elapsed_time, frame;
97    Elm_Animator *animator = (Elm_Animator *) data;
98
99    animator->cur_time = ecore_loop_time_get();
100    elapsed_time = animator->cur_time - animator->begin_time;
101    if (elapsed_time > animator->duration) elapsed_time = animator->duration;
102
103    //Compute current frame
104    switch (animator->curve_style)
105      {
106        case ELM_ANIMATOR_CURVE_IN_OUT:
107           frame = _animator_curve_in_out(elapsed_time / animator->duration);
108           break;
109        case ELM_ANIMATOR_CURVE_IN:
110           frame = _animator_curve_in(elapsed_time / animator->duration);
111           break;
112        case ELM_ANIMATOR_CURVE_OUT:
113           frame = _animator_curve_out(elapsed_time / animator->duration);
114           break;
115        default:
116           frame = _animator_curve_linear(elapsed_time / animator->duration);
117           break;
118      }
119
120    //Reverse?
121    if (animator->auto_reverse)
122      {
123         if (!(animator->cur_repeat_cnt % 2)) frame = 1 - frame;
124      }
125
126    if (animator->duration > 0)
127       animator->animator_op(animator->animator_arg, animator, frame);
128    //Not end. Keep going.
129    if (elapsed_time < animator->duration) return ECORE_CALLBACK_RENEW;
130
131    //Repeat and reverse and time done!
132    if (!animator->cur_repeat_cnt)
133      {
134         animator->on_animating = EINA_FALSE;
135         _delete_animator(animator);
136         if (animator->completion_op)
137           animator->completion_op(animator->completion_arg);
138         return ECORE_CALLBACK_CANCEL;
139      }
140
141    //Repeat Case
142    animator->cur_repeat_cnt--;
143    animator->begin_time = ecore_loop_time_get();
144
145    return ECORE_CALLBACK_RENEW;
146 }
147
148 static void
149 _animator_parent_del(void *data, Evas *evas __UNUSED__,
150                      Evas_Object *obj __UNUSED__, void *event __UNUSED__)
151 {
152    elm_animator_del(data);
153 }
154
155 EAPI Eina_Bool
156 elm_animator_auto_reverse_get(const Elm_Animator *animator)
157 {
158    ELM_ANIMATOR_CHECK_OR_RETURN(animator, EINA_FALSE);
159    return animator->auto_reverse;
160 }
161
162 EAPI unsigned int
163 elm_animator_repeat_get(const Elm_Animator *animator)
164 {
165    ELM_ANIMATOR_CHECK_OR_RETURN(animator, 0);
166    return animator->repeat_cnt;
167 }
168
169 EAPI Elm_Animator_Curve_Style
170 elm_animator_curve_style_get(const Elm_Animator *animator)
171 {
172    ELM_ANIMATOR_CHECK_OR_RETURN(animator, ELM_ANIMATOR_CURVE_LINEAR);
173    return animator->curve_style;
174 }
175
176 EAPI void
177 elm_animator_auto_reverse_set(Elm_Animator *animator, Eina_Bool reverse)
178 {
179    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
180    if (animator->auto_reverse == reverse) return;
181    animator->auto_reverse = reverse;
182    if (reverse)
183       animator->repeat_cnt =
184         _animator_compute_reverse_repeat_count(animator->repeat_cnt);
185    else
186       animator->repeat_cnt =
187         _animator_compute_no_reverse_repeat_count(animator->repeat_cnt);
188 }
189
190 EAPI void
191 elm_animator_curve_style_set(Elm_Animator *animator,
192                              Elm_Animator_Curve_Style cs)
193 {
194    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
195    animator->curve_style = cs;
196 }
197 EAPI void
198 elm_animator_duration_set(Elm_Animator *animator, double duration)
199 {
200    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
201    if (animator->on_animating) return;
202    animator->duration = duration;
203 }
204
205 EAPI void
206 elm_animator_operation_callback_set(Elm_Animator *animator,
207                                     Elm_Animator_Operation_Cb func,
208                                     void *data)
209 {
210    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
211    if (animator->on_animating) return;
212    animator->animator_op = func;
213    animator->animator_arg = data;
214 }
215
216 EAPI Elm_Animator *
217 elm_animator_add(Evas_Object *parent)
218 {
219    Elm_Animator *animator = ELM_NEW(Elm_Animator);
220    if (!animator) return NULL;
221    EINA_MAGIC_SET(animator, ELM_ANIMATOR_MAGIC);
222    animator->parent = parent;
223    elm_animator_auto_reverse_set(animator, EINA_FALSE);
224    elm_animator_curve_style_set(animator, ELM_ANIMATOR_CURVE_LINEAR);
225    if (parent)
226       evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
227                                      _animator_parent_del, animator);
228    return animator;
229 }
230
231 EAPI Eina_Bool
232 elm_animator_operating_get(const Elm_Animator *animator)
233 {
234    ELM_ANIMATOR_CHECK_OR_RETURN(animator, EINA_FALSE);
235    return animator->on_animating;
236 }
237
238 EAPI void
239 elm_animator_del(Elm_Animator *animator)
240 {
241    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
242    _delete_animator(animator);
243    if (animator->parent)
244       evas_object_event_callback_del(animator->parent, EVAS_CALLBACK_DEL,
245                                      _animator_parent_del);
246
247    EINA_MAGIC_SET(animator, EINA_MAGIC_NONE);
248    free(animator);
249 }
250
251 EAPI void
252 elm_animator_completion_callback_set(Elm_Animator *animator,
253                                      Elm_Animator_Completion_Cb func,
254                                      void *data)
255 {
256    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
257    if (animator->on_animating) return;
258    animator->completion_op = func;
259    animator->completion_arg = data;
260 }
261
262 EAPI void
263 elm_animator_pause(Elm_Animator *animator)
264 {
265    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
266    if (!animator->on_animating) return;
267    ecore_animator_freeze(animator->animator);
268 }
269
270 EAPI void
271 elm_animator_resume(Elm_Animator *animator)
272 {
273    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
274    if (!animator->on_animating) return;
275    ecore_animator_thaw(animator->animator);
276 }
277
278 EAPI void
279 elm_animator_stop(Elm_Animator *animator)
280 {
281    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
282    animator->on_animating = EINA_FALSE;
283    _delete_animator(animator);
284 }
285
286 EAPI void
287 elm_animator_repeat_set(Elm_Animator *animator, unsigned int repeat_cnt)
288 {
289    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
290    if (!animator->auto_reverse) animator->repeat_cnt = repeat_cnt;
291    else
292       animator->repeat_cnt = _animator_compute_reverse_repeat_count(repeat_cnt);
293 }
294
295 EAPI void
296 elm_animator_animate(Elm_Animator *animator)
297 {
298    ELM_ANIMATOR_CHECK_OR_RETURN(animator);
299    if (!animator->animator_op) return;
300    animator->begin_time = ecore_loop_time_get();
301    animator->cur_repeat_cnt = animator->repeat_cnt;
302    if (!animator->animator)
303       animator->animator = ecore_animator_add(_animator_animate_cb, animator);
304    if (animator->animator) animator->on_animating = EINA_TRUE;
305 }