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