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
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 { } } }"
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:
* 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
*/
/**
+ * @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
*
/* 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;
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;
int object_handler_num(void);
int statement_handler_num(void);
+int nested_handler_num(void);
void reorder_parts(void);
void source_edd(void);
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;
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;
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);
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);
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);
{"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
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)
{
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);
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));
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;
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;
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++;
}
/**
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)
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;
}
/**
@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
insert_before
@parameters
[another part's name]
*/
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;
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
{
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;
@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;
+ 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);
- pc = eina_list_data_get(eina_list_last(edje_collections));
-
{
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);
}
}
}
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;
+ 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);
- pc = eina_list_data_get(eina_list_last(edje_collections));
-
{
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);
}
}
@page edcref
</table>
*/
+
+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);
+ }
+}
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 */
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");
}
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)
{
_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;
exit(-1);
}
}
- free(id);
}
static void
new_statement(void)
{
- char *id;
+ const char *id;
New_Statement_Handler *sh;
fill_object_statement_hashes();
err_show();
exit(-1);
}
- free(id);
}
static char *
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)
+ {
+ 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();
+ }
+ }
+ }
+ }
+ if (do_append)
{
- strcat(id, data);
- if (eina_list_next(l)) strcat(id, ".");
+ if (stack) eina_strbuf_append(stack_buf, ".");
+ eina_strbuf_append(stack_buf, token);
}
- return id;
+ 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
DBG("Parsing input file");
+ /* Allocate arrays used to impl nested parts */
+ edje_cc_handlers_hierarchy_alloc();
p = data;
end = data + size;
line = 1;
exit(-1);
}
else
- stack_chop_top();
+ stack_pop();
}
else if (*token == ';')
{
params = eina_list_remove(params, eina_list_data_get(params));
}
/* remove top from stack */
- stack_chop_top();
+ stack_pop();
}
}
else if (*token == '{')
params = eina_list_append(params, token);
else
{
- stack = eina_list_append(stack, token);
+ stack_push(token);
new_object();
if ((verbatim == 1) && (p < (end - 2)))
{
}
}
+ edje_cc_handlers_hierarchy_free();
DBG("Parsing done");
}
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));
--- /dev/null
+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;
+ }
+ }
+ }
+ }
+ }
+ }
+}
}
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,
/* 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;
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);
+ }
}
}
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);
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,
}
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;
* (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);
} 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
{
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;
}
}
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;
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;
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)
{
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)
{
_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);
{
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 */
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
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
#ifdef EDJE_CALC_CACHE
unsigned char invalidate : 1; // 0
#endif
-}; // 264
+}; // 268
// WITH EDJE_CALC_CACHE: 404
struct _Edje_Running_Program
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);
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;
}
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);
}