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 <cedric@osg.samsung.com>
This commit is contained in:
Jee-Yong Um 2016-02-05 07:55:46 +01:00 committed by Cedric BAIL
parent a416f73790
commit 800f5d8156
10 changed files with 311 additions and 16 deletions

View File

@ -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;

View File

@ -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} */

View File

@ -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);
}

View File

@ -1045,6 +1045,7 @@ compile(void)
eina_array_flush(&params);
eina_strbuf_free(stack_buf);
stack_buf = NULL;
color_tree_root_free();
}
else
{

View File

@ -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)

View File

@ -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)
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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)
{