diff options
author | Jaehyun Cho <jae_hyun.cho@samsung.com> | 2017-07-04 15:16:59 +0900 |
---|---|---|
committer | Jaehyun Cho <jae_hyun.cho@samsung.com> | 2017-08-18 12:06:01 +0900 |
commit | 2f15b916863f21911ed6771bf2ec42c5164564cb (patch) | |
tree | 785a2c161f9fc94c5a6026c969e4cd1c60df6e9c | |
parent | d5dda644ecb7179de2f9407089ee81a47f6fded8 (diff) | |
download | efl-2f15b916863f21911ed6771bf2ec42c5164564cb.tar.gz |
efl_animation: Support event animation
-rw-r--r-- | src/lib/evas/canvas/efl_animation_types.eot | 12 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_canvas_object.eo | 17 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_object_main.c | 322 | ||||
-rw-r--r-- | src/lib/evas/include/evas_private.h | 7 |
4 files changed, 357 insertions, 1 deletions
diff --git a/src/lib/evas/canvas/efl_animation_types.eot b/src/lib/evas/canvas/efl_animation_types.eot index 7c448dd5e7..b16e73056b 100644 --- a/src/lib/evas/canvas/efl_animation_types.eot +++ b/src/lib/evas/canvas/efl_animation_types.eot @@ -1,4 +1,14 @@ // ---------------------------------------------------------------------------- // All the below types are for Efl Animation -struct Efl.Animation.Instance.Animate_Event_Info; [[Information of animate event]]
\ No newline at end of file +struct Efl.Animation.Instance.Animate_Event_Info; [[Information of animate event]] + +enum Efl.Animation.Event_Type +{ + [[Animation event type]] + + show = 0, [["show" event type]] + hide, [["hide" event type]] + clicked, [["clicked" event type]] + count [[total count of event type]] +}
\ No newline at end of file diff --git a/src/lib/evas/canvas/efl_canvas_object.eo b/src/lib/evas/canvas/efl_canvas_object.eo index cf92e6f2c7..f14835bd5f 100644 --- a/src/lib/evas/canvas/efl_canvas_object.eo +++ b/src/lib/evas/canvas/efl_canvas_object.eo @@ -1,4 +1,5 @@ import efl_text_types; +import efl_animation_types; abstract Efl.Canvas.Object (Efl.Object, Efl.Gfx, Efl.Gfx.Stack, Efl.Animator, Efl.Input.Interface, Efl.Gfx.Size.Hint, @@ -656,6 +657,22 @@ abstract Efl.Canvas.Object (Efl.Object, Efl.Gfx, Efl.Gfx.Stack, Efl.Animator, } return: bool @warn_unused; [[$true if the coords are inside the object, $false otherwise]] } + event_animation_set { + [[Set the $animation which starts when the given $event_name happens to the object.]] + params { + @in event_type: Efl.Animation.Event_Type; [[The event type the given $animation is set for.]] + @in animation: Efl.Animation; [[The animation which starts when the given $event_name happens to the object.]] + } + legacy: null; + } + event_animation_get { + [[Get the $animation which starts when the given $event happens to the object.]] + params { + @in event_type: Efl.Animation.Event_Type; [[The event type the given $animation is set for.]] + } + legacy: null; + return: Efl.Animation @warn_unused; + } } implements { Efl.Object.constructor; diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c index f1fef26b00..a2cdaae298 100644 --- a/src/lib/evas/canvas/evas_object_main.c +++ b/src/lib/evas/canvas/evas_object_main.c @@ -46,6 +46,19 @@ Eina_Cow *evas_object_3d_cow = NULL; Eina_Cow *evas_object_mask_cow = NULL; Eina_Cow *evas_object_events_cow = NULL; +typedef struct _Event_Animation +{ + Efl_Animation *anim; + Efl_Animation_Instance *inst; +} Event_Animation; + +typedef struct _Hide_Anim_Data +{ + Efl_Canvas_Object *target; + Eina_Bool anim_started; + Eina_Bool anim_ended; +} Hide_Anim_Data; + static Eina_Bool _init_cow(void) { @@ -162,6 +175,33 @@ _evas_object_pointer_data_get(Evas_Pointer_Data *evas_pdata, return pdata; } +static void +_init_event_anims(Evas_Object_Protected_Data *obj) +{ + obj->event_anims = eina_array_new(EFL_ANIMATION_EVENT_TYPE_COUNT); + + int i; + for (i = 0; i < EFL_ANIMATION_EVENT_TYPE_COUNT; i++) + { + Event_Animation *event_anims = calloc(1, sizeof(Event_Animation)); + eina_array_push(obj->event_anims, event_anims); + } +} + +static void +_free_event_anims(Evas_Object_Protected_Data *obj) +{ + int i; + for (i = 0; i < EFL_ANIMATION_EVENT_TYPE_COUNT; i++) + { + Event_Animation *event_anims = eina_array_pop(obj->event_anims); + if (event_anims) free(event_anims); + } + + eina_array_free(obj->event_anims); + obj->event_anims = NULL; +} + EOLIAN static Eo * _efl_canvas_object_efl_object_constructor(Eo *eo_obj, Evas_Object_Protected_Data *obj) { @@ -191,6 +231,8 @@ _efl_canvas_object_efl_object_constructor(Eo *eo_obj, Evas_Object_Protected_Data obj->mask = eina_cow_alloc(evas_object_mask_cow); obj->events = eina_cow_alloc(evas_object_events_cow); + _init_event_anims(obj); + evas_object_inject(eo_obj, obj, evas); evas_object_callback_init(eo_obj, obj); @@ -494,6 +536,9 @@ evas_object_free(Evas_Object *eo_obj, Eina_Bool clean_layer) eina_cow_free(evas_object_3d_cow, (const Eina_Cow_Data**) &obj->data_3d); eina_cow_free(evas_object_mask_cow, (const Eina_Cow_Data**) &obj->mask); eina_cow_free(evas_object_events_cow, (const Eina_Cow_Data**) &obj->events); + + _free_event_anims(obj); + efl_data_unref(eo_obj, obj->private_data); obj->private_data = NULL; @@ -1016,6 +1061,77 @@ _is_event_blocked(Eo *eo_obj, const Efl_Event_Description *desc, return EINA_FALSE; } +static Eina_Bool +_efl_animation_event_type_is_inform_call(Efl_Animation_Event_Type event) +{ + if ((event == EFL_ANIMATION_EVENT_TYPE_SHOW) || + (event == EFL_ANIMATION_EVENT_TYPE_HIDE)) + return EINA_TRUE; + + return EINA_FALSE; +} + +static Efl_Animation_Event_Type +_efl_animation_event_type_get(const char *event_str) +{ + if (!event_str) return -1; + + if (!strncmp(event_str, EFL_ANIMATION_EVENT_TYPE_SHOW_STR, + strlen(EFL_ANIMATION_EVENT_TYPE_SHOW_STR))) + return EFL_ANIMATION_EVENT_TYPE_SHOW; + + else if (!strncmp(event_str, EFL_ANIMATION_EVENT_TYPE_HIDE_STR, + strlen(EFL_ANIMATION_EVENT_TYPE_HIDE_STR))) + return EFL_ANIMATION_EVENT_TYPE_HIDE; + + else if (!strncmp(event_str, EFL_ANIMATION_EVENT_TYPE_CLICKED_STR, + strlen(EFL_ANIMATION_EVENT_TYPE_CLICKED_STR))) + return EFL_ANIMATION_EVENT_TYPE_CLICKED; + + return -1; +} + +static Eina_Bool +_efl_animation_event_type_is_valid(Efl_Animation_Event_Type event) +{ + if ((event < 0) || (event >= EFL_ANIMATION_EVENT_TYPE_COUNT)) + return EINA_FALSE; + + return EINA_TRUE; +} + +static Efl_Animation_Instance * +_event_animation_instance_get(Eo *eo_obj, + Efl_Animation_Event_Type event_type) +{ + Evas_Object_Protected_Data *pd = efl_data_scope_get(eo_obj, MY_CLASS); + if (!pd) return NULL; + + if (!_efl_animation_event_type_is_valid(event_type)) + return NULL; + + Event_Animation *event_anim = eina_array_data_get(pd->event_anims, + event_type); + if (event_anim && event_anim->inst) + return event_anim->inst; + + return NULL; +} + +static void +_all_animation_instances_cancel(Eo *eo_obj) +{ + Efl_Animation_Event_Type event_type; + for (event_type = EFL_ANIMATION_EVENT_TYPE_SHOW; + event_type < EFL_ANIMATION_EVENT_TYPE_COUNT; event_type++) + { + Efl_Animation_Instance *inst = _event_animation_instance_get(eo_obj, + event_type); + if (inst) + efl_animation_instance_cancel(inst); + } +} + EOLIAN static Eina_Bool _efl_canvas_object_efl_object_event_callback_call(Eo *eo_obj, Evas_Object_Protected_Data *obj EINA_UNUSED, @@ -1023,6 +1139,24 @@ _efl_canvas_object_efl_object_event_callback_call(Eo *eo_obj, void *event_info) { if (_is_event_blocked(eo_obj, desc, event_info)) return EINA_FALSE; + + if (desc && desc->name) + { + Efl_Animation_Event_Type event_type = + _efl_animation_event_type_get(desc->name); + + if (!_efl_animation_event_type_is_inform_call(event_type)) + { + Efl_Animation_Instance *inst = + _event_animation_instance_get(eo_obj, event_type); + if (inst) + { + _all_animation_instances_cancel(eo_obj); + efl_animation_instance_start(inst); + } + } + } + return efl_event_callback_call(efl_super(eo_obj, MY_CLASS), desc, event_info); } @@ -1034,6 +1168,24 @@ _efl_canvas_object_efl_object_event_callback_legacy_call(Eo *eo_obj, void *event_info) { if (_is_event_blocked(eo_obj, desc, event_info)) return EINA_FALSE; + + if (desc && desc->name) + { + Efl_Animation_Event_Type event_type = + _efl_animation_event_type_get(desc->name); + + if (!_efl_animation_event_type_is_inform_call(event_type)) + { + Efl_Animation_Instance *inst = + _event_animation_instance_get(eo_obj, event_type); + if (inst) + { + _all_animation_instances_cancel(eo_obj); + efl_animation_instance_start(inst); + } + } + } + return efl_event_callback_legacy_call(efl_super(eo_obj, MY_CLASS), desc, event_info); } @@ -1053,6 +1205,15 @@ _efl_canvas_object_efl_object_destructor(Eo *eo_obj, Evas_Object_Protected_Data int event_id; edata = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS); + + //Unset event animations + efl_canvas_object_event_animation_set(eo_obj, EFL_ANIMATION_EVENT_TYPE_SHOW, + NULL); + efl_canvas_object_event_animation_set(eo_obj, EFL_ANIMATION_EVENT_TYPE_HIDE, + NULL); + efl_canvas_object_event_animation_set(eo_obj, + EFL_ANIMATION_EVENT_TYPE_CLICKED, + NULL); evas_object_hide(eo_obj); if (obj->events) EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) @@ -1696,6 +1857,39 @@ evas_object_hide(Evas_Object *eo_obj) efl_gfx_visible_set(eo_obj, EINA_FALSE); } +static void _animation_intercept_hide(void *data, Evas_Object *eo_obj); + +static void +_animation_hide_end_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + Hide_Anim_Data *hide_anim_data = data; + + hide_anim_data->anim_ended = EINA_TRUE; + + _animation_intercept_hide(hide_anim_data, hide_anim_data->target); + + hide_anim_data->anim_started = EINA_FALSE; + hide_anim_data->anim_ended = EINA_FALSE; +} + +static void +_animation_intercept_hide(void *data, Evas_Object *eo_obj) +{ + Hide_Anim_Data *hide_anim_data = data; + + Efl_Animation_Instance *inst = + _event_animation_instance_get(eo_obj, EFL_ANIMATION_EVENT_TYPE_HIDE); + if (inst && !hide_anim_data->anim_started && !hide_anim_data->anim_ended) + { + hide_anim_data->anim_started = EINA_TRUE; + + _all_animation_instances_cancel(eo_obj); + efl_animation_instance_start(inst); + } + else + efl_gfx_visible_set(eo_obj, EINA_FALSE); +} + EAPI Eina_Bool evas_object_visible_get(const Evas_Object *obj) { @@ -1737,6 +1931,14 @@ _show(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj) } evas_object_update_bounding_box(eo_obj, obj, NULL); evas_object_inform_call_show(eo_obj); + + Efl_Animation_Instance *inst = + _event_animation_instance_get(eo_obj, EFL_ANIMATION_EVENT_TYPE_SHOW); + if (inst) + { + _all_animation_instances_cancel(eo_obj); + efl_animation_instance_start(inst); + } } static void @@ -2667,4 +2869,124 @@ EOAPI EFL_VOID_FUNC_BODYV(efl_canvas_object_type_set, EFL_FUNC_CALL(type), const EFL_OBJECT_OP_FUNC(efl_canvas_object_legacy_ctor, _efl_canvas_object_legacy_ctor), \ EFL_OBJECT_OP_FUNC(efl_canvas_object_type_set, _efl_canvas_object_type_set) +static void +_anim_del_cb(void *data, const Efl_Event *event) +{ + Eo *eo_obj = data; + Efl_Animation_Instance *inst = event->object; + Efl_Animation_Event_Type event_type; + + for (event_type = EFL_ANIMATION_EVENT_TYPE_SHOW; + event_type < EFL_ANIMATION_EVENT_TYPE_COUNT; event_type++) + { + if (inst == _event_animation_instance_get(eo_obj, event_type)) + efl_canvas_object_event_animation_set(eo_obj, event_type, NULL); + } +} + +EOLIAN void +_efl_canvas_object_event_animation_set(Eo *eo_obj, + Evas_Object_Protected_Data *pd, + Efl_Animation_Event_Type event_type, + Efl_Animation *animation) +{ + if (!_efl_animation_event_type_is_valid(event_type)) + return; + + Event_Animation *event_anim = eina_array_data_get(pd->event_anims, event_type); + if (!event_anim) return; + + Efl_Animation *cur_anim = event_anim->anim; + Efl_Animation_Instance *cur_inst = event_anim->inst; + + //Unset for current event animation + if (cur_anim) + { + Efl_Canvas_Object *prev_target = efl_animation_target_get(cur_anim); + + //Deallocate memory and Unset callbacks for Hide event + if (event_type == EFL_ANIMATION_EVENT_TYPE_HIDE) + { + Hide_Anim_Data *hide_anim_data + = evas_object_intercept_hide_callback_del(prev_target, + _animation_intercept_hide); + if (hide_anim_data) + { + efl_event_callback_del(cur_inst, + EFL_ANIMATION_INSTANCE_EVENT_END, + _animation_hide_end_cb, + hide_anim_data); + + if (hide_anim_data->anim_started && + !hide_anim_data->anim_ended) + efl_gfx_visible_set(prev_target, EINA_FALSE); + + free(hide_anim_data); + } + } + + //Unset callback + efl_event_callback_del(cur_inst, EFL_EVENT_DEL, + _anim_del_cb, prev_target); + + //Stop animation + efl_animation_instance_cancel(cur_inst); + } + + Efl_Animation *new_anim = animation; + Efl_Animation_Instance *new_inst = NULL; + + //Set for new event animation + if (new_anim) + { + //Set target object for the given animation + Efl_Canvas_Object *target = efl_animation_target_get(new_anim); + if (!target) + target = eo_obj; + efl_animation_target_set(new_anim, target); + + new_inst = efl_animation_instance_create(new_anim); + + //Allocate memory and Set callbacks for Hide event + if (event_type == EFL_ANIMATION_EVENT_TYPE_HIDE) + { + Hide_Anim_Data *hide_anim_data = calloc(1, sizeof(Hide_Anim_Data)); + hide_anim_data->target = target; + hide_anim_data->anim_started = EINA_FALSE; + hide_anim_data->anim_ended = EINA_FALSE; + + evas_object_intercept_hide_callback_add(target, + _animation_intercept_hide, + hide_anim_data); + + efl_event_callback_add(new_inst, EFL_ANIMATION_INSTANCE_EVENT_END, + _animation_hide_end_cb, + hide_anim_data); + } + + //Set callback + efl_event_callback_add(new_inst, EFL_EVENT_DEL, _anim_del_cb, target); + } + + //Replace current event animation with new event animation + event_anim->anim = new_anim; + event_anim->inst = new_inst; +} + +EOLIAN Efl_Animation * +_efl_canvas_object_event_animation_get(Eo *eo_obj EINA_UNUSED, + Evas_Object_Protected_Data *pd, + Efl_Animation_Event_Type event_type) +{ + if (!_efl_animation_event_type_is_valid(event_type)) + return NULL; + + Event_Animation *event_anim = eina_array_data_get(pd->event_anims, + event_type); + if (event_anim && event_anim->anim) + return event_anim->anim; + + return NULL; +} + #include "canvas/efl_canvas_object.eo.c" diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 9998007046..44491cd71a 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -125,6 +125,11 @@ typedef struct _Evas_Object_Animation_Instance_Group_Parallel_Data Evas_Objec typedef struct _Evas_Object_Animation_Instance_Group_Sequential_Data Evas_Object_Animation_Instance_Group_Sequential_Data; typedef struct _Evas_Object_Animation_Instance_Data Evas_Object_Animation_Instance_Data; +//These macros are matched to Efl_Animation_Event_Type enum values. +#define EFL_ANIMATION_EVENT_TYPE_SHOW_STR "show" +#define EFL_ANIMATION_EVENT_TYPE_HIDE_STR "hide" +#define EFL_ANIMATION_EVENT_TYPE_CLICKED_STR "clicked" + // 3D stuff #define EVAS_CANVAS3D_VERTEX_ATTRIB_COUNT 5 @@ -1235,6 +1240,8 @@ struct _Evas_Object_Protected_Data unsigned char no_change_render; unsigned char delete_me; + Eina_Array *event_anims; //Array of Efl_Animation + Eina_Bool render_pre : 1; Eina_Bool rect_del : 1; |