From bac07e79cea59b1859e23d83028763e3f38c087a Mon Sep 17 00:00:00 2001 From: Vitalii Vorobiov Date: Mon, 2 Feb 2015 11:14:45 +0200 Subject: [PATCH] Edje: edje_edit - abort Recursive Reference in edje_edit_part_source_set It is unable to do recursive reference such as: > Having group A with GROUP part that has group B as source. > Having group B with GROUP part that has group A as source. Here we have a loop that is not allowed by edje_cc, so edje_edit also need to check this case. @fix --- src/lib/edje/Edje_Edit.h | 4 ++++ src/lib/edje/edje_edit.c | 41 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/lib/edje/Edje_Edit.h b/src/lib/edje/Edje_Edit.h index 053a511b78..12db53b4c0 100644 --- a/src/lib/edje/Edje_Edit.h +++ b/src/lib/edje/Edje_Edit.h @@ -1233,6 +1233,10 @@ EAPI Eina_Bool edje_edit_part_clip_to_set(Evas_Object *obj, const char *part, co EAPI const char * edje_edit_part_source_get(Evas_Object *obj, const char *part); /** Set the source of part. + * + * If setting source of the part will lead to recursive reference + * (when A source to B, and B is going to be source to A because of this funciton), + * then it will return EINA_FALSE. * * @param obj Object being edited. * @param part Part to set the source of. diff --git a/src/lib/edje/edje_edit.c b/src/lib/edje/edje_edit.c index 55a262dd31..d19a19aa0f 100644 --- a/src/lib/edje/edje_edit.c +++ b/src/lib/edje/edje_edit.c @@ -3893,17 +3893,58 @@ edje_edit_part_source_get(Evas_Object *obj, const char *part) return eina_stringshare_add(rp->part->source); } +static Eina_Bool +_check_recursive_reference(Edje *ed, const char *source, Eina_List *group_path, Edje_Part *part) +{ + unsigned int i; + char *data; + Edje_Part_Collection_Directory_Entry *e; + Eina_List *l; + Eina_Bool no_ref = EINA_TRUE; + + if (!source) return EINA_TRUE; + + e = eina_hash_find(ed->file->collection, source); + + /* Go through every part to find parts with type GROUP */ + for (i = 0; i < e->ref->parts_count; ++i) + { + if ((e->ref->parts[i]->type == EDJE_PART_TYPE_GROUP) && + (e->ref->parts[i]->source)) + { + /* Make sure that this group isn't already in the tree of parents */ + EINA_LIST_FOREACH(group_path, l, data) + { + if (data == e->ref->parts[i]->source) + return EINA_FALSE; + } + group_path = eina_list_append(group_path, source); + no_ref &= _check_recursive_reference(ed, e->ref->parts[i]->source, group_path, part); + } + + /* We did a loop here... this part doesn't have source yet, + but if it will set, it'll be a recursive reference. */ + if (e->ref->parts[i] == part) return EINA_FALSE; + } + return no_ref; +} + EAPI Eina_Bool edje_edit_part_source_set(Evas_Object *obj, const char *part, const char *source) { GET_RP_OR_RETURN(EINA_FALSE); Evas_Object *child_obj; + Eina_List *group_path = NULL; //printf("Set source for part: %s [source: %s]\n", part, source); switch (rp->part->type) { case EDJE_PART_TYPE_GROUP: + /* find source group */ + if (!_check_recursive_reference(ed, source, group_path, rp->part)) + return EINA_FALSE; + if ((rp->typedata.swallow) && (rp->typedata.swallow->swallowed_object)) { _edje_real_part_swallow_clear(ed, rp);