From abc87fd4494886265c2550293522c873e1d6813f Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Wed, 29 Sep 2010 00:28:54 +0000 Subject: [PATCH] Adding a transition layout animation for edje box. Perform an animation when changing the layout from an edje box. By: Otavio Pontes ------- Sample EDC: {{{ collections { group { name: "main"; min: 500 500; max: 500 500; parts { part { name: "bg"; type: RECT; description { color: 255 255 255 255; rel1 { relative: 0.0 0.0; } rel2 { relative: 1.0 1.0; } } } part { name: "box1"; type: BOX; description { state: "default" 0.0; box { layout: vertical; padding: 0 0; } rel1 { relative: 0.0 0.0; } rel2 { relative: 1.0 1.0; } } description { state: "default" 0.1; inherit: "default" 0.0; box { padding: 10 10; layout: horizontal; } } description { state: "default" 0.2; inherit: "default" 0.0; box { layout: vertical; } rel1 { relative: 0.0 0.0; offset: 100 100; } rel2 { relative: 1.0 1.0; } } box { items { item { name: "rect1"; type: GROUP; source: "grp_rect1"; weight: 1.0 1.0; align: -1 -1; } item { name: "rect2"; type: GROUP; source: "grp_rect2"; weight: 1.0 1.0; align: -1 -1; } } } } } programs { program { name: "change_layout"; signal: "mouse,clicked,1"; source: "box1"; action: STATE_SET "default" 0.1; target: "box1"; transition: LINEAR 5.0; after: "change_back"; } program { name: "change_back"; action: STATE_SET "default" 0.2; target: "box1"; transition: LINEAR 5.0; } } } group { name: "grp_rect1"; parts { part { name: "r1"; type: RECT; description { state: "default" 0.0; color: 255 0 0 255; rel1 { relative: 0.0 0.0; } rel2 { relative: 1.0 1.0; } } description { state: "default" 0.1; inherit: "default" 0.0; color: 255 0 0 255; } } } } group { name: "grp_rect2"; parts { part { name: "r2"; type: RECT; description { state: "default" 0.0; color: 0 255 0 255; rel1 { relative: 0.0 0.0; } rel2 { relative: 1.0 1.0; } } description { state: "default" 0.1; color: 0 0 255 255; } } } } } }}} SVN revision: 52871 --- legacy/edje/src/lib/Makefile.am | 1 + legacy/edje/src/lib/edje_box_layout.c | 231 ++++++++++++++++++++++++++ legacy/edje/src/lib/edje_calc.c | 37 ----- legacy/edje/src/lib/edje_load.c | 6 + legacy/edje/src/lib/edje_private.h | 7 + legacy/edje/src/lib/edje_util.c | 27 +++ 6 files changed, 272 insertions(+), 37 deletions(-) create mode 100644 legacy/edje/src/lib/edje_box_layout.c diff --git a/legacy/edje/src/lib/Makefile.am b/legacy/edje/src/lib/Makefile.am index b4df06a539..01ba3c00db 100644 --- a/legacy/edje/src/lib/Makefile.am +++ b/legacy/edje/src/lib/Makefile.am @@ -20,6 +20,7 @@ includes_HEADERS = Edje.h Edje_Edit.h includesdir = $(includedir)/edje-@VMAJ@ base_sources = \ +edje_box_layout.c \ edje_cache.c \ edje_calc.c \ edje_callbacks.c \ diff --git a/legacy/edje/src/lib/edje_box_layout.c b/legacy/edje/src/lib/edje_box_layout.c new file mode 100644 index 0000000000..d5aaa2725e --- /dev/null +++ b/legacy/edje/src/lib/edje_box_layout.c @@ -0,0 +1,231 @@ +#include "edje_private.h" + +typedef struct _Edje_Transition_Animation_Data Edje_Transition_Animation_Data; +struct _Edje_Transition_Animation_Data +{ + Evas_Object *obj; + struct + { + Evas_Coord x, y, w, h; + } start, end; +}; + +struct _Edje_Part_Box_Animation +{ + struct + { + Evas_Object_Box_Layout layout; + void *data; + void(*free_data)(void *data); + Edje_Alignment align; + Evas_Point padding; + } start, end; + Eina_List *objs; + Eina_Bool recalculate:1; + Evas_Object *box; + double progress; + double start_progress; + int box_start_w, box_start_h; +}; + +static void +_edje_box_layout_find_all(const char *name, const char *name_alt, Evas_Object_Box_Layout *cb, void **data, void (**free_data)(void *data)) +{ + if (!_edje_box_layout_find(name, cb, data, free_data)) + { + if ((!name_alt) || + (!_edje_box_layout_find(name_alt, cb, data, free_data))) + { + ERR("box layout '%s' (fallback '%s') not available, using horizontal.", + name, name_alt); + *cb = evas_object_box_layout_horizontal; + *free_data = NULL; + *data = NULL; + } + } +} + +static void +_edje_box_layout_calculate_coords(Evas_Object *obj, Evas_Object_Box_Data *priv, Edje_Part_Box_Animation *anim) +{ + Eina_List *l; + Edje_Transition_Animation_Data *tad; + Evas_Coord x, y; + + evas_object_geometry_get(obj, &x, &y, &anim->box_start_w, &anim->box_start_h); + EINA_LIST_FOREACH(anim->objs, l, tad) + { + evas_object_geometry_get(tad->obj, &tad->start.x, &tad->start.y, + &tad->start.w, &tad->start.h); + tad->start.x = tad->start.x - x; + tad->start.y = tad->start.y - y; + } + evas_object_box_padding_set(obj, anim->end.padding.x, anim->end.padding.y); + evas_object_box_align_set(obj, TO_DOUBLE(anim->end.align.x), TO_DOUBLE(anim->end.align.y)); + anim->end.layout(obj, priv, anim->end.data); + EINA_LIST_FOREACH(anim->objs, l, tad) + { + evas_object_geometry_get(tad->obj, &tad->end.x, &tad->end.y, + &tad->end.w, &tad->end.h); + tad->end.x = tad->end.x - x; + tad->end.y = tad->end.y - y; + } +} + +static void +_edje_box_layout_exec(Evas_Object *obj, Edje_Part_Box_Animation *anim) +{ + Eina_List *l; + Edje_Transition_Animation_Data *tad; + Evas_Coord x, y, w, h; + Evas_Coord cur_x, cur_y, cur_w, cur_h; + evas_object_geometry_get(obj, &x, &y, &w, &h); + double progress = (anim->progress - anim->start_progress) / (1 - anim->start_progress); + + EINA_LIST_FOREACH(anim->objs, l, tad) + { + cur_x = x + (tad->start.x + ((tad->end.x - tad->start.x) * progress)) * (w / (double)anim->box_start_w); + cur_y = y + (tad->start.y + ((tad->end.y - tad->start.y) * progress)) * (h / (double)anim->box_start_h); + cur_w = (w / (double)anim->box_start_w) * (tad->start.w + ((tad->end.w - tad->start.w) * progress)); + cur_h = (h / (double)anim->box_start_h) * (tad->start.h + ((tad->end.h - tad->start.h) * progress)); + evas_object_move(tad->obj, cur_x, cur_y); + evas_object_resize(tad->obj, cur_w, cur_h); + } +} + +static void +_edje_box_layout(Evas_Object *obj, Evas_Object_Box_Data *priv, void *data) +{ + Edje_Part_Box_Animation *anim = data; + if (anim->progress < 0.01) + { + evas_object_box_padding_set(obj, anim->start.padding.x, anim->start.padding.y); + evas_object_box_align_set(obj, TO_DOUBLE(anim->start.align.x), TO_DOUBLE(anim->start.align.y)); + anim->start.layout(obj, priv, anim->start.data); + return; + } + + if (anim->recalculate) + { + _edje_box_layout_calculate_coords(obj, priv, anim); + anim->start_progress = anim->progress; + anim->recalculate = EINA_FALSE; + } + + if ((anim->progress > 0) && (anim->start_progress < 1)) + _edje_box_layout_exec(obj, anim); +} + +void +_edje_box_layout_free_data(void *data) +{ + Edje_Transition_Animation_Data *tad; + Edje_Part_Box_Animation *anim = data; + if (anim->start.free_data && anim->start.data) + anim->start.free_data(anim->start.data); + if (anim->end.free_data && anim->end.data) + anim->end.free_data(anim->end.data); + EINA_LIST_FREE(anim->objs, tad) + free(tad); + free(data); +} + +Edje_Part_Box_Animation * +_edje_box_layout_anim_new(Evas_Object *box) +{ + Edje_Part_Box_Animation *anim = calloc(1, sizeof(Edje_Part_Box_Animation)); + if (!anim) + return NULL; + + anim->box = box; + evas_object_box_layout_set(box, _edje_box_layout, anim, NULL); + + return anim; +} + +void +_edje_box_recalc_apply(Edje *ed __UNUSED__, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Box *chosen_desc) +{ + Evas_Object_Box_Data *priv; + int min_w, min_h; + if ((ep->param2) && (ep->description_pos != ZERO)) + { + Edje_Part_Description_Box *param2_desc = (Edje_Part_Description_Box *)ep->param2->description; + if (ep->anim->end.layout == NULL) + { + _edje_box_layout_find_all(param2_desc->box.layout, param2_desc->box.alt_layout, &ep->anim->end.layout, &ep->anim->end.data, &ep->anim->end.free_data); + ep->anim->end.padding.x = param2_desc->box.padding.x; + ep->anim->end.padding.y = param2_desc->box.padding.y; + ep->anim->end.align.x = param2_desc->box.align.x; + ep->anim->end.align.y = param2_desc->box.align.y; + + priv = evas_object_smart_data_get(ep->object); + if (priv == NULL) + return; + + evas_object_box_padding_set(ep->object, ep->anim->start.padding.x, ep->anim->start.padding.y); + evas_object_box_align_set(ep->object, TO_DOUBLE(ep->anim->start.align.x), TO_DOUBLE(ep->anim->start.align.y)); + ep->anim->start.layout(ep->object, priv, ep->anim->start.data); + _edje_box_layout_calculate_coords(ep->object, priv, ep->anim); + ep->anim->start_progress = 0.0; + } + evas_object_smart_changed(ep->object); + } + else { + ep->anim->end.layout = NULL; + } + + if (ep->description_pos < 0.01 || !ep->anim->start.layout) + { + _edje_box_layout_find_all(chosen_desc->box.layout, chosen_desc->box.alt_layout, &ep->anim->start.layout, &ep->anim->start.data, &ep->anim->start.free_data); + ep->anim->start.padding.x = chosen_desc->box.padding.x; + ep->anim->start.padding.y = chosen_desc->box.padding.y; + ep->anim->start.align.x = chosen_desc->box.align.x; + ep->anim->start.align.y = chosen_desc->box.align.y; + evas_object_smart_changed(ep->object); + } + + ep->anim->progress = ep->description_pos; + + if (evas_object_smart_need_recalculate_get(ep->object)) + { + evas_object_smart_need_recalculate_set(ep->object, 0); + evas_object_smart_calculate(ep->object); + } + evas_object_size_hint_min_get(ep->object, &min_w, &min_h); + if (chosen_desc->box.min.h && (p3->w < min_w)) + p3->w = min_w; + if (chosen_desc->box.min.v && (p3->h < min_h)) + p3->h = min_h; +} + +Eina_Bool +_edje_box_layout_add_child(Edje_Real_Part *rp, Evas_Object *child_obj) +{ + Edje_Transition_Animation_Data *tad; + tad = calloc(1, sizeof(Edje_Transition_Animation_Data)); + if (!tad) + return EINA_FALSE; + tad->obj = child_obj; + rp->anim->objs = eina_list_append(rp->anim->objs, tad); + rp->anim->recalculate = EINA_TRUE; + return EINA_TRUE; +} + +void +_edje_box_layout_remove_child(Edje_Real_Part *rp, Evas_Object *child_obj) +{ + Eina_List *l; + Edje_Transition_Animation_Data *tad; + + EINA_LIST_FOREACH(rp->anim->objs, l, tad) + { + if (tad->obj == child_obj) + { + free(eina_list_data_get(l)); + rp->anim->objs = eina_list_remove_list(rp->anim->objs, l); + rp->anim->recalculate = EINA_TRUE; + } + } + rp->anim->recalculate = EINA_TRUE; +} diff --git a/legacy/edje/src/lib/edje_calc.c b/legacy/edje/src/lib/edje_calc.c index be21e17ff3..0f82b8c8bf 100644 --- a/legacy/edje/src/lib/edje_calc.c +++ b/legacy/edje/src/lib/edje_calc.c @@ -1419,43 +1419,6 @@ _edje_part_recalc_single(Edje *ed, } } -static void -_edje_box_recalc_apply(Edje *ed __UNUSED__, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Box *chosen_desc) -{ - Evas_Object_Box_Layout layout; - void (*free_data)(void *data); - void *data; - int min_w, min_h; - - if (!_edje_box_layout_find(chosen_desc->box.layout, &layout, &data, &free_data)) - { - if ((!chosen_desc->box.alt_layout) || - (!_edje_box_layout_find(chosen_desc->box.alt_layout, &layout, &data, &free_data))) - { - ERR("box layout '%s' (fallback '%s') not available, using horizontal.", - chosen_desc->box.layout, chosen_desc->box.alt_layout); - layout = evas_object_box_layout_horizontal; - free_data = NULL; - data = NULL; - } - } - - evas_object_box_layout_set(ep->object, layout, data, free_data); - evas_object_box_align_set(ep->object, TO_DOUBLE(chosen_desc->box.align.x), TO_DOUBLE(chosen_desc->box.align.y)); - evas_object_box_padding_set(ep->object, chosen_desc->box.padding.x, chosen_desc->box.padding.y); - - if (evas_object_smart_need_recalculate_get(ep->object)) - { - evas_object_smart_need_recalculate_set(ep->object, 0); - evas_object_smart_calculate(ep->object); - } - evas_object_size_hint_min_get(ep->object, &min_w, &min_h); - if (chosen_desc->box.min.h && (p3->w < min_w)) - p3->w = min_w; - if (chosen_desc->box.min.v && (p3->h < min_h)) - p3->h = min_h; -} - static void _edje_table_recalc_apply(Edje *ed __UNUSED__, Edje_Real_Part *ep, diff --git a/legacy/edje/src/lib/edje_load.c b/legacy/edje/src/lib/edje_load.c index 660eff05cf..4a1ac1b7bd 100644 --- a/legacy/edje/src/lib/edje_load.c +++ b/legacy/edje/src/lib/edje_load.c @@ -455,6 +455,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g break; case EDJE_PART_TYPE_BOX: rp->object = evas_object_box_add(ed->evas); + rp->anim = _edje_box_layout_anim_new(rp->object); break; case EDJE_PART_TYPE_TABLE: rp->object = evas_object_table_add(ed->evas); @@ -971,6 +972,11 @@ _edje_file_del(Edje *ed) /* evas_box/table handles deletion of objects */ rp->items = eina_list_free(rp->items); } + if (rp->anim) + { + _edje_box_layout_free_data(rp->anim); + rp->anim = NULL; + } if (rp->text.text) eina_stringshare_del(rp->text.text); if (rp->text.font) eina_stringshare_del(rp->text.font); if (rp->text.cache.in_str) eina_stringshare_del(rp->text.cache.in_str); diff --git a/legacy/edje/src/lib/edje_private.h b/legacy/edje/src/lib/edje_private.h index 7c70ca65c1..77d44c6b45 100644 --- a/legacy/edje/src/lib/edje_private.h +++ b/legacy/edje/src/lib/edje_private.h @@ -289,6 +289,7 @@ typedef struct _Edje_Part_Description_Spec_Text Edje_Part_Description_Spec_ typedef struct _Edje_Part_Description_Spec_Box Edje_Part_Description_Spec_Box; typedef struct _Edje_Part_Description_Spec_Table Edje_Part_Description_Spec_Table; typedef struct _Edje_Patterns Edje_Patterns; +typedef struct _Edje_Part_Box_Animation Edje_Part_Box_Animation; #define EDJE_INF_MAX_W 100000 #define EDJE_INF_MAX_H 100000 @@ -1108,6 +1109,7 @@ struct _Edje_Real_Part Edje_Rectangle req; // 16 Eina_List *items; // 4 //FIXME: only if table/box + Edje_Part_Box_Animation *anim; // 4 //FIXME: Used only if box void *entry_data; // 4 // FIXME: move to entry section Evas_Object *cursorbg_object; // 4 // FIXME: move to entry section Evas_Object *cursorfg_object; // 4 // FIXME: move to entry section @@ -1519,6 +1521,11 @@ void _edje_real_part_swallow_clear(Edje_Real_Part *rp); void _edje_box_init(void); void _edje_box_shutdown(void); Eina_Bool _edje_box_layout_find(const char *name, Evas_Object_Box_Layout *cb, void **data, void (**free_data)(void *data)); +void _edje_box_recalc_apply(Edje *ed __UNUSED__, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Box *chosen_desc); +Eina_Bool _edje_box_layout_add_child(Edje_Real_Part *rp, Evas_Object *child_obj); +void _edje_box_layout_remove_child(Edje_Real_Part *rp, Evas_Object *child_obj); +Edje_Part_Box_Animation * _edje_box_layout_anim_new(Evas_Object *box); +void _edje_box_layout_free_data(void *data); Eina_Bool _edje_real_part_box_append(Edje_Real_Part *rp, Evas_Object *child_obj); Eina_Bool _edje_real_part_box_prepend(Edje_Real_Part *rp, Evas_Object *child_obj); diff --git a/legacy/edje/src/lib/edje_util.c b/legacy/edje/src/lib/edje_util.c index b7dd24a7eb..11dde2c471 100644 --- a/legacy/edje/src/lib/edje_util.c +++ b/legacy/edje/src/lib/edje_util.c @@ -3678,6 +3678,12 @@ _edje_real_part_box_append(Edje_Real_Part *rp, Evas_Object *child_obj) opt = evas_object_box_append(rp->object, child_obj); if (!opt) return EINA_FALSE; + if (!_edje_box_layout_add_child(rp, child_obj)) + { + evas_object_box_remove(rp->object, child_obj); + return EINA_FALSE; + } + _edje_box_child_add(rp, child_obj); return EINA_TRUE; @@ -3691,6 +3697,12 @@ _edje_real_part_box_prepend(Edje_Real_Part *rp, Evas_Object *child_obj) opt = evas_object_box_prepend(rp->object, child_obj); if (!opt) return EINA_FALSE; + if (!_edje_box_layout_add_child(rp, child_obj)) + { + evas_object_box_remove(rp->object, child_obj); + return EINA_FALSE; + } + _edje_box_child_add(rp, child_obj); return EINA_TRUE; @@ -3704,6 +3716,12 @@ _edje_real_part_box_insert_before(Edje_Real_Part *rp, Evas_Object *child_obj, co opt = evas_object_box_insert_before(rp->object, child_obj, ref); if (!opt) return EINA_FALSE; + if (!_edje_box_layout_add_child(rp, child_obj)) + { + evas_object_box_remove(rp->object, child_obj); + return EINA_FALSE; + } + _edje_box_child_add(rp, child_obj); return EINA_TRUE; @@ -3717,6 +3735,12 @@ _edje_real_part_box_insert_at(Edje_Real_Part *rp, Evas_Object *child_obj, unsign opt = evas_object_box_insert_at(rp->object, child_obj, pos); if (!opt) return EINA_FALSE; + if (!_edje_box_layout_add_child(rp, child_obj)) + { + evas_object_box_remove(rp->object, child_obj); + return EINA_FALSE; + } + _edje_box_child_add(rp, child_obj); return EINA_TRUE; @@ -3727,6 +3751,7 @@ _edje_real_part_box_remove(Edje_Real_Part *rp, Evas_Object *child_obj) { if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL; if (!evas_object_box_remove(rp->object, child_obj)) return NULL; + _edje_box_layout_remove_child(rp, child_obj); _edje_box_child_remove(rp, child_obj); return child_obj; } @@ -3744,6 +3769,7 @@ _edje_real_part_box_remove_at(Edje_Real_Part *rp, unsigned int pos) child_obj = opt->obj; if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL; if (!evas_object_box_remove_at(rp->object, pos)) return NULL; + _edje_box_layout_remove_child(rp, child_obj); _edje_box_child_remove(rp, child_obj); return child_obj; } @@ -3762,6 +3788,7 @@ _edje_real_part_box_remove_all(Edje_Real_Part *rp, Eina_Bool clear) i++; else { + _edje_box_layout_remove_child(rp, child_obj); _edje_box_child_remove(rp, child_obj); if (!evas_object_box_remove_at(rp->object, i)) return EINA_FALSE;