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