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