edje: add nested part support to edc.
authorCedric BAIL <cedric.bail@free.fr>
Tue, 4 Sep 2012 11:27:43 +0000 (11:27 +0000)
committerCedric BAIL <cedric.bail@free.fr>
Tue, 4 Sep 2012 11:27:43 +0000 (11:27 +0000)
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

13 files changed:
legacy/edje/ChangeLog
legacy/edje/NEWS
legacy/edje/doc/examples.dox
legacy/edje/src/bin/edje_cc.h
legacy/edje/src/bin/edje_cc_handlers.c
legacy/edje/src/bin/edje_cc_parse.c
legacy/edje/src/examples/edje-nested.edc [new file with mode: 0644]
legacy/edje/src/lib/edje_calc.c
legacy/edje/src/lib/edje_data.c
legacy/edje/src/lib/edje_edit.c
legacy/edje/src/lib/edje_load.c
legacy/edje/src/lib/edje_private.h
legacy/edje/src/lib/edje_smart.c

index 075a97d..bd38c4a 100644 (file)
 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 { } } }"
index eb1d060..ccc28da 100644 (file)
@@ -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:
index d0efafe..a2afc5a 100644 (file)
@@ -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
  */
 
 /**
+ * @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
  *
index 2001b90..4c5ec06 100644 (file)
@@ -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;
index 2f8a84b..b081161 100644 (file)
@@ -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;
                     }
@@ -3145,6 +3200,38 @@ st_collections_group_parts_part_type(void)
 /**
     @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]
@@ -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;
+   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);
    }
 }
@@ -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;
+   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);
    }
 }
@@ -8051,3 +8151,86 @@ ob_collections_group_programs_program_script(void)
     @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);
+     }
+}
index b327752..e87047a 100644 (file)
@@ -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)
+     {
+        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
@@ -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 (file)
index 0000000..d3ea064
--- /dev/null
@@ -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;
+                  }
+               }
+            }
+         }
+      }
+   }
+}
index 84f8090..b3827b6 100644 (file)
@@ -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);
+               }
           }
      }
 
index da30329..4c278d0 100644 (file)
@@ -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);
index 3991542..5ae5947 100644 (file)
@@ -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);
index d3f9fd2..d5c7293 100644 (file)
@@ -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);
index 9d5bb01..5678b8a 100644 (file)
@@ -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);
index 0a855cf..97f996e 100644 (file)
@@ -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);
 }