feat(property): add style selector support for property API (#6275)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
@@ -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)*/
|
int32_t num; /**< Number integer number (opacity, enums, booleans or "normal" numbers)*/
|
||||||
const void * ptr; /**< Constant pointers (font, cone text, etc)*/
|
const void * ptr; /**< Constant pointers (font, cone text, etc)*/
|
||||||
lv_color_t color; /**< Colors*/
|
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;
|
} lv_property_t;
|
||||||
|
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value)
|
|||||||
LV_ASSERT(obj && value);
|
LV_ASSERT(obj && value);
|
||||||
|
|
||||||
if(value->id == LV_PROPERTY_ID_INVALID) {
|
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;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(value->id < LV_PROPERTY_ID_START) {
|
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;
|
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;
|
lv_property_t value;
|
||||||
|
|
||||||
if(id == LV_PROPERTY_ID_INVALID) {
|
if(id == LV_PROPERTY_ID_INVALID) {
|
||||||
LV_LOG_WARN("invalid property id to get from %p\n", obj);
|
LV_LOG_WARN("Invalid property id to get from %p", obj);
|
||||||
value.id = 0;
|
value.id = LV_PROPERTY_ID_INVALID;
|
||||||
value.num = 0;
|
value.num = 0;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(id < LV_PROPERTY_ID_START) {
|
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.id = id;
|
||||||
|
value.selector = 0;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = obj_property(obj, id, &value, false);
|
result = obj_property(obj, id, &value, false);
|
||||||
if(result != LV_RESULT_OK)
|
if(result != LV_RESULT_OK)
|
||||||
value.id = 0;
|
value.id = LV_PROPERTY_ID_INVALID;
|
||||||
|
|
||||||
return value;
|
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)
|
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;
|
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*/
|
/*id matched but we got null pointer to functions*/
|
||||||
if(set ? prop->setter == NULL : prop->getter == NULL) {
|
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;
|
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);
|
else value->color = ((lv_property_get_color_t)(prop->getter))(obj);
|
||||||
break;
|
break;
|
||||||
default:
|
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;
|
return LV_RESULT_INVALID;
|
||||||
break;
|
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*/
|
/*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;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,6 @@ extern "C" {
|
|||||||
#define LV_PROPERTY_TYPE_POINTER 4 /*void * pointer*/
|
#define LV_PROPERTY_TYPE_POINTER 4 /*void * pointer*/
|
||||||
#define LV_PROPERTY_TYPE_IMGSRC 5 /*Special pointer for image*/
|
#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(clz, name, type, index) LV_PROPERTY_## clz ##_##name = (LV_PROPERTY_## clz ##_START + (index)) | ((type) << 28)
|
||||||
|
|
||||||
#define LV_PROPERTY_ID_TYPE(id) ((id) >> 28)
|
#define LV_PROPERTY_ID_TYPE(id) ((id) >> 28)
|
||||||
@@ -42,25 +38,28 @@ extern "C" {
|
|||||||
/*Set properties from an array of lv_property_t*/
|
/*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]))
|
#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.
|
* Group of predefined widget ID start value.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
LV_PROPERTY_ID_INVALID = 0,
|
LV_PROPERTY_ID_INVALID = 0,
|
||||||
|
|
||||||
/*ID 0 to 0xff are style ID, check lv_style_prop_t*/
|
/*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_PROPERTY_ID_START = 0x100, /*ID little than 0xff is style ID*/
|
||||||
|
|
||||||
/* lv_obj.c */
|
/*Define the property ID for every widget here. */
|
||||||
LV_PROPERTY_OBJ_START = 1000,
|
LV_PROPERTY_OBJ_START = 0x100, /* lv_obj.c */
|
||||||
|
LV_PROPERTY_IMAGE_START = 0x200, /* lv_image.c */
|
||||||
|
|
||||||
/* lv_image.c */
|
/*Special ID, use it to extend ID and make sure it's unique and compile time determinant*/
|
||||||
LV_PROPERTY_IMAGE_START = 1100,
|
LV_PROPERTY_ID_BUILTIN_LAST = 0x10000000,
|
||||||
|
|
||||||
/*Special ID*/
|
/*Special ID used by lvgl to intercept all setter/getter call.*/
|
||||||
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,
|
||||||
|
|
||||||
LV_PROPERTY_ID_ANY = 0x7ffffffe, /*Special ID used by lvgl to intercept all setter/getter call.*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t lv_prop_id_t;
|
typedef uint32_t lv_prop_id_t;
|
||||||
@@ -72,7 +71,30 @@ typedef struct {
|
|||||||
const void * ptr; /**< Constant pointers (font, cone text, etc)*/
|
const void * ptr; /**< Constant pointers (font, cone text, etc)*/
|
||||||
lv_color_t color; /**< Colors*/
|
lv_color_t color; /**< Colors*/
|
||||||
lv_value_precise_t precise; /**< float or int for precise value*/
|
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;
|
} lv_property_t;
|
||||||
|
|
||||||
@@ -92,14 +114,20 @@ typedef struct {
|
|||||||
*====================*/
|
*====================*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set widget property value.
|
* Set widget property.
|
||||||
* @param obj pointer to an object
|
* @param obj pointer to an object
|
||||||
* @param id ID of which property
|
|
||||||
* @param value The property value to set
|
* @param value The property value to set
|
||||||
* @return return LV_RESULT_OK if success
|
* @return return LV_RESULT_OK if success
|
||||||
*/
|
*/
|
||||||
lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value);
|
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);
|
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 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
|
* @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);
|
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
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ set(LVGL_TEST_OPTIONS_TEST_SYSHEAP
|
|||||||
|
|
||||||
set(LVGL_TEST_OPTIONS_TEST_DEFHEAP
|
set(LVGL_TEST_OPTIONS_TEST_DEFHEAP
|
||||||
-DLV_TEST_OPTION=5
|
-DLV_TEST_OPTION=5
|
||||||
|
-DLV_USE_OBJ_PROPERTY=1 # add obj property test and disable pedantic
|
||||||
-DLVGL_CI_USING_DEF_HEAP
|
-DLVGL_CI_USING_DEF_HEAP
|
||||||
-fsanitize=address
|
-fsanitize=address
|
||||||
-fsanitize=leak
|
-fsanitize=leak
|
||||||
@@ -194,6 +195,12 @@ list(APPEND COMPILE_OPTIONS
|
|||||||
${BUILD_TARGET_DEF}
|
${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})
|
filter_compiler_options(C LVGL_C_COMPILE_OPTIONS ${COMPILE_OPTIONS})
|
||||||
|
|
||||||
if(NOT (CMAKE_C_COMPILER_ID STREQUAL "MSVC"))
|
if(NOT (CMAKE_C_COMPILER_ID STREQUAL "MSVC"))
|
||||||
|
|||||||
@@ -110,7 +110,6 @@
|
|||||||
|
|
||||||
#define LV_USE_OBJ_ID 1
|
#define LV_USE_OBJ_ID 1
|
||||||
#define LV_USE_OBJ_ID_BUILTIN 1
|
#define LV_USE_OBJ_ID_BUILTIN 1
|
||||||
#define LV_USE_OBJ_PROPERTY 0
|
|
||||||
|
|
||||||
#define LV_CACHE_DEF_SIZE (10 * 1024 * 1024)
|
#define LV_CACHE_DEF_SIZE (10 * 1024 * 1024)
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,30 @@ void test_obj_property_set_get_should_match(void)
|
|||||||
#endif
|
#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)
|
void test_obj_property_flag(void)
|
||||||
{
|
{
|
||||||
#if LV_USE_OBJ_PROPERTY
|
#if LV_USE_OBJ_PROPERTY
|
||||||
|
|||||||
Reference in New Issue
Block a user