mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-23 17:53:45 +08:00
feat(property): add style selector support for property API (#6275)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
parent
2d4dd3ba1b
commit
71df208074
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
**********************/
|
||||
|
@ -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"))
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user