Merge "[*][editfield] change the location of elm_entry_coursor_end set just after...
[framework/uifw/elementary.git] / src / lib / elm_transit.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define ELM_TRANSIT_CHECK_OR_RETURN(transit, ...) \
5    do { \
6       if (!transit) { \
7          CRITICAL("Elm_Transit " # transit " is NULL!"); \
8          return __VA_ARGS__; \
9       } \
10       if (!EINA_MAGIC_CHECK(transit, ELM_TRANSIT_MAGIC)) { \
11          EINA_MAGIC_FAIL(transit, ELM_TRANSIT_MAGIC); \
12          return __VA_ARGS__; \
13       } \
14       if (transit->deleted){ \
15          ERR("Elm_Transit " # transit " has already been deleted!"); \
16          return __VA_ARGS__; \
17       } \
18    } while (0)
19
20
21 #define _TRANSIT_FOCAL 2000
22
23 struct _Elm_Transit
24 {
25 #define ELM_TRANSIT_MAGIC 0xd27f190a
26    EINA_MAGIC;
27
28    Ecore_Animator *animator;
29    Eina_Inlist *effect_list;
30    Eina_List *objs;
31    Elm_Transit *prev_chain_transit;
32    Eina_List *next_chain_transits;
33    Elm_Transit_Tween_Mode tween_mode;
34    struct {
35       Elm_Transit_Del_Cb func;
36       void *arg;
37    } del_data;
38    struct {
39       double delayed;
40       double paused;
41       double duration;
42       double begin;
43       double current;
44    } time;
45    struct {
46       int count;
47       int current;
48       Eina_Bool reverse;
49    } repeat;
50    double progress;
51    unsigned int effects_pending_del;
52    int walking;
53    Eina_Bool auto_reverse : 1;
54    Eina_Bool event_enabled : 1;
55    Eina_Bool deleted : 1;
56    Eina_Bool state_keep : 1;
57    Eina_Bool finished : 1;
58 };
59
60 struct _Elm_Transit_Effect_Module
61 {
62    EINA_INLIST;
63    Elm_Transit_Effect_Transition_Cb transition_cb;
64    Elm_Transit_Effect_End_Cb end_cb;
65    Elm_Transit_Effect *effect;
66    Eina_Bool deleted : 1;
67 };
68
69 struct _Elm_Transit_Obj_State
70 {
71    Evas_Coord x, y, w, h;
72    int r,g,b,a;
73    Evas_Map *map;
74    Eina_Bool map_enabled : 1;
75    Eina_Bool visible : 1;
76 };
77
78 struct _Elm_Transit_Obj_Data
79 {
80    struct _Elm_Transit_Obj_State *state;
81    Eina_Bool pass_events : 1;
82 };
83
84 typedef struct _Elm_Transit_Effect_Module Elm_Transit_Effect_Module;
85 typedef struct _Elm_Transit_Obj_Data Elm_Transit_Obj_Data;
86 typedef struct _Elm_Transit_Obj_State Elm_Transit_Obj_State;
87
88 static void _transit_obj_data_update(Elm_Transit *transit, Evas_Object *obj);
89 static void _transit_obj_data_recover(Elm_Transit *transit, Evas_Object *obj);
90 static void _transit_obj_states_save(Evas_Object *obj, Elm_Transit_Obj_Data *obj_data);
91 static void _transit_obj_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
92 static void _transit_obj_remove(Elm_Transit *transit, Evas_Object *obj);
93 static void _transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Module *effect_module);
94 static void _transit_remove_dead_effects(Elm_Transit *transit);
95 static void _transit_del(Elm_Transit *transit);
96 static Eina_Bool _transit_animate_op(Elm_Transit *transit, double progress);
97 static Eina_Bool _transit_animate_cb(void *data);
98
99 static char *_transit_key= "_elm_transit_key";
100
101 static void
102 _transit_obj_data_update(Elm_Transit *transit, Evas_Object *obj)
103 {
104    Elm_Transit_Obj_Data *obj_data = evas_object_data_get(obj, _transit_key);
105
106    if (!obj_data)
107      obj_data = ELM_NEW(Elm_Transit_Obj_Data);
108
109    obj_data->pass_events = evas_object_pass_events_get(obj);
110
111    if ((!transit->state_keep) && (obj_data->state))
112      {
113         free(obj_data->state);
114         obj_data->state = NULL;
115      }
116    else
117      {
118        _transit_obj_states_save(obj, obj_data);
119      }
120
121    evas_object_data_set(obj, _transit_key, obj_data);
122 }
123
124 static void
125 _transit_obj_states_save(Evas_Object *obj, Elm_Transit_Obj_Data *obj_data)
126 {
127    Elm_Transit_Obj_State *state = obj_data->state;
128
129    if (!state)
130      state = calloc(1, sizeof(Elm_Transit_Obj_State));
131    if (!state) return;
132
133    evas_object_geometry_get(obj, &state->x, &state->y, &state->w, &state->h);
134    evas_object_color_get(obj, &state->r, &state->g, &state->b, &state->a);
135    state->visible = evas_object_visible_get(obj);
136    state->map_enabled = evas_object_map_enable_get(obj);
137    if (evas_object_map_get(obj))
138      state->map = evas_map_dup(evas_object_map_get(obj));
139    obj_data->state = state;
140 }
141
142 static void
143 _remove_obj_from_list(Elm_Transit *transit, Evas_Object *obj)
144 {
145    //Remove duplicated objects
146    //TODO: Need to consider about optimizing here
147    while(1)
148      {
149         if (!eina_list_data_find_list(transit->objs, obj))
150           break;
151         transit->objs = eina_list_remove(transit->objs, obj);
152         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
153                                        _transit_obj_remove_cb,
154                                        transit);
155      }
156 }
157
158 static void
159 _transit_obj_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
160 {
161    Elm_Transit *transit = data;
162    Elm_Transit_Obj_Data *obj_data = evas_object_data_get(obj, _transit_key);
163    if (obj_data)
164      {
165         if (obj_data->state)
166           free(obj_data->state);
167         free(obj_data);
168      }
169    _remove_obj_from_list(transit, obj);
170    if (!transit->objs) elm_transit_del(transit);
171 }
172
173 static void
174 _transit_obj_data_recover(Elm_Transit *transit, Evas_Object *obj)
175 {
176    Elm_Transit_Obj_Data *obj_data;
177    Elm_Transit_Obj_State *state;
178
179    obj_data = evas_object_data_get(obj, _transit_key);
180    if (!obj_data) return;
181    evas_object_data_del(obj, _transit_key);
182    evas_object_pass_events_set(obj, obj_data->pass_events);
183    state = obj_data->state;
184    if (state)
185      {
186         //recover the states of the object.
187         if (!transit->state_keep)
188           {
189              evas_object_move(obj, state->x, state->y);
190              evas_object_resize(obj, state->w, state->h);
191              evas_object_color_set(obj, state->r, state->g, state->b, state->a);
192              if (state->visible) evas_object_show(obj);
193              else evas_object_hide(obj);
194              if (state->map_enabled)
195                evas_object_map_enable_set(obj, EINA_TRUE);
196              else
197                evas_object_map_enable_set(obj, EINA_FALSE);
198              if (state->map)
199                evas_object_map_set(obj, state->map);
200           }
201         free(state);
202      }
203    free(obj_data);
204 }
205
206 static void
207 _transit_obj_remove(Elm_Transit *transit, Evas_Object *obj)
208 {
209    _remove_obj_from_list(transit, obj);
210    _transit_obj_data_recover(transit, obj);
211 }
212
213 static void
214 _transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Module *effect_module)
215 {
216    if (effect_module->end_cb)
217      effect_module->end_cb(effect_module->effect, transit);
218    free(effect_module);
219 }
220
221 static void
222 _transit_remove_dead_effects(Elm_Transit *transit)
223 {
224    Elm_Transit_Effect_Module *effect_module;
225
226    EINA_INLIST_FOREACH(transit->effect_list, effect_module)
227      {
228         if (effect_module->deleted)
229           {
230              _transit_effect_del(transit, effect_module);
231              transit->effects_pending_del--;
232              if (!transit->effects_pending_del) return;
233           }
234      }
235 }
236
237 static void
238 _transit_del(Elm_Transit *transit)
239 {
240    Elm_Transit_Effect_Module *effect_module;
241    Elm_Transit *chain_transit;
242    Eina_List *elist, *elist_next;
243
244    if (transit->animator)
245      ecore_animator_del(transit->animator);
246
247    //remove effects
248    while (transit->effect_list)
249      {
250         effect_module = EINA_INLIST_CONTAINER_GET(transit->effect_list, Elm_Transit_Effect_Module);
251         transit->effect_list = eina_inlist_remove(transit->effect_list, transit->effect_list);
252         _transit_effect_del(transit, effect_module);
253      }
254
255    //remove objects.
256    while (transit->objs)
257      _transit_obj_remove(transit, eina_list_data_get(transit->objs));
258
259    transit->deleted = EINA_TRUE;
260
261    if (transit->del_data.func)
262      transit->del_data.func(transit->del_data.arg, transit);
263
264    //cut off the chain transit relationship
265    EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
266      chain_transit->prev_chain_transit = NULL;
267
268    if (transit->prev_chain_transit)
269      transit->prev_chain_transit->next_chain_transits =
270         eina_list_remove(transit->prev_chain_transit->next_chain_transits, transit);
271
272    // run chain transits
273    if (transit->finished && transit->next_chain_transits)
274      {
275         EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
276           elm_transit_go(chain_transit);
277      }
278
279    eina_list_free(transit->next_chain_transits);
280
281    EINA_MAGIC_SET(transit, EINA_MAGIC_NONE);
282    free(transit);
283 }
284
285 //If the transit is deleted then EINA_FALSE is retruned.
286 static Eina_Bool
287 _transit_animate_op(Elm_Transit *transit, double progress)
288 {
289    Elm_Transit_Effect_Module *effect_module;
290
291    transit->walking++;
292    EINA_INLIST_FOREACH(transit->effect_list, effect_module)
293      {
294         if (transit->deleted) break;
295         if (!effect_module->deleted)
296           effect_module->transition_cb(effect_module->effect, transit, progress);
297      }
298    transit->walking--;
299
300    if (transit->walking) return EINA_TRUE;
301
302    if (transit->deleted)
303      {
304         _transit_del(transit);
305         return EINA_FALSE;
306      }
307
308    else if (transit->effects_pending_del) _transit_remove_dead_effects(transit);
309
310    return EINA_TRUE;
311 }
312
313 static Eina_Bool
314 _transit_animate_cb(void *data)
315 {
316    Elm_Transit *transit = data;
317    double elapsed_time, duration;
318
319    transit->time.current = ecore_loop_time_get();
320    elapsed_time = transit->time.current - transit->time.begin;
321    duration = transit->time.duration + transit->time.delayed;
322
323    if (elapsed_time > duration)
324      elapsed_time = duration;
325
326    transit->progress = elapsed_time / duration;
327    switch (transit->tween_mode)
328      {
329       case ELM_TRANSIT_TWEEN_MODE_ACCELERATE:
330         transit->progress = 1.0 - sin((ELM_PI / 2.0) + (transit->progress * ELM_PI / 2.0));
331         break;
332       case ELM_TRANSIT_TWEEN_MODE_DECELERATE:
333         transit->progress = sin(transit->progress * ELM_PI / 2.0);
334         break;
335       case ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL:
336         transit->progress = (1.0 - cos(transit->progress * ELM_PI)) / 2.0;
337         break;
338       default:
339         break;
340      }
341
342    /* Reverse? */
343    if (transit->repeat.reverse) transit->progress = 1 - transit->progress;
344
345    if (transit->time.duration > 0)
346      {
347         if (!_transit_animate_op(transit, transit->progress))
348           return ECORE_CALLBACK_CANCEL;
349      }
350
351    /* Not end. Keep going. */
352    if (elapsed_time < duration) return ECORE_CALLBACK_RENEW;
353
354    /* Repeat and reverse and time done! */
355    if ((transit->repeat.count >= 0) &&
356        (transit->repeat.current == transit->repeat.count) &&
357        ((!transit->auto_reverse) || transit->repeat.reverse))
358      {
359         transit->finished = EINA_TRUE;
360         elm_transit_del(transit);
361         return ECORE_CALLBACK_CANCEL;
362      }
363
364    /* Repeat Case */
365    if (!transit->auto_reverse || transit->repeat.reverse)
366      {
367         transit->repeat.current++;
368         transit->repeat.reverse = EINA_FALSE;
369      }
370    else transit->repeat.reverse = EINA_TRUE;
371
372    transit->time.begin = ecore_loop_time_get();
373
374    return ECORE_CALLBACK_RENEW;
375 }
376
377 EAPI Elm_Transit *
378 elm_transit_add(void)
379 {
380    Elm_Transit *transit = ELM_NEW(Elm_Transit);
381    if (!transit)
382      {
383         ERR("Failed to allocate a elm_transit object!");
384         return NULL;
385      }
386
387    EINA_MAGIC_SET(transit, ELM_TRANSIT_MAGIC);
388
389    elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
390
391    return transit;
392 }
393
394 EAPI void
395 elm_transit_del(Elm_Transit *transit)
396 {
397    ELM_TRANSIT_CHECK_OR_RETURN(transit);
398
399    if (transit->walking) transit->deleted = EINA_TRUE;
400    else _transit_del(transit);
401 }
402
403 EAPI void
404 elm_transit_effect_add(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect, Elm_Transit_Effect_End_Cb end_cb)
405 {
406    ELM_TRANSIT_CHECK_OR_RETURN(transit);
407    EINA_SAFETY_ON_NULL_RETURN(transition_cb);
408    Elm_Transit_Effect_Module *effect_module;
409
410    EINA_INLIST_FOREACH(transit->effect_list, effect_module)
411      if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect))
412        {
413           WRN("elm_transit does not allow to add the duplicated effect! : transit=%p", transit);
414           return;
415        }
416
417    effect_module = ELM_NEW(Elm_Transit_Effect_Module);
418    if (!effect_module)
419      {
420         ERR("Failed to allocate a new effect!: transit=%p", transit);
421         return;
422      }
423
424    effect_module->end_cb = end_cb;
425    effect_module->transition_cb = transition_cb;
426    effect_module->effect = effect;
427
428    transit->effect_list = eina_inlist_append(transit->effect_list, (Eina_Inlist*) effect_module);
429 }
430
431 EAPI void
432 elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect)
433 {
434    ELM_TRANSIT_CHECK_OR_RETURN(transit);
435    EINA_SAFETY_ON_NULL_RETURN(transition_cb);
436    Elm_Transit_Effect_Module *effect_module;
437
438    EINA_INLIST_FOREACH(transit->effect_list, effect_module)
439      {
440         if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect))
441           {
442              if (transit->walking)
443                {
444                   effect_module->deleted = EINA_TRUE;
445                   transit->effects_pending_del++;
446                }
447              else
448                {
449                   _transit_effect_del(transit, effect_module);
450                   if (!transit->effect_list) elm_transit_del(transit);
451                }
452              return;
453           }
454      }
455 }
456
457 EAPI void
458 elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj)
459 {
460    ELM_TRANSIT_CHECK_OR_RETURN(transit);
461    EINA_SAFETY_ON_NULL_RETURN(obj);
462
463    if (transit->animator)
464      {
465         if (!evas_object_data_get(obj, _transit_key))
466           {
467              _transit_obj_data_update(transit, obj);
468              evas_object_pass_events_set(obj, EINA_TRUE);
469           }
470      }
471
472    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
473                                   _transit_obj_remove_cb,
474                                   transit);
475
476    transit->objs = eina_list_append(transit->objs, obj);
477 }
478
479 EAPI void
480 elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
481 {
482    ELM_TRANSIT_CHECK_OR_RETURN(transit);
483    EINA_SAFETY_ON_NULL_RETURN(obj);
484
485    _transit_obj_remove(transit, obj);
486    if (!transit->objs) elm_transit_del(transit);
487 }
488
489 EAPI const Eina_List *
490 elm_transit_objects_get(const Elm_Transit *transit)
491 {
492    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
493    return transit->objs;
494 }
495
496 EAPI void
497 elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled)
498 {
499    ELM_TRANSIT_CHECK_OR_RETURN(transit);
500
501    Eina_List *list;
502    Evas_Object *obj;
503
504    if (transit->event_enabled == enabled) return;
505    transit->event_enabled = !!enabled;
506    if (!transit->animator) return;
507
508    EINA_LIST_FOREACH(transit->objs, list, obj)
509      evas_object_pass_events_set(obj, enabled);
510 }
511
512 EAPI Eina_Bool
513 elm_transit_event_enabled_get(const Elm_Transit *transit)
514 {
515    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
516    return transit->event_enabled;
517 }
518
519 EAPI void
520 elm_transit_del_cb_set(Elm_Transit *transit, void (*cb) (void *data, Elm_Transit *transit), void *data)
521 {
522    ELM_TRANSIT_CHECK_OR_RETURN(transit);
523    transit->del_data.func = cb;
524    transit->del_data.arg = data;
525 }
526
527 EAPI void
528 elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse)
529 {
530    ELM_TRANSIT_CHECK_OR_RETURN(transit);
531    transit->auto_reverse = reverse;
532 }
533
534 EAPI Eina_Bool
535 elm_transit_auto_reverse_get(const Elm_Transit *transit)
536 {
537    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
538    return transit->auto_reverse;
539 }
540
541 EAPI void
542 elm_transit_repeat_times_set(Elm_Transit *transit, int repeat)
543 {
544    ELM_TRANSIT_CHECK_OR_RETURN(transit);
545    transit->repeat.count = repeat;
546    transit->repeat.current = 0;
547 }
548
549 EAPI int
550 elm_transit_repeat_times_get(const Elm_Transit *transit)
551 {
552    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
553    return transit->repeat.count;
554 }
555
556 EAPI void
557 elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode)
558 {
559    ELM_TRANSIT_CHECK_OR_RETURN(transit);
560    transit->tween_mode = tween_mode;
561 }
562
563 EAPI Elm_Transit_Tween_Mode
564 elm_transit_tween_mode_get(const Elm_Transit *transit)
565 {
566    ELM_TRANSIT_CHECK_OR_RETURN(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
567    return transit->tween_mode;
568 }
569
570 EAPI void
571 elm_transit_duration_set(Elm_Transit *transit, double duration)
572 {
573    ELM_TRANSIT_CHECK_OR_RETURN(transit);
574    if (transit->animator)
575      {
576         WRN("elm_transit does not allow to set the duration time in operating! : transit=%p", transit);
577         return;
578      }
579    transit->time.duration = duration;
580 }
581
582 EAPI double
583 elm_transit_duration_get(const Elm_Transit *transit)
584 {
585    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0.0);
586    return transit->time.duration;
587 }
588
589 EAPI void
590 elm_transit_go(Elm_Transit *transit)
591 {
592    ELM_TRANSIT_CHECK_OR_RETURN(transit);
593
594    Eina_List *elist;
595    Evas_Object *obj;
596
597    if (transit->animator)
598      ecore_animator_del(transit->animator);
599
600    EINA_LIST_FOREACH(transit->objs, elist, obj)
601      _transit_obj_data_update(transit, obj);
602
603    if (!transit->event_enabled)
604      {
605         EINA_LIST_FOREACH(transit->objs, elist, obj)
606           evas_object_pass_events_set(obj, EINA_TRUE);
607      }
608
609    transit->time.paused = 0;
610    transit->time.delayed = 0;
611    transit->time.begin = ecore_loop_time_get();
612    transit->animator = ecore_animator_add(_transit_animate_cb, transit);
613 }
614
615 EAPI void
616 elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused)
617 {
618    ELM_TRANSIT_CHECK_OR_RETURN(transit);
619
620    if (!transit->animator) return;
621
622    if (paused)
623      {
624         if (transit->time.paused > 0)
625           return;
626         ecore_animator_freeze(transit->animator);
627         transit->time.paused = ecore_loop_time_get();
628      }
629    else
630      {
631         if (transit->time.paused == 0)
632           return;
633         ecore_animator_thaw(transit->animator);
634         transit->time.delayed += (ecore_loop_time_get() - transit->time.paused);
635         transit->time.paused = 0;
636      }
637 }
638
639 EAPI Eina_Bool
640 elm_transit_paused_get(const Elm_Transit *transit)
641 {
642    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
643
644    if (transit->time.paused == 0)
645      return EINA_FALSE;
646
647    return EINA_TRUE;
648 }
649
650 EAPI double
651 elm_transit_progress_value_get(const Elm_Transit *transit)
652 {
653    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
654
655    return transit->progress;
656 }
657
658 EAPI void
659 elm_transit_objects_final_state_keep_set(Elm_Transit *transit, Eina_Bool state_keep)
660 {
661    ELM_TRANSIT_CHECK_OR_RETURN(transit);
662
663    if (transit->state_keep == state_keep) return;
664    if (transit->animator)
665      {
666         WRN("elm_transit does not allow to change final state keep mode in operating! : transit=%p", transit);
667         return;
668      }
669    transit->state_keep = !!state_keep;
670 }
671
672 EAPI Eina_Bool
673 elm_transit_objects_final_state_keep_get(const Elm_Transit *transit)
674 {
675    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
676    return transit->state_keep;
677 }
678
679 EAPI void
680 elm_transit_chain_transit_add(Elm_Transit *transit, Elm_Transit *chain_transit)
681 {
682    ELM_TRANSIT_CHECK_OR_RETURN(transit);
683    ELM_TRANSIT_CHECK_OR_RETURN(chain_transit);
684
685    if (transit == chain_transit)
686      {
687         WRN("You add a same transit as a chain transit! : transit=%p, chain_transit=%p", transit, chain_transit);
688         return;
689      }
690    if (transit == chain_transit->prev_chain_transit)
691      return;
692
693    if (chain_transit->prev_chain_transit)
694      chain_transit->prev_chain_transit->next_chain_transits = eina_list_remove(chain_transit->prev_chain_transit->next_chain_transits, chain_transit);
695
696    chain_transit->prev_chain_transit = transit;
697    transit->next_chain_transits = eina_list_append(transit->next_chain_transits, chain_transit);
698 }
699
700 EAPI void
701 elm_transit_chain_transit_del(Elm_Transit *transit, Elm_Transit *chain_transit)
702 {
703    ELM_TRANSIT_CHECK_OR_RETURN(transit);
704    ELM_TRANSIT_CHECK_OR_RETURN(chain_transit);
705
706    if (chain_transit->prev_chain_transit != transit)
707      {
708         WRN("These two transit does not have the chain relationship! : transit=%p, chain_transit=%p", transit, chain_transit);
709         return;
710      }
711
712    chain_transit->prev_chain_transit = NULL;
713    transit->next_chain_transits = eina_list_remove(transit->next_chain_transits, chain_transit);
714 }
715
716 /**
717  * Get the current chain transit list.
718  *
719  * @note @p transit can not be NULL.
720  *
721  * @param transit The transit object.
722  * @return chain transit list.
723  *
724  * @ingroup Transit
725  */
726 EAPI Eina_List *
727 elm_transit_chain_transits_get(const Elm_Transit * transit)
728 {
729    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
730    return transit->next_chain_transits;
731 }
732
733 ///////////////////////////////////////////////////////////////////////////
734 //Resizing Effect
735 ///////////////////////////////////////////////////////////////////////////
736 typedef struct _Elm_Transit_Effect_Resizing Elm_Transit_Effect_Resizing;
737
738 struct _Elm_Transit_Effect_Resizing
739 {
740    struct _size {
741       Evas_Coord w, h;
742    } from, to;
743 };
744
745 static void
746 _transit_effect_resizing_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
747 {
748    Elm_Transit_Effect_Resizing *resizing = effect;
749    free(resizing);
750 }
751
752 static void
753 _transit_effect_resizing_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
754 {
755    EINA_SAFETY_ON_NULL_RETURN(effect);
756    EINA_SAFETY_ON_NULL_RETURN(transit);
757    Evas_Coord w, h;
758    Evas_Object *obj;
759    Eina_List *elist;
760    Elm_Transit_Effect_Resizing *resizing = effect;
761
762    w = resizing->from.w + (resizing->to.w * progress);
763    h = resizing->from.h + (resizing->to.h * progress);
764
765    EINA_LIST_FOREACH(transit->objs, elist, obj)
766      evas_object_resize(obj, w, h);
767 }
768
769 static Elm_Transit_Effect *
770 _transit_effect_resizing_context_new(Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
771 {
772    Elm_Transit_Effect_Resizing *resizing;
773
774    resizing = ELM_NEW(Elm_Transit_Effect_Resizing);
775    if (!resizing) return NULL;
776
777    resizing->from.w = from_w;
778    resizing->from.h = from_h;
779    resizing->to.w = to_w - from_w;
780    resizing->to.h = to_h - from_h;
781
782    return resizing;
783 }
784
785 EAPI Elm_Transit_Effect *
786 elm_transit_effect_resizing_add(Elm_Transit *transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
787 {
788    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
789    Elm_Transit_Effect *effect = _transit_effect_resizing_context_new(from_w, from_h, to_w, to_h);
790
791    if (!effect)
792      {
793         ERR("Failed to allocate resizing effect! : transit=%p", transit);
794         return NULL;
795      }
796    elm_transit_effect_add(transit,
797                           _transit_effect_resizing_op, effect,
798                           _transit_effect_resizing_context_free);
799    return effect;
800 }
801
802 ///////////////////////////////////////////////////////////////////////////
803 //Translation Effect
804 ///////////////////////////////////////////////////////////////////////////
805 typedef struct _Elm_Transit_Effect_Translation Elm_Transit_Effect_Translation;
806 typedef struct _Elm_Transit_Effect_Translation_Node Elm_Transit_Effect_Translation_Node;
807
808 struct _Elm_Transit_Effect_Translation_Node
809 {
810    Evas_Object *obj;
811    Evas_Coord x, y;
812 };
813
814 struct _Elm_Transit_Effect_Translation
815 {
816    struct _position_variation {
817       Evas_Coord dx, dy;
818    } from, to;
819    Eina_List *nodes;
820 };
821
822 static void
823 _translation_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
824 {
825    Elm_Transit_Effect_Translation *translation = data;
826    Eina_List *elist;
827    Elm_Transit_Effect_Translation_Node *translation_node;
828
829    EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
830      {
831         if (translation_node->obj != obj) continue;
832         translation->nodes = eina_list_remove_list(translation->nodes, elist);
833         free(translation_node);
834         break;
835      }
836 }
837
838 static Eina_List *
839 _translation_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Translation *translation)
840 {
841    Elm_Transit_Effect_Translation_Node *translation_node;
842    const Eina_List *elist;
843    Evas_Object *obj;
844    Eina_List *data_list = NULL;
845    const Eina_List *objs = elm_transit_objects_get(transit);
846
847    EINA_LIST_FOREACH(objs, elist, obj)
848      {
849         translation_node = ELM_NEW(Elm_Transit_Effect_Translation_Node);
850         if (!translation_node)
851           {
852              eina_list_free(data_list);
853              return NULL;
854           }
855         translation_node->obj = obj;
856         evas_object_geometry_get(obj, &(translation_node->x),
857                                  &(translation_node->y), NULL, NULL);
858         data_list = eina_list_append(data_list, translation_node);
859         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
860                                        _translation_object_del_cb, translation);
861      }
862    return data_list;
863 }
864
865 void
866 _transit_effect_translation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
867 {
868    EINA_SAFETY_ON_NULL_RETURN(effect);
869    Elm_Transit_Effect_Translation *translation = effect;
870    Eina_List *elist, *elist_next;
871    Elm_Transit_Effect_Translation_Node *translation_node;
872
873    EINA_LIST_FOREACH_SAFE(translation->nodes,
874                           elist, elist_next, translation_node)
875      {
876         evas_object_event_callback_del(translation_node->obj,
877                                        EVAS_CALLBACK_DEL, _translation_object_del_cb);
878         translation->nodes = eina_list_remove_list(translation->nodes, elist);
879         free(translation_node);
880      }
881    free(translation);
882 }
883
884 void
885 _transit_effect_translation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress __UNUSED__)
886 {
887    EINA_SAFETY_ON_NULL_RETURN(effect);
888    EINA_SAFETY_ON_NULL_RETURN(transit);
889    Evas_Coord x, y;
890    Elm_Transit_Effect_Translation *translation = effect;
891    Elm_Transit_Effect_Translation_Node *translation_node;
892    Eina_List *elist;
893
894    if (!translation->nodes)
895      translation->nodes = _translation_nodes_build(transit, translation);
896
897    EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
898      {
899         x = translation_node->x + translation->from.dx
900            + (translation->to.dx * progress);
901         y = translation_node->y + translation->from.dy
902            + (translation->to.dy * progress);
903         evas_object_move(translation_node->obj, x, y);
904      }
905 }
906
907 static Elm_Transit_Effect *
908 _transit_effect_translation_context_new(Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
909 {
910    Elm_Transit_Effect_Translation *translation;
911
912    translation = ELM_NEW(Elm_Transit_Effect_Translation);
913    if (!translation) return NULL;
914
915    translation->from.dx = from_dx;
916    translation->from.dy = from_dy;
917    translation->to.dx = to_dx - from_dx;
918    translation->to.dy = to_dy - from_dy;
919
920    return translation;
921 }
922
923 EAPI Elm_Transit_Effect *
924 elm_transit_effect_translation_add(Elm_Transit *transit, Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
925 {
926    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
927    Elm_Transit_Effect *effect = _transit_effect_translation_context_new(from_dx, from_dy, to_dx, to_dy);
928
929    if (!effect)
930      {
931         ERR("Failed to allocate translation effect! : transit=%p", transit);
932         return NULL;
933      }
934    elm_transit_effect_add(transit,
935                           _transit_effect_translation_op, effect,
936                           _transit_effect_translation_context_free);
937    return effect;
938 }
939
940 ///////////////////////////////////////////////////////////////////////////
941 //Zoom Effect
942 ///////////////////////////////////////////////////////////////////////////
943 typedef struct _Elm_Transit_Effect_Zoom Elm_Transit_Effect_Zoom;
944
945 struct _Elm_Transit_Effect_Zoom
946 {
947    float from, to;
948 };
949
950 void
951 _transit_effect_zoom_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
952 {
953    Elm_Transit_Effect_Zoom *zoom = effect;
954    free(zoom);
955 }
956
957 static void
958 _transit_effect_zoom_op(Elm_Transit_Effect *effect, Elm_Transit *transit , double progress)
959 {
960    EINA_SAFETY_ON_NULL_RETURN(effect);
961    EINA_SAFETY_ON_NULL_RETURN(transit);
962    Evas_Object *obj;
963    Eina_List *elist;
964    Elm_Transit_Effect_Zoom *zoom = effect;
965    Evas_Map *map;
966    Evas_Coord x, y, w, h;
967
968    map = evas_map_new(4);
969    if (!map) return;
970
971    EINA_LIST_FOREACH(transit->objs, elist, obj)
972      {
973         evas_object_geometry_get(obj, &x, &y, &w, &h);
974         evas_map_util_points_populate_from_object_full(map, obj, zoom->from +
975                                                        (progress * zoom->to));
976         evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
977         evas_object_map_set(obj, map);
978         evas_object_map_enable_set(obj, EINA_TRUE);
979      }
980    evas_map_free(map);
981 }
982
983 static Elm_Transit_Effect *
984 _transit_effect_zoom_context_new(float from_rate, float to_rate)
985 {
986    Elm_Transit_Effect_Zoom *zoom;
987
988    zoom = ELM_NEW(Elm_Transit_Effect_Zoom);
989    if (!zoom) return NULL;
990
991    zoom->from = (_TRANSIT_FOCAL - (from_rate * _TRANSIT_FOCAL)) * (1 / from_rate);
992    zoom->to = ((_TRANSIT_FOCAL - (to_rate * _TRANSIT_FOCAL)) * (1 / to_rate)) - zoom->from;
993
994    return zoom;
995 }
996
997 EAPI Elm_Transit_Effect *
998 elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate)
999 {
1000    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1001    Elm_Transit_Effect *effect = _transit_effect_zoom_context_new(from_rate, to_rate);
1002
1003    if (!effect)
1004      {
1005         ERR("Failed to allocate zoom effect! : transit=%p", transit);
1006         return NULL;
1007      }
1008    elm_transit_effect_add(transit,
1009                           _transit_effect_zoom_op, effect,
1010                           _transit_effect_zoom_context_free);
1011    return effect;
1012 }
1013
1014 ///////////////////////////////////////////////////////////////////////////
1015 //Flip Effect
1016 ///////////////////////////////////////////////////////////////////////////
1017 typedef struct _Elm_Transit_Effect_Flip Elm_Transit_Effect_Flip;
1018
1019 struct _Elm_Transit_Effect_Flip
1020 {
1021    Elm_Transit_Effect_Flip_Axis axis;
1022    Eina_Bool cw : 1;
1023 };
1024
1025 static void
1026 _transit_effect_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
1027 {
1028    EINA_SAFETY_ON_NULL_RETURN(effect);
1029    EINA_SAFETY_ON_NULL_RETURN(transit);
1030    Elm_Transit_Effect_Flip *flip = effect;
1031    Evas_Object *front, *back;
1032    int i;
1033    int count = eina_list_count(transit->objs);
1034
1035    for (i = 0; i < (count - 1); i += 2)
1036      {
1037         front = eina_list_nth(transit->objs, i);
1038         back = eina_list_nth(transit->objs, i+1);
1039         evas_object_map_enable_set(front, EINA_FALSE);
1040         evas_object_map_enable_set(back, EINA_FALSE);
1041      }
1042    free(flip);
1043 }
1044
1045 static void
1046 _transit_effect_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1047 {
1048    EINA_SAFETY_ON_NULL_RETURN(effect);
1049    EINA_SAFETY_ON_NULL_RETURN(transit);
1050    Evas_Object *obj, *front, *back;
1051    int count, i;
1052    Elm_Transit_Effect_Flip *flip = effect;
1053    Evas_Map *map;
1054    float degree;
1055    Evas_Coord x, y, w, h;
1056
1057    map = evas_map_new(4);
1058    if (!map) return;
1059
1060    if (flip->cw) degree = (float)(progress * 180);
1061    else degree = (float)(progress * -180);
1062
1063    count = eina_list_count(transit->objs);
1064
1065    for (i = 0; i < (count - 1); i += 2)
1066      {
1067         Evas_Coord half_w, half_h;
1068
1069         front = eina_list_nth(transit->objs, i);
1070         back = eina_list_nth(transit->objs, i+1);
1071
1072         if ((degree < 90) && (degree > -90))
1073           {
1074              obj = front;
1075              if (front != back)
1076                {
1077                   evas_object_hide(back);
1078                   evas_object_show(front);
1079                }
1080           }
1081         else
1082           {
1083              obj = back;
1084              if (front != back)
1085                {
1086                   evas_object_hide(front);
1087                   evas_object_show(back);
1088                }
1089           }
1090
1091         evas_map_util_points_populate_from_object_full(map, obj, 0);
1092         evas_object_geometry_get(obj, &x, &y, &w, &h);
1093         half_w = (w / 2);
1094         half_h = (h / 2);
1095
1096         if (flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1097           {
1098              if ((degree >= 90) || (degree <= -90))
1099                {
1100                   evas_map_point_image_uv_set(map, 0, w, 0);
1101                   evas_map_point_image_uv_set(map, 1, 0, 0);
1102                   evas_map_point_image_uv_set(map, 2, 0, h);
1103                   evas_map_point_image_uv_set(map, 3, w, h);
1104                }
1105              evas_map_util_3d_rotate(map, 0, degree,
1106                                      0, x + half_w, y + half_h, 0);
1107           }
1108         else
1109           {
1110              if ((degree >= 90) || (degree <= -90))
1111                {
1112                   evas_map_point_image_uv_set(map, 0, 0, h);
1113                   evas_map_point_image_uv_set(map, 1, w, h);
1114                   evas_map_point_image_uv_set(map, 2, w, 0);
1115                   evas_map_point_image_uv_set(map, 3, 0, 0);
1116                }
1117              evas_map_util_3d_rotate(map, degree,
1118                                      0, 0, x + half_w, y + half_h, 0);
1119           }
1120         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
1121         evas_object_map_enable_set(front, EINA_TRUE);
1122         evas_object_map_enable_set(back, EINA_TRUE);
1123         evas_object_map_set(obj, map);
1124      }
1125    evas_map_free(map);
1126 }
1127
1128 static Elm_Transit_Effect *
1129 _transit_effect_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1130 {
1131    Elm_Transit_Effect_Flip *flip;
1132
1133    flip = ELM_NEW(Elm_Transit_Effect_Flip);
1134    if (!flip) return NULL;
1135
1136    flip->cw = cw;
1137    flip->axis = axis;
1138
1139    return flip;
1140 }
1141
1142 EAPI Elm_Transit_Effect *
1143 elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1144 {
1145    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1146    Elm_Transit_Effect *effect = _transit_effect_flip_context_new(axis, cw);
1147
1148    if (!effect)
1149      {
1150         ERR("Failed to allocate flip effect! : transit=%p", transit);
1151         return NULL;
1152      }
1153    elm_transit_effect_add(transit,
1154                           _transit_effect_flip_op, effect,
1155                           _transit_effect_flip_context_free);
1156    return effect;
1157 }
1158
1159 ///////////////////////////////////////////////////////////////////////////
1160 //ResizableFlip Effect
1161 ///////////////////////////////////////////////////////////////////////////
1162 typedef struct _Elm_Transit_Effect_Resizable_Flip Elm_Transit_Effect_ResizableFlip;
1163 typedef struct _Elm_Transit_Effect_Resizable_Flip_Node Elm_Transit_Effect_ResizableFlip_Node;
1164
1165 struct _Elm_Transit_Effect_Resizable_Flip_Node
1166 {
1167    Evas_Object *front;
1168    Evas_Object *back;
1169    struct _vector2d {
1170       float x, y;
1171    } from_pos, from_size, to_pos, to_size;
1172 };
1173
1174 struct _Elm_Transit_Effect_Resizable_Flip
1175 {
1176    Eina_List *nodes;
1177    Eina_Bool cw : 1;
1178    Elm_Transit_Effect_Flip_Axis axis;
1179 };
1180
1181 static void
1182 _resizable_flip_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1183 {
1184    Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
1185    Eina_List *elist;
1186    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1187
1188    EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1189      {
1190         if (resizable_flip_node->front == obj)
1191           evas_object_event_callback_del(resizable_flip_node->back,
1192                                          EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1193         else if (resizable_flip_node->back == obj)
1194           evas_object_event_callback_del(resizable_flip_node->front,
1195                                          EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1196         else continue;
1197
1198         resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1199                                                       elist);
1200         free(resizable_flip_node);
1201         break;
1202      }
1203 }
1204
1205 static Eina_List *
1206 _resizable_flip_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_ResizableFlip *resizable_flip)
1207 {
1208    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1209    Eina_List *data_list = NULL;
1210    Evas_Coord front_x, front_y, front_w, front_h;
1211    Evas_Coord back_x, back_y, back_w, back_h;
1212    int i, count;
1213
1214    count = eina_list_count(transit->objs);
1215    for (i = 0; i < (count - 1); i += 2)
1216      {
1217         resizable_flip_node = ELM_NEW(Elm_Transit_Effect_ResizableFlip_Node);
1218         if (!resizable_flip_node)
1219           {
1220              eina_list_free(data_list);
1221              return NULL;
1222           }
1223
1224         resizable_flip_node->front = eina_list_nth(transit->objs, i);
1225         resizable_flip_node->back = eina_list_nth(transit->objs, i+1);
1226
1227         evas_object_geometry_get(resizable_flip_node->front,
1228                                  &front_x, &front_y, &front_w, &front_h);
1229         evas_object_geometry_get(resizable_flip_node->back,
1230                                  &back_x, &back_y, &back_w, &back_h);
1231
1232         resizable_flip_node->from_pos.x = front_x;
1233         resizable_flip_node->from_pos.y = front_y;
1234         resizable_flip_node->to_pos.x = back_x - front_x;
1235         resizable_flip_node->to_pos.y = back_y - front_y;
1236
1237         resizable_flip_node->from_size.x = front_w;
1238         resizable_flip_node->from_size.y = front_h;
1239         resizable_flip_node->to_size.x = back_w - front_w;
1240         resizable_flip_node->to_size.y = back_h - front_h;
1241
1242         data_list = eina_list_append(data_list, resizable_flip_node);
1243
1244         evas_object_event_callback_add(resizable_flip_node->back,
1245                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1246         evas_object_event_callback_add(resizable_flip_node->front,
1247                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1248      }
1249
1250    return data_list;
1251 }
1252
1253 static void
1254 _set_image_uv_by_axis_y(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
1255 {
1256    if ((degree >= 90) || (degree <= -90))
1257      {
1258         evas_map_point_image_uv_set(map, 0,
1259                                     (flip->from_size.x * 2) + flip->to_size.x,
1260                                     0);
1261         evas_map_point_image_uv_set(map, 1, 0, 0);
1262         evas_map_point_image_uv_set(map, 2, 0,
1263                                     (flip->from_size.y * 2) + flip->to_size.y);
1264         evas_map_point_image_uv_set(map, 3,
1265                                     (flip->from_size.x * 2) + flip->to_size.x,
1266                                     (flip->from_size.y * 2) + flip->to_size.y);
1267      }
1268    else
1269      {
1270         evas_map_point_image_uv_set(map, 0, 0, 0);
1271         evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1272         evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1273                                     flip->from_size.y);
1274         evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1275      }
1276 }
1277
1278 static void
1279 _set_image_uv_by_axis_x(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
1280 {
1281    if ((degree >= 90) || (degree <= -90))
1282      {
1283         evas_map_point_image_uv_set(map, 0, 0,
1284                                     (flip->from_size.y * 2) + flip->to_size.y);
1285         evas_map_point_image_uv_set(map, 1,
1286                                     (flip->from_size.x * 2) + flip->to_size.x,
1287                                     (flip->from_size.y * 2) + flip->to_size.y);
1288         evas_map_point_image_uv_set(map, 2,
1289                                     (flip->from_size.x * 2) + flip->to_size.x,
1290                                     0);
1291         evas_map_point_image_uv_set(map, 3, 0, 0);
1292      }
1293    else
1294      {
1295         evas_map_point_image_uv_set(map, 0, 0, 0);
1296         evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1297         evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1298                                     flip->from_size.y);
1299         evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1300      }
1301 }
1302
1303 void
1304 _transit_effect_resizable_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1305 {
1306    EINA_SAFETY_ON_NULL_RETURN(effect);
1307
1308    Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
1309    Eina_List *elist, *elist_next;
1310    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1311
1312    EINA_LIST_FOREACH_SAFE(resizable_flip->nodes,
1313                           elist, elist_next, resizable_flip_node)
1314      {
1315         evas_object_map_enable_set(resizable_flip_node->front, EINA_FALSE);
1316         evas_object_map_enable_set(resizable_flip_node->back, EINA_FALSE);
1317
1318         resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1319                                                       elist);
1320
1321         evas_object_event_callback_del(resizable_flip_node->back,
1322                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1323         evas_object_event_callback_del(resizable_flip_node->front,
1324                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1325         free(resizable_flip_node);
1326      }
1327    free(resizable_flip);
1328 }
1329
1330 void
1331 _transit_effect_resizable_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
1332 {
1333    EINA_SAFETY_ON_NULL_RETURN(effect);
1334    Evas_Map *map;
1335    Evas_Object *obj;
1336    float x, y, w, h;
1337    float degree;
1338    Evas_Coord half_w, half_h;
1339    Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
1340    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1341    Eina_List *elist;
1342
1343    map = evas_map_new(4);
1344    if (!map) return;
1345
1346    if (resizable_flip->cw) degree = (float)(progress * 180);
1347    else degree = (float)(progress * -180);
1348
1349    if (!resizable_flip->nodes)
1350      resizable_flip->nodes = _resizable_flip_nodes_build(transit,
1351                                                          resizable_flip);
1352
1353    EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1354      {
1355         if ((degree < 90) && (degree > -90))
1356           {
1357              obj = resizable_flip_node->front;
1358              if (resizable_flip_node->front != resizable_flip_node->back)
1359                {
1360                   evas_object_hide(resizable_flip_node->back);
1361                   evas_object_show(resizable_flip_node->front);
1362                }
1363           }
1364         else
1365           {
1366              obj = resizable_flip_node->back;
1367              if (resizable_flip_node->front != resizable_flip_node->back)
1368                {
1369                   evas_object_hide(resizable_flip_node->front);
1370                   evas_object_show(resizable_flip_node->back);
1371                }
1372           }
1373
1374         x = resizable_flip_node->from_pos.x +
1375            (resizable_flip_node->to_pos.x * progress);
1376         y = resizable_flip_node->from_pos.y +
1377            (resizable_flip_node->to_pos.y * progress);
1378         w = resizable_flip_node->from_size.x +
1379            (resizable_flip_node->to_size.x * progress);
1380         h = resizable_flip_node->from_size.y +
1381            (resizable_flip_node->to_size.y * progress);
1382         evas_map_point_coord_set(map, 0, x, y, 0);
1383         evas_map_point_coord_set(map, 1, x + w, y, 0);
1384         evas_map_point_coord_set(map, 2, x + w, y + h, 0);
1385         evas_map_point_coord_set(map, 3, x, y + h, 0);
1386
1387         half_w = (Evas_Coord)(w / 2);
1388         half_h = (Evas_Coord)(h / 2);
1389
1390         if (resizable_flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1391           {
1392              _set_image_uv_by_axis_y(map, resizable_flip_node, degree);
1393              evas_map_util_3d_rotate(map, 0, degree,
1394                                      0, x + half_w, y + half_h, 0);
1395           }
1396         else
1397           {
1398              _set_image_uv_by_axis_x(map, resizable_flip_node, degree);
1399              evas_map_util_3d_rotate(map, degree, 0,
1400                                      0, x + half_w, y + half_h, 0);
1401           }
1402
1403         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
1404         evas_object_map_enable_set(resizable_flip_node->front, EINA_TRUE);
1405         evas_object_map_enable_set(resizable_flip_node->back, EINA_TRUE);
1406         evas_object_map_set(obj, map);
1407      }
1408    evas_map_free(map);
1409 }
1410
1411 static Elm_Transit_Effect *
1412 _transit_effect_resizable_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1413 {
1414    Elm_Transit_Effect_ResizableFlip *resizable_flip;
1415
1416    resizable_flip = ELM_NEW(Elm_Transit_Effect_ResizableFlip);
1417    if (!resizable_flip) return NULL;
1418
1419    resizable_flip->cw = cw;
1420    resizable_flip->axis = axis;
1421
1422    return resizable_flip;
1423 }
1424
1425 EAPI Elm_Transit_Effect *
1426 elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1427 {
1428    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1429    Elm_Transit_Effect *effect = _transit_effect_resizable_flip_context_new(axis, cw);
1430
1431    if (!effect)
1432      {
1433         ERR("Failed to allocate resizable_flip effect! : transit=%p", transit);
1434         return NULL;
1435      }
1436    elm_transit_effect_add(transit,
1437                           _transit_effect_resizable_flip_op, effect,
1438                           _transit_effect_resizable_flip_context_free);
1439    return effect;
1440 }
1441
1442 ///////////////////////////////////////////////////////////////////////////
1443 //Wipe Effect
1444 ///////////////////////////////////////////////////////////////////////////
1445 typedef struct _Elm_Transit_Effect_Wipe Elm_Transit_Effect_Wipe;
1446
1447 struct _Elm_Transit_Effect_Wipe
1448 {
1449    Elm_Transit_Effect_Wipe_Type type;
1450    Elm_Transit_Effect_Wipe_Dir dir;
1451 };
1452
1453 static void
1454 _elm_fx_wipe_hide(Evas_Map * map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1455 {
1456    float w2, h2;
1457
1458    switch (dir)
1459      {
1460       case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1461          w2 = w - (w * progress);
1462          h2 = (y + h);
1463          evas_map_point_image_uv_set(map, 0, 0, 0);
1464          evas_map_point_image_uv_set(map, 1, w2, 0);
1465          evas_map_point_image_uv_set(map, 2, w2, h);
1466          evas_map_point_image_uv_set(map, 3, 0, h);
1467          evas_map_point_coord_set(map, 0, x, y, 0);
1468          evas_map_point_coord_set(map, 1, x + w2, y, 0);
1469          evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1470          evas_map_point_coord_set(map, 3, x, h2, 0);
1471          break;
1472       case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1473          w2 = (w * progress);
1474          h2 = (y + h);
1475          evas_map_point_image_uv_set(map, 0, w2, 0);
1476          evas_map_point_image_uv_set(map, 1, w, 0);
1477          evas_map_point_image_uv_set(map, 2, w, h);
1478          evas_map_point_image_uv_set(map, 3, w2, h);
1479          evas_map_point_coord_set(map, 0, x + w2, y, 0);
1480          evas_map_point_coord_set(map, 1, x + w, y, 0);
1481          evas_map_point_coord_set(map, 2, x + w, h2, 0);
1482          evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1483          break;
1484       case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1485          w2 = (x + w);
1486          h2 = h - (h * progress);
1487          evas_map_point_image_uv_set(map, 0, 0, 0);
1488          evas_map_point_image_uv_set(map, 1, w, 0);
1489          evas_map_point_image_uv_set(map, 2, w, h2);
1490          evas_map_point_image_uv_set(map, 3, 0, h2);
1491          evas_map_point_coord_set(map, 0, x, y, 0);
1492          evas_map_point_coord_set(map, 1, w2, y, 0);
1493          evas_map_point_coord_set(map, 2, w2, y+h2, 0);
1494          evas_map_point_coord_set(map, 3, x, y+h2, 0);
1495          break;
1496       case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1497          w2 = (x + w);
1498          h2 = (h * progress);
1499          evas_map_point_image_uv_set(map, 0, 0, h2);
1500          evas_map_point_image_uv_set(map, 1, w, h2);
1501          evas_map_point_image_uv_set(map, 2, w, h);
1502          evas_map_point_image_uv_set(map, 3, 0, h);
1503          evas_map_point_coord_set(map, 0, x, y + h2, 0);
1504          evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1505          evas_map_point_coord_set(map, 2, w2, y + h, 0);
1506          evas_map_point_coord_set(map, 3, x, y + h, 0);
1507          break;
1508       default:
1509          break;
1510      }
1511    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
1512 }
1513
1514 static void
1515 _elm_fx_wipe_show(Evas_Map *map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1516 {
1517    float w2, h2;
1518
1519    switch (dir)
1520      {
1521       case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1522          w2 = (w - (w * progress));
1523          h2 = (y + h);
1524          evas_map_point_image_uv_set(map, 0, w2, 0);
1525          evas_map_point_image_uv_set(map, 1, w, 0);
1526          evas_map_point_image_uv_set(map, 2, w, h);
1527          evas_map_point_image_uv_set(map, 3, w2, h);
1528          evas_map_point_coord_set(map, 0, x + w2, y, 0);
1529          evas_map_point_coord_set(map, 1, w, y, 0);
1530          evas_map_point_coord_set(map, 2, w, h2, 0);
1531          evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1532          break;
1533       case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1534          w2 = (w * progress);
1535          h2 = (y + h);
1536          evas_map_point_image_uv_set(map, 0, 0, 0);
1537          evas_map_point_image_uv_set(map, 1, w2, 0);
1538          evas_map_point_image_uv_set(map, 2, w2, h);
1539          evas_map_point_image_uv_set(map, 3, 0, h);
1540          evas_map_point_coord_set(map, 0, x, y, 0);
1541          evas_map_point_coord_set(map, 1, x + w2, y, 0);
1542          evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1543          evas_map_point_coord_set(map, 3, x, h2, 0);
1544          break;
1545       case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1546          w2 = (x + w);
1547          h2 = (h - (h * progress));
1548          evas_map_point_image_uv_set(map, 0, 0, h2);
1549          evas_map_point_image_uv_set(map, 1, w, h2);
1550          evas_map_point_image_uv_set(map, 2, w, h);
1551          evas_map_point_image_uv_set(map, 3, 0, h);
1552          evas_map_point_coord_set(map, 0, x, y + h2, 0);
1553          evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1554          evas_map_point_coord_set(map, 2, w2, y + h, 0);
1555          evas_map_point_coord_set(map, 3, x, y + h, 0);
1556          break;
1557       case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1558          w2 = (x + w);
1559          h2 = (h * progress);
1560          evas_map_point_image_uv_set(map, 0, 0, 0);
1561          evas_map_point_image_uv_set(map, 1, w, 0);
1562          evas_map_point_image_uv_set(map, 2, w, h2);
1563          evas_map_point_image_uv_set(map, 3, 0, h2);
1564          evas_map_point_coord_set(map, 0, x, y, 0);
1565          evas_map_point_coord_set(map, 1, w2, y, 0);
1566          evas_map_point_coord_set(map, 2, w2, y + h2, 0);
1567          evas_map_point_coord_set(map, 3, x, y + h2, 0);
1568          break;
1569       default:
1570          break;
1571      }
1572    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
1573 }
1574
1575 static void
1576 _transit_effect_wipe_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
1577 {
1578    EINA_SAFETY_ON_NULL_RETURN(effect);
1579    EINA_SAFETY_ON_NULL_RETURN(transit);
1580    Eina_List *elist;
1581    Evas_Object *obj;
1582    Elm_Transit_Effect_Wipe *wipe = effect;
1583    Eina_Bool reverse = elm_transit_auto_reverse_get(transit);
1584
1585    EINA_LIST_FOREACH(transit->objs, elist, obj)
1586      {
1587         if ((wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW && !reverse)
1588             || (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE && reverse))
1589           evas_object_show(obj);
1590         else evas_object_hide(obj);
1591         evas_object_map_enable_set(obj, EINA_FALSE);
1592      }
1593
1594    free(wipe);
1595 }
1596
1597 static void
1598 _transit_effect_wipe_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1599 {
1600    EINA_SAFETY_ON_NULL_RETURN(effect);
1601    EINA_SAFETY_ON_NULL_RETURN(transit);
1602    Elm_Transit_Effect_Wipe *wipe = effect;
1603    Evas_Map *map;
1604    Evas_Coord _x, _y, _w, _h;
1605    Eina_List *elist;
1606    Evas_Object *obj;
1607
1608    map = evas_map_new(4);
1609    if (!map) return;
1610
1611    EINA_LIST_FOREACH(transit->objs, elist, obj)
1612      {
1613         evas_object_geometry_get(obj, &_x, &_y, &_w, &_h);
1614
1615         if (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW)
1616           _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)progress);
1617         else
1618           _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)progress);
1619
1620         evas_object_map_enable_set(obj, EINA_TRUE);
1621         evas_object_map_set(obj, map);
1622      }
1623    evas_map_free(map);
1624 }
1625
1626 static Elm_Transit_Effect *
1627 _transit_effect_wipe_context_new(Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
1628 {
1629    Elm_Transit_Effect_Wipe *wipe;
1630
1631    wipe = ELM_NEW(Elm_Transit_Effect_Wipe);
1632    if (!wipe) return NULL;
1633
1634    wipe->type = type;
1635    wipe->dir = dir;
1636
1637    return wipe;
1638 }
1639
1640 EAPI void *
1641 elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
1642 {
1643    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1644    void *effect = _transit_effect_wipe_context_new(type, dir);
1645
1646    if (!effect)
1647      {
1648         ERR("Failed to allocate wipe effect! : transit=%p", transit);
1649         return NULL;
1650      }
1651    elm_transit_effect_add(transit,
1652                           _transit_effect_wipe_op, effect,
1653                           _transit_effect_wipe_context_free);
1654    return effect;
1655 }
1656
1657 ///////////////////////////////////////////////////////////////////////////
1658 //Color Effect
1659 ///////////////////////////////////////////////////////////////////////////
1660 typedef struct _Elm_Transit_Effect_Color Elm_Transit_Effect_Color;
1661
1662 struct _Elm_Transit_Effect_Color
1663 {
1664    struct _unsigned_color {
1665       unsigned int r, g, b, a;
1666    } from;
1667    struct _signed_color {
1668       int r, g, b, a;
1669    } to;
1670 };
1671
1672 static void
1673 _transit_effect_color_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1674 {
1675    Elm_Transit_Effect_Color *color = effect;
1676    free(color);
1677 }
1678
1679 static void
1680 _transit_effect_color_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1681 {
1682    EINA_SAFETY_ON_NULL_RETURN(effect);
1683    EINA_SAFETY_ON_NULL_RETURN(transit);
1684    Elm_Transit_Effect_Color *color = effect;
1685    Evas_Object *obj;
1686    Eina_List *elist;
1687    unsigned int r, g, b, a;
1688
1689    r = (color->from.r + (int)((float)color->to.r * progress));
1690    g = (color->from.g + (int)((float)color->to.g * progress));
1691    b = (color->from.b + (int)((float)color->to.b * progress));
1692    a = (color->from.a + (int)((float)color->to.a * progress));
1693
1694    EINA_LIST_FOREACH(transit->objs, elist, obj)
1695      evas_object_color_set(obj, r, g, b, a);
1696 }
1697
1698 static Elm_Transit_Effect *
1699 _transit_effect_color_context_new(unsigned int from_r, unsigned int from_g, unsigned int from_b, unsigned int from_a, unsigned int to_r, unsigned int to_g, unsigned int to_b, unsigned int to_a)
1700 {
1701    Elm_Transit_Effect_Color *color;
1702
1703    color = ELM_NEW(Elm_Transit_Effect_Color);
1704    if (!color) return NULL;
1705
1706    color->from.r = from_r;
1707    color->from.g = from_g;
1708    color->from.b = from_b;
1709    color->from.a = from_a;
1710    color->to.r = to_r - from_r;
1711    color->to.g = to_g - from_g;
1712    color->to.b = to_b - from_b;
1713    color->to.a = to_a - from_a;
1714
1715    return color;
1716 }
1717
1718 EAPI Elm_Transit_Effect *
1719 elm_transit_effect_color_add(Elm_Transit *transit, unsigned int from_r, unsigned int from_g, unsigned int from_b, unsigned int from_a, unsigned int to_r, unsigned int to_g, unsigned int to_b, unsigned int to_a)
1720 {
1721    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1722    Elm_Transit_Effect *effect = _transit_effect_color_context_new(from_r, from_g, from_b, from_a, to_r, to_g, to_b, to_a);
1723
1724    if (!effect)
1725      {
1726         ERR("Failed to allocate color effect! : transit=%p", transit);
1727         return NULL;
1728      }
1729    elm_transit_effect_add(transit,
1730                           _transit_effect_color_op, effect,
1731                           _transit_effect_color_context_free);
1732    return effect;
1733 }
1734
1735 ///////////////////////////////////////////////////////////////////////////
1736 //Fade Effect
1737 ///////////////////////////////////////////////////////////////////////////
1738 typedef struct _Elm_Transit_Effect_Fade Elm_Transit_Effect_Fade;
1739 typedef struct _Elm_Transit_Effect_Fade_Node Elm_Transit_Effect_Fade_Node;
1740
1741 struct _Elm_Transit_Effect_Fade_Node
1742 {
1743    Evas_Object *before;
1744    Evas_Object *after;
1745    struct _signed_color before_color, after_color;
1746    int before_alpha;
1747    int after_alpha;
1748    Eina_Bool inversed : 1;
1749 };
1750
1751 struct _Elm_Transit_Effect_Fade
1752 {
1753    Eina_List *nodes;
1754 };
1755
1756 static void
1757 _fade_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1758 {
1759    Elm_Transit_Effect_Fade *fade = data;
1760    Eina_List *elist;
1761    Elm_Transit_Effect_Fade_Node *fade_node;
1762
1763    EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
1764      {
1765         if (fade_node->before == obj)
1766           evas_object_event_callback_del(fade_node->after,
1767                                          EVAS_CALLBACK_DEL, _fade_object_del_cb);
1768         else if (fade_node->after == obj)
1769           evas_object_event_callback_del(fade_node->before,
1770                                          EVAS_CALLBACK_DEL, _fade_object_del_cb);
1771         else continue;
1772
1773         fade->nodes = eina_list_remove_list(fade->nodes, elist);
1774         free(fade_node);
1775         break;
1776      }
1777 }
1778
1779 static Eina_List *
1780 _fade_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Fade *fade_data)
1781 {
1782    Elm_Transit_Effect_Fade_Node *fade;
1783    Eina_List *data_list = NULL;
1784    int i, count;
1785
1786    count = eina_list_count(transit->objs);
1787    for (i = 0; i < count; i += 2)
1788      {
1789         fade = ELM_NEW(Elm_Transit_Effect_Fade_Node);
1790         if (!fade)
1791           {
1792              eina_list_free(data_list);
1793              return NULL;
1794           }
1795
1796         fade->before = eina_list_nth(transit->objs, i);
1797         fade->after = eina_list_nth(transit->objs, i+1);
1798
1799         evas_object_color_get(fade->before,
1800                               &fade->before_color.r, &fade->before_color.g,
1801                               &fade->before_color.b, &fade->before_color.a);
1802         evas_object_color_get(fade->after,
1803                               &fade->after_color.r, &fade->after_color.g,
1804                               &fade->after_color.b, &fade->after_color.a);
1805
1806         fade->before_alpha = (255 - fade->before_color.a);
1807         fade->after_alpha = (255 - fade->after_color.a);
1808
1809         data_list = eina_list_append(data_list, fade);
1810
1811         evas_object_event_callback_add(fade->before,
1812                                        EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
1813         evas_object_event_callback_add(fade->after,
1814                                        EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
1815      }
1816    return data_list;
1817 }
1818
1819 static void
1820 _transit_effect_fade_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1821 {
1822    EINA_SAFETY_ON_NULL_RETURN(effect);
1823    Elm_Transit_Effect_Fade *fade = effect;
1824    Elm_Transit_Effect_Fade_Node *fade_node;
1825    Eina_List *elist, *elist_next;
1826
1827    EINA_LIST_FOREACH_SAFE(fade->nodes, elist, elist_next, fade_node)
1828      {
1829         evas_object_color_set(fade_node->before, fade_node->before_color.r,
1830                               fade_node->before_color.g,
1831                               fade_node->before_color.b,
1832                               fade_node->before_color.a);
1833         evas_object_color_set(fade_node->after, fade_node->after_color.r,
1834                               fade_node->after_color.g,
1835                               fade_node->after_color.b,
1836                               fade_node->after_color.a);
1837
1838         fade->nodes = eina_list_remove_list(fade->nodes, elist);
1839         evas_object_event_callback_del(fade_node->before,
1840                                        EVAS_CALLBACK_DEL, _fade_object_del_cb);
1841         evas_object_event_callback_del(fade_node->after,
1842                                        EVAS_CALLBACK_DEL, _fade_object_del_cb);
1843         free(fade_node);
1844      }
1845
1846    free(fade);
1847 }
1848
1849 static void
1850 _transit_effect_fade_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
1851 {
1852    EINA_SAFETY_ON_NULL_RETURN(effect);
1853    Elm_Transit_Effect_Fade *fade = effect;
1854    Eina_List *elist;
1855    Elm_Transit_Effect_Fade_Node *fade_node;
1856    float _progress;
1857
1858    if (!fade->nodes)
1859      fade->nodes = _fade_nodes_build(transit, fade);
1860
1861    EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
1862      {
1863         if (progress < 0.5)
1864           {
1865              if (!fade_node->inversed)
1866                {
1867                   evas_object_hide(fade_node->after);
1868                   evas_object_show(fade_node->before);
1869                   fade_node->inversed = EINA_TRUE;
1870                }
1871
1872              _progress = (1 - (progress * 2));
1873
1874              evas_object_color_set(fade_node->before,
1875                                    fade_node->before_color.r * _progress,
1876                                    fade_node->before_color.g * _progress,
1877                                    fade_node->before_color.b * _progress,
1878                                    fade_node->before_color.a +
1879                                    fade_node->before_alpha * (1 - _progress));
1880           }
1881         else
1882           {
1883              if (fade_node->inversed)
1884                {
1885                   evas_object_hide(fade_node->before);
1886                   evas_object_show(fade_node->after);
1887                   fade_node->inversed = EINA_FALSE;
1888                }
1889
1890              _progress = ((progress - 0.5) * 2);
1891
1892              evas_object_color_set(fade_node->after,
1893                                    fade_node->after_color.r * _progress,
1894                                    fade_node->after_color.g * _progress,
1895                                    fade_node->after_color.b * _progress,
1896                                    fade_node->after_color.a +
1897                                    fade_node->after_alpha * (1 - _progress));
1898           }
1899      }
1900 }
1901
1902 static Elm_Transit_Effect *
1903 _transit_effect_fade_context_new(void)
1904 {
1905    Elm_Transit_Effect_Fade *fade;
1906    fade = ELM_NEW(Elm_Transit_Effect_Fade);
1907    if (!fade) return NULL;
1908    return fade;
1909 }
1910
1911 EAPI Elm_Transit_Effect *
1912 elm_transit_effect_fade_add(Elm_Transit *transit)
1913 {
1914    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1915
1916    Elm_Transit_Effect *effect = _transit_effect_fade_context_new();
1917
1918    if (!effect)
1919      {
1920         ERR("Failed to allocate fade effect! : transit=%p", transit);
1921         return NULL;
1922      }
1923    elm_transit_effect_add(transit,
1924                           _transit_effect_fade_op, effect,
1925                           _transit_effect_fade_context_free);
1926    return effect;
1927 }
1928
1929 ///////////////////////////////////////////////////////////////////////////
1930 //Blend Effect
1931 ///////////////////////////////////////////////////////////////////////////
1932 typedef struct _Elm_Transit_Effect_Blend Elm_Transit_Effect_Blend;
1933 typedef struct _Elm_Transit_Effect_Blend_Node Elm_Transit_Effect_Blend_Node;
1934
1935 struct _Elm_Transit_Effect_Blend_Node
1936 {
1937    Evas_Object *before;
1938    Evas_Object *after;
1939    struct _signed_color from, to;
1940 };
1941
1942 struct _Elm_Transit_Effect_Blend
1943 {
1944    Eina_List *nodes;
1945 };
1946
1947 static void
1948 _blend_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1949 {
1950    Elm_Transit_Effect_Blend *blend = data;
1951    Eina_List *elist;
1952    Elm_Transit_Effect_Blend_Node *blend_node;
1953
1954    EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
1955      {
1956         if (blend_node->after == obj)
1957           evas_object_event_callback_del(blend_node->before,
1958                                          EVAS_CALLBACK_DEL, _blend_object_del_cb);
1959         else if (blend_node->before == obj)
1960           evas_object_event_callback_del(blend_node->after,
1961                                          EVAS_CALLBACK_DEL, _blend_object_del_cb);
1962         else continue;
1963
1964         blend->nodes = eina_list_remove_list(blend->nodes, elist);
1965         free(blend_node);
1966         break;
1967      }
1968 }
1969
1970 static Eina_List *
1971 _blend_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Blend *blend)
1972 {
1973    Elm_Transit_Effect_Blend_Node *blend_node;
1974    Eina_List *data_list = NULL;
1975    int i, count;
1976
1977    count = eina_list_count(transit->objs);
1978    for (i = 0; i < (count - 1); i += 2)
1979      {
1980         blend_node = ELM_NEW(Elm_Transit_Effect_Blend_Node);
1981         if (!blend_node)
1982           {
1983              eina_list_free(data_list);
1984              return NULL;
1985           }
1986
1987         blend_node->before = eina_list_nth(transit->objs, i);
1988         blend_node->after = eina_list_nth(transit->objs, i + 1);
1989         evas_object_show(blend_node->before);
1990         evas_object_show(blend_node->after);
1991
1992         evas_object_color_get(blend_node->before, &blend_node->from.r,
1993                               &blend_node->from.g, &blend_node->from.b,
1994                               &blend_node->from.a);
1995         evas_object_color_get(blend_node->after, &blend_node->to.r,
1996                               &blend_node->to.g, &blend_node->to.b,
1997                               &blend_node->to.a);
1998
1999         data_list = eina_list_append(data_list, blend_node);
2000
2001         evas_object_event_callback_add(blend_node->before,
2002                                        EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
2003         evas_object_event_callback_add(blend_node->after,
2004                                        EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
2005      }
2006    return data_list;
2007 }
2008
2009 void
2010 _transit_effect_blend_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2011 {
2012    EINA_SAFETY_ON_NULL_RETURN(effect);
2013    Elm_Transit_Effect_Blend *blend = effect;
2014    Elm_Transit_Effect_Blend_Node *blend_node;
2015    Eina_List *elist, *elist_next;
2016
2017    EINA_LIST_FOREACH_SAFE(blend->nodes, elist, elist_next, blend_node)
2018      {
2019         evas_object_color_set(blend_node->before,
2020                               blend_node->from.r, blend_node->from.g,
2021                               blend_node->from.b, blend_node->from.a);
2022         evas_object_color_set(blend_node->after, blend_node->to.r,
2023                               blend_node->to.g, blend_node->to.b,
2024                               blend_node->to.a);
2025
2026         if (elm_transit_auto_reverse_get(transit))
2027           evas_object_hide(blend_node->after);
2028         else
2029           evas_object_hide(blend_node->before);
2030
2031         blend->nodes = eina_list_remove_list(blend->nodes, elist);
2032
2033         evas_object_event_callback_del(blend_node->before,
2034                                        EVAS_CALLBACK_DEL, _blend_object_del_cb);
2035         evas_object_event_callback_del(blend_node->after,
2036                                        EVAS_CALLBACK_DEL, _blend_object_del_cb);
2037         free(blend_node);
2038      }
2039    free(blend);
2040 }
2041
2042 void
2043 _transit_effect_blend_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2044 {
2045    EINA_SAFETY_ON_NULL_RETURN(effect);
2046    EINA_SAFETY_ON_NULL_RETURN(transit);
2047    Elm_Transit_Effect_Blend *blend = effect;
2048    Elm_Transit_Effect_Blend_Node *blend_node;
2049    Eina_List *elist;
2050
2051    if (!blend->nodes) blend->nodes = _blend_nodes_build(transit, blend);
2052
2053    EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
2054      {
2055         evas_object_color_set(blend_node->before,
2056                               (int)(blend_node->from.r * (1 - progress)),
2057                               (int)(blend_node->from.g * (1 - progress)),
2058                               (int)(blend_node->from.b * (1 - progress)),
2059                               (int)(blend_node->from.a * (1 - progress)));
2060         evas_object_color_set(blend_node->after,
2061                               (int)(blend_node->to.r * progress),
2062                               (int)(blend_node->to.g * progress),
2063                               (int)(blend_node->to.b * progress),
2064                               (int)(blend_node->to.a * progress));
2065      }
2066 }
2067
2068 static Elm_Transit_Effect *
2069 _transit_effect_blend_context_new(void)
2070 {
2071    Elm_Transit_Effect_Blend *blend;
2072
2073    blend = ELM_NEW(Elm_Transit_Effect_Blend);
2074    if (!blend) return NULL;
2075    return blend;
2076 }
2077
2078 EAPI Elm_Transit_Effect *
2079 elm_transit_effect_blend_add(Elm_Transit *transit)
2080 {
2081    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2082    Elm_Transit_Effect *effect = _transit_effect_blend_context_new();
2083
2084    if (!effect)
2085      {
2086         ERR("Failed to allocate blend effect! : transit=%p", transit);
2087         return NULL;
2088      }
2089    elm_transit_effect_add(transit,
2090                           _transit_effect_blend_op, effect,
2091                           _transit_effect_blend_context_free);
2092    return effect;
2093 }
2094
2095 ///////////////////////////////////////////////////////////////////////////
2096 //Rotation Effect
2097 ///////////////////////////////////////////////////////////////////////////
2098 typedef struct _Elm_Transit_Effect_Rotation Elm_Transit_Effect_Rotation;
2099
2100 struct _Elm_Transit_Effect_Rotation
2101 {
2102    float from, to;
2103 };
2104
2105 static void
2106 _transit_effect_rotation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2107 {
2108    Elm_Transit_Effect_Rotation *rotation = effect;
2109    free(rotation);
2110 }
2111
2112 static void
2113 _transit_effect_rotation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2114 {
2115    EINA_SAFETY_ON_NULL_RETURN(effect);
2116    EINA_SAFETY_ON_NULL_RETURN(transit);
2117    Elm_Transit_Effect_Rotation *rotation = effect;
2118    Evas_Map *map;
2119    Evas_Coord x, y, w, h;
2120    float degree;
2121    float half_w, half_h;
2122    Eina_List *elist;
2123    Evas_Object *obj;
2124
2125    map = evas_map_new(4);
2126    if (!map) return;
2127
2128    EINA_LIST_FOREACH(transit->objs, elist, obj)
2129      {
2130         evas_map_util_points_populate_from_object_full(map, obj, 0);
2131         degree = rotation->from + (float)(progress * rotation->to);
2132
2133         evas_object_geometry_get(obj, &x, &y, &w, &h);
2134
2135         half_w = (float)w * 0.5;
2136         half_h = (float)h * 0.5;
2137
2138         evas_map_util_rotate(map, degree, x + half_w, y + half_h);
2139         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
2140         evas_object_map_enable_set(obj, EINA_TRUE);
2141         evas_object_map_set(obj, map);
2142      }
2143    evas_map_free(map);
2144 }
2145
2146 static Elm_Transit_Effect *
2147 _transit_effect_rotation_context_new(float from_degree, float to_degree)
2148 {
2149    Elm_Transit_Effect_Rotation *rotation;
2150
2151    rotation = ELM_NEW(Elm_Transit_Effect_Rotation);
2152    if (!rotation) return NULL;
2153
2154    rotation->from = from_degree;
2155    rotation->to = to_degree - from_degree;
2156
2157    return rotation;
2158 }
2159
2160 EAPI Elm_Transit_Effect *
2161 elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree)
2162 {
2163    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2164    Elm_Transit_Effect *effect = _transit_effect_rotation_context_new(from_degree, to_degree);
2165
2166    if (!effect)
2167      {
2168         ERR("Failed to allocate rotation effect! : transit=%p", transit);
2169         return NULL;
2170      }
2171    elm_transit_effect_add(transit,
2172                           _transit_effect_rotation_op, effect,
2173                           _transit_effect_rotation_context_free);
2174    return effect;
2175 }
2176
2177 ///////////////////////////////////////////////////////////////////////////
2178 //ImageAnimation Effect
2179 ///////////////////////////////////////////////////////////////////////////
2180 typedef struct _Elm_Transit_Effect_Image_Animation Elm_Transit_Effect_Image_Animation;
2181
2182 struct _Elm_Transit_Effect_Image_Animation
2183 {
2184    Eina_List *images;
2185 };
2186
2187 static void
2188 _transit_effect_image_animation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2189 {
2190    EINA_SAFETY_ON_NULL_RETURN(effect);
2191    Elm_Transit_Effect_Image_Animation *image_animation = effect;
2192    const char *image;
2193    Eina_List *elist, *elist_next;
2194
2195    EINA_LIST_FOREACH_SAFE(image_animation->images, elist, elist_next, image)
2196      {
2197         image_animation->images =
2198            eina_list_remove_list(image_animation->images, elist);
2199         eina_stringshare_del(image);
2200      }
2201
2202    free(image_animation);
2203 }
2204
2205 static void
2206 _transit_effect_image_animation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2207 {
2208    EINA_SAFETY_ON_NULL_RETURN(effect);
2209    EINA_SAFETY_ON_NULL_RETURN(transit);
2210    Eina_List *elist;
2211    Evas_Object *obj;
2212    const char *type;
2213    Elm_Transit_Effect_Image_Animation *image_animation = effect;
2214    unsigned int count = 0;
2215    int len;
2216
2217    type = eina_stringshare_add("icon");
2218    len = eina_list_count(image_animation->images);
2219
2220    if (!len) count = floor(progress * len);
2221    else count = floor(progress * (len - 1));
2222
2223    EINA_LIST_FOREACH(transit->objs, elist, obj)
2224      {
2225         if (elm_widget_type_check(obj, type))
2226           elm_icon_file_set(obj,
2227                             eina_list_nth(image_animation->images, count), NULL);
2228      }
2229
2230    eina_stringshare_del(type);
2231 }
2232
2233 static Elm_Transit_Effect *
2234 _transit_effect_image_animation_context_new(Eina_List *images)
2235 {
2236    Elm_Transit_Effect_Image_Animation *image_animation;
2237    image_animation = ELM_NEW(Elm_Transit_Effect_Image_Animation);
2238
2239    if (!image_animation) return NULL;
2240    image_animation->images = images;
2241    return image_animation;
2242 }
2243
2244 EAPI Elm_Transit_Effect *
2245 elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images)
2246 {
2247    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2248    Elm_Transit_Effect *effect = _transit_effect_image_animation_context_new(images);
2249
2250    if (!effect)
2251      {
2252         ERR("Failed to allocate image_animation effect! : transit=%p", transit);
2253         return NULL;
2254      }
2255    elm_transit_effect_add(transit,
2256                           _transit_effect_image_animation_op, effect,
2257                           _transit_effect_image_animation_context_free);
2258    return effect;
2259 }