Description
What MCU/Processor/Board and compiler are you using?
Simulator, GCC.
What LVGL version are you using?
v7.1.0
What do you want to achieve?
I’d like to be able to apply styles in a theme (that I create) in a more fine-grained way to basic widgets.
For example, if I have a label that’s a heading, I’d like to say mylabel = lv_label_create(...)
, “tag” it somehow, and have the theme apply a style that’s appropriate (eg. larger font, different colour).
Another application is alternating colours on table rows. Instead of having a loop that manually sets a specific colour, I could have the loop tag each row “odd” and “even”, and the theme applies the relevant background colour.
What have you tried so far?
I’ve defined an enum
type that uses the typical bit-as-flag idiom. Each bit is a tag eg. 0x01
means odd table row. Kind of like:
typedef enum
{
MY_THEME_TAG_EVEN = 1U << 0,
MY_THEME_TAG_ODD = 1U << 1,
MY_THEME_TAG_HEADER = 1U << 2
} my_theme_tag_t;
In lv_conf.h
I’ve set the type for user_data
on the base object to be this type ie.
typedef my_theme_tag_t lv_obj_user_data_t;
I apply the tag after creating the object eg.
myobj = lv_(whatever)_create(...);
myobj.user_data = MY_THEME_TAG_HEADER;
In my custom theme, I have the theme_apply()
function read these tags and apply some extra logic eg.
void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
{
lv_style_list_t * list;
const my_theme_tag_t tags = obj->user_data;
switch(name) {
// ...
case LV_THEME_LABEL:
lv_obj_clean_style_list(obj, LV_LABEL_PART_MAIN);
list = lv_obj_get_style_list(obj, LV_LABEL_PART_MAIN);
if (tags & MY_THEME_TAG_HEADER)
{
_lv_style_list_add_style(list, &styles->header);
}
else
{
_lv_style_list_add_style(list, &styles->bg);
}
break;
// ...
}
But since the theme is applied to the object in the create function (actually in the init function), I need to apply the theme again after tagging it, so finally:
lv_theme_apply(myobj, LV_THEME_WHATEVER);
This seems a bit clunky, and not very performant. Each style for each widget has to be applied twice, sometimes in a loop (in the case of table rows). It’s also an extra line of code for each object, which I need to remember and someone else needs to read.
But I can’t really think of a better way to do this (without modifying LVGL in my own project, which I don’t want to do). The next best thing I can think of is to ignore themes and just put all my custom styles on each object manually, which seems worse.
Code to reproduce
I didn’t want to dump my entire theme source etc. etc. in here, so I just put snippets up there. Let me know if you want more info.