feat(property): add style selector support for property API (#6275)

Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
Neo Xu 2024-05-31 10:49:19 +08:00 committed by GitHub
parent 2d4dd3ba1b
commit 71df208074
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 121 additions and 31 deletions

View File

@ -24,7 +24,11 @@ Two APIs are provided to get/set widget properties. It can be enabled by setting
int32_t num; /**< Number integer number (opacity, enums, booleans or "normal" numbers)*/
const void * ptr; /**< Constant pointers (font, cone text, etc)*/
lv_color_t color; /**< Colors*/
lv_style_value_t _style; /**< A place holder for style value which is same as property value.*/
lv_value_precise_t precise; /**< float or int for precise value*/
struct {
lv_style_value_t style; /**< Make sure it's the first element in struct. */
uint32_t selector; /**< Style selector, lv_part_t | lv_state_t */
};
};
} lv_property_t;

View File

@ -53,12 +53,12 @@ lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value)
LV_ASSERT(obj && value);
if(value->id == LV_PROPERTY_ID_INVALID) {
LV_LOG_WARN("invalid property id set to %p\n", obj);
LV_LOG_WARN("Invalid property id set to %p", obj);
return LV_RESULT_INVALID;
}
if(value->id < LV_PROPERTY_ID_START) {
lv_obj_set_local_style_prop(obj, value->id, value->_style, 0);
lv_obj_set_local_style_prop(obj, value->id, value->style, value->selector);
return LV_RESULT_OK;
}
@ -83,25 +83,43 @@ lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id)
lv_property_t value;
if(id == LV_PROPERTY_ID_INVALID) {
LV_LOG_WARN("invalid property id to get from %p\n", obj);
value.id = 0;
LV_LOG_WARN("Invalid property id to get from %p", obj);
value.id = LV_PROPERTY_ID_INVALID;
value.num = 0;
return value;
}
if(id < LV_PROPERTY_ID_START) {
lv_obj_get_local_style_prop(obj, id, &value._style, 0);
lv_obj_get_local_style_prop(obj, id, &value.style, 0);
value.id = id;
value.selector = 0;
return value;
}
result = obj_property(obj, id, &value, false);
if(result != LV_RESULT_OK)
value.id = 0;
value.id = LV_PROPERTY_ID_INVALID;
return value;
}
lv_property_t lv_obj_get_style_property(lv_obj_t * obj, lv_prop_id_t id, uint32_t selector)
{
lv_property_t value;
if(id == LV_PROPERTY_ID_INVALID || id >= LV_PROPERTY_ID_START) {
LV_LOG_WARN("invalid style property id %d", id);
value.id = LV_PROPERTY_ID_INVALID;
value.num = 0;
return value;
}
lv_obj_get_local_style_prop(obj, id, &value.style, selector);
value.id = id;
value.selector = selector;
return value;
}
static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t * value, bool set)
{
const lv_property_ops_t * properties;
@ -139,7 +157,7 @@ static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t *
/*id matched but we got null pointer to functions*/
if(set ? prop->setter == NULL : prop->getter == NULL) {
LV_LOG_WARN("null %s provided, id: %d\n", set ? "setter" : "getter", id);
LV_LOG_WARN("NULL %s provided, id: %d", set ? "setter" : "getter", id);
return LV_RESULT_INVALID;
}
@ -161,7 +179,7 @@ static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t *
else value->color = ((lv_property_get_color_t)(prop->getter))(obj);
break;
default:
LV_LOG_WARN("unknown property id: 0x%08x\n", prop->id);
LV_LOG_WARN("Unknown property id: 0x%08x", prop->id);
return LV_RESULT_INVALID;
break;
}
@ -172,7 +190,7 @@ static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t *
/*If no setter found, try base class then*/
}
LV_LOG_WARN("unknown property id: 0x%08x\n", id);
LV_LOG_WARN("Unknown property id: 0x%08x", id);
return LV_RESULT_INVALID;
}

View File

@ -30,10 +30,6 @@ extern "C" {
#define LV_PROPERTY_TYPE_POINTER 4 /*void * pointer*/
#define LV_PROPERTY_TYPE_IMGSRC 5 /*Special pointer for image*/
/**********************
* TYPEDEFS
**********************/
#define LV_PROPERTY_ID(clz, name, type, index) LV_PROPERTY_## clz ##_##name = (LV_PROPERTY_## clz ##_START + (index)) | ((type) << 28)
#define LV_PROPERTY_ID_TYPE(id) ((id) >> 28)
@ -42,6 +38,10 @@ extern "C" {
/*Set properties from an array of lv_property_t*/
#define LV_OBJ_SET_PROPERTY_ARRAY(obj, array) lv_obj_set_properties(obj, array, sizeof(array)/sizeof(array[0]))
/**********************
* TYPEDEFS
**********************/
/**
* Group of predefined widget ID start value.
*/
@ -51,16 +51,15 @@ enum {
/*ID 0 to 0xff are style ID, check lv_style_prop_t*/
LV_PROPERTY_ID_START = 0x100, /*ID little than 0xff is style ID*/
/* lv_obj.c */
LV_PROPERTY_OBJ_START = 1000,
/*Define the property ID for every widget here. */
LV_PROPERTY_OBJ_START = 0x100, /* lv_obj.c */
LV_PROPERTY_IMAGE_START = 0x200, /* lv_image.c */
/* lv_image.c */
LV_PROPERTY_IMAGE_START = 1100,
/*Special ID, use it to extend ID and make sure it's unique and compile time determinant*/
LV_PROPERTY_ID_BUILTIN_LAST = 0x10000000,
/*Special ID*/
LV_PROPERTY_ID_BUILTIN_LAST, /*Use it to extend ID and make sure it's unique and compile time determinant*/
LV_PROPERTY_ID_ANY = 0x7ffffffe, /*Special ID used by lvgl to intercept all setter/getter call.*/
/*Special ID used by lvgl to intercept all setter/getter call.*/
LV_PROPERTY_ID_ANY = 0x7ffffffe,
};
typedef uint32_t lv_prop_id_t;
@ -72,7 +71,30 @@ typedef struct {
const void * ptr; /**< Constant pointers (font, cone text, etc)*/
lv_color_t color; /**< Colors*/
lv_value_precise_t precise; /**< float or int for precise value*/
lv_style_value_t _style; /**< A place holder for style value which is same as property value.*/
struct {
/**
* Note that place struct member `style` at first place is intended.
* `style` shares same memory with `num`, `ptr`, `color`.
* So we set the style value directly without using `prop.style.num`.
*
* E.g.
*
* static const lv_property_t obj_pos_x = {
* .id = LV_STYLE_X,
* .num = 123,
* .selector = LV_STATE_PRESSED,
* }
*
* instead of:
* static const lv_property_t obj_pos_x = {
* .id = LV_STYLE_X,
* .style.num = 123, // note this line.
* .selector = LV_STATE_PRESSED,
* }
*/
lv_style_value_t style; /**< Make sure it's the first element in struct. */
uint32_t selector; /**< Style selector, lv_part_t | lv_state_t */
};
};
} lv_property_t;
@ -92,14 +114,20 @@ typedef struct {
*====================*/
/**
* Set widget property value.
* Set widget property.
* @param obj pointer to an object
* @param id ID of which property
* @param value The property value to set
* @return return LV_RESULT_OK if success
*/
lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value);
/**
* Set multiple widget properties. Helper `LV_OBJ_SET_PROPERTY_ARRAY` can be used for constant property array.
* @param obj pointer to an object
* @param value The property value array to set
* @param count The count of the property value array
* @return return LV_RESULT_OK if success
*/
lv_result_t lv_obj_set_properties(lv_obj_t * obj, const lv_property_t * value, uint32_t count);
/*=====================
@ -107,14 +135,24 @@ lv_result_t lv_obj_set_properties(lv_obj_t * obj, const lv_property_t * value, u
*====================*/
/**
* Read property value from object
* Read property value from object.
* If id is a style property, the style selector is default to 0.
* @param obj pointer to an object
* @param id ID of which property
* @param id ID of which property to read
* @param value pointer to a buffer to store the value
* @return ? to be discussed, LV_RESULT_OK or LV_RESULT_INVALID
* @return return the property value read. The returned property ID is set to `LV_PROPERTY_ID_INVALID` if failed.
*/
lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id);
/**
* Read a style property value from object
* @param obj pointer to an object
* @param id ID of style property
* @param selector selector for the style property.
* @return return the property value read. The returned property ID is set to `LV_PROPERTY_ID_INVALID` if failed.
*/
lv_property_t lv_obj_get_style_property(lv_obj_t * obj, lv_prop_id_t id, uint32_t selector);
/**********************
* MACROS
**********************/

View File

@ -90,6 +90,7 @@ set(LVGL_TEST_OPTIONS_TEST_SYSHEAP
set(LVGL_TEST_OPTIONS_TEST_DEFHEAP
-DLV_TEST_OPTION=5
-DLV_USE_OBJ_PROPERTY=1 # add obj property test and disable pedantic
-DLVGL_CI_USING_DEF_HEAP
-fsanitize=address
-fsanitize=leak
@ -194,6 +195,12 @@ list(APPEND COMPILE_OPTIONS
${BUILD_TARGET_DEF}
)
# LV_USE_OBJ_PROPERTY is enabled in option OPTIONS_TEST_DEFHEAP
# It relies on C11 anonymous struct/union support, thus disable warnings.
if(OPTIONS_TEST_DEFHEAP)
list(REMOVE_ITEM COMPILE_OPTIONS -pedantic-errors -Wpedantic)
endif()
filter_compiler_options(C LVGL_C_COMPILE_OPTIONS ${COMPILE_OPTIONS})
if(NOT (CMAKE_C_COMPILER_ID STREQUAL "MSVC"))

View File

@ -110,7 +110,6 @@
#define LV_USE_OBJ_ID 1
#define LV_USE_OBJ_ID_BUILTIN 1
#define LV_USE_OBJ_PROPERTY 0
#define LV_CACHE_DEF_SIZE (10 * 1024 * 1024)

View File

@ -94,6 +94,30 @@ void test_obj_property_set_get_should_match(void)
#endif
}
void test_obj_property_style_selector(void)
{
#if LV_USE_OBJ_PROPERTY
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_property_t prop = { };
/* Style property with default selector(0) should work */
prop.id = LV_STYLE_X;
prop.num = 0xaabb; /* `num` shares same memory with `prop.style.value.num` */
/* selector is initialed to zero when prop is defined. */
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_UINT32(0xaabb, lv_obj_get_style_x(obj, 0));
TEST_ASSERT_EQUAL_UINT32(0xaabb, lv_obj_get_style_property(obj, LV_STYLE_X, 0).num);
lv_style_selector_t selector = LV_PART_MAIN | LV_STATE_PRESSED;
prop.id = LV_STYLE_X;
prop.num = 0x1122;
prop.selector = selector;
TEST_ASSERT_TRUE(lv_obj_set_property(obj, &prop) == LV_RESULT_OK);
TEST_ASSERT_EQUAL_UINT32(0x1122, lv_obj_get_style_x(obj, selector));
TEST_ASSERT_EQUAL_UINT32(0x1122, lv_obj_get_style_property(obj, LV_STYLE_X, selector).num);
#endif
}
void test_obj_property_flag(void)
{
#if LV_USE_OBJ_PROPERTY