#include "e_efx_private.h" struct E_Efx_Queue_Data { E_EFX *e; E_Efx_Queued_Effect effect; E_Efx_Effect_Speed speed; double time; E_Efx_End_Cb cb; void *data; Eina_List *subeffects; void *effect_data; Eina_Bool active : 1; }; static void _queue_advance(E_Efx_Queue_Data *eqd) { E_Efx_Queue_Data *run; Eina_List *l; INF("queue_advance: %p", eqd->e->obj); switch (eqd->effect.type) { case E_EFX_EFFECT_TYPE_ROTATE: e_efx_rotate(eqd->e->obj, eqd->speed, eqd->effect.effect.rotation.degrees, eqd->effect.effect.rotation.center, eqd->time, eqd->cb, eqd->data); eqd->effect_data = eqd->e->rotate_data; break; case E_EFX_EFFECT_TYPE_ZOOM: e_efx_zoom(eqd->e->obj, eqd->speed, eqd->effect.effect.zoom.start, eqd->effect.effect.zoom.end, eqd->effect.effect.zoom.center, eqd->time, eqd->cb, eqd->data); eqd->effect_data = eqd->e->zoom_data; break; case E_EFX_EFFECT_TYPE_MOVE: e_efx_move(eqd->e->obj, eqd->speed, &eqd->effect.effect.movement.point, eqd->time, eqd->cb, eqd->data); eqd->effect_data = eqd->e->move_data; break; case E_EFX_EFFECT_TYPE_PAN: e_efx_pan(eqd->e->obj, eqd->speed, &eqd->effect.effect.movement.point, eqd->time, eqd->cb, eqd->data); eqd->effect_data = eqd->e->pan_data; break; case E_EFX_EFFECT_TYPE_FADE: e_efx_fade(eqd->e->obj, eqd->speed, &eqd->effect.effect.fade.color, eqd->effect.effect.fade.alpha, eqd->time, eqd->cb, eqd->data); eqd->effect_data = eqd->e->fade_data; break; case E_EFX_EFFECT_TYPE_RESIZE: default: e_efx_resize(eqd->e->obj, eqd->speed, eqd->effect.effect.resize.point, eqd->effect.effect.resize.w, eqd->effect.effect.resize.h, eqd->time, eqd->cb, eqd->data); eqd->effect_data = eqd->e->resize_data; } eqd->active = EINA_TRUE; EINA_LIST_FOREACH(eqd->subeffects, l, run) _queue_advance(run); } void e_efx_queue_process(E_EFX *e) { E_Efx_Queue_Data *eqd; eqd = eina_list_data_get(e->queue); if (!eqd) return; if (eqd->active) return; _queue_advance(eqd); } void eqd_free(E_Efx_Queue_Data *eqd) { E_Efx_Queue_Data *sub; if (!eqd) return; if (eqd->effect.type == E_EFX_EFFECT_TYPE_ROTATE) free(eqd->effect.effect.rotation.center); else if (eqd->effect.type == E_EFX_EFFECT_TYPE_ZOOM) free(eqd->effect.effect.zoom.center); else if (eqd->effect.type == E_EFX_EFFECT_TYPE_RESIZE) free(eqd->effect.effect.resize.point); EINA_LIST_FREE(eqd->subeffects, sub) eqd_free(sub); free(eqd); } Eina_Bool e_efx_queue_complete(E_EFX *e, void *effect_data) { E_Efx_Queue_Data *eqd; eqd = eina_list_data_get(e->queue); if (!eqd) { e_efx_free(e); return EINA_FALSE; } DBG("%p: %p", e->obj, effect_data); if (eqd->effect_data != effect_data) return EINA_FALSE; e->queue = eina_list_remove_list(e->queue, e->queue); eqd_free(eqd); return !!e->queue; } E_Efx_Queue_Data * eqd_new(E_EFX *e, E_Efx_Effect_Speed speed, const E_Efx_Queued_Effect *effect, double total_time, E_Efx_End_Cb cb, const void *data) { E_Efx_Queue_Data *eqd; eqd = calloc(1, sizeof(E_Efx_Queue_Data)); memcpy(&eqd->effect, effect, sizeof(E_Efx_Queued_Effect)); eqd->e = e; if (effect->type == E_EFX_EFFECT_TYPE_ROTATE) { if (effect->effect.rotation.center) { eqd->effect.effect.rotation.center = malloc(sizeof(Evas_Point)); if (!eqd->effect.effect.rotation.center) goto error; memcpy(eqd->effect.effect.rotation.center, effect->effect.rotation.center, sizeof(Evas_Point)); } } else if (effect->type == E_EFX_EFFECT_TYPE_ZOOM) { if (effect->effect.zoom.center) { eqd->effect.effect.zoom.center = malloc(sizeof(Evas_Point)); if (!eqd->effect.effect.zoom.center) goto error; memcpy(eqd->effect.effect.zoom.center, effect->effect.zoom.center, sizeof(Evas_Point)); } } else if (effect->type == E_EFX_EFFECT_TYPE_RESIZE) { if (effect->effect.resize.point) { eqd->effect.effect.resize.point = malloc(sizeof(Evas_Point)); if (!eqd->effect.effect.resize.point) goto error; memcpy(eqd->effect.effect.resize.point, effect->effect.resize.point, sizeof(Evas_Point)); } } eqd->speed = speed; eqd->time = total_time; eqd->cb = cb; eqd->data = (void*)data; return eqd; error: free(eqd); e_efx_free(e); return NULL; } EAPI void e_efx_queue_run(Evas_Object *obj) { E_EFX *e; e = evas_object_data_get(obj, "e_efx-data"); if (!e) return; e_efx_queue_process(e); } EAPI E_Efx_Queue_Data * e_efx_queue_append(Evas_Object *obj, E_Efx_Effect_Speed speed, const E_Efx_Queued_Effect *effect, double total_time, E_Efx_End_Cb cb, const void *data) { E_EFX *e; E_Efx_Queue_Data *eqd; EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(effect, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL(total_time >= 0.0, NULL); if (effect->type > E_EFX_EFFECT_TYPE_RESIZE) return NULL; e = evas_object_data_get(obj, "e_efx-data"); if (!e) e = e_efx_new(obj); EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); eqd = eqd_new(e, speed, effect, total_time, cb, data); EINA_SAFETY_ON_NULL_RETURN_VAL(eqd, NULL); e->queue = eina_list_append(e->queue, eqd); return eqd; (void)e_efx_speed_str; } EAPI E_Efx_Queue_Data * e_efx_queue_prepend(Evas_Object *obj, E_Efx_Effect_Speed speed, const E_Efx_Queued_Effect *effect, double total_time, E_Efx_End_Cb cb, const void *data) { E_EFX *e; E_Efx_Queue_Data *eqd, *eqd2; EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(effect, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL(total_time >= 0.0, NULL); if (effect->type > E_EFX_EFFECT_TYPE_RESIZE) return NULL; e = evas_object_data_get(obj, "e_efx-data"); if (!e) e = e_efx_new(obj); EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); eqd = eqd_new(e, speed, effect, total_time, cb, data); EINA_SAFETY_ON_NULL_RETURN_VAL(eqd, NULL); if (e->queue) { eqd2 = eina_list_data_get(e->queue); if (eqd2->active) e->queue = eina_list_append_relative_list(e->queue, eqd, e->queue); else e->queue = eina_list_prepend(e->queue, eqd); } else e->queue = eina_list_append(e->queue, eqd); return eqd; (void)e_efx_speed_str; } EAPI void e_efx_queue_promote(Evas_Object *obj, E_Efx_Queue_Data *eqd) { E_EFX *e; EINA_SAFETY_ON_NULL_RETURN(obj); EINA_SAFETY_ON_NULL_RETURN(eqd); e = evas_object_data_get(obj, "e_efx-data"); EINA_SAFETY_ON_NULL_RETURN(e); EINA_SAFETY_ON_NULL_RETURN(e->queue); EINA_SAFETY_ON_TRUE_RETURN(eqd->active); if (e->queue->data == eqd) return; e->queue = eina_list_remove(e->queue, eqd); e->queue = eina_list_append_relative_list(e->queue, eqd, e->queue); } EAPI void e_efx_queue_demote(Evas_Object *obj, E_Efx_Queue_Data *eqd) { E_EFX *e; EINA_SAFETY_ON_NULL_RETURN(obj); EINA_SAFETY_ON_NULL_RETURN(eqd); e = evas_object_data_get(obj, "e_efx-data"); EINA_SAFETY_ON_NULL_RETURN(e); EINA_SAFETY_ON_NULL_RETURN(e->queue); EINA_SAFETY_ON_TRUE_RETURN(eqd->active); if (eina_list_last(e->queue)->data == eqd) return; e->queue = eina_list_demote_list(e->queue, eina_list_data_find_list(e->queue, eqd)); } EAPI void e_efx_queue_delete(Evas_Object *obj, E_Efx_Queue_Data *eqd) { E_EFX *e; EINA_SAFETY_ON_NULL_RETURN(obj); EINA_SAFETY_ON_NULL_RETURN(eqd); e = evas_object_data_get(obj, "e_efx-data"); EINA_SAFETY_ON_NULL_RETURN(e); EINA_SAFETY_ON_NULL_RETURN(e->queue); EINA_SAFETY_ON_TRUE_RETURN(eqd->active); e->queue = eina_list_remove(e->queue, eqd); eqd_free(eqd); } EAPI void e_efx_queue_clear(Evas_Object *obj) { E_EFX *e; E_Efx_Queue_Data *eqd; Eina_List *l, *ll; EINA_SAFETY_ON_NULL_RETURN(obj); e = evas_object_data_get(obj, "e_efx-data"); EINA_SAFETY_ON_NULL_RETURN(e); if (!e->queue) return; EINA_LIST_FOREACH_SAFE(e->queue, l, ll, eqd) { if (eqd->active) continue; e->queue = eina_list_remove_list(e->queue, l); eqd_free(eqd); } } EAPI Eina_Bool e_efx_queue_effect_attach(E_Efx_Queue_Data *eqd, E_Efx_Effect_Speed speed, const E_Efx_Queued_Effect *effect, double total_time, E_Efx_End_Cb cb, const void *data) { E_EFX *e; E_Efx_Queue_Data *sub; EINA_SAFETY_ON_NULL_RETURN_VAL(eqd, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(effect, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(total_time >= 0.0, EINA_FALSE); if (effect->type > E_EFX_EFFECT_TYPE_RESIZE) return EINA_FALSE; e = eqd->e; sub = eqd_new(e, speed, effect, total_time, cb, data); EINA_SAFETY_ON_NULL_RETURN_VAL(sub, EINA_FALSE); eqd->subeffects = eina_list_append(eqd->subeffects, sub); return EINA_TRUE; (void)e_efx_speed_str; }