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