From 287d63c016fbc8ef18a685cced62561dbb5d26fa Mon Sep 17 00:00:00 2001 From: Andrii Kroitor Date: Thu, 19 Dec 2013 15:47:25 +0900 Subject: [PATCH] edje: edje_edit - image api modification Changed edje_edit_image_del logic: image can't be deleted if it's in use, after deletion last image in list is moved to freed position so there are no "holes" in image list. Following functions added to api: edje_edit_image_replace edje_edit_image_usage_list_get edje_edit_image_usage_list_free Reviewers: cedric, seoz, raster Reviewed By: cedric CC: reutskiy.v.v, cedric Differential Revision: https://phab.enlightenment.org/D392 Signed-off-by: Cedric BAIL --- src/lib/edje/Edje_Edit.h | 44 +++++++- src/lib/edje/edje_edit.c | 231 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 256 insertions(+), 19 deletions(-) diff --git a/src/lib/edje/Edje_Edit.h b/src/lib/edje/Edje_Edit.h index a264260a35..d5c3d43f2e 100644 --- a/src/lib/edje/Edje_Edit.h +++ b/src/lib/edje/Edje_Edit.h @@ -50,6 +50,17 @@ struct _Edje_Edit_Script_Error }; typedef struct _Edje_Edit_Script_Error Edje_Edit_Script_Error; +struct _Edje_Part_Image_Use +{ + const char *group; + const char *part; + struct { + const char *name; + double value; + } state; +}; +typedef struct _Edje_Part_Image_Use Edje_Part_Image_Use; + /** * @file * @brief Functions to deal with edje internal object. Don't use in standard @@ -2830,15 +2841,46 @@ EAPI Eina_Bool edje_edit_image_add(Evas_Object *obj, const char *path); /** Delete an image from the image collection * * It actually write directly to the file so you don't have to save. + * Can't delete image if it is used by any part. * * @param obj Object being edited. * @param name The name of the image file to include in the edje. * * @return EINA_TRUE if successful, EINA_FALSE otherwise (including the - * case when the name is not valid). + * case when the name is not valid or image is in use). */ EAPI Eina_Bool edje_edit_image_del(Evas_Object *obj, const char *name); +/** Replace one image in all descriptions + * + * @param obj Object being edited. + * @param name The name of the image to replace. + * @param name The new_name of the image to replace with. + * + * @return EINA_TRUE if successful, EINA_FALSE otherwise (including the + * case when one of the names is not valid) + */ +EAPI Eina_Bool edje_edit_image_replace(Evas_Object *obj, const char *name, const char *new_name); + +/** Get list of (Edje_Part_Image_Use *) - group-part-state triplets where given + * image is used + * + * Use edje_edit_image_usage_list_free() when you don't need it anymore. + * + * @param obj Object being edited. + * @param name The name of the image. + * @param first_only If EINA_TRUE, return only one triplete. + * + * @return Eina_List containing Edje_Part_Image_Use if successful, NULL otherwise + */ +EAPI Eina_List* edje_edit_image_usage_list_get(Evas_Object *obj, const char *name, Eina_Bool first_only); + +/** Free an Eina_List of (Edje_Part_Image_Use *) allocated by an edje_edit_image_usage_list_get() function. + * + * @param lst List of strings to free. + */ +EAPI void edje_edit_image_usage_list_free(Eina_List *lst); + /** Add an image entry to the image collection * * This function adds the given image entry to the edje image collection. The diff --git a/src/lib/edje/edje_edit.c b/src/lib/edje/edje_edit.c index f38cf44b1a..214381fa1a 100644 --- a/src/lib/edje/edje_edit.c +++ b/src/lib/edje/edje_edit.c @@ -4811,11 +4811,149 @@ edje_edit_image_add(Evas_Object *obj, const char* path) return EINA_TRUE; } +EAPI Eina_Bool +edje_edit_image_replace(Evas_Object *obj, const char *name, const char *new_name) +{ + Eina_Iterator *it; + Edje_Part_Collection_Directory_Entry *pce; + Edje_Part *part; + Edje_Part_Description_Image *part_desc_image; + unsigned int i, j, k; + int image_id, new_image_id; + + GET_ED_OR_RETURN(EINA_FALSE); + + image_id = edje_edit_image_id_get(obj, name); + new_image_id = edje_edit_image_id_get(obj, new_name); + if ((image_id < 0) || (new_image_id < 0)) + return EINA_FALSE; + + it = eina_hash_iterator_data_new(ed->file->collection); + + EINA_ITERATOR_FOREACH(it, pce) + { + for (i = 0; i < pce->ref->parts_count; i++) + { + part = pce->ref->parts[i]; + if (part->type == EDJE_PART_TYPE_IMAGE) + { + part_desc_image = (Edje_Part_Description_Image *)part->default_desc; + if (part_desc_image->image.id == image_id) + part_desc_image->image.id = new_image_id; + for (k = 0; k < part_desc_image->image.tweens_count; k++) + if (part_desc_image->image.tweens[k]->id == image_id) + part_desc_image->image.id = new_image_id; + for (j = 0; j < part->other.desc_count; j++) + { + part_desc_image = (Edje_Part_Description_Image *)part->other.desc[j]; + if (part_desc_image->image.id == image_id) + part_desc_image->image.id = new_image_id; + for (k = 0; k < part_desc_image->image.tweens_count; k++) + if (part_desc_image->image.tweens[k]->id == image_id) + part_desc_image->image.id = new_image_id; + } + } + } + } + eina_iterator_free(it); + + return EINA_TRUE; +} + +EAPI Eina_List* +edje_edit_image_usage_list_get(Evas_Object *obj, const char *name, Eina_Bool first_only) +{ + Eina_List *result = NULL; + Eina_Iterator *it; + Edje_Part_Collection_Directory_Entry *pce; + Edje_Part_Image_Use *item; + Edje_Part *part; + Edje_Part_Description_Image *part_desc_image; + unsigned int i, j, k; + int image_id; + + GET_ED_OR_RETURN(NULL); + + image_id = edje_edit_image_id_get(obj, name); + if (image_id < 0) + return NULL; + + it = eina_hash_iterator_data_new(ed->file->collection); + + #define ITEM_ADD() \ + item = (Edje_Part_Image_Use *) calloc(1, sizeof(Edje_Part_Image_Use)); \ + item->group = eina_stringshare_add(pce->entry); \ + item->part = eina_stringshare_add(part->name); \ + item->state.name = eina_stringshare_add(part_desc_image->common.state.name); \ + item->state.value = part_desc_image->common.state.value; \ + result = eina_list_append(result, item); + + #define FIND_IN_PART_DESCRIPTION() \ + if (part_desc_image->image.id == image_id) \ + { \ + ITEM_ADD(); \ + if (first_only) \ + return result; \ + else \ + continue; \ + } \ + for (k = 0; k < part_desc_image->image.tweens_count; k++) \ + { \ + if (part_desc_image->image.tweens[k]->id == image_id) \ + { \ + ITEM_ADD(); \ + if (first_only) \ + return result; \ + else \ + continue; \ + } \ + } + + EINA_ITERATOR_FOREACH(it, pce) + { + for (i = 0; i < pce->ref->parts_count; i++) + { + part = pce->ref->parts[i]; + if (part->type == EDJE_PART_TYPE_IMAGE) + { + part_desc_image = (Edje_Part_Description_Image *)part->default_desc; + FIND_IN_PART_DESCRIPTION(); + for (j = 0; j < part->other.desc_count; j++) + { + part_desc_image = (Edje_Part_Description_Image *)part->other.desc[j]; + FIND_IN_PART_DESCRIPTION(); + } + } + } + } + #undef ITEM_ADD + #undef FIND_IN_PART_DESCRIPTION + eina_iterator_free(it); + + return result; +} + +EAPI void +edje_edit_image_usage_list_free(Eina_List *list) +{ + Edje_Part_Image_Use *item; + EINA_LIST_FREE(list, item) + { + eina_stringshare_del(item->group); + eina_stringshare_del(item->part); + eina_stringshare_del(item->state.name); + free(item); + } +} + EAPI Eina_Bool edje_edit_image_del(Evas_Object *obj, const char* name) { - Edje_Image_Directory_Entry *de; - unsigned int i; + Edje_Image_Directory_Entry *de, *de_last; + unsigned int i, j, k; + Eina_List *used; + Eina_Iterator *it; + Edje_Part_Collection_Directory_Entry *pce; GET_EED_OR_RETURN(EINA_FALSE); GET_ED_OR_RETURN(EINA_FALSE); @@ -4824,33 +4962,45 @@ edje_edit_image_del(Evas_Object *obj, const char* name) if (!ed->file) return EINA_FALSE; if (!ed->path) return EINA_FALSE; + used = edje_edit_image_usage_list_get(obj, name, EINA_TRUE); + if (used) + { + edje_edit_image_usage_list_free(used); + WRN("Image \"%s\" is used", name); + return EINA_FALSE; + } + edje_edit_image_usage_list_free(used); + /* Create Image_Directory if not exist */ if (!ed->file->image_dir) goto invalid_image; for (i = 0; i < ed->file->image_dir->entries_count; ++i) { - de = ed->file->image_dir->entries + i; + de = ed->file->image_dir->entries + i; - if (de->entry - && !strcmp(name, de->entry)) - break; + if ((de->entry) && (!strcmp(name, de->entry))) + break; } - if (i == ed->file->image_dir->entries_count) goto invalid_image; + de_last = ed->file->image_dir->entries + ed->file->image_dir->entries_count - 1; + { char entry[PATH_MAX]; + char last_entry[PATH_MAX]; Eet_File *eetf; + void *data; + int size = 0; /* open the eet file */ eetf = eet_open(ed->path, EET_FILE_MODE_READ_WRITE); if (!eetf) - { - ERR("Unable to open \"%s\" for writing output", ed->path); - return EINA_FALSE; - } + { + ERR("Unable to open \"%s\" for writing output", ed->path); + return EINA_FALSE; + } snprintf(entry, sizeof(entry), "edje/images/%i", de->id); @@ -4860,20 +5010,65 @@ edje_edit_image_del(Evas_Object *obj, const char* name) eet_close(eetf); return EINA_FALSE; } - + if (de_last->id != de->id) + { + snprintf(last_entry, sizeof(last_entry), "edje/images/%i", de_last->id); + data = eet_read(eetf, last_entry, &size); + eet_delete(eetf, last_entry); + eet_write(eetf, entry, data, size, 0); + } /* write the edje_file */ if (!_edje_edit_edje_file_save(eetf, ed->file)) - { - eet_close(eetf); - return EINA_FALSE; - } + { + eet_close(eetf); + return EINA_FALSE; + } eet_close(eetf); } - _edje_if_string_free(ed, de->entry); - de->entry = NULL; + _edje_if_string_free(ed, de->entry); + --ed->file->image_dir->entries_count; + + if (de_last->id != de->id) + { + Edje_Part *part; + Edje_Part_Description_Image *part_desc_image; + + de->entry = de_last->entry; + it = eina_hash_iterator_data_new(ed->file->collection); + EINA_ITERATOR_FOREACH(it, pce) + { + for (i = 0; i < pce->ref->parts_count; i++) + { + part = pce->ref->parts[i]; + if (part->type == EDJE_PART_TYPE_IMAGE) + { + part_desc_image = (Edje_Part_Description_Image *)part->default_desc; + if (part_desc_image->image.id == de_last->id) + part_desc_image->image.id = de->id; + for (k = 0; k < part_desc_image->image.tweens_count; k++) + if (part_desc_image->image.id == de_last->id) + part_desc_image->image.id = de->id; + + for (j = 0; j < part->other.desc_count; j++) + { + part_desc_image = (Edje_Part_Description_Image *)part->other.desc[j]; + if (part_desc_image->image.id == de_last->id) + part_desc_image->image.id = de->id; + for (k = 0; k < part_desc_image->image.tweens_count; k++) + if (part_desc_image->image.id == de_last->id) + part_desc_image->image.id = de->id; + } + } + } + } + eina_iterator_free(it); + } + ed->file->image_dir->entries = realloc(ed->file->image_dir->entries, + sizeof(Edje_Image_Directory_Entry) * + ed->file->image_dir->entries_count); _edje_edit_flag_script_dirty(eed, EINA_TRUE); return EINA_TRUE;