5d110ef44e9e9c1c02bc50e37a220f8ae6aea07f
[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  *
22  * @defgroup Transit Transit
23  * @ingroup Elementary
24  *
25  * Transit (see Warning below) is designed to set the various effects for the
26  * Evas_Object such like translation, rotation, etc. For using Effects, Create
27  * transit and insert effects which are interesting.
28  * Once effects are inserted into transit, transit will manage those effects.
29  * (ex deleting).
30  *
31  * Example:
32  * @code
33  * Elm_Transit *trans = elm_transit_add();
34  * elm_transit_object_add(trans, obj);
35  * void *effect_context = elm_transit_effect_translation_context_new(0.0, 0.0,
36  *                                                               280.0, 280.0);
37  * elm_transit_effect_add(transit,
38  *                        elm_transit_effect_translation_op, effect_context,
39  *                        elm_transit_effect_translation_context_free);
40  * elm_transit_duration_set(transit, 1);
41  * elm_transit_auto_reverse_set(transit, EINA_TRUE);
42  * elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
43  * elm_transit_repeat_times_set(transit, 3);
44  * @endcode
45  *
46  * @warning We strongly recomend to use elm_transit just when edje can not do
47  * the trick. Edje has more advantage than Elm_Transit, it has more flexibility and
48  * animations can be manipulated inside the theme.
49  */
50
51 #define _TRANSIT_FOCAL 2000
52
53 struct _Elm_Transit
54 {
55 #define ELM_TRANSIT_MAGIC 0xd27f190a
56    EINA_MAGIC;
57
58    Ecore_Animator *animator;
59    Eina_Inlist *effect_list;
60    Eina_List *objs;
61    Eina_Hash *objs_data_hash;
62    Elm_Transit *prev_chain_transit;
63    Eina_List *next_chain_transits;
64    Elm_Transit_Tween_Mode tween_mode;
65    struct {
66       Elm_Transit_Effect_End_Cb func;
67       void *arg;
68    } del_data;
69    struct {
70       double delayed;
71       double paused;
72       double duration;
73       double begin;
74       double current;
75    } time;
76    struct {
77       int count;
78       int current;
79       Eina_Bool reverse;
80    } repeat;
81    double progress;
82    unsigned int effects_pending_del;
83    int walking;
84    Eina_Bool auto_reverse : 1;
85    Eina_Bool event_enabled : 1;
86    Eina_Bool deleted : 1;
87    Eina_Bool state_keep : 1;
88 };
89
90 struct _Elm_Transit_Effect_Module
91 {
92    EINA_INLIST;
93    Elm_Transit_Effect_Transition_Cb transition_cb;
94    Elm_Transit_Effect_End_Cb end_cb;
95    Elm_Transit_Effect *effect;
96    Eina_Bool deleted : 1;
97 };
98
99 struct _Elm_Obj_State
100 {
101    Evas_Coord x, y, w, h;
102    int r,g,b,a;
103    Evas_Map *map;
104    Eina_Bool map_enabled : 1;
105    Eina_Bool visible : 1;
106 };
107
108 struct _Elm_Obj_Data
109 {
110    struct _Elm_Obj_State *state;
111    Eina_Bool pass_events : 1;
112 };
113
114 typedef struct _Elm_Transit_Effect_Module Elm_Transit_Effect_Module;
115 typedef struct _Elm_Obj_Data Elm_Obj_Data;
116 typedef struct _Elm_Obj_State Elm_Obj_State;
117
118 static void
119 _elm_transit_obj_states_save(Evas_Object *obj, Elm_Obj_Data *obj_data)
120 {
121    Elm_Obj_State *state;
122
123    if (obj_data->state) return;
124    state = calloc(1, sizeof(Elm_Obj_State));
125    if (!state) return;
126    evas_object_geometry_get(obj, &state->x, &state->y, &state->w, &state->h);
127    evas_object_color_get(obj, &state->r, &state->g, &state->b, &state->a);
128    state->visible = evas_object_visible_get(obj);
129    state->map_enabled = evas_object_map_enable_get(obj);
130    if (evas_object_map_get(obj))
131      state->map = evas_map_dup(evas_object_map_get(obj));
132    obj_data->state = state;
133 }
134
135 static Eina_Bool
136 _hash_foreach_pass_events_set(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
137 {
138    Elm_Transit *transit = fdata;
139    evas_object_pass_events_set((Evas_Object*) key, transit->event_enabled);
140    return EINA_TRUE;
141 }
142
143 static Eina_Bool
144 _hash_foreach_obj_states_save(const Eina_Hash *hash __UNUSED__, const void *key, void *data, void *fdata __UNUSED__)
145 {
146    _elm_transit_obj_states_save((Evas_Object *) key, (Elm_Obj_Data *) data);
147    return EINA_TRUE;
148 }
149
150 static void
151 _elm_transit_object_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
152 {
153    Elm_Transit *transit = data;
154    Elm_Obj_Data *obj_data = eina_hash_find(transit->objs_data_hash, obj);
155    if (!obj_data) return;
156    eina_hash_del_by_key(transit->objs_data_hash, obj);
157    evas_object_pass_events_set(obj, obj_data->pass_events);
158    if (obj_data->state)
159      free(obj_data->state);
160    free(obj_data);
161    transit->objs = eina_list_remove(transit->objs, obj);
162    if (!transit->objs) elm_transit_del(transit);
163 }
164
165 //TODO: Remove!
166 //Since evas map have a afterimage bug for this time.
167 //This function is added temporary.
168 static void
169 _obj_damage_area_set(Evas_Object *obj)
170 {
171    const Evas_Map *map;
172    Evas_Coord_Point coords;
173    Evas_Coord_Point min, max;
174    int i;
175
176    map  = evas_object_map_get(obj);
177    if (!map) return;
178
179   evas_map_point_coord_get(map, 0, &coords.x, &coords.y, NULL);
180
181    max = min = coords;
182
183    for (i = 1; i < 4; ++i)
184      {
185         evas_map_point_coord_get(map, i, &coords.x, &coords.y, NULL);
186
187         if (coords.x < min.x)
188           min.x = coords.x;
189         else if (coords.x > max.x)
190           max.x = coords.x;
191
192         if (coords.y < min.y)
193           min.y = coords.y;
194         else if (coords.y > max.y)
195           max.y = coords.y;
196      }
197
198    evas_damage_rectangle_add(evas_object_evas_get(obj),
199                              min.x, min.y,
200                              max.x - min.x, max.y - min.y);
201 }
202
203 static void
204 _elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
205 {
206    Elm_Obj_Data *obj_data;
207    Elm_Obj_State *state;
208
209    //Remove duplicated objects
210    //TODO: Need to consider about optimizing here
211    while(1)
212      {
213        if (!eina_list_data_find_list(transit->objs, obj))
214          break;
215        transit->objs = eina_list_remove(transit->objs, obj);
216      }
217
218    obj_data = eina_hash_find(transit->objs_data_hash, obj);
219    if (!obj_data) return;
220    eina_hash_del_by_key(transit->objs_data_hash, obj);
221    state = obj_data->state;
222
223    evas_object_pass_events_set(obj, obj_data->pass_events);
224
225    if (state)
226      {
227         //recover the states of the object.
228         if (!transit->state_keep)
229           {
230              evas_object_move(obj, state->x, state->y);
231              evas_object_resize(obj, state->w, state->h);
232              evas_object_color_set(obj, state->r, state->g, state->b, state->a);
233              if (state->visible) evas_object_show(obj);
234              else evas_object_hide(obj);
235              if (state->map_enabled)
236                 evas_object_map_enable_set(obj, EINA_TRUE);
237              else
238                 evas_object_map_enable_set(obj, EINA_FALSE);
239              if (state->map)
240                 evas_object_map_set(obj, state->map);
241
242              //TODO: Remove!
243              //Since evas map have a afterimage bug for this time.
244              //This line is added temporary.
245              _obj_damage_area_set(obj);
246
247           }
248         free(state);
249      }
250    free(obj_data);
251
252
253    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
254                                        _elm_transit_object_remove_cb,
255                                        transit);
256 }
257
258 static void
259 _elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Module *effect_module)
260 {
261    if (effect_module->end_cb)
262      effect_module->end_cb(effect_module->effect, transit);
263    free(effect_module);
264 }
265
266 static void
267 _remove_dead_effects(Elm_Transit *transit)
268 {
269    Elm_Transit_Effect_Module *effect_module;
270
271    EINA_INLIST_FOREACH(transit->effect_list, effect_module)
272      {
273         if (effect_module->deleted)
274           {
275              _elm_transit_effect_del(transit, effect_module);
276              transit->effects_pending_del--;
277              if (!transit->effects_pending_del) return;
278           }
279      }
280 }
281
282 static void
283 _elm_transit_del(Elm_Transit *transit)
284 {
285    Elm_Transit_Effect_Module *effect_module;
286    Elm_Transit *chain_transit;
287    Eina_List *elist, *elist_next;
288
289    EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
290      {
291         if (transit->prev_chain_transit)
292           transit->prev_chain_transit->next_chain_transits = eina_list_remove(transit->prev_chain_transit->next_chain_transits, transit);
293         chain_transit->prev_chain_transit = NULL;
294      }
295
296    eina_list_free(transit->next_chain_transits);
297
298    if (transit->animator)
299      ecore_animator_del(transit->animator);
300
301    while (transit->effect_list)
302      {
303         effect_module = EINA_INLIST_CONTAINER_GET(transit->effect_list, Elm_Transit_Effect_Module);
304         transit->effect_list = eina_inlist_remove(transit->effect_list, transit->effect_list);
305      }
306
307    while (transit->objs)
308      _elm_transit_object_remove(transit, eina_list_data_get(transit->objs));
309
310    transit->deleted = EINA_TRUE;
311
312    if (transit->del_data.func)
313      transit->del_data.func(transit->del_data.arg, transit);
314
315    eina_hash_free(transit->objs_data_hash);
316
317    EINA_MAGIC_SET(transit, EINA_MAGIC_NONE);
318    free(transit);
319 }
320
321 static void
322 _chain_transits_go(Elm_Transit *transit)
323 {
324    Eina_List *elist, *elist_next;
325    Elm_Transit *chain_transit;
326
327    EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
328      elm_transit_go(chain_transit);
329 }
330
331 static void
332 _transit_animate_op(Elm_Transit *transit, double progress)
333 {
334    Elm_Transit_Effect_Module *effect_module;
335
336    transit->walking++;
337    EINA_INLIST_FOREACH(transit->effect_list, effect_module)
338      {
339         if (transit->deleted) break;
340         if (!effect_module->deleted)
341           effect_module->transition_cb(effect_module->effect, transit, progress);
342      }
343    transit->walking--;
344
345    if (transit->walking) return;
346
347    if (transit->deleted) _elm_transit_del(transit);
348    else if (transit->effects_pending_del) _remove_dead_effects(transit);
349 }
350
351 static Eina_Bool
352 _animator_animate_cb(void *data)
353 {
354    Elm_Transit *transit = data;
355    double elapsed_time, duration;
356
357    transit->time.current = ecore_loop_time_get();
358    elapsed_time = transit->time.current - transit->time.begin;
359    duration = transit->time.duration + transit->time.delayed;
360
361    if (elapsed_time > duration)
362      elapsed_time = duration;
363
364    transit->progress = elapsed_time / duration;
365    switch (transit->tween_mode)
366      {
367       case ELM_TRANSIT_TWEEN_MODE_ACCELERATE:
368         transit->progress = 1.0 - sin((ELM_PI / 2.0) + (transit->progress * ELM_PI / 2.0));
369         break;
370       case ELM_TRANSIT_TWEEN_MODE_DECELERATE:
371         transit->progress = sin(transit->progress * ELM_PI / 2.0);
372         break;
373       case ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL:
374         transit->progress = (1.0 - cos(transit->progress * ELM_PI)) / 2.0;
375         break;
376       default:
377         break;
378      }
379
380    /* Reverse? */
381    if (transit->repeat.reverse) transit->progress = 1 - transit->progress;
382
383    if (transit->time.duration > 0) _transit_animate_op(transit, transit->progress);
384
385    /* Not end. Keep going. */
386    if (elapsed_time < duration) return ECORE_CALLBACK_RENEW;
387
388    /* Repeat and reverse and time done! */
389    if ((transit->repeat.count >= 0) &&
390        (transit->repeat.current == transit->repeat.count) &&
391        ((!transit->auto_reverse) || transit->repeat.reverse))
392      {
393         /* run chain transit */
394         if (transit->next_chain_transits)
395            _chain_transits_go(transit);
396
397         elm_transit_del(transit);
398         return ECORE_CALLBACK_CANCEL;
399      }
400
401    /* Repeat Case */
402    if (!transit->auto_reverse || transit->repeat.reverse)
403      {
404         transit->repeat.current++;
405         transit->repeat.reverse = EINA_FALSE;
406      }
407    else transit->repeat.reverse = EINA_TRUE;
408
409    transit->time.begin = ecore_loop_time_get();
410
411    return ECORE_CALLBACK_RENEW;
412 }
413
414 /**
415  * Add new transit.
416  *
417  * @note Is not necessary to delete the transit object, it will be deleted at
418  * the end of its operation.
419  * @note The transit will start playing when the program enter in the main loop, is not
420  * necessary to give a start to the transit.
421  *
422  * @param duration The duration of the transit in seconds. When transit starts
423  * to run, it will last a @p duration time.
424  * @return The transit object.
425  *
426  * @ingroup Transit
427  */
428 EAPI Elm_Transit *
429 elm_transit_add(void)
430 {
431    Elm_Transit *transit = ELM_NEW(Elm_Transit);
432    if (!transit) return NULL;
433
434    EINA_MAGIC_SET(transit, ELM_TRANSIT_MAGIC);
435
436    elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
437
438    transit->objs_data_hash = eina_hash_pointer_new(NULL);
439
440    return transit;
441 }
442 /**
443  * Stops the animation and delete the @p transit object.
444  *
445  * Call this function if you wants to stop the animation before the duration
446  * time. Make sure the @p transit object is still alive with
447  * elm_transit_del_cb_set() function.
448  * All added effects will be deleted, calling its repective data_free_cb
449  * functions. The function setted by elm_transit_del_cb_set() will be called.
450  *
451  * @see elm_transit_del_cb_set()
452  *
453  * @param transit The transit object to be deleted.
454  *
455  * @ingroup Transit
456  * @warning Just call this function if you are sure the transit is alive.
457  */
458 EAPI void
459 elm_transit_del(Elm_Transit *transit)
460 {
461    ELM_TRANSIT_CHECK_OR_RETURN(transit);
462
463    if (transit->walking) transit->deleted = EINA_TRUE;
464    else _elm_transit_del(transit);
465 }
466
467 /**
468  * Add a new effect to the transit.
469  *
470  * @note The cb function and the data are the key to the effect. If you try to
471  * add an already added effect, nothing is done.
472  * @note After the first addition of an effect in @p transit, if its
473  * effect list become empty again, the @p transit will be killed by
474  * elm_transit_del(transit) function.
475  *
476  * Exemple:
477  * @code
478  * Elm_Transit *transit = elm_transit_add();
479  * elm_transit_effect_add(transit,
480  *                        elm_transit_effect_blend_op,
481  *                        elm_transit_effect_blend_context_new(),
482  *                        elm_transit_effect_blend_context_free);
483  * @endcode
484  *
485  * @param transit The transit object.
486  * @param cb The operation function. It is called when the animation begins,
487  * it is the function that actually performs the animation. It is called with
488  * the @p data, @p transit and the time progression of the animation (a double
489  * value between 0.0 and 1.0).
490  * @param data The context data of the effect.
491  * @param data_free_cb The function to free the context data, it will be called
492  * at the end of the effect, it must finalize the animation and free the
493  * @p data.
494  *
495  * @ingroup Transit
496  * @warning The transit free the context data at the and of the transition with
497  * the data_free_cb function, do not use the context data in another transit.
498  */
499 EAPI void
500 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)
501 {
502    ELM_TRANSIT_CHECK_OR_RETURN(transit);
503    EINA_SAFETY_ON_NULL_RETURN(transition_cb);
504    Elm_Transit_Effect_Module *effect_module;
505
506    EINA_INLIST_FOREACH(transit->effect_list, effect_module)
507      if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect)) return;
508
509    effect_module = ELM_NEW(Elm_Transit_Effect_Module);
510    if (!effect_module) return;
511
512    effect_module->end_cb = end_cb;
513    effect_module->transition_cb = transition_cb;
514    effect_module->effect = effect;
515
516    transit->effect_list = eina_inlist_append(transit->effect_list, (Eina_Inlist*) effect_module);
517 }
518
519 /**
520  * Delete an added effect.
521  *
522  * This function will remove the effect from the @p transit, calling the
523  * data_free_cb to free the @p data.
524  *
525  * @see elm_transit_effect_add()
526  *
527  * @note If the effect is not found, nothing is done.
528  * @note If the effect list become empty, this function will call
529  * elm_transit_del(transit), that is, it will kill the @p transit.
530  *
531  * @param transit The transit object.
532  * @param cb The operation function.
533  * @param data The context data of the effect.
534  *
535  * @ingroup Transit
536  */
537 EAPI void
538 elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect)
539 {
540    ELM_TRANSIT_CHECK_OR_RETURN(transit);
541    EINA_SAFETY_ON_NULL_RETURN(transition_cb);
542    Elm_Transit_Effect_Module *effect_module;
543
544    EINA_INLIST_FOREACH(transit->effect_list, effect_module)
545      {
546         if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect))
547           {
548              if (transit->walking)
549                {
550                   effect_module->deleted = EINA_TRUE;
551                   transit->effects_pending_del++;
552                }
553              else
554                {
555                   _elm_transit_effect_del(transit, effect_module);
556                   if (!transit->effect_list) elm_transit_del(transit);
557                }
558              return;
559           }
560      }
561 }
562
563 /**
564  * Add new object to apply the effects.
565  *
566  * @note After the first addition of an object in @p transit, if its
567  * object list become empty again, the @p transit will be killed by
568  * elm_transit_del(transit) function.
569  * @note If the @p obj belongs to another transit, the @p obj will be
570  * removed from it and it will only belong to the @p transit. If the old
571  * transit stays without objects, it will die.
572  * @note When you add an object into the @p transit, its state from
573  * evas_object_pass_events_get(obj) is saved, and it is applied when the
574  * transit ends, if you change this state whith evas_object_pass_events_set()
575  * after add the object, this state will change again when @p transit stops to
576  * run.
577  *
578  * @param transit The transit object.
579  * @param obj Object to be animated.
580  *
581  * @ingroup Transit
582  * @warning It is not allowed to add a new object after transit begins to go.
583  */
584 EAPI void
585 elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj)
586 {
587    ELM_TRANSIT_CHECK_OR_RETURN(transit);
588    EINA_SAFETY_ON_NULL_RETURN(obj);
589    Elm_Obj_Data *obj_data;
590
591    obj_data = ELM_NEW(Elm_Obj_Data);
592    obj_data->pass_events = evas_object_pass_events_get(obj);
593    if (!transit->event_enabled)
594      evas_object_pass_events_set(obj, EINA_TRUE);
595
596    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
597                                   _elm_transit_object_remove_cb,
598                                   transit);
599
600    transit->objs = eina_list_append(transit->objs, obj);
601    eina_hash_add(transit->objs_data_hash, obj, obj_data);
602
603    if (!transit->state_keep)
604      _elm_transit_obj_states_save(obj, obj_data);
605 }
606
607 /**
608  * Removes an added object from the transit.
609  *
610  * @note If the @p obj is not in the @p transit, nothing is done.
611  * @note If the list become empty, this function will call
612  * elm_transit_del(transit), that is, it will kill the @p transit.
613  *
614  * @param transit The transit object.
615  * @param obj Object to be removed from @p transit.
616  *
617  * @ingroup Transit
618  * @warning It is not allowed to remove objects after transit begins to go.
619  */
620 EAPI void
621 elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
622 {
623    ELM_TRANSIT_CHECK_OR_RETURN(transit);
624    EINA_SAFETY_ON_NULL_RETURN(obj);
625
626    _elm_transit_object_remove(transit, obj);
627    if (!transit->objs) elm_transit_del(transit);
628 }
629
630 /**
631  * Get the objects of the transit.
632  *
633  * @param transit The transit object.
634  * @return a Eina_List with the objects from the transit.
635  *
636  * @ingroup Transit
637  */
638 EAPI const Eina_List *
639 elm_transit_objects_get(const Elm_Transit *transit)
640 {
641    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
642    return transit->objs;
643 }
644
645 /**
646  * Set the event enabled when transit is operating.
647  *
648  * If @p enabled is EINA_TRUE, the objects of the transit will receives
649  * events from mouse and keyboard during the animation.
650  * @note When you add an object with elm_transit_object_add(), its state from
651  * evas_object_pass_events_get(obj) is saved, and it is applied when the
652  * transit ends, if you change this state with evas_object_pass_events_set()
653  * after adding the object, this state will change again when @p transit stops
654  * to run.
655  *
656  * @param transit The transit object.
657  * @param enabled Disable or enable.
658  *
659  * @ingroup Transit
660  */
661 EAPI void
662 elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled)
663 {
664    ELM_TRANSIT_CHECK_OR_RETURN(transit);
665
666    if (transit->event_enabled == enabled) return;
667    transit->event_enabled = !!enabled;
668    eina_hash_foreach(transit->objs_data_hash, _hash_foreach_pass_events_set, transit);
669 }
670
671 /**
672  * Get the value of event enabled status.
673  *
674  * @see elm_transit_event_enabled_set()
675  *
676  * @param transit The Transit object
677  * @return EINA_TRUE, when event is enabled. If @p transit is NULL
678  * EINA_FALSE is returned
679  *
680  * @ingroup Transit
681  */
682 EAPI Eina_Bool
683 elm_transit_event_enabled_get(const Elm_Transit *transit)
684 {
685    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
686    return transit->event_enabled;
687 }
688
689
690 /**
691  * Set the event enabled when transit is operating.
692  *
693  * If @p disabled is EINA_TRUE, the objects of the transit will receives
694  * events from mouse and keyboard during the animation.
695  * @note When you add an object with elm_transit_object_add(), its state from
696  * evas_object_pass_events_get(obj) is saved, and it is applied when the
697  * transit ends, if you change this state with evas_object_pass_events_set()
698  * after add the object, this state will change again when @p transit stops to
699  * run.
700  *
701  * @see elm_transit_event_enabled_set()
702  *
703  * @param transit The transit object.
704  * @param disabled Disable or enable.
705  *
706  * @ingroup Transit
707  */
708 EINA_DEPRECATED EAPI void
709 elm_transit_event_block_set(Elm_Transit *transit, Eina_Bool disabled)
710 {
711    elm_transit_event_enabled_set(transit, disabled);
712 }
713
714
715 /**
716  * Get the value of event block enabled  status.
717  *
718  * @see elm_transit_event_enabled_set(), elm_transit_event_enabled_get()
719  *
720  * @param transit The Transit object
721  * @return EINA_TRUE, when event is enabled. If @p transit is NULL
722  * EINA_FALSE is returned
723  *
724  * @ingroup Transit
725  */
726 EINA_DEPRECATED EAPI Eina_Bool
727 elm_transit_event_block_get(const Elm_Transit *transit)
728 {
729    return !elm_transit_event_enabled_get(transit);
730 }
731
732 /**
733  * Set the user-callback function when the transit is deleted.
734  *
735  * @note Using this function twice will overwrite the first function setted.
736  * @note the @p transit object will be deleted after call @p cb function.
737  *
738  * @param transit The transit object.
739  * @param cb Callback function pointer. This function will be called before
740  * the deletion of the transit.
741  * @param data Callback funtion user data. It is the @p op parameter.
742  *
743  * @ingroup Transit
744  */
745 EAPI void
746 elm_transit_del_cb_set(Elm_Transit *transit, void (*cb) (void *data, Elm_Transit *transit), void *data)
747 {
748    ELM_TRANSIT_CHECK_OR_RETURN(transit);
749    transit->del_data.func = cb;
750    transit->del_data.arg = data;
751 }
752
753 /**
754  * Set reverse effect automatically.
755  *
756  * If auto reverse is setted, after running the effects with the progress
757  * parameter from 0 to 1, it will call the effecs again with the progress
758  * from 1 to 0. The transit will last for a time iqual to (2 * duration * repeat),
759  * where the duration was setted with the function elm_transit_add and
760  * the repeat with the function elm_transit_repeat_times_set().
761  *
762  * @param transit The transit object.
763  * @param reverse EINA_TRUE means the auto_reverse is on.
764  *
765  * @ingroup Transit
766  */
767 EAPI void
768 elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse)
769 {
770    ELM_TRANSIT_CHECK_OR_RETURN(transit);
771    transit->auto_reverse = reverse;
772 }
773
774 /**
775  * Get if the auto reverse is on.
776  *
777  * @see elm_transit_auto_reverse_set()
778  *
779  * @param transit The transit object.
780  * @return EINA_TRUE means auto reverse is on. If @p transit is NULL
781  * EINA_FALSE is returned
782  *
783  * @ingroup Transit
784  */
785 EAPI Eina_Bool
786 elm_transit_auto_reverse_get(const Elm_Transit *transit)
787 {
788    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
789    return transit->auto_reverse;
790 }
791
792 /**
793  * Set the transit repeat count. Effect will be repeated by repeat count.
794  *
795  * This function sets the number of repetition the transit will run after
796  * the first one, that is, if @p repeat is 1, the transit will run 2 times.
797  * If the @p repeat is a negative number, it will repeat infinite times.
798  *
799  * @note If this function is called during the transit execution, the transit
800  * will run @p repeat times, ignoring the times it already performed.
801  *
802  * @param transit The transit object
803  * @param repeat Repeat count
804  *
805  * @ingroup Transit
806  */
807 EAPI void
808 elm_transit_repeat_times_set(Elm_Transit *transit, int repeat)
809 {
810    ELM_TRANSIT_CHECK_OR_RETURN(transit);
811    transit->repeat.count = repeat;
812    transit->repeat.current = 0;
813 }
814
815 /**
816  * Get the transit repeat count.
817  *
818  * @see elm_transit_repeat_times_set()
819  *
820  * @param transit The Transit object.
821  * @return The repeat count. If @p transit is NULL
822  * 0 is returned
823  *
824  * @ingroup Transit
825  */
826 EAPI int
827 elm_transit_repeat_times_get(const Elm_Transit *transit)
828 {
829    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
830    return transit->repeat.count;
831 }
832
833 /**
834  * Set the transit animation acceleration type.
835  *
836  * This function sets the tween mode of the transit that can be:
837  * ELM_TRANSIT_TWEEN_MODE_LINEAR - The default mode.
838  * ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL - Starts in accelerate mode and ends decelerating.
839  * ELM_TRANSIT_TWEEN_MODE_DECELERATE - The animation will be slowed over time.
840  * ELM_TRANSIT_TWEEN_MODE_ACCELERATE - The animation will accelerate over time.
841  *
842  * @param transit The transit object.
843  * @param tween_mode The tween type.
844  *
845  * @ingroup Transit
846  */
847 EAPI void
848 elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode)
849 {
850    ELM_TRANSIT_CHECK_OR_RETURN(transit);
851    transit->tween_mode = tween_mode;
852 }
853
854 /**
855  * Get the transit animation acceleration type.
856  *
857  * @note @p transit can not be NULL
858  *
859  * @param transit The transit object.
860  * @return The tween type. If @p transit is NULL
861  * ELM_TRANSIT_TWEEN_MODE_LINEAR is returned.
862  *
863  * @ingroup Transit
864  */
865 EAPI Elm_Transit_Tween_Mode
866 elm_transit_tween_mode_get(const Elm_Transit *transit)
867 {
868    ELM_TRANSIT_CHECK_OR_RETURN(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
869    return transit->tween_mode;
870 }
871
872 /**
873  * Set the transit animation time
874  *
875  * @note @p transit can not be NULL
876  *
877  * @param transit The transit object.
878  * @param duration The animation time.
879  *
880  * @ingroup Transit
881  */
882 EAPI void
883 elm_transit_duration_set(Elm_Transit *transit, double duration)
884 {
885    ELM_TRANSIT_CHECK_OR_RETURN(transit);
886    if (transit->animator) return;
887    transit->time.duration = duration;
888 }
889
890 /**
891  * Get the transit animation time
892  *
893  * @note @p transit can not be NULL
894  *
895  * @param transit The transit object.
896  *
897  * @return The transit animation time.
898  *
899  * @ingroup Transit
900  */
901 EAPI double
902 elm_transit_duration_get(const Elm_Transit *transit)
903 {
904    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0.0);
905    return transit->time.duration;
906 }
907
908 /**
909  * Starts the transition.
910  * Once this API is called, the transit begins to measure the time.
911  *
912  * @note @p transit can not be NULL
913  *
914  * @param transit The transit object.
915  *
916  * @ingroup Transit
917  */
918 EAPI void
919 elm_transit_go(Elm_Transit *transit)
920 {
921    ELM_TRANSIT_CHECK_OR_RETURN(transit);
922
923    if (transit->animator)
924      ecore_animator_del(transit->animator);
925
926    transit->time.paused = 0;
927    transit->time.delayed = 0;
928    transit->time.begin = ecore_loop_time_get();
929    transit->animator = ecore_animator_add(_animator_animate_cb, transit);
930 }
931
932 /**
933  * Pause/Resume the transition.
934  * If you call elm_transit_go again, paused states will affect no anymore.
935  *
936  * @note @p transit can not be NULL
937  *
938  * @param transit The transit object.
939  *
940  * @ingroup Transit
941  */
942 EAPI void
943 elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused)
944 {
945    ELM_TRANSIT_CHECK_OR_RETURN(transit);
946
947    if (!transit->animator) return;
948
949    if (paused)
950      {
951         if (transit->time.paused > 0)
952           return;
953         ecore_animator_freeze(transit->animator);
954         transit->time.paused = ecore_loop_time_get();
955      }
956    else
957      {
958         if (transit->time.paused == 0)
959           return;
960         ecore_animator_thaw(transit->animator);
961         transit->time.delayed += (ecore_loop_time_get() - transit->time.paused);
962         transit->time.paused = 0;
963      }
964 }
965
966 /**
967  * Get the value of paused status.
968  *
969  * @see elm_transit_paused_set()
970  *
971  * @note @p transit can not be NULL
972  *
973  * @param transit The transit object.
974  * @return EINA_TRUE means transition is paused. If @p transit is NULL
975  * EINA_FALSE is returned
976  *
977  * @ingroup Transit
978  */
979 EAPI Eina_Bool
980 elm_transit_paused_get(const Elm_Transit *transit)
981 {
982    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
983
984    if (transit->time.paused == 0)
985      return EINA_FALSE;
986
987    return EINA_TRUE;
988 }
989
990 /**
991  * Get the time progression of the animation (a double value between 0.0 and 1.0).
992  *
993  * @note @p transit can not be NULL
994  *
995  * @param transit The transit object.
996  *
997  * @return The time progression value. If @p transit is NULL
998  * 0 is returned
999  *
1000  * @ingroup Transit
1001  */
1002 EAPI double
1003 elm_transit_progress_value_get(const Elm_Transit *transit)
1004 {
1005    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
1006    return transit->progress;
1007 }
1008
1009
1010
1011 /**
1012  * Enable/disable keeping up the objects states.
1013  * If it is not kept, the objects states will be reset when transition ends.
1014  *
1015  * @note @p transit can not be NULL.
1016  * @note One state includes geometry, color, map data.
1017  *
1018  * @param transit The transit object.
1019  * @param state_keep Keeping or Non Keeping.
1020  *
1021  * @ingroup Transit
1022  */
1023 EAPI void
1024 elm_transit_objects_final_state_keep_set(Elm_Transit *transit, Eina_Bool state_keep)
1025 {
1026    ELM_TRANSIT_CHECK_OR_RETURN(transit);
1027    if (transit->state_keep == state_keep) return;
1028    if (transit->animator) return;
1029    transit->state_keep = !!state_keep;
1030    if (state_keep) return;
1031    eina_hash_foreach(transit->objs_data_hash, _hash_foreach_obj_states_save, NULL);
1032 }
1033
1034 /**
1035  * Get a value whether the objects states will be reset or not.
1036  *
1037  * @note @p transit can not be NULL
1038  *
1039  * @see elm_transit_objects_final_state_keep_set()
1040  *
1041  * @param transit The transit object.
1042  * @return EINA_TRUE means the states of the objects will be reset.
1043  * If @p transit is NULL, EINA_FALSE is returned
1044  *
1045  * @ingroup Transit
1046  */
1047 EAPI Eina_Bool
1048 elm_transit_objects_final_state_keep_get(const Elm_Transit *transit)
1049 {
1050    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
1051    return transit->state_keep;
1052 }
1053
1054 /**
1055  * Makes the chain relationship between two transits.
1056  *
1057  * @note @p transit can not be NULL. Transit would have multiple chain transits.
1058  * @note @p chain_transit can not be NULL. Chain transits could be chained to the only one transit.
1059  *
1060  * @param transit The transit object.
1061  * @param chain_transit The chain transit object. This transit will be operated  *                      after transit is done.
1062  *
1063  * @ingroup Transit
1064  */
1065 EAPI void
1066 elm_transit_chain_transit_add(Elm_Transit *transit, Elm_Transit *chain_transit)
1067 {
1068    ELM_TRANSIT_CHECK_OR_RETURN(transit);
1069    ELM_TRANSIT_CHECK_OR_RETURN(chain_transit);
1070
1071    if (transit == chain_transit) return;
1072    if (transit == chain_transit->prev_chain_transit) return;
1073
1074    if (chain_transit->prev_chain_transit)
1075      chain_transit->prev_chain_transit->next_chain_transits = eina_list_remove(chain_transit->prev_chain_transit->next_chain_transits, chain_transit);
1076
1077    chain_transit->prev_chain_transit = transit;
1078    transit->next_chain_transits = eina_list_append(transit->next_chain_transits, chain_transit);
1079 }
1080
1081 /**
1082  * Get the current chain transit list.
1083  *
1084  * @note @p transit can not be NULL.
1085  *
1086  * @param transit The transit object.
1087  * @return chain transit list.
1088  *
1089  * @ingroup Transit
1090  */
1091 EAPI Eina_List *
1092 elm_transit_chain_transits_get(const Elm_Transit * transit)
1093 {
1094    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1095    return transit->next_chain_transits;
1096 }
1097
1098 ///////////////////////////////////////////////////////////////////////////////
1099 //Resizing Effect
1100 ///////////////////////////////////////////////////////////////////////////////
1101 typedef struct _Elm_Transit_Effect_Resizing Elm_Transit_Effect_Resizing;
1102
1103 struct _Elm_Transit_Effect_Resizing
1104 {
1105    struct _size {
1106       Evas_Coord w, h;
1107    } from, to;
1108 };
1109
1110 static void
1111 _transit_effect_resizing_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1112 {
1113    Elm_Transit_Effect_Resizing *resizing = effect;
1114    free(resizing);
1115 }
1116
1117 static void
1118 _transit_effect_resizing_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1119 {
1120    EINA_SAFETY_ON_NULL_RETURN(effect);
1121    EINA_SAFETY_ON_NULL_RETURN(transit);
1122    Evas_Coord w, h;
1123    Evas_Object *obj;
1124    Eina_List *elist;
1125    Elm_Transit_Effect_Resizing *resizing = effect;
1126
1127    w = resizing->from.w + (resizing->to.w * progress);
1128    h = resizing->from.h + (resizing->to.h * progress);
1129
1130    EINA_LIST_FOREACH(transit->objs, elist, obj)
1131      evas_object_resize(obj, w, h);
1132 }
1133
1134 static Elm_Transit_Effect *
1135 _transit_effect_resizing_context_new(Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
1136 {
1137    Elm_Transit_Effect_Resizing *resizing;
1138
1139    resizing = ELM_NEW(Elm_Transit_Effect_Resizing);
1140    if (!resizing) return NULL;
1141
1142    resizing->from.w = from_w;
1143    resizing->from.h = from_h;
1144    resizing->to.w = to_w - from_w;
1145    resizing->to.h = to_h - from_h;
1146
1147    return resizing;
1148 }
1149
1150 /**
1151  * Add the Resizing Effect to Elm_Transit.
1152  *
1153  * @note This API is one of the facades. It creates resizing effect context
1154  * and add it's required APIs to elm_transit_effect_add.
1155  *
1156  * @see elm_transit_effect_add()
1157  *
1158  * @param transit Transit object.
1159  * @param from_w Object width size when effect begins.
1160  * @param from_h Object height size when effect begins.
1161  * @param to_w Object width size when effect ends.
1162  * @param to_h Object height size when effect ends.
1163  * @return Resizing effect context data.
1164  *
1165  * @ingroup Transit
1166  */
1167 EAPI Elm_Transit_Effect *
1168 elm_transit_effect_resizing_add(Elm_Transit *transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
1169 {
1170    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1171    Elm_Transit_Effect *effect = _transit_effect_resizing_context_new(from_w, from_h, to_w, to_h);
1172
1173    if (!effect) return NULL;
1174    elm_transit_effect_add(transit,
1175                           _transit_effect_resizing_op, effect,
1176                           _transit_effect_resizing_context_free);
1177    return effect;
1178 }
1179
1180 ///////////////////////////////////////////////////////////////////////////////
1181 //Translation Effect
1182 ///////////////////////////////////////////////////////////////////////////////
1183 typedef struct _Elm_Transit_Effect_Translation Elm_Transit_Effect_Translation;
1184 typedef struct _Elm_Transit_Effect_Translation_Node Elm_Transit_Effect_Translation_Node;
1185
1186 struct _Elm_Transit_Effect_Translation_Node
1187 {
1188    Evas_Object *obj;
1189    Evas_Coord x, y;
1190 };
1191
1192 struct _Elm_Transit_Effect_Translation
1193 {
1194    struct _position_variation {
1195       Evas_Coord dx, dy;
1196    } from, to;
1197    Eina_List *nodes;
1198 };
1199
1200 static void
1201 _translation_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1202 {
1203    Elm_Transit_Effect_Translation *translation = data;
1204    Eina_List *elist;
1205    Elm_Transit_Effect_Translation_Node *translation_node;
1206
1207    EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
1208      {
1209         if (translation_node->obj != obj) continue;
1210         translation->nodes = eina_list_remove_list(translation->nodes, elist);
1211         free(translation_node);
1212         break;
1213      }
1214 }
1215
1216 static Eina_List *
1217 _translation_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Translation *translation)
1218 {
1219    Elm_Transit_Effect_Translation_Node *translation_node;
1220    const Eina_List *elist;
1221    Evas_Object *obj;
1222    Eina_List *data_list = NULL;
1223    const Eina_List *objs = elm_transit_objects_get(transit);
1224
1225    EINA_LIST_FOREACH(objs, elist, obj)
1226      {
1227         translation_node = ELM_NEW(Elm_Transit_Effect_Translation_Node);
1228         if (!translation_node)
1229           {
1230              eina_list_free(data_list);
1231              return NULL;
1232           }
1233         translation_node->obj = obj;
1234         evas_object_geometry_get(obj, &(translation_node->x),
1235                                  &(translation_node->y), NULL, NULL);
1236         data_list = eina_list_append(data_list, translation_node);
1237         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1238                                        _translation_object_del_cb, translation);
1239      }
1240    return data_list;
1241 }
1242
1243 void
1244 _transit_effect_translation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1245 {
1246    EINA_SAFETY_ON_NULL_RETURN(effect);
1247    Elm_Transit_Effect_Translation *translation = effect;
1248    Eina_List *elist, *elist_next;
1249    Elm_Transit_Effect_Translation_Node *translation_node;
1250
1251    EINA_LIST_FOREACH_SAFE(translation->nodes,
1252                           elist, elist_next, translation_node)
1253      {
1254         evas_object_event_callback_del(translation_node->obj,
1255                                        EVAS_CALLBACK_DEL, _translation_object_del_cb);
1256         translation->nodes = eina_list_remove_list(translation->nodes, elist);
1257         free(translation_node);
1258      }
1259    free(translation);
1260 }
1261
1262 void
1263 _transit_effect_translation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress __UNUSED__)
1264 {
1265    EINA_SAFETY_ON_NULL_RETURN(effect);
1266    EINA_SAFETY_ON_NULL_RETURN(transit);
1267    Evas_Coord x, y;
1268    Elm_Transit_Effect_Translation *translation = effect;
1269    Elm_Transit_Effect_Translation_Node *translation_node;
1270    Eina_List *elist;
1271
1272    if (!translation->nodes)
1273      translation->nodes = _translation_nodes_build(transit, translation);
1274
1275    EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
1276      {
1277         x = translation_node->x + translation->from.dx
1278            + (translation->to.dx * progress);
1279         y = translation_node->y + translation->from.dy
1280            + (translation->to.dy * progress);
1281         evas_object_move(translation_node->obj, x, y);
1282      }
1283 }
1284
1285 static Elm_Transit_Effect *
1286 _transit_effect_translation_context_new(Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
1287 {
1288    Elm_Transit_Effect_Translation *translation;
1289
1290    translation = ELM_NEW(Elm_Transit_Effect_Translation);
1291    if (!translation) return NULL;
1292
1293    translation->from.dx = from_dx;
1294    translation->from.dy = from_dy;
1295    translation->to.dx = to_dx - from_dx;
1296    translation->to.dy = to_dy - from_dy;
1297
1298    return translation;
1299 }
1300
1301 /**
1302  * Add the Translation Effect to Elm_Transit.
1303  *
1304  * @note This API is one of the facades. It creates translation effect context
1305  * and add it's required APIs to elm_transit_effect_add.
1306  *
1307  * @see elm_transit_effect_add()
1308  *
1309  * @param transit Transit object.
1310  * @param from_dx X Position variation when effect begins.
1311  * @param from_dy Y Position variation when effect begins.
1312  * @param to_dx X Position variation when effect ends.
1313  * @param to_dy Y Position variation when effect ends.
1314  * @return Translation effect context data.
1315  *
1316  * @ingroup Transit
1317  * @warning Is higher recommended just create a transit with this effect when
1318  * the window that the objects of the transit belongs has already been created.
1319  * This is because this effect needs the geometry information about the objects,
1320  * and if the window was not created yet, it can get a wrong information.
1321  */
1322 EAPI Elm_Transit_Effect *
1323 elm_transit_effect_translation_add(Elm_Transit *transit, Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
1324 {
1325    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1326    Elm_Transit_Effect *effect_context = _transit_effect_translation_context_new(from_dx, from_dy, to_dx, to_dy);
1327
1328    if (!effect_context) return NULL;
1329    elm_transit_effect_add(transit,
1330                           _transit_effect_translation_op, effect_context,
1331                           _transit_effect_translation_context_free);
1332    return effect_context;
1333 }
1334
1335
1336 ///////////////////////////////////////////////////////////////////////////////
1337 //Zoom Effect
1338 ///////////////////////////////////////////////////////////////////////////////
1339 typedef struct _Elm_Transit_Effect_Zoom Elm_Transit_Effect_Zoom;
1340
1341 struct _Elm_Transit_Effect_Zoom
1342 {
1343    float from, to;
1344 };
1345
1346 void
1347 _transit_effect_zoom_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1348 {
1349    Elm_Transit_Effect_Zoom *zoom = effect;
1350    free(zoom);
1351 }
1352
1353 static void
1354 _transit_effect_zoom_op(Elm_Transit_Effect *effect, Elm_Transit *transit , double progress)
1355 {
1356    EINA_SAFETY_ON_NULL_RETURN(effect);
1357    EINA_SAFETY_ON_NULL_RETURN(transit);
1358    Evas_Object *obj;
1359    Eina_List *elist;
1360    Elm_Transit_Effect_Zoom *zoom = effect;
1361    Evas_Map *map;
1362    Evas_Coord x, y, w, h;
1363
1364    map = evas_map_new(4);
1365    if (!map) return;
1366
1367    EINA_LIST_FOREACH(transit->objs, elist, obj)
1368      {
1369         evas_object_geometry_get(obj, &x, &y, &w, &h);
1370         evas_map_util_points_populate_from_object_full(map, obj, zoom->from +
1371                                                        (progress * zoom->to));
1372         evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
1373         evas_object_map_set(obj, map);
1374         evas_object_map_enable_set(obj, EINA_TRUE);
1375      }
1376    evas_map_free(map);
1377 }
1378
1379 static Elm_Transit_Effect *
1380 _transit_effect_zoom_context_new(float from_rate, float to_rate)
1381 {
1382    Elm_Transit_Effect_Zoom *zoom;
1383
1384    zoom = ELM_NEW(Elm_Transit_Effect_Zoom);
1385    if (!zoom) return NULL;
1386
1387    zoom->from = (_TRANSIT_FOCAL - (from_rate * _TRANSIT_FOCAL)) * (1 / from_rate);
1388    zoom->to = ((_TRANSIT_FOCAL - (to_rate * _TRANSIT_FOCAL)) * (1 / to_rate)) - zoom->from;
1389
1390    return zoom;
1391 }
1392
1393 /**
1394  * Add the Zoom Effect to Elm_Transit.
1395  *
1396  * @note This API is one of the facades. It creates zoom effect context
1397  * and add it's required APIs to elm_transit_effect_add.
1398  *
1399  * @see elm_transit_effect_add()
1400  *
1401  * @param transit Transit object.
1402  * @param from_rate Scale rate when effect begins (1 is current rate).
1403  * @param to_rate Scale rate when effect ends.
1404  * @return Zoom effect context data.
1405  *
1406  * @ingroup Transit
1407  * @warning Is higher recommended just create a transit with this effect when
1408  * the window that the objects of the transit belongs has already been created.
1409  * This is because this effect needs the geometry information about the objects,
1410  * and if the window was not created yet, it can get a wrong information.
1411  */
1412 EAPI Elm_Transit_Effect *
1413 elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate)
1414 {
1415    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1416    Elm_Transit_Effect *effect_context = _transit_effect_zoom_context_new(from_rate, to_rate);
1417
1418    if (!effect_context) return NULL;
1419    elm_transit_effect_add(transit,
1420                           _transit_effect_zoom_op, effect_context,
1421                           _transit_effect_zoom_context_free);
1422    return effect_context;
1423 }
1424
1425
1426 ///////////////////////////////////////////////////////////////////////////////
1427 //Flip Effect
1428 ///////////////////////////////////////////////////////////////////////////////
1429 typedef struct _Elm_Transit_Effect_Flip Elm_Transit_Effect_Flip;
1430
1431 struct _Elm_Transit_Effect_Flip
1432 {
1433    Elm_Transit_Effect_Flip_Axis axis;
1434    Eina_Bool cw : 1;
1435 };
1436
1437 static void
1438 _transit_effect_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
1439 {
1440    EINA_SAFETY_ON_NULL_RETURN(effect);
1441    EINA_SAFETY_ON_NULL_RETURN(transit);
1442    Elm_Transit_Effect_Flip *flip = effect;
1443    Evas_Object *front, *back;
1444    int i;
1445    int count = eina_list_count(transit->objs);
1446
1447    for (i = 0; i < (count - 1); i += 2)
1448      {
1449         front = eina_list_nth(transit->objs, i);
1450         back = eina_list_nth(transit->objs, i+1);
1451         evas_object_map_enable_set(front, EINA_FALSE);
1452         evas_object_map_enable_set(back, EINA_FALSE);
1453      }
1454    free(flip);
1455 }
1456
1457 static void
1458 _transit_effect_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1459 {
1460    EINA_SAFETY_ON_NULL_RETURN(effect);
1461    EINA_SAFETY_ON_NULL_RETURN(transit);
1462    Evas_Object *obj, *front, *back;
1463    int count, i;
1464    Elm_Transit_Effect_Flip *flip = effect;
1465    Evas_Map *map;
1466    float degree;
1467    Evas_Coord x, y, w, h;
1468
1469    map = evas_map_new(4);
1470    if (!map) return;
1471
1472    if (flip->cw) degree = (float)(progress * 180);
1473    else degree = (float)(progress * -180);
1474
1475    count = eina_list_count(transit->objs);
1476
1477    for (i = 0; i < (count - 1); i += 2)
1478      {
1479         Evas_Coord half_w, half_h;
1480
1481         front = eina_list_nth(transit->objs, i);
1482         back = eina_list_nth(transit->objs, i+1);
1483
1484         if ((degree < 90) && (degree > -90))
1485           {
1486              obj = front;
1487              if (front != back)
1488                {
1489                   evas_object_hide(back);
1490                   evas_object_show(front);
1491                }
1492           }
1493         else
1494           {
1495              obj = back;
1496              if (front != back)
1497                {
1498                   evas_object_hide(front);
1499                   evas_object_show(back);
1500                }
1501           }
1502
1503         evas_map_util_points_populate_from_object_full(map, obj, 0);
1504         evas_object_geometry_get(obj, &x, &y, &w, &h);
1505         half_w = (w / 2);
1506         half_h = (h / 2);
1507
1508         if (flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1509           {
1510              if ((degree >= 90) || (degree <= -90))
1511                {
1512                   evas_map_point_image_uv_set(map, 0, w, 0);
1513                   evas_map_point_image_uv_set(map, 1, 0, 0);
1514                   evas_map_point_image_uv_set(map, 2, 0, h);
1515                   evas_map_point_image_uv_set(map, 3, w, h);
1516                }
1517              evas_map_util_3d_rotate(map, 0, degree,
1518                                      0, x + half_w, y + half_h, 0);
1519           }
1520         else
1521           {
1522              if ((degree >= 90) || (degree <= -90))
1523                {
1524                   evas_map_point_image_uv_set(map, 0, 0, h);
1525                   evas_map_point_image_uv_set(map, 1, w, h);
1526                   evas_map_point_image_uv_set(map, 2, w, 0);
1527                   evas_map_point_image_uv_set(map, 3, 0, 0);
1528                }
1529              evas_map_util_3d_rotate(map, degree,
1530                                      0, 0, x + half_w, y + half_h, 0);
1531           }
1532         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
1533         evas_object_map_enable_set(front, EINA_TRUE);
1534         evas_object_map_enable_set(back, EINA_TRUE);
1535         evas_object_map_set(obj, map);
1536      }
1537    evas_map_free(map);
1538 }
1539
1540 static Elm_Transit_Effect *
1541 _transit_effect_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1542 {
1543    Elm_Transit_Effect_Flip *flip;
1544
1545    flip = ELM_NEW(Elm_Transit_Effect_Flip);
1546    if (!flip) return NULL;
1547
1548    flip->cw = cw;
1549    flip->axis = axis;
1550
1551    return flip;
1552 }
1553
1554 /**
1555  * Add the Flip Effect to Elm_Transit.
1556  *
1557  * @note This API is one of the facades. It creates flip effect context
1558  * and add it's required APIs to elm_transit_effect_add.
1559  * @note This effect is applied to each pair of objects in the order they are listed
1560  * in the transit list of objects. The first object in the pair will be the
1561  * "front" object and the second will be the "back" object.
1562  *
1563  * @see elm_transit_effect_add()
1564  *
1565  * @param transit Transit object.
1566  * @param axis Flipping Axis(X or Y).
1567  * @param cw Flipping Direction. EINA_TRUE is clock-wise.
1568  * @return Flip effect context data.
1569  *
1570  * @ingroup Transit
1571  * @warning Is higher recommended just create a transit with this effect when
1572  * the window that the objects of the transit belongs has already been created.
1573  * This is because this effect needs the geometry information about the objects,
1574  * and if the window was not created yet, it can get a wrong information.
1575  */
1576 EAPI Elm_Transit_Effect *
1577 elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1578 {
1579    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1580    Elm_Transit_Effect *effect_context = _transit_effect_flip_context_new(axis, cw);
1581
1582    if (!effect_context) return NULL;
1583    elm_transit_effect_add(transit,
1584                           _transit_effect_flip_op, effect_context,
1585                           _transit_effect_flip_context_free);
1586    return effect_context;
1587 }
1588
1589 ///////////////////////////////////////////////////////////////////////////////
1590 //ResizableFlip Effect
1591 ///////////////////////////////////////////////////////////////////////////////
1592 typedef struct _Elm_Transit_Effect_Resizable_Flip Elm_Transit_Effect_ResizableFlip;
1593 typedef struct _Elm_Transit_Effect_Resizable_Flip_Node Elm_Transit_Effect_ResizableFlip_Node;
1594
1595 struct _Elm_Transit_Effect_Resizable_Flip_Node
1596 {
1597    Evas_Object *front;
1598    Evas_Object *back;
1599    struct _vector2d {
1600       float x, y;
1601    } from_pos, from_size, to_pos, to_size;
1602 };
1603
1604 struct _Elm_Transit_Effect_Resizable_Flip
1605 {
1606    Eina_List *nodes;
1607    Eina_Bool cw : 1;
1608    Elm_Transit_Effect_Flip_Axis axis;
1609 };
1610
1611 static void
1612 _resizable_flip_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1613 {
1614    Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
1615    Eina_List *elist;
1616    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1617
1618    EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1619      {
1620         if (resizable_flip_node->front == obj)
1621           evas_object_event_callback_del(resizable_flip_node->back,
1622                                          EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1623         else if (resizable_flip_node->back == obj)
1624           evas_object_event_callback_del(resizable_flip_node->front,
1625                                          EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1626         else continue;
1627
1628         resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1629                                                       elist);
1630         free(resizable_flip_node);
1631         break;
1632      }
1633 }
1634
1635 static Eina_List *
1636 _resizable_flip_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_ResizableFlip *resizable_flip)
1637 {
1638    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1639    Eina_List *data_list = NULL;
1640    Evas_Coord front_x, front_y, front_w, front_h;
1641    Evas_Coord back_x, back_y, back_w, back_h;
1642    int i, count;
1643
1644    count = eina_list_count(transit->objs);
1645    for (i = 0; i < (count - 1); i += 2)
1646      {
1647         resizable_flip_node = ELM_NEW(Elm_Transit_Effect_ResizableFlip_Node);
1648         if (!resizable_flip_node)
1649           {
1650              eina_list_free(data_list);
1651              return NULL;
1652           }
1653
1654         resizable_flip_node->front = eina_list_nth(transit->objs, i);
1655         resizable_flip_node->back = eina_list_nth(transit->objs, i+1);
1656
1657         evas_object_geometry_get(resizable_flip_node->front,
1658                                  &front_x, &front_y, &front_w, &front_h);
1659         evas_object_geometry_get(resizable_flip_node->back,
1660                                  &back_x, &back_y, &back_w, &back_h);
1661
1662         resizable_flip_node->from_pos.x = front_x;
1663         resizable_flip_node->from_pos.y = front_y;
1664         resizable_flip_node->to_pos.x = back_x - front_x;
1665         resizable_flip_node->to_pos.y = back_y - front_y;
1666
1667         resizable_flip_node->from_size.x = front_w;
1668         resizable_flip_node->from_size.y = front_h;
1669         resizable_flip_node->to_size.x = back_w - front_w;
1670         resizable_flip_node->to_size.y = back_h - front_h;
1671
1672         data_list = eina_list_append(data_list, resizable_flip_node);
1673
1674         evas_object_event_callback_add(resizable_flip_node->back,
1675                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1676         evas_object_event_callback_add(resizable_flip_node->front,
1677                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1678      }
1679
1680    return data_list;
1681 }
1682
1683 static void
1684 _set_image_uv_by_axis_y(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
1685 {
1686    if ((degree >= 90) || (degree <= -90))
1687      {
1688         evas_map_point_image_uv_set(map, 0,
1689                                     (flip->from_size.x * 2) + flip->to_size.x,
1690                                     0);
1691         evas_map_point_image_uv_set(map, 1, 0, 0);
1692         evas_map_point_image_uv_set(map, 2, 0,
1693                                     (flip->from_size.y * 2) + flip->to_size.y);
1694         evas_map_point_image_uv_set(map, 3,
1695                                     (flip->from_size.x * 2) + flip->to_size.x,
1696                                     (flip->from_size.y * 2) + flip->to_size.y);
1697      }
1698    else
1699      {
1700         evas_map_point_image_uv_set(map, 0, 0, 0);
1701         evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1702         evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1703                                     flip->from_size.y);
1704         evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1705      }
1706 }
1707
1708 static void
1709 _set_image_uv_by_axis_x(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
1710 {
1711    if ((degree >= 90) || (degree <= -90))
1712      {
1713         evas_map_point_image_uv_set(map, 0, 0,
1714                                     (flip->from_size.y * 2) + flip->to_size.y);
1715         evas_map_point_image_uv_set(map, 1,
1716                                     (flip->from_size.x * 2) + flip->to_size.x,
1717                                     (flip->from_size.y * 2) + flip->to_size.y);
1718         evas_map_point_image_uv_set(map, 2,
1719                                     (flip->from_size.x * 2) + flip->to_size.x,
1720                                     0);
1721         evas_map_point_image_uv_set(map, 3, 0, 0);
1722      }
1723    else
1724      {
1725         evas_map_point_image_uv_set(map, 0, 0, 0);
1726         evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1727         evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1728                                     flip->from_size.y);
1729         evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1730      }
1731 }
1732
1733 void
1734 _transit_effect_resizable_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1735 {
1736    EINA_SAFETY_ON_NULL_RETURN(effect);
1737
1738    Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
1739    Eina_List *elist, *elist_next;
1740    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1741
1742    EINA_LIST_FOREACH_SAFE(resizable_flip->nodes,
1743                           elist, elist_next, resizable_flip_node)
1744      {
1745         evas_object_map_enable_set(resizable_flip_node->front, EINA_FALSE);
1746         evas_object_map_enable_set(resizable_flip_node->back, EINA_FALSE);
1747
1748         resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1749                                                       elist);
1750
1751         evas_object_event_callback_del(resizable_flip_node->back,
1752                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1753         evas_object_event_callback_del(resizable_flip_node->front,
1754                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1755         free(resizable_flip_node);
1756      }
1757    free(resizable_flip);
1758 }
1759
1760 void
1761 _transit_effect_resizable_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
1762 {
1763    EINA_SAFETY_ON_NULL_RETURN(effect);
1764    Evas_Map *map;
1765    Evas_Object *obj;
1766    float x, y, w, h;
1767    float degree;
1768    Evas_Coord half_w, half_h;
1769    Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
1770    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1771    Eina_List *elist;
1772
1773    map = evas_map_new(4);
1774    if (!map) return;
1775
1776    if (resizable_flip->cw) degree = (float)(progress * 180);
1777    else degree = (float)(progress * -180);
1778
1779    if (!resizable_flip->nodes)
1780      resizable_flip->nodes = _resizable_flip_nodes_build(transit,
1781                                                           resizable_flip);
1782
1783    EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1784      {
1785         if ((degree < 90) && (degree > -90))
1786           {
1787              obj = resizable_flip_node->front;
1788              if (resizable_flip_node->front != resizable_flip_node->back)
1789                {
1790                   evas_object_hide(resizable_flip_node->back);
1791                   evas_object_show(resizable_flip_node->front);
1792                }
1793           }
1794         else
1795           {
1796              obj = resizable_flip_node->back;
1797              if (resizable_flip_node->front != resizable_flip_node->back)
1798                {
1799                   evas_object_hide(resizable_flip_node->front);
1800                   evas_object_show(resizable_flip_node->back);
1801                }
1802           }
1803
1804         x = resizable_flip_node->from_pos.x +
1805            (resizable_flip_node->to_pos.x * progress);
1806         y = resizable_flip_node->from_pos.y +
1807            (resizable_flip_node->to_pos.y * progress);
1808         w = resizable_flip_node->from_size.x +
1809            (resizable_flip_node->to_size.x * progress);
1810         h = resizable_flip_node->from_size.y +
1811            (resizable_flip_node->to_size.y * progress);
1812         evas_map_point_coord_set(map, 0, x, y, 0);
1813         evas_map_point_coord_set(map, 1, x + w, y, 0);
1814         evas_map_point_coord_set(map, 2, x + w, y + h, 0);
1815         evas_map_point_coord_set(map, 3, x, y + h, 0);
1816
1817         half_w = (Evas_Coord)(w / 2);
1818         half_h = (Evas_Coord)(h / 2);
1819
1820         if (resizable_flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1821           {
1822              _set_image_uv_by_axis_y(map, resizable_flip_node, degree);
1823              evas_map_util_3d_rotate(map, 0, degree,
1824                                      0, x + half_w, y + half_h, 0);
1825           }
1826         else
1827           {
1828              _set_image_uv_by_axis_x(map, resizable_flip_node, degree);
1829              evas_map_util_3d_rotate(map, degree, 0,
1830                                      0, x + half_w, y + half_h, 0);
1831           }
1832
1833         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
1834         evas_object_map_enable_set(resizable_flip_node->front, EINA_TRUE);
1835         evas_object_map_enable_set(resizable_flip_node->back, EINA_TRUE);
1836         evas_object_map_set(obj, map);
1837      }
1838    evas_map_free(map);
1839 }
1840
1841 static Elm_Transit_Effect *
1842 _transit_effect_resizable_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1843 {
1844    Elm_Transit_Effect_ResizableFlip *resizable_flip;
1845
1846    resizable_flip = ELM_NEW(Elm_Transit_Effect_ResizableFlip);
1847    if (!resizable_flip) return NULL;
1848
1849    resizable_flip->cw = cw;
1850    resizable_flip->axis = axis;
1851
1852    return resizable_flip;
1853 }
1854
1855 /**
1856  * Add the Resizable Flip Effect to Elm_Transit.
1857  *
1858  * @note This API is one of the facades. It creates resizable flip effect context
1859  * and add it's required APIs to elm_transit_effect_add.
1860  * @note This effect is applied to each pair of objects in the order they are listed
1861  * in the transit list of objects. The first object in the pair will be the
1862  * "front" object and the second will be the "back" object.
1863  *
1864  * @see elm_transit_effect_add()
1865  *
1866  * @param transit Transit object.
1867  * @param axis Flipping Axis(X or Y).
1868  * @param cw Flipping Direction. EINA_TRUE is clock-wise.
1869  * @return Resizable flip effect context data.
1870  *
1871  * @ingroup Transit
1872  * @warning Is higher recommended just create a transit with this effect when
1873  * the window that the objects of the transit belongs has already been created.
1874  * This is because this effect needs the geometry information about the objects,
1875  * and if the window was not created yet, it can get a wrong information.
1876  */
1877 EAPI Elm_Transit_Effect *
1878 elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1879 {
1880    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1881    Elm_Transit_Effect *effect_context = _transit_effect_resizable_flip_context_new(axis, cw);
1882
1883    if (!effect_context) return NULL;
1884    elm_transit_effect_add(transit,
1885                           _transit_effect_resizable_flip_op, effect_context,
1886                           _transit_effect_resizable_flip_context_free);
1887    return effect_context;
1888 }
1889
1890
1891 ///////////////////////////////////////////////////////////////////////////////
1892 //Wipe Effect
1893 ///////////////////////////////////////////////////////////////////////////////
1894 typedef struct _Elm_Transit_Effect_Wipe Elm_Transit_Effect_Wipe;
1895
1896 struct _Elm_Transit_Effect_Wipe
1897 {
1898    Elm_Transit_Effect_Wipe_Type type;
1899    Elm_Transit_Effect_Wipe_Dir dir;
1900 };
1901
1902 static void
1903 _elm_fx_wipe_hide(Evas_Map * map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1904 {
1905    float w2, h2;
1906
1907    switch (dir)
1908      {
1909       case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1910          w2 = w - (w * progress);
1911          h2 = (y + h);
1912          evas_map_point_image_uv_set(map, 0, 0, 0);
1913          evas_map_point_image_uv_set(map, 1, w2, 0);
1914          evas_map_point_image_uv_set(map, 2, w2, h);
1915          evas_map_point_image_uv_set(map, 3, 0, h);
1916          evas_map_point_coord_set(map, 0, x, y, 0);
1917          evas_map_point_coord_set(map, 1, x + w2, y, 0);
1918          evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1919          evas_map_point_coord_set(map, 3, x, h2, 0);
1920          break;
1921       case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1922          w2 = (w * progress);
1923          h2 = (y + h);
1924          evas_map_point_image_uv_set(map, 0, w2, 0);
1925          evas_map_point_image_uv_set(map, 1, w, 0);
1926          evas_map_point_image_uv_set(map, 2, w, h);
1927          evas_map_point_image_uv_set(map, 3, w2, h);
1928          evas_map_point_coord_set(map, 0, x + w2, y, 0);
1929          evas_map_point_coord_set(map, 1, x + w, y, 0);
1930          evas_map_point_coord_set(map, 2, x + w, h2, 0);
1931          evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1932          break;
1933       case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1934          w2 = (x + w);
1935          h2 = h - (h * progress);
1936          evas_map_point_image_uv_set(map, 0, 0, 0);
1937          evas_map_point_image_uv_set(map, 1, w, 0);
1938          evas_map_point_image_uv_set(map, 2, w, h2);
1939          evas_map_point_image_uv_set(map, 3, 0, h2);
1940          evas_map_point_coord_set(map, 0, x, y, 0);
1941          evas_map_point_coord_set(map, 1, w2, y, 0);
1942          evas_map_point_coord_set(map, 2, w2, y+h2, 0);
1943          evas_map_point_coord_set(map, 3, x, y+h2, 0);
1944          break;
1945       case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1946          w2 = (x + w);
1947          h2 = (h * progress);
1948          evas_map_point_image_uv_set(map, 0, 0, h2);
1949          evas_map_point_image_uv_set(map, 1, w, h2);
1950          evas_map_point_image_uv_set(map, 2, w, h);
1951          evas_map_point_image_uv_set(map, 3, 0, h);
1952          evas_map_point_coord_set(map, 0, x, y + h2, 0);
1953          evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1954          evas_map_point_coord_set(map, 2, w2, y + h, 0);
1955          evas_map_point_coord_set(map, 3, x, y + h, 0);
1956          break;
1957       default:
1958          break;
1959      }
1960    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
1961 }
1962
1963 static void
1964 _elm_fx_wipe_show(Evas_Map *map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1965 {
1966    float w2, h2;
1967
1968    switch (dir)
1969      {
1970       case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1971          w2 = (w - (w * progress));
1972          h2 = (y + h);
1973          evas_map_point_image_uv_set(map, 0, w2, 0);
1974          evas_map_point_image_uv_set(map, 1, w, 0);
1975          evas_map_point_image_uv_set(map, 2, w, h);
1976          evas_map_point_image_uv_set(map, 3, w2, h);
1977          evas_map_point_coord_set(map, 0, x + w2, y, 0);
1978          evas_map_point_coord_set(map, 1, w, y, 0);
1979          evas_map_point_coord_set(map, 2, w, h2, 0);
1980          evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1981          break;
1982       case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1983          w2 = (w * progress);
1984          h2 = (y + h);
1985          evas_map_point_image_uv_set(map, 0, 0, 0);
1986          evas_map_point_image_uv_set(map, 1, w2, 0);
1987          evas_map_point_image_uv_set(map, 2, w2, h);
1988          evas_map_point_image_uv_set(map, 3, 0, h);
1989          evas_map_point_coord_set(map, 0, x, y, 0);
1990          evas_map_point_coord_set(map, 1, x + w2, y, 0);
1991          evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1992          evas_map_point_coord_set(map, 3, x, h2, 0);
1993          break;
1994       case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1995          w2 = (x + w);
1996          h2 = (h - (h * progress));
1997          evas_map_point_image_uv_set(map, 0, 0, h2);
1998          evas_map_point_image_uv_set(map, 1, w, h2);
1999          evas_map_point_image_uv_set(map, 2, w, h);
2000          evas_map_point_image_uv_set(map, 3, 0, h);
2001          evas_map_point_coord_set(map, 0, x, y + h2, 0);
2002          evas_map_point_coord_set(map, 1, w2, y + h2, 0);
2003          evas_map_point_coord_set(map, 2, w2, y + h, 0);
2004          evas_map_point_coord_set(map, 3, x, y + h, 0);
2005          break;
2006       case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
2007          w2 = (x + w);
2008          h2 = (h * progress);
2009          evas_map_point_image_uv_set(map, 0, 0, 0);
2010          evas_map_point_image_uv_set(map, 1, w, 0);
2011          evas_map_point_image_uv_set(map, 2, w, h2);
2012          evas_map_point_image_uv_set(map, 3, 0, h2);
2013          evas_map_point_coord_set(map, 0, x, y, 0);
2014          evas_map_point_coord_set(map, 1, w2, y, 0);
2015          evas_map_point_coord_set(map, 2, w2, y + h2, 0);
2016          evas_map_point_coord_set(map, 3, x, y + h2, 0);
2017          break;
2018       default:
2019          break;
2020      }
2021    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
2022 }
2023
2024 static void
2025 _transit_effect_wipe_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
2026 {
2027    EINA_SAFETY_ON_NULL_RETURN(effect);
2028    EINA_SAFETY_ON_NULL_RETURN(transit);
2029    Eina_List *elist;
2030    Evas_Object *obj;
2031    Elm_Transit_Effect_Wipe *wipe = effect;
2032    Eina_Bool reverse = elm_transit_auto_reverse_get(transit);
2033
2034    EINA_LIST_FOREACH(transit->objs, elist, obj)
2035      {
2036         if ((wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW && !reverse)
2037             || (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE && reverse))
2038           evas_object_show(obj);
2039         else evas_object_hide(obj);
2040         evas_object_map_enable_set(obj, EINA_FALSE);
2041      }
2042
2043    free(wipe);
2044 }
2045
2046 static void
2047 _transit_effect_wipe_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2048 {
2049    EINA_SAFETY_ON_NULL_RETURN(effect);
2050    EINA_SAFETY_ON_NULL_RETURN(transit);
2051    Elm_Transit_Effect_Wipe *wipe = effect;
2052    Evas_Map *map;
2053    Evas_Coord _x, _y, _w, _h;
2054    Eina_List *elist;
2055    Evas_Object *obj;
2056
2057    map = evas_map_new(4);
2058    if (!map) return;
2059
2060    EINA_LIST_FOREACH(transit->objs, elist, obj)
2061      {
2062         evas_object_geometry_get(obj, &_x, &_y, &_w, &_h);
2063
2064         if (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW)
2065           _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)progress);
2066         else
2067            _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)progress);
2068
2069         evas_object_map_enable_set(obj, EINA_TRUE);
2070         evas_object_map_set(obj, map);
2071      }
2072    evas_map_free(map);
2073 }
2074
2075 static Elm_Transit_Effect *
2076 _transit_effect_wipe_context_new(Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
2077 {
2078    Elm_Transit_Effect_Wipe *wipe;
2079
2080    wipe = ELM_NEW(Elm_Transit_Effect_Wipe);
2081    if (!wipe) return NULL;
2082
2083    wipe->type = type;
2084    wipe->dir = dir;
2085
2086    return wipe;
2087 }
2088
2089 /**
2090  * Add the Wipe Effect to Elm_Transit.
2091  *
2092  * @note This API is one of the facades. It creates wipe effect context
2093  * and add it's required APIs to elm_transit_effect_add.
2094  *
2095  * @see elm_transit_effect_add()
2096  *
2097  * @param transit Transit object.
2098  * @param type Wipe type. Hide or show.
2099  * @param dir Wipe Direction.
2100  * @return Wipe effect context data.
2101  *
2102  * @ingroup Transit
2103  * @warning Is higher recommended just create a transit with this effect when
2104  * the window that the objects of the transit belongs has already been created.
2105  * This is because this effect needs the geometry information about the objects,
2106  * and if the window was not created yet, it can get a wrong information.
2107  */
2108 EAPI void *
2109 elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
2110 {
2111    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2112    void *effect_context = _transit_effect_wipe_context_new(type, dir);
2113
2114    if (!effect_context) return NULL;
2115    elm_transit_effect_add(transit,
2116                           _transit_effect_wipe_op, effect_context,
2117                           _transit_effect_wipe_context_free);
2118    return effect_context;
2119 }
2120
2121
2122 ///////////////////////////////////////////////////////////////////////////////
2123 //Color Effect
2124 ///////////////////////////////////////////////////////////////////////////////
2125 typedef struct _Elm_Transit_Effect_Color Elm_Transit_Effect_Color;
2126
2127 struct _Elm_Transit_Effect_Color
2128 {
2129    struct _unsigned_color {
2130       unsigned int r, g, b, a;
2131    } from;
2132    struct _signed_color {
2133       int r, g, b, a;
2134    } to;
2135 };
2136
2137 static void
2138 _transit_effect_color_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2139 {
2140    Elm_Transit_Effect_Color *color = effect;
2141    free(color);
2142 }
2143
2144 static void
2145 _transit_effect_color_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2146 {
2147    EINA_SAFETY_ON_NULL_RETURN(effect);
2148    EINA_SAFETY_ON_NULL_RETURN(transit);
2149    Elm_Transit_Effect_Color *color = effect;
2150    Evas_Object *obj;
2151    Eina_List *elist;
2152    unsigned int r, g, b, a;
2153
2154    r = (color->from.r + (int)((float)color->to.r * progress));
2155    g = (color->from.g + (int)((float)color->to.g * progress));
2156    b = (color->from.b + (int)((float)color->to.b * progress));
2157    a = (color->from.a + (int)((float)color->to.a * progress));
2158
2159    EINA_LIST_FOREACH(transit->objs, elist, obj)
2160      evas_object_color_set(obj, r, g, b, a);
2161 }
2162
2163 static Elm_Transit_Effect *
2164 _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)
2165 {
2166    Elm_Transit_Effect_Color *color;
2167
2168    color = ELM_NEW(Elm_Transit_Effect_Color);
2169    if (!color) return NULL;
2170
2171    color->from.r = from_r;
2172    color->from.g = from_g;
2173    color->from.b = from_b;
2174    color->from.a = from_a;
2175    color->to.r = to_r - from_r;
2176    color->to.g = to_g - from_g;
2177    color->to.b = to_b - from_b;
2178    color->to.a = to_a - from_a;
2179
2180    return color;
2181 }
2182
2183 /**
2184  * Add the Color Effect to Elm_Transit.
2185  *
2186  * @note This API is one of the facades. It creates color effect context
2187  * and add it's required APIs to elm_transit_effect_add.
2188  *
2189  * @see elm_transit_effect_add()
2190  *
2191  * @param transit        Transit object.
2192  * @param  from_r        RGB R when effect begins.
2193  * @param  from_g        RGB G when effect begins.
2194  * @param  from_b        RGB B when effect begins.
2195  * @param  from_a        RGB A when effect begins.
2196  * @param  to_r          RGB R when effect ends.
2197  * @param  to_g          RGB G when effect ends.
2198  * @param  to_b          RGB B when effect ends.
2199  * @param  to_a          RGB A when effect ends.
2200  * @return               Color effect context data.
2201  *
2202  * @ingroup Transit
2203  */
2204 EAPI Elm_Transit_Effect *
2205 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)
2206 {
2207    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2208    Elm_Transit_Effect *effect_context = _transit_effect_color_context_new(from_r, from_g, from_b, from_a, to_r, to_g, to_b, to_a);
2209
2210    if (!effect_context) return NULL;
2211    elm_transit_effect_add(transit,
2212                           _transit_effect_color_op, effect_context,
2213                           _transit_effect_color_context_free);
2214    return effect_context;
2215 }
2216
2217 ///////////////////////////////////////////////////////////////////////////////
2218 //Fade Effect
2219 ///////////////////////////////////////////////////////////////////////////////
2220 typedef struct _Elm_Transit_Effect_Fade Elm_Transit_Effect_Fade;
2221 typedef struct _Elm_Transit_Effect_Fade_Node Elm_Transit_Effect_Fade_Node;
2222
2223 struct _Elm_Transit_Effect_Fade_Node
2224 {
2225    Evas_Object *before;
2226    Evas_Object *after;
2227    struct _signed_color before_color, after_color;
2228    int before_alpha;
2229    int after_alpha;
2230    Eina_Bool inversed : 1;
2231 };
2232
2233 struct _Elm_Transit_Effect_Fade
2234 {
2235    Eina_List *nodes;
2236 };
2237
2238 static void
2239 _fade_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2240 {
2241    Elm_Transit_Effect_Fade *fade = data;
2242    Eina_List *elist;
2243    Elm_Transit_Effect_Fade_Node *fade_node;
2244
2245    EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
2246      {
2247         if (fade_node->before == obj)
2248           evas_object_event_callback_del(fade_node->after,
2249                                          EVAS_CALLBACK_DEL, _fade_object_del_cb);
2250         else if (fade_node->after == obj)
2251           evas_object_event_callback_del(fade_node->before,
2252                                          EVAS_CALLBACK_DEL, _fade_object_del_cb);
2253         else continue;
2254
2255         fade->nodes = eina_list_remove_list(fade->nodes, elist);
2256         free(fade_node);
2257         break;
2258      }
2259 }
2260
2261 static Eina_List *
2262 _fade_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Fade *fade_data)
2263 {
2264    Elm_Transit_Effect_Fade_Node *fade;
2265    Eina_List *data_list = NULL;
2266    int i, count;
2267
2268    count = eina_list_count(transit->objs);
2269    for (i = 0; i < count; i += 2)
2270      {
2271         fade = ELM_NEW(Elm_Transit_Effect_Fade_Node);
2272         if (!fade)
2273           {
2274              eina_list_free(data_list);
2275              return NULL;
2276           }
2277
2278         fade->before = eina_list_nth(transit->objs, i);
2279         fade->after = eina_list_nth(transit->objs, i+1);
2280
2281         evas_object_color_get(fade->before,
2282                               &fade->before_color.r, &fade->before_color.g,
2283                               &fade->before_color.b, &fade->before_color.a);
2284         evas_object_color_get(fade->after,
2285                               &fade->after_color.r, &fade->after_color.g,
2286                               &fade->after_color.b, &fade->after_color.a);
2287
2288         fade->before_alpha = (255 - fade->before_color.a);
2289         fade->after_alpha = (255 - fade->after_color.a);
2290
2291         data_list = eina_list_append(data_list, fade);
2292
2293         evas_object_event_callback_add(fade->before,
2294                                        EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
2295         evas_object_event_callback_add(fade->after,
2296                                        EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
2297      }
2298    return data_list;
2299 }
2300
2301 static void
2302 _transit_effect_fade_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2303 {
2304    EINA_SAFETY_ON_NULL_RETURN(effect);
2305    Elm_Transit_Effect_Fade *fade = effect;
2306    Elm_Transit_Effect_Fade_Node *fade_node;
2307    Eina_List *elist, *elist_next;
2308
2309    EINA_LIST_FOREACH_SAFE(fade->nodes, elist, elist_next, fade_node)
2310      {
2311         evas_object_color_set(fade_node->before, fade_node->before_color.r,
2312                               fade_node->before_color.g,
2313                               fade_node->before_color.b,
2314                               fade_node->before_color.a);
2315         evas_object_color_set(fade_node->after, fade_node->after_color.r,
2316                               fade_node->after_color.g,
2317                               fade_node->after_color.b,
2318                               fade_node->after_color.a);
2319
2320         fade->nodes = eina_list_remove_list(fade->nodes, elist);
2321         evas_object_event_callback_del(fade_node->before,
2322                                        EVAS_CALLBACK_DEL, _fade_object_del_cb);
2323         evas_object_event_callback_del(fade_node->after,
2324                                        EVAS_CALLBACK_DEL, _fade_object_del_cb);
2325         free(fade_node);
2326      }
2327
2328    free(fade);
2329 }
2330
2331 static void
2332 _transit_effect_fade_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
2333 {
2334    EINA_SAFETY_ON_NULL_RETURN(effect);
2335    Elm_Transit_Effect_Fade *fade = effect;
2336    Eina_List *elist;
2337    Elm_Transit_Effect_Fade_Node *fade_node;
2338    float _progress;
2339
2340    if (!fade->nodes)
2341      fade->nodes = _fade_nodes_build(transit, fade);
2342
2343    EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
2344      {
2345         if (progress < 0.5)
2346           {
2347              if (!fade_node->inversed)
2348                {
2349                   evas_object_hide(fade_node->after);
2350                   evas_object_show(fade_node->before);
2351                   fade_node->inversed = EINA_TRUE;
2352                }
2353
2354              _progress = (1 - (progress * 2));
2355
2356              evas_object_color_set(fade_node->before,
2357                                    fade_node->before_color.r * _progress,
2358                                    fade_node->before_color.g * _progress,
2359                                    fade_node->before_color.b * _progress,
2360                                    fade_node->before_color.a +
2361                                    fade_node->before_alpha * (1 - _progress));
2362           }
2363         else
2364           {
2365              if (fade_node->inversed)
2366                {
2367                   evas_object_hide(fade_node->before);
2368                   evas_object_show(fade_node->after);
2369                   fade_node->inversed = EINA_FALSE;
2370                }
2371
2372              _progress = ((progress - 0.5) * 2);
2373
2374              evas_object_color_set(fade_node->after,
2375                                    fade_node->after_color.r * _progress,
2376                                    fade_node->after_color.g * _progress,
2377                                    fade_node->after_color.b * _progress,
2378                                    fade_node->after_color.a +
2379                                    fade_node->after_alpha * (1 - _progress));
2380           }
2381      }
2382 }
2383
2384 static Elm_Transit_Effect *
2385 _transit_effect_fade_context_new(void)
2386 {
2387    Elm_Transit_Effect_Fade *fade;
2388    fade = ELM_NEW(Elm_Transit_Effect_Fade);
2389    if (!fade) return NULL;
2390    return fade;
2391 }
2392
2393 /**
2394  * Add the Fade Effect to Elm_Transit.
2395  *
2396  * @note This API is one of the facades. It creates fade effect context
2397  * and add it's required APIs to elm_transit_effect_add.
2398  * @note This effect is applied to each pair of objects in the order they are listed
2399  * in the transit list of objects. The first object in the pair will be the
2400  * "before" object and the second will be the "after" object.
2401  *
2402  * @see elm_transit_effect_add()
2403  *
2404  * @param transit Transit object.
2405  * @return Fade effect context data.
2406  *
2407  * @ingroup Transit
2408  * @warning Is higher recommended just create a transit with this effect when
2409  * the window that the objects of the transit belongs has already been created.
2410  * This is because this effect needs the color information about the objects,
2411  * and if the window was not created yet, it can get a wrong information.
2412  */
2413 EAPI Elm_Transit_Effect *
2414 elm_transit_effect_fade_add(Elm_Transit *transit)
2415 {
2416    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2417
2418    Elm_Transit_Effect *effect_context = _transit_effect_fade_context_new();
2419    if (!effect_context) return NULL;
2420    elm_transit_effect_add(transit,
2421                           _transit_effect_fade_op, effect_context,
2422                           _transit_effect_fade_context_free);
2423    return effect_context;
2424 }
2425
2426
2427 ///////////////////////////////////////////////////////////////////////////////
2428 //Blend Effect
2429 ///////////////////////////////////////////////////////////////////////////////
2430 typedef struct _Elm_Transit_Effect_Blend Elm_Transit_Effect_Blend;
2431 typedef struct _Elm_Transit_Effect_Blend_Node Elm_Transit_Effect_Blend_Node;
2432
2433 struct _Elm_Transit_Effect_Blend_Node
2434 {
2435    Evas_Object *before;
2436    Evas_Object *after;
2437    struct _signed_color from, to;
2438 };
2439
2440 struct _Elm_Transit_Effect_Blend
2441 {
2442    Eina_List *nodes;
2443 };
2444
2445 static void
2446 _blend_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2447 {
2448    Elm_Transit_Effect_Blend *blend = data;
2449    Eina_List *elist;
2450    Elm_Transit_Effect_Blend_Node *blend_node;
2451
2452    EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
2453      {
2454         if (blend_node->after == obj)
2455           evas_object_event_callback_del(blend_node->before,
2456                                          EVAS_CALLBACK_DEL, _blend_object_del_cb);
2457         else if (blend_node->before == obj)
2458           evas_object_event_callback_del(blend_node->after,
2459                                          EVAS_CALLBACK_DEL, _blend_object_del_cb);
2460         else continue;
2461
2462         blend->nodes = eina_list_remove_list(blend->nodes, elist);
2463         free(blend_node);
2464         break;
2465      }
2466 }
2467
2468 static Eina_List *
2469 _blend_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Blend *blend)
2470 {
2471    Elm_Transit_Effect_Blend_Node *blend_node;
2472    Eina_List *data_list = NULL;
2473    int i, count;
2474
2475    count = eina_list_count(transit->objs);
2476    for (i = 0; i < (count - 1); i += 2)
2477      {
2478         blend_node = ELM_NEW(Elm_Transit_Effect_Blend_Node);
2479         if (!blend_node)
2480           {
2481              eina_list_free(data_list);
2482              return NULL;
2483           }
2484
2485         blend_node->before = eina_list_nth(transit->objs, i);
2486         blend_node->after = eina_list_nth(transit->objs, i + 1);
2487         evas_object_show(blend_node->before);
2488         evas_object_show(blend_node->after);
2489
2490         evas_object_color_get(blend_node->before, &blend_node->from.r,
2491                               &blend_node->from.g, &blend_node->from.b,
2492                               &blend_node->from.a);
2493         evas_object_color_get(blend_node->after, &blend_node->to.r,
2494                               &blend_node->to.g, &blend_node->to.b,
2495                               &blend_node->to.a);
2496
2497         data_list = eina_list_append(data_list, blend_node);
2498
2499         evas_object_event_callback_add(blend_node->before,
2500                                        EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
2501         evas_object_event_callback_add(blend_node->after,
2502                                        EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
2503      }
2504    return data_list;
2505 }
2506
2507 void
2508 _transit_effect_blend_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2509 {
2510    EINA_SAFETY_ON_NULL_RETURN(effect);
2511    Elm_Transit_Effect_Blend *blend = effect;
2512    Elm_Transit_Effect_Blend_Node *blend_node;
2513    Eina_List *elist, *elist_next;
2514
2515    EINA_LIST_FOREACH_SAFE(blend->nodes, elist, elist_next, blend_node)
2516      {
2517         evas_object_color_set(blend_node->before,
2518                               blend_node->from.r, blend_node->from.g,
2519                               blend_node->from.b, blend_node->from.a);
2520         evas_object_color_set(blend_node->after, blend_node->to.r,
2521                               blend_node->to.g, blend_node->to.b,
2522                               blend_node->to.a);
2523
2524         if (elm_transit_auto_reverse_get(transit))
2525           evas_object_hide(blend_node->after);
2526         else
2527           evas_object_hide(blend_node->before);
2528
2529         blend->nodes = eina_list_remove_list(blend->nodes, elist);
2530
2531         evas_object_event_callback_del(blend_node->before,
2532                                        EVAS_CALLBACK_DEL, _blend_object_del_cb);
2533         evas_object_event_callback_del(blend_node->after,
2534                                        EVAS_CALLBACK_DEL, _blend_object_del_cb);
2535         free(blend_node);
2536      }
2537    free(blend);
2538 }
2539
2540 void
2541 _transit_effect_blend_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2542 {
2543    EINA_SAFETY_ON_NULL_RETURN(effect);
2544    EINA_SAFETY_ON_NULL_RETURN(transit);
2545    Elm_Transit_Effect_Blend *blend = effect;
2546    Elm_Transit_Effect_Blend_Node *blend_node;
2547    Eina_List *elist;
2548
2549    if (!blend->nodes) blend->nodes = _blend_nodes_build(transit, blend);
2550
2551    EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
2552      {
2553         evas_object_color_set(blend_node->before,
2554                               (int)(blend_node->from.r * (1 - progress)),
2555                               (int)(blend_node->from.g * (1 - progress)),
2556                               (int)(blend_node->from.b * (1 - progress)),
2557                               (int)(blend_node->from.a * (1 - progress)));
2558         evas_object_color_set(blend_node->after,
2559                               (int)(blend_node->to.r * progress),
2560                               (int)(blend_node->to.g * progress),
2561                               (int)(blend_node->to.b * progress),
2562                               (int)(blend_node->to.a * progress));
2563      }
2564 }
2565
2566 static Elm_Transit_Effect *
2567 _transit_effect_blend_context_new(void)
2568 {
2569    Elm_Transit_Effect_Blend *blend;
2570
2571    blend = ELM_NEW(Elm_Transit_Effect_Blend);
2572    if (!blend) return NULL;
2573    return blend;
2574 }
2575
2576 /**
2577  * Add the Blend Effect to Elm_Transit.
2578  *
2579  * @note This API is one of the facades. It creates blend effect context
2580  * and add it's required APIs to elm_transit_effect_add.
2581  * @note This effect is applied to each pair of objects in the order they are listed
2582  * in the transit list of objects. The first object in the pair will be the
2583  * "before" object and the second will be the "after" object.
2584  *
2585  * @see elm_transit_effect_add()
2586  *
2587  * @param transit Transit object.
2588  * @return Blend effect context data.
2589  *
2590  * @ingroup Transit
2591  * @warning Is higher recommended just create a transit with this effect when
2592  * the window that the objects of the transit belongs has already been created.
2593  * This is because this effect needs the color information about the objects,
2594  * and if the window was not created yet, it can get a wrong information.
2595  */
2596 EAPI Elm_Transit_Effect *
2597 elm_transit_effect_blend_add(Elm_Transit *transit)
2598 {
2599    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2600    Elm_Transit_Effect *effect_context = _transit_effect_blend_context_new();
2601
2602    if (!effect_context) return NULL;
2603    elm_transit_effect_add(transit,
2604                           _transit_effect_blend_op, effect_context,
2605                           _transit_effect_blend_context_free);
2606    return effect_context;
2607 }
2608
2609
2610 ///////////////////////////////////////////////////////////////////////////////
2611 //Rotation Effect
2612 ///////////////////////////////////////////////////////////////////////////////
2613 typedef struct _Elm_Transit_Effect_Rotation Elm_Transit_Effect_Rotation;
2614
2615 struct _Elm_Transit_Effect_Rotation
2616 {
2617    float from, to;
2618 };
2619
2620 static void
2621 _transit_effect_rotation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2622 {
2623    Elm_Transit_Effect_Rotation *rotation = effect;
2624    free(rotation);
2625 }
2626
2627 static void
2628 _transit_effect_rotation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2629 {
2630    EINA_SAFETY_ON_NULL_RETURN(effect);
2631    EINA_SAFETY_ON_NULL_RETURN(transit);
2632    Elm_Transit_Effect_Rotation *rotation = effect;
2633    Evas_Map *map;
2634    Evas_Coord x, y, w, h;
2635    float degree;
2636    float half_w, half_h;
2637    Eina_List *elist;
2638    Evas_Object *obj;
2639
2640    map = evas_map_new(4);
2641    if (!map) return;
2642
2643    EINA_LIST_FOREACH(transit->objs, elist, obj)
2644      {
2645         evas_map_util_points_populate_from_object_full(map, obj, 0);
2646         degree = rotation->from + (float)(progress * rotation->to);
2647
2648         evas_object_geometry_get(obj, &x, &y, &w, &h);
2649
2650         half_w = (float)w * 0.5;
2651         half_h = (float)h * 0.5;
2652
2653         evas_map_util_3d_rotate(map, 0, 0, degree, x + half_w, y + half_h, 0);
2654         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
2655         evas_object_map_enable_set(obj, EINA_TRUE);
2656         evas_object_map_set(obj, map);
2657      }
2658    evas_map_free(map);
2659 }
2660
2661 static Elm_Transit_Effect *
2662 _transit_effect_rotation_context_new(float from_degree, float to_degree)
2663 {
2664    Elm_Transit_Effect_Rotation *rotation;
2665
2666    rotation = ELM_NEW(Elm_Transit_Effect_Rotation);
2667    if (!rotation) return NULL;
2668
2669    rotation->from = from_degree;
2670    rotation->to = to_degree - from_degree;
2671
2672    return rotation;
2673 }
2674
2675 /**
2676  * Add the Rotation Effect to Elm_Transit.
2677  *
2678  * @note This API is one of the facades. It creates rotation effect context
2679  * and add it's required APIs to elm_transit_effect_add.
2680  *
2681  * @see elm_transit_effect_add()
2682  *
2683  * @param transit Transit object.
2684  * @param from_degree Degree when effect begins.
2685  * @param to_degree Degree when effect is ends.
2686  * @return Rotation effect context data.
2687  *
2688  * @ingroup Transit
2689  * @warning Is higher recommended just create a transit with this effect when
2690  * the window that the objects of the transit belongs has already been created.
2691  * This is because this effect needs the geometry information about the objects,
2692  * and if the window was not created yet, it can get a wrong information.
2693  */
2694 EAPI Elm_Transit_Effect *
2695 elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree)
2696 {
2697    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2698    Elm_Transit_Effect *effect_context = _transit_effect_rotation_context_new(from_degree, to_degree);
2699
2700    if (!effect_context) return NULL;
2701    elm_transit_effect_add(transit,
2702                           _transit_effect_rotation_op, effect_context,
2703                           _transit_effect_rotation_context_free);
2704    return effect_context;
2705 }
2706
2707
2708 ///////////////////////////////////////////////////////////////////////////////
2709 //ImageAnimation Effect
2710 ///////////////////////////////////////////////////////////////////////////////
2711 typedef struct _Elm_Transit_Effect_Image_Animation Elm_Transit_Effect_Image_Animation;
2712
2713 struct _Elm_Transit_Effect_Image_Animation
2714 {
2715    Eina_List *images;
2716 };
2717
2718 static void
2719 _transit_effect_image_animation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2720 {
2721    EINA_SAFETY_ON_NULL_RETURN(effect);
2722    Elm_Transit_Effect_Image_Animation *image_animation = effect;
2723    const char *image;
2724    Eina_List *elist, *elist_next;
2725
2726    EINA_LIST_FOREACH_SAFE(image_animation->images, elist, elist_next, image)
2727      {
2728         image_animation->images =
2729            eina_list_remove_list(image_animation->images, elist);
2730         eina_stringshare_del(image);
2731      }
2732
2733    free(image_animation);
2734 }
2735
2736 static void
2737 _transit_effect_image_animation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2738 {
2739    EINA_SAFETY_ON_NULL_RETURN(effect);
2740    EINA_SAFETY_ON_NULL_RETURN(transit);
2741    Eina_List *elist;
2742    Evas_Object *obj;
2743    const char *type;
2744    Elm_Transit_Effect_Image_Animation *image_animation = effect;
2745    unsigned int count = 0;
2746    int len;
2747
2748    type = eina_stringshare_add("icon");
2749    len = eina_list_count(image_animation->images);
2750
2751    if (!len) count = floor(progress * len);
2752    else count = floor(progress * (len - 1));
2753
2754    EINA_LIST_FOREACH(transit->objs, elist, obj)
2755      {
2756         if (elm_widget_type_check(obj, type))
2757           elm_icon_file_set(obj,
2758                             eina_list_nth(image_animation->images, count), NULL);
2759      }
2760
2761    eina_stringshare_del(type);
2762 }
2763
2764 static Elm_Transit_Effect *
2765 _transit_effect_image_animation_context_new(Eina_List *images)
2766 {
2767    Elm_Transit_Effect_Image_Animation *image_animation;
2768    image_animation = ELM_NEW(Elm_Transit_Effect_Image_Animation);
2769
2770    if (!image_animation) return NULL;
2771    image_animation->images = images;
2772    return image_animation;
2773 }
2774
2775 /**
2776  * Add the ImageAnimation Effect to Elm_Transit.
2777  *
2778  * @note This API is one of the facades. It creates image animation effect context
2779  * and add it's required APIs to elm_transit_effect_add.
2780  * The @p images parameter is a list images paths. This list and
2781  * its contents will be deleted at the end of the effect by
2782  * elm_transit_effect_image_animation_context_free() function.
2783  *
2784  * Example:
2785  * @code
2786  * char buf[PATH_MAX];
2787  * Eina_List *images = NULL;
2788  * Elm_Transit *transi = elm_transit_add();
2789  *
2790  * snprintf(buf, sizeof(buf), "%s/images/icon_11.png", PACKAGE_DATA_DIR);
2791  * images = eina_list_append(images, eina_stringshare_add(buf));
2792  *
2793  * snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
2794  * images = eina_list_append(images, eina_stringshare_add(buf));
2795  * elm_transit_effect_image_animation_add(transi, images);
2796  *
2797  * @endcode
2798  *
2799  * @see elm_transit_effect_add()
2800  *
2801  * @param transit Transit object.
2802  * @param images Eina_List of images file paths. This list and
2803  * its contents will be deleted at the end of the effect by
2804  * elm_transit_effect_image_animation_context_free() function.
2805  * @return Image Animation effect context data.
2806  *
2807  * @ingroup Transit
2808  */
2809 EAPI Elm_Transit_Effect *
2810 elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images)
2811 {
2812    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2813    Elm_Transit_Effect *effect = _transit_effect_image_animation_context_new(images);
2814
2815    if (!effect) return NULL;
2816    elm_transit_effect_add(transit,
2817                           _transit_effect_image_animation_op, effect,
2818                           _transit_effect_image_animation_context_free);
2819    return effect;
2820 }