cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=800f5d81569caab9fca824b11fb8ea2259e2ae7d

commit 800f5d81569caab9fca824b11fb8ea2259e2ae7d
Author: Jee-Yong Um <jc9...@samsung.com>
Date:   Fri Feb 5 07:55:46 2016 +0100

    edje: introduce color_tree (color_class inheritance)
    
    Summary:
    The "color_tree" block contains a list of one or more "node" blocks.
    A "node" block consists of its own color class name and the list of child
    color classes. At runtime, parent color class will be referred instead,
    if child color class is set to part but its color values are not defined.
    
    Reviewers: raster, Jaehyun_Cho, jpeg, cedric
    
    Reviewed By: cedric
    
    Subscribers: cedric, kimcinoo
    
    Differential Revision: https://phab.enlightenment.org/D3606
    
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 src/bin/edje/edje_cc.h          |   4 ++
 src/bin/edje/edje_cc_handlers.c |  48 ++++++++++++++
 src/bin/edje/edje_cc_out.c      | 141 ++++++++++++++++++++++++++++++++++++++++
 src/bin/edje/edje_cc_parse.c    |   1 +
 src/lib/edje/edje_cache.c       |  10 ++-
 src/lib/edje/edje_calc.c        |   2 +-
 src/lib/edje/edje_data.c        |   8 +++
 src/lib/edje/edje_load.c        |   9 +++
 src/lib/edje/edje_private.h     |  11 ++++
 src/lib/edje/edje_util.c        |  93 ++++++++++++++++++++++----
 10 files changed, 311 insertions(+), 16 deletions(-)

diff --git a/src/bin/edje/edje_cc.h b/src/bin/edje/edje_cc.h
index aa49caa..84d8223 100644
--- a/src/bin/edje/edje_cc.h
+++ b/src/bin/edje/edje_cc.h
@@ -194,6 +194,7 @@ void    data_queue_spectrum_slave_lookup(int *master, int 
*slave);
 void    data_process_lookups(void);
 void    data_process_scripts(void);
 void    data_process_script_lookups(void);
+void    process_color_tree(char *s, const char *file_in, int line);
 
 void    part_description_image_cleanup(Edje_Part *ep);
 
@@ -252,6 +253,8 @@ void edje_cc_handlers_hierarchy_free(void);
 void edje_cc_handlers_pop_notify(const char *token);
 int get_param_index(char *str);
 
+void color_tree_root_free(void);
+
 /* global vars */
 extern Eina_List             *ext_dirs;
 extern Eina_List             *img_dirs;
@@ -297,6 +300,7 @@ extern int                    compress_mode;
 extern int                    threads;
 extern int                    annotate;
 extern Eina_Bool current_group_inherit;
+extern Eina_List             *color_tree_root;
 
 extern int had_quote;
 
diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c
index f5fd940..2042064 100644
--- a/src/bin/edje/edje_cc_handlers.c
+++ b/src/bin/edje/edje_cc_handlers.c
@@ -216,6 +216,8 @@ static void st_styles_style_name(void);
 static void st_styles_style_base(void);
 static void st_styles_style_tag(void);
 
+static void ob_color_tree(void);
+
 static void ob_color_class(void);
 static void st_color_class_name(void);
 static void st_color_class_color(void);
@@ -1172,6 +1174,7 @@ New_Object_Handler object_handlers[] =
      {"data", NULL},
      {"styles", NULL},
      {"styles.style", ob_styles_style},
+     {"color_tree", ob_color_tree},
      {"color_classes", NULL},
      {"color_classes.color_class", ob_color_class},
      {"text_classes", NULL},
@@ -1192,6 +1195,7 @@ New_Object_Handler object_handlers[] =
      {"collections.fonts", NULL}, /* dup */
      {"collections.styles", NULL}, /* dup */
      {"collections.styles.style", ob_styles_style}, /* dup */
+     {"collections.color_tree", ob_color_tree}, /* dup */
      {"collections.color_classes", NULL}, /* dup */
      {"collections.color_classes.color_class", ob_color_class}, /* dup */
      {"collections.text_classes", NULL},
@@ -1228,6 +1232,7 @@ New_Object_Handler object_handlers[] =
      {"collections.group.fonts", NULL}, /* dup */
      {"collections.group.styles", NULL}, /* dup */
      {"collections.group.styles.style", ob_styles_style}, /* dup */
+     {"collections.group.color_tree", ob_color_tree}, /* dup */
      {"collections.group.color_classes", NULL}, /* dup */
      {"collections.group.color_classes.color_class", ob_color_class}, /* dup */
      {"collections.group.text_classes", NULL},
@@ -2644,6 +2649,49 @@ st_data_file(void)
    free(filename);
 }
 
+/** @edcsubsection{toplevel_color_tree,
+ *                 Color Tree} */
+
+/**
+    @page edcref
+    @block
+        color_tree
+    @context
+        color_tree {
+            "color_class_0" {
+                "color_class_3";
+                "color_class_4" {
+                    "color_class_5";
+                    "color_class_6";
+                }
+            }
+            "color_class_1";
+            "color_class_2";
+            ..
+        }
+    @description
+        The "color_tree" block contains color tree node blocks.
+        Each node block begins with the name of color class and enclosed with 
braces.
+        Node block can be placed within another node block.
+    @endblock
+*/
+static void
+ob_color_tree(void)
+{
+   if (!is_verbatim()) track_verbatim(1);
+   else
+     {
+        char *s;
+
+        s = get_verbatim();
+        if (s)
+          {
+             process_color_tree(s, file_in, get_verbatim_line1());
+             set_verbatim(NULL, 0, 0);
+          }
+     }
+}
+
 /** @edcsubsection{toplevel_color_classes,
  *                 Color Classes} */
 
diff --git a/src/bin/edje/edje_cc_out.c b/src/bin/edje/edje_cc_out.c
index cc11fad..ea1c190 100644
--- a/src/bin/edje/edje_cc_out.c
+++ b/src/bin/edje/edje_cc_out.c
@@ -220,6 +220,7 @@ Eina_List *fonts = NULL;
 Eina_List *codes = NULL;
 Eina_List *code_lookups = NULL;
 Eina_List *aliases = NULL;
+Eina_List *color_tree_root = NULL;
 
 static Eet_Data_Descriptor *edd_edje_file = NULL;
 static Eet_Data_Descriptor *edd_edje_part_collection = NULL;
@@ -4139,3 +4140,143 @@ needed_part_exists(Edje_Part_Collection *pc, const char 
*name)
      }
    return found;
 }
+
+void
+color_tree_root_free(void)
+{
+   char *name;
+
+   EINA_LIST_FREE(color_tree_root, name)
+     free(name);
+}
+
+char *
+color_tree_token_next(char *dst, char *src, int *line)
+{
+   Eina_Bool begin = EINA_FALSE, next = EINA_FALSE;
+
+   while (!next)
+     {
+        if (*src == '\0') break;
+
+        if (*src == '"')
+          {
+             if (!begin) begin = EINA_TRUE;
+             else next = EINA_TRUE;
+          }
+        else if ((!begin) && ((*src == '{') || (*src == '}') || (*src == ';')))
+          {
+             *dst++ = *src;
+             next = EINA_TRUE;
+          }
+        else if ((!begin) && (*src == '\n'))
+          {
+             (*line)++;
+          }
+        else if (begin)
+          {
+             *dst++ = *src;
+          }
+        src++;
+     }
+   *dst = '\0';
+   return src;
+}
+
+Edje_Color_Tree_Node *
+color_tree_parent_node_get(const char *color_class)
+{
+   Edje_Color_Tree_Node *ctn;
+   Eina_List *l, *ll;
+   char *name;
+
+   EINA_LIST_FOREACH(edje_file->color_tree, l, ctn)
+      if (ctn->color_classes)
+         EINA_LIST_FOREACH(ctn->color_classes, ll, name)
+            if (!strcmp(name, color_class))
+              return ctn;
+
+   return NULL;
+}
+
+void
+process_color_tree(char *s, const char *file_in, int line)
+{
+   char token[2][1024];
+   int id = 0;
+   Eina_Array *array;
+   Edje_Color_Tree_Node *ctn;
+   Eina_List *l;
+   char *name;
+
+   array = eina_array_new(4);
+
+   if (!s) return;
+
+   do
+     {
+        s = color_tree_token_next(token[id], s, &line);
+
+        if (!strcmp(token[id], "{"))
+          {
+             if (!token[!id][0])
+               error_and_abort(NULL, "parse error %s:%i. color class is not 
set to newly opened node block.",
+                               file_in, line - 1);
+
+             ctn = mem_alloc(SZ(Edje_Color_Tree_Node));
+             ctn->name = strdup(token[!id]);
+             ctn->color_classes = NULL;
+
+             edje_file->color_tree = eina_list_append(edje_file->color_tree, 
ctn);
+
+             eina_array_push(array, ctn);
+             token[id][0] = '\0';
+          }
+        else if (!strcmp(token[id], "}"))
+          {
+             eina_array_pop(array);
+             token[id][0] = '\0';
+          }
+        else if (!strcmp(token[id], ";"))
+          {
+             token[id][0] = '\0';
+          }
+        else if (*s != '\0')
+          {
+             if (eina_array_count(array))
+               {
+                  if (color_tree_root)
+                    EINA_LIST_FOREACH(color_tree_root, l, name)
+                      if (!strcmp(name, token[id]))
+                        {
+                           error_and_abort(NULL, "parse error %s:%i. The color 
class \"%s\" already belongs to the root node.",
+                                           file_in, line -1, token[id]);
+                        }
+
+                  if ((ctn = color_tree_parent_node_get(token[id])))
+                    error_and_abort(NULL, "parse error %s:%i. The color class 
\"%s\" already belongs to the \"%s\" node.",
+                                    file_in, line -1, token[id], ctn->name);
+
+                  ctn = eina_array_data_get(array, eina_array_count(array) - 
1);
+                  ctn->color_classes = eina_list_append(ctn->color_classes, 
strdup(token[id]));
+               }
+             else
+               {
+                  if ((ctn = color_tree_parent_node_get(token[id])))
+                    error_and_abort(NULL, "parse error %s:%i. The color class 
\"%s\" already belongs to the \"%s\" node.",
+                                    file_in, line -1, token[id], ctn->name);
+
+                  color_tree_root = eina_list_append(color_tree_root, 
strdup(token[id]));
+               }
+          }
+
+        id = !id;
+
+     } while (*s);
+
+   if (eina_array_count(array))
+     error_and_abort(NULL, "parse error %s:%i. check pair of parens.", 
file_in, line - 1);
+
+   eina_array_clean(array);
+   eina_array_free(array);
+}
diff --git a/src/bin/edje/edje_cc_parse.c b/src/bin/edje/edje_cc_parse.c
index 4466c87..c7ea53a 100644
--- a/src/bin/edje/edje_cc_parse.c
+++ b/src/bin/edje/edje_cc_parse.c
@@ -1045,6 +1045,7 @@ compile(void)
         eina_array_flush(&params);
         eina_strbuf_free(stack_buf);
         stack_buf = NULL;
+        color_tree_root_free();
      }
    else
      {
diff --git a/src/lib/edje/edje_cache.c b/src/lib/edje/edje_cache.c
index 526324e..e6e99b4 100644
--- a/src/lib/edje/edje_cache.c
+++ b/src/lib/edje/edje_cache.c
@@ -261,12 +261,14 @@ _edje_file_coll_open(Edje_File *edf, const char *coll)
 static Edje_File *
 _edje_file_open(const Eina_File *f, int *error_ret, time_t mtime, Eina_Bool 
coll)
 {
+   Edje_Color_Tree_Node *ctn;
    Edje_Color_Class *cc;
    Edje_Text_Class *tc;
    Edje_Size_Class *sc;
    Edje_File *edf;
-   Eina_List *l;
+   Eina_List *l, *ll;
    Eet_File *ef;
+   char *name;
 
    ef = eet_mmap(f);
    if (!ef)
@@ -315,6 +317,12 @@ _edje_file_open(const Eina_File *f, int *error_ret, time_t 
mtime, Eina_Bool coll
 
    /* This should be done at edje generation time */
    _edje_textblock_style_parse_and_fix(edf);
+
+   edf->color_tree_hash = eina_hash_string_small_new(NULL);
+   EINA_LIST_FOREACH(edf->color_tree, l, ctn)
+     EINA_LIST_FOREACH(ctn->color_classes, ll, name)
+       eina_hash_add(edf->color_tree_hash, name, ctn);
+
    edf->color_hash = eina_hash_string_small_new(NULL);
    EINA_LIST_FOREACH(edf->color_classes, l, cc)
      if (cc->name)
diff --git a/src/lib/edje/edje_calc.c b/src/lib/edje/edje_calc.c
index 1704670..ce2652b 100644
--- a/src/lib/edje/edje_calc.c
+++ b/src/lib/edje/edje_calc.c
@@ -2762,7 +2762,7 @@ _edje_part_recalc_single(Edje *ed,
    if (ep->part->type != EDJE_PART_TYPE_SPACER)
      {
         if ((desc->color_class) && (*desc->color_class))
-          cc = _edje_color_class_find(ed, desc->color_class);
+          cc = _edje_color_class_recursive_find(ed, desc->color_class);
 
         if (cc)
           {
diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c
index 18e014e..4eaaec9 100644
--- a/src/lib/edje/edje_data.c
+++ b/src/lib/edje/edje_data.c
@@ -6,6 +6,7 @@ EAPI Eet_Data_Descriptor * _edje_edd_edje_part_collection = 
NULL;
 Eet_Data_Descriptor *_edje_edd_edje_string = NULL;
 Eet_Data_Descriptor *_edje_edd_edje_style = NULL;
 Eet_Data_Descriptor *_edje_edd_edje_style_tag = NULL;
+Eet_Data_Descriptor *_edje_edd_edje_color_tree_node = NULL;
 Eet_Data_Descriptor *_edje_edd_edje_color_class = NULL;
 Eet_Data_Descriptor *_edje_edd_edje_text_class = NULL;
 Eet_Data_Descriptor *_edje_edd_edje_size_class = NULL;
@@ -521,6 +522,12 @@ _edje_edd_init(void)
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_style, Edje_Style, "name", 
name, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_style, Edje_Style, "tags", 
tags, _edje_edd_edje_style_tag);
 
+   EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Color_Tree_Node);
+   _edje_edd_edje_color_tree_node =
+     eet_data_descriptor_file_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_color_tree_node, 
Edje_Color_Tree_Node, "name", name, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_LIST_STRING(_edje_edd_edje_color_tree_node, 
Edje_Color_Tree_Node, "color_classes", color_classes);
+
    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Color_Class);
    _edje_edd_edje_color_class =
      eet_data_descriptor_file_new(&eddc);
@@ -579,6 +586,7 @@ _edje_edd_init(void)
 
    EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, 
"vibration_dir", vibration_dir, _edje_edd_edje_vibration_directory);
    EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "styles", 
styles, _edje_edd_edje_style);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "color_tree", 
color_tree, _edje_edd_edje_color_tree_node);
    EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, 
"color_classes", color_classes, _edje_edd_edje_color_class);
    EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, 
"text_classes", text_classes, _edje_edd_edje_text_class);
    EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, 
"size_classes", size_classes, _edje_edd_edje_size_class);
diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c
index 4f0e070..a338542 100644
--- a/src/lib/edje/edje_load.c
+++ b/src/lib/edje/edje_load.c
@@ -1682,6 +1682,7 @@ _edje_file_del(Edje *ed)
 void
 _edje_file_free(Edje_File *edf)
 {
+   Edje_Color_Tree_Node *ectn;
    Edje_Color_Class *ecc;
    Edje_Text_Class *etc;
    Edje_Size_Class *esc;
@@ -1777,6 +1778,14 @@ _edje_file_free(Edje_File *edf)
         free(edf->external_dir);
      }
 
+   eina_hash_free(edf->color_tree_hash);
+   EINA_LIST_FREE(edf->color_tree, ectn)
+     {
+        if (edf->free_strings && ectn->name) eina_stringshare_del(ectn->name);
+        eina_list_free(ectn->color_classes);
+        free(ectn);
+     }
+
    eina_hash_free(edf->color_hash);
    EINA_LIST_FREE(edf->color_classes, ecc)
      {
diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h
index fe82a6c..75f9a7f 100644
--- a/src/lib/edje/edje_private.h
+++ b/src/lib/edje/edje_private.h
@@ -328,6 +328,7 @@ typedef struct _Edje_Mo                              
Edje_Mo;
 typedef struct _Edje_Mo_Directory                    Edje_Mo_Directory;
 typedef struct _Edje_Gfx_Filter                      Edje_Gfx_Filter;
 typedef struct _Edje_Gfx_Filter_Directory            Edje_Gfx_Filter_Directory;
+typedef struct _Edje_Color_Tree_Node                 Edje_Color_Tree_Node;
 
 typedef struct _Edje_Vibration_Sample                Edje_Vibration_Sample;
 typedef struct _Edje_Vibration_Directory             Edje_Vibration_Directory;
@@ -539,6 +540,9 @@ struct _Edje_File
 
    Eina_List                      *styles;
 
+   Eina_List                      *color_tree;
+   Eina_Hash                      *color_tree_hash;
+
    Eina_List                      *color_classes;
    Eina_Hash                      *color_hash;
 
@@ -741,6 +745,12 @@ struct _Edje_Gfx_Filter_Directory
    int              filters_count;
 };
 
+struct _Edje_Color_Tree_Node
+{
+   const char *name;
+   Eina_List  *color_classes;
+};
+
 /*----------*/
 
 struct _Edje_Program /* a conditional program to be run */
@@ -2360,6 +2370,7 @@ const char *   _edje_text_font_get(const char *base, 
const char *new,
 Edje_Real_Part   *_edje_real_part_get(const Edje *ed, const char *part);
 Edje_Real_Part   *_edje_real_part_recursive_get(Edje **ed, const char *part);
 Edje_Color_Class *_edje_color_class_find(const Edje *ed, const char 
*color_class);
+Edje_Color_Class *_edje_color_class_recursive_find(const Edje *ed, const char 
*color_class);
 void              _edje_color_class_member_add(Edje *ed, const char 
*color_class);
 void              _edje_color_class_member_del(Edje *ed, const char 
*color_class);
 void              _edje_color_class_member_clean(Edje *ed);
diff --git a/src/lib/edje/edje_util.c b/src/lib/edje/edje_util.c
index 8dc51c3..892022b 100644
--- a/src/lib/edje/edje_util.c
+++ b/src/lib/edje/edje_util.c
@@ -613,6 +613,39 @@ _edje_object_thaw(Eo *obj EINA_UNUSED, Edje *ed)
    return _edje_util_thaw(ed);
 }
 
+static void
+_edje_color_class_apply(const char *color_class, const char *parent)
+{
+   Eina_Hash *members;
+   Eina_Iterator *it;
+   Edje_Refcount *er;
+   Edje_Color_Tree_Node *ctn;
+   Eina_List *l, *ll;
+   char *name;
+
+   members = eina_hash_find(_edje_color_class_member_hash, color_class);
+   if (!members) return;
+   it = eina_hash_iterator_data_new(members);
+   EINA_ITERATOR_FOREACH(it, er)
+     {
+        er->ed->dirty = EINA_TRUE;
+        er->ed->recalc_call = EINA_TRUE;
+#ifdef EDJE_CALC_CACHE
+        er->ed->all_part_change = EINA_TRUE;
+#endif
+        _edje_recalc(er->ed);
+        _edje_emit(er->ed, "color_class,set", parent);
+
+        EINA_LIST_FOREACH(er->ed->file->color_tree, l, ctn)
+          {
+             if ((!strcmp(ctn->name, color_class)) && (ctn->color_classes))
+                EINA_LIST_FOREACH(ctn->color_classes, ll, name)
+                  _edje_color_class_apply(name, parent);
+          }
+     }
+   eina_iterator_free(it);
+}
+
 EAPI Eina_Bool
 edje_color_class_set(const char *color_class, int r, int g, int b, int a, int 
r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3)
 {
@@ -671,20 +704,8 @@ edje_color_class_set(const char *color_class, int r, int 
g, int b, int a, int r2
    cc->b3 = b3;
    cc->a3 = a3;
 
-   members = eina_hash_find(_edje_color_class_member_hash, color_class);
-   if (!members) return EINA_TRUE;
-   it = eina_hash_iterator_data_new(members);
-   EINA_ITERATOR_FOREACH(it, er)
-     {
-        er->ed->dirty = EINA_TRUE;
-        er->ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-        er->ed->all_part_change = EINA_TRUE;
-#endif
-        _edje_recalc(er->ed);
-        _edje_emit(er->ed, "color_class,set", color_class);
-     }
-   eina_iterator_free(it);
+   _edje_color_class_apply(color_class, color_class);
+
    return EINA_TRUE;
 }
 
@@ -5761,6 +5782,50 @@ _edje_color_class_find(const Edje *ed, const char 
*color_class)
    return NULL;
 }
 
+Edje_Color_Class *
+_edje_color_class_recursive_find_helper(const Edje *ed, Eina_Hash *hash, const 
char *color_class)
+{
+   Edje_Color_Class *cc = NULL;
+   Edje_Color_Tree_Node *ctn = NULL;
+   const char *parent;
+
+   cc = eina_hash_find(hash, color_class);
+   if (cc) return cc;
+   else
+     {
+        parent = color_class;
+        while ((ctn = eina_hash_find(ed->file->color_tree_hash, parent)))
+          {
+             parent = ctn->name;
+             cc = eina_hash_find(hash, parent);
+             if (cc) return cc;
+          }
+     }
+   return NULL;
+}
+
+Edje_Color_Class *
+_edje_color_class_recursive_find(const Edje *ed, const char *color_class)
+{
+   Edje_Color_Class *cc = NULL;
+
+   if ((!ed) || (!color_class)) return NULL;
+
+   /* first look through the object scope */
+   cc = _edje_color_class_recursive_find_helper(ed, ed->color_classes, 
color_class);
+   if (cc) return cc;
+
+   /* next look through the global scope */
+   cc = _edje_color_class_recursive_find_helper(ed, _edje_color_class_hash, 
color_class);
+   if (cc) return cc;
+
+   /* finally, look through the file scope */
+   cc = _edje_color_class_recursive_find_helper(ed, ed->file->color_hash, 
color_class);
+   if (cc) return cc;
+
+   return NULL;
+}
+
 void
 _edje_color_class_member_add(Edje *ed, const char *color_class)
 {

-- 


Reply via email to