feat(state): Add state trickle down (#8499)

This commit is contained in:
Gauthier Provost
2025-07-04 00:20:25 +08:00
committed by GitHub
parent 6ec45fa613
commit 095b99cbc3
8 changed files with 59 additions and 10 deletions
@@ -468,6 +468,7 @@ There are some Widget attributes which can be enabled/disabled by
- :cpp:enumerator:`LV_OBJ_FLAG_PRESS_LOCK` Keep the Widget pressed even if the press slid from the Widget
- :cpp:enumerator:`LV_OBJ_FLAG_EVENT_BUBBLE` Propagate the events to the parent as well
- :cpp:enumerator:`LV_OBJ_FLAG_EVENT_TRICKLE` Propagate the events to the children as well
- :cpp:enumerator:`LV_OBJ_FLAG_STATE_TRICKLE` Propagate the state changes to the children as well
- :cpp:enumerator:`LV_OBJ_FLAG_GESTURE_BUBBLE` Propagate the gestures to the parent
- :cpp:enumerator:`LV_OBJ_FLAG_ADV_HITTEST` Allow performing more accurate hit (click) test. E.g. accounting for rounded corners
- :cpp:enumerator:`LV_OBJ_FLAG_IGNORE_LAYOUT` Make the Widget not positioned by the layouts
+1 -2
View File
@@ -25,7 +25,6 @@ void lv_example_event_trickle(void)
for(i = 0; i < 9; i++) {
lv_obj_t * subcont = lv_obj_create(cont);
lv_obj_set_size(subcont, 70, 50);
lv_obj_t * label = lv_label_create(subcont);
lv_label_set_text_fmt(label, "%" LV_PRIu32, i);
@@ -34,4 +33,4 @@ void lv_example_event_trickle(void)
}
}
#endif
#endif
+42
View File
@@ -60,6 +60,8 @@ static void draw_scrollbar(lv_obj_t * obj, lv_layer_t * layer);
static lv_result_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc);
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find);
static void update_obj_state(lv_obj_t * obj, lv_state_t new_state);
static void lv_obj_children_add_state(lv_obj_t * obj, lv_state_t state);
static void lv_obj_children_remove_state(lv_obj_t * obj, lv_state_t state);
static void null_on_delete_cb(lv_event_t * e);
static void screen_load_on_trigger_event_cb(lv_event_t * e);
static void screen_create_on_trigger_event_cb(lv_event_t * e);
@@ -322,6 +324,9 @@ void lv_obj_add_state(lv_obj_t * obj, lv_state_t state)
lv_state_t new_state = obj->state | state;
if(obj->state != new_state) {
update_obj_state(obj, new_state);
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_STATE_TRICKLE)) {
lv_obj_children_add_state(obj, state);
}
}
}
@@ -332,6 +337,9 @@ void lv_obj_remove_state(lv_obj_t * obj, lv_state_t state)
lv_state_t new_state = obj->state & (~state);
if(obj->state != new_state) {
update_obj_state(obj, new_state);
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_STATE_TRICKLE)) {
lv_obj_children_remove_state(obj, state);
}
}
}
@@ -1031,6 +1039,40 @@ static void update_obj_state(lv_obj_t * obj, lv_state_t new_state)
}
}
/**
* Apply the state to the children of the object
* @param obj pointer to an object
* @param state the state to apply
*/
static void lv_obj_children_add_state(lv_obj_t * obj, lv_state_t state)
{
uint32_t child_count = lv_obj_get_child_count(obj);
for(uint32_t i = 0; i < child_count; i++) {
lv_obj_t * child = lv_obj_get_child(obj, i);
if(child) {
lv_obj_add_state(child, state);
}
}
}
/**
* Remove the state from the children of the object
* @param obj pointer to an object
* @param state the state to remove
*/
static void lv_obj_children_remove_state(lv_obj_t * obj, lv_state_t state)
{
uint32_t child_count = lv_obj_get_child_count(obj);
for(uint32_t i = 0; i < child_count; i++) {
lv_obj_t * child = lv_obj_get_child(obj, i);
if(child) {
lv_obj_remove_state(child, state);
}
}
}
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find)
{
/*Check all children of `parent`*/
+8 -6
View File
@@ -112,13 +112,14 @@ typedef enum {
LV_OBJ_FLAG_FLOATING = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/
LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS = (1L << 19), /**< Send `LV_EVENT_DRAW_TASK_ADDED` events*/
LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 20),/**< Do not clip the children to the parent's ext draw size*/
#if LV_USE_FLEX
LV_OBJ_FLAG_FLEX_IN_NEW_TRACK = (1L << 21), /**< Start a new flex track on this item*/
#endif
LV_OBJ_FLAG_EVENT_TRICKLE = (1L << 22), /**< Propagate the events to the children too*/
LV_OBJ_FLAG_EVENT_TRICKLE = (1L << 21), /**< Propagate the events to the children too*/
LV_OBJ_FLAG_STATE_TRICKLE = (1L << 22), /**< Propagate the states to the children too*/
LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/
LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/
#if LV_USE_FLEX
LV_OBJ_FLAG_FLEX_IN_NEW_TRACK = LV_OBJ_FLAG_LAYOUT_1, /**< Start a new flex track on this item*/
#endif
LV_OBJ_FLAG_WIDGET_1 = (1L << 25), /**< Custom flag, free to use by widget*/
LV_OBJ_FLAG_WIDGET_2 = (1L << 26), /**< Custom flag, free to use by widget*/
@@ -153,10 +154,11 @@ enum _lv_signed_prop_id_t {
LV_PROPERTY_ID(OBJ, FLAG_FLOATING, LV_PROPERTY_TYPE_INT, 18),
LV_PROPERTY_ID(OBJ, FLAG_SEND_DRAW_TASK_EVENTS, LV_PROPERTY_TYPE_INT, 19),
LV_PROPERTY_ID(OBJ, FLAG_OVERFLOW_VISIBLE, LV_PROPERTY_TYPE_INT, 20),
LV_PROPERTY_ID(OBJ, FLAG_FLEX_IN_NEW_TRACK, LV_PROPERTY_TYPE_INT, 21),
LV_PROPERTY_ID(OBJ, FLAG_EVENT_TRICKLE, LV_PROPERTY_TYPE_INT, 22),
LV_PROPERTY_ID(OBJ, FLAG_EVENT_TRICKLE, LV_PROPERTY_TYPE_INT, 21),
LV_PROPERTY_ID(OBJ, FLAG_STATE_TRICKLE, LV_PROPERTY_TYPE_INT, 22),
LV_PROPERTY_ID(OBJ, FLAG_LAYOUT_1, LV_PROPERTY_TYPE_INT, 23),
LV_PROPERTY_ID(OBJ, FLAG_LAYOUT_2, LV_PROPERTY_TYPE_INT, 24),
LV_PROPERTY_ID(OBJ, FLAG_FLEX_IN_NEW_TRACK, LV_PROPERTY_TYPE_INT, 23), /*Mapped to FLAG_LAYOUT_1*/
LV_PROPERTY_ID(OBJ, FLAG_WIDGET_1, LV_PROPERTY_TYPE_INT, 25),
LV_PROPERTY_ID(OBJ, FLAG_WIDGET_2, LV_PROPERTY_TYPE_INT, 26),
LV_PROPERTY_ID(OBJ, FLAG_USER_1, LV_PROPERTY_TYPE_INT, 27),
@@ -118,6 +118,8 @@ void lv_xml_obj_apply(lv_xml_parser_state_t * state, const char ** attrs)
lv_xml_to_bool(value));
else if(lv_streq("event_trickle", name)) lv_obj_set_flag(item, LV_OBJ_FLAG_EVENT_TRICKLE,
lv_xml_to_bool(value));
else if(lv_streq("state_trickle", name)) lv_obj_set_flag(item, LV_OBJ_FLAG_STATE_TRICKLE,
lv_xml_to_bool(value));
else if(lv_streq("gesture_bubble", name)) lv_obj_set_flag(item, LV_OBJ_FLAG_GESTURE_BUBBLE,
lv_xml_to_bool(value));
else if(lv_streq("adv_hittest", name)) lv_obj_set_flag(item, LV_OBJ_FLAG_ADV_HITTEST,
@@ -649,6 +651,7 @@ static lv_obj_flag_t flag_to_enum(const char * txt)
if(lv_streq("press_lock", txt)) return LV_OBJ_FLAG_PRESS_LOCK;
if(lv_streq("event_bubble", txt)) return LV_OBJ_FLAG_EVENT_BUBBLE;
if(lv_streq("event_trickle", txt)) return LV_OBJ_FLAG_EVENT_TRICKLE;
if(lv_streq("state_trickle", txt)) return LV_OBJ_FLAG_STATE_TRICKLE;
if(lv_streq("gesture_bubble", txt)) return LV_OBJ_FLAG_GESTURE_BUBBLE;
if(lv_streq("adv_hittest", txt)) return LV_OBJ_FLAG_ADV_HITTEST;
if(lv_streq("ignore_layout", txt)) return LV_OBJ_FLAG_IGNORE_LAYOUT;
+2 -1
View File
@@ -14,7 +14,7 @@
* Generated code from properties.py
*/
/* *INDENT-OFF* */
const lv_property_name_t lv_obj_property_names[74] = {
const lv_property_name_t lv_obj_property_names[75] = {
{"align", LV_PROPERTY_OBJ_ALIGN,},
{"child_count", LV_PROPERTY_OBJ_CHILD_COUNT,},
{"content_height", LV_PROPERTY_OBJ_CONTENT_HEIGHT,},
@@ -49,6 +49,7 @@ const lv_property_name_t lv_obj_property_names[74] = {
{"flag_send_draw_task_events", LV_PROPERTY_OBJ_FLAG_SEND_DRAW_TASK_EVENTS,},
{"flag_snappable", LV_PROPERTY_OBJ_FLAG_SNAPPABLE,},
{"flag_start", LV_PROPERTY_OBJ_FLAG_START,},
{"flag_state_trickle", LV_PROPERTY_OBJ_FLAG_STATE_TRICKLE,},
{"flag_user_1", LV_PROPERTY_OBJ_FLAG_USER_1,},
{"flag_user_2", LV_PROPERTY_OBJ_FLAG_USER_2,},
{"flag_user_3", LV_PROPERTY_OBJ_FLAG_USER_3,},
+1 -1
View File
@@ -15,7 +15,7 @@
extern const lv_property_name_t lv_image_property_names[11];
extern const lv_property_name_t lv_keyboard_property_names[4];
extern const lv_property_name_t lv_label_property_names[4];
extern const lv_property_name_t lv_obj_property_names[74];
extern const lv_property_name_t lv_obj_property_names[75];
extern const lv_property_name_t lv_roller_property_names[3];
extern const lv_property_name_t lv_slider_property_names[8];
extern const lv_property_name_t lv_style_property_names[120];
+1
View File
@@ -344,6 +344,7 @@ Example
<prop name="press_lock" type="flag:flag lv_obj_flag"/>
<prop name="event_bubble" type="flag:flag lv_obj_flag"/>
<prop name="event_trickle" type="flag:flag lv_obj_flag"/>
<prop name="state_trickle" type="flag:flag lv_obj_flag"/>
<prop name="gesture_bubble" type="flag:flag lv_obj_flag"/>
<prop name="adv_hittest" type="flag:flag lv_obj_flag"/>
<prop name="ignore_layout" type="flag:flag lv_obj_flag"/>