From 800f5d81569caab9fca824b11fb8ea2259e2ae7d Mon Sep 17 00:00:00 2001 From: Jee-Yong Um Date: Fri, 5 Feb 2016 07:55:46 +0100 Subject: [PATCH] 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 --- 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 aa49caa8a4..84d8223fe1 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 f5fd9408c7..20420642cb 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 cc11fad5e0..ea1c190831 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 4466c8729d..c7ea53a723 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(¶ms); 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 526324ed83..e6e99b43c7 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 17046708b8..ce2652ba15 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 18e014e7e6..4eaaec9592 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 4f0e070ee4..a3385421d4 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 fe82a6c921..75f9a7fcec 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 8dc51c361e..892022b96e 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) {