1 #include <Elementary.h>
4 #define ELM_TRANSIT_CHECK_OR_RETURN(transit, ...) \
7 CRITICAL("Elm_Transit " # transit " is NULL!"); \
10 if (!EINA_MAGIC_CHECK(transit, ELM_TRANSIT_MAGIC)) { \
11 EINA_MAGIC_FAIL(transit, ELM_TRANSIT_MAGIC); \
14 if (transit->deleted){ \
15 ERR("Elm_Transit " # transit " has already been deleted!"); \
21 #define _TRANSIT_FOCAL 2000
25 #define ELM_TRANSIT_MAGIC 0xd27f190a
28 Ecore_Animator *animator;
29 Eina_Inlist *effect_list;
31 Elm_Transit *prev_chain_transit;
32 Eina_List *next_chain_transits;
33 Elm_Transit_Tween_Mode tween_mode;
35 Elm_Transit_Del_Cb func;
51 unsigned int effects_pending_del;
53 Eina_Bool auto_reverse : 1;
54 Eina_Bool event_enabled : 1;
55 Eina_Bool deleted : 1;
56 Eina_Bool state_keep : 1;
57 Eina_Bool finished : 1;
60 struct _Elm_Transit_Effect_Module
63 Elm_Transit_Effect_Transition_Cb transition_cb;
64 Elm_Transit_Effect_End_Cb end_cb;
65 Elm_Transit_Effect *effect;
66 Eina_Bool deleted : 1;
69 struct _Elm_Transit_Obj_State
71 Evas_Coord x, y, w, h;
74 Eina_Bool map_enabled : 1;
75 Eina_Bool visible : 1;
78 struct _Elm_Transit_Obj_Data
80 struct _Elm_Transit_Obj_State *state;
81 Eina_Bool pass_events : 1;
84 typedef struct _Elm_Transit_Effect_Module Elm_Transit_Effect_Module;
85 typedef struct _Elm_Transit_Obj_Data Elm_Transit_Obj_Data;
86 typedef struct _Elm_Transit_Obj_State Elm_Transit_Obj_State;
88 static void _transit_obj_data_update(Elm_Transit *transit, Evas_Object *obj);
89 static void _transit_obj_data_recover(Elm_Transit *transit, Evas_Object *obj);
90 static void _transit_obj_states_save(Evas_Object *obj, Elm_Transit_Obj_Data *obj_data);
91 static void _transit_obj_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
92 static void _transit_obj_remove(Elm_Transit *transit, Evas_Object *obj);
93 static void _transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Module *effect_module);
94 static void _transit_remove_dead_effects(Elm_Transit *transit);
95 static void _transit_del(Elm_Transit *transit);
96 static void _transit_animate_op(Elm_Transit *transit, double progress);
97 static Eina_Bool _transit_animate_cb(void *data);
99 static char *_transit_key= "_elm_transit_key";
102 _transit_obj_data_update(Elm_Transit *transit, Evas_Object *obj)
104 Elm_Transit_Obj_Data *obj_data = evas_object_data_get(obj, _transit_key);
107 obj_data = ELM_NEW(Elm_Transit_Obj_Data);
109 obj_data->pass_events = evas_object_pass_events_get(obj);
111 if ((!transit->state_keep) && (obj_data->state))
113 free(obj_data->state);
114 obj_data->state = NULL;
118 _transit_obj_states_save(obj, obj_data);
121 evas_object_data_set(obj, _transit_key, obj_data);
125 _transit_obj_states_save(Evas_Object *obj, Elm_Transit_Obj_Data *obj_data)
127 Elm_Transit_Obj_State *state = obj_data->state;
130 state = calloc(1, sizeof(Elm_Transit_Obj_State));
133 evas_object_geometry_get(obj, &state->x, &state->y, &state->w, &state->h);
134 evas_object_color_get(obj, &state->r, &state->g, &state->b, &state->a);
135 state->visible = evas_object_visible_get(obj);
136 state->map_enabled = evas_object_map_enable_get(obj);
137 if (evas_object_map_get(obj))
138 state->map = evas_map_dup(evas_object_map_get(obj));
139 obj_data->state = state;
143 _remove_obj_from_list(Elm_Transit *transit, Evas_Object *obj)
145 //Remove duplicated objects
146 //TODO: Need to consider about optimizing here
149 if (!eina_list_data_find_list(transit->objs, obj))
151 transit->objs = eina_list_remove(transit->objs, obj);
152 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
153 _transit_obj_remove_cb,
159 _transit_obj_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
161 Elm_Transit *transit = data;
162 Elm_Transit_Obj_Data *obj_data = evas_object_data_get(obj, _transit_key);
166 free(obj_data->state);
169 _remove_obj_from_list(transit, obj);
170 if (!transit->objs) elm_transit_del(transit);
174 _transit_obj_data_recover(Elm_Transit *transit, Evas_Object *obj)
176 Elm_Transit_Obj_Data *obj_data;
177 Elm_Transit_Obj_State *state;
179 obj_data = evas_object_data_get(obj, _transit_key);
180 if (!obj_data) return;
181 evas_object_data_del(obj, _transit_key);
182 evas_object_pass_events_set(obj, obj_data->pass_events);
183 state = obj_data->state;
186 //recover the states of the object.
187 if (!transit->state_keep)
189 evas_object_move(obj, state->x, state->y);
190 evas_object_resize(obj, state->w, state->h);
191 evas_object_color_set(obj, state->r, state->g, state->b, state->a);
192 if (state->visible) evas_object_show(obj);
193 else evas_object_hide(obj);
194 if (state->map_enabled)
195 evas_object_map_enable_set(obj, EINA_TRUE);
197 evas_object_map_enable_set(obj, EINA_FALSE);
199 evas_object_map_set(obj, state->map);
207 _transit_obj_remove(Elm_Transit *transit, Evas_Object *obj)
209 _remove_obj_from_list(transit, obj);
210 _transit_obj_data_recover(transit, obj);
214 _transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Module *effect_module)
216 if (effect_module->end_cb)
217 effect_module->end_cb(effect_module->effect, transit);
222 _transit_remove_dead_effects(Elm_Transit *transit)
224 Elm_Transit_Effect_Module *effect_module;
226 EINA_INLIST_FOREACH(transit->effect_list, effect_module)
228 if (effect_module->deleted)
230 _transit_effect_del(transit, effect_module);
231 transit->effects_pending_del--;
232 if (!transit->effects_pending_del) return;
238 _transit_del(Elm_Transit *transit)
240 Elm_Transit_Effect_Module *effect_module;
241 Elm_Transit *chain_transit;
242 Eina_List *elist, *elist_next;
244 if (transit->animator)
245 ecore_animator_del(transit->animator);
248 while (transit->effect_list)
250 effect_module = EINA_INLIST_CONTAINER_GET(transit->effect_list, Elm_Transit_Effect_Module);
251 transit->effect_list = eina_inlist_remove(transit->effect_list, transit->effect_list);
252 _transit_effect_del(transit, effect_module);
256 while (transit->objs)
257 _transit_obj_remove(transit, eina_list_data_get(transit->objs));
259 transit->deleted = EINA_TRUE;
261 if (transit->del_data.func)
262 transit->del_data.func(transit->del_data.arg, transit);
264 //cut off the chain transit relationship
265 EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
266 chain_transit->prev_chain_transit = NULL;
268 if (transit->prev_chain_transit)
269 transit->prev_chain_transit->next_chain_transits =
270 eina_list_remove(transit->prev_chain_transit->next_chain_transits, transit);
272 // run chain transits
273 if (transit->finished && transit->next_chain_transits)
275 EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
276 elm_transit_go(chain_transit);
279 eina_list_free(transit->next_chain_transits);
281 EINA_MAGIC_SET(transit, EINA_MAGIC_NONE);
286 _transit_animate_op(Elm_Transit *transit, double progress)
288 Elm_Transit_Effect_Module *effect_module;
291 EINA_INLIST_FOREACH(transit->effect_list, effect_module)
293 if (transit->deleted) break;
294 if (!effect_module->deleted)
295 effect_module->transition_cb(effect_module->effect, transit, progress);
299 if (transit->walking) return;
301 if (transit->deleted) _transit_del(transit);
302 else if (transit->effects_pending_del) _transit_remove_dead_effects(transit);
306 _transit_animate_cb(void *data)
308 Elm_Transit *transit = data;
309 double elapsed_time, duration;
311 transit->time.current = ecore_loop_time_get();
312 elapsed_time = transit->time.current - transit->time.begin;
313 duration = transit->time.duration + transit->time.delayed;
315 if (elapsed_time > duration)
316 elapsed_time = duration;
318 transit->progress = elapsed_time / duration;
319 switch (transit->tween_mode)
321 case ELM_TRANSIT_TWEEN_MODE_ACCELERATE:
322 transit->progress = 1.0 - sin((ELM_PI / 2.0) + (transit->progress * ELM_PI / 2.0));
324 case ELM_TRANSIT_TWEEN_MODE_DECELERATE:
325 transit->progress = sin(transit->progress * ELM_PI / 2.0);
327 case ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL:
328 transit->progress = (1.0 - cos(transit->progress * ELM_PI)) / 2.0;
335 if (transit->repeat.reverse) transit->progress = 1 - transit->progress;
337 if (transit->time.duration > 0) _transit_animate_op(transit, transit->progress);
339 /* Not end. Keep going. */
340 if (elapsed_time < duration) return ECORE_CALLBACK_RENEW;
342 /* Repeat and reverse and time done! */
343 if ((transit->repeat.count >= 0) &&
344 (transit->repeat.current == transit->repeat.count) &&
345 ((!transit->auto_reverse) || transit->repeat.reverse))
347 transit->finished = EINA_TRUE;
348 elm_transit_del(transit);
349 return ECORE_CALLBACK_CANCEL;
353 if (!transit->auto_reverse || transit->repeat.reverse)
355 transit->repeat.current++;
356 transit->repeat.reverse = EINA_FALSE;
358 else transit->repeat.reverse = EINA_TRUE;
360 transit->time.begin = ecore_loop_time_get();
362 return ECORE_CALLBACK_RENEW;
366 elm_transit_add(void)
368 Elm_Transit *transit = ELM_NEW(Elm_Transit);
371 ERR("Failed to allocate a elm_transit object!");
375 EINA_MAGIC_SET(transit, ELM_TRANSIT_MAGIC);
377 elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
383 elm_transit_del(Elm_Transit *transit)
385 ELM_TRANSIT_CHECK_OR_RETURN(transit);
387 if (transit->walking) transit->deleted = EINA_TRUE;
388 else _transit_del(transit);
392 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)
394 ELM_TRANSIT_CHECK_OR_RETURN(transit);
395 EINA_SAFETY_ON_NULL_RETURN(transition_cb);
396 Elm_Transit_Effect_Module *effect_module;
398 EINA_INLIST_FOREACH(transit->effect_list, effect_module)
399 if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect))
401 WRN("elm_transit does not allow to add the duplicated effect! : transit=%p", transit);
405 effect_module = ELM_NEW(Elm_Transit_Effect_Module);
408 ERR("Failed to allocate a new effect!: transit=%p", transit);
412 effect_module->end_cb = end_cb;
413 effect_module->transition_cb = transition_cb;
414 effect_module->effect = effect;
416 transit->effect_list = eina_inlist_append(transit->effect_list, (Eina_Inlist*) effect_module);
420 elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect)
422 ELM_TRANSIT_CHECK_OR_RETURN(transit);
423 EINA_SAFETY_ON_NULL_RETURN(transition_cb);
424 Elm_Transit_Effect_Module *effect_module;
426 EINA_INLIST_FOREACH(transit->effect_list, effect_module)
428 if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect))
430 if (transit->walking)
432 effect_module->deleted = EINA_TRUE;
433 transit->effects_pending_del++;
437 _transit_effect_del(transit, effect_module);
438 if (!transit->effect_list) elm_transit_del(transit);
446 elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj)
448 ELM_TRANSIT_CHECK_OR_RETURN(transit);
449 EINA_SAFETY_ON_NULL_RETURN(obj);
451 if (transit->animator)
453 if (!evas_object_data_get(obj, _transit_key))
455 _transit_obj_data_update(transit, obj);
456 evas_object_pass_events_set(obj, EINA_TRUE);
460 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
461 _transit_obj_remove_cb,
464 transit->objs = eina_list_append(transit->objs, obj);
468 elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
470 ELM_TRANSIT_CHECK_OR_RETURN(transit);
471 EINA_SAFETY_ON_NULL_RETURN(obj);
473 _transit_obj_remove(transit, obj);
474 if (!transit->objs) elm_transit_del(transit);
477 EAPI const Eina_List *
478 elm_transit_objects_get(const Elm_Transit *transit)
480 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
481 return transit->objs;
485 elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled)
487 ELM_TRANSIT_CHECK_OR_RETURN(transit);
492 if (transit->event_enabled == enabled) return;
493 transit->event_enabled = !!enabled;
494 if (!transit->animator) return;
496 EINA_LIST_FOREACH(transit->objs, list, obj)
497 evas_object_pass_events_set(obj, enabled);
501 elm_transit_event_enabled_get(const Elm_Transit *transit)
503 ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
504 return transit->event_enabled;
508 elm_transit_del_cb_set(Elm_Transit *transit, void (*cb) (void *data, Elm_Transit *transit), void *data)
510 ELM_TRANSIT_CHECK_OR_RETURN(transit);
511 transit->del_data.func = cb;
512 transit->del_data.arg = data;
516 elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse)
518 ELM_TRANSIT_CHECK_OR_RETURN(transit);
519 transit->auto_reverse = reverse;
523 elm_transit_auto_reverse_get(const Elm_Transit *transit)
525 ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
526 return transit->auto_reverse;
530 elm_transit_repeat_times_set(Elm_Transit *transit, int repeat)
532 ELM_TRANSIT_CHECK_OR_RETURN(transit);
533 transit->repeat.count = repeat;
534 transit->repeat.current = 0;
538 elm_transit_repeat_times_get(const Elm_Transit *transit)
540 ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
541 return transit->repeat.count;
545 elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode)
547 ELM_TRANSIT_CHECK_OR_RETURN(transit);
548 transit->tween_mode = tween_mode;
551 EAPI Elm_Transit_Tween_Mode
552 elm_transit_tween_mode_get(const Elm_Transit *transit)
554 ELM_TRANSIT_CHECK_OR_RETURN(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
555 return transit->tween_mode;
559 elm_transit_duration_set(Elm_Transit *transit, double duration)
561 ELM_TRANSIT_CHECK_OR_RETURN(transit);
562 if (transit->animator)
564 WRN("elm_transit does not allow to set the duration time in operating! : transit=%p", transit);
567 transit->time.duration = duration;
571 elm_transit_duration_get(const Elm_Transit *transit)
573 ELM_TRANSIT_CHECK_OR_RETURN(transit, 0.0);
574 return transit->time.duration;
578 elm_transit_go(Elm_Transit *transit)
580 ELM_TRANSIT_CHECK_OR_RETURN(transit);
585 if (transit->animator)
586 ecore_animator_del(transit->animator);
588 EINA_LIST_FOREACH(transit->objs, elist, obj)
589 _transit_obj_data_update(transit, obj);
591 if (!transit->event_enabled)
593 EINA_LIST_FOREACH(transit->objs, elist, obj)
594 evas_object_pass_events_set(obj, EINA_TRUE);
597 transit->time.paused = 0;
598 transit->time.delayed = 0;
599 transit->time.begin = ecore_loop_time_get();
600 transit->animator = ecore_animator_add(_transit_animate_cb, transit);
604 elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused)
606 ELM_TRANSIT_CHECK_OR_RETURN(transit);
608 if (!transit->animator) return;
612 if (transit->time.paused > 0)
614 ecore_animator_freeze(transit->animator);
615 transit->time.paused = ecore_loop_time_get();
619 if (transit->time.paused == 0)
621 ecore_animator_thaw(transit->animator);
622 transit->time.delayed += (ecore_loop_time_get() - transit->time.paused);
623 transit->time.paused = 0;
628 elm_transit_paused_get(const Elm_Transit *transit)
630 ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
632 if (transit->time.paused == 0)
639 elm_transit_progress_value_get(const Elm_Transit *transit)
641 ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
643 return transit->progress;
647 elm_transit_objects_final_state_keep_set(Elm_Transit *transit, Eina_Bool state_keep)
649 ELM_TRANSIT_CHECK_OR_RETURN(transit);
651 if (transit->state_keep == state_keep) return;
652 if (transit->animator)
654 WRN("elm_transit does not allow to change final state keep mode in operating! : transit=%p", transit);
657 transit->state_keep = !!state_keep;
661 elm_transit_objects_final_state_keep_get(const Elm_Transit *transit)
663 ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
664 return transit->state_keep;
668 elm_transit_chain_transit_add(Elm_Transit *transit, Elm_Transit *chain_transit)
670 ELM_TRANSIT_CHECK_OR_RETURN(transit);
671 ELM_TRANSIT_CHECK_OR_RETURN(chain_transit);
673 if (transit == chain_transit)
675 WRN("You add a same transit as a chain transit! : transit=%p, chain_transit=%p", transit, chain_transit);
678 if (transit == chain_transit->prev_chain_transit)
681 if (chain_transit->prev_chain_transit)
682 chain_transit->prev_chain_transit->next_chain_transits = eina_list_remove(chain_transit->prev_chain_transit->next_chain_transits, chain_transit);
684 chain_transit->prev_chain_transit = transit;
685 transit->next_chain_transits = eina_list_append(transit->next_chain_transits, chain_transit);
689 elm_transit_chain_transit_del(Elm_Transit *transit, Elm_Transit *chain_transit)
691 ELM_TRANSIT_CHECK_OR_RETURN(transit);
692 ELM_TRANSIT_CHECK_OR_RETURN(chain_transit);
694 if (chain_transit->prev_chain_transit != transit)
696 WRN("A pair of transits does not have the chain relationship! : transit=%p, chain_transit=%p", transit, chain_transit);
700 chain_transit->prev_chain_transit = NULL;
701 transit->next_chain_transits = eina_list_remove(transit->next_chain_transits, chain_transit);
705 elm_transit_chain_transits_get(const Elm_Transit * transit)
707 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
708 return transit->next_chain_transits;
711 ///////////////////////////////////////////////////////////////////////////
713 ///////////////////////////////////////////////////////////////////////////
714 typedef struct _Elm_Transit_Effect_Resizing Elm_Transit_Effect_Resizing;
716 struct _Elm_Transit_Effect_Resizing
724 _transit_effect_resizing_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
726 Elm_Transit_Effect_Resizing *resizing = effect;
731 _transit_effect_resizing_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
733 EINA_SAFETY_ON_NULL_RETURN(effect);
734 EINA_SAFETY_ON_NULL_RETURN(transit);
738 Elm_Transit_Effect_Resizing *resizing = effect;
740 w = resizing->from.w + (resizing->to.w * progress);
741 h = resizing->from.h + (resizing->to.h * progress);
743 EINA_LIST_FOREACH(transit->objs, elist, obj)
744 evas_object_resize(obj, w, h);
747 static Elm_Transit_Effect *
748 _transit_effect_resizing_context_new(Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
750 Elm_Transit_Effect_Resizing *resizing;
752 resizing = ELM_NEW(Elm_Transit_Effect_Resizing);
753 if (!resizing) return NULL;
755 resizing->from.w = from_w;
756 resizing->from.h = from_h;
757 resizing->to.w = to_w - from_w;
758 resizing->to.h = to_h - from_h;
763 EAPI Elm_Transit_Effect *
764 elm_transit_effect_resizing_add(Elm_Transit *transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
766 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
767 Elm_Transit_Effect *effect = _transit_effect_resizing_context_new(from_w, from_h, to_w, to_h);
771 ERR("Failed to allocate resizing effect! : transit=%p", transit);
774 elm_transit_effect_add(transit,
775 _transit_effect_resizing_op, effect,
776 _transit_effect_resizing_context_free);
780 ///////////////////////////////////////////////////////////////////////////
782 ///////////////////////////////////////////////////////////////////////////
783 typedef struct _Elm_Transit_Effect_Translation Elm_Transit_Effect_Translation;
784 typedef struct _Elm_Transit_Effect_Translation_Node Elm_Transit_Effect_Translation_Node;
786 struct _Elm_Transit_Effect_Translation_Node
792 struct _Elm_Transit_Effect_Translation
794 struct _position_variation {
801 _translation_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
803 Elm_Transit_Effect_Translation *translation = data;
805 Elm_Transit_Effect_Translation_Node *translation_node;
807 EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
809 if (translation_node->obj != obj) continue;
810 translation->nodes = eina_list_remove_list(translation->nodes, elist);
811 free(translation_node);
817 _translation_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Translation *translation)
819 Elm_Transit_Effect_Translation_Node *translation_node;
820 const Eina_List *elist;
822 Eina_List *data_list = NULL;
823 const Eina_List *objs = elm_transit_objects_get(transit);
825 EINA_LIST_FOREACH(objs, elist, obj)
827 translation_node = ELM_NEW(Elm_Transit_Effect_Translation_Node);
828 if (!translation_node)
830 eina_list_free(data_list);
833 translation_node->obj = obj;
834 evas_object_geometry_get(obj, &(translation_node->x),
835 &(translation_node->y), NULL, NULL);
836 data_list = eina_list_append(data_list, translation_node);
837 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
838 _translation_object_del_cb, translation);
844 _transit_effect_translation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
846 EINA_SAFETY_ON_NULL_RETURN(effect);
847 Elm_Transit_Effect_Translation *translation = effect;
848 Eina_List *elist, *elist_next;
849 Elm_Transit_Effect_Translation_Node *translation_node;
851 EINA_LIST_FOREACH_SAFE(translation->nodes,
852 elist, elist_next, translation_node)
854 evas_object_event_callback_del(translation_node->obj,
855 EVAS_CALLBACK_DEL, _translation_object_del_cb);
856 translation->nodes = eina_list_remove_list(translation->nodes, elist);
857 free(translation_node);
863 _transit_effect_translation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress __UNUSED__)
865 EINA_SAFETY_ON_NULL_RETURN(effect);
866 EINA_SAFETY_ON_NULL_RETURN(transit);
868 Elm_Transit_Effect_Translation *translation = effect;
869 Elm_Transit_Effect_Translation_Node *translation_node;
872 if (!translation->nodes)
873 translation->nodes = _translation_nodes_build(transit, translation);
875 EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
877 x = translation_node->x + translation->from.dx
878 + (translation->to.dx * progress);
879 y = translation_node->y + translation->from.dy
880 + (translation->to.dy * progress);
881 evas_object_move(translation_node->obj, x, y);
885 static Elm_Transit_Effect *
886 _transit_effect_translation_context_new(Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
888 Elm_Transit_Effect_Translation *translation;
890 translation = ELM_NEW(Elm_Transit_Effect_Translation);
891 if (!translation) return NULL;
893 translation->from.dx = from_dx;
894 translation->from.dy = from_dy;
895 translation->to.dx = to_dx - from_dx;
896 translation->to.dy = to_dy - from_dy;
901 EAPI Elm_Transit_Effect *
902 elm_transit_effect_translation_add(Elm_Transit *transit, Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
904 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
905 Elm_Transit_Effect *effect = _transit_effect_translation_context_new(from_dx, from_dy, to_dx, to_dy);
909 ERR("Failed to allocate translation effect! : transit=%p", transit);
912 elm_transit_effect_add(transit,
913 _transit_effect_translation_op, effect,
914 _transit_effect_translation_context_free);
918 ///////////////////////////////////////////////////////////////////////////
920 ///////////////////////////////////////////////////////////////////////////
921 typedef struct _Elm_Transit_Effect_Zoom Elm_Transit_Effect_Zoom;
923 struct _Elm_Transit_Effect_Zoom
929 _transit_effect_zoom_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
931 Elm_Transit_Effect_Zoom *zoom = effect;
936 _transit_effect_zoom_op(Elm_Transit_Effect *effect, Elm_Transit *transit , double progress)
938 EINA_SAFETY_ON_NULL_RETURN(effect);
939 EINA_SAFETY_ON_NULL_RETURN(transit);
942 Elm_Transit_Effect_Zoom *zoom = effect;
944 Evas_Coord x, y, w, h;
946 map = evas_map_new(4);
949 EINA_LIST_FOREACH(transit->objs, elist, obj)
951 evas_object_geometry_get(obj, &x, &y, &w, &h);
952 evas_map_util_points_populate_from_object_full(map, obj, zoom->from +
953 (progress * zoom->to));
954 evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
955 evas_object_map_set(obj, map);
956 evas_object_map_enable_set(obj, EINA_TRUE);
961 static Elm_Transit_Effect *
962 _transit_effect_zoom_context_new(float from_rate, float to_rate)
964 Elm_Transit_Effect_Zoom *zoom;
966 zoom = ELM_NEW(Elm_Transit_Effect_Zoom);
967 if (!zoom) return NULL;
969 zoom->from = (_TRANSIT_FOCAL - (from_rate * _TRANSIT_FOCAL)) * (1 / from_rate);
970 zoom->to = ((_TRANSIT_FOCAL - (to_rate * _TRANSIT_FOCAL)) * (1 / to_rate)) - zoom->from;
975 EAPI Elm_Transit_Effect *
976 elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate)
978 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
979 Elm_Transit_Effect *effect = _transit_effect_zoom_context_new(from_rate, to_rate);
983 ERR("Failed to allocate zoom effect! : transit=%p", transit);
986 elm_transit_effect_add(transit,
987 _transit_effect_zoom_op, effect,
988 _transit_effect_zoom_context_free);
992 ///////////////////////////////////////////////////////////////////////////
994 ///////////////////////////////////////////////////////////////////////////
995 typedef struct _Elm_Transit_Effect_Flip Elm_Transit_Effect_Flip;
997 struct _Elm_Transit_Effect_Flip
999 Elm_Transit_Effect_Flip_Axis axis;
1004 _transit_effect_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
1006 EINA_SAFETY_ON_NULL_RETURN(effect);
1007 EINA_SAFETY_ON_NULL_RETURN(transit);
1008 Elm_Transit_Effect_Flip *flip = effect;
1009 Evas_Object *front, *back;
1011 int count = eina_list_count(transit->objs);
1013 for (i = 0; i < (count - 1); i += 2)
1015 front = eina_list_nth(transit->objs, i);
1016 back = eina_list_nth(transit->objs, i+1);
1017 evas_object_map_enable_set(front, EINA_FALSE);
1018 evas_object_map_enable_set(back, EINA_FALSE);
1024 _transit_effect_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1026 EINA_SAFETY_ON_NULL_RETURN(effect);
1027 EINA_SAFETY_ON_NULL_RETURN(transit);
1028 Evas_Object *obj, *front, *back;
1030 Elm_Transit_Effect_Flip *flip = effect;
1033 Evas_Coord x, y, w, h;
1035 map = evas_map_new(4);
1038 if (flip->cw) degree = (float)(progress * 180);
1039 else degree = (float)(progress * -180);
1041 count = eina_list_count(transit->objs);
1043 for (i = 0; i < (count - 1); i += 2)
1045 Evas_Coord half_w, half_h;
1047 front = eina_list_nth(transit->objs, i);
1048 back = eina_list_nth(transit->objs, i+1);
1050 if ((degree < 90) && (degree > -90))
1055 evas_object_hide(back);
1056 evas_object_show(front);
1064 evas_object_hide(front);
1065 evas_object_show(back);
1069 evas_map_util_points_populate_from_object_full(map, obj, 0);
1070 evas_object_geometry_get(obj, &x, &y, &w, &h);
1074 if (flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1076 if ((degree >= 90) || (degree <= -90))
1078 evas_map_point_image_uv_set(map, 0, w, 0);
1079 evas_map_point_image_uv_set(map, 1, 0, 0);
1080 evas_map_point_image_uv_set(map, 2, 0, h);
1081 evas_map_point_image_uv_set(map, 3, w, h);
1083 evas_map_util_3d_rotate(map, 0, degree,
1084 0, x + half_w, y + half_h, 0);
1088 if ((degree >= 90) || (degree <= -90))
1090 evas_map_point_image_uv_set(map, 0, 0, h);
1091 evas_map_point_image_uv_set(map, 1, w, h);
1092 evas_map_point_image_uv_set(map, 2, w, 0);
1093 evas_map_point_image_uv_set(map, 3, 0, 0);
1095 evas_map_util_3d_rotate(map, degree,
1096 0, 0, x + half_w, y + half_h, 0);
1098 evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
1099 evas_object_map_enable_set(front, EINA_TRUE);
1100 evas_object_map_enable_set(back, EINA_TRUE);
1101 evas_object_map_set(obj, map);
1106 static Elm_Transit_Effect *
1107 _transit_effect_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1109 Elm_Transit_Effect_Flip *flip;
1111 flip = ELM_NEW(Elm_Transit_Effect_Flip);
1112 if (!flip) return NULL;
1120 EAPI Elm_Transit_Effect *
1121 elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1123 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1124 Elm_Transit_Effect *effect = _transit_effect_flip_context_new(axis, cw);
1128 ERR("Failed to allocate flip effect! : transit=%p", transit);
1131 elm_transit_effect_add(transit,
1132 _transit_effect_flip_op, effect,
1133 _transit_effect_flip_context_free);
1137 ///////////////////////////////////////////////////////////////////////////
1138 //ResizableFlip Effect
1139 ///////////////////////////////////////////////////////////////////////////
1140 typedef struct _Elm_Transit_Effect_Resizable_Flip Elm_Transit_Effect_ResizableFlip;
1141 typedef struct _Elm_Transit_Effect_Resizable_Flip_Node Elm_Transit_Effect_ResizableFlip_Node;
1143 struct _Elm_Transit_Effect_Resizable_Flip_Node
1149 } from_pos, from_size, to_pos, to_size;
1152 struct _Elm_Transit_Effect_Resizable_Flip
1156 Elm_Transit_Effect_Flip_Axis axis;
1160 _resizable_flip_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1162 Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
1164 Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1166 EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1168 if (resizable_flip_node->front == obj)
1169 evas_object_event_callback_del(resizable_flip_node->back,
1170 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1171 else if (resizable_flip_node->back == obj)
1172 evas_object_event_callback_del(resizable_flip_node->front,
1173 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1176 resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1178 free(resizable_flip_node);
1184 _resizable_flip_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_ResizableFlip *resizable_flip)
1186 Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1187 Eina_List *data_list = NULL;
1188 Evas_Coord front_x, front_y, front_w, front_h;
1189 Evas_Coord back_x, back_y, back_w, back_h;
1192 count = eina_list_count(transit->objs);
1193 for (i = 0; i < (count - 1); i += 2)
1195 resizable_flip_node = ELM_NEW(Elm_Transit_Effect_ResizableFlip_Node);
1196 if (!resizable_flip_node)
1198 eina_list_free(data_list);
1202 resizable_flip_node->front = eina_list_nth(transit->objs, i);
1203 resizable_flip_node->back = eina_list_nth(transit->objs, i+1);
1205 evas_object_geometry_get(resizable_flip_node->front,
1206 &front_x, &front_y, &front_w, &front_h);
1207 evas_object_geometry_get(resizable_flip_node->back,
1208 &back_x, &back_y, &back_w, &back_h);
1210 resizable_flip_node->from_pos.x = front_x;
1211 resizable_flip_node->from_pos.y = front_y;
1212 resizable_flip_node->to_pos.x = back_x - front_x;
1213 resizable_flip_node->to_pos.y = back_y - front_y;
1215 resizable_flip_node->from_size.x = front_w;
1216 resizable_flip_node->from_size.y = front_h;
1217 resizable_flip_node->to_size.x = back_w - front_w;
1218 resizable_flip_node->to_size.y = back_h - front_h;
1220 data_list = eina_list_append(data_list, resizable_flip_node);
1222 evas_object_event_callback_add(resizable_flip_node->back,
1223 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1224 evas_object_event_callback_add(resizable_flip_node->front,
1225 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1232 _set_image_uv_by_axis_y(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
1234 if ((degree >= 90) || (degree <= -90))
1236 evas_map_point_image_uv_set(map, 0,
1237 (flip->from_size.x * 2) + flip->to_size.x,
1239 evas_map_point_image_uv_set(map, 1, 0, 0);
1240 evas_map_point_image_uv_set(map, 2, 0,
1241 (flip->from_size.y * 2) + flip->to_size.y);
1242 evas_map_point_image_uv_set(map, 3,
1243 (flip->from_size.x * 2) + flip->to_size.x,
1244 (flip->from_size.y * 2) + flip->to_size.y);
1248 evas_map_point_image_uv_set(map, 0, 0, 0);
1249 evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1250 evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1252 evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1257 _set_image_uv_by_axis_x(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
1259 if ((degree >= 90) || (degree <= -90))
1261 evas_map_point_image_uv_set(map, 0, 0,
1262 (flip->from_size.y * 2) + flip->to_size.y);
1263 evas_map_point_image_uv_set(map, 1,
1264 (flip->from_size.x * 2) + flip->to_size.x,
1265 (flip->from_size.y * 2) + flip->to_size.y);
1266 evas_map_point_image_uv_set(map, 2,
1267 (flip->from_size.x * 2) + flip->to_size.x,
1269 evas_map_point_image_uv_set(map, 3, 0, 0);
1273 evas_map_point_image_uv_set(map, 0, 0, 0);
1274 evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1275 evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1277 evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1282 _transit_effect_resizable_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1284 EINA_SAFETY_ON_NULL_RETURN(effect);
1286 Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
1287 Eina_List *elist, *elist_next;
1288 Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1290 EINA_LIST_FOREACH_SAFE(resizable_flip->nodes,
1291 elist, elist_next, resizable_flip_node)
1293 evas_object_map_enable_set(resizable_flip_node->front, EINA_FALSE);
1294 evas_object_map_enable_set(resizable_flip_node->back, EINA_FALSE);
1296 resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1299 evas_object_event_callback_del(resizable_flip_node->back,
1300 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1301 evas_object_event_callback_del(resizable_flip_node->front,
1302 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1303 free(resizable_flip_node);
1305 free(resizable_flip);
1309 _transit_effect_resizable_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
1311 EINA_SAFETY_ON_NULL_RETURN(effect);
1316 Evas_Coord half_w, half_h;
1317 Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
1318 Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1321 map = evas_map_new(4);
1324 if (resizable_flip->cw) degree = (float)(progress * 180);
1325 else degree = (float)(progress * -180);
1327 if (!resizable_flip->nodes)
1328 resizable_flip->nodes = _resizable_flip_nodes_build(transit,
1331 EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1333 if ((degree < 90) && (degree > -90))
1335 obj = resizable_flip_node->front;
1336 if (resizable_flip_node->front != resizable_flip_node->back)
1338 evas_object_hide(resizable_flip_node->back);
1339 evas_object_show(resizable_flip_node->front);
1344 obj = resizable_flip_node->back;
1345 if (resizable_flip_node->front != resizable_flip_node->back)
1347 evas_object_hide(resizable_flip_node->front);
1348 evas_object_show(resizable_flip_node->back);
1352 x = resizable_flip_node->from_pos.x +
1353 (resizable_flip_node->to_pos.x * progress);
1354 y = resizable_flip_node->from_pos.y +
1355 (resizable_flip_node->to_pos.y * progress);
1356 w = resizable_flip_node->from_size.x +
1357 (resizable_flip_node->to_size.x * progress);
1358 h = resizable_flip_node->from_size.y +
1359 (resizable_flip_node->to_size.y * progress);
1360 evas_map_point_coord_set(map, 0, x, y, 0);
1361 evas_map_point_coord_set(map, 1, x + w, y, 0);
1362 evas_map_point_coord_set(map, 2, x + w, y + h, 0);
1363 evas_map_point_coord_set(map, 3, x, y + h, 0);
1365 half_w = (Evas_Coord)(w / 2);
1366 half_h = (Evas_Coord)(h / 2);
1368 if (resizable_flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1370 _set_image_uv_by_axis_y(map, resizable_flip_node, degree);
1371 evas_map_util_3d_rotate(map, 0, degree,
1372 0, x + half_w, y + half_h, 0);
1376 _set_image_uv_by_axis_x(map, resizable_flip_node, degree);
1377 evas_map_util_3d_rotate(map, degree, 0,
1378 0, x + half_w, y + half_h, 0);
1381 evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
1382 evas_object_map_enable_set(resizable_flip_node->front, EINA_TRUE);
1383 evas_object_map_enable_set(resizable_flip_node->back, EINA_TRUE);
1384 evas_object_map_set(obj, map);
1389 static Elm_Transit_Effect *
1390 _transit_effect_resizable_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1392 Elm_Transit_Effect_ResizableFlip *resizable_flip;
1394 resizable_flip = ELM_NEW(Elm_Transit_Effect_ResizableFlip);
1395 if (!resizable_flip) return NULL;
1397 resizable_flip->cw = cw;
1398 resizable_flip->axis = axis;
1400 return resizable_flip;
1403 EAPI Elm_Transit_Effect *
1404 elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1406 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1407 Elm_Transit_Effect *effect = _transit_effect_resizable_flip_context_new(axis, cw);
1411 ERR("Failed to allocate resizable_flip effect! : transit=%p", transit);
1414 elm_transit_effect_add(transit,
1415 _transit_effect_resizable_flip_op, effect,
1416 _transit_effect_resizable_flip_context_free);
1420 ///////////////////////////////////////////////////////////////////////////
1422 ///////////////////////////////////////////////////////////////////////////
1423 typedef struct _Elm_Transit_Effect_Wipe Elm_Transit_Effect_Wipe;
1425 struct _Elm_Transit_Effect_Wipe
1427 Elm_Transit_Effect_Wipe_Type type;
1428 Elm_Transit_Effect_Wipe_Dir dir;
1432 _elm_fx_wipe_hide(Evas_Map * map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1438 case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1439 w2 = w - (w * progress);
1441 evas_map_point_image_uv_set(map, 0, 0, 0);
1442 evas_map_point_image_uv_set(map, 1, w2, 0);
1443 evas_map_point_image_uv_set(map, 2, w2, h);
1444 evas_map_point_image_uv_set(map, 3, 0, h);
1445 evas_map_point_coord_set(map, 0, x, y, 0);
1446 evas_map_point_coord_set(map, 1, x + w2, y, 0);
1447 evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1448 evas_map_point_coord_set(map, 3, x, h2, 0);
1450 case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1451 w2 = (w * progress);
1453 evas_map_point_image_uv_set(map, 0, w2, 0);
1454 evas_map_point_image_uv_set(map, 1, w, 0);
1455 evas_map_point_image_uv_set(map, 2, w, h);
1456 evas_map_point_image_uv_set(map, 3, w2, h);
1457 evas_map_point_coord_set(map, 0, x + w2, y, 0);
1458 evas_map_point_coord_set(map, 1, x + w, y, 0);
1459 evas_map_point_coord_set(map, 2, x + w, h2, 0);
1460 evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1462 case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1464 h2 = h - (h * progress);
1465 evas_map_point_image_uv_set(map, 0, 0, 0);
1466 evas_map_point_image_uv_set(map, 1, w, 0);
1467 evas_map_point_image_uv_set(map, 2, w, h2);
1468 evas_map_point_image_uv_set(map, 3, 0, h2);
1469 evas_map_point_coord_set(map, 0, x, y, 0);
1470 evas_map_point_coord_set(map, 1, w2, y, 0);
1471 evas_map_point_coord_set(map, 2, w2, y+h2, 0);
1472 evas_map_point_coord_set(map, 3, x, y+h2, 0);
1474 case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1476 h2 = (h * progress);
1477 evas_map_point_image_uv_set(map, 0, 0, h2);
1478 evas_map_point_image_uv_set(map, 1, w, h2);
1479 evas_map_point_image_uv_set(map, 2, w, h);
1480 evas_map_point_image_uv_set(map, 3, 0, h);
1481 evas_map_point_coord_set(map, 0, x, y + h2, 0);
1482 evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1483 evas_map_point_coord_set(map, 2, w2, y + h, 0);
1484 evas_map_point_coord_set(map, 3, x, y + h, 0);
1489 evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
1493 _elm_fx_wipe_show(Evas_Map *map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1499 case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1500 w2 = (w - (w * progress));
1502 evas_map_point_image_uv_set(map, 0, w2, 0);
1503 evas_map_point_image_uv_set(map, 1, w, 0);
1504 evas_map_point_image_uv_set(map, 2, w, h);
1505 evas_map_point_image_uv_set(map, 3, w2, h);
1506 evas_map_point_coord_set(map, 0, x + w2, y, 0);
1507 evas_map_point_coord_set(map, 1, w, y, 0);
1508 evas_map_point_coord_set(map, 2, w, h2, 0);
1509 evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1511 case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1512 w2 = (w * progress);
1514 evas_map_point_image_uv_set(map, 0, 0, 0);
1515 evas_map_point_image_uv_set(map, 1, w2, 0);
1516 evas_map_point_image_uv_set(map, 2, w2, h);
1517 evas_map_point_image_uv_set(map, 3, 0, h);
1518 evas_map_point_coord_set(map, 0, x, y, 0);
1519 evas_map_point_coord_set(map, 1, x + w2, y, 0);
1520 evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1521 evas_map_point_coord_set(map, 3, x, h2, 0);
1523 case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1525 h2 = (h - (h * progress));
1526 evas_map_point_image_uv_set(map, 0, 0, h2);
1527 evas_map_point_image_uv_set(map, 1, w, h2);
1528 evas_map_point_image_uv_set(map, 2, w, h);
1529 evas_map_point_image_uv_set(map, 3, 0, h);
1530 evas_map_point_coord_set(map, 0, x, y + h2, 0);
1531 evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1532 evas_map_point_coord_set(map, 2, w2, y + h, 0);
1533 evas_map_point_coord_set(map, 3, x, y + h, 0);
1535 case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1537 h2 = (h * progress);
1538 evas_map_point_image_uv_set(map, 0, 0, 0);
1539 evas_map_point_image_uv_set(map, 1, w, 0);
1540 evas_map_point_image_uv_set(map, 2, w, h2);
1541 evas_map_point_image_uv_set(map, 3, 0, h2);
1542 evas_map_point_coord_set(map, 0, x, y, 0);
1543 evas_map_point_coord_set(map, 1, w2, y, 0);
1544 evas_map_point_coord_set(map, 2, w2, y + h2, 0);
1545 evas_map_point_coord_set(map, 3, x, y + h2, 0);
1550 evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
1554 _transit_effect_wipe_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
1556 EINA_SAFETY_ON_NULL_RETURN(effect);
1557 EINA_SAFETY_ON_NULL_RETURN(transit);
1560 Elm_Transit_Effect_Wipe *wipe = effect;
1561 Eina_Bool reverse = elm_transit_auto_reverse_get(transit);
1563 EINA_LIST_FOREACH(transit->objs, elist, obj)
1565 if ((wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW && !reverse)
1566 || (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE && reverse))
1567 evas_object_show(obj);
1568 else evas_object_hide(obj);
1569 evas_object_map_enable_set(obj, EINA_FALSE);
1576 _transit_effect_wipe_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1578 EINA_SAFETY_ON_NULL_RETURN(effect);
1579 EINA_SAFETY_ON_NULL_RETURN(transit);
1580 Elm_Transit_Effect_Wipe *wipe = effect;
1582 Evas_Coord _x, _y, _w, _h;
1586 map = evas_map_new(4);
1589 EINA_LIST_FOREACH(transit->objs, elist, obj)
1591 evas_object_geometry_get(obj, &_x, &_y, &_w, &_h);
1593 if (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW)
1594 _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)progress);
1596 _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)progress);
1598 evas_object_map_enable_set(obj, EINA_TRUE);
1599 evas_object_map_set(obj, map);
1604 static Elm_Transit_Effect *
1605 _transit_effect_wipe_context_new(Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
1607 Elm_Transit_Effect_Wipe *wipe;
1609 wipe = ELM_NEW(Elm_Transit_Effect_Wipe);
1610 if (!wipe) return NULL;
1619 elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
1621 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1622 void *effect = _transit_effect_wipe_context_new(type, dir);
1626 ERR("Failed to allocate wipe effect! : transit=%p", transit);
1629 elm_transit_effect_add(transit,
1630 _transit_effect_wipe_op, effect,
1631 _transit_effect_wipe_context_free);
1635 ///////////////////////////////////////////////////////////////////////////
1637 ///////////////////////////////////////////////////////////////////////////
1638 typedef struct _Elm_Transit_Effect_Color Elm_Transit_Effect_Color;
1640 struct _Elm_Transit_Effect_Color
1642 struct _unsigned_color {
1643 unsigned int r, g, b, a;
1645 struct _signed_color {
1651 _transit_effect_color_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1653 Elm_Transit_Effect_Color *color = effect;
1658 _transit_effect_color_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1660 EINA_SAFETY_ON_NULL_RETURN(effect);
1661 EINA_SAFETY_ON_NULL_RETURN(transit);
1662 Elm_Transit_Effect_Color *color = effect;
1665 unsigned int r, g, b, a;
1667 r = (color->from.r + (int)((float)color->to.r * progress));
1668 g = (color->from.g + (int)((float)color->to.g * progress));
1669 b = (color->from.b + (int)((float)color->to.b * progress));
1670 a = (color->from.a + (int)((float)color->to.a * progress));
1672 EINA_LIST_FOREACH(transit->objs, elist, obj)
1673 evas_object_color_set(obj, r, g, b, a);
1676 static Elm_Transit_Effect *
1677 _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)
1679 Elm_Transit_Effect_Color *color;
1681 color = ELM_NEW(Elm_Transit_Effect_Color);
1682 if (!color) return NULL;
1684 color->from.r = from_r;
1685 color->from.g = from_g;
1686 color->from.b = from_b;
1687 color->from.a = from_a;
1688 color->to.r = to_r - from_r;
1689 color->to.g = to_g - from_g;
1690 color->to.b = to_b - from_b;
1691 color->to.a = to_a - from_a;
1696 EAPI Elm_Transit_Effect *
1697 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)
1699 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1700 Elm_Transit_Effect *effect = _transit_effect_color_context_new(from_r, from_g, from_b, from_a, to_r, to_g, to_b, to_a);
1704 ERR("Failed to allocate color effect! : transit=%p", transit);
1707 elm_transit_effect_add(transit,
1708 _transit_effect_color_op, effect,
1709 _transit_effect_color_context_free);
1713 ///////////////////////////////////////////////////////////////////////////
1715 ///////////////////////////////////////////////////////////////////////////
1716 typedef struct _Elm_Transit_Effect_Fade Elm_Transit_Effect_Fade;
1717 typedef struct _Elm_Transit_Effect_Fade_Node Elm_Transit_Effect_Fade_Node;
1719 struct _Elm_Transit_Effect_Fade_Node
1721 Evas_Object *before;
1723 struct _signed_color before_color, after_color;
1726 Eina_Bool inversed : 1;
1729 struct _Elm_Transit_Effect_Fade
1735 _fade_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1737 Elm_Transit_Effect_Fade *fade = data;
1739 Elm_Transit_Effect_Fade_Node *fade_node;
1741 EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
1743 if (fade_node->before == obj)
1744 evas_object_event_callback_del(fade_node->after,
1745 EVAS_CALLBACK_DEL, _fade_object_del_cb);
1746 else if (fade_node->after == obj)
1747 evas_object_event_callback_del(fade_node->before,
1748 EVAS_CALLBACK_DEL, _fade_object_del_cb);
1751 fade->nodes = eina_list_remove_list(fade->nodes, elist);
1758 _fade_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Fade *fade_data)
1760 Elm_Transit_Effect_Fade_Node *fade;
1761 Eina_List *data_list = NULL;
1764 count = eina_list_count(transit->objs);
1765 for (i = 0; i < count; i += 2)
1767 fade = ELM_NEW(Elm_Transit_Effect_Fade_Node);
1770 eina_list_free(data_list);
1774 fade->before = eina_list_nth(transit->objs, i);
1775 fade->after = eina_list_nth(transit->objs, i+1);
1777 evas_object_color_get(fade->before,
1778 &fade->before_color.r, &fade->before_color.g,
1779 &fade->before_color.b, &fade->before_color.a);
1780 evas_object_color_get(fade->after,
1781 &fade->after_color.r, &fade->after_color.g,
1782 &fade->after_color.b, &fade->after_color.a);
1784 fade->before_alpha = (255 - fade->before_color.a);
1785 fade->after_alpha = (255 - fade->after_color.a);
1787 data_list = eina_list_append(data_list, fade);
1789 evas_object_event_callback_add(fade->before,
1790 EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
1791 evas_object_event_callback_add(fade->after,
1792 EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
1798 _transit_effect_fade_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1800 EINA_SAFETY_ON_NULL_RETURN(effect);
1801 Elm_Transit_Effect_Fade *fade = effect;
1802 Elm_Transit_Effect_Fade_Node *fade_node;
1803 Eina_List *elist, *elist_next;
1805 EINA_LIST_FOREACH_SAFE(fade->nodes, elist, elist_next, fade_node)
1807 evas_object_color_set(fade_node->before, fade_node->before_color.r,
1808 fade_node->before_color.g,
1809 fade_node->before_color.b,
1810 fade_node->before_color.a);
1811 evas_object_color_set(fade_node->after, fade_node->after_color.r,
1812 fade_node->after_color.g,
1813 fade_node->after_color.b,
1814 fade_node->after_color.a);
1816 fade->nodes = eina_list_remove_list(fade->nodes, elist);
1817 evas_object_event_callback_del(fade_node->before,
1818 EVAS_CALLBACK_DEL, _fade_object_del_cb);
1819 evas_object_event_callback_del(fade_node->after,
1820 EVAS_CALLBACK_DEL, _fade_object_del_cb);
1828 _transit_effect_fade_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
1830 EINA_SAFETY_ON_NULL_RETURN(effect);
1831 Elm_Transit_Effect_Fade *fade = effect;
1833 Elm_Transit_Effect_Fade_Node *fade_node;
1837 fade->nodes = _fade_nodes_build(transit, fade);
1839 EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
1843 if (!fade_node->inversed)
1845 evas_object_hide(fade_node->after);
1846 evas_object_show(fade_node->before);
1847 fade_node->inversed = EINA_TRUE;
1850 _progress = (1 - (progress * 2));
1852 evas_object_color_set(fade_node->before,
1853 fade_node->before_color.r * _progress,
1854 fade_node->before_color.g * _progress,
1855 fade_node->before_color.b * _progress,
1856 fade_node->before_color.a +
1857 fade_node->before_alpha * (1 - _progress));
1861 if (fade_node->inversed)
1863 evas_object_hide(fade_node->before);
1864 evas_object_show(fade_node->after);
1865 fade_node->inversed = EINA_FALSE;
1868 _progress = ((progress - 0.5) * 2);
1870 evas_object_color_set(fade_node->after,
1871 fade_node->after_color.r * _progress,
1872 fade_node->after_color.g * _progress,
1873 fade_node->after_color.b * _progress,
1874 fade_node->after_color.a +
1875 fade_node->after_alpha * (1 - _progress));
1880 static Elm_Transit_Effect *
1881 _transit_effect_fade_context_new(void)
1883 Elm_Transit_Effect_Fade *fade;
1884 fade = ELM_NEW(Elm_Transit_Effect_Fade);
1885 if (!fade) return NULL;
1889 EAPI Elm_Transit_Effect *
1890 elm_transit_effect_fade_add(Elm_Transit *transit)
1892 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1894 Elm_Transit_Effect *effect = _transit_effect_fade_context_new();
1898 ERR("Failed to allocate fade effect! : transit=%p", transit);
1901 elm_transit_effect_add(transit,
1902 _transit_effect_fade_op, effect,
1903 _transit_effect_fade_context_free);
1907 ///////////////////////////////////////////////////////////////////////////
1909 ///////////////////////////////////////////////////////////////////////////
1910 typedef struct _Elm_Transit_Effect_Blend Elm_Transit_Effect_Blend;
1911 typedef struct _Elm_Transit_Effect_Blend_Node Elm_Transit_Effect_Blend_Node;
1913 struct _Elm_Transit_Effect_Blend_Node
1915 Evas_Object *before;
1917 struct _signed_color from, to;
1920 struct _Elm_Transit_Effect_Blend
1926 _blend_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1928 Elm_Transit_Effect_Blend *blend = data;
1930 Elm_Transit_Effect_Blend_Node *blend_node;
1932 EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
1934 if (blend_node->after == obj)
1935 evas_object_event_callback_del(blend_node->before,
1936 EVAS_CALLBACK_DEL, _blend_object_del_cb);
1937 else if (blend_node->before == obj)
1938 evas_object_event_callback_del(blend_node->after,
1939 EVAS_CALLBACK_DEL, _blend_object_del_cb);
1942 blend->nodes = eina_list_remove_list(blend->nodes, elist);
1949 _blend_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Blend *blend)
1951 Elm_Transit_Effect_Blend_Node *blend_node;
1952 Eina_List *data_list = NULL;
1955 count = eina_list_count(transit->objs);
1956 for (i = 0; i < (count - 1); i += 2)
1958 blend_node = ELM_NEW(Elm_Transit_Effect_Blend_Node);
1961 eina_list_free(data_list);
1965 blend_node->before = eina_list_nth(transit->objs, i);
1966 blend_node->after = eina_list_nth(transit->objs, i + 1);
1967 evas_object_show(blend_node->before);
1968 evas_object_show(blend_node->after);
1970 evas_object_color_get(blend_node->before, &blend_node->from.r,
1971 &blend_node->from.g, &blend_node->from.b,
1972 &blend_node->from.a);
1973 evas_object_color_get(blend_node->after, &blend_node->to.r,
1974 &blend_node->to.g, &blend_node->to.b,
1977 data_list = eina_list_append(data_list, blend_node);
1979 evas_object_event_callback_add(blend_node->before,
1980 EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
1981 evas_object_event_callback_add(blend_node->after,
1982 EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
1988 _transit_effect_blend_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1990 EINA_SAFETY_ON_NULL_RETURN(effect);
1991 Elm_Transit_Effect_Blend *blend = effect;
1992 Elm_Transit_Effect_Blend_Node *blend_node;
1993 Eina_List *elist, *elist_next;
1995 EINA_LIST_FOREACH_SAFE(blend->nodes, elist, elist_next, blend_node)
1997 evas_object_color_set(blend_node->before,
1998 blend_node->from.r, blend_node->from.g,
1999 blend_node->from.b, blend_node->from.a);
2000 evas_object_color_set(blend_node->after, blend_node->to.r,
2001 blend_node->to.g, blend_node->to.b,
2004 if (elm_transit_auto_reverse_get(transit))
2005 evas_object_hide(blend_node->after);
2007 evas_object_hide(blend_node->before);
2009 blend->nodes = eina_list_remove_list(blend->nodes, elist);
2011 evas_object_event_callback_del(blend_node->before,
2012 EVAS_CALLBACK_DEL, _blend_object_del_cb);
2013 evas_object_event_callback_del(blend_node->after,
2014 EVAS_CALLBACK_DEL, _blend_object_del_cb);
2021 _transit_effect_blend_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2023 EINA_SAFETY_ON_NULL_RETURN(effect);
2024 EINA_SAFETY_ON_NULL_RETURN(transit);
2025 Elm_Transit_Effect_Blend *blend = effect;
2026 Elm_Transit_Effect_Blend_Node *blend_node;
2029 if (!blend->nodes) blend->nodes = _blend_nodes_build(transit, blend);
2031 EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
2033 evas_object_color_set(blend_node->before,
2034 (int)(blend_node->from.r * (1 - progress)),
2035 (int)(blend_node->from.g * (1 - progress)),
2036 (int)(blend_node->from.b * (1 - progress)),
2037 (int)(blend_node->from.a * (1 - progress)));
2038 evas_object_color_set(blend_node->after,
2039 (int)(blend_node->to.r * progress),
2040 (int)(blend_node->to.g * progress),
2041 (int)(blend_node->to.b * progress),
2042 (int)(blend_node->to.a * progress));
2046 static Elm_Transit_Effect *
2047 _transit_effect_blend_context_new(void)
2049 Elm_Transit_Effect_Blend *blend;
2051 blend = ELM_NEW(Elm_Transit_Effect_Blend);
2052 if (!blend) return NULL;
2056 EAPI Elm_Transit_Effect *
2057 elm_transit_effect_blend_add(Elm_Transit *transit)
2059 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2060 Elm_Transit_Effect *effect = _transit_effect_blend_context_new();
2064 ERR("Failed to allocate blend effect! : transit=%p", transit);
2067 elm_transit_effect_add(transit,
2068 _transit_effect_blend_op, effect,
2069 _transit_effect_blend_context_free);
2073 ///////////////////////////////////////////////////////////////////////////
2075 ///////////////////////////////////////////////////////////////////////////
2076 typedef struct _Elm_Transit_Effect_Rotation Elm_Transit_Effect_Rotation;
2078 struct _Elm_Transit_Effect_Rotation
2084 _transit_effect_rotation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2086 Elm_Transit_Effect_Rotation *rotation = effect;
2091 _transit_effect_rotation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2093 EINA_SAFETY_ON_NULL_RETURN(effect);
2094 EINA_SAFETY_ON_NULL_RETURN(transit);
2095 Elm_Transit_Effect_Rotation *rotation = effect;
2097 Evas_Coord x, y, w, h;
2099 float half_w, half_h;
2103 map = evas_map_new(4);
2106 EINA_LIST_FOREACH(transit->objs, elist, obj)
2108 evas_map_util_points_populate_from_object_full(map, obj, 0);
2109 degree = rotation->from + (float)(progress * rotation->to);
2111 evas_object_geometry_get(obj, &x, &y, &w, &h);
2113 half_w = (float)w * 0.5;
2114 half_h = (float)h * 0.5;
2116 evas_map_util_rotate(map, degree, x + half_w, y + half_h);
2117 evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
2118 evas_object_map_enable_set(obj, EINA_TRUE);
2119 evas_object_map_set(obj, map);
2124 static Elm_Transit_Effect *
2125 _transit_effect_rotation_context_new(float from_degree, float to_degree)
2127 Elm_Transit_Effect_Rotation *rotation;
2129 rotation = ELM_NEW(Elm_Transit_Effect_Rotation);
2130 if (!rotation) return NULL;
2132 rotation->from = from_degree;
2133 rotation->to = to_degree - from_degree;
2138 EAPI Elm_Transit_Effect *
2139 elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree)
2141 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2142 Elm_Transit_Effect *effect = _transit_effect_rotation_context_new(from_degree, to_degree);
2146 ERR("Failed to allocate rotation effect! : transit=%p", transit);
2149 elm_transit_effect_add(transit,
2150 _transit_effect_rotation_op, effect,
2151 _transit_effect_rotation_context_free);
2155 ///////////////////////////////////////////////////////////////////////////
2156 //ImageAnimation Effect
2157 ///////////////////////////////////////////////////////////////////////////
2158 typedef struct _Elm_Transit_Effect_Image_Animation Elm_Transit_Effect_Image_Animation;
2160 struct _Elm_Transit_Effect_Image_Animation
2166 _transit_effect_image_animation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2168 EINA_SAFETY_ON_NULL_RETURN(effect);
2169 Elm_Transit_Effect_Image_Animation *image_animation = effect;
2171 Eina_List *elist, *elist_next;
2173 EINA_LIST_FOREACH_SAFE(image_animation->images, elist, elist_next, image)
2175 image_animation->images =
2176 eina_list_remove_list(image_animation->images, elist);
2177 eina_stringshare_del(image);
2180 free(image_animation);
2184 _transit_effect_image_animation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2186 EINA_SAFETY_ON_NULL_RETURN(effect);
2187 EINA_SAFETY_ON_NULL_RETURN(transit);
2191 Elm_Transit_Effect_Image_Animation *image_animation = effect;
2192 unsigned int count = 0;
2195 type = eina_stringshare_add("icon");
2196 len = eina_list_count(image_animation->images);
2198 if (!len) count = floor(progress * len);
2199 else count = floor(progress * (len - 1));
2201 EINA_LIST_FOREACH(transit->objs, elist, obj)
2203 if (elm_widget_type_check(obj, type))
2204 elm_icon_file_set(obj,
2205 eina_list_nth(image_animation->images, count), NULL);
2208 eina_stringshare_del(type);
2211 static Elm_Transit_Effect *
2212 _transit_effect_image_animation_context_new(Eina_List *images)
2214 Elm_Transit_Effect_Image_Animation *image_animation;
2215 image_animation = ELM_NEW(Elm_Transit_Effect_Image_Animation);
2217 if (!image_animation) return NULL;
2218 image_animation->images = images;
2219 return image_animation;
2222 EAPI Elm_Transit_Effect *
2223 elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images)
2225 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2226 Elm_Transit_Effect *effect = _transit_effect_image_animation_context_new(images);
2230 ERR("Failed to allocate image_animation effect! : transit=%p", transit);
2233 elm_transit_effect_add(transit,
2234 _transit_effect_image_animation_op, effect,
2235 _transit_effect_image_animation_context_free);