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