From 1e25d7b70154576dca5aced4210b9a10d89b5740 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Tue, 4 Sep 2012 11:27:43 +0000 Subject: [PATCH] edje: add nested part support to edc. Blame Tasn and not the people he enslaved to get it out. First patch by Aharon Hillel with some modification by myself. SVN revision: 76127 --- legacy/edje/ChangeLog | 5 + legacy/edje/NEWS | 1 + legacy/edje/doc/examples.dox | 24 +++ legacy/edje/src/bin/edje_cc.h | 15 ++ legacy/edje/src/bin/edje_cc_handlers.c | 235 ++++++++++++++++++++--- legacy/edje/src/bin/edje_cc_parse.c | 173 ++++++++++++----- legacy/edje/src/examples/edje-nested.edc | 39 ++++ legacy/edje/src/lib/edje_calc.c | 82 +++++--- legacy/edje/src/lib/edje_data.c | 1 + legacy/edje/src/lib/edje_edit.c | 6 +- legacy/edje/src/lib/edje_load.c | 109 ++++++++++- legacy/edje/src/lib/edje_private.h | 8 +- legacy/edje/src/lib/edje_smart.c | 6 +- 13 files changed, 596 insertions(+), 108 deletions(-) create mode 100644 legacy/edje/src/examples/edje-nested.edc diff --git a/legacy/edje/ChangeLog b/legacy/edje/ChangeLog index 075a97d2c3..bd38c4a3dd 100644 --- a/legacy/edje/ChangeLog +++ b/legacy/edje/ChangeLog @@ -589,3 +589,8 @@ 2012-09-04 Jihoon Kim (jihoon) * Add EDJE_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN. + +2012-09-04 Aharon Hillel + + * Added nested parts support. + This lets us do nested parts, e.g parts "{ part { part { } } }" diff --git a/legacy/edje/NEWS b/legacy/edje/NEWS index eb1d0605b8..ccc28dacaa 100644 --- a/legacy/edje/NEWS +++ b/legacy/edje/NEWS @@ -5,6 +5,7 @@ Changes since Edje 1.8.0: Additions: * Report type of file when listing file used by an edc. + * Add nested parts support. * Add EDJE_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN Improvements: diff --git a/legacy/edje/doc/examples.dox b/legacy/edje/doc/examples.dox index d0efafe401..a2afc5ae3d 100644 --- a/legacy/edje/doc/examples.dox +++ b/legacy/edje/doc/examples.dox @@ -4,6 +4,7 @@ * Here is a page with examples. * * @li @ref Example_Edje_Basics + * @li @ref tutorial_edje_nested * @li @ref tutorial_edje_swallow * @li @ref tutorial_edje_swallow2 * @li @ref tutorial_edje_text @@ -153,6 +154,29 @@ * @example edje-basic.c */ +/** + * @page tutorial_edje_nested Edje Nested Part (hierarchy) example + * + * Nested part feature represents the concept of hierarchy to edje. + * + * A nested part inherits it's location relatively to the parent part. + * Thus, parent part modifications such move or map effects all nested parts. + * To declare a nested part just start a new part declaration within + * (before closing) the current part declaration. + * + * Note that nested part declaration is allowed only after + * current part name is defined. + * + * Here's an example of a rect nested in other rect plus inner nested rect: + * @include edje-nested.edc + * + * The example's window should look like this picture: + * + * @image html edje-nested.png + * @image rtf edje-nested.png + * @image latex edje-nested.eps width=\textwidth + */ + /** * @page tutorial_edje_swallow Swallow example * @dontinclude edje-swallow.c diff --git a/legacy/edje/src/bin/edje_cc.h b/legacy/edje/src/bin/edje_cc.h index 2001b904fb..4c5ec0629e 100644 --- a/legacy/edje/src/bin/edje_cc.h +++ b/legacy/edje/src/bin/edje_cc.h @@ -42,6 +42,7 @@ extern int _edje_cc_log_dom ; /* types */ typedef struct _New_Object_Handler New_Object_Handler; typedef struct _New_Statement_Handler New_Statement_Handler; +typedef struct _New_Nested_Handler New_Nested_Handler; typedef struct _External_List External_List; typedef struct _External External; typedef struct _Font_List Font_List; @@ -67,6 +68,14 @@ struct _New_Statement_Handler void (*func)(void); }; +struct _New_Nested_Handler +{ + const char *type; + const char *token; + void (*func_push)(void); + void (*func_pop)(void); +}; + struct _External_List { Eina_List *list; @@ -189,6 +198,7 @@ void check_min_arg_count(int n); int object_handler_num(void); int statement_handler_num(void); +int nested_handler_num(void); void reorder_parts(void); void source_edd(void); @@ -206,6 +216,10 @@ void using_file(const char *filename, const char type); void error_and_abort(Eet_File *ef, const char *fmt, ...); + +void edje_cc_handlers_hierarchy_alloc(void); +void edje_cc_handlers_hierarchy_free(void); + /* global vars */ extern Eina_List *ext_dirs; extern Eina_List *img_dirs; @@ -233,6 +247,7 @@ extern Eina_List *defines; extern Eina_List *aliases; extern New_Object_Handler object_handlers[]; extern New_Statement_Handler statement_handlers[]; +extern New_Nested_Handler nested_handlers[]; extern int compress_mode; extern int threads; extern int anotate; diff --git a/legacy/edje/src/bin/edje_cc_handlers.c b/legacy/edje/src/bin/edje_cc_handlers.c index 2f8a84ba21..b081161b96 100644 --- a/legacy/edje/src/bin/edje_cc_handlers.c +++ b/legacy/edje/src/bin/edje_cc_handlers.c @@ -72,6 +72,25 @@ static Edje_Part_Description_Common *current_desc = NULL; static Edje_Part_Description_Common *parent_desc = NULL; static Edje_Program *current_program = NULL; +struct _Edje_Cc_Handlers_Hierarchy_Info +{ /* Struct that keeps globals value to impl hierarchy */ + Edje_Part_Collection_Directory_Entry *current_de; + Edje_Part *current_part; + Edje_Pack_Element *current_item; + Edje_Part_Description_Common *current_desc; + Edje_Part_Description_Common *parent_desc; + Edje_Program *current_program; + Edje_Part *ep; +}; +typedef struct _Edje_Cc_Handlers_Hierarchy_Info Edje_Cc_Handlers_Hierarchy_Info; + +static Eina_Array *part_hierarchy = NULL; /* stack parts,support nested parts */ +static void edje_cc_handlers_hierarchy_set(Edje_Part *src); +static Edje_Part *edje_cc_handlers_hierarchy_parent_get(void); +static void edje_cc_handlers_hierarchy_push(Edje_Part *ep, Edje_Part *cp); +static void edje_cc_handlers_hierarchy_rename(Edje_Part *old, Edje_Part *new); +static void edje_cc_handlers_hierarchy_pop(void); + static void st_externals_external(void); static void st_images_image(void); @@ -118,6 +137,7 @@ static void ob_collections_group_lua_script(void); static void st_collections_group_parts_alias(void); +static Edje_Part *edje_cc_handlers_part_make(void); static void ob_collections_group_parts_part(void); static void st_collections_group_parts_part_name(void); static void st_collections_group_parts_part_type(void); @@ -182,11 +202,13 @@ static void st_collections_group_parts_part_description_aspect(void); static void st_collections_group_parts_part_description_aspect_preference(void); static void st_collections_group_parts_part_description_rel1_relative(void); static void st_collections_group_parts_part_description_rel1_offset(void); +static void st_collections_group_parts_part_description_rel1_to_set(const char *name); static void st_collections_group_parts_part_description_rel1_to(void); static void st_collections_group_parts_part_description_rel1_to_x(void); static void st_collections_group_parts_part_description_rel1_to_y(void); static void st_collections_group_parts_part_description_rel2_relative(void); static void st_collections_group_parts_part_description_rel2_offset(void); +static void st_collections_group_parts_part_description_rel2_to_set(const char *name); static void st_collections_group_parts_part_description_rel2_to(void); static void st_collections_group_parts_part_description_rel2_to_x(void); static void st_collections_group_parts_part_description_rel2_to_y(void); @@ -808,6 +830,10 @@ New_Object_Handler object_handlers[] = {"collections.group.programs.script", ob_collections_group_script} /* dup */ }; +New_Nested_Handler nested_handlers[] = { + {"collections.group.parts", "part", NULL, edje_cc_handlers_hierarchy_pop } +}; + /*****/ int @@ -822,6 +848,12 @@ statement_handler_num(void) return sizeof(statement_handlers) / sizeof (New_Object_Handler); } +int +nested_handler_num(void) +{ + return sizeof(nested_handlers) / sizeof (New_Nested_Handler); +} + static void _edje_part_description_fill(Edje_Part_Description_Spec_Fill *fill) { @@ -2373,7 +2405,7 @@ st_collections_group_inherit(void) for (i = 0 ; i < pc2->parts_count ; i++) { // copy the part - ob_collections_group_parts_part(); + edje_cc_handlers_part_make(); ep = pc->parts[i]; ep2 = pc2->parts[i]; ep->name = STRDUP(ep2->name); @@ -2406,6 +2438,7 @@ st_collections_group_inherit(void) ep->dragable.y = ep2->dragable.y; ep->dragable.step_y = ep2->dragable.step_y; ep->dragable.count_y = ep2->dragable.count_y; + ep->nested_children_count = ep2->nested_children_count; data_queue_copied_part_lookup(pc, &(ep2->dragable.confine_id), &(ep->dragable.confine_id)); data_queue_copied_part_lookup(pc, &(ep2->dragable.event_id), &(ep->dragable.event_id)); @@ -2964,9 +2997,9 @@ st_collections_group_parts_alias(void) on a button. @endblock */ -static void -ob_collections_group_parts_part(void) -{ +static Edje_Part * +edje_cc_handlers_part_make(void) +{ /* Doing ob_collections_group_parts_part() job, without hierarchy */ Edje_Part_Collection *pc; Edje_Part *ep; Edje_Part_Parser *epp; @@ -2997,6 +3030,7 @@ ob_collections_group_parts_part(void) ep->dragable.confine_id = -1; ep->dragable.event_id = -1; ep->items = NULL; + ep->nested_children_count = 0; epp = (Edje_Part_Parser *)ep; epp->reorder.insert_before = NULL; @@ -3007,6 +3041,23 @@ ob_collections_group_parts_part(void) epp->reorder.linked_next = 0; epp->reorder.done = EINA_FALSE; epp->can_override = EINA_FALSE; + + return ep; +} + +static void +ob_collections_group_parts_part(void) +{ + Edje_Part *cp = current_part; /* Save to restore on pop */ + Edje_Part *ep = edje_cc_handlers_part_make(); /* This changes current_part */ + Edje_Part *prnt; + + /* Add this new part to hierarchy stack (removed part finished parse) */ + edje_cc_handlers_hierarchy_push(ep, cp); + + prnt = edje_cc_handlers_hierarchy_parent_get(); + if (prnt) /* This is the child of parent in stack */ + prnt->nested_children_count++; } /** @@ -3039,8 +3090,10 @@ st_collections_group_parts_part_name(void) unsigned int i; for (i = 0; i < (pc->parts_count - 1); i++) - { - if (pc->parts[i]->name && (!strcmp(pc->parts[i]->name, ep->name))) + { /* Compare name only if did NOT updated ep from hircy pop */ + if ((ep != pc->parts[i]) && + (pc->parts[i]->name && + (!strcmp(pc->parts[i]->name, ep->name)))) { epp = (Edje_Part_Parser *)pc->parts[i]; if (!epp->can_override) @@ -3054,7 +3107,9 @@ st_collections_group_parts_part_name(void) free(ep); pc->parts_count--; pc->parts = realloc(pc->parts, pc->parts_count * sizeof (Edje_Part *)); - ep = current_part = pc->parts[i]; + current_part = pc->parts[i]; + edje_cc_handlers_hierarchy_rename(ep, current_part); + ep = current_part; epp->can_override = EINA_FALSE; break; } @@ -3142,6 +3197,38 @@ st_collections_group_parts_part_type(void) current_part->type = type; } +/** + @page edcref + @property + part + @parameters + [part declaration] + @effect + @code + group { + parts { + part { + name: "parent_rect"; + type: RECT; + description { } + part { + name: "nested_rect"; + type: RECT; + description { } + } + } + .. + } + } + @endcode + Nested parts adds hierarchy to edje. + Nested part inherits it's location relatively to the parent part. + To declare a nested part just start a new part within current part decl. + You must define parent part name before adding nested parts. + @endproperty + @since 1.7.0 +*/ + /** @page edcref @property @@ -4265,7 +4352,7 @@ static void st_collections_group_parts_part_table_items_item_span(void) */ static void ob_collections_group_parts_part_description(void) -{ +{ /* Allocate and set desc, set relative part hierarchy if needed */ Edje_Part_Collection *pc; Edje_Part *ep; Edje_Part_Description_Common *ed; @@ -4275,9 +4362,20 @@ ob_collections_group_parts_part_description(void) ed = _edje_part_description_alloc(ep->type, pc->part, ep->name); + ed->rel1.id_x = -1; + ed->rel1.id_y = -1; + ed->rel2.id_x = -1; + ed->rel2.id_y = -1; + if (!ep->default_desc) { current_desc = ep->default_desc = ed; + + { /* Get the ptr of the part above current part in hierarchy */ + Edje_Part *node = edje_cc_handlers_hierarchy_parent_get(); + if (node) /* Make relative according to part hierarchy */ + edje_cc_handlers_hierarchy_set(node); + } } else { @@ -4301,14 +4399,10 @@ ob_collections_group_parts_part_description(void) ed->rel1.relative_y = FROM_DOUBLE(0.0); ed->rel1.offset_x = 0; ed->rel1.offset_y = 0; - ed->rel1.id_x = -1; - ed->rel1.id_y = -1; ed->rel2.relative_x = FROM_DOUBLE(1.0); ed->rel2.relative_y = FROM_DOUBLE(1.0); ed->rel2.offset_x = -1; ed->rel2.offset_y = -1; - ed->rel2.id_x = -1; - ed->rel2.id_y = -1; ed->color_class = NULL; ed->color.r = 255; ed->color.g = 255; @@ -5148,20 +5242,23 @@ st_collections_group_parts_part_description_rel1_offset(void) @endproperty */ static void -st_collections_group_parts_part_description_rel1_to(void) +st_collections_group_parts_part_description_rel1_to_set(const char *name) { Edje_Part_Collection *pc; - - check_arg_count(1); - pc = eina_list_data_get(eina_list_last(edje_collections)); + data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x)); + data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y)); +} + +static void +st_collections_group_parts_part_description_rel1_to(void) +{ + check_arg_count(1); { char *name; - name = parse_str(0); - data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x)); - data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y)); + st_collections_group_parts_part_description_rel1_to_set(name); free(name); } } @@ -5245,20 +5342,23 @@ st_collections_group_parts_part_description_rel2_offset(void) } static void -st_collections_group_parts_part_description_rel2_to(void) +st_collections_group_parts_part_description_rel2_to_set(const char *name) { Edje_Part_Collection *pc; - - check_arg_count(1); - pc = eina_list_data_get(eina_list_last(edje_collections)); + data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x)); + data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y)); +} + +static void +st_collections_group_parts_part_description_rel2_to(void) +{ + check_arg_count(1); { char *name; - name = parse_str(0); - data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x)); - data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y)); + st_collections_group_parts_part_description_rel2_to_set(name); free(name); } } @@ -8051,3 +8151,86 @@ ob_collections_group_programs_program_script(void) @page edcref */ + +static void +edje_cc_handlers_hierarchy_set(Edje_Part *src) +{ /* This funcion makes current part rel_1.id, rel_2.id relative to src */ + if (!src->name) + { + ERR("parse error %s:%i. You must set parent name before creating nested part", + file_in, line - 1); + exit(-1); + } + st_collections_group_parts_part_description_rel1_to_set(src->name); + st_collections_group_parts_part_description_rel2_to_set(src->name); +} + +static Edje_Part * +edje_cc_handlers_hierarchy_parent_get(void) +{ /* Return the parent part pointer */ + int idx = eina_array_count(part_hierarchy) - 2; + Edje_Cc_Handlers_Hierarchy_Info *info = (idx >= 0) ? + eina_array_data_get(part_hierarchy, idx) : NULL; + + return (info) ? info->ep : NULL; +} + +static void +edje_cc_handlers_hierarchy_push(Edje_Part *ep, Edje_Part *cp) +{ /* Remove part from hierarchy stack when finished parsing it */ + Edje_Cc_Handlers_Hierarchy_Info *info = malloc(sizeof(*info)); + info->current_de = current_de; + info->current_part = cp; /* current_part restored on pop */ + info->current_item = current_item; + info->current_desc = current_desc; + info->parent_desc = parent_desc; + info->current_program = current_program; + info->ep = ep; + + eina_array_push(part_hierarchy, info); +} + +static void +edje_cc_handlers_hierarchy_rename(Edje_Part *old, Edje_Part *new) +{ + Edje_Cc_Handlers_Hierarchy_Info *item; + Eina_Array_Iterator iterator; + unsigned int i; + + EINA_ARRAY_ITER_NEXT(part_hierarchy, i, item, iterator) + { + if (item->ep == old) item->ep = new; + if (item->current_part == old) item->current_part = new; + } +} + +void +edje_cc_handlers_hierarchy_alloc(void) +{ + part_hierarchy = eina_array_new(8); +} + +void +edje_cc_handlers_hierarchy_free(void) +{ + eina_array_free(part_hierarchy); + part_hierarchy = NULL; +} + +static void +edje_cc_handlers_hierarchy_pop(void) +{ /* Remove part from hierarchy stack when finished parsing it */ + Edje_Cc_Handlers_Hierarchy_Info *info = eina_array_pop(part_hierarchy); + + if (info) + { + current_de = info->current_de; + current_part = info->current_part; + current_item = info->current_item; + current_desc = info->current_desc; + parent_desc = info->parent_desc; + current_program = info->current_program; + + free(info); + } +} diff --git a/legacy/edje/src/bin/edje_cc_parse.c b/legacy/edje/src/bin/edje_cc_parse.c index b327752f25..e87047a73e 100644 --- a/legacy/edje/src/bin/edje_cc_parse.c +++ b/legacy/edje/src/bin/edje_cc_parse.c @@ -44,8 +44,7 @@ static void new_statement(void); static char *perform_math (char *input); static int isdelim(char c); static char *next_token(char *p, char *end, char **new_p, int *delim); -static char *stack_id(void); -static void stack_chop_top(void); +static const char *stack_id(void); static void parse(char *data, off_t size); /* simple expression parsing protos */ @@ -82,18 +81,16 @@ static int verbatim = 0; static int verbatim_line1 = 0; static int verbatim_line2 = 0; static char *verbatim_str = NULL; +static Eina_Strbuf *stack_buf = NULL; static void err_show_stack(void) { - char *s; + const char *s; s = stack_id(); if (s) - { - ERR("PARSE STACK:\n%s", s); - free(s); - } + ERR("PARSE STACK:\n%s", s); else ERR("NO PARSE STACK"); } @@ -120,6 +117,7 @@ err_show(void) static Eina_Hash *_new_object_hash = NULL; static Eina_Hash *_new_statement_hash = NULL; +static Eina_Hash *_new_nested_hash = NULL; static void fill_object_statement_hashes(void) { @@ -129,25 +127,32 @@ fill_object_statement_hashes(void) _new_object_hash = eina_hash_string_superfast_new(NULL); _new_statement_hash = eina_hash_string_superfast_new(NULL); + _new_nested_hash = eina_hash_string_superfast_new(NULL); n = object_handler_num(); for (i = 0; i < n; i++) { - eina_hash_add(_new_object_hash, object_handlers[i].type, - &(object_handlers[i])); + eina_hash_direct_add(_new_object_hash, object_handlers[i].type, + &(object_handlers[i])); } n = statement_handler_num(); for (i = 0; i < n; i++) { - eina_hash_add(_new_statement_hash, statement_handlers[i].type, - &(statement_handlers[i])); + eina_hash_direct_add(_new_statement_hash, statement_handlers[i].type, + &(statement_handlers[i])); + } + n = nested_handler_num(); + for (i = 0; i < n; i++) + { + eina_hash_direct_add(_new_nested_hash, nested_handlers[i].type, + &(nested_handlers[i])); } } static void new_object(void) { - char *id; + const char *id; New_Object_Handler *oh; New_Statement_Handler *sh; @@ -170,13 +175,12 @@ new_object(void) exit(-1); } } - free(id); } static void new_statement(void) { - char *id; + const char *id; New_Statement_Handler *sh; fill_object_statement_hashes(); @@ -194,7 +198,6 @@ new_statement(void) err_show(); exit(-1); } - free(id); } static char * @@ -432,46 +435,120 @@ next_token(char *p, char *end, char **new_p, int *delim) return tok; } -static char * -stack_id(void) +static void +stack_push(char *token) { - char *id; - int len; - Eina_List *l; - char *data; + New_Nested_Handler *nested; + Eina_Bool do_append = EINA_TRUE; - len = 0; - EINA_LIST_FOREACH(stack, l, data) - len += strlen(data) + 1; - id = mem_alloc(len); - id[0] = 0; - EINA_LIST_FOREACH(stack, l, data) + if (eina_list_count(stack) > 1) { - strcat(id, data); - if (eina_list_next(l)) strcat(id, "."); + if (!strcmp(token, eina_list_data_get(eina_list_last(stack)))) + { + char *tmp; + int token_length; + + token_length = strlen(token); + tmp = alloca(eina_strbuf_length_get(stack_buf)); + memcpy(tmp, + eina_strbuf_string_get(stack_buf), + eina_strbuf_length_get(stack_buf) - token_length - 1); + tmp[eina_strbuf_length_get(stack_buf) - token_length - 1] = '\0'; + + nested = eina_hash_find(_new_nested_hash, tmp); + if (nested) + { + if (!strcmp(token, nested->token) && + stack && !strcmp(eina_list_data_get(eina_list_last(stack)), nested->token)) + { + /* Do not append the nested token in buffer */ + do_append = EINA_FALSE; + if (nested->func_push) nested->func_push(); + } + } + } } - return id; + if (do_append) + { + if (stack) eina_strbuf_append(stack_buf, "."); + eina_strbuf_append(stack_buf, token); + } + stack = eina_list_append(stack, token); } static void -stack_chop_top(void) +stack_pop(void) { - char *top; + char *tmp; + int tmp_length; + Eina_Bool do_remove = EINA_TRUE; - /* remove top from stack */ - top = eina_list_data_get(eina_list_last(stack)); - if (top) - { - free(top); - stack = eina_list_remove(stack, top); - } - else + if (!stack) { ERR("parse error %s:%i. } marker without matching { marker", file_in, line - 1); err_show(); exit(-1); } + tmp = eina_list_data_get(eina_list_last(stack)); + tmp_length = strlen(tmp); + + stack = eina_list_remove_list(stack, eina_list_last(stack)); + if (eina_list_count(stack) > 0) + { + const char *prev; + New_Nested_Handler *nested; + char *hierarchy; + char *lookup; + + hierarchy = alloca(eina_strbuf_length_get(stack_buf)); + memcpy(hierarchy, + eina_strbuf_string_get(stack_buf), + eina_strbuf_length_get(stack_buf)); + + /* This is nasty, but it's the way to get parts.part when they are collapsed together. still not perfect */ + lookup = strrchr(hierarchy + eina_strbuf_length_get(stack_buf) - tmp_length, '.'); + while (lookup) + { + hierarchy[lookup - hierarchy] = '\0'; + nested = eina_hash_find(_new_nested_hash, hierarchy); + if (nested && nested->func_pop) nested->func_pop(); + lookup = strrchr(hierarchy + eina_strbuf_length_get(stack_buf) - tmp_length, '.'); + } + + hierarchy[eina_strbuf_length_get(stack_buf) - 1 - tmp_length] = '\0'; + + nested = eina_hash_find(_new_nested_hash, hierarchy); + if (nested) + { + if (nested->func_pop) nested->func_pop(); + + prev = eina_list_data_get(eina_list_last(stack)); + if (!strcmp(tmp, prev)) + { + if (!strcmp(nested->token, tmp)) + do_remove = EINA_FALSE; + } + } + + if (do_remove) + eina_strbuf_remove(stack_buf, + eina_strbuf_length_get(stack_buf) - tmp_length - 1, + eina_strbuf_length_get(stack_buf)); /* remove: '.tmp' */ + } + else + { + eina_strbuf_remove(stack_buf, + eina_strbuf_length_get(stack_buf) - tmp_length, + eina_strbuf_length_get(stack_buf)); /* remove: 'tmp' */ + } + free(tmp); +} + +static const char * +stack_id(void) +{ + return eina_strbuf_string_get(stack_buf); } static void @@ -483,6 +560,8 @@ parse(char *data, off_t size) DBG("Parsing input file"); + /* Allocate arrays used to impl nested parts */ + edje_cc_handlers_hierarchy_alloc(); p = data; end = data + size; line = 1; @@ -511,7 +590,7 @@ parse(char *data, off_t size) exit(-1); } else - stack_chop_top(); + stack_pop(); } else if (*token == ';') { @@ -526,7 +605,7 @@ parse(char *data, off_t size) params = eina_list_remove(params, eina_list_data_get(params)); } /* remove top from stack */ - stack_chop_top(); + stack_pop(); } } else if (*token == '{') @@ -547,7 +626,7 @@ parse(char *data, off_t size) params = eina_list_append(params, token); else { - stack = eina_list_append(stack, token); + stack_push(token); new_object(); if ((verbatim == 1) && (p < (end - 2))) { @@ -629,6 +708,7 @@ parse(char *data, off_t size) } } + edje_cc_handlers_hierarchy_free(); DBG("Parsing done"); } @@ -773,7 +853,12 @@ compile(void) lseek(fd, 0, SEEK_SET); data = malloc(size); if (data && (read(fd, data, size) == size)) - parse(data, size); + { + stack_buf = eina_strbuf_new(); + parse(data, size); + eina_strbuf_free(stack_buf); + stack_buf = NULL; + } else { ERR("Cannot read file \"%s\". %s", file_in, strerror(errno)); diff --git a/legacy/edje/src/examples/edje-nested.edc b/legacy/edje/src/examples/edje-nested.edc new file mode 100644 index 0000000000..d3ea0646fc --- /dev/null +++ b/legacy/edje/src/examples/edje-nested.edc @@ -0,0 +1,39 @@ +collections { + group { + name: "main"; + parts { + part { + type: RECT; + name: "red_rect"; + description { + state: "default" 0.0; + color: 255 0 0 255; + rel1.relative: 0.2 0.1; + rel2.relative: 0.4 0.8; + } + + part { /* This rect is nested in red_rect */ + type: RECT; + name: "green_rect"; + description { + state: "default" 0.0; + color: 0 255 0 255; + rel2.relative: 0.8 0.5; + } + + part { /* This rect is nested in green_rect */ + type: RECT; + name: "blue_rect"; + description { + state: "default" 0.0; + color: 0 0 255 255; + align: 1.0 1.0; + rel1.relative: 0.5 0.5; + rel2.relative: 1.0 1.0; + } + } + } + } + } + } +} diff --git a/legacy/edje/src/lib/edje_calc.c b/legacy/edje/src/lib/edje_calc.c index 84f8090dad..b3827b647e 100644 --- a/legacy/edje/src/lib/edje_calc.c +++ b/legacy/edje/src/lib/edje_calc.c @@ -2277,28 +2277,35 @@ _edje_proxy_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edj } pp = ed->table_parts[part_id % ed->table_parts_size]; - switch (pp->part->type) + if (pp->nested_smart) /* using nested_smart for nested parts */ { - case EDJE_PART_TYPE_IMAGE: - case EDJE_PART_TYPE_TEXT: - case EDJE_PART_TYPE_TEXTBLOCK: - case EDJE_PART_TYPE_RECTANGLE: - case EDJE_PART_TYPE_BOX: - case EDJE_PART_TYPE_TABLE: - case EDJE_PART_TYPE_PROXY: - evas_object_image_source_set(ep->object, pp->object); - break; - case EDJE_PART_TYPE_GRADIENT: - /* FIXME: THIS ONE SHOULD NEVER BE TRIGGERED. */ - break; - case EDJE_PART_TYPE_GROUP: - case EDJE_PART_TYPE_SWALLOW: - case EDJE_PART_TYPE_EXTERNAL: - evas_object_image_source_set(ep->object, pp->swallowed_object); - break; - case EDJE_PART_TYPE_SPACER: - /* FIXME: detect that at compile time and prevent it */ - break; + evas_object_image_source_set(ep->object, pp->nested_smart); + } + else + { + switch (pp->part->type) + { + case EDJE_PART_TYPE_IMAGE: + case EDJE_PART_TYPE_TEXT: + case EDJE_PART_TYPE_TEXTBLOCK: + case EDJE_PART_TYPE_RECTANGLE: + case EDJE_PART_TYPE_BOX: + case EDJE_PART_TYPE_TABLE: + case EDJE_PART_TYPE_PROXY: + evas_object_image_source_set(ep->object, pp->object); + break; + case EDJE_PART_TYPE_GRADIENT: + /* FIXME: THIS ONE SHOULD NEVER BE TRIGGERED. */ + break; + case EDJE_PART_TYPE_GROUP: + case EDJE_PART_TYPE_SWALLOW: + case EDJE_PART_TYPE_EXTERNAL: + evas_object_image_source_set(ep->object, pp->swallowed_object); + break; + case EDJE_PART_TYPE_SPACER: + /* FIXME: detect that at compile time and prevent it */ + break; + } } evas_object_image_fill_set(ep->object, p3->type.common.fill.x, p3->type.common.fill.y, @@ -2924,6 +2931,14 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta /* visibility and color have no meaning on SWALLOW and GROUP part. */ evas_object_move(ep->object, ed->x + pf->x, ed->y + pf->y); evas_object_resize(ep->object, pf->w, pf->h); + + if (ep->nested_smart) + { /* Move, Resize all nested parts */ + /* Not really needed but will improve the bounding box evaluation done by Evas */ + evas_object_move(ep->nested_smart, + ed->x + pf->x, ed->y + pf->y); + evas_object_resize(ep->nested_smart, pf->w, pf->h); + } if (ep->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) _edje_entry_real_part_configure(ep); break; @@ -3056,13 +3071,30 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta if (chosen_desc->map.alpha) evas_map_alpha_set(map, 1); else evas_map_alpha_set(map, 0); - evas_object_map_set(mo, map); - evas_object_map_enable_set(mo, 1); + + if (ep->nested_smart) + { /* Apply map to smart obj holding nested parts */ + evas_object_map_set(ep->nested_smart, map); + evas_object_map_enable_set(ep->nested_smart, 1); + } + else + { + evas_object_map_set(mo, map); + evas_object_map_enable_set(mo, 1); + } } else { - evas_object_map_enable_set(mo, 0); - evas_object_map_set(mo, NULL); + if (ep->nested_smart) + { /* Cancel map of smart obj holding nested parts */ + evas_object_map_enable_set(ep->nested_smart, 0); + evas_object_map_set(ep->nested_smart, NULL); + } + else + { + evas_object_map_enable_set(mo, 0); + evas_object_map_set(mo, NULL); + } } } diff --git a/legacy/edje/src/lib/edje_data.c b/legacy/edje/src/lib/edje_data.c index da3032905c..4c278d0fbd 100644 --- a/legacy/edje/src/lib/edje_data.c +++ b/legacy/edje/src/lib/edje_data.c @@ -869,6 +869,7 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "access", access, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "api.name", api.name, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "api.description", api.description, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "nested_children_count", nested_children_count, EET_T_UCHAR); EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Limit); _edje_edd_edje_part_limit = eet_data_descriptor_file_new(&eddc); diff --git a/legacy/edje/src/lib/edje_edit.c b/legacy/edje/src/lib/edje_edit.c index 3991542705..5ae5947a5e 100644 --- a/legacy/edje/src/lib/edje_edit.c +++ b/legacy/edje/src/lib/edje_edit.c @@ -123,7 +123,7 @@ struct _Program_Script static void _edje_edit_smart_add(Evas_Object *obj); static void _edje_edit_smart_del(Evas_Object *obj); -static Eina_Bool _edje_edit_smart_file_set(Evas_Object *obj, const char *file, const char *group); +static Eina_Bool _edje_edit_smart_file_set(Evas_Object *obj, const char *file, const char *group, Eina_Array *nested); static Eina_Bool _edje_edit_edje_file_save(Eet_File *eetf, Edje_File *ef); EVAS_SMART_SUBCLASS_NEW(_edje_edit_type, _edje_edit, Edje_Smart_Api, @@ -212,7 +212,7 @@ _edje_edit_program_script_free(Program_Script *ps) } static Eina_Bool -_edje_edit_smart_file_set(Evas_Object *obj, const char *file, const char *group) +_edje_edit_smart_file_set(Evas_Object *obj, const char *file, const char *group, Eina_Array *nested) { Edje_Edit *eed; Eet_File *ef; @@ -237,7 +237,7 @@ _edje_edit_smart_file_set(Evas_Object *obj, const char *file, const char *group) * (GROUP parts or BOX/TABLE items pointing to non-existent/renamed * groups). */ - if (!_edje_edit_parent_sc->file_set(obj, file, group)) + if (!_edje_edit_parent_sc->file_set(obj, file, group, nested)) return EINA_FALSE; eed->program_scripts = eina_hash_int32_new((Eina_Free_Cb)_edje_edit_program_script_free); diff --git a/legacy/edje/src/lib/edje_load.c b/legacy/edje/src/lib/edje_load.c index d3f9fd2211..d5c72936b3 100644 --- a/legacy/edje/src/lib/edje_load.c +++ b/legacy/edje/src/lib/edje_load.c @@ -24,6 +24,40 @@ struct _Edje_Drag_Items } page; }; +/* START - Nested part support */ +#define _edje_smart_nested_type "Evas_Smart_Nested" +typedef struct _Edje_Nested_Support Edje_Nested_Support; +struct _Edje_Nested_Support +{ /* We builed nested-parts list using this struct */ + Evas_Object *o; /* Smart object containing nested children */ + unsigned char nested_children_count; /* Number of nested children */ +}; + +Evas_Smart * +_edje_smart_nested_smart_class_new(void) +{ + static Evas_Smart_Class _sc = EVAS_SMART_CLASS_INIT_NAME_VERSION("EdjeNested"); + static const Evas_Smart_Class *class = NULL; + static Evas_Smart *smart; + + if (smart) + return smart; + + class = &_sc; + smart = evas_smart_class_new(class); + return smart; +} + + +Evas_Object * +edje_smart_nested_add(Evas *evas) +{ + return evas_object_smart_add(evas, _edje_smart_nested_smart_class_new()); +} + +/* END - Nested part support */ + + #ifdef EDJE_PROGRAM_CACHE static Eina_Bool _edje_collection_free_prog_cache_matches_free_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata); #endif @@ -41,11 +75,17 @@ edje_object_file_set(Evas_Object *obj, const char *file, const char *group) { Eina_Bool ret; Edje *ed; + Eina_Array *nested; ed = _edje_fetch(obj); if (!ed) return EINA_FALSE; - ret = ed->api->file_set(obj, file, group); + + nested = eina_array_new(8); + ret = ed->api->file_set(obj, file, group, nested); + eina_array_free(nested); + nested = NULL; + _edje_object_orientation_inform(obj); return ret; } @@ -298,7 +338,7 @@ _edje_programs_patterns_init(Edje *ed) } int -_edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *group, const char *parent, Eina_List *group_path) +_edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *group, const char *parent, Eina_List *group_path, Eina_Array *nested) { Edje *ed; Evas *tev; @@ -310,6 +350,11 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g unsigned int n; Eina_List *parts = NULL; int group_path_started = 0; + Evas_Object *nested_smart = NULL; + + /* Get data pointer of top-of-stack */ + int idx = eina_array_count(nested) - 1; + Edje_Nested_Support *st_nested = (idx >= 0) ? eina_array_data_get(nested, idx) : NULL; ed = _edje_fetch(obj); if (!ed) return 0; @@ -409,6 +454,22 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g Edje_Part *ep; ep = ed->collection->parts[n]; + + if (ep->nested_children_count) + { /* Add object to nested parts list */ + st_nested = malloc(sizeof(*st_nested)); + nested_smart = st_nested->o = edje_smart_nested_add(tev); + + /* We add 1 to children_count because the parent + object is added to smart obj children as well */ + st_nested->nested_children_count = + ep->nested_children_count + 1; + + evas_object_show(st_nested->o); + + eina_array_push(nested, st_nested); + } + rp = eina_mempool_malloc(_edje_real_part_mp, sizeof(Edje_Real_Part)); if (!rp) { @@ -501,7 +562,47 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g if (rp->object) { - evas_object_smart_member_add(rp->object, ed->obj); + if (nested_smart) + { /* Update this pointer to father object only + this will make smart object size == father sz */ + rp->nested_smart = nested_smart; + nested_smart = NULL; + } + + if (st_nested && st_nested->nested_children_count) + { /* Add this to list of children */ + evas_object_smart_member_add(rp->object, + st_nested->o); + + st_nested->nested_children_count--; + + /* No more nested children for this obj */ + while (st_nested && (st_nested->nested_children_count == 0)) + { + /* Loop to add smart counter as child */ + Evas_Object *p_obj = st_nested->o; + + st_nested = eina_array_pop(nested); + free(st_nested); + + /* Check for parent in stack */ + idx = eina_array_count(nested) - 1; + st_nested = (idx >= 0) ? eina_array_data_get(nested,idx) : NULL; + + if (st_nested) + { + st_nested->nested_children_count--; + evas_object_smart_member_add(p_obj, st_nested->o); + } + else + { + evas_object_smart_member_add(p_obj, ed->obj); + } + } + } + else + 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 && ep->type != EDJE_PART_TYPE_EXTERNAL) { @@ -775,7 +876,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g _edje_real_part_swallow(rp, child_obj, EINA_FALSE); } - if (!_edje_object_file_set_internal(child_obj, file, source, rp->part->name, group_path)) + if (!_edje_object_file_set_internal(child_obj, file, source, rp->part->name, group_path, nested)) { ERR("impossible to set part '%s' of group '%s' from file '%s' to '%s'", rp->part->name, group_path_entry, file, source); diff --git a/legacy/edje/src/lib/edje_private.h b/legacy/edje/src/lib/edje_private.h index 9d5bb01377..5678b8ae46 100644 --- a/legacy/edje/src/lib/edje_private.h +++ b/legacy/edje/src/lib/edje_private.h @@ -179,7 +179,7 @@ struct _Edje_Smart_Api { Evas_Smart_Class base; int version; - Eina_Bool (*file_set)(Evas_Object *obj, const char *file, const char *group); + Eina_Bool (*file_set)(Evas_Object *obj, const char *file, const char *group, Eina_Array *nested); }; /* Basic macro to init the Edje Smart API */ @@ -873,6 +873,7 @@ struct _Edje_Part unsigned char multiline; unsigned char access; /* it will be used accessibility feature */ Edje_Part_Api api; + unsigned char nested_children_count; }; struct _Edje_Part_Image_Id @@ -1312,6 +1313,7 @@ struct _Edje_Real_Part Edje *edje; // 4 Edje_Part *part; // 4 Evas_Object *object; // 4 + Evas_Object *nested_smart; // 4 int x, y, w, h; // 16 Edje_Rectangle req; // 16 @@ -1374,7 +1376,7 @@ struct _Edje_Real_Part #ifdef EDJE_CALC_CACHE unsigned char invalidate : 1; // 0 #endif -}; // 264 +}; // 268 // WITH EDJE_CALC_CACHE: 404 struct _Edje_Running_Program @@ -1719,7 +1721,7 @@ void _edje_callbacks_focus_del(Evas_Object *obj, Edje *ed); void _edje_edd_init(void); void _edje_edd_shutdown(void); -int _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *group, const char *parent, Eina_List *group_path); +int _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *group, const char *parent, Eina_List *group_path, Eina_Array *nested); void _edje_file_add(Edje *ed); void _edje_file_del(Edje *ed); diff --git a/legacy/edje/src/lib/edje_smart.c b/legacy/edje/src/lib/edje_smart.c index 0a855cfa1d..97f996e3eb 100644 --- a/legacy/edje/src/lib/edje_smart.c +++ b/legacy/edje/src/lib/edje_smart.c @@ -8,7 +8,7 @@ static void _edje_smart_show(Evas_Object * obj); static void _edje_smart_hide(Evas_Object * obj); static void _edje_smart_calculate(Evas_Object * obj); -static Eina_Bool _edje_smart_file_set(Evas_Object *obj, const char *file, const char *group); +static Eina_Bool _edje_smart_file_set(Evas_Object *obj, const char *file, const char *group, Eina_Array *nested); static Edje_Smart_Api _edje_smart_class = EDJE_SMART_API_INIT_NAME_VERSION("edje"); static Evas_Smart_Class _edje_smart_parent; @@ -342,7 +342,7 @@ _edje_smart_calculate(Evas_Object *obj) } static Eina_Bool -_edje_smart_file_set(Evas_Object *obj, const char *file, const char *group) +_edje_smart_file_set(Evas_Object *obj, const char *file, const char *group, Eina_Array *nested) { - return _edje_object_file_set_internal(obj, file, group, NULL, NULL); + return _edje_object_file_set_internal(obj, file, group, NULL, NULL, nested); }