Merge "[genlist] Removed unnecessary variable. Upstream merge r60747."
[framework/uifw/elementary.git] / src / lib / elm_transit.c
index 3f2fde4..fa921d3 100644 (file)
 #include <Elementary.h>
+#include "elm_priv.h"
+
+#define ELM_TRANSIT_CHECK_OR_RETURN(transit, ...) \
+   do { \
+      if (!transit) { \
+         CRITICAL("Elm_Transit " # transit " is NULL!"); \
+         return __VA_ARGS__; \
+      } \
+      if (!EINA_MAGIC_CHECK(transit, ELM_TRANSIT_MAGIC)) { \
+         EINA_MAGIC_FAIL(transit, ELM_TRANSIT_MAGIC); \
+         return __VA_ARGS__; \
+      } \
+      if (transit->deleted){ \
+         ERR("Elm_Transit " # transit " has already been deleted!"); \
+         return __VA_ARGS__; \
+      } \
+   } while (0)
 
 /**
  *
  * @defgroup Transit Transit
  * @ingroup Elementary
  *
- * Transit is designed to set the various effects for the Evas_Object such like translation, 
- * rotation, etc. For using Effects, Create transit and insert the some of effects which are 
- * interested. Each effects has the type of Elm_Effect and those can be inserted into transit. 
- * Once effects are inserted into transit, transit will manage those effects.(ex) deleting). 
-*/
-struct _transit
-{
-   Evas_Object *parent;
-   Elm_Animator *animator;
-   Eina_List *effect_list;
-   Evas_Object *block_rect;
-   void (*completion_op) (void *data, Elm_Transit *transit);
-   void *completion_arg;
-   Eina_Bool reserved_del:1;
+ * Transit (see Warning below) is designed to set the various effects for the
+ * Evas_Object such like translation, rotation, etc. For using Effects, Create
+ * transit and insert effects which are interesting.
+ * Once effects are inserted into transit, transit will manage those effects.
+ * (ex deleting).
+ *
+ * Example:
+ * @code
+ * Elm_Transit *trans = elm_transit_add();
+ * elm_transit_object_add(trans, obj);
+ * void *effect_context = elm_transit_effect_translation_context_new(0.0, 0.0,
+ *                                                               280.0, 280.0);
+ * elm_transit_effect_add(transit,
+ *                        elm_transit_effect_translation_op, effect_context,
+ *                        elm_transit_effect_translation_context_free);
+ * elm_transit_duration_set(transit, 1);
+ * elm_transit_auto_reverse_set(transit, EINA_TRUE);
+ * elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
+ * elm_transit_repeat_times_set(transit, 3);
+ * @endcode
+ *
+ * @warning We strongly recomend to use elm_transit just when edje can not do
+ * the trick. Edje has more advantage than Elm_Transit, it has more flexibility and
+ * animations can be manipulated inside the theme.
+ */
+
+#define _TRANSIT_FOCAL 2000
+
+struct _Elm_Transit
+{
+#define ELM_TRANSIT_MAGIC 0xd27f190a
+   EINA_MAGIC;
+
+   Ecore_Animator *animator;
+   Eina_Inlist *effect_list;
+   Eina_List *objs;
+   Eina_Hash *objs_data_hash;
+   Elm_Transit *prev_chain_transit;
+   Eina_List *next_chain_transits;
+   Elm_Transit_Tween_Mode tween_mode;
+   struct {
+      Elm_Transit_Effect_End_Cb func;
+      void *arg;
+   } del_data;
+   struct {
+      double delayed;
+      double paused;
+      double duration;
+      double begin;
+      double current;
+   } time;
+   struct {
+      int count;
+      int current;
+      Eina_Bool reverse;
+   } repeat;
+   double progress;
+   unsigned int effects_pending_del;
+   int walking;
+   Eina_Bool auto_reverse : 1;
+   Eina_Bool event_enabled : 1;
+   Eina_Bool deleted : 1;
+   Eina_Bool state_keep : 1;
 };
 
-struct _effect
+struct _Elm_Transit_Effect_Module
 {
-   void (*animation_op) (void *data, Elm_Animator *animator, double frame);
-   void (*begin_op) (void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt);
-   void (*end_op) (void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt);
-   void (*del_op) (void* data);
-   unsigned int shared_cnt;
-   void *user_data;
+   EINA_INLIST;
+   Elm_Transit_Effect_Transition_Cb transition_cb;
+   Elm_Transit_Effect_End_Cb end_cb;
+   Elm_Transit_Effect *effect;
+   Eina_Bool deleted : 1;
 };
 
-static Evas_Object *_create_block_rect(Evas_Object *parent);
-static void _transit_animate_cb(void *data, Elm_Animator *animator, 
-                               double frame);
-static void _transit_fx_begin(Elm_Transit *transit);
-static void _transit_fx_end(Elm_Transit *transit);
-static void _transit_complete_cb(void *data);
-static void _transit_fx_del(Elm_Effect *effect);
-//static void _transit_parent_del(void *data); 
-
-/*
-static void
-_animator_parent_del(void *data)
+struct _Elm_Obj_State
 {
-       Elm_Transit *transit = data; 
-       elm_transit_del(data);
-}
-*/
+   Evas_Coord x, y, w, h;
+   int r,g,b,a;
+   Evas_Map *map;
+   Eina_Bool map_enabled : 1;
+   Eina_Bool visible : 1;
+};
 
-static Evas_Object *
-_create_block_rect(Evas_Object *parent)
+struct _Elm_Obj_Data
 {
-   Evas_Object *rect;
-
-   Evas_Coord w, h;
+   struct _Elm_Obj_State *state;
+   Eina_Bool pass_events : 1;
+};
 
-   rect = evas_object_rectangle_add(evas_object_evas_get(parent));
-   evas_output_size_get(evas_object_evas_get(parent), &w, &h);
-   evas_object_resize(rect, w, h);
-   evas_object_color_set(rect, 0, 0, 0, 0);
-   return rect;
-}
+typedef struct _Elm_Transit_Effect_Module Elm_Transit_Effect_Module;
+typedef struct _Elm_Obj_Data Elm_Obj_Data;
+typedef struct _Elm_Obj_State Elm_Obj_State;
 
 static void
-_transit_animate_cb(void *data, Elm_Animator *animator, double frame)
+_elm_transit_obj_states_save(Evas_Object *obj, Elm_Obj_Data *obj_data)
 {
-   Eina_List *elist;
+   Elm_Obj_State *state;
 
-   Elm_Effect *effect;
+   if (obj_data->state) return;
+   state = calloc(1, sizeof(Elm_Obj_State));
+   if (!state) return;
+   evas_object_geometry_get(obj, &state->x, &state->y, &state->w, &state->h);
+   evas_object_color_get(obj, &state->r, &state->g, &state->b, &state->a);
+   state->visible = evas_object_visible_get(obj);
+   state->map_enabled = evas_object_map_enable_get(obj);
+   if (evas_object_map_get(obj))
+     state->map = evas_map_dup(evas_object_map_get(obj));
+   obj_data->state = state;
+}
 
-   Elm_Transit *transit = data;
+static Eina_Bool
+_hash_foreach_pass_events_set(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
+{
+   Elm_Transit *transit = fdata;
+   evas_object_pass_events_set((Evas_Object*) key, transit->event_enabled);
+   return EINA_TRUE;
+}
 
-   EINA_LIST_FOREACH(transit->effect_list, elist, effect)
-   {
-      effect->animation_op(effect->user_data, animator, frame);
-   }
+static Eina_Bool
+_hash_foreach_obj_states_save(const Eina_Hash *hash __UNUSED__, const void *key, void *data, void *fdata __UNUSED__)
+{
+   _elm_transit_obj_states_save((Evas_Object *) key, (Elm_Obj_Data *) data);
+   return EINA_TRUE;
 }
 
 static void
-_transit_fx_begin(Elm_Transit *transit)
+_elm_transit_object_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Transit *transit;
+   Elm_Obj_Data *obj_data;
+   Eina_List *list;
+
+   transit = data;
+   list = eina_list_data_find_list(transit->objs, obj);
+   obj_data = eina_hash_find(transit->objs_data_hash, list);
+   if (!obj_data) return;
+   eina_hash_del_by_key(transit->objs_data_hash, list);
+   evas_object_pass_events_set(obj, obj_data->pass_events);
+   if (obj_data->state)
+     free(obj_data->state);
+   free(obj_data);
+   transit->objs = eina_list_remove(transit->objs, obj);
+   if (!transit->objs) elm_transit_del(transit);
+}
+
+//TODO: Remove!
+//Since evas map have a afterimage bug for this time.
+//This function is added temporary.
+static void
+_obj_damage_area_set(Evas_Object *obj)
 {
-   Eina_List *elist;
+   const Evas_Map *map;
+   Evas_Coord_Point coords;
+   Evas_Coord_Point min, max;
+   int i;
 
-   Elm_Effect *effect;
+   map  = evas_object_map_get(obj);
+   if (!map) return;
 
-   Eina_Bool auto_reverse;
+   evas_map_point_coord_get(map, 0, &coords.x, &coords.y, NULL);
+
+   max = min = coords;
+
+   for (i = 1; i < 4; ++i)
+     {
+        evas_map_point_coord_get(map, i, &coords.x, &coords.y, NULL);
 
-   unsigned int repeat_cnt;
+        if (coords.x < min.x)
+          min.x = coords.x;
+        else if (coords.x > max.x)
+          max.x = coords.x;
 
-   auto_reverse = elm_animator_auto_reverse_get(transit->animator);
-   repeat_cnt = elm_animator_repeat_get(transit->animator);
+        if (coords.y < min.y)
+          min.y = coords.y;
+        else if (coords.y > max.y)
+          max.y = coords.y;
+     }
 
-   EINA_LIST_FOREACH(transit->effect_list, elist, effect)
-   {
-      if (effect->begin_op)
-        effect->begin_op(effect->user_data, auto_reverse, repeat_cnt);
-   }
+   evas_damage_rectangle_add(evas_object_evas_get(obj),
+                             min.x, min.y,
+                             max.x - min.x, max.y - min.y);
 }
 
 static void
-_transit_fx_end(Elm_Transit *transit)
+_remove_obj_from_list(Elm_Transit *transit, Evas_Object *obj)
 {
-   Eina_List *elist;
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
+                                       _elm_transit_object_remove_cb,
+                                       transit);
 
-   Elm_Effect *effect;
+   //Remove duplicated objects
+   //TODO: Need to consider about optimizing here
+   while(1)
+     {
+        if (!eina_list_data_find_list(transit->objs, obj))
+          break;
+        transit->objs = eina_list_remove(transit->objs, obj);
+     }
+}
 
-   Eina_Bool auto_reverse;
+static void
+_elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
+{
+   Elm_Obj_Data *obj_data;
+   Elm_Obj_State *state;
+   Eina_List *list;
 
-   unsigned int repeat_cnt;
+   list = eina_list_data_find_list(transit->objs, obj);
+   obj_data = eina_hash_find(transit->objs_data_hash, list);
+   if (!obj_data)
+     {
+        _remove_obj_from_list(transit, obj);
+        return;
+     }
+   eina_hash_del_by_key(transit->objs_data_hash, list);
+   _remove_obj_from_list(transit, obj);
+   evas_object_pass_events_set(obj, obj_data->pass_events);
+   state = obj_data->state;
+   if (state)
+     {
+        //recover the states of the object.
+        if (!transit->state_keep)
+          {
+             evas_object_move(obj, state->x, state->y);
+             evas_object_resize(obj, state->w, state->h);
+             evas_object_color_set(obj, state->r, state->g, state->b, state->a);
+             if (state->visible) evas_object_show(obj);
+             else evas_object_hide(obj);
+             if (state->map_enabled)
+               evas_object_map_enable_set(obj, EINA_TRUE);
+             else
+               evas_object_map_enable_set(obj, EINA_FALSE);
+             if (state->map)
+               evas_object_map_set(obj, state->map);
+
+             //TODO: Remove!
+             //Since evas map have a afterimage bug for this time.
+             //This line is added temporary.
+             _obj_damage_area_set(obj);
+
+          }
+        free(state);
+     }
+   free(obj_data);
 
-   auto_reverse = elm_animator_auto_reverse_get(transit->animator);
-   repeat_cnt = elm_animator_repeat_get(transit->animator);
+}
 
-   EINA_LIST_FOREACH(transit->effect_list, elist, effect)
-   {
-      if (effect->end_op)
-        effect->end_op(effect->user_data, auto_reverse, repeat_cnt);
-   }
+static void
+_elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Module *effect_module)
+{
+   if (effect_module->end_cb)
+     effect_module->end_cb(effect_module->effect, transit);
+   free(effect_module);
 }
 
 static void
-_transit_complete_cb(void *data)
+_remove_dead_effects(Elm_Transit *transit)
 {
-   Elm_Transit *transit = (Elm_Transit *) data;
+   Elm_Transit_Effect_Module *effect_module;
 
-   evas_render(evas_object_evas_get(transit->parent));
+   EINA_INLIST_FOREACH(transit->effect_list, effect_module)
+     {
+        if (effect_module->deleted)
+          {
+             _elm_transit_effect_del(transit, effect_module);
+             transit->effects_pending_del--;
+             if (!transit->effects_pending_del) return;
+          }
+     }
+}
 
-   _transit_fx_end(transit);
+static void
+_elm_transit_del(Elm_Transit *transit)
+{
+   Elm_Transit_Effect_Module *effect_module;
+   Elm_Transit *chain_transit;
+   Eina_List *elist, *elist_next;
 
-   if (transit->block_rect)
-      evas_object_hide(transit->block_rect);
+   EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
+     {
+        if (transit->prev_chain_transit)
+          transit->prev_chain_transit->next_chain_transits = eina_list_remove(transit->prev_chain_transit->next_chain_transits, transit);
+        chain_transit->prev_chain_transit = NULL;
+     }
 
-   if (transit->completion_op)
-      transit->completion_op(transit->completion_arg, transit);
+   eina_list_free(transit->next_chain_transits);
 
-   if (transit->reserved_del)
+   if (transit->animator)
+     ecore_animator_del(transit->animator);
+
+   while (transit->effect_list)
      {
-       transit->reserved_del = EINA_FALSE;
-       elm_transit_del(transit);
+        effect_module = EINA_INLIST_CONTAINER_GET(transit->effect_list, Elm_Transit_Effect_Module);
+        transit->effect_list = eina_inlist_remove(transit->effect_list, transit->effect_list);
+        _elm_transit_effect_del(transit, effect_module);
      }
+
+   while (transit->objs)
+     _elm_transit_object_remove(transit, eina_list_data_get(transit->objs));
+
+   transit->deleted = EINA_TRUE;
+
+   if (transit->del_data.func)
+     transit->del_data.func(transit->del_data.arg, transit);
+
+   eina_hash_free(transit->objs_data_hash);
+
+   EINA_MAGIC_SET(transit, EINA_MAGIC_NONE);
+   free(transit);
 }
 
 static void
-_transit_fx_del(Elm_Effect *effect)
+_chain_transits_go(Elm_Transit *transit)
 {
-   if (!effect)
-      return;
+   Eina_List *elist, *elist_next;
+   Elm_Transit *chain_transit;
 
-   --effect->shared_cnt;
+   EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
+     elm_transit_go(chain_transit);
+}
 
-   if (effect->shared_cnt > 0)
-      return;
+static void
+_transit_animate_op(Elm_Transit *transit, double progress)
+{
+   Elm_Transit_Effect_Module *effect_module;
+
+   transit->walking++;
+   EINA_INLIST_FOREACH(transit->effect_list, effect_module)
+     {
+        if (transit->deleted) break;
+        if (!effect_module->deleted)
+          effect_module->transition_cb(effect_module->effect, transit, progress);
+     }
+   transit->walking--;
 
-   if(effect->del_op)
-          (*effect->del_op)(effect->user_data);
+   if (transit->walking) return;
 
-   if (effect->user_data)
-      free(effect->user_data);
-   free(effect);
+   if (transit->deleted) _elm_transit_del(transit);
+   else if (transit->effects_pending_del) _remove_dead_effects(transit);
 }
 
-/**
- * Set the event blocked when transit is operating.  
- *
- * @param transit Transit object
- * @param disabled Disable or enable
- *
- * @ingroup Transit 
- */
-EAPI void
-elm_transit_event_block_disabled_set(Elm_Transit *transit, Eina_Bool disabled)
+static Eina_Bool
+_animator_animate_cb(void *data)
 {
-   if (!transit)
-      return;
+   Elm_Transit *transit = data;
+   double elapsed_time, duration;
+
+   transit->time.current = ecore_loop_time_get();
+   elapsed_time = transit->time.current - transit->time.begin;
+   duration = transit->time.duration + transit->time.delayed;
 
-   if (disabled)
+   if (elapsed_time > duration)
+     elapsed_time = duration;
+
+   transit->progress = elapsed_time / duration;
+   switch (transit->tween_mode)
      {
-       if (transit->block_rect)
-         {
-            evas_object_del(transit->block_rect);
-            transit->block_rect = NULL;
-         }
+      case ELM_TRANSIT_TWEEN_MODE_ACCELERATE:
+        transit->progress = 1.0 - sin((ELM_PI / 2.0) + (transit->progress * ELM_PI / 2.0));
+        break;
+      case ELM_TRANSIT_TWEEN_MODE_DECELERATE:
+        transit->progress = sin(transit->progress * ELM_PI / 2.0);
+        break;
+      case ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL:
+        transit->progress = (1.0 - cos(transit->progress * ELM_PI)) / 2.0;
+        break;
+      default:
+        break;
      }
-   else
+
+   /* Reverse? */
+   if (transit->repeat.reverse) transit->progress = 1 - transit->progress;
+
+   if (transit->time.duration > 0) _transit_animate_op(transit, transit->progress);
+
+   /* Not end. Keep going. */
+   if (elapsed_time < duration) return ECORE_CALLBACK_RENEW;
+
+   /* Repeat and reverse and time done! */
+   if ((transit->repeat.count >= 0) &&
+       (transit->repeat.current == transit->repeat.count) &&
+       ((!transit->auto_reverse) || transit->repeat.reverse))
      {
-       if (transit->block_rect == NULL)
-          transit->block_rect = _create_block_rect(transit->parent);
+        /* run chain transit */
+        if (transit->next_chain_transits)
+          _chain_transits_go(transit);
+
+        elm_transit_del(transit);
+        return ECORE_CALLBACK_CANCEL;
      }
+
+   /* Repeat Case */
+   if (!transit->auto_reverse || transit->repeat.reverse)
+     {
+        transit->repeat.current++;
+        transit->repeat.reverse = EINA_FALSE;
+     }
+   else transit->repeat.reverse = EINA_TRUE;
+
+   transit->time.begin = ecore_loop_time_get();
+
+   return ECORE_CALLBACK_RENEW;
 }
 
 /**
- * Get the value of event blockd status.
+ * Add new transit.
+ *
+ * @note Is not necessary to delete the transit object, it will be deleted at
+ * the end of its operation.
+ * @note The transit will start playing when the program enter in the main loop, is not
+ * necessary to give a start to the transit.
  *
- * @param transit Transit
- * @return EINA_TRUE, when event block is disabled
+ * @param duration The duration of the transit in seconds. When transit starts
+ * to run, it will last a @p duration time.
+ * @return The transit object.
  *
- * @ingroup Transit 
+ * @ingroup Transit
  */
-EAPI Eina_Bool
-elm_transit_event_block_disabled_get(Elm_Transit *transit)
+EAPI Elm_Transit *
+elm_transit_add(void)
 {
-   if (!transit)
-      return EINA_FALSE;
-   return transit->block_rect ? EINA_TRUE : EINA_FALSE;
-}
+   Elm_Transit *transit = ELM_NEW(Elm_Transit);
+   if (!transit) return NULL;
+
+   EINA_MAGIC_SET(transit, ELM_TRANSIT_MAGIC);
+
+   elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
+
+   transit->objs_data_hash = eina_hash_int32_new(NULL);
 
+   return transit;
+}
 /**
- * Remove effect from transit.  
+ * Stops the animation and delete the @p transit object.
+ *
+ * Call this function if you wants to stop the animation before the duration
+ * time. Make sure the @p transit object is still alive with
+ * elm_transit_del_cb_set() function.
+ * All added effects will be deleted, calling its repective data_free_cb
+ * functions. The function setted by elm_transit_del_cb_set() will be called.
+ *
+ * @see elm_transit_del_cb_set()
  *
- * @param transit      Transit
- * @param effect Effect to be removed
- * @return EINA_TRUE, if the effect is removed
- * @warning If removed effect does not inserted in any transit, it will be deleted. 
+ * @param transit The transit object to be deleted.
  *
- * @ingroup Transit 
+ * @ingroup Transit
+ * @warning Just call this function if you are sure the transit is alive.
  */
-EAPI Eina_Bool
-elm_transit_fx_remove(Elm_Transit *transit, Elm_Effect *effect)
+EAPI void
+elm_transit_del(Elm_Transit *transit)
 {
-   Eina_List *elist;
-
-   Elm_Effect *_effect;
-
-   if (!transit)
-      return EINA_FALSE;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
 
-   EINA_LIST_FOREACH(transit->effect_list, elist, _effect)
-   {
-      if (_effect == effect)
-       {
-          transit->effect_list =
-             eina_list_remove(transit->effect_list, _effect);
-          _transit_fx_del(_effect);
-          return EINA_TRUE;
-       }
-   }
-   return EINA_FALSE;
+   if (transit->walking) transit->deleted = EINA_TRUE;
+   else _elm_transit_del(transit);
 }
 
 /**
- * Remove all current inserted effects. 
+ * Add a new effect to the transit.
  *
- * @param transit      Transit 
+ * @note The cb function and the data are the key to the effect. If you try to
+ * add an already added effect, nothing is done.
+ * @note After the first addition of an effect in @p transit, if its
+ * effect list become empty again, the @p transit will be killed by
+ * elm_transit_del(transit) function.
  *
- * @ingroup Transit 
+ * Exemple:
+ * @code
+ * Elm_Transit *transit = elm_transit_add();
+ * elm_transit_effect_add(transit,
+ *                        elm_transit_effect_blend_op,
+ *                        elm_transit_effect_blend_context_new(),
+ *                        elm_transit_effect_blend_context_free);
+ * @endcode
+ *
+ * @param transit The transit object.
+ * @param cb The operation function. It is called when the animation begins,
+ * it is the function that actually performs the animation. It is called with
+ * the @p data, @p transit and the time progression of the animation (a double
+ * value between 0.0 and 1.0).
+ * @param data The context data of the effect.
+ * @param data_free_cb The function to free the context data, it will be called
+ * at the end of the effect, it must finalize the animation and free the
+ * @p data.
+ *
+ * @ingroup Transit
+ * @warning The transit free the context data at the and of the transition with
+ * the data_free_cb function, do not use the context data in another transit.
  */
 EAPI void
-elm_transit_fx_clear(Elm_Transit *transit)
+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)
 {
-   Eina_List *elist;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   EINA_SAFETY_ON_NULL_RETURN(transition_cb);
+   Elm_Transit_Effect_Module *effect_module;
+
+   EINA_INLIST_FOREACH(transit->effect_list, effect_module)
+     if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect)) return;
 
-   Elm_Effect *effect;
+   effect_module = ELM_NEW(Elm_Transit_Effect_Module);
+   if (!effect_module) return;
 
-   if (!transit)
-      return;
+   effect_module->end_cb = end_cb;
+   effect_module->transition_cb = transition_cb;
+   effect_module->effect = effect;
 
-   EINA_LIST_FOREACH(transit->effect_list, elist, effect)
-   {
-      transit->effect_list = eina_list_remove(transit->effect_list, effect);
-      _transit_fx_del(effect);
-   }
+   transit->effect_list = eina_inlist_append(transit->effect_list, (Eina_Inlist*) effect_module);
 }
 
 /**
- * Get the list of current inseted effects. 
+ * Delete an added effect.
+ *
+ * This function will remove the effect from the @p transit, calling the
+ * data_free_cb to free the @p data.
  *
- * @param transit      Transit
- * @return Effect list 
+ * @see elm_transit_effect_add()
  *
- * @ingroup Transit 
+ * @note If the effect is not found, nothing is done.
+ * @note If the effect list become empty, this function will call
+ * elm_transit_del(transit), that is, it will kill the @p transit.
+ *
+ * @param transit The transit object.
+ * @param cb The operation function.
+ * @param data The context data of the effect.
+ *
+ * @ingroup Transit
  */
-EAPI const Eina_List *
-elm_transit_fx_get(Elm_Transit *transit)
+EAPI void
+elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect)
 {
-   if (!transit)
-      return NULL;
-   return transit->effect_list;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   EINA_SAFETY_ON_NULL_RETURN(transition_cb);
+   Elm_Transit_Effect_Module *effect_module;
+
+   EINA_INLIST_FOREACH(transit->effect_list, effect_module)
+     {
+        if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect))
+          {
+             if (transit->walking)
+               {
+                  effect_module->deleted = EINA_TRUE;
+                  transit->effects_pending_del++;
+               }
+             else
+               {
+                  _elm_transit_effect_del(transit, effect_module);
+                  if (!transit->effect_list) elm_transit_del(transit);
+               }
+             return;
+          }
+     }
 }
 
 /**
- * Set the user-callback function when the transit operation is done. 
+ * Add new object to apply the effects.
+ *
+ * @note After the first addition of an object in @p transit, if its
+ * object list become empty again, the @p transit will be killed by
+ * elm_transit_del(transit) function.
+ * @note If the @p obj belongs to another transit, the @p obj will be
+ * removed from it and it will only belong to the @p transit. If the old
+ * transit stays without objects, it will die.
+ * @note When you add an object into the @p transit, its state from
+ * evas_object_pass_events_get(obj) is saved, and it is applied when the
+ * transit ends, if you change this state whith evas_object_pass_events_set()
+ * after add the object, this state will change again when @p transit stops to
+ * run.
  *
- * @param transit      Transit
- * @param op Callback function pointer
- * @param data Callback funtion user data
+ * @param transit The transit object.
+ * @param obj Object to be animated.
  *
- * @ingroup Transit 
+ * @ingroup Transit
+ * @warning It is not allowed to add a new object after transit begins to go.
  */
 EAPI void
-elm_transit_completion_callback_set(Elm_Transit *transit,
-                                   void (*op) (void *data,
-                                               Elm_Transit *transit),
-                                   void *data)
+elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj)
 {
-   if (!transit)
-      return;
-   transit->completion_op = op;
-   transit->completion_arg = data;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   Elm_Obj_Data *obj_data;
+   Eina_List * list;
+
+//TODO: Check the remove case of the same objects in this transit. 
+   obj_data = ELM_NEW(Elm_Obj_Data);
+   obj_data->pass_events = evas_object_pass_events_get(obj);
+   if (!transit->event_enabled)
+     evas_object_pass_events_set(obj, EINA_TRUE);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                  _elm_transit_object_remove_cb,
+                                  transit);
+
+   transit->objs = eina_list_append(transit->objs, obj);
+   list = eina_list_last(transit->objs);
+   eina_hash_add(transit->objs_data_hash, list, obj_data);
+
+   if (!transit->state_keep)
+     _elm_transit_obj_states_save(obj, obj_data);
 }
 
 /**
- * Delete transit. 
+ * Removes an added object from the transit.
  *
- * @param transit      Transit to be deleted
+ * @note If the @p obj is not in the @p transit, nothing is done.
+ * @note If the list become empty, this function will call
+ * elm_transit_del(transit), that is, it will kill the @p transit.
  *
- * @ingroup Transit 
+ * @param transit The transit object.
+ * @param obj Object to be removed from @p transit.
+ *
+ * @ingroup Transit
+ * @warning It is not allowed to remove objects after transit begins to go.
  */
 EAPI void
-elm_transit_del(Elm_Transit *transit)
+elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
 {
-   if (!transit)
-      return;
-   if (elm_animator_operating_get(transit->animator))
-     {
-       transit->reserved_del = EINA_TRUE;
-       return;
-     }
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   EINA_SAFETY_ON_NULL_RETURN(obj);
 
-   if (transit->block_rect)
-      evas_object_del(transit->block_rect);
+   _elm_transit_object_remove(transit, obj);
+   if (!transit->objs) elm_transit_del(transit);
+}
 
-   elm_animator_del(transit->animator);
-   elm_transit_fx_clear(transit);
+/**
+ * Get the objects of the transit.
+ *
+ * @param transit The transit object.
+ * @return a Eina_List with the objects from the transit.
+ *
+ * @ingroup Transit
+ */
+EAPI const Eina_List *
+elm_transit_objects_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   return transit->objs;
+}
 
-//     if(transit->parent) 
-//     {
-//             evas_object_event_callback_del(transit->parent, EVAS_CALLBACK_DEL, _transit_parent_del);
-//     }
+/**
+ * Set the event enabled when transit is operating.
+ *
+ * If @p enabled is EINA_TRUE, the objects of the transit will receives
+ * events from mouse and keyboard during the animation.
+ * @note When you add an object with elm_transit_object_add(), its state from
+ * evas_object_pass_events_get(obj) is saved, and it is applied when the
+ * transit ends, if you change this state with evas_object_pass_events_set()
+ * after adding the object, this state will change again when @p transit stops
+ * to run.
+ *
+ * @param transit The transit object.
+ * @param enabled Disable or enable.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
 
-   free(transit);
+   if (transit->event_enabled == enabled) return;
+   transit->event_enabled = !!enabled;
+   eina_hash_foreach(transit->objs_data_hash, _hash_foreach_pass_events_set, transit);
 }
 
 /**
- * Set the transit animation acceleration style. 
+ * Get the value of event enabled status.
  *
- * @param transit      Transit
- * @param cs Curve style(Please refer elm_animator_curve_style_set)
+ * @see elm_transit_event_enabled_set()
  *
- * @ingroup Transit 
+ * @param transit The Transit object
+ * @return EINA_TRUE, when event is enabled. If @p transit is NULL
+ * EINA_FALSE is returned
+ *
+ * @ingroup Transit
  */
-EAPI void
-elm_transit_curve_style_set(Elm_Transit *transit, Elm_Animator_Curve_Style cs)
+EAPI Eina_Bool
+elm_transit_event_enabled_get(const Elm_Transit *transit)
 {
-   if (!transit)
-      return;
-   elm_animator_curve_style_set(transit->animator, cs);
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
+   return transit->event_enabled;
 }
 
 
 /**
- * Add new transit. 
+ * Set the event enabled when transit is operating.
  *
- * @param parent Parent object
- * @return transit 
+ * If @p disabled is EINA_TRUE, the objects of the transit will receives
+ * events from mouse and keyboard during the animation.
+ * @note When you add an object with elm_transit_object_add(), its state from
+ * evas_object_pass_events_get(obj) is saved, and it is applied when the
+ * transit ends, if you change this state with evas_object_pass_events_set()
+ * after add the object, this state will change again when @p transit stops to
+ * run.
  *
- * @ingroup Transit 
+ * @see elm_transit_event_enabled_set()
+ *
+ * @param transit The transit object.
+ * @param disabled Disable or enable.
+ *
+ * @ingroup Transit
  */
-EAPI Elm_Transit *
-elm_transit_add(Evas_Object *parent)
+EINA_DEPRECATED EAPI void
+elm_transit_event_block_set(Elm_Transit *transit, Eina_Bool disabled)
 {
-   Elm_Transit *transit = calloc(1, sizeof(Elm_Transit));
-
-   if (!transit)
-      return NULL;
+   elm_transit_event_enabled_set(transit, disabled);
+}
 
-   transit->animator = elm_animator_add(parent);
 
-   if (!transit->animator)
-     {
-       free(transit);
-       return NULL;
-     }
+/**
+ * Get the value of event block enabled  status.
+ *
+ * @see elm_transit_event_enabled_set(), elm_transit_event_enabled_get()
+ *
+ * @param transit The Transit object
+ * @return EINA_TRUE, when event is enabled. If @p transit is NULL
+ * EINA_FALSE is returned
+ *
+ * @ingroup Transit
+ */
+EINA_DEPRECATED EAPI Eina_Bool
+elm_transit_event_block_get(const Elm_Transit *transit)
+{
+   return !elm_transit_event_enabled_get(transit);
+}
 
-   transit->parent = parent;
-   elm_animator_operation_callback_set(transit->animator, _transit_animate_cb,
-                                      transit);
-   elm_animator_completion_callback_set(transit->animator, _transit_complete_cb,
-                                       transit);
-   elm_transit_event_block_disabled_set(transit, EINA_FALSE);
-/*
-       if(parent)
-       {
-               evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL, _transit_parent_del, 
-                                                        transit);
-       }
-*/
-   return transit;
+/**
+ * Set the user-callback function when the transit is deleted.
+ *
+ * @note Using this function twice will overwrite the first function setted.
+ * @note the @p transit object will be deleted after call @p cb function.
+ *
+ * @param transit The transit object.
+ * @param cb Callback function pointer. This function will be called before
+ * the deletion of the transit.
+ * @param data Callback funtion user data. It is the @p op parameter.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_del_cb_set(Elm_Transit *transit, void (*cb) (void *data, Elm_Transit *transit), void *data)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   transit->del_data.func = cb;
+   transit->del_data.arg = data;
 }
 
 /**
- * Set reverse effect automatically.  
+ * Set reverse effect automatically.
  *
- * @param transit Transit  
- * @param reverse EINA_TRUE is reverse.
+ * If auto reverse is setted, after running the effects with the progress
+ * parameter from 0 to 1, it will call the effecs again with the progress
+ * from 1 to 0. The transit will last for a time iqual to (2 * duration * repeat),
+ * where the duration was setted with the function elm_transit_add and
+ * the repeat with the function elm_transit_repeat_times_set().
  *
- * @ingroup Transit 
+ * @param transit The transit object.
+ * @param reverse EINA_TRUE means the auto_reverse is on.
+ *
+ * @ingroup Transit
  */
 EAPI void
 elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse)
 {
-   if (!transit)
-      return;
-   elm_animator_auto_reverse_set(transit->animator, reverse);
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   transit->auto_reverse = reverse;
 }
 
 /**
- * Insert an effect into the transit. 
+ * Get if the auto reverse is on.
  *
- * @param transit Transit
- * @param effect Effect to be inserted
- * @return EINA_TRUE is success
+ * @see elm_transit_auto_reverse_set()
  *
- * @ingroup Transit 
+ * @param transit The transit object.
+ * @return EINA_TRUE means auto reverse is on. If @p transit is NULL
+ * EINA_FALSE is returned
+ *
+ * @ingroup Transit
  */
 EAPI Eina_Bool
-elm_transit_fx_insert(Elm_Transit *transit, Elm_Effect *effect)
+elm_transit_auto_reverse_get(const Elm_Transit *transit)
 {
-   Eina_List *elist;
-
-   Elm_Effect *_effect;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
+   return transit->auto_reverse;
+}
 
-   if (!transit)
-      return EINA_FALSE;
+/**
+ * Set the transit repeat count. Effect will be repeated by repeat count.
+ *
+ * This function sets the number of repetition the transit will run after
+ * the first one, that is, if @p repeat is 1, the transit will run 2 times.
+ * If the @p repeat is a negative number, it will repeat infinite times.
+ *
+ * @note If this function is called during the transit execution, the transit
+ * will run @p repeat times, ignoring the times it already performed.
+ *
+ * @param transit The transit object
+ * @param repeat Repeat count
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_repeat_times_set(Elm_Transit *transit, int repeat)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   transit->repeat.count = repeat;
+   transit->repeat.current = 0;
+}
 
-   EINA_LIST_FOREACH(transit->effect_list, elist, _effect)
-   {
-      if (_effect == effect)
-        return EINA_FALSE;
-   }
+/**
+ * Get the transit repeat count.
+ *
+ * @see elm_transit_repeat_times_set()
+ *
+ * @param transit The Transit object.
+ * @return The repeat count. If @p transit is NULL
+ * 0 is returned
+ *
+ * @ingroup Transit
+ */
+EAPI int
+elm_transit_repeat_times_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
+   return transit->repeat.count;
+}
 
-   ++effect->shared_cnt;
-   transit->effect_list = eina_list_append(transit->effect_list, effect);
+/**
+ * Set the transit animation acceleration type.
+ *
+ * This function sets the tween mode of the transit that can be:
+ * ELM_TRANSIT_TWEEN_MODE_LINEAR - The default mode.
+ * ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL - Starts in accelerate mode and ends decelerating.
+ * ELM_TRANSIT_TWEEN_MODE_DECELERATE - The animation will be slowed over time.
+ * ELM_TRANSIT_TWEEN_MODE_ACCELERATE - The animation will accelerate over time.
+ *
+ * @param transit The transit object.
+ * @param tween_mode The tween type.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   transit->tween_mode = tween_mode;
+}
 
-   return EINA_TRUE;
+/**
+ * Get the transit animation acceleration type.
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ * @return The tween type. If @p transit is NULL
+ * ELM_TRANSIT_TWEEN_MODE_LINEAR is returned.
+ *
+ * @ingroup Transit
+ */
+EAPI Elm_Transit_Tween_Mode
+elm_transit_tween_mode_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
+   return transit->tween_mode;
 }
 
 /**
- * Set the transit repeat count. Effect will be repeated by repeat count.
+ * Set the transit animation time
+ *
+ * @note @p transit can not be NULL
  *
- * @param transit Transit 
- * @param repeat Repeat count 
+ * @param transit The transit object.
+ * @param duration The animation time.
  *
- * @ingroup Transit 
+ * @ingroup Transit
  */
 EAPI void
-elm_transit_repeat_set(Elm_Transit *transit, unsigned int repeat)
+elm_transit_duration_set(Elm_Transit *transit, double duration)
 {
-   if (!transit)
-      return;
-   elm_animator_repeat_set(transit->animator, repeat);
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   if (transit->animator) return;
+   transit->time.duration = duration;
 }
 
 /**
- * Stop the current transit, if the transit is operating. 
+ * Get the transit animation time
+ *
+ * @note @p transit can not be NULL
  *
- * @param transit Transit 
+ * @param transit The transit object.
  *
- * @ingroup Transit 
+ * @return The transit animation time.
+ *
+ * @ingroup Transit
  */
-EAPI void
-elm_transit_stop(Elm_Transit *transit)
+EAPI double
+elm_transit_duration_get(const Elm_Transit *transit)
 {
-   if (!transit)
-      return;
-   elm_animator_stop(transit->animator);
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, 0.0);
+   return transit->time.duration;
 }
 
 /**
- * Run the all the inserted effects.  
+ * Starts the transition.
+ * Once this API is called, the transit begins to measure the time.
+ *
+ * @note @p transit can not be NULL
  *
- * @param transit Transit
- * @param duration Transit time in seconds
+ * @param transit The transit object.
  *
- * @ingroup Transit 
+ * @ingroup Transit
  */
 EAPI void
-elm_transit_run(Elm_Transit *transit, double duration)
+elm_transit_go(Elm_Transit *transit)
 {
-   if (!transit)
-      return;
-   _transit_fx_begin(transit);
-   elm_animator_duration_set(transit->animator, duration);
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
 
-   //Block to Top
-   if (transit->block_rect)
-      evas_object_show(transit->block_rect);
+   if (transit->animator)
+     ecore_animator_del(transit->animator);
 
-   elm_animator_animate(transit->animator);
+   transit->time.paused = 0;
+   transit->time.delayed = 0;
+   transit->time.begin = ecore_loop_time_get();
+   transit->animator = ecore_animator_add(_animator_animate_cb, transit);
+}
 
-   //If failed to animate.  
-   if (!elm_animator_operating_get(transit->animator))
+/**
+ * Pause/Resume the transition.
+ * If you call elm_transit_go again, paused states will affect no anymore.
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+
+   if (!transit->animator) return;
+
+   if (paused)
+     {
+        if (transit->time.paused > 0)
+          return;
+        ecore_animator_freeze(transit->animator);
+        transit->time.paused = ecore_loop_time_get();
+     }
+   else
      {
-       if (transit->block_rect)
-          evas_object_hide(transit->block_rect);
-       _transit_fx_end(transit);
+        if (transit->time.paused == 0)
+          return;
+        ecore_animator_thaw(transit->animator);
+        transit->time.delayed += (ecore_loop_time_get() - transit->time.paused);
+        transit->time.paused = 0;
      }
 }
 
 /**
- * Pause the transit
+ * Get the value of paused status.
  *
- * @param  transit Transit
+ * @see elm_transit_paused_set()
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ * @return EINA_TRUE means transition is paused. If @p transit is NULL
+ * EINA_FALSE is returned
  *
  * @ingroup Transit
  */
-EAPI void
-elm_transit_pause(Elm_Transit *transit)
+EAPI Eina_Bool
+elm_transit_paused_get(const Elm_Transit *transit)
 {
-       if(!transit)
-               return;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
+
+   if (transit->time.paused == 0)
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
 
-       elm_animator_pause(transit->animator);
+/**
+ * Get the time progression of the animation (a double value between 0.0 and 1.0).
+ *
+ * @note @p transit can not be NULL
+ *
+ * @param transit The transit object.
+ *
+ * @return The time progression value. If @p transit is NULL
+ * 0 is returned
+ *
+ * @ingroup Transit
+ */
+EAPI double
+elm_transit_progress_value_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
+   return transit->progress;
 }
 
+
+
 /**
- * Resume the transit
+ * Enable/disable keeping up the objects states.
+ * If it is not kept, the objects states will be reset when transition ends.
+ *
+ * @note @p transit can not be NULL.
+ * @note One state includes geometry, color, map data.
  *
- * @param  transit Transit
+ * @param transit The transit object.
+ * @param state_keep Keeping or Non Keeping.
  *
  * @ingroup Transit
  */
 EAPI void
-elm_transit_resume(Elm_Transit *transit)
+elm_transit_objects_final_state_keep_set(Elm_Transit *transit, Eina_Bool state_keep)
 {
-       if(!transit)
-               return;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   if (transit->state_keep == state_keep) return;
+   if (transit->animator) return;
+   transit->state_keep = !!state_keep;
+   if (state_keep) return;
+   eina_hash_foreach(transit->objs_data_hash, _hash_foreach_obj_states_save, NULL);
+}
 
-       elm_animator_resume(transit->animator);
+/**
+ * Get a value whether the objects states will be reset or not.
+ *
+ * @note @p transit can not be NULL
+ *
+ * @see elm_transit_objects_final_state_keep_set()
+ *
+ * @param transit The transit object.
+ * @return EINA_TRUE means the states of the objects will be reset.
+ * If @p transit is NULL, EINA_FALSE is returned
+ *
+ * @ingroup Transit
+ */
+EAPI Eina_Bool
+elm_transit_objects_final_state_keep_get(const Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
+   return transit->state_keep;
 }
 
+/**
+ * Makes the chain relationship between two transits.
+ *
+ * @note @p transit can not be NULL. Transit would have multiple chain transits.
+ * @note @p chain_transit can not be NULL. Chain transits could be chained to the only one transit.
+ *
+ * @param transit The transit object.
+ * @param chain_transit The chain transit object. This transit will be operated  
+ *        after transit is done.
+ *
+ * @ingroup Transit
+ */
+EAPI void
+elm_transit_chain_transit_add(Elm_Transit *transit, Elm_Transit *chain_transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit);
+   ELM_TRANSIT_CHECK_OR_RETURN(chain_transit);
+
+   if (transit == chain_transit) return;
+   if (transit == chain_transit->prev_chain_transit) return;
 
+   if (chain_transit->prev_chain_transit)
+     chain_transit->prev_chain_transit->next_chain_transits = eina_list_remove(chain_transit->prev_chain_transit->next_chain_transits, chain_transit);
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Resizing FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _resizing Elm_Fx_Resizing;
-static void _elm_fx_resizing_op(void *data, Elm_Animator *animator, 
-                               double frame);
-static void _elm_fx_resizing_begin(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
+   chain_transit->prev_chain_transit = transit;
+   transit->next_chain_transits = eina_list_append(transit->next_chain_transits, chain_transit);
+}
 
-struct _resizing
+/**
+ * Get the current chain transit list.
+ *
+ * @note @p transit can not be NULL.
+ *
+ * @param transit The transit object.
+ * @return chain transit list.
+ *
+ * @ingroup Transit
+ */
+EAPI Eina_List *
+elm_transit_chain_transits_get(const Elm_Transit * transit)
 {
-   Evas_Object *obj;
-   struct _size
-   {
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   return transit->next_chain_transits;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//Resizing Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Resizing Elm_Transit_Effect_Resizing;
+
+struct _Elm_Transit_Effect_Resizing
+{
+   struct _size {
       Evas_Coord w, h;
    } from, to;
 };
 
 static void
-_elm_fx_resizing_begin(void *data, Eina_Bool auto_reverse,
-                      unsigned int repeat_cnt)
+_transit_effect_resizing_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
 {
-   Elm_Fx_Resizing *resizing = data;
-
-   evas_object_show(resizing->obj);
-   evas_object_resize(resizing->obj, resizing->from.w, resizing->from.h);
+   Elm_Transit_Effect_Resizing *resizing = effect;
+   free(resizing);
 }
 
 static void
-_elm_fx_resizing_op(void *data, Elm_Animator *animator, double frame)
+_transit_effect_resizing_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
 {
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
    Evas_Coord w, h;
+   Evas_Object *obj;
+   Eina_List *elist;
+   Elm_Transit_Effect_Resizing *resizing = effect;
 
-   Elm_Fx_Resizing *resizing = data;
+   w = resizing->from.w + (resizing->to.w * progress);
+   h = resizing->from.h + (resizing->to.h * progress);
 
-   w = resizing->from.w + (Evas_Coord) ((float)resizing->to.h * (float)frame);
-   h = resizing->from.h + (Evas_Coord) ((float)resizing->to.w * (float)frame);
-   evas_object_resize(resizing->obj, w, h);
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     evas_object_resize(obj, w, h);
 }
 
-/**
- * Add Resizing effect.  
- *
- * @param obj Evas_Object that effect is applying to
- * @param from_w Object width size when effect begins
- * @param from_h Object height size when effect begins
- * @param to_w Object width size when effect ends
- * @param to_h Object height size when effect ends
- * @return Resizing effect 
- *
- * @ingroup Transit 
- */
-EAPI Elm_Effect *
-elm_fx_resizing_add(Evas_Object *obj, Evas_Coord from_w, Evas_Coord from_h,
-                   Evas_Coord to_w, Evas_Coord to_h)
+static Elm_Transit_Effect *
+_transit_effect_resizing_context_new(Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
 {
-   Elm_Effect *effect;
-
-   Elm_Fx_Resizing *resizing;
-
-   if (!obj)
-      return NULL;
-
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
+   Elm_Transit_Effect_Resizing *resizing;
 
-   resizing = calloc(1, sizeof(Elm_Fx_Resizing));
-   if (!resizing)
-     {
-       free(effect);
-       return NULL;
-     }
+   resizing = ELM_NEW(Elm_Transit_Effect_Resizing);
+   if (!resizing) return NULL;
 
-   resizing->obj = obj;
    resizing->from.w = from_w;
    resizing->from.h = from_h;
    resizing->to.w = to_w - from_w;
    resizing->to.h = to_h - from_h;
 
-   effect->begin_op = _elm_fx_resizing_begin;
-   effect->animation_op = _elm_fx_resizing_op;
-   effect->user_data = resizing;
+   return resizing;
+}
+
+/**
+ * Add the Resizing Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates resizing effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param from_w Object width size when effect begins.
+ * @param from_h Object height size when effect begins.
+ * @param to_w Object width size when effect ends.
+ * @param to_h Object height size when effect ends.
+ * @return Resizing effect context data.
+ *
+ * @ingroup Transit
+ */
+EAPI Elm_Transit_Effect *
+elm_transit_effect_resizing_add(Elm_Transit *transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   Elm_Transit_Effect *effect = _transit_effect_resizing_context_new(from_w, from_h, to_w, to_h);
 
+   if (!effect) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_resizing_op, effect,
+                          _transit_effect_resizing_context_free);
    return effect;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Translation FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _translation Elm_Fx_Translation;
-static void _elm_fx_translation_op(void *data, Elm_Animator *animator, 
-                               double frame);
-static void _elm_fx_translation_begin(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_translation_end(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
+///////////////////////////////////////////////////////////////////////////////
+//Translation Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Translation Elm_Transit_Effect_Translation;
+typedef struct _Elm_Transit_Effect_Translation_Node Elm_Transit_Effect_Translation_Node;
 
-struct _translation
+struct _Elm_Transit_Effect_Translation_Node
 {
    Evas_Object *obj;
-   struct _point
-   {
-      Evas_Coord x, y;
+   Evas_Coord x, y;
+};
+
+struct _Elm_Transit_Effect_Translation
+{
+   struct _position_variation {
+      Evas_Coord dx, dy;
    } from, to;
+   Eina_List *nodes;
 };
 
 static void
-_elm_fx_translation_begin(void *data, Eina_Bool auto_reverse,
-                         unsigned int repeat_cnt)
+_translation_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
 {
-   Elm_Fx_Translation *translation = data;
+   Elm_Transit_Effect_Translation *translation = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_Translation_Node *translation_node;
 
-   evas_object_show(translation->obj);
-   evas_object_move(translation->obj, translation->from.x, translation->from.y);
+   EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
+     {
+        if (translation_node->obj != obj) continue;
+        translation->nodes = eina_list_remove_list(translation->nodes, elist);
+        free(translation_node);
+        break;
+     }
 }
 
-static void
-_elm_fx_translation_end(void *data, Eina_Bool auto_reverse,
-                       unsigned int repeat_cnt)
+static Eina_List *
+_translation_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Translation *translation)
 {
-   Elm_Fx_Translation *translation = data;
+   Elm_Transit_Effect_Translation_Node *translation_node;
+   const Eina_List *elist;
+   Evas_Object *obj;
+   Eina_List *data_list = NULL;
+   const Eina_List *objs = elm_transit_objects_get(transit);
 
-   evas_object_move(translation->obj, translation->from.x + translation->to.x,
-                   translation->from.y + translation->to.y);
+   EINA_LIST_FOREACH(objs, elist, obj)
+     {
+        translation_node = ELM_NEW(Elm_Transit_Effect_Translation_Node);
+        if (!translation_node)
+          {
+             eina_list_free(data_list);
+             return NULL;
+          }
+        translation_node->obj = obj;
+        evas_object_geometry_get(obj, &(translation_node->x),
+                                 &(translation_node->y), NULL, NULL);
+        data_list = eina_list_append(data_list, translation_node);
+        evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                       _translation_object_del_cb, translation);
+     }
+   return data_list;
 }
 
-static void
-_elm_fx_translation_op(void *data, Elm_Animator *animator, double frame)
+void
+_transit_effect_translation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
 {
-   Evas_Coord x, y;
-
-   Elm_Fx_Translation *translation = data;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   Elm_Transit_Effect_Translation *translation = effect;
+   Eina_List *elist, *elist_next;
+   Elm_Transit_Effect_Translation_Node *translation_node;
 
-   x = translation->from.x +
-      (Evas_Coord) ((float)translation->to.x * (float)frame);
-   y = translation->from.y +
-      (Evas_Coord) ((float)translation->to.y * (float)frame);
-   evas_object_move(translation->obj, x, y);
+   EINA_LIST_FOREACH_SAFE(translation->nodes,
+                          elist, elist_next, translation_node)
+     {
+        evas_object_event_callback_del(translation_node->obj,
+                                       EVAS_CALLBACK_DEL, _translation_object_del_cb);
+        translation->nodes = eina_list_remove_list(translation->nodes, elist);
+        free(translation_node);
+     }
+   free(translation);
 }
 
-/**
- * Add Translation effect.  
- *
- * @param obj Evas_Object that effect is applying to
- * @param from_x Position X when effect begins
- * @param from_y Position Y when effect begins
- * @param to_x Position X when effect ends
- * @param to_y Position Y when effect ends
- * @return Translation effect 
- *
- * @ingroup Transit 
- */
-EAPI Elm_Effect *
-elm_fx_translation_add(Evas_Object *obj, Evas_Coord from_x, Evas_Coord from_y,
-                      Evas_Coord to_x, Evas_Coord to_y)
+void
+_transit_effect_translation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress __UNUSED__)
 {
-   Elm_Effect *effect;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Evas_Coord x, y;
+   Elm_Transit_Effect_Translation *translation = effect;
+   Elm_Transit_Effect_Translation_Node *translation_node;
+   Eina_List *elist;
 
-   Elm_Fx_Translation *translation;
+   if (!translation->nodes)
+     translation->nodes = _translation_nodes_build(transit, translation);
 
-   if (!obj)
-      return NULL;
+   EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
+     {
+        x = translation_node->x + translation->from.dx
+           + (translation->to.dx * progress);
+        y = translation_node->y + translation->from.dy
+           + (translation->to.dy * progress);
+        evas_object_move(translation_node->obj, x, y);
+     }
+}
 
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
+static Elm_Transit_Effect *
+_transit_effect_translation_context_new(Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
+{
+   Elm_Transit_Effect_Translation *translation;
 
-   translation = calloc(1, sizeof(Elm_Fx_Translation));
+   translation = ELM_NEW(Elm_Transit_Effect_Translation);
+   if (!translation) return NULL;
 
-   if (!translation)
-     {
-       free(effect);
-       return NULL;
-     }
+   translation->from.dx = from_dx;
+   translation->from.dy = from_dy;
+   translation->to.dx = to_dx - from_dx;
+   translation->to.dy = to_dy - from_dy;
 
-   translation->obj = obj;
-   translation->from.x = from_x;
-   translation->from.y = from_y;
-   translation->to.x = to_x - from_x;
-   translation->to.y = to_y - from_y;
+   return translation;
+}
 
-   effect->begin_op = _elm_fx_translation_begin;
-   effect->end_op = _elm_fx_translation_end;
-   effect->animation_op = _elm_fx_translation_op;
-   effect->user_data = translation;
+/**
+ * Add the Translation Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates translation effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param from_dx X Position variation when effect begins.
+ * @param from_dy Y Position variation when effect begins.
+ * @param to_dx X Position variation when effect ends.
+ * @param to_dy Y Position variation when effect ends.
+ * @return Translation effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ */
+EAPI Elm_Transit_Effect *
+elm_transit_effect_translation_add(Elm_Transit *transit, Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   Elm_Transit_Effect *effect_context = _transit_effect_translation_context_new(from_dx, from_dy, to_dx, to_dy);
 
-   return effect;
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_translation_op, effect_context,
+                          _transit_effect_translation_context_free);
+   return effect_context;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Zoom FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _zoom Elm_Fx_Zoom;
-static void _elm_fx_zoom_op(void *data, Elm_Animator * animator, 
-                               double frame);
-static void _elm_fx_zoom_begin(void *data, Eina_Bool reverse, 
-                               unsigned int repeat);
-static void _elm_fx_zoom_end(void *data, Eina_Bool reverse, 
-                               unsigned int repeat);
 
-struct _zoom
+///////////////////////////////////////////////////////////////////////////////
+//Zoom Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Zoom Elm_Transit_Effect_Zoom;
+
+struct _Elm_Transit_Effect_Zoom
 {
-   Evas_Object *obj;
    float from, to;
 };
 
-static void
-_elm_fx_zoom_begin(void *data, Eina_Bool reverse, unsigned int repeat)
+void
+_transit_effect_zoom_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
 {
-   Elm_Fx_Zoom *zoom = data;
-
-   evas_object_show(zoom->obj);
-   _elm_fx_zoom_op(data, NULL, 0);
+   Elm_Transit_Effect_Zoom *zoom = effect;
+   free(zoom);
 }
 
 static void
-_elm_fx_zoom_end(void *data, Eina_Bool reverse, unsigned int repeat)
+_transit_effect_zoom_op(Elm_Transit_Effect *effect, Elm_Transit *transit , double progress)
 {
-   Elm_Fx_Zoom *zoom = data;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Evas_Object *obj;
+   Eina_List *elist;
+   Elm_Transit_Effect_Zoom *zoom = effect;
+   Evas_Map *map;
+   Evas_Coord x, y, w, h;
 
-   evas_object_map_enable_set(zoom->obj, EINA_FALSE);
+   map = evas_map_new(4);
+   if (!map) return;
+
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        evas_object_geometry_get(obj, &x, &y, &w, &h);
+        evas_map_util_points_populate_from_object_full(map, obj, zoom->from +
+                                                       (progress * zoom->to));
+        evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
+        evas_object_map_set(obj, map);
+        evas_object_map_enable_set(obj, EINA_TRUE);
+     }
+   evas_map_free(map);
 }
 
-static void
-_elm_fx_zoom_op(void *data, Elm_Animator *animator, double frame)
+static Elm_Transit_Effect *
+_transit_effect_zoom_context_new(float from_rate, float to_rate)
 {
-   Elm_Fx_Zoom *zoom;
+   Elm_Transit_Effect_Zoom *zoom;
 
-   Evas_Map *map;
+   zoom = ELM_NEW(Elm_Transit_Effect_Zoom);
+   if (!zoom) return NULL;
 
-   Evas_Coord x, y, w, h;
+   zoom->from = (_TRANSIT_FOCAL - (from_rate * _TRANSIT_FOCAL)) * (1 / from_rate);
+   zoom->to = ((_TRANSIT_FOCAL - (to_rate * _TRANSIT_FOCAL)) * (1 / to_rate)) - zoom->from;
 
-   map = evas_map_new(4);
-   if (!map)
-      return;
-
-   zoom = data;
-   evas_object_geometry_get(zoom->obj, &x, &y, &w, &h);
-   evas_map_smooth_set(map, EINA_TRUE);
-   evas_map_util_points_populate_from_object_full(map, zoom->obj,
-                                                 zoom->from +
-                                                 (frame * zoom->to));
-   evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, 10000);
-   evas_object_map_set(zoom->obj, map);
-   evas_object_map_enable_set(zoom->obj, EINA_TRUE);
-   evas_map_free(map);
+   return zoom;
 }
 
 /**
- * Add Zoom effect.  
+ * Add the Zoom Effect to Elm_Transit.
  *
- * @param obj Evas_Object that effect is applying to
- * @param from_rate Scale rate when effect begins (1 is current rate) 
- * @param to_rate Scale rate when effect ends
- * @return Zoom effect 
+ * @note This API is one of the facades. It creates zoom effect context
+ * and add it's required APIs to elm_transit_effect_add.
  *
- * @ingroup Transit 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param from_rate Scale rate when effect begins (1 is current rate).
+ * @param to_rate Scale rate when effect ends.
+ * @return Zoom effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
  */
-EAPI Elm_Effect *
-elm_fx_zoom_add(Evas_Object *obj, float from_rate, float to_rate)
+EAPI Elm_Transit_Effect *
+elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate)
 {
-   Elm_Effect *effect;
-
-   Elm_Fx_Zoom *zoom;
-
-   if (!obj)
-      return NULL;
-
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
-
-   zoom = calloc(1, sizeof(Elm_Fx_Zoom));
-   if (!zoom)
-     {
-       free(effect);
-       return NULL;
-     }
-
-   zoom->obj = obj;
-   zoom->from = (10000 - (from_rate * 10000)) * (1 / from_rate);
-   zoom->to = ((10000 - (to_rate * 10000)) * (1 / to_rate)) - zoom->from;
-   effect->begin_op = _elm_fx_zoom_begin;
-   effect->end_op = _elm_fx_zoom_end;
-   effect->animation_op = _elm_fx_zoom_op;
-   effect->user_data = zoom;
-
-   return effect;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   Elm_Transit_Effect *effect_context = _transit_effect_zoom_context_new(from_rate, to_rate);
 
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_zoom_op, effect_context,
+                          _transit_effect_zoom_context_free);
+   return effect_context;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Flip FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _flip Elm_Fx_Flip;
-static void _elm_fx_flip_op(void *data, Elm_Animator *animator, 
-                               double frame);
-static void _elm_fx_flip_end(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
 
-struct _flip
+///////////////////////////////////////////////////////////////////////////////
+//Flip Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Flip Elm_Transit_Effect_Flip;
+
+struct _Elm_Transit_Effect_Flip
 {
-   Evas_Object *front;
-   Evas_Object *back;
-   Elm_Fx_Flip_Axis axis;
-   Eina_Bool cw:1;
+   Elm_Transit_Effect_Flip_Axis axis;
+   Eina_Bool cw : 1;
 };
 
 static void
-_elm_fx_flip_end(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
+_transit_effect_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
 {
-   Elm_Fx_Flip *flip = data;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Flip *flip = effect;
+   Evas_Object *front, *back;
+   int i;
+   int count = eina_list_count(transit->objs);
 
-   evas_object_map_enable_set(flip->front, EINA_FALSE);
-   evas_object_map_enable_set(flip->back, EINA_FALSE);
+   for (i = 0; i < (count - 1); i += 2)
+     {
+        front = eina_list_nth(transit->objs, i);
+        back = eina_list_nth(transit->objs, i+1);
+        evas_object_map_enable_set(front, EINA_FALSE);
+        evas_object_map_enable_set(back, EINA_FALSE);
+     }
+   free(flip);
 }
 
 static void
-_elm_fx_flip_op(void *data, Elm_Animator *animator, double frame)
+_transit_effect_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
 {
-   Elm_Fx_Flip *flip;
-
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Evas_Object *obj, *front, *back;
+   int count, i;
+   Elm_Transit_Effect_Flip *flip = effect;
    Evas_Map *map;
-
    float degree;
-
-   Evas_Object *obj;
-
    Evas_Coord x, y, w, h;
 
    map = evas_map_new(4);
-   if (!map)
-      return;
+   if (!map) return;
 
-   flip = data;
+   if (flip->cw) degree = (float)(progress * 180);
+   else degree = (float)(progress * -180);
 
-   if (flip->cw)
-      degree = (float)(frame * 180);
-   else
-      degree = (float)(frame * -180);
+   count = eina_list_count(transit->objs);
 
-   if (degree < 90 && degree > -90)
+   for (i = 0; i < (count - 1); i += 2)
      {
-       obj = flip->front;
-       evas_object_hide(flip->back);
-       evas_object_show(flip->front);
+        Evas_Coord half_w, half_h;
+
+        front = eina_list_nth(transit->objs, i);
+        back = eina_list_nth(transit->objs, i+1);
+
+        if ((degree < 90) && (degree > -90))
+          {
+             obj = front;
+             if (front != back)
+               {
+                  evas_object_hide(back);
+                  evas_object_show(front);
+               }
+          }
+        else
+          {
+             obj = back;
+             if (front != back)
+               {
+                  evas_object_hide(front);
+                  evas_object_show(back);
+               }
+          }
+
+        evas_map_util_points_populate_from_object_full(map, obj, 0);
+        evas_object_geometry_get(obj, &x, &y, &w, &h);
+        half_w = (w / 2);
+        half_h = (h / 2);
+
+        if (flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
+          {
+             if ((degree >= 90) || (degree <= -90))
+               {
+                  evas_map_point_image_uv_set(map, 0, w, 0);
+                  evas_map_point_image_uv_set(map, 1, 0, 0);
+                  evas_map_point_image_uv_set(map, 2, 0, h);
+                  evas_map_point_image_uv_set(map, 3, w, h);
+               }
+             evas_map_util_3d_rotate(map, 0, degree,
+                                     0, x + half_w, y + half_h, 0);
+          }
+        else
+          {
+             if ((degree >= 90) || (degree <= -90))
+               {
+                  evas_map_point_image_uv_set(map, 0, 0, h);
+                  evas_map_point_image_uv_set(map, 1, w, h);
+                  evas_map_point_image_uv_set(map, 2, w, 0);
+                  evas_map_point_image_uv_set(map, 3, 0, 0);
+               }
+             evas_map_util_3d_rotate(map, degree,
+                                     0, 0, x + half_w, y + half_h, 0);
+          }
+        evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
+        evas_object_map_enable_set(front, EINA_TRUE);
+        evas_object_map_enable_set(back, EINA_TRUE);
+        evas_object_map_set(obj, map);
      }
-   else
-     {
-       obj = flip->back;
-       evas_object_hide(flip->front);
-       evas_object_show(flip->back);
-     }
-
-   evas_map_smooth_set(map, EINA_TRUE);
-   evas_map_util_points_populate_from_object_full(map, obj, 0);
-   evas_object_geometry_get(obj, &x, &y, &w, &h);
-   Evas_Coord half_w = (w / 2);
-
-   Evas_Coord half_h = (h / 2);
-
-   if (flip->axis == ELM_FX_FLIP_AXIS_Y)
-     {
-       if ((degree >= 90) || (degree <= -90))
-         {
-            evas_map_point_image_uv_set(map, 0, w, 0);
-            evas_map_point_image_uv_set(map, 1, 0, 0);
-            evas_map_point_image_uv_set(map, 2, 0, h);
-            evas_map_point_image_uv_set(map, 3, w, h);
-         }
-       evas_map_util_3d_rotate(map, 0, degree, 0, x + half_w, y + half_h, 0);
-     }
-   else
-     {
-       if ((degree >= 90) || (degree <= -90))
-         {
-            evas_map_point_image_uv_set(map, 0, 0, h);
-            evas_map_point_image_uv_set(map, 1, w, h);
-            evas_map_point_image_uv_set(map, 2, w, 0);
-            evas_map_point_image_uv_set(map, 3, 0, 0);
-         }
-       evas_map_util_3d_rotate(map, degree, 0, 0, x + half_w, y + half_h, 0);
-     }
-   evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, 10000);
-   evas_object_map_enable_set(flip->front, EINA_TRUE);
-   evas_object_map_enable_set(flip->back, EINA_TRUE);
-   evas_object_map_set(obj, map);
    evas_map_free(map);
 }
 
-/**
- * Add Flip effect.  
- *
- * @param front Front surface object 
- * @param back Back surface object
- * @param axis Flipping Axis(X or Y)
- * @param cw Flipping Direction. EINA_TRUE is clock-wise 
- * @return Flip effect 
- * 
- * @ingroup Transit 
- */
-EAPI Elm_Effect *
-elm_fx_flip_add(Evas_Object *front, Evas_Object *back, Elm_Fx_Flip_Axis axis,
-               Eina_Bool cw)
+static Elm_Transit_Effect *
+_transit_effect_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
 {
-   Elm_Effect *effect;
-
-   Elm_Fx_Flip *flip;
+   Elm_Transit_Effect_Flip *flip;
 
-   if ((!front) || (!back))
-      return NULL;
+   flip = ELM_NEW(Elm_Transit_Effect_Flip);
+   if (!flip) return NULL;
 
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
-
-   flip = calloc(1, sizeof(Elm_Fx_Flip));
-
-   if (!flip)
-     {
-       free(effect);
-       return NULL;
-     }
-
-   flip->front = front;
-   flip->back = back;
    flip->cw = cw;
    flip->axis = axis;
-   effect->end_op = _elm_fx_flip_end;
-   effect->animation_op = _elm_fx_flip_op;
-   effect->user_data = flip;
 
-   return effect;
+   return flip;
+}
+
+/**
+ * Add the Flip Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates flip effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ * @note This effect is applied to each pair of objects in the order they are listed
+ * in the transit list of objects. The first object in the pair will be the
+ * "front" object and the second will be the "back" object.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param axis Flipping Axis(X or Y).
+ * @param cw Flipping Direction. EINA_TRUE is clock-wise.
+ * @return Flip effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ */
+EAPI Elm_Transit_Effect *
+elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   Elm_Transit_Effect *effect_context = _transit_effect_flip_context_new(axis, cw);
+
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_flip_op, effect_context,
+                          _transit_effect_flip_context_free);
+   return effect_context;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//ResizableFlip FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _resizable_flip Elm_Fx_ResizableFlip;
-static void _elm_fx_resizable_flip_begin(void *data, Eina_Bool reverse, 
-                               unsigned int repeat);
-static void _elm_fx_resizable_flip_end(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_resizable_flip_op(void *data, Elm_Animator *animator,
-                                     double frame);
-static void _set_image_uv_by_axis_y(Evas_Map *map, Elm_Fx_ResizableFlip *flip, 
-                               float degree);
-static void _set_image_uv_by_axis_x(Evas_Map *map, Elm_Fx_ResizableFlip *flip, 
-                               float degree);
+///////////////////////////////////////////////////////////////////////////////
+//ResizableFlip Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Resizable_Flip Elm_Transit_Effect_ResizableFlip;
+typedef struct _Elm_Transit_Effect_Resizable_Flip_Node Elm_Transit_Effect_ResizableFlip_Node;
 
-struct _resizable_flip
+struct _Elm_Transit_Effect_Resizable_Flip_Node
 {
    Evas_Object *front;
    Evas_Object *back;
-   Elm_Fx_Flip_Axis axis;
-   struct _vector2d
-   {
+   struct _vector2d {
       float x, y;
    } from_pos, from_size, to_pos, to_size;
-   Eina_Bool cw:1;
+};
+
+struct _Elm_Transit_Effect_Resizable_Flip
+{
+   Eina_List *nodes;
+   Eina_Bool cw : 1;
+   Elm_Transit_Effect_Flip_Axis axis;
 };
 
 static void
-_elm_fx_resizable_flip_begin(void *data, Eina_Bool reverse, unsigned int repeat)
+_resizable_flip_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
 {
-   Elm_Fx_ResizableFlip *resizable_flip = data;
+   Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
 
-   evas_object_show(resizable_flip->front);
-   _elm_fx_resizable_flip_op(data, NULL, 0);
+   EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
+     {
+        if (resizable_flip_node->front == obj)
+          evas_object_event_callback_del(resizable_flip_node->back,
+                                         EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
+        else if (resizable_flip_node->back == obj)
+          evas_object_event_callback_del(resizable_flip_node->front,
+                                         EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
+        else continue;
+
+        resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
+                                                      elist);
+        free(resizable_flip_node);
+        break;
+     }
 }
 
-static void
-_elm_fx_resizable_flip_end(void *data, Eina_Bool auto_reverse,
-                          unsigned int repeat_cnt)
+static Eina_List *
+_resizable_flip_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_ResizableFlip *resizable_flip)
 {
-   Elm_Fx_ResizableFlip *resizable_flip = data;
+   Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
+   Eina_List *data_list = NULL;
+   Evas_Coord front_x, front_y, front_w, front_h;
+   Evas_Coord back_x, back_y, back_w, back_h;
+   int i, count;
+
+   count = eina_list_count(transit->objs);
+   for (i = 0; i < (count - 1); i += 2)
+     {
+        resizable_flip_node = ELM_NEW(Elm_Transit_Effect_ResizableFlip_Node);
+        if (!resizable_flip_node)
+          {
+             eina_list_free(data_list);
+             return NULL;
+          }
+
+        resizable_flip_node->front = eina_list_nth(transit->objs, i);
+        resizable_flip_node->back = eina_list_nth(transit->objs, i+1);
+
+        evas_object_geometry_get(resizable_flip_node->front,
+                                 &front_x, &front_y, &front_w, &front_h);
+        evas_object_geometry_get(resizable_flip_node->back,
+                                 &back_x, &back_y, &back_w, &back_h);
+
+        resizable_flip_node->from_pos.x = front_x;
+        resizable_flip_node->from_pos.y = front_y;
+        resizable_flip_node->to_pos.x = back_x - front_x;
+        resizable_flip_node->to_pos.y = back_y - front_y;
+
+        resizable_flip_node->from_size.x = front_w;
+        resizable_flip_node->from_size.y = front_h;
+        resizable_flip_node->to_size.x = back_w - front_w;
+        resizable_flip_node->to_size.y = back_h - front_h;
+
+        data_list = eina_list_append(data_list, resizable_flip_node);
+
+        evas_object_event_callback_add(resizable_flip_node->back,
+                                       EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
+        evas_object_event_callback_add(resizable_flip_node->front,
+                                       EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
+     }
 
-   evas_object_map_enable_set(resizable_flip->front, EINA_FALSE);
-   evas_object_map_enable_set(resizable_flip->back, EINA_FALSE);
+   return data_list;
 }
 
 static void
-_set_image_uv_by_axis_y(Evas_Map *map, Elm_Fx_ResizableFlip *flip,
-                       float degree)
+_set_image_uv_by_axis_y(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
 {
    if ((degree >= 90) || (degree <= -90))
      {
-       evas_map_point_image_uv_set(map, 0,
-                                   (flip->from_size.x * 2) + flip->to_size.x,
-                                   0);
-       evas_map_point_image_uv_set(map, 1, 0, 0);
-       evas_map_point_image_uv_set(map, 2, 0,
-                                   (flip->from_size.y * 2) + flip->to_size.y);
-       evas_map_point_image_uv_set(map, 3,
-                                   (flip->from_size.x * 2) + flip->to_size.x,
-                                   (flip->from_size.y * 2) + flip->to_size.y);
+        evas_map_point_image_uv_set(map, 0,
+                                    (flip->from_size.x * 2) + flip->to_size.x,
+                                    0);
+        evas_map_point_image_uv_set(map, 1, 0, 0);
+        evas_map_point_image_uv_set(map, 2, 0,
+                                    (flip->from_size.y * 2) + flip->to_size.y);
+        evas_map_point_image_uv_set(map, 3,
+                                    (flip->from_size.x * 2) + flip->to_size.x,
+                                    (flip->from_size.y * 2) + flip->to_size.y);
      }
    else
      {
-       evas_map_point_image_uv_set(map, 0, 0, 0);
-       evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
-       evas_map_point_image_uv_set(map, 2, flip->from_size.x,
-                                   flip->from_size.y);
-       evas_map_point_image_uv_set(map, 3, 0, flip->to_size.y);
+        evas_map_point_image_uv_set(map, 0, 0, 0);
+        evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
+        evas_map_point_image_uv_set(map, 2, flip->from_size.x,
+                                    flip->from_size.y);
+        evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
      }
 }
 
 static void
-_set_image_uv_by_axis_x(Evas_Map *map, Elm_Fx_ResizableFlip *flip,
-                       float degree)
+_set_image_uv_by_axis_x(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
 {
    if ((degree >= 90) || (degree <= -90))
      {
-       evas_map_point_image_uv_set(map, 0, 0,
-                                   (flip->from_size.y * 2) + flip->to_size.y);
-       evas_map_point_image_uv_set(map, 1,
-                                   (flip->from_size.x * 2) + flip->to_size.x,
-                                   (flip->from_size.y * 2) + flip->to_size.y);
-       evas_map_point_image_uv_set(map, 2,
-                                   (flip->from_size.x * 2) + flip->to_size.x,
-                                   0);
-       evas_map_point_image_uv_set(map, 3, 0, 0);
+        evas_map_point_image_uv_set(map, 0, 0,
+                                    (flip->from_size.y * 2) + flip->to_size.y);
+        evas_map_point_image_uv_set(map, 1,
+                                    (flip->from_size.x * 2) + flip->to_size.x,
+                                    (flip->from_size.y * 2) + flip->to_size.y);
+        evas_map_point_image_uv_set(map, 2,
+                                    (flip->from_size.x * 2) + flip->to_size.x,
+                                    0);
+        evas_map_point_image_uv_set(map, 3, 0, 0);
      }
    else
      {
-       evas_map_point_image_uv_set(map, 0, 0, 0);
-       evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
-       evas_map_point_image_uv_set(map, 2, flip->from_size.x,
-                                   flip->from_size.y);
-       evas_map_point_image_uv_set(map, 3, 0, flip->to_size.y);
+        evas_map_point_image_uv_set(map, 0, 0, 0);
+        evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
+        evas_map_point_image_uv_set(map, 2, flip->from_size.x,
+                                    flip->from_size.y);
+        evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
      }
 }
 
-static void
-_elm_fx_resizable_flip_op(void *data, Elm_Animator *animator, double frame)
+void
+_transit_effect_resizable_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
 {
-   Elm_Fx_ResizableFlip *resizable_flip;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
 
-   Evas_Map *map;
+   Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
+   Eina_List *elist, *elist_next;
+   Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
 
-   float degree;
+   EINA_LIST_FOREACH_SAFE(resizable_flip->nodes,
+                          elist, elist_next, resizable_flip_node)
+     {
+        evas_object_map_enable_set(resizable_flip_node->front, EINA_FALSE);
+        evas_object_map_enable_set(resizable_flip_node->back, EINA_FALSE);
 
-   Evas_Object *obj;
+        resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
+                                                      elist);
 
-   float x, y, w, h;
+        evas_object_event_callback_del(resizable_flip_node->back,
+                                       EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
+        evas_object_event_callback_del(resizable_flip_node->front,
+                                       EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
+        free(resizable_flip_node);
+     }
+   free(resizable_flip);
+}
 
+void
+_transit_effect_resizable_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   Evas_Map *map;
+   Evas_Object *obj;
+   float x, y, w, h;
+   float degree;
    Evas_Coord half_w, half_h;
+   Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
+   Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
+   Eina_List *elist;
 
    map = evas_map_new(4);
-   if (!map)
-      return;
+   if (!map) return;
 
-   resizable_flip = data;
+   if (resizable_flip->cw) degree = (float)(progress * 180);
+   else degree = (float)(progress * -180);
 
-   if (resizable_flip->cw)
-      degree = (float)(frame * 180);
-   else
-      degree = (float)(frame * -180);
+   if (!resizable_flip->nodes)
+     resizable_flip->nodes = _resizable_flip_nodes_build(transit,
+                                                         resizable_flip);
 
-   if ((degree < 90) && (degree > -90))
-     {
-       obj = resizable_flip->front;
-       evas_object_hide(resizable_flip->back);
-       evas_object_show(resizable_flip->front);
-     }
-   else
+   EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
      {
-       obj = resizable_flip->back;
-       evas_object_hide(resizable_flip->front);
-       evas_object_show(resizable_flip->back);
+        if ((degree < 90) && (degree > -90))
+          {
+             obj = resizable_flip_node->front;
+             if (resizable_flip_node->front != resizable_flip_node->back)
+               {
+                  evas_object_hide(resizable_flip_node->back);
+                  evas_object_show(resizable_flip_node->front);
+               }
+          }
+        else
+          {
+             obj = resizable_flip_node->back;
+             if (resizable_flip_node->front != resizable_flip_node->back)
+               {
+                  evas_object_hide(resizable_flip_node->front);
+                  evas_object_show(resizable_flip_node->back);
+               }
+          }
+
+        x = resizable_flip_node->from_pos.x +
+           (resizable_flip_node->to_pos.x * progress);
+        y = resizable_flip_node->from_pos.y +
+           (resizable_flip_node->to_pos.y * progress);
+        w = resizable_flip_node->from_size.x +
+           (resizable_flip_node->to_size.x * progress);
+        h = resizable_flip_node->from_size.y +
+           (resizable_flip_node->to_size.y * progress);
+        evas_map_point_coord_set(map, 0, x, y, 0);
+        evas_map_point_coord_set(map, 1, x + w, y, 0);
+        evas_map_point_coord_set(map, 2, x + w, y + h, 0);
+        evas_map_point_coord_set(map, 3, x, y + h, 0);
+
+        half_w = (Evas_Coord)(w / 2);
+        half_h = (Evas_Coord)(h / 2);
+
+        if (resizable_flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
+          {
+             _set_image_uv_by_axis_y(map, resizable_flip_node, degree);
+             evas_map_util_3d_rotate(map, 0, degree,
+                                     0, x + half_w, y + half_h, 0);
+          }
+        else
+          {
+             _set_image_uv_by_axis_x(map, resizable_flip_node, degree);
+             evas_map_util_3d_rotate(map, degree, 0,
+                                     0, x + half_w, y + half_h, 0);
+          }
+
+        evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
+        evas_object_map_enable_set(resizable_flip_node->front, EINA_TRUE);
+        evas_object_map_enable_set(resizable_flip_node->back, EINA_TRUE);
+        evas_object_map_set(obj, map);
      }
+   evas_map_free(map);
+}
 
-   evas_map_smooth_set(map, EINA_TRUE);
-
-   x = resizable_flip->from_pos.x + (resizable_flip->to_pos.x * frame);
-   y = resizable_flip->from_pos.y + (resizable_flip->to_pos.y * frame);
-   w = resizable_flip->from_size.x + (resizable_flip->to_size.x * frame);
-   h = resizable_flip->from_size.y + (resizable_flip->to_size.y * frame);
-   evas_map_point_coord_set(map, 0, x, y, 0);
-   evas_map_point_coord_set(map, 1, x + w, y, 0);
-   evas_map_point_coord_set(map, 2, x + w, y + h, 0);
-   evas_map_point_coord_set(map, 3, x, y + h, 0);
+static Elm_Transit_Effect *
+_transit_effect_resizable_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
+{
+   Elm_Transit_Effect_ResizableFlip *resizable_flip;
 
-   half_w = (Evas_Coord) (w / 2);
-   half_h = (Evas_Coord) (h / 2);
+   resizable_flip = ELM_NEW(Elm_Transit_Effect_ResizableFlip);
+   if (!resizable_flip) return NULL;
 
-   if (resizable_flip->axis == ELM_FX_FLIP_AXIS_Y)
-     {
-       _set_image_uv_by_axis_y(map, resizable_flip, degree);
-       evas_map_util_3d_rotate(map, 0, degree, 0, x + half_w, y + half_h, 0);
-     }
-   else
-     {
-       _set_image_uv_by_axis_x(map, resizable_flip, degree);
-       evas_map_util_3d_rotate(map, degree, 0, 0, x + half_w, y + half_h, 0);
-     }
+   resizable_flip->cw = cw;
+   resizable_flip->axis = axis;
 
-   evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, 10000);
-   evas_object_map_enable_set(resizable_flip->front, EINA_TRUE);
-   evas_object_map_enable_set(resizable_flip->back, EINA_TRUE);
-   evas_object_map_set(obj, map);
-   evas_map_free(map);
+   return resizable_flip;
 }
 
 /**
- * Add ResizbleFlip effect. the size of each surface objects are interpolated automatically.
+ * Add the Resizable Flip Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates resizable flip effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ * @note This effect is applied to each pair of objects in the order they are listed
+ * in the transit list of objects. The first object in the pair will be the
+ * "front" object and the second will be the "back" object.
+ *
+ * @see elm_transit_effect_add()
  *
- * @param front Front surface object 
- * @param back Back surface object
- * @param axis Flipping Axis.(X or Y)  
- * @param cw Flipping Direction. EINA_TRUE is clock-wise
- * @return Flip effect 
+ * @param transit Transit object.
+ * @param axis Flipping Axis(X or Y).
+ * @param cw Flipping Direction. EINA_TRUE is clock-wise.
+ * @return Resizable flip effect context data.
  *
- * @ingroup Transit 
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
  */
-EAPI Elm_Effect *
-elm_fx_resizable_flip_add(Evas_Object *front, Evas_Object *back,
-                         Elm_Fx_Flip_Axis axis, Eina_Bool cw)
+EAPI Elm_Transit_Effect *
+elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
 {
-   Elm_Fx_ResizableFlip *resizable_flip;
-
-   Elm_Effect *effect;
-
-   Evas_Coord front_x, front_y, front_w, front_h;
-
-   Evas_Coord back_x, back_y, back_w, back_h;
-
-   if (!front || !back)
-      return NULL;
-
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
-
-   resizable_flip = calloc(1, sizeof(Elm_Fx_ResizableFlip));
-
-   if (!resizable_flip)
-     {
-       free(effect);
-       return NULL;
-     }
-
-   resizable_flip->front = front;
-   resizable_flip->back = back;
-   resizable_flip->cw = cw;
-   resizable_flip->axis = axis;
-
-   evas_object_geometry_get(resizable_flip->front, &front_x, &front_y, &front_w,
-                           &front_h);
-   evas_object_geometry_get(resizable_flip->back, &back_x, &back_y, &back_w,
-                           &back_h);
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   Elm_Transit_Effect *effect_context = _transit_effect_resizable_flip_context_new(axis, cw);
 
-   resizable_flip->from_pos.x = front_x;
-   resizable_flip->from_pos.y = front_y;
-   resizable_flip->to_pos.x = back_x - front_x;
-   resizable_flip->to_pos.y = back_y - front_y;
-
-   resizable_flip->from_size.x = front_w;
-   resizable_flip->from_size.y = front_h;
-   resizable_flip->to_size.x = back_w - front_w;
-   resizable_flip->to_size.y = back_h - front_h;
-
-   effect->begin_op = _elm_fx_resizable_flip_begin;
-   effect->end_op = _elm_fx_resizable_flip_end;
-   effect->animation_op = _elm_fx_resizable_flip_op;
-   effect->user_data = resizable_flip;
-
-   return effect;
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_resizable_flip_op, effect_context,
+                          _transit_effect_resizable_flip_context_free);
+   return effect_context;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Wipe FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _wipe Elm_Fx_Wipe;
-static void _elm_fx_wipe_op(void *data, Elm_Animator *animator, 
-                               double frame);
-static void _elm_fx_wipe_begin(void *data, Eina_Bool auto_repeat, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_wipe_end(void *data, Eina_Bool auto_repeat, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_wipe_hide(Evas_Map * map, Elm_Fx_Wipe_Dir dir, 
-                               float x, float y, float w, float h, float frame);
-static void _elm_fx_wipe_show(Evas_Map *map, Elm_Fx_Wipe_Dir dir, 
-                               float x, float y, float w, float h, float frame);
 
-struct _wipe
-{
-   Evas_Object *obj;
-   Elm_Fx_Wipe_Type type;
-   Elm_Fx_Wipe_Dir dir;
-};
+///////////////////////////////////////////////////////////////////////////////
+//Wipe Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Wipe Elm_Transit_Effect_Wipe;
 
-static void
-_elm_fx_wipe_begin(void *data, Eina_Bool auto_repeat, unsigned int repeat_cnt)
+struct _Elm_Transit_Effect_Wipe
 {
-   Elm_Fx_Wipe *wipe = data;
-
-   evas_object_show(wipe->obj);
-   _elm_fx_wipe_op(data, NULL, 0);
-}
+   Elm_Transit_Effect_Wipe_Type type;
+   Elm_Transit_Effect_Wipe_Dir dir;
+};
 
 static void
-_elm_fx_wipe_end(void *data, Eina_Bool auto_repeat, unsigned int repeat_cnt)
+_elm_fx_wipe_hide(Evas_Map * map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
 {
-   Elm_Fx_Wipe *wipe = data;
+   float w2, h2;
 
-   evas_object_map_enable_set(wipe->obj, EINA_FALSE);
+   switch (dir)
+     {
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
+         w2 = w - (w * progress);
+         h2 = (y + h);
+         evas_map_point_image_uv_set(map, 0, 0, 0);
+         evas_map_point_image_uv_set(map, 1, w2, 0);
+         evas_map_point_image_uv_set(map, 2, w2, h);
+         evas_map_point_image_uv_set(map, 3, 0, h);
+         evas_map_point_coord_set(map, 0, x, y, 0);
+         evas_map_point_coord_set(map, 1, x + w2, y, 0);
+         evas_map_point_coord_set(map, 2, x + w2, h2, 0);
+         evas_map_point_coord_set(map, 3, x, h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
+         w2 = (w * progress);
+         h2 = (y + h);
+         evas_map_point_image_uv_set(map, 0, w2, 0);
+         evas_map_point_image_uv_set(map, 1, w, 0);
+         evas_map_point_image_uv_set(map, 2, w, h);
+         evas_map_point_image_uv_set(map, 3, w2, h);
+         evas_map_point_coord_set(map, 0, x + w2, y, 0);
+         evas_map_point_coord_set(map, 1, x + w, y, 0);
+         evas_map_point_coord_set(map, 2, x + w, h2, 0);
+         evas_map_point_coord_set(map, 3, x + w2, h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
+         w2 = (x + w);
+         h2 = h - (h * progress);
+         evas_map_point_image_uv_set(map, 0, 0, 0);
+         evas_map_point_image_uv_set(map, 1, w, 0);
+         evas_map_point_image_uv_set(map, 2, w, h2);
+         evas_map_point_image_uv_set(map, 3, 0, h2);
+         evas_map_point_coord_set(map, 0, x, y, 0);
+         evas_map_point_coord_set(map, 1, w2, y, 0);
+         evas_map_point_coord_set(map, 2, w2, y+h2, 0);
+         evas_map_point_coord_set(map, 3, x, y+h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
+         w2 = (x + w);
+         h2 = (h * progress);
+         evas_map_point_image_uv_set(map, 0, 0, h2);
+         evas_map_point_image_uv_set(map, 1, w, h2);
+         evas_map_point_image_uv_set(map, 2, w, h);
+         evas_map_point_image_uv_set(map, 3, 0, h);
+         evas_map_point_coord_set(map, 0, x, y + h2, 0);
+         evas_map_point_coord_set(map, 1, w2, y + h2, 0);
+         evas_map_point_coord_set(map, 2, w2, y + h, 0);
+         evas_map_point_coord_set(map, 3, x, y + h, 0);
+         break;
+      default:
+         break;
+     }
+   evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
 }
 
 static void
-_elm_fx_wipe_hide(Evas_Map * map, Elm_Fx_Wipe_Dir dir, float x, float y,
-                 float w, float h, float frame)
+_elm_fx_wipe_show(Evas_Map *map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
 {
    float w2, h2;
 
    switch (dir)
      {
-   case ELM_FX_WIPE_DIR_UP:
-       w2 = (x + w);
-       h2 = h - (h * frame);
-       evas_map_point_image_uv_set(map, 0, 0, 0);
-       evas_map_point_image_uv_set(map, 1, w, 0);
-       evas_map_point_image_uv_set(map, 2, w, h2);
-       evas_map_point_image_uv_set(map, 3, 0, h2);
-       evas_map_point_coord_set(map, 0, x, y, 0);
-       evas_map_point_coord_set(map, 1, w2, y, 0);
-       evas_map_point_coord_set(map, 2, w2, h2, 0);
-       evas_map_point_coord_set(map, 3, x, h2, 0);
-       break;
-     case ELM_FX_WIPE_DIR_LEFT:
-       w2 = w - (w * frame);
-       h2 = (y + h);
-       evas_map_point_image_uv_set(map, 0, 0, 0);
-       evas_map_point_image_uv_set(map, 1, w2, 0);
-       evas_map_point_image_uv_set(map, 2, w2, h);
-       evas_map_point_image_uv_set(map, 3, 0, h);
-       evas_map_point_coord_set(map, 0, x, y, 0);
-       evas_map_point_coord_set(map, 1, x + w2, y, 0);
-       evas_map_point_coord_set(map, 2, x + w2, h2, 0);
-       evas_map_point_coord_set(map, 3, x, h2, 0);
-       break;
-     case ELM_FX_WIPE_DIR_RIGHT:
-       w2 = (w * frame);
-       h2 = (y + h);
-       evas_map_point_image_uv_set(map, 0, w2, 0);
-       evas_map_point_image_uv_set(map, 1, w, 0);
-       evas_map_point_image_uv_set(map, 2, w, h);
-       evas_map_point_image_uv_set(map, 3, w2, h);
-       evas_map_point_coord_set(map, 0, x + w2, y, 0);
-       evas_map_point_coord_set(map, 1, x + w, y, 0);
-       evas_map_point_coord_set(map, 2, x + w, h2, 0);
-       evas_map_point_coord_set(map, 3, x + w2, h2, 0);
-       break;
-     case ELM_FX_WIPE_DIR_DOWN:
-       w2 = (x + w);
-       h2 = (h * frame);
-       evas_map_point_image_uv_set(map, 0, 0, h2);
-       evas_map_point_image_uv_set(map, 1, w, h2);
-       evas_map_point_image_uv_set(map, 2, w, h);
-       evas_map_point_image_uv_set(map, 3, 0, h);
-       evas_map_point_coord_set(map, 0, x, y + h2, 0);
-       evas_map_point_coord_set(map, 1, w2, y + h2, 0);
-       evas_map_point_coord_set(map, 2, w2, y + h, 0);
-       evas_map_point_coord_set(map, 3, x, y + h, 0);
-       break;
-     default:
-       break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
+         w2 = (w - (w * progress));
+         h2 = (y + h);
+         evas_map_point_image_uv_set(map, 0, w2, 0);
+         evas_map_point_image_uv_set(map, 1, w, 0);
+         evas_map_point_image_uv_set(map, 2, w, h);
+         evas_map_point_image_uv_set(map, 3, w2, h);
+         evas_map_point_coord_set(map, 0, x + w2, y, 0);
+         evas_map_point_coord_set(map, 1, w, y, 0);
+         evas_map_point_coord_set(map, 2, w, h2, 0);
+         evas_map_point_coord_set(map, 3, x + w2, h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
+         w2 = (w * progress);
+         h2 = (y + h);
+         evas_map_point_image_uv_set(map, 0, 0, 0);
+         evas_map_point_image_uv_set(map, 1, w2, 0);
+         evas_map_point_image_uv_set(map, 2, w2, h);
+         evas_map_point_image_uv_set(map, 3, 0, h);
+         evas_map_point_coord_set(map, 0, x, y, 0);
+         evas_map_point_coord_set(map, 1, x + w2, y, 0);
+         evas_map_point_coord_set(map, 2, x + w2, h2, 0);
+         evas_map_point_coord_set(map, 3, x, h2, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
+         w2 = (x + w);
+         h2 = (h - (h * progress));
+         evas_map_point_image_uv_set(map, 0, 0, h2);
+         evas_map_point_image_uv_set(map, 1, w, h2);
+         evas_map_point_image_uv_set(map, 2, w, h);
+         evas_map_point_image_uv_set(map, 3, 0, h);
+         evas_map_point_coord_set(map, 0, x, y + h2, 0);
+         evas_map_point_coord_set(map, 1, w2, y + h2, 0);
+         evas_map_point_coord_set(map, 2, w2, y + h, 0);
+         evas_map_point_coord_set(map, 3, x, y + h, 0);
+         break;
+      case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
+         w2 = (x + w);
+         h2 = (h * progress);
+         evas_map_point_image_uv_set(map, 0, 0, 0);
+         evas_map_point_image_uv_set(map, 1, w, 0);
+         evas_map_point_image_uv_set(map, 2, w, h2);
+         evas_map_point_image_uv_set(map, 3, 0, h2);
+         evas_map_point_coord_set(map, 0, x, y, 0);
+         evas_map_point_coord_set(map, 1, w2, y, 0);
+         evas_map_point_coord_set(map, 2, w2, y + h2, 0);
+         evas_map_point_coord_set(map, 3, x, y + h2, 0);
+         break;
+      default:
+         break;
      }
-
-   evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, 10000);
+   evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
 }
 
 static void
-_elm_fx_wipe_show(Evas_Map *map, Elm_Fx_Wipe_Dir dir, float x, float y,
-                 float w, float h, float frame)
+_transit_effect_wipe_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
 {
-   float w2, h2;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Eina_List *elist;
+   Evas_Object *obj;
+   Elm_Transit_Effect_Wipe *wipe = effect;
+   Eina_Bool reverse = elm_transit_auto_reverse_get(transit);
 
-   switch (dir)
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
      {
-         case ELM_FX_WIPE_DIR_UP:
-       w2 = (x + w);
-       h2 = (h - (h * frame));
-       evas_map_point_image_uv_set(map, 0, 0, h2);
-       evas_map_point_image_uv_set(map, 1, w, h2);
-       evas_map_point_image_uv_set(map, 2, w, h);
-       evas_map_point_image_uv_set(map, 3, 0, h);
-       evas_map_point_coord_set(map, 0, x, y + h2, 0);
-       evas_map_point_coord_set(map, 1, w2, y + h2, 0);
-       evas_map_point_coord_set(map, 2, w2, y + h, 0);
-       evas_map_point_coord_set(map, 3, x, y + h, 0);
-       break;
-     case ELM_FX_WIPE_DIR_LEFT:
-       w2 = (w - (w * frame));
-       h2 = (y + h);
-       evas_map_point_image_uv_set(map, 0, w2, 0);
-       evas_map_point_image_uv_set(map, 1, w, 0);
-       evas_map_point_image_uv_set(map, 2, w, h);
-       evas_map_point_image_uv_set(map, 3, w2, h);
-       evas_map_point_coord_set(map, 0, x + w2, y, 0);
-       evas_map_point_coord_set(map, 1, x + w, y, 0);
-       evas_map_point_coord_set(map, 2, x +w, h2, 0);
-       evas_map_point_coord_set(map, 3, x + w2, h2, 0);
-       break;
-     case ELM_FX_WIPE_DIR_RIGHT:
-       w2 = (w * frame);
-       h2 = (y + h);
-       evas_map_point_image_uv_set(map, 0, 0, 0);
-       evas_map_point_image_uv_set(map, 1, w2, 0);
-       evas_map_point_image_uv_set(map, 2, w2, h);
-       evas_map_point_image_uv_set(map, 3, 0, h);
-       evas_map_point_coord_set(map, 0, x, y, 0);
-       evas_map_point_coord_set(map, 1, x + w2, y, 0);
-       evas_map_point_coord_set(map, 2, x + w2, h2, 0);
-       evas_map_point_coord_set(map, 3, x, h2, 0);
-       break;
-     case ELM_FX_WIPE_DIR_DOWN:
-       w2 = (x + w);
-       h2 = (h * frame);
-       evas_map_point_image_uv_set(map, 0, 0, 0);
-       evas_map_point_image_uv_set(map, 1, w, 0);
-       evas_map_point_image_uv_set(map, 2, w, h2);
-       evas_map_point_image_uv_set(map, 3, 0, h2);
-       evas_map_point_coord_set(map, 0, x, y, 0);
-       evas_map_point_coord_set(map, 1, w2, y, 0);
-       evas_map_point_coord_set(map, 2, w2, y + h2, 0);
-       evas_map_point_coord_set(map, 3, x, y + h2, 0);
-       break;
-     default:
-       break;
+        if ((wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW && !reverse)
+            || (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE && reverse))
+          evas_object_show(obj);
+        else evas_object_hide(obj);
+        evas_object_map_enable_set(obj, EINA_FALSE);
      }
 
-   evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, 10000);
+   free(wipe);
 }
 
 static void
-_elm_fx_wipe_op(void *data, Elm_Animator *animator, double frame)
+_transit_effect_wipe_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
 {
-   Elm_Fx_Wipe *wipe;
-
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Wipe *wipe = effect;
    Evas_Map *map;
-
    Evas_Coord _x, _y, _w, _h;
+   Eina_List *elist;
+   Evas_Object *obj;
 
    map = evas_map_new(4);
-   if (!map)
-      return;
+   if (!map) return;
 
-   wipe = data;
-   evas_map_smooth_set(map, EINA_TRUE);
-   evas_object_geometry_get(wipe->obj, &_x, &_y, &_w, &_h);
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        evas_object_geometry_get(obj, &_x, &_y, &_w, &_h);
 
-   if (wipe->type == ELM_FX_WIPE_TYPE_SHOW)
-      _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)frame);
-   else
-      _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)frame);
+        if (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW)
+          _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)progress);
+        else
+          _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)progress);
 
-   evas_object_map_enable_set(wipe->obj, EINA_TRUE);
-   evas_object_map_set(wipe->obj, map);
+        evas_object_map_enable_set(obj, EINA_TRUE);
+        evas_object_map_set(obj, map);
+     }
    evas_map_free(map);
 }
 
-/**
- * Add Wipe effect.  
- *
- * @param obj Evas_Object that effect is applying to
- * @param type Wipe type. Hide or show
- * @param dir Wipe Direction
- * @return Wipe effect
- *
- * @ingroup Transit 
- */
-EAPI Elm_Effect *
-elm_fx_wipe_add(Evas_Object *obj, Elm_Fx_Wipe_Type type, Elm_Fx_Wipe_Dir dir)
+static Elm_Transit_Effect *
+_transit_effect_wipe_context_new(Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
 {
-   Elm_Effect *effect;
-
-   Elm_Fx_Wipe *wipe;
+   Elm_Transit_Effect_Wipe *wipe;
 
-   if (!obj)
-      return NULL;
+   wipe = ELM_NEW(Elm_Transit_Effect_Wipe);
+   if (!wipe) return NULL;
 
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
-
-   wipe = calloc(1, sizeof(Elm_Fx_Wipe));
-   if (!wipe)
-     {
-       free(effect);
-       return NULL;
-     }
-
-   wipe->obj = obj;
    wipe->type = type;
    wipe->dir = dir;
-   effect->begin_op = _elm_fx_wipe_begin;
-   effect->end_op = _elm_fx_wipe_end;
-   effect->animation_op = _elm_fx_wipe_op;
-   effect->user_data = wipe;
 
-   return effect;
+   return wipe;
+}
+
+/**
+ * Add the Wipe Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates wipe effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param type Wipe type. Hide or show.
+ * @param dir Wipe Direction.
+ * @return Wipe effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ */
+EAPI void *
+elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   void *effect_context = _transit_effect_wipe_context_new(type, dir);
+
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_wipe_op, effect_context,
+                          _transit_effect_wipe_context_free);
+   return effect_context;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Color FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _color Elm_Fx_Color;
-static void _elm_fx_color_begin(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt);
-static void _elm_fx_color_op(void *data, Elm_Animator *animator, double frame);
 
-struct _color
+///////////////////////////////////////////////////////////////////////////////
+//Color Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Color Elm_Transit_Effect_Color;
+
+struct _Elm_Transit_Effect_Color
 {
-   Evas_Object *obj;
-   struct _unsigned_color
-   {
+   struct _unsigned_color {
       unsigned int r, g, b, a;
    } from;
-   struct _signed_color
-   {
+   struct _signed_color {
       int r, g, b, a;
    } to;
 };
 
 static void
-_elm_fx_color_begin(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
+_transit_effect_color_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
 {
-   Elm_Fx_Color *color = data;
-
-   evas_object_show(color->obj);
+   Elm_Transit_Effect_Color *color = effect;
+   free(color);
 }
 
 static void
-_elm_fx_color_op(void *data, Elm_Animator *animator, double frame)
+_transit_effect_color_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
 {
-   Elm_Fx_Color *color;
-
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Color *color = effect;
+   Evas_Object *obj;
+   Eina_List *elist;
    unsigned int r, g, b, a;
 
-   color = data;
-   r = (color->from.r + (int)((float)color->to.r * frame));
-   g = (color->from.g + (int)((float)color->to.g * frame));
-   b = (color->from.b + (int)((float)color->to.b * frame));
-   a = (color->from.a + (int)((float)color->to.a * frame));
+   r = (color->from.r + (int)((float)color->to.r * progress));
+   g = (color->from.g + (int)((float)color->to.g * progress));
+   b = (color->from.b + (int)((float)color->to.b * progress));
+   a = (color->from.a + (int)((float)color->to.a * progress));
 
-   evas_object_color_set(color->obj, r, g, b, a);
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     evas_object_color_set(obj, r, g, b, a);
 }
 
-/**
- * Add Color effect.  
- *
- * @param  obj           Evas_Object that effect is applying to
- * @param  from_r        RGB R when effect begins
- * @param  from_g        RGB G when effect begins 
- * @param  from_b        RGB B when effect begins
- * @param  from_a        RGB A when effect begins
- * @param  to_r          RGB R when effect ends
- * @param  to_g          RGB G when effect ends
- * @param  to_b          RGB B when effect ends
- * @param  to_a          RGB A when effect ends
- * @return               Color Effect
- *
- * @ingroup Transit 
- */
-EAPI Elm_Effect *
-elm_fx_color_add(Evas_Object *obj, 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)
+static Elm_Transit_Effect *
+_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)
 {
-   Elm_Effect *effect;
+   Elm_Transit_Effect_Color *color;
 
-   Elm_Fx_Color *color;
+   color = ELM_NEW(Elm_Transit_Effect_Color);
+   if (!color) return NULL;
 
-   if (!obj)
-      return NULL;
-
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
-
-   color = calloc(1, sizeof(Elm_Fx_Color));
-   if (!color)
-     {
-       free(effect);
-       return NULL;
-     }
-
-   color->obj = obj;
    color->from.r = from_r;
    color->from.g = from_g;
    color->from.b = from_b;
@@ -1530,466 +2196,644 @@ elm_fx_color_add(Evas_Object *obj, unsigned int from_r, unsigned int from_g,
    color->to.b = to_b - from_b;
    color->to.a = to_a - from_a;
 
-   effect->begin_op = _elm_fx_color_begin;
-   effect->animation_op = _elm_fx_color_op;
-   effect->user_data = color;
+   return color;
+}
 
-   return effect;
+/**
+ * Add the Color Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates color effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit        Transit object.
+ * @param  from_r        RGB R when effect begins.
+ * @param  from_g        RGB G when effect begins.
+ * @param  from_b        RGB B when effect begins.
+ * @param  from_a        RGB A when effect begins.
+ * @param  to_r          RGB R when effect ends.
+ * @param  to_g          RGB G when effect ends.
+ * @param  to_b          RGB B when effect ends.
+ * @param  to_a          RGB A when effect ends.
+ * @return               Color effect context data.
+ *
+ * @ingroup Transit
+ */
+EAPI Elm_Transit_Effect *
+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)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   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);
+
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_color_op, effect_context,
+                          _transit_effect_color_context_free);
+   return effect_context;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Fade FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _fade Elm_Fx_Fade;
-static void _elm_fx_fade_begin(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_fade_end(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_fade_op(void *data, Elm_Animator *animator, 
-                               double frame);
+///////////////////////////////////////////////////////////////////////////////
+//Fade Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Fade Elm_Transit_Effect_Fade;
+typedef struct _Elm_Transit_Effect_Fade_Node Elm_Transit_Effect_Fade_Node;
 
-struct _fade
+struct _Elm_Transit_Effect_Fade_Node
 {
    Evas_Object *before;
    Evas_Object *after;
    struct _signed_color before_color, after_color;
    int before_alpha;
    int after_alpha;
-   Eina_Bool inversed:1;
+   Eina_Bool inversed : 1;
+};
+
+struct _Elm_Transit_Effect_Fade
+{
+   Eina_List *nodes;
 };
 
 static void
-_elm_fx_fade_begin(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
+_fade_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
 {
-   Elm_Fx_Fade *fade = data;
+   Elm_Transit_Effect_Fade *fade = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_Fade_Node *fade_node;
 
-   fade->inversed = EINA_FALSE;
+   EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
+     {
+        if (fade_node->before == obj)
+          evas_object_event_callback_del(fade_node->after,
+                                         EVAS_CALLBACK_DEL, _fade_object_del_cb);
+        else if (fade_node->after == obj)
+          evas_object_event_callback_del(fade_node->before,
+                                         EVAS_CALLBACK_DEL, _fade_object_del_cb);
+        else continue;
+
+        fade->nodes = eina_list_remove_list(fade->nodes, elist);
+        free(fade_node);
+        break;
+     }
 }
 
-static void
-_elm_fx_fade_end(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
+static Eina_List *
+_fade_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Fade *fade_data)
 {
-   Elm_Fx_Fade *fade = data;
+   Elm_Transit_Effect_Fade_Node *fade;
+   Eina_List *data_list = NULL;
+   int i, count;
 
-   evas_object_color_set(fade->before, fade->before_color.r,
-                        fade->before_color.g, fade->before_color.b,
-                        fade->before_color.a);
-   evas_object_color_set(fade->after, fade->after_color.r, fade->after_color.g,
-                        fade->after_color.b, fade->after_color.a);
+   count = eina_list_count(transit->objs);
+   for (i = 0; i < count; i += 2)
+     {
+        fade = ELM_NEW(Elm_Transit_Effect_Fade_Node);
+        if (!fade)
+          {
+             eina_list_free(data_list);
+             return NULL;
+          }
+
+        fade->before = eina_list_nth(transit->objs, i);
+        fade->after = eina_list_nth(transit->objs, i+1);
+
+        evas_object_color_get(fade->before,
+                              &fade->before_color.r, &fade->before_color.g,
+                              &fade->before_color.b, &fade->before_color.a);
+        evas_object_color_get(fade->after,
+                              &fade->after_color.r, &fade->after_color.g,
+                              &fade->after_color.b, &fade->after_color.a);
+
+        fade->before_alpha = (255 - fade->before_color.a);
+        fade->after_alpha = (255 - fade->after_color.a);
+
+        data_list = eina_list_append(data_list, fade);
+
+        evas_object_event_callback_add(fade->before,
+                                       EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
+        evas_object_event_callback_add(fade->after,
+                                       EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
+     }
+   return data_list;
 }
 
 static void
-_elm_fx_fade_op(void *data, Elm_Animator *animator, double frame)
+_transit_effect_fade_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
 {
-   Elm_Fx_Fade *fade;
-
-   float _frame;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   Elm_Transit_Effect_Fade *fade = effect;
+   Elm_Transit_Effect_Fade_Node *fade_node;
+   Eina_List *elist, *elist_next;
 
-   fade = data;
-
-   if (frame < 0.5)
-     {
-       if (!fade->inversed)
-         {
-            evas_object_hide(fade->after);
-            evas_object_show(fade->before);
-            fade->inversed = EINA_TRUE;
-         }
-
-       _frame = (1 - (frame * 2));
-
-       evas_object_color_set(fade->before, fade->before_color.r * _frame,
-                             fade->before_color.g * _frame,
-                             fade->before_color.b * _frame,
-                             fade->before_color.a + fade->before_alpha * (1 -
-                                                                          _frame));
-     }
-   else
+   EINA_LIST_FOREACH_SAFE(fade->nodes, elist, elist_next, fade_node)
      {
-       if (fade->inversed)
-         {
-            evas_object_hide(fade->before);
-            evas_object_show(fade->after);
-            fade->inversed = EINA_FALSE;
-         }
-
-       _frame = ((frame - 0.5) * 2);
-
-       evas_object_color_set(fade->after, fade->after_color.r * _frame,
-                             fade->after_color.g * _frame,
-                             fade->after_color.b * _frame,
-                             fade->after_color.a + fade->after_alpha * (1 -
-                                                                        _frame));
+        evas_object_color_set(fade_node->before, fade_node->before_color.r,
+                              fade_node->before_color.g,
+                              fade_node->before_color.b,
+                              fade_node->before_color.a);
+        evas_object_color_set(fade_node->after, fade_node->after_color.r,
+                              fade_node->after_color.g,
+                              fade_node->after_color.b,
+                              fade_node->after_color.a);
+
+        fade->nodes = eina_list_remove_list(fade->nodes, elist);
+        evas_object_event_callback_del(fade_node->before,
+                                       EVAS_CALLBACK_DEL, _fade_object_del_cb);
+        evas_object_event_callback_del(fade_node->after,
+                                       EVAS_CALLBACK_DEL, _fade_object_del_cb);
+        free(fade_node);
      }
 
+   free(fade);
 }
 
-/**
- * Add Fade effect  
- *
- * @param before Evas Object before fade in 
- * @param after Evas Object after fade out 
- * @return Fade effect
- * 
- * @ingroup Transit 
- */
-EAPI Elm_Effect *
-elm_fx_fade_add(Evas_Object *before, Evas_Object *after)
+static void
+_transit_effect_fade_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
 {
-   Elm_Effect *effect;
-
-   Elm_Fx_Fade *fade;
-
-   if ((!before) && (!after))
-      return NULL;
-
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   Elm_Transit_Effect_Fade *fade = effect;
+   Eina_List *elist;
+   Elm_Transit_Effect_Fade_Node *fade_node;
+   float _progress;
 
-   fade = calloc(1, sizeof(Elm_Fx_Fade));
+   if (!fade->nodes)
+     fade->nodes = _fade_nodes_build(transit, fade);
 
-   if (!fade)
+   EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
      {
-       free(effect);
-       return NULL;
+        if (progress < 0.5)
+          {
+             if (!fade_node->inversed)
+               {
+                  evas_object_hide(fade_node->after);
+                  evas_object_show(fade_node->before);
+                  fade_node->inversed = EINA_TRUE;
+               }
+
+             _progress = (1 - (progress * 2));
+
+             evas_object_color_set(fade_node->before,
+                                   fade_node->before_color.r * _progress,
+                                   fade_node->before_color.g * _progress,
+                                   fade_node->before_color.b * _progress,
+                                   fade_node->before_color.a +
+                                   fade_node->before_alpha * (1 - _progress));
+          }
+        else
+          {
+             if (fade_node->inversed)
+               {
+                  evas_object_hide(fade_node->before);
+                  evas_object_show(fade_node->after);
+                  fade_node->inversed = EINA_FALSE;
+               }
+
+             _progress = ((progress - 0.5) * 2);
+
+             evas_object_color_set(fade_node->after,
+                                   fade_node->after_color.r * _progress,
+                                   fade_node->after_color.g * _progress,
+                                   fade_node->after_color.b * _progress,
+                                   fade_node->after_color.a +
+                                   fade_node->after_alpha * (1 - _progress));
+          }
      }
+}
 
-   evas_object_color_get(before, &fade->before_color.r, &fade->before_color.g,
-                        &fade->before_color.b, &fade->before_color.a);
-   evas_object_color_get(after, &fade->after_color.r, &fade->after_color.g,
-                        &fade->after_color.b, &fade->after_color.a);
-
-   fade->before = before;
-   fade->after = after;
-   fade->before_alpha = (255 - fade->before_color.a);
-   fade->after_alpha = (255 - fade->after_color.a);
+static Elm_Transit_Effect *
+_transit_effect_fade_context_new(void)
+{
+   Elm_Transit_Effect_Fade *fade;
+   fade = ELM_NEW(Elm_Transit_Effect_Fade);
+   if (!fade) return NULL;
+   return fade;
+}
 
-   effect->begin_op = _elm_fx_fade_begin;
-   effect->end_op = _elm_fx_fade_end;
-   effect->animation_op = _elm_fx_fade_op;
-   effect->user_data = fade;
+/**
+ * Add the Fade Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates fade effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ * @note This effect is applied to each pair of objects in the order they are listed
+ * in the transit list of objects. The first object in the pair will be the
+ * "before" object and the second will be the "after" object.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @return Fade effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the color information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ */
+EAPI Elm_Transit_Effect *
+elm_transit_effect_fade_add(Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
 
-   return effect;
+   Elm_Transit_Effect *effect_context = _transit_effect_fade_context_new();
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_fade_op, effect_context,
+                          _transit_effect_fade_context_free);
+   return effect_context;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Blend FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _blend Elm_Fx_Blend;
-static void _elm_fx_blend_begin(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_blend_end(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_blend_op(void *data, Elm_Animator *animator, 
-                               double frame);
 
-struct _blend
+///////////////////////////////////////////////////////////////////////////////
+//Blend Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Blend Elm_Transit_Effect_Blend;
+typedef struct _Elm_Transit_Effect_Blend_Node Elm_Transit_Effect_Blend_Node;
+
+struct _Elm_Transit_Effect_Blend_Node
 {
    Evas_Object *before;
    Evas_Object *after;
    struct _signed_color from, to;
 };
 
-static void
-_elm_fx_blend_begin(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
+struct _Elm_Transit_Effect_Blend
 {
-   Elm_Fx_Blend *blend = data;
-
-   evas_object_show(blend->before);
-}
+   Eina_List *nodes;
+};
 
 static void
-_elm_fx_blend_end(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
+_blend_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
 {
-   Elm_Fx_Blend *blend = data;
+   Elm_Transit_Effect_Blend *blend = data;
+   Eina_List *elist;
+   Elm_Transit_Effect_Blend_Node *blend_node;
 
-   evas_object_color_set(blend->before, blend->from.r, blend->from.g,
-                        blend->from.b, blend->from.a);
-   evas_object_color_set(blend->after, blend->to.r, blend->to.g, blend->to.b,
-                        blend->to.a);
-   if (!auto_reverse)
-      evas_object_hide(blend->before);
-   else
-      evas_object_hide(blend->after);
+   EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
+     {
+        if (blend_node->after == obj)
+          evas_object_event_callback_del(blend_node->before,
+                                         EVAS_CALLBACK_DEL, _blend_object_del_cb);
+        else if (blend_node->before == obj)
+          evas_object_event_callback_del(blend_node->after,
+                                         EVAS_CALLBACK_DEL, _blend_object_del_cb);
+        else continue;
+
+        blend->nodes = eina_list_remove_list(blend->nodes, elist);
+        free(blend_node);
+        break;
+     }
 }
 
-static void
-_elm_fx_blend_op(void *data, Elm_Animator *animator, double frame)
+static Eina_List *
+_blend_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Blend *blend)
 {
-   Elm_Fx_Blend *blend = data;
+   Elm_Transit_Effect_Blend_Node *blend_node;
+   Eina_List *data_list = NULL;
+   int i, count;
 
-   evas_object_show(blend->after);
-   evas_object_color_set(blend->before, (int)(blend->from.r * (1 - frame)),
-                        (int)(blend->from.g * (1 - frame)),
-                        (int)(blend->from.b * (1 - frame)),
-                        (int)(blend->from.a * (1 - frame)));
-   evas_object_color_set(blend->after, (int)(blend->to.r * frame),
-                        (int)(blend->to.g * frame), (int)(blend->to.b * frame),
-                        (int)(blend->to.a * frame));
+   count = eina_list_count(transit->objs);
+   for (i = 0; i < (count - 1); i += 2)
+     {
+        blend_node = ELM_NEW(Elm_Transit_Effect_Blend_Node);
+        if (!blend_node)
+          {
+             eina_list_free(data_list);
+             return NULL;
+          }
+
+        blend_node->before = eina_list_nth(transit->objs, i);
+        blend_node->after = eina_list_nth(transit->objs, i + 1);
+        evas_object_show(blend_node->before);
+        evas_object_show(blend_node->after);
+
+        evas_object_color_get(blend_node->before, &blend_node->from.r,
+                              &blend_node->from.g, &blend_node->from.b,
+                              &blend_node->from.a);
+        evas_object_color_get(blend_node->after, &blend_node->to.r,
+                              &blend_node->to.g, &blend_node->to.b,
+                              &blend_node->to.a);
+
+        data_list = eina_list_append(data_list, blend_node);
+
+        evas_object_event_callback_add(blend_node->before,
+                                       EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
+        evas_object_event_callback_add(blend_node->after,
+                                       EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
+     }
+   return data_list;
 }
 
-/**
- * Add Blend effect  
- *
- * @param before Evas Object before blending
- * @param after Evas Object after blending 
- * @return Blend effect
- *
- * @ingroup Transit 
- */
-EAPI Elm_Effect *
-elm_fx_blend_add(Evas_Object *before, Evas_Object *after)
+void
+_transit_effect_blend_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
 {
-   Elm_Effect *effect;
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   Elm_Transit_Effect_Blend *blend = effect;
+   Elm_Transit_Effect_Blend_Node *blend_node;
+   Eina_List *elist, *elist_next;
 
-   Elm_Fx_Blend *blend;
+   EINA_LIST_FOREACH_SAFE(blend->nodes, elist, elist_next, blend_node)
+     {
+        evas_object_color_set(blend_node->before,
+                              blend_node->from.r, blend_node->from.g,
+                              blend_node->from.b, blend_node->from.a);
+        evas_object_color_set(blend_node->after, blend_node->to.r,
+                              blend_node->to.g, blend_node->to.b,
+                              blend_node->to.a);
+
+        if (elm_transit_auto_reverse_get(transit))
+          evas_object_hide(blend_node->after);
+        else
+          evas_object_hide(blend_node->before);
+
+        blend->nodes = eina_list_remove_list(blend->nodes, elist);
+
+        evas_object_event_callback_del(blend_node->before,
+                                       EVAS_CALLBACK_DEL, _blend_object_del_cb);
+        evas_object_event_callback_del(blend_node->after,
+                                       EVAS_CALLBACK_DEL, _blend_object_del_cb);
+        free(blend_node);
+     }
+   free(blend);
+}
 
-   if ((!before) && (!after))
-      return NULL;
+void
+_transit_effect_blend_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
+{
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Blend *blend = effect;
+   Elm_Transit_Effect_Blend_Node *blend_node;
+   Eina_List *elist;
 
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
+   if (!blend->nodes) blend->nodes = _blend_nodes_build(transit, blend);
 
-   blend = calloc(1, sizeof(Elm_Fx_Blend));
-   if (!blend)
+   EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
      {
-       free(effect);
-       return NULL;
+        evas_object_color_set(blend_node->before,
+                              (int)(blend_node->from.r * (1 - progress)),
+                              (int)(blend_node->from.g * (1 - progress)),
+                              (int)(blend_node->from.b * (1 - progress)),
+                              (int)(blend_node->from.a * (1 - progress)));
+        evas_object_color_set(blend_node->after,
+                              (int)(blend_node->to.r * progress),
+                              (int)(blend_node->to.g * progress),
+                              (int)(blend_node->to.b * progress),
+                              (int)(blend_node->to.a * progress));
      }
+}
 
-   blend->before = before;
-   blend->after = after;
-   evas_object_color_get(before, &blend->from.r, &blend->from.g, &blend->from.b,
-                        &blend->from.a);
-   evas_object_color_get(after, &blend->to.r, &blend->to.g, &blend->to.b,
-                        &blend->to.a);
+static Elm_Transit_Effect *
+_transit_effect_blend_context_new(void)
+{
+   Elm_Transit_Effect_Blend *blend;
 
-   effect->begin_op = _elm_fx_blend_begin;
-   effect->end_op = _elm_fx_blend_end;
-   effect->animation_op = _elm_fx_blend_op;
-   effect->user_data = blend;
+   blend = ELM_NEW(Elm_Transit_Effect_Blend);
+   if (!blend) return NULL;
+   return blend;
+}
 
-   return effect;
+/**
+ * Add the Blend Effect to Elm_Transit.
+ *
+ * @note This API is one of the facades. It creates blend effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ * @note This effect is applied to each pair of objects in the order they are listed
+ * in the transit list of objects. The first object in the pair will be the
+ * "before" object and the second will be the "after" object.
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @return Blend effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the color information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
+ */
+EAPI Elm_Transit_Effect *
+elm_transit_effect_blend_add(Elm_Transit *transit)
+{
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   Elm_Transit_Effect *effect_context = _transit_effect_blend_context_new();
+
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_blend_op, effect_context,
+                          _transit_effect_blend_context_free);
+   return effect_context;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-//Rotation FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _rotation Elm_Fx_Rotation;
-static void _elm_fx_rotation_begin(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_rotation_end(void *data, Eina_Bool auto_reverse, 
-                               unsigned int repeat_cnt);
-static void _elm_fx_rotation_op(void *data, Elm_Animator *animator, 
-                               double frame);
 
-struct _rotation
+///////////////////////////////////////////////////////////////////////////////
+//Rotation Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Rotation Elm_Transit_Effect_Rotation;
+
+struct _Elm_Transit_Effect_Rotation
 {
-   Evas_Object *obj;
-   Eina_Bool cw;
    float from, to;
 };
 
 static void
-_elm_fx_rotation_begin(void *data, Eina_Bool auto_reverse,
-                      unsigned int repeat_cnt)
-{
-   Elm_Fx_Rotation *rotation = data;
-
-   evas_object_show(rotation->obj);
-}
-
-static void
-_elm_fx_rotation_end(void *data, Eina_Bool auto_reverse,
-                    unsigned int repeat_cnt)
+_transit_effect_rotation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
 {
-   Elm_Fx_Rotation *rotation = data;
-
-   evas_object_map_enable_set(rotation->obj, EINA_FALSE);
+   Elm_Transit_Effect_Rotation *rotation = effect;
+   free(rotation);
 }
 
 static void
-_elm_fx_rotation_op(void *data, Elm_Animator *animator, double frame)
+_transit_effect_rotation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
 {
-   Elm_Fx_Rotation *rotation;
-
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Elm_Transit_Effect_Rotation *rotation = effect;
    Evas_Map *map;
-
    Evas_Coord x, y, w, h;
-
    float degree;
-
    float half_w, half_h;
+   Eina_List *elist;
+   Evas_Object *obj;
 
    map = evas_map_new(4);
-   if (!map)
-      return;
+   if (!map) return;
+
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        evas_map_util_points_populate_from_object_full(map, obj, 0);
+        degree = rotation->from + (float)(progress * rotation->to);
 
-   rotation = data;
+        evas_object_geometry_get(obj, &x, &y, &w, &h);
 
-   evas_map_smooth_set(map, EINA_TRUE);
-   evas_map_util_points_populate_from_object_full(map, rotation->obj, 0);
-   degree = rotation->from + (float)(frame * rotation->to);
+        half_w = (float)w * 0.5;
+        half_h = (float)h * 0.5;
 
-   if (!rotation->cw)
-      degree *= -1;
+        evas_map_util_3d_rotate(map, 0, 0, degree, x + half_w, y + half_h, 0);
+        evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
+        evas_object_map_enable_set(obj, EINA_TRUE);
+        evas_object_map_set(obj, map);
+     }
+   evas_map_free(map);
+}
 
-   evas_object_geometry_get(rotation->obj, &x, &y, &w, &h);
+static Elm_Transit_Effect *
+_transit_effect_rotation_context_new(float from_degree, float to_degree)
+{
+   Elm_Transit_Effect_Rotation *rotation;
 
-   half_w = (float)w *0.5;
+   rotation = ELM_NEW(Elm_Transit_Effect_Rotation);
+   if (!rotation) return NULL;
 
-   half_h = (float)h *0.5;
+   rotation->from = from_degree;
+   rotation->to = to_degree - from_degree;
 
-   evas_map_util_3d_rotate(map, 0, 0, degree, x + half_w, y + half_h, 0);
-   evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, 10000);
-   evas_object_map_enable_set(rotation->obj, EINA_TRUE);
-   evas_object_map_set(rotation->obj, map);
-   evas_map_free(map);
+   return rotation;
 }
 
 /**
- * Add Rotation effect
+ * Add the Rotation Effect to Elm_Transit.
  *
- * @param obj Evas_Object that effect is applying to 
- * @param from degree Degree when effect begins
- * @param to_degree Degree when effect is ends
- * @param cw Rotation direction. EINA_TRUE is clock wise
- * @return Rotation effect
+ * @note This API is one of the facades. It creates rotation effect context
+ * and add it's required APIs to elm_transit_effect_add.
  *
- * @ingroup Transit 
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param from_degree Degree when effect begins.
+ * @param to_degree Degree when effect is ends.
+ * @return Rotation effect context data.
+ *
+ * @ingroup Transit
+ * @warning Is higher recommended just create a transit with this effect when
+ * the window that the objects of the transit belongs has already been created.
+ * This is because this effect needs the geometry information about the objects,
+ * and if the window was not created yet, it can get a wrong information.
  */
-EAPI Elm_Effect *
-elm_fx_rotation_add(Evas_Object *obj, float from_degree, float to_degree,
-                   Eina_Bool cw)
+EAPI Elm_Transit_Effect *
+elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree)
 {
-   Elm_Effect *effect;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   Elm_Transit_Effect *effect_context = _transit_effect_rotation_context_new(from_degree, to_degree);
+
+   if (!effect_context) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_rotation_op, effect_context,
+                          _transit_effect_rotation_context_free);
+   return effect_context;
+}
 
-   Elm_Fx_Rotation *rotation;
 
-   if (!obj)
-      return NULL;
+///////////////////////////////////////////////////////////////////////////////
+//ImageAnimation Effect
+///////////////////////////////////////////////////////////////////////////////
+typedef struct _Elm_Transit_Effect_Image_Animation Elm_Transit_Effect_Image_Animation;
 
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
+struct _Elm_Transit_Effect_Image_Animation
+{
+   Eina_List *images;
+};
 
-   rotation = calloc(1, sizeof(Elm_Fx_Rotation));
+static void
+_transit_effect_image_animation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
+{
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   Elm_Transit_Effect_Image_Animation *image_animation = effect;
+   const char *image;
+   Eina_List *elist, *elist_next;
 
-   if (!rotation)
+   EINA_LIST_FOREACH_SAFE(image_animation->images, elist, elist_next, image)
      {
-       free(effect);
-       return NULL;
+        image_animation->images =
+           eina_list_remove_list(image_animation->images, elist);
+        eina_stringshare_del(image);
      }
 
-   rotation->obj = obj;
-   rotation->from = from_degree;
-   rotation->to = to_degree - from_degree;
-   rotation->cw = cw;
-
-   effect->begin_op = _elm_fx_rotation_begin;
-   effect->end_op = _elm_fx_rotation_end;
-   effect->animation_op = _elm_fx_rotation_op;
-   effect->user_data = rotation;
-
-   return effect;
+   free(image_animation);
 }
 
-/////////////////////////////////////////////////////////////////////////////////////
-// ImageAnimation FX
-/////////////////////////////////////////////////////////////////////////////////////
-typedef struct _image_animation Elm_Fx_Image_Animation;
-static void _elm_fx_image_animation_begin(void *data, Eina_Bool auto_reverse,
-                      unsigned int repeat_cnt);
-static void _elm_fx_image_animation_op(void *data, Elm_Animator *animator, 
-                               double frame);
-EAPI Elm_Effect *elm_fx_image_animation_add(Evas_Object *obj, const char **images, 
-                               unsigned int item_num);
-
-struct _image_animation
+static void
+_transit_effect_image_animation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
 {
+   EINA_SAFETY_ON_NULL_RETURN(effect);
+   EINA_SAFETY_ON_NULL_RETURN(transit);
+   Eina_List *elist;
    Evas_Object *obj;
-   char **images;
-   int img_cnt;
-};
+   const char *type;
+   Elm_Transit_Effect_Image_Animation *image_animation = effect;
+   unsigned int count = 0;
+   int len;
 
+   type = eina_stringshare_add("icon");
+   len = eina_list_count(image_animation->images);
 
-static void
-_elm_fx_image_animation_begin(void *data, Eina_Bool auto_reverse,
-                      unsigned int repeat_cnt)
-{
-   Elm_Fx_Image_Animation *image_animation = data;
-   evas_object_show(image_animation->obj);
-}
-
+   if (!len) count = floor(progress * len);
+   else count = floor(progress * (len - 1));
 
-static void
-_elm_fx_image_animation_op(void *data, Elm_Animator *animator, double frame)
-{
-   Elm_Fx_Image_Animation *image_animation = (Elm_Fx_Image_Animation *) data;
+   EINA_LIST_FOREACH(transit->objs, elist, obj)
+     {
+        if (elm_widget_type_check(obj, type))
+          elm_icon_file_set(obj,
+                            eina_list_nth(image_animation->images, count), NULL);
+     }
 
-   elm_icon_file_set(image_animation->obj,
-                    image_animation->images[ (int) floor(frame * (image_animation->img_cnt-1)) ], NULL);
+   eina_stringshare_del(type);
 }
 
-static void
-_elm_fx_image_animation_del(void *data)
+static Elm_Transit_Effect *
+_transit_effect_image_animation_context_new(Eina_List *images)
 {
-       int idx;
-       Elm_Fx_Image_Animation *image_animation = data;
-
-       for(idx = 0; idx < image_animation->img_cnt; ++idx ) {
-               eina_stringshare_del(image_animation->images[ idx ]);
-       }
+   Elm_Transit_Effect_Image_Animation *image_animation;
+   image_animation = ELM_NEW(Elm_Transit_Effect_Image_Animation);
 
-       free(image_animation->images);
+   if (!image_animation) return NULL;
+   image_animation->images = images;
+   return image_animation;
 }
 
 /**
- * Add image_animation effect.  
+ * Add the ImageAnimation Effect to Elm_Transit.
  *
- * @param obj Icon object
- * @param images Array of image file path. 
- * @param img_cnt Count of image. 
- * @return ImageAnimation effect.
+ * @note This API is one of the facades. It creates image animation effect context
+ * and add it's required APIs to elm_transit_effect_add.
+ * The @p images parameter is a list images paths. This list and
+ * its contents will be deleted at the end of the effect by
+ * elm_transit_effect_image_animation_context_free() function.
  *
- * @ingroup Transit 
+ * Example:
+ * @code
+ * char buf[PATH_MAX];
+ * Eina_List *images = NULL;
+ * Elm_Transit *transi = elm_transit_add();
+ *
+ * snprintf(buf, sizeof(buf), "%s/images/icon_11.png", PACKAGE_DATA_DIR);
+ * images = eina_list_append(images, eina_stringshare_add(buf));
+ *
+ * snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+ * images = eina_list_append(images, eina_stringshare_add(buf));
+ * elm_transit_effect_image_animation_add(transi, images);
+ *
+ * @endcode
+ *
+ * @see elm_transit_effect_add()
+ *
+ * @param transit Transit object.
+ * @param images Eina_List of images file paths. This list and
+ * its contents will be deleted at the end of the effect by
+ * elm_transit_effect_image_animation_context_free() function.
+ * @return Image Animation effect context data.
+ *
+ * @ingroup Transit
  */
-EAPI Elm_Effect *
-elm_fx_image_animation_add(Evas_Object *obj, const char **images,
-                         unsigned int img_cnt)
+EAPI Elm_Transit_Effect *
+elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images)
 {
-   Elm_Effect *effect;
-   Elm_Fx_Image_Animation *image_animation;
-   int idx;
-
-   if ((!obj) || !images || !(*images))
-      return NULL;
-
-   effect = calloc(1, sizeof(Elm_Effect));
-   if (!effect)
-      return NULL;
-
-   image_animation = calloc(1, sizeof(Elm_Fx_Image_Animation));
-
-   if (!image_animation)
-     {
-       free(effect);
-       return NULL;
-     }
-
-   image_animation->obj = obj;
-   image_animation->images = calloc( img_cnt, sizeof(char*));
-   for(idx = 0; idx < img_cnt; ++idx )
-          image_animation->images[ idx ] = eina_stringshare_add( images[ idx ] );
-
-   image_animation->img_cnt = img_cnt;
-
-   effect->begin_op = _elm_fx_image_animation_begin;
-   effect->animation_op = _elm_fx_image_animation_op;
-   effect->del_op = _elm_fx_image_animation_del;
-   effect->user_data = image_animation;
+   ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
+   Elm_Transit_Effect *effect = _transit_effect_image_animation_context_new(images);
 
+   if (!effect) return NULL;
+   elm_transit_effect_add(transit,
+                          _transit_effect_image_animation_op, effect,
+                          _transit_effect_image_animation_context_free);
    return effect;
 }