You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

7871 lines
198 KiB

/*
* TODO
* -----------------------------------------------------------------
* Add LUA Support :)
* Remove images/fonts
* Clean the saving routines
*
*/
#include "edje_private.h"
#define EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT
#include "Edje_Edit.h"
#include <Eo.h>
#ifdef MY_CLASS
# undef MY_CLASS
#endif
#define MY_CLASS EDJE_EDIT_CLASS
static const char EDJE_EDIT_ERROR_GROUP_CURRENTLY_USED_STR[] = "Current group cannot be deleted";
static const char EDJE_EDIT_ERROR_GROUP_REFERENCED_STR[] = "Group still in use";
static const char EDJE_EDIT_ERROR_GROUP_DOES_NOT_EXIST_STR[] = "Group does not exist";
EAPI Eina_Error EDJE_EDIT_ERROR_GROUP_CURRENTLY_USED = 0 ;
EAPI Eina_Error EDJE_EDIT_ERROR_GROUP_REFERENCED = 0;
EAPI Eina_Error EDJE_EDIT_ERROR_GROUP_DOES_NOT_EXIST = 0;
/* Get eed(Edje_Edit*) from obj(Evas_Object*) */
#define GET_EED_OR_RETURN(RET) \
Edje_Edit *eed; \
if (!eo_isa(obj, MY_CLASS)) \
return RET; \
eed = eo_data_get(obj, MY_CLASS); \
if (!eed) return RET;
/* Get ed(Edje*) from obj(Evas_Object*) */
#define GET_ED_OR_RETURN(RET) \
Edje *ed; \
if (!eo_isa(obj, EDJE_OBJ_CLASS)) \
return RET; \
ed = eo_data_get(obj, EDJE_OBJ_CLASS); \
/* Get rp(Edje_Real_Part*) from obj(Evas_Object*) and part(char*) */
#define GET_RP_OR_RETURN(RET) \
GET_EED_OR_RETURN(RET) \
GET_ED_OR_RETURN(RET) \
Edje_Real_Part *rp; \
rp = _edje_real_part_get(ed, part); \
if (!rp) return RET;
/* Get pd(Edje_Part_Description*) from obj(Evas_Object*), part(char*) and state (char*) */
#define GET_PD_OR_RETURN(RET) \
GET_EED_OR_RETURN(RET) \
GET_ED_OR_RETURN(RET) \
Edje_Real_Part *rp; \
Edje_Part_Description_Common *pd; \
rp = _edje_real_part_get(ed, part); \
if (!rp) return RET; \
pd = _edje_part_description_find_byname(eed, part, state, value); \
if (!pd) return RET;
/* Get epr(Edje_Program*) from obj(Evas_Object*) and prog(char*)*/
#define GET_EPR_OR_RETURN(RET) \
Edje_Program *epr; \
if (!eo_isa(obj, MY_CLASS)) \
return RET; \
epr = _edje_program_get_byname(obj, prog); \
if (!epr) return RET;
static void *
_alloc(size_t size)
{
void *mem;
mem = calloc(1, size);
if (mem) return mem;
ERR("Edje_Edit: Error. memory allocation of %i bytes failed. %s",
(int)size, strerror(errno));
return NULL;
}
/*************/
/* INTERNALS */
/*************/
/* Edje_Edit smart! Overloads the edje one adding some more control stuff */
static const char _edje_edit_type[] = "edje_edit";
typedef struct _Edje_Edit Edje_Edit;
struct _Edje_Edit
{
Edje *base;
void *bytecode;
int bytecode_size;
char *embryo_source;
char *embryo_processed;
Eina_Hash *program_scripts;
Eina_List *errors;
Eina_Bool bytecode_dirty:1;
Eina_Bool embryo_source_dirty:1;
Eina_Bool all_dirty:1;
Eina_Bool script_need_recompile:1;
};
typedef struct _Program_Script Program_Script;
struct _Program_Script
{
int id;
char *code;
char *processed;
Eina_Bool dirty:1;
Eina_Bool delete_me:1;
};
static Eina_Bool _edje_edit_edje_file_save(Eet_File *eetf, Edje_File *ef);
static void
_edje_edit_data_clean(Edje_Edit *eed)
{
Edje_Edit_Script_Error *se;
free(eed->bytecode);
free(eed->embryo_source);
free(eed->embryo_processed);
if (eed->program_scripts)
eina_hash_free(eed->program_scripts);
EINA_LIST_FREE(eed->errors, se)
{
eina_stringshare_del(se->program_name);
eina_stringshare_del(se->error_str);
free(se);
}
eed->bytecode = NULL;
eed->embryo_source = NULL;
eed->embryo_processed = NULL;
eed->program_scripts = NULL;
eed->bytecode_size = 0;
eed->bytecode_dirty = EINA_FALSE;
eed->embryo_source_dirty = EINA_FALSE;
eed->all_dirty = EINA_FALSE;
eed->script_need_recompile = EINA_FALSE;
}
static void
_edje_edit_smart_del(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
{
Edje_Edit *eed = _pd;
_edje_edit_data_clean(eed);
eo_do_super(obj, evas_obj_smart_del());
}
static void
_edje_edit_program_script_free(Program_Script *ps)
{
free(ps->code);
free(ps->processed);
free(ps);
}
static void
_edje_edit_smart_file_set(Eo *obj, void *_pd, va_list *list)
{
const char *file = va_arg(*list, const char *);
const char *group= va_arg(*list, const char *);
Eina_Bool *ret = va_arg(*list, Eina_Bool *);
Edje_Edit *eed = _pd;
Eet_File *ef;
char **keys, buf[64];
int count, i;
int len = strlen("edje/scripts/embryo/source/");
if (ret) *ret = EINA_FALSE;
_edje_edit_data_clean(eed);
/* TODO and maybes:
* * The whole point of this thing is keep track of stuff such as
* strings to free and who knows what, so we need to take care
* of those if the file/group changes.
* * Maybe have the possibility to open just files, not always with
* a group given.
* * A way to skip the cache? Could help avoid some issues when editing
* a group being used by the application in some other way, or multiple
* opens of the same file.
* * Here we probably want to allow opening groups with broken references
* (GROUP parts or BOX/TABLE items pointing to non-existent/renamed
* groups).
*/
Eina_Bool int_ret = EINA_FALSE;
eo_do_super(obj, edje_obj_file_set(file, group, &int_ret));
if (!int_ret)
return;
eed->program_scripts = eina_hash_int32_new((Eina_Free_Cb)_edje_edit_program_script_free);
ef = eet_open(file, EET_FILE_MODE_READ);
snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%i",
eed->base->collection->id);
eed->embryo_source = eet_read(ef, buf, &count);
snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%i/*",
eed->base->collection->id);
keys = eet_list(ef, buf, &count);
for (i = 0; i < count; i++)
{
Program_Script *ps;
int size;
ps = calloc(1, sizeof(Program_Script));
sscanf(keys[i] + len, "%*i/%i", &ps->id);
ps->code = eet_read(ef, keys[i], &size);
eina_hash_add(eed->program_scripts, &ps->id, ps);
}
if (keys) free(keys);
eet_close(ef);
if (ret) *ret = EINA_TRUE;
}
static void
_edje_edit_error_register(void)
{
EDJE_EDIT_ERROR_GROUP_DOES_NOT_EXIST =
eina_error_msg_static_register(EDJE_EDIT_ERROR_GROUP_DOES_NOT_EXIST_STR);
EDJE_EDIT_ERROR_GROUP_CURRENTLY_USED =
eina_error_msg_static_register(EDJE_EDIT_ERROR_GROUP_CURRENTLY_USED_STR);
EDJE_EDIT_ERROR_GROUP_REFERENCED =
eina_error_msg_static_register(EDJE_EDIT_ERROR_GROUP_REFERENCED_STR);
}
EAPI Evas_Object *
edje_edit_object_add(Evas *evas)
{
Evas_Object *e;
e = eo_add(MY_CLASS, evas);
eo_unref(e);
return e;
}
static void
_edje_edit_constructor(Eo *obj, void *class_data, va_list *list EINA_UNUSED)
{
Edje_Edit *eed = class_data;
eed->base = eo_data_get(obj, EDJE_OBJ_CLASS);
eo_do_super(obj, eo_constructor());
eina_error_set(0);
if (!EDJE_EDIT_ERROR_GROUP_DOES_NOT_EXIST)
_edje_edit_error_register();
}
/* End of Edje_Edit smart stuff */
static Edje_Part_Description_Common *
_edje_part_description_find_byname(Edje_Edit *eed, const char *part, const char *state, double value)
{
Edje_Real_Part *rp;
Edje_Part_Description_Common *pd;
if (!eed || !part || !state) return NULL;
rp = _edje_real_part_get((Edje *)eed, part);
if (!rp) return NULL;
pd = _edje_part_description_find((Edje *)eed, rp, state, value);
return pd;
}
static int
_edje_image_id_find(Edje_Edit *eed, const char *image_name)
{
unsigned int i;
if (!eed->base->file) return -1;
if (!eed->base->file->image_dir) return -1;
//printf("SEARCH IMAGE %s\n", image_name);
for (i = 0; i < eed->base->file->image_dir->entries_count; ++i)
if (eed->base->file->image_dir->entries[i].entry
&& !strcmp(image_name, eed->base->file->image_dir->entries[i].entry))
return i;
return -1;
}
static const char *
_edje_image_name_find(Edje_Edit *eed, int image_id)
{
if (!eed->base->file) return NULL;
if (!eed->base->file->image_dir) return NULL;
/* Special case for external image */
if (image_id < 0) image_id = -image_id - 1;
//printf("SEARCH IMAGE ID %d\n", image_id);
if ((unsigned int) image_id >= eed->base->file->image_dir->entries_count)
return NULL;
return eed->base->file->image_dir->entries[image_id].entry;
}
static void
_edje_real_part_free(Edje_Real_Part *rp)
{
if (!rp) return;
if (rp->object)
{
_edje_callbacks_del(rp->object, rp->edje);
evas_object_del(rp->object);
}
if (rp->typedata.swallow->swallowed_object)
{
evas_object_smart_member_del(rp->typedata.swallow->swallowed_object);
evas_object_event_callback_del(rp->typedata.swallow->swallowed_object,
EVAS_CALLBACK_FREE,
_edje_object_part_swallow_free_cb);
evas_object_clip_unset(rp->typedata.swallow->swallowed_object);
evas_object_data_del(rp->typedata.swallow->swallowed_object, "\377 edje.swallowing_part");
if (rp->part->mouse_events)
_edje_callbacks_del(rp->typedata.swallow->swallowed_object, rp->edje);
if (rp->part->type == EDJE_PART_TYPE_GROUP ||
rp->part->type == EDJE_PART_TYPE_EXTERNAL)
evas_object_del(rp->typedata.swallow->swallowed_object);
rp->typedata.swallow->swallowed_object = NULL;
}
if (rp->typedata.text->text) eina_stringshare_del(rp->typedata.text->text);
if (rp->typedata.text->font) eina_stringshare_del(rp->typedata.text->font);
if (rp->typedata.text->cache.in_str) eina_stringshare_del(rp->typedata.text->cache.in_str);
if (rp->typedata.text->cache.out_str) eina_stringshare_del(rp->typedata.text->cache.out_str);
if (rp->custom)
{
_edje_collection_free_part_description_clean(rp->part->type, rp->custom->description, 0);
if (rp->custom) free(rp->custom->set);
eina_mempool_free(_edje_real_part_state_mp, rp->custom);
rp->custom = NULL;
}
free(rp->drag);
if (rp->param2) free(rp->param2->set);
eina_mempool_free(_edje_real_part_state_mp, rp->param2);
_edje_unref(rp->edje);
eina_mempool_free(_edje_real_part_mp, rp);
}
static Eina_Bool
_edje_import_font_file(Edje *ed, const char *path, const char *entry)
{
Eina_File *f;
Eet_File *eetf = NULL;
void *fdata = NULL;
long fsize = 0;
/* Read font data from file */
f = eina_file_open(path, 0);
if (!f)
{
ERR("Unable to open font file \"%s\"", path);
return EINA_FALSE;
}
fsize = eina_file_size_get(f);
fdata = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
if (!fdata)
{
ERR("Unable to map font file \"%s\"", path);
goto on_error;
}
/* Write font to edje file */
eetf = eet_open(ed->path, EET_FILE_MODE_READ_WRITE);
if (!eetf)
{
ERR("Unable to open \"%s\" for writing output", ed->path);
goto on_error;
}
if (eet_write(eetf, entry, fdata, fsize, 1) <= 0)
{
ERR("Unable to write font part \"%s\" as \"%s\" part entry",
path, entry);
goto on_error;
}
/* write the edje_file */
if (!_edje_edit_edje_file_save(eetf, ed->file))
goto on_error;
eet_close(eetf);
eina_file_map_free(f, fdata);
eina_file_close(f);
return EINA_TRUE;
on_error:
if (eetf) eet_close(eetf);
eina_file_map_free(f, fdata);
eina_file_close(f);
return EINA_FALSE;
}
static Eina_Bool
_edje_import_image_file(Edje *ed, const char *path, int id)
{
char entry[PATH_MAX];
Evas_Object *im;
Eet_File *eetf;
void *im_data;
int im_w, im_h;
int im_alpha;
int bytes;
/* Try to load the file */
im = evas_object_image_add(ed->base->evas);
if (!im) return EINA_FALSE;
evas_object_image_file_set(im, path, NULL);
if (evas_object_image_load_error_get(im) != EVAS_LOAD_ERROR_NONE)
{
ERR("Edje_Edit: unable to load image \"%s\"."
"Missing PNG or JPEG loader modules for Evas or "
"file does not exist, or is not readable.", path);
evas_object_del(im);
im = NULL;
return EINA_FALSE;
}
/* Write the loaded image to the edje file */
evas_object_image_size_get(im, &im_w, &im_h);
im_alpha = evas_object_image_alpha_get(im);
im_data = evas_object_image_data_get(im, 0);
if ((!im_data) || !(im_w > 0) || !(im_h > 0))
{
evas_object_del(im);
return EINA_FALSE;
}
/* 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);
evas_object_del(im);
return EINA_FALSE;
}
snprintf(entry, sizeof(entry), "edje/images/%i", id);
/* write the image data */
bytes = eet_data_image_write(eetf, entry,
im_data, im_w, im_h,
im_alpha,
0, 100, 1);
if (bytes <= 0)
{
ERR("Unable to write image part \"%s\" part entry to %s",
entry, ed->path);
eet_close(eetf);
evas_object_del(im);
return EINA_FALSE;
}
evas_object_del(im);
/* write the edje_file */
if (!_edje_edit_edje_file_save(eetf, ed->file))
{
eet_delete(eetf, entry);
eet_close(eetf);
return EINA_FALSE;
}
eet_close(eetf);
return EINA_TRUE;
}
static int
_edje_part_id_find(Edje *ed, const char *part)
{
unsigned int id;
for (id = 0; id < ed->table_parts_size; id++)
{
Edje_Real_Part *rp = ed->table_parts[id];
if (!strcmp(rp->part->name, part))
return id;
}
return -1;
}
static void
_edje_part_description_id_set(int type, Edje_Part_Description_Common *c, int old_id, int new_id)
{
if (c->rel1.id_x == old_id) c->rel1.id_x = new_id;
if (c->rel1.id_y == old_id) c->rel1.id_y = new_id;
if (c->rel2.id_x == old_id) c->rel2.id_x = new_id;
if (c->rel2.id_y == old_id) c->rel2.id_y = new_id;
if (type == EDJE_PART_TYPE_TEXT
|| type == EDJE_PART_TYPE_TEXTBLOCK)
{
Edje_Part_Description_Text *t;
t = (Edje_Part_Description_Text *) c;
if (t->text.id_source == old_id) t->text.id_source = new_id;
if (t->text.id_text_source == old_id) t->text.id_text_source = new_id;
}
}
static void
_edje_part_program_id_set(Edje_Program *epr, int old_id, int new_id)
{
Edje_Program_Target *pt;
Eina_List *ll, *l_next;
if (epr->action != EDJE_ACTION_TYPE_STATE_SET)
return;
EINA_LIST_FOREACH_SAFE(epr->targets, ll, l_next, pt)
{
if (pt->id == old_id)
{
if (new_id == -1)
epr->targets = eina_list_remove_list(epr->targets, ll);
else
pt->id = new_id;
}
}
}
static void
_edje_part_id_set(Edje *ed, Edje_Real_Part *rp, int new_id)
{
/* This function change the id of a given real_part.
* All the depedency will be updated too.
* Also the table_parts is updated, and the current *rp in the table
* is lost.
* If new Id = -1 then all the depencies will be deleted
*/
Edje_Part *part;
unsigned int j;
int old_id;
part = rp->part;
if (!part) return;
//printf("CHANGE ID OF PART %s TO %d\n", part->name, new_id);
if (!ed || new_id < -1) return;
if (part->id == new_id) return;
old_id = part->id;
part->id = new_id;
/* Fix all the dependecies in all parts... */
for (j = 0; j < ed->collection->parts_count; ++j)
{
Edje_Part *p;
unsigned int k;
p = ed->collection->parts[j];
//printf(" search id: %d in %s\n", old_id, p->name);
if (p->clip_to_id == old_id) p->clip_to_id = new_id;
if (p->dragable.confine_id == old_id) p->dragable.confine_id = new_id;
/* ...in default description */
_edje_part_description_id_set(p->type, p->default_desc, old_id, new_id);
/* ...and in all other descriptions */
for (k = 0; k < p->other.desc_count; ++k)
_edje_part_description_id_set(p->type, p->other.desc[k], old_id, new_id);
}
/*...and also in programs targets */
#define EDJE_EDIT_PROGRAM_ID_SET(Array, Ed, It, Old, New) \
for (It = 0; It < Ed->collection->programs.Array##_count; ++It) \
_edje_part_program_id_set(Ed->collection->programs.Array[It], Old, New);
EDJE_EDIT_PROGRAM_ID_SET(fnmatch, ed, j, old_id, new_id);
EDJE_EDIT_PROGRAM_ID_SET(strcmp, ed, j, old_id, new_id);
EDJE_EDIT_PROGRAM_ID_SET(strncmp, ed, j, old_id, new_id);
EDJE_EDIT_PROGRAM_ID_SET(strrncmp, ed, j, old_id, new_id);
EDJE_EDIT_PROGRAM_ID_SET(nocmp, ed, j, old_id, new_id);
/* Adjust table_parts */
if (new_id >= 0)
ed->table_parts[new_id] = rp;
}
static void
_edje_part_description_id_switch(int type, Edje_Part_Description_Common *c, int id1, int id2)
{
if (c->rel1.id_x == id1) c->rel1.id_x = id2;
else if (c->rel1.id_x == id2) c->rel1.id_x = id1;
if (c->rel1.id_y == id1) c->rel1.id_y = id2;
else if (c->rel1.id_y == id2) c->rel1.id_y = id1;
if (c->rel2.id_x == id1) c->rel2.id_x = id2;
else if (c->rel2.id_x == id2) c->rel2.id_x = id1;
if (c->rel2.id_y == id1) c->rel2.id_y = id2;
else if (c->rel2.id_y == id2) c->rel2.id_y = id1;
if (type == EDJE_PART_TYPE_TEXT
|| type == EDJE_PART_TYPE_TEXTBLOCK)
{
Edje_Part_Description_Text *t;
t = (Edje_Part_Description_Text *) c;
if (t->text.id_source == id1) t->text.id_source = id2;
else if (t->text.id_source == id2) t->text.id_source = id1;
if (t->text.id_text_source == id1) t->text.id_text_source = id2;
else if (t->text.id_text_source == id2) t->text.id_text_source = id2;
}
}
static void
_edje_part_program_id_switch(Edje_Program *epr, int id1, int id2)
{
Edje_Program_Target *pt;
Eina_List *ll;
if (epr->action != EDJE_ACTION_TYPE_STATE_SET)
return;
EINA_LIST_FOREACH(epr->targets, ll, pt)
{
if (pt->id == id1) pt->id = id2;
else if (pt->id == id2) pt->id = id1;
}
}
static void
_edje_parts_id_switch(Edje *ed, Edje_Real_Part *rp1, Edje_Real_Part *rp2)
{
/* This function switch the id of two parts.
* All the depedency will be updated too.
* Also the table_parts is updated,
* The parts list isn't touched
*/
int id1;
int id2;
unsigned int i;
//printf("SWITCH ID OF PART %d AND %d\n", rp1->part->id, rp2->part->id);
if (!ed || !rp1 || !rp2) return;
if (rp1 == rp2) return;
id1 = rp1->part->id;
id2 = rp2->part->id;
/* Switch ids */
rp1->part->id = id2;
rp2->part->id = id1;
/* adjust table_parts */
ed->table_parts[id1] = rp2;
ed->table_parts[id2] = rp1;
// Fix all the dependecies in all parts...
for (i = 0; i < ed->collection->parts_count; ++i)
{
unsigned int j;
Edje_Part *p;
p = ed->collection->parts[i];
//printf(" search id: %d in %s\n", old_id, p->name);
if (p->clip_to_id == id1) p->clip_to_id = id2;
else if (p->clip_to_id == id2) p->clip_to_id = id1;
if (p->dragable.confine_id == id1) p->dragable.confine_id = id2;
else if (p->dragable.confine_id == id2) p->dragable.confine_id = id1;
// ...in default description
_edje_part_description_id_switch(p->type, p->default_desc, id1, id2);
// ...and in all other descriptions
for (j = 0; j < p->other.desc_count; ++j)
_edje_part_description_id_switch(p->type, p->other.desc[j], id1, id2);
}
//...and also in programs targets
#define EDJE_EDIT_PROGRAM_SWITCH(Array, Ed, It, Id1, Id2) \
for (It = 0; It < Ed->collection->programs.Array##_count; ++It) \
_edje_part_program_id_switch(Ed->collection->programs.Array[i], Id1, Id2);
EDJE_EDIT_PROGRAM_SWITCH(fnmatch, ed, i, id1, id2);
EDJE_EDIT_PROGRAM_SWITCH(strcmp, ed, i, id1, id2);
EDJE_EDIT_PROGRAM_SWITCH(strncmp, ed, i, id1, id2);
EDJE_EDIT_PROGRAM_SWITCH(strrncmp, ed, i, id1, id2);
EDJE_EDIT_PROGRAM_SWITCH(nocmp, ed, i, id1, id2);
//TODO Real part dependencies are ok?
}
static void
_edje_fix_parts_id(Edje *ed)
{
/* We use this to clear the id hole leaved when a part is removed.
* After the execution of this function all parts will have a right
* (uniqe & ordered) id. The table_parts is also updated.
*/
unsigned int i;
int correct_id;
unsigned int count;
//printf("FIXING PARTS ID \n");
//TODO order the list first to be more robust
/* Give a correct id to all the parts */
correct_id = 0;
for (i = 0; i < ed->collection->parts_count; ++i)
{
Edje_Part *p;
p = ed->collection->parts[i];
//printf(" [%d]Checking part: %s id: %d\n", correct_id, p->name, p->id);
if (p->id != correct_id)
if (ed->table_parts[p->id])
_edje_part_id_set(ed, ed->table_parts[p->id], correct_id);
correct_id++;
}
/* If we have removed some parts realloc table_parts */
count = ed->collection->parts_count;
if (count != ed->table_parts_size)
{
ed->table_parts = realloc(ed->table_parts, sizeof(Edje_Real_Part *) * count);
ed->table_parts_size = count;
}
//printf("\n");
}
static void
_edje_if_string_free(Edje *ed, const char *str)
{
Eet_Dictionary *dict;
if (!ed || !str) return;
dict = eet_dictionary_get(ed->file->ef);
if (eet_dictionary_string_check(dict, str)) return;
eina_stringshare_del(str);
str = NULL;
}
static Edje_Style *
_edje_edit_style_get(Edje *ed, const char *name)
{
Eina_List *l;
Edje_Style *s;
if (!ed || !ed->file || !ed->file->styles || !name)
return NULL;
EINA_LIST_FOREACH(ed->file->styles, l, s)
if (s->name && !strcmp(s->name, name))
return s;
return NULL;
}
static Edje_Style_Tag *
_edje_edit_style_tag_get(Edje *ed, const char *style, const char *name)
{
Eina_List *l;
Edje_Style *s;
Edje_Style_Tag *t;
if (!ed || !ed->file || !ed->file->styles || !name)
return NULL;
s = _edje_edit_style_get(ed, style);
EINA_LIST_FOREACH(s->tags, l, t)
if (t->key && !strcmp(t->key, name))
return t;
return NULL;
}
static Edje_External_Directory_Entry *
_edje_edit_external_get(Edje *ed, const char *name)
{
unsigned int i;
if (!ed || !ed->file || !ed->file->external_dir || !name)
return NULL;
for (i = 0; i < ed->file->external_dir->entries_count; ++i)
if (ed->file->external_dir->entries[i].entry
&& !strcmp(ed->file->external_dir->entries[i].entry, name))
return ed->file->external_dir->entries + i;
return NULL;
}
static void
_edje_edit_group_references_update(Evas_Object *obj, const char *old_group_name, const char *new_group_name)
{
Eina_Iterator *i;
Eina_List *pll, *pl;
// Edje_Part_Collection *pc;
Edje_Part_Collection_Directory_Entry *pce;
char *part_name;
const char *source, *old;
Edje_Part_Type type;
Evas_Object *part_obj;
GET_ED_OR_RETURN();
// pc = ed->collection;
part_obj = edje_edit_object_add(ed->base->evas);
old = eina_stringshare_add(old_group_name);
i = eina_hash_iterator_data_new(ed->file->collection);
EINA_ITERATOR_FOREACH(i, pce)
{
edje_object_file_set(part_obj, ed->file->path, pce->entry);
pl = edje_edit_parts_list_get(part_obj);
EINA_LIST_FOREACH(pl, pll, part_name)
{
source = edje_edit_part_source_get(part_obj, part_name);
type = edje_edit_part_type_get(part_obj, part_name);
if (type == EDJE_PART_TYPE_GROUP && source == old)
edje_edit_part_source_set(part_obj, part_name, new_group_name);
if (source)
eina_stringshare_del(source);
}
}
eina_iterator_free(i);
eina_stringshare_del(old);
evas_object_del(part_obj);
}
static void
_edje_edit_flag_script_dirty(Edje_Edit *eed, Eina_Bool all)
{
eed->script_need_recompile = EINA_TRUE;
if (all)
eed->all_dirty = EINA_TRUE;
}
/*****************/
/* GENERAL API */
/*****************/
EAPI void
edje_edit_string_list_free(Eina_List *lst)
{
eina_error_set(0);
//printf("FREE LIST: \n");
while (lst)
{
if (eina_list_data_get(lst)) eina_stringshare_del(eina_list_data_get(lst));
//printf("FREE: %s\n", eina_list_data_get(lst));
lst = eina_list_remove(lst, eina_list_data_get(lst));
}
}
EAPI void
edje_edit_string_free(const char *str)
{
eina_error_set(0);
if (str) eina_stringshare_del(str);
}
EAPI const char*
edje_edit_compiler_get(Evas_Object *obj)
{
eina_error_set(0);
GET_ED_OR_RETURN(0);
return eina_stringshare_add(ed->file->compiler);
}
/****************/
/* GROUPS API */
/****************/
EAPI Eina_Bool
edje_edit_group_add(Evas_Object *obj, const char *name)
{
Edje_Part_Collection_Directory_Entry *de;
Edje_Part_Collection_Directory_Entry *d;
Edje_Part_Collection *pc;
int id;
int search;
//Code *cd;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
//printf("ADD GROUP: %s \n", name);
/* check if a group with the same name already exists */
if (eina_hash_find(ed->file->collection, name))
return EINA_FALSE;
/* Create structs */
de = _alloc(sizeof(Edje_Part_Collection_Directory_Entry));
if (!de) return EINA_FALSE;
pc = _alloc(sizeof(Edje_Part_Collection));
if (!pc)
{
free(de);
return EINA_FALSE;
}
/* Search first free id */
id = -1;
search = 0;
while (id == -1)
{
Eina_Iterator *i;
Eina_Bool found = 0;
i = eina_hash_iterator_data_new(ed->file->collection);
EINA_ITERATOR_FOREACH(i, d)
{
// printf("search if %d is free [id %d]\n", search, d->id);
if (search == d->id)
{
found = 1;
break;
}
}
eina_iterator_free(i);
if (!found) id = search;
else search++;
}
/* Init Edje_Part_Collection_Directory_Entry */
//printf(" new id: %d\n", id);
de->id = id;
de->entry = eina_stringshare_add(name);
eina_hash_direct_add(ed->file->collection, de->entry, de);
/* Init Edje_Part_Collection */
pc->id = id;
pc->references = 0;
memset(&pc->programs, 0, sizeof (pc->programs));
pc->parts = NULL;
pc->data = NULL;
pc->script = NULL;
pc->part = eina_stringshare_add(name);
//cd = _alloc(sizeof(Code));
//codes = eina_list_append(codes, cd);
#define EDIT_EMN(Tp, Sz, Ce) \
Ce->mp.Tp = eina_mempool_add("chained_mempool", #Tp, NULL, sizeof (Sz), 8);
EDIT_EMN(RECTANGLE, Edje_Part_Description_Common, de);
EDIT_EMN(TEXT, Edje_Part_Description_Text, de);
EDIT_EMN(IMAGE, Edje_Part_Description_Image, de);
EDIT_EMN(SWALLOW, Edje_Part_Description_Common, de);
EDIT_EMN(TEXTBLOCK, Edje_Part_Description_Text, de);
EDIT_EMN(GROUP, Edje_Part_Description_Common, de);
EDIT_EMN(BOX, Edje_Part_Description_Box, de);
EDIT_EMN(TABLE, Edje_Part_Description_Table, de);
EDIT_EMN(EXTERNAL, Edje_Part_Description_External, de);
EDIT_EMN(SPACER, Edje_Part_Description_Common, de);
EDIT_EMN(part, Edje_Part, de);
ed->file->collection_cache = eina_list_prepend(ed->file->collection_cache, pc);
_edje_cache_coll_clean(ed->file);
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_group_del(Evas_Object *obj, const char *group_name)
{
Edje_Part_Collection_Directory_Entry *e;
Edje_Part_Collection *die = NULL;
Edje_Part_Collection *g;
Eina_List *l;
Eet_File *eetf;
char buf[64], **keys;
int count;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
/* if (eina_hash_find(ed->file->collection_hash, group_name)) */
/* return EINA_FALSE; */
if (strcmp(ed->group, group_name) == 0)
{
eina_error_set(EDJE_EDIT_ERROR_GROUP_CURRENTLY_USED);
return EINA_FALSE;
}
e = eina_hash_find(ed->file->collection, group_name);
if (!e)
{
eina_error_set(EDJE_EDIT_ERROR_GROUP_DOES_NOT_EXIST);
return EINA_FALSE;
}
if (e->id == ed->collection->id)
{
eina_error_set(EDJE_EDIT_ERROR_GROUP_CURRENTLY_USED);
return EINA_FALSE;
}
if (e->ref)
{
eina_error_set(EDJE_EDIT_ERROR_GROUP_REFERENCED);
return EINA_FALSE;
}
_edje_edit_group_references_update(obj, group_name, NULL);
EINA_LIST_FOREACH(ed->file->collection_cache, l, g)
if (g->id == e->id)
{
ed->file->collection_cache =
eina_list_remove_list(ed->file->collection_cache, l);
die = g;
break;
}
/* Remove collection/id from eet file */
eetf = eet_open(ed->file->path, EET_FILE_MODE_READ_WRITE);
if (!eetf)
{
ERR("Edje_Edit: Error. unable to open \"%s\" "
"for writing output", ed->file->path);
return EINA_FALSE;
}
snprintf(buf, sizeof(buf), "edje/collections/%d", e->id);
eet_delete(eetf, buf);
snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%d", e->id);
eet_delete(eetf, buf);
snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%d", e->id);
eet_delete(eetf, buf);
snprintf(buf, sizeof(buf), "edje/scripts/embryo/source/%d/*", e->id);
keys = eet_list(eetf, buf, &count);
if (keys)
{
do
{
count--;
eet_delete(eetf, keys[count]);
}
while(count);
free(keys);
}
eet_close(eetf);
/* Free Group */
if (die) _edje_collection_free(ed->file, die, e);
eina_hash_del(ed->file->collection, group_name, e);
/* we need to save everything to make sure the file won't have broken
* references the next time is loaded */
edje_edit_save_all(obj);
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_group_exist(Evas_Object *obj, const char *group)
{
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (eina_hash_find(ed->file->collection, group))
return EINA_TRUE;
return EINA_FALSE;
}
EAPI Eina_Bool
edje_edit_group_name_set(Evas_Object *obj, const char *new_name)
{
Edje_Part_Collection_Directory_Entry *pce;
Edje_Part_Collection *pc;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!new_name) return EINA_FALSE;
pc = ed->collection;
if (!strcmp(pc->part, new_name)) return EINA_TRUE;
if (edje_edit_group_exist(obj, new_name)) return EINA_FALSE;
_edje_edit_group_references_update(obj, pc->part, new_name);
//printf("Set name of current group: %s [id: %d][new name: %s]\n",
// pc->part, pc->id, new_name);
//if (pc->part && ed->file->free_strings) eina_stringshare_del(pc->part); TODO FIXME
pce = eina_hash_find(ed->file->collection, pc->part);
eina_hash_move(ed->file->collection, pce->entry, new_name);
pce->entry = eina_stringshare_add(new_name);
pc->part = pce->entry;
eina_stringshare_replace(&ed->group, new_name);
return EINA_TRUE;
}
#define FUNC_GROUP_ACCESSOR(Class, Value) \
EAPI int \
edje_edit_group_##Class##_##Value##_get(Evas_Object *obj) \
{ \
eina_error_set(0); \
GET_ED_OR_RETURN(-1); \
if (!ed->collection) return -1; \
return ed->collection->prop.Class.Value; \
} \
EAPI void \
edje_edit_group_##Class##_##Value##_set(Evas_Object *obj, int v) \
{ \
eina_error_set(0); \
GET_ED_OR_RETURN(); \
ed->collection->prop.Class.Value = v; \
}
FUNC_GROUP_ACCESSOR(min, w);
FUNC_GROUP_ACCESSOR(min, h);
FUNC_GROUP_ACCESSOR(max, w);
FUNC_GROUP_ACCESSOR(max, h);
/***************/
/* DATA API */
/***************/
EAPI Eina_List *
edje_edit_group_data_list_get(Evas_Object * obj)
{
Eina_Iterator *it;
Eina_List *datas = NULL;
const char *key;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
if (!ed->file || !ed->collection || !ed->collection->data)
return NULL;
it = eina_hash_iterator_key_new(ed->collection->data);
if (!it) return NULL;
EINA_ITERATOR_FOREACH(it, key)
datas = eina_list_append(datas, eina_stringshare_add(key));
eina_iterator_free(it);
return datas;
}
EAPI Eina_List *
edje_edit_data_list_get(Evas_Object * obj)
{
Eina_Iterator *i;
Eina_List *datas = NULL;
const char *key;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
if (!ed->file || !ed->file->data)
return NULL;
i = eina_hash_iterator_key_new(ed->file->data);
EINA_ITERATOR_FOREACH(i, key)
datas = eina_list_append(datas, eina_stringshare_add(key));
eina_iterator_free(i);
return datas;
}
EAPI Eina_Bool
edje_edit_group_data_add(Evas_Object *obj, const char *key, const char *value)
{
Edje_String *es;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!key || !ed->file || !ed->collection)
return EINA_FALSE;
if (!ed->collection->data)
ed->collection->data = eina_hash_string_small_new(NULL);
if (eina_hash_find(ed->collection->data, key))
return EINA_FALSE;
es = calloc(1, sizeof(Edje_String));
if (!es)
return EINA_FALSE;
es->str = eina_stringshare_add(value);
if (!eina_hash_add(ed->collection->data, key, es))
{
eina_stringshare_del(es->str);
free(es);
return EINA_FALSE;
}
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_data_add(Evas_Object *obj, const char *itemname, const char *value)
{
Edje_String *es;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!itemname || !ed->file)
return EINA_FALSE;
if (eina_hash_find(ed->file->data, itemname))
return EINA_FALSE;
es = calloc(1, sizeof(Edje_String));
if (!es)
return EINA_FALSE;
es->str = eina_stringshare_add(value);
if (!eina_hash_add(ed->file->data, itemname, es))
{
eina_stringshare_del(es->str);
free(es);
return EINA_FALSE;
}
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_group_data_del(Evas_Object *obj, const char *key)
{
Edje_String *value;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!key || !ed->file || !ed->collection)
return EINA_FALSE;
value = eina_hash_find(ed->collection->data, key);
if (!value) return EINA_FALSE;
eina_hash_del(ed->collection->data, key, value);
_edje_if_string_free(ed, value->str);
free(value);
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_data_del(Evas_Object *obj, const char *itemname)
{
Edje_String *value;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!itemname || !ed->file || !ed->file->data)
return 0;
value = eina_hash_find(ed->file->data, itemname);
if (!value)
return EINA_FALSE;
eina_hash_del(ed->file->data, itemname, value);
_edje_if_string_free(ed, value->str);
free(value);
return EINA_TRUE;
}
EAPI const char *
edje_edit_group_data_value_get(Evas_Object * obj, const char *key)
{
Edje_String *value;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
if (!key || !ed->file || !ed->collection)
return NULL;
value = eina_hash_find(ed->collection->data, key);
if (!value)
return NULL;
return eina_stringshare_add(edje_string_get(value));
}
EAPI const char *
edje_edit_data_value_get(Evas_Object * obj, const char *itemname)
{
Edje_String *value;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
if (!itemname || !ed->file || !ed->file->data)
return NULL;
value = eina_hash_find(ed->file->data, itemname);
if (!value)
return NULL;
return eina_stringshare_add(edje_string_get(value));
}
EAPI Eina_Bool
edje_edit_group_data_value_set(Evas_Object *obj, const char *key, const char *value)
{
Edje_String *es;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!key || !value || !ed->file || !ed->collection)
return EINA_FALSE;
es = eina_hash_find(ed->collection->data, key);
if (es)
{
_edje_if_string_free(ed, es->str);
es->str = eina_stringshare_add(value);
es->id = 0;
return EINA_TRUE;
}
return EINA_FALSE;
}
EAPI Eina_Bool
edje_edit_data_value_set(Evas_Object *obj, const char *itemname, const char *value)
{
Edje_String *es;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!itemname || !value || !ed->file || !ed->file->data)
return EINA_FALSE;
es = eina_hash_find(ed->file->data, itemname);
if (es)
{
_edje_if_string_free(ed, es->str);
es->str = eina_stringshare_add(value);
es->id = 0;
return EINA_TRUE;
}
return EINA_FALSE;
}
EAPI Eina_Bool
edje_edit_group_data_name_set(Evas_Object *obj, const char *key, const char *new_key)
{
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!key || !new_key || !ed->file || !ed->collection) {
return EINA_FALSE;
}
return eina_hash_move(ed->collection->data, key, new_key);
}
EAPI Eina_Bool
edje_edit_data_name_set(Evas_Object *obj, const char *itemname, const char *newname)
{
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!itemname || !newname || !ed->file || !ed->file->data)
return EINA_FALSE;
return eina_hash_move(ed->file->data, itemname, newname);
}
/***********************/
/* COLOR CLASSES API */
/***********************/
EAPI Eina_List *
edje_edit_color_classes_list_get(Evas_Object * obj)
{
Eina_List *classes = NULL;
Eina_List *l;
Edje_Color_Class *cc;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
if (!ed->file || !ed->file->color_classes)
return NULL;
//printf("GET CLASSES LIST %d %d\n", eina_list_count(ed->color_classes), eina_list_count(ed->file->color_classes));
EINA_LIST_FOREACH(ed->file->color_classes, l, cc)
classes = eina_list_append(classes, eina_stringshare_add(cc->name));
return classes;
}
EAPI Eina_Bool
edje_edit_color_class_colors_get(Evas_Object *obj, const char *class_name, int *r, int *g, int *b, int *a, int *r2, int *g2, int *b2, int *a2, int *r3, int *g3, int *b3, int *a3)
{
Eina_List *l;
Edje_Color_Class *cc;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!ed->file || !ed->file->color_classes)
return EINA_FALSE;
EINA_LIST_FOREACH(ed->file->color_classes, l, cc)
if (!strcmp(cc->name, class_name))
{
if (r) *r = cc->r;
if (g) *g = cc->g;
if (b) *b = cc->b;
if (a) *a = cc->a;
if (r2) *r2 = cc->r2;
if (g2) *g2 = cc->g2;
if (b2) *b2 = cc->b2;
if (a2) *a2 = cc->a2;
if (r3) *r3 = cc->r3;
if (g3) *g3 = cc->g3;
if (b3) *b3 = cc->b3;
if (a3) *a3 = cc->a3;
return EINA_TRUE;
}
return EINA_FALSE;
}
EAPI Eina_Bool
edje_edit_color_class_colors_set(Evas_Object *obj, const char *class_name, int r, int g, int b, int a, int r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3)
{
Eina_List *l;
Edje_Color_Class *cc;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!ed->file || !ed->file->color_classes)
return EINA_FALSE;
EINA_LIST_FOREACH(ed->file->color_classes, l, cc)
if (!strcmp(cc->name, class_name))
{
if (r > -1) cc->r = r;
if (g > -1) cc->g = g;
if (b > -1) cc->b = b;
if (a > -1) cc->a = a;
if (r2 > -1) cc->r2 = r2;
if (g2 > -1) cc->g2 = g2;
if (b2 > -1) cc->b2 = b2;
if (a2 > -1) cc->a2 = a2;
if (r3 > -1) cc->r3 = r3;
if (g3 > -1) cc->g3 = g3;
if (b3 > -1) cc->b3 = b3;
if (a3 > -1) cc->a3 = a3;
return EINA_TRUE;
}
return EINA_FALSE;
}
EAPI Eina_Bool
edje_edit_color_class_add(Evas_Object *obj, const char *name)
{
Eina_List *l;
Edje_Color_Class *c;
Edje_Color_Class *cc;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!name || !ed->file)
return EINA_FALSE;
EINA_LIST_FOREACH(ed->file->color_classes, l, cc)
if (strcmp(cc->name, name) == 0)
return EINA_FALSE;
c = _alloc(sizeof(Edje_Color_Class));
if (!c) return EINA_FALSE;
c->name = (char*)eina_stringshare_add(name);
c->r = c->g = c->b = c->a = 255;
c->r2 = c->g2 = c->b2 = c->a2 = 255;
c->r3 = c->g3 = c->b3 = c->a3 = 255;
ed->file->color_classes = eina_list_append(ed->file->color_classes, c);
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_color_class_del(Evas_Object *obj, const char *name)
{
Eina_List *l;
Edje_Color_Class *cc;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!name || !ed->file || !ed->file->color_classes)
return EINA_FALSE;
EINA_LIST_FOREACH(ed->file->color_classes, l, cc)
if (strcmp(cc->name, name) == 0)
{
_edje_if_string_free(ed, cc->name);
ed->file->color_classes = eina_list_remove(ed->file->color_classes, cc);
free(cc);
return EINA_TRUE;
}
return EINA_FALSE;
}
EAPI Eina_Bool
edje_edit_color_class_name_set(Evas_Object *obj, const char *name, const char *newname)
{
Eina_List *l;
Edje_Color_Class *cc;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
if (!ed->file || !ed->file->color_classes)
return EINA_FALSE;
EINA_LIST_FOREACH(ed->file->color_classes, l, cc)
if (!strcmp(cc->name, name))
{
_edje_if_string_free(ed, cc->name);
cc->name = (char*)eina_stringshare_add(newname);
return EINA_TRUE;
}
return EINA_FALSE;
}
/*********************/
/* TEXT STYLES API */
/*********************/
EAPI Eina_List *
edje_edit_styles_list_get(Evas_Object * obj)
{
Eina_List *styles = NULL;
Eina_List *l;
Edje_Style *s;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
if (!ed->file || !ed->file->styles)
return NULL;
//printf("GET STYLES LIST %d\n", eina_list_count(ed->file->styles));
EINA_LIST_FOREACH(ed->file->styles, l, s)
styles = eina_list_append(styles, eina_stringshare_add(s->name));
return styles;
}
EAPI Eina_Bool
edje_edit_style_add(Evas_Object * obj, const char* style)
{
Edje_Style *s;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
//printf("ADD STYLE '%s'\n", style);
s = _edje_edit_style_get(ed, style);
if (s) return EINA_FALSE;
s = _alloc(sizeof(Edje_Style));
if (!s) return EINA_FALSE;
s->name = (char*)eina_stringshare_add(style);
s->tags = NULL;
s->style = NULL;
ed->file->styles = eina_list_append(ed->file->styles, s);
return EINA_TRUE;
}
EAPI void
edje_edit_style_del(Evas_Object * obj, const char* style)
{
Edje_Style *s;
eina_error_set(0);
GET_ED_OR_RETURN();
//printf("DEL STYLE '%s'\n", style);
s = _edje_edit_style_get(ed, style);
if (!s) return;
ed->file->styles = eina_list_remove(ed->file->styles, s);
_edje_if_string_free(ed, s->name);
//~ //s->style HOWTO FREE ???
while (s->tags)
{
Edje_Style_Tag *t;
t = s->tags->data;
s->tags = eina_list_remove(s->tags, t);
_edje_if_string_free(ed, t->key);
_edje_if_string_free(ed, t->value);
_edje_if_string_free(ed, t->font);
_edje_if_string_free(ed, t->text_class);
free(t);
t = NULL;
}
free(s);
s = NULL;
s = NULL;
}
EAPI Eina_List *
edje_edit_style_tags_list_get(Evas_Object * obj, const char* style)
{
Eina_List *tags = NULL;
Eina_List *l;
Edje_Style *s;
Edje_Style_Tag *t;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
if (!ed->file || !ed->file->styles || !style)
return NULL;
s = _edje_edit_style_get(ed, style);
//printf("GET STYLE TAG LIST %d\n", eina_list_count(s->tags));
EINA_LIST_FOREACH(s->tags, l, t)
tags = eina_list_append(tags, eina_stringshare_add(t->key));
return tags;
}
EAPI void
edje_edit_style_tag_name_set(Evas_Object * obj, const char* style, const char* tag, const char*new_name)
{
Edje_Style_Tag *t;
eina_error_set(0);
GET_ED_OR_RETURN();
//printf("SET TAG NAME for '%s' FOR STYLE '%s'\n", tag, style);
if (!ed->file || !ed->file->styles || !style || !tag)
return;
t = _edje_edit_style_tag_get(ed, style, tag);
if (!t) return;
_edje_if_string_free(ed, t->key);
t->key = eina_stringshare_add(new_name);
}
EAPI const char*
edje_edit_style_tag_value_get(Evas_Object * obj, const char* style, const char* tag)
{
Edje_Style_Tag *t;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
//printf("GET TAG '%s' FOR STYLE '%s'\n", tag, style);
if (!ed->file || !ed->file->styles || !style || !tag)
return NULL;
t = _edje_edit_style_tag_get(ed, style, tag);
if (t && t->value)
return eina_stringshare_add(t->value);
return NULL;
}
EAPI void
edje_edit_style_tag_value_set(Evas_Object * obj, const char* style, const char* tag, const char*new_value)
{
Edje_Style_Tag *t;
eina_error_set(0);
GET_ED_OR_RETURN();
//printf("SET TAG VALUE for '%s' FOR STYLE '%s'\n", tag, style);
if (!ed->file || !ed->file->styles || !style || !tag)
return;
t = _edje_edit_style_tag_get(ed, style, tag);
if (!t) return;
_edje_if_string_free(ed, t->value);
t->value = eina_stringshare_add(new_value);
}
EAPI Eina_Bool
edje_edit_style_tag_add(Evas_Object * obj, const char* style, const char* tag_name)
{
Edje_Style *s;
Edje_Style_Tag *t;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
//printf("ADD TAG '%s' IN STYLE '%s'\n", tag_name, style);
t = _edje_edit_style_tag_get(ed, style, tag_name);
if (t) return EINA_FALSE;
s = _edje_edit_style_get(ed, style);
if (!s) return EINA_FALSE;
t = _alloc(sizeof(Edje_Style_Tag));
if (!t) return EINA_FALSE;
t->key = eina_stringshare_add(tag_name);
t->value = NULL;
t->font = NULL;
t->text_class = NULL;
s->tags = eina_list_append(s->tags, t);
return EINA_TRUE;
}
EAPI void
edje_edit_style_tag_del(Evas_Object * obj, const char* style, const char* tag)
{
Edje_Style *s;
Edje_Style_Tag *t;
eina_error_set(0);
GET_ED_OR_RETURN();
//printf("DEL TAG '%s' IN STYLE '%s'\n", tag, style);
s = _edje_edit_style_get(ed, style);
t = _edje_edit_style_tag_get(ed, style, tag);
s->tags = eina_list_remove(s->tags, t);
_edje_if_string_free(ed, t->key);
_edje_if_string_free(ed, t->value);
_edje_if_string_free(ed, t->font);
_edje_if_string_free(ed, t->text_class);
free(t);
t = NULL;
}
/*******************/
/* EXTERNALS API */
/*******************/
EAPI Eina_List *
edje_edit_externals_list_get(Evas_Object *obj)
{
Eina_List *externals = NULL;
unsigned int i;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
if (!ed->file || !ed->file->external_dir)
return NULL;
//printf("GET STYLES LIST %d\n", eina_list_count(ed->file->styles));
for (i = 0; i < ed->file->external_dir->entries_count; ++i)
externals = eina_list_append(externals,
eina_stringshare_add(ed->file->external_dir->entries[i].entry));
return externals;
}
EAPI Eina_Bool
edje_edit_external_add(Evas_Object *obj, const char *external)
{
Edje_External_Directory_Entry *e;
unsigned int freeid;
unsigned int i;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
e = _edje_edit_external_get(ed, external);
if (e) return EINA_FALSE;
if (!ed->file->external_dir)
ed->file->external_dir = _alloc(sizeof(Edje_External_Directory));
for (i = 0; i < ed->file->external_dir->entries_count; ++i)
if (!ed->file->external_dir->entries[i].entry)
break ;
if (i == ed->file->external_dir->entries_count)
{
Edje_External_Directory_Entry *tmp;
unsigned int max;
max = ed->file->external_dir->entries_count + 1;
tmp = realloc(ed->file->external_dir->entries,
sizeof (Edje_External_Directory_Entry) * max);
if (!tmp) return EINA_FALSE;
ed->file->external_dir->entries = tmp;
freeid = ed->file->external_dir->entries_count;
ed->file->external_dir->entries_count = max;
}
else
freeid = i;
ed->file->external_dir->entries[freeid].entry = (char*)eina_stringshare_add(external);
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_external_del(Evas_Object *obj, const char *external)
{
Edje_External_Directory_Entry *e;
eina_error_set(0);
GET_ED_OR_RETURN(EINA_FALSE);
e = _edje_edit_external_get(ed, external);
if (!e) return EINA_FALSE;
_edje_if_string_free(ed, e->entry);
e->entry = NULL;
return EINA_TRUE;
}
/***************/
/* PARTS API */
/***************/
EAPI Eina_List *
edje_edit_parts_list_get(Evas_Object *obj)
{
Eina_List *parts = NULL;
unsigned int i;
eina_error_set(0);
GET_ED_OR_RETURN(NULL);
//printf("EE: Found %d parts\n", ed->table_parts_size);
parts = NULL;
for (i = 0; i < ed->table_parts_size; i++)
{
Edje_Real_Part *rp;
rp = ed->table_parts[i];
parts = eina_list_append(parts, eina_stringshare_add(rp->part->name));
}
return parts;
}
EAPI Eina_Bool
edje_edit_part_name_set(Evas_Object *obj, const char* part, const char* new_name)
{
eina_error_set(0);
GET_RP_OR_RETURN(EINA_FALSE);
if (!new_name) return EINA_FALSE;
if (!strcmp(part, new_name)) return EINA_TRUE;
if (_edje_real_part_get(ed, new_name)) return EINA_FALSE;
//printf("Set name of part: %s [new name: %s]\n", part, new_name);
_edje_if_string_free(ed, rp->part->name);
rp->part->name = (char *)eina_stringshare_add(new_name);
_edje_edit_flag_script_dirty(eed, EINA_TRUE);
return EINA_TRUE;
}
#define FUNC_PART_API_STRING(Value) \
EAPI const char * \
edje_edit_part_api_##Value##_get(Evas_Object *obj, const char *part) \
{ \
eina_error_set(0); \
GET_RP_OR_RETURN(NULL); \
return eina_stringshare_add(rp->part->api.Value); \
} \
EAPI Eina_Bool \
edje_edit_part_api_##Value##_set(Evas_Object *obj, const char *part, const char *s) \
{ \
eina_error_set(0); \
GET_RP_OR_RETURN(EINA_FALSE); \
_edje_if_string_free(ed, rp->part->api.Value); \
rp->part->api.Value = eina_stringshare_add(s); \
return EINA_TRUE; \
}
FUNC_PART_API_STRING(name);
FUNC_PART_API_STRING(description);
static Eina_Bool
_edje_edit_real_part_add(Evas_Object *obj, const char *name, Edje_Part_Type type, const char *source)
{
Edje_Part_Collection_Directory_Entry *ce;
Edje_Part_Collection *pc;
Edje_Part **tmp;
Edje_Part *ep;
Edje_Real_Part *rp;
int id;
GET_ED_OR_RETURN(EINA_FALSE);
//printf("ADD PART: %s [type: %d]\n", name, type);
/* Check if part already exists */
if (_edje_real_part_get(ed, name))
return EINA_FALSE;
ce = eina_hash_find(ed->file->collection, ed->group);
/* Alloc Edje_Part or return */
ep = eina_mempool_malloc(ce->mp.part, sizeof(Edje_Part));
if (!ep) return EINA_FALSE;
memset(ep, 0, sizeof(Edje_Part));
/* Alloc Edje_Real_Part or return */
rp = eina_mempool_malloc(_edje_real_part_mp, sizeof(Edje_Real_Part));
if (!rp)
{
eina_mempool_free(ce->mp.part, ep);
return EINA_FALSE;
}
memset(rp, 0, sizeof(Edje_Real_Part));
/* Init Edje_Part */
pc = ed->collection;
tmp = realloc(pc->parts, (pc->parts_count + 1) * sizeof (Edje_Part *));
if (!tmp)
{
eina_mempool_free(ce->mp.part, ep);
eina_mempool_free(_edje_real_part_mp, rp);
return EINA_FALSE;
}
id = pc->parts_count++;
pc->parts = tmp;
pc->parts[id] = ep;
ep->id = id;
ep->type = type;
ep->name = eina_stringshare_add(name);
ep->mouse_events = 1;
ep->repeat_events = 0;
ep->ignore_flags = EVAS_EVENT_FLAG_NONE;
ep->pointer_mode = EVAS_OBJECT_POINTER_MODE_AUTOGRAB;
ep->precise_is_inside = 0;
ep->use_alternate_font_metrics = 0;
ep->clip_to_id = -1;
ep->dragable.confine_id = -1;
ep->dragable.event_id = -1;
if (source)
ep->source = eina_stringshare_add(source);
ep->default_desc = NULL;
ep->other.desc = NULL;
ep->other.desc_count = 0;
/* Init Edje_Real_Part */
rp->edje = ed;
_edje_ref(rp->edje);
rp->part = ep;
if (ep->type == EDJE_PART_TYPE_RECTANGLE)
rp->object = evas_object_rectangle_add(ed->base->evas);
else if (ep->type == EDJE_PART_TYPE_IMAGE || ep->type == EDJE_PART_TYPE_PROXY)
rp->object = evas_object_image_add(ed->base->evas);
else if (ep->type == EDJE_PART_TYPE_TEXT)
{
_edje_text_part_on_add(ed, rp);
rp->object = evas_object_text_add(ed->base->evas);
evas_object_text_font_source_set(rp->object, ed->path);
}
else if (ep->type == EDJE_PART_TYPE_SWALLOW ||
ep->type == EDJE_PART_TYPE_GROUP ||
ep->type == EDJE_PART_TYPE_EXTERNAL)
{
rp->object = evas_object_rectangle_add(ed->base->evas);
evas_object_color_set(rp->object, 0, 0, 0, 0);
evas_object_pass_events_set(rp->object, 1);
evas_object_pointer_mode_set(rp->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
}
else if (ep->type == EDJE_PART_TYPE_TEXTBLOCK)
rp->object = evas_object_textblock_add(ed->base->evas);
else if (ep->type != EDJE_PART_TYPE_SPACER)
ERR("wrong part type %i!", ep->type);
if (rp->object)
{
evas_object_show(rp->object);
evas_object_smart_member_add(rp->object, ed->obj);
evas_object_layer_set(rp->object, evas_object_layer_get(ed->obj));
if (ep->type != EDJE_PART_TYPE_SWALLOW && ep->type != EDJE_PART_TYPE_GROUP)
{
if (ep->mouse_events)
{
_edje_callbacks_add(rp->object, ed, rp);
if (ep->repeat_events)
evas_object_repeat_events_set(rp->object, 1);
if (ep->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
evas_object_pointer_mode_set(rp->object, ep->pointer_mode);
}
else
{
evas_object_pass_events_set(rp->object, 1);
evas_object_pointer_mode_set(rp->object,
EVAS_OBJECT_POINTER_MODE_NOGRAB);
}
if (ep->precise_is_inside)
evas_object_precise_is_inside_set(rp->object, 1);
}
if (ep->type == EDJE_PART_TYPE_EXTERNAL)
{
Evas_Object *child;
child = _edje_external_type_add(source, evas_object_evas_get(ed->obj), ed->obj, NULL, name);
if (child)
_edje_real_part_swallow(rp, child, EINA_TRUE);
}
evas_object_clip_set(rp->object, ed->base->clipper);
evas_object_show(ed->base->clipper);
}
/* Update table_parts */
ed->table_parts_size++;
ed->table_parts = realloc(ed->table_parts,
sizeof(Edje_Real_Part *) * ed->table_parts_size);
ed->table_parts[ep->id % ed->table_parts_size] = rp;
/* Create default description */
if (!edje_edit_state_add(obj, name, "default", 0.0))
{
_edje_if_string_free(ed, ep->name);
if (source)
_edje_if_string_free(ed, ep->source);
eina_mempool_free(ce->mp.part, ep);
eina_mempool_free(_edje_real_part_mp, rp);
return EINA_FALSE;
}
edje_edit_part_selected_state_set(obj, name, "default", 0.0);
ce->count.part++;
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_part_add(Evas_Object *obj, const char *name, Edje_Part_Type type)
{
eina_error_set(0);
if (type == EDJE_PART_TYPE_EXTERNAL)
return EINA_FALSE;
return _edje_edit_real_part_add(obj, name, type, NULL);
}
EAPI Eina_Bool
edje_edit_part_external_add(Evas_Object *obj, const char *name, const char *source)
{
eina_error_set(0);
if (!source)
return EINA_FALSE;
return _edje_edit_real_part_add(obj, name, EDJE_PART_TYPE_EXTERNAL, source);
}
EAPI Eina_Bool
edje_edit_part_del(Evas_Object *obj, const char* part)
{
Edje_Part_Collection_Directory_Entry *ce;
Edje_Part_Collection *pc;
Edje_Part *ep;
unsigned int k;
unsigned int id;
unsigned int i;
eina_error_set(0);
GET_RP_OR_RETURN(EINA_FALSE);
//printf("REMOVE PART: %s\n", part);
ep = rp->part;
id = ep->id;
/* Unlik Edje_Real_Parts that link to the removed one */
for (i = 0; i < ed->table_parts_size; i++)
{
Edje_Real_Part *real;
if (i == id) continue; //don't check the deleted id
real = ed->table_parts[i];
if (real->typedata.text->source == rp) real->typedata.text->source = NULL;
if (real->typedata.text->text_source == rp) real->typedata.text->text_source = NULL;
if (real->param1.rel1_to_x == rp) real->param1.rel1_to_x = NULL;
if (real->param1.rel1_to_y == rp) real->param1.rel1_to_y = NULL;
if (real->param1.rel2_to_x == rp) real->param1.rel2_to_x = NULL;
if (real->param1.rel2_to_y == rp) real->param1.rel2_to_y = NULL;
if (real->param2)
{
if (real->param2->rel1_to_x == rp) real->param2->rel1_to_x = NULL;
if (real->param2->rel1_to_y == rp) real->param2->rel1_to_y = NULL;
if (real->param2->rel2_to_x == rp) real->param2->rel2_to_x = NULL;
if (real->param2->rel2_to_y == rp) real->param2->rel2_to_y = NULL;
}
if (real->custom)
{
if (real->custom->rel1_to_x == rp) real->custom->rel1_to_x = NULL;
if (real->custom->rel1_to_y == rp) real->custom->rel1_to_y = NULL;
if (real->custom->rel2_to_x == rp) real->custom->rel2_to_x = NULL;
if (real->custom->rel2_to_y == rp) real->custom->rel2_to_y = NULL;
}
if (real->clip_to == rp)
{
evas_object_clip_set(real->object, ed->base->clipper);
real->clip_to = NULL;
}
if (real->drag && real->drag->confine_to == rp)
real->drag->confine_to = NULL;
}
/* Unlink all the parts and descriptions that refer to id */
_edje_part_id_set(ed, rp, -1);
/* Remove part from parts list */
pc = ed->collection;
pc->parts_count--;
if (id < pc->parts_count) /* Forward parts */
{
int mcount = (pc->parts_count - id) * sizeof(Edje_Part *);
memmove(&pc->parts[id], &pc->parts[id+1], mcount);
}
pc->parts[pc->parts_count] = NULL;
_edje_fix_parts_id(ed);
/* Free Edje_Part and all descriptions */
ce = eina_hash_find(ed->file->collection, ed->group);
_edje_if_string_free(ed, ep->name);
if (ep->default_desc)
{
_edje_collection_free_part_description_free(ep->type, ep->default_desc, ce, 0);
ep->default_desc = NULL;
}
for (k = 0; k < ep->other.desc_count; ++k)
_edje_collection_free_part_description_free(ep->type, ep->other.desc[k], ce, 0);
free(ep->other.desc);
eina_mempool_free(ce->mp.part, ep);
/* Free Edje_Real_Part */
_edje_real_part_free(rp);
/* if all parts are gone, hide the clipper */
if (ed->table_parts_size == 0)
evas_object_hide(ed->base->clipper);
edje_object_calc_force(obj);
ce->count.part--;
_edje_edit_flag_script_dirty(eed, EINA_TRUE);
return EINA_TRUE;
}
EAPI Eina_Bool
edje_edit_part_exist(Evas_Object *obj, const char *part)
{
eina_error_set(0);
GET_RP_OR_RETURN(EINA_FALSE);
return EINA_TRUE;
}
EAPI const<