From afcf722e6fa2ef6fd1b1145394f86c7e6c1d434a Mon Sep 17 00:00:00 2001 From: Neo Xu Date: Wed, 21 Aug 2024 16:20:37 +0800 Subject: [PATCH] fix(objid): free old id before assign new one (#6697) Signed-off-by: Neo Xu --- docs/others/obj_id.rst | 1 + src/core/lv_obj.c | 8 +-- src/core/lv_obj.h | 10 ++-- src/core/lv_obj_id_builtin.c | 10 +++- src/core/lv_obj_property.c | 58 ++++++++++++++----- src/core/lv_obj_property.h | 21 ++++++- .../test_cases/widgets/test_obj_property.c | 17 ++++++ 7 files changed, 94 insertions(+), 31 deletions(-) diff --git a/docs/others/obj_id.rst b/docs/others/obj_id.rst index 4da50ffd6e..e02ed5983b 100644 --- a/docs/others/obj_id.rst +++ b/docs/others/obj_id.rst @@ -33,6 +33,7 @@ Below APIs needed to be implemented and linked to lvgl. .. code:: c + void lv_obj_set_id(lv_obj_t * obj, void * id); void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj); void lv_obj_free_id(lv_obj_t * obj); const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len); diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index b5fd51f8df..9b9f56d3fe 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -433,19 +433,13 @@ void lv_obj_null_on_delete(lv_obj_t ** obj_ptr) } #if LV_USE_OBJ_ID -void lv_obj_set_id(lv_obj_t * obj, void * id) -{ - LV_ASSERT_NULL(obj); - obj->id = id; -} - void * lv_obj_get_id(const lv_obj_t * obj) { LV_ASSERT_NULL(obj); return obj->id; } -lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, void * id) +lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, const void * id) { if(obj == NULL) obj = lv_display_get_screen_active(NULL); if(obj == NULL) return NULL; diff --git a/src/core/lv_obj.h b/src/core/lv_obj.h index 3331d7570f..56f8f26dbd 100644 --- a/src/core/lv_obj.h +++ b/src/core/lv_obj.h @@ -407,14 +407,14 @@ void * lv_obj_get_id(const lv_obj_t * obj); * @param id the id of the child object * @return pointer to the child object or NULL if not found */ -lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, void * id); +lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, const void * id); /** * Assign id to object if not previously assigned. * This function gets called automatically when LV_OBJ_ID_AUTO_ASSIGN is enabled. * * Set `LV_USE_OBJ_ID_BUILTIN` to use the builtin method to generate object ID. - * Otherwise, these functions including `lv_obj_[assign|free|stringify]_id` and + * Otherwise, these functions including `lv_obj_[set|assign|free|stringify]_id` and * `lv_obj_id_compare`should be implemented externally. * * @param class_p the class this obj belongs to. Note obj->class_p is the class currently being constructed. @@ -423,8 +423,8 @@ lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, void * id); void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj); /** - * Free resources allocated by `lv_obj_assign_id`. - * This function gets called automatically when object is deleted. + * Free resources allocated by `lv_obj_assign_id` or `lv_obj_set_id`. + * This function is also called automatically when object is deleted. * @param obj pointer to an object */ void lv_obj_free_id(lv_obj_t * obj); @@ -439,7 +439,7 @@ void lv_obj_free_id(lv_obj_t * obj); * @param id2: the second id * @return 0 if they are equal, non-zero otherwise. */ -int lv_obj_id_compare(void * id1, void * id2); +int lv_obj_id_compare(const void * id1, const void * id2); /** * Format an object's id into a string. diff --git a/src/core/lv_obj_id_builtin.c b/src/core/lv_obj_id_builtin.c index 7a0494a729..ed8f745ffa 100644 --- a/src/core/lv_obj_id_builtin.c +++ b/src/core/lv_obj_id_builtin.c @@ -79,9 +79,17 @@ void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj) obj->id = (void *)(lv_uintptr_t)id; } +void lv_obj_set_id(lv_obj_t * obj, void * id) +{ + LV_ASSERT_NULL(obj); + if(obj->id) lv_obj_free_id(obj); + obj->id = id; +} + void lv_obj_free_id(lv_obj_t * obj) { LV_UNUSED(obj); + obj->id = NULL; } const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len) @@ -106,7 +114,7 @@ void lv_objid_builtin_destroy(void) global->objid_count = 0; } -int lv_obj_id_compare(void * id1, void * id2) +int lv_obj_id_compare(const void * id1, const void * id2) { return id1 == id2 ? 0 : 1; } diff --git a/src/core/lv_obj_property.c b/src/core/lv_obj_property.c index e9bc411d04..f15ee1186b 100644 --- a/src/core/lv_obj_property.c +++ b/src/core/lv_obj_property.c @@ -133,28 +133,56 @@ lv_property_t lv_obj_get_style_property(lv_obj_t * obj, lv_prop_id_t id, uint32_ return value; } -lv_prop_id_t lv_obj_property_get_id(const lv_obj_t * obj, const char * name) +lv_prop_id_t lv_style_property_get_id(const char * name) { #if LV_USE_OBJ_PROPERTY_NAME - const lv_obj_class_t * clz; - const lv_property_name_t * names; lv_property_name_t * found; - - for(clz = obj->class_p; clz; clz = clz->base_class) { - names = clz->property_names; - if(names == NULL) { - /* try base class*/ - continue; - } - - found = lv_utils_bsearch(name, names, clz->names_count, sizeof(lv_property_name_t), property_name_compare); - if(found) return found->id; - } - /*Check style property*/ found = lv_utils_bsearch(name, lv_style_property_names, sizeof(lv_style_property_names) / sizeof(lv_property_name_t), sizeof(lv_property_name_t), property_name_compare); if(found) return found->id; +#else + LV_UNUSED(name); +#endif + return LV_PROPERTY_ID_INVALID; +} + +lv_prop_id_t lv_obj_class_property_get_id(const lv_obj_class_t * clz, const char * name) +{ +#if LV_USE_OBJ_PROPERTY_NAME + const lv_property_name_t * names; + lv_property_name_t * found; + + names = clz->property_names; + if(names == NULL) { + /* try base class*/ + return LV_PROPERTY_ID_INVALID; + } + + found = lv_utils_bsearch(name, names, clz->names_count, sizeof(lv_property_name_t), property_name_compare); + if(found) return found->id; +#else + LV_UNUSED(obj); + LV_UNUSED(name); + LV_UNUSED(property_name_compare); +#endif + return LV_PROPERTY_ID_INVALID; +} + +lv_prop_id_t lv_obj_property_get_id(const lv_obj_t * obj, const char * name) +{ +#if LV_USE_OBJ_PROPERTY_NAME + const lv_obj_class_t * clz; + lv_prop_id_t id; + + for(clz = obj->class_p; clz; clz = clz->base_class) { + id = lv_obj_class_property_get_id(clz, name); + if(id != LV_PROPERTY_ID_INVALID) return id; + } + + /*Check style property*/ + id = lv_style_property_get_id(name); + if(id != LV_PROPERTY_ID_INVALID) return id; #else LV_UNUSED(obj); LV_UNUSED(name); diff --git a/src/core/lv_obj_property.h b/src/core/lv_obj_property.h index b06278cec0..4c8c142f4d 100644 --- a/src/core/lv_obj_property.h +++ b/src/core/lv_obj_property.h @@ -98,14 +98,14 @@ typedef struct { * E.g. * * static const lv_property_t obj_pos_x = { - * .id = LV_STYLE_X, + * .id = LV_PROPERTY_STYLE_X, * .num = 123, * .selector = LV_STATE_PRESSED, * } * * instead of: * static const lv_property_t obj_pos_x = { - * .id = LV_STYLE_X, + * .id = LV_PROPERTY_STYLE_X, * .style.num = 123, // note this line. * .selector = LV_STATE_PRESSED, * } @@ -171,13 +171,28 @@ lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id); lv_property_t lv_obj_get_style_property(lv_obj_t * obj, lv_prop_id_t id, uint32_t selector); /** - * Get the property ID by name. Requires to enable `LV_USE_OBJ_PROPERTY_NAME`. + * Get the property ID by name recursively to base classes. Requires to enable `LV_USE_OBJ_PROPERTY_NAME`. * @param obj pointer to an object that has specified property or base class has. * @param name property name * @return property ID found or `LV_PROPERTY_ID_INVALID` if not found. */ lv_prop_id_t lv_obj_property_get_id(const lv_obj_t * obj, const char * name); +/** + * Get the property ID by name without check base class recursively. Requires to enable `LV_USE_OBJ_PROPERTY_NAME`. + * @param clz pointer to an object class that has specified property or base class has. + * @param name property name + * @return property ID found or `LV_PROPERTY_ID_INVALID` if not found. + */ +lv_prop_id_t lv_obj_class_property_get_id(const lv_obj_class_t * clz, const char * name); + +/** + * Get the style property ID by name. Requires to enable `LV_USE_OBJ_PROPERTY_NAME`. + * @param name property name + * @return property ID found or `LV_PROPERTY_ID_INVALID` if not found. + */ +lv_prop_id_t lv_style_property_get_id(const char * name); + /********************** * MACROS **********************/ diff --git a/tests/src/test_cases/widgets/test_obj_property.c b/tests/src/test_cases/widgets/test_obj_property.c index fa2736cec6..370ffa09e0 100644 --- a/tests/src/test_cases/widgets/test_obj_property.c +++ b/tests/src/test_cases/widgets/test_obj_property.c @@ -272,6 +272,23 @@ void test_obj_property_name(void) #endif } +void test_obj_class_property(void) +{ +#if LV_USE_OBJ_PROPERTY && LV_USE_OBJ_PROPERTY_NAME + /* An image obj has align property */ + lv_obj_t * img = lv_image_create(lv_screen_active()); + TEST_ASSERT_EQUAL_UINT32(LV_PROPERTY_OBJ_ALIGN, lv_obj_property_get_id(img, "align")); + + /* obj class has align property but image doesn't. */ + TEST_ASSERT_EQUAL_UINT32(LV_PROPERTY_OBJ_ALIGN, lv_obj_class_property_get_id(&lv_obj_class, "align")); + TEST_ASSERT_EQUAL_UINT32(LV_PROPERTY_ID_INVALID, lv_obj_class_property_get_id(&lv_image_class, "align")); + + /* style can also have property name that conflicts with obj */ + TEST_ASSERT_EQUAL_UINT32(LV_PROPERTY_STYLE_X, lv_style_property_get_id("x")); + TEST_ASSERT_EQUAL_UINT32(LV_PROPERTY_OBJ_X, lv_obj_property_get_id(img, "x")); +#endif +} + void test_label_properties(void) { #if LV_USE_OBJ_PROPERTY