feat(xml): add remove_style and remove_style_all support

This commit is contained in:
Gabor Kiss-Vamosi
2025-06-07 18:23:01 +02:00
parent a134a56995
commit 3951ea4b95
10 changed files with 211 additions and 35 deletions
+37 -3
View File
@@ -3,10 +3,44 @@
void lv_example_xml_2(void)
{
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/view.xml");
lv_result_t res;
res = lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_h3.xml");
if(res != LV_RESULT_OK) {
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Couldn't open the XML files.");
lv_obj_center(label);
return;
}
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_card.xml");
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_button.xml");
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/view.xml");
lv_obj_t * obj = (lv_obj_t *) lv_xml_create(NULL, "view", NULL);
lv_screen_load(obj);
lv_xml_register_font(NULL, "lv_montserrat_18", &lv_font_montserrat_18);
lv_obj_t * obj = (lv_obj_t *) lv_xml_create(lv_screen_active(), "view", NULL);
lv_obj_set_pos(obj, 10, 10);
const char * my_button_attrs[] = {
"x", "10",
"y", "-10",
"align", "bottom_left",
"btn_text", "New button",
NULL, NULL,
};
lv_xml_component_unregister("my_button");
lv_xml_create(lv_screen_active(), "my_button", my_button_attrs);
const char * slider_attrs[] = {
"x", "200",
"y", "-15",
"align", "bottom_left",
"value", "30",
NULL, NULL,
};
lv_obj_t * slider = (lv_obj_t *) lv_xml_create(lv_screen_active(), "lv_slider", slider_attrs);
lv_obj_set_width(slider, 100);
}
#endif
+2 -5
View File
@@ -8,11 +8,8 @@
<prop name="btn_text" type="string"/>
</api>
<view width="#size">
<lv_button align="center">
<lv_label text="$btn_text" align="center" color="#orange"/>
<screen_load_event screen="main_screen"/>
</lv_button>
<view extends="lv_button" width="#size">
<my_h3 text="$btn_text" align="center" color="#orange"/>
</view>
</component>
+39 -8
View File
@@ -1,8 +1,39 @@
<screen>
<view style_bg_color="0xff7788" name="main_screen">
<lv_button>
<lv_label text="Load"/>
<screen_create_event screen="my_button" anim_type="over_right" duration="500" delay="1000"/>
</lv_button>
</view>
</screen>
<component>
<consts>
<color name="light_blue" value="0xbbbbff"/>
<color name="dark_blue" value="0x000080"/>
</consts>
<styles>
<style name="btn_style" bg_color="#dark_blue" bg_opa="150"/>
<style name="btn_pr_style" bg_opa="255"/>
<style name="red_border" border_width="2" border_side="full" border_color="0xff0000"></style>
</styles>
<subjects>
<int name="subject1" value="10"/>
</subjects>
<view extends="lv_obj" flex_flow="column" name="main" width="280" height="content" style_bg_color="#light_blue">
<lv_label bind_text="subject1" styles="btn_style:disabled red_border:checked">
<bind_flag_if_gt subject="subject1" flag="hidden" ref_value="60"/>
<bind_state_if_lt subject="subject1" state="checked" ref_value="40"/>
<bind_state_if_lt subject="subject1" state="disabled" ref_value="20"/>
<style name="btn_style" selector="disabled"/>
<style name="red_border" selector="knob checked"/>
</lv_label>
<lv_slider bind_value="subject1" />
<my_card title="Card 1" name="card1"
y="100"
styles="red_border"
btn_rel_style="btn_style"
btn_pr_style="btn_pr_style"/>
<my_card y="185"
bg_color="0xffaaaa"
action="Apply"
btn_rel_style="btn_style"
btn_pr_style="btn_pr_style"/>
</view>
</component>
+5
View File
@@ -110,6 +110,10 @@ void lv_xml_init(void)
lv_xml_calendar_header_dropdown_apply);
lv_xml_widget_register("lv_obj-style", lv_obj_xml_style_create, lv_obj_xml_style_apply);
lv_xml_widget_register("lv_obj-remove_style", lv_obj_xml_remove_style_create, lv_obj_xml_remove_style_apply);
lv_xml_widget_register("lv_obj-remove_style_all", lv_obj_xml_remove_style_all_create,
lv_obj_xml_remove_style_all_apply);
lv_xml_widget_register("lv_obj-event_cb", lv_obj_xml_event_cb_create, lv_obj_xml_event_cb_apply);
lv_xml_widget_register("lv_obj-subject_set_int", lv_obj_xml_subject_set_create, lv_obj_xml_subject_set_apply);
lv_xml_widget_register("lv_obj-subject_set_string", lv_obj_xml_subject_set_create, lv_obj_xml_subject_set_apply);
@@ -119,6 +123,7 @@ void lv_xml_init(void)
lv_obj_xml_screen_load_event_apply);
lv_xml_widget_register("lv_obj-screen_create_event", lv_obj_xml_screen_create_event_create,
lv_obj_xml_screen_create_event_apply);
lv_xml_widget_register("lv_obj-bind_flag_if_eq", lv_obj_xml_bind_flag_create, lv_obj_xml_bind_flag_apply);
lv_xml_widget_register("lv_obj-bind_flag_if_not_eq", lv_obj_xml_bind_flag_create, lv_obj_xml_bind_flag_apply);
lv_xml_widget_register("lv_obj-bind_flag_if_gt", lv_obj_xml_bind_flag_create, lv_obj_xml_bind_flag_apply);
+67 -17
View File
@@ -34,6 +34,7 @@ typedef struct {
**********************/
static lv_obj_flag_t flag_to_enum(const char * txt);
static void apply_styles(lv_xml_parser_state_t * state, lv_obj_t * obj, const char * name, const char * value);
static lv_style_selector_t get_selector(const char * str);
static void free_user_data_event_cb(lv_event_t * e);
static void screen_create_on_trigger_event_cb(lv_event_t * e);
static void screen_load_on_trigger_event_cb(lv_event_t * e);
@@ -173,29 +174,56 @@ void lv_obj_xml_style_apply(lv_xml_parser_state_t * state, const char ** attrs)
return;
}
lv_style_selector_t selector = 0;
const char * selector_str = lv_xml_get_value_of(attrs, "selector");
if(selector_str) {
char buf[256];
lv_strncpy(buf, selector_str, sizeof(buf));
char * bufp = buf;
const char * next = lv_xml_split_str(&bufp, '|');
while(next) {
/* Handle different states and parts */
selector |= lv_xml_style_state_to_enum(next);
selector |= lv_xml_style_part_to_enum(next);
/* Move to the next token */
next = lv_xml_split_str(&bufp, '|');
}
}
lv_style_selector_t selector = get_selector(selector_str);
void * item = lv_xml_state_get_parent(state);
lv_obj_add_style(item, &xml_style->style, selector);
}
void * lv_obj_xml_remove_style_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_parent(state);
return item;
}
void lv_obj_xml_remove_style_apply(lv_xml_parser_state_t * state, const char ** attrs)
{
const char * style_str = lv_xml_get_value_of(attrs, "name");
const char * selector_str = lv_xml_get_value_of(attrs, "selector");
lv_style_t * style = NULL;
if(style_str) {
lv_xml_style_t * xml_style = lv_xml_get_style_by_name(&state->scope, style_str);
if(xml_style == NULL) {
LV_LOG_WARN("No style found with name `%s`", style_str);
return;
}
style = &xml_style->style;
}
lv_style_selector_t selector = get_selector(selector_str);
void * item = lv_xml_state_get_item(state);
lv_obj_remove_style(item, style, selector);
}
void * lv_obj_xml_remove_style_all_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_parent(state);
return item;
}
void lv_obj_xml_remove_style_all_apply(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_item(state);
lv_obj_remove_style_all(item);
}
void * lv_obj_xml_event_cb_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
@@ -724,6 +752,28 @@ static void apply_styles(lv_xml_parser_state_t * state, lv_obj_t * obj, const ch
else SET_STYLE_IF(grid_cell_y_align, lv_xml_grid_align_to_enum(value));
}
static lv_style_selector_t get_selector(const char * str)
{
if(str == NULL) return 0;
lv_style_selector_t selector = 0;
char buf[256];
lv_strncpy(buf, str, sizeof(buf));
char * bufp = buf;
const char * next = lv_xml_split_str(&bufp, '|');
while(next) {
/* Handle different states and parts */
selector |= lv_xml_style_state_to_enum(next);
selector |= lv_xml_style_part_to_enum(next);
/* Move to the next token */
next = lv_xml_split_str(&bufp, '|');
}
return selector;
}
static void free_user_data_event_cb(lv_event_t * e)
{
lv_free(lv_event_get_user_data(e));
@@ -30,6 +30,12 @@ void lv_xml_obj_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_style_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_style_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_remove_style_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_remove_style_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_remove_style_all_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_remove_style_all_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_event_cb_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_event_cb_apply(lv_xml_parser_state_t * state, const char ** attrs);
@@ -1,4 +1,4 @@
#if LV_BUILD_TEST || 1
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
+42 -1
View File
@@ -1,4 +1,4 @@
#if LV_BUILD_TEST
#if LV_BUILD_TEST || 1
#include "../lvgl.h"
#include "unity/unity.h"
@@ -138,7 +138,48 @@ void test_xml_style_same_name(void)
lv_xml_component_register_from_data("comp1", comp1);
lv_obj_t * obj = lv_xml_create(lv_screen_active(), "comp1", NULL);
TEST_ASSERT_EQUAL(20, lv_obj_get_style_bg_opa(obj, 0));
}
void test_xml_style_remove(void)
{
const char * comp1 =
"<component>"
" <styles>"
" <style name=\"s1\" bg_opa=\"100\" border_width=\"2\"/>"
" <style name=\"s2\" bg_color=\"0xff0000\"/>"
" </styles>"
""
" <view extends=\"lv_slider\">"
" <remove_style/>"
" <remove_style selector=\"knob\"/>"
" <style name=\"s1\" selector=\"knob|pressed\"/>"
" <style name=\"s2\" selector=\"knob|pressed\"/>"
" <remove_style name=\"s2\" selector=\"knob|pressed\"/>"
" <remove_style name=\"s3\"/>"
" </view>"
"</component>";
lv_xml_component_register_from_data("comp1", comp1);
lv_obj_t * obj = lv_xml_create(lv_screen_active(), "comp1", NULL);
/*The first remove_style removed the main style, so the radius should be the default 0*/
TEST_ASSERT_EQUAL(0, lv_obj_get_style_radius(obj, 0));
/*Styles are removed from the knob in the default state*/
TEST_ASSERT_EQUAL(0, lv_obj_get_style_radius(obj, LV_PART_KNOB));
lv_obj_add_state(obj, LV_STATE_PRESSED);
lv_test_wait(1000); /*Wait for transitions*/
/*s1 sets bg_opa=100 in pressed state*/
TEST_ASSERT_EQUAL(100, lv_obj_get_style_bg_opa(obj, LV_PART_KNOB));
/*s2 is added and removed so the red bg_color shouldn't be applied*/
TEST_ASSERT_NOT_EQUAL_COLOR(lv_color_hex(0xff0000), lv_obj_get_style_bg_color(obj, LV_PART_KNOB));
lv_xml_component_unregister("comp1");
}
#endif
+5
View File
@@ -33,6 +33,11 @@ extern "C" {
# define TEST_ASSERT_EQUAL_COLOR32(c1, c2) TEST_ASSERT_TRUE(lv_color32_eq(c1, c2))
# define TEST_ASSERT_EQUAL_COLOR32_MESSAGE(c1, c2, msg) TEST_ASSERT_TRUE(lv_color32_eq(c1, c2), msg)
# define TEST_ASSERT_NOT_EQUAL_COLOR(c1, c2) TEST_ASSERT_FALSE(lv_color_eq(c1, c2))
# define TEST_ASSERT_NOT_EQUAL_COLOR_MESSAGE(c1, c2, msg) TEST_ASSERT_FALSE(lv_color_eq(c1, c2), msg)
# define TEST_ASSERT_NOT_EQUAL_COLOR32(c1, c2) TEST_ASSERT_FALSE(lv_color32_eq(c1, c2))
# define TEST_ASSERT_NOT_EQUAL_COLOR32_MESSAGE(c1, c2, msg) TEST_ASSERT_FALSE(lv_color32_eq(c1, c2), msg)
# define TEST_ASSERT_MEM_LEAK_LESS_THAN(prev_usage, threshold) TEST_ASSERT_LESS_OR_EQUAL(threshold, LV_ABS((int64_t)(prev_usage) - (int64_t)lv_test_get_free_mem()));
+7
View File
@@ -44,6 +44,13 @@ Example
<arg name="selector" type="selector+" default="0"/>
</element>
<element name="remove_style" access="custom" type="void">
<arg name="name" type="style" default="NULL"/>
<arg name="selector" type="selector+" default="0"/>
</element>
<element name="remove_style_all" access="custom" type="void"/>
<element name="event_cb" access="add">
<arg name="name" type="string"/>
<arg name="trigger" type="lv_event" default="clicked"/>