1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

feat(style): add API to check specific style property is set (#5055)

Signed-off-by: yushuailong1 <yushuailong1@xiaomi.com>
Co-authored-by: yushuailong1 <yushuailong1@xiaomi.com>
This commit is contained in:
yushuailong 2024-01-02 15:43:47 +08:00 committed by GitHub
parent 6d57d71f41
commit 95e40c4652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 128 additions and 62 deletions

View File

@ -50,7 +50,8 @@ typedef enum {
**********************/
static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector);
static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part);
static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v);
static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop,
lv_style_value_t * v);
static void report_style_change_core(void * style, lv_obj_t * obj);
static void refresh_children_style(lv_obj_t * obj);
static bool trans_delete(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit);
@ -62,6 +63,8 @@ static void full_cache_refresh(lv_obj_t * obj, lv_part_t part);
static void fade_anim_cb(void * obj, int32_t v);
static void fade_in_anim_ready(lv_anim_t * a);
static bool style_has_flag(const lv_style_t * style, uint32_t flag);
static lv_style_res_t get_selector_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop,
lv_style_value_t * value_act);
/**********************
* STATIC VARIABLES
@ -390,72 +393,29 @@ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_
{
LV_ASSERT_NULL(obj)
lv_style_selector_t selector = part | obj->state;
lv_style_value_t value_act = { .ptr = NULL };
lv_style_res_t found;
/*The happy path*/
#if LV_OBJ_STYLE_CACHE
const uint32_t prop_shifted = STYLE_PROP_SHIFTED(prop);
if((part == LV_PART_MAIN ? obj->style_main_prop_is_set : obj->style_other_prop_is_set) & prop_shifted)
#endif
{
found = get_prop_core(obj, part, prop, &value_act);
found = get_selector_style_prop(obj, selector, prop, &value_act);
if(found == LV_STYLE_RES_FOUND) return value_act;
}
extern const uint8_t _lv_style_builtin_prop_flag_lookup_table[];
bool inheritable = false;
if(prop < _LV_STYLE_NUM_BUILT_IN_PROPS) {
inheritable = _lv_style_builtin_prop_flag_lookup_table[prop] & LV_STYLE_PROP_FLAG_INHERITABLE;
}
else {
if(_style_custom_prop_flag_lookup_table != NULL) {
inheritable = _style_custom_prop_flag_lookup_table[prop - _LV_STYLE_NUM_BUILT_IN_PROPS] &
LV_STYLE_PROP_FLAG_INHERITABLE;
}
}
if(inheritable) {
/*If not found, check the `MAIN` style first, if already on the MAIN part go to the parent*/
if(part != LV_PART_MAIN) part = LV_PART_MAIN;
else obj = obj->parent;
while(obj) {
#if LV_OBJ_STYLE_CACHE
if(obj->style_main_prop_is_set & prop_shifted)
#endif
{
found = get_prop_core(obj, part, prop, &value_act);
if(found == LV_STYLE_RES_FOUND) return value_act;
}
/*Check the parent too.*/
obj = obj->parent;
}
}
else {
/*Get the width and height from the class.
* WIDTH and HEIGHT are not inherited so add them in the `else` to skip checking them for inherited properties */
if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) {
const lv_obj_class_t * cls = obj->class_p;
while(cls) {
if(prop == LV_STYLE_WIDTH) {
if(cls->width_def != 0) return (lv_style_value_t) {
.num = cls->width_def
};
}
else {
if(cls->height_def != 0) return (lv_style_value_t) {
.num = cls->height_def
};
}
cls = cls->base_class;
}
}
}
return lv_style_prop_get_default_inlined(prop);
}
bool lv_obj_has_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop)
{
LV_ASSERT_NULL(obj)
lv_style_value_t value_act = { .ptr = NULL };
lv_style_res_t found;
found = get_selector_style_prop(obj, selector, prop, &value_act);
if(found == LV_STYLE_RES_FOUND) return true;
return false;
}
void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value,
lv_style_selector_t selector)
{
@ -786,11 +746,13 @@ static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, lv_style_selector_t se
return &obj->styles[0];
}
static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v)
static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop,
lv_style_value_t * v)
{
const uint32_t group = (uint32_t)1 << _lv_style_get_prop_group(prop);
const lv_state_t state = obj->state;
const lv_part_t part = lv_obj_style_get_selector_part(selector);
const lv_state_t state = lv_obj_style_get_selector_state(selector);
const lv_state_t state_inv = ~state;
const bool skip_trans = obj->skip_trans;
int32_t weight = -1;
@ -1140,3 +1102,75 @@ static bool style_has_flag(const lv_style_t * style, uint32_t flag)
}
return false;
}
static lv_style_res_t get_selector_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop,
lv_style_value_t * value_act)
{
lv_style_res_t found;
lv_part_t part = lv_obj_style_get_selector_part(selector);
/*The happy path*/
#if LV_OBJ_STYLE_CACHE
const uint32_t prop_shifted = STYLE_PROP_SHIFTED(prop);
if((part == LV_PART_MAIN ? obj->style_main_prop_is_set : obj->style_other_prop_is_set) & prop_shifted)
#endif
{
found = get_prop_core(obj, selector, prop, value_act);
if(found == LV_STYLE_RES_FOUND) return LV_STYLE_RES_FOUND;
}
extern const uint8_t _lv_style_builtin_prop_flag_lookup_table[];
bool inheritable = false;
if(prop < _LV_STYLE_NUM_BUILT_IN_PROPS) {
inheritable = _lv_style_builtin_prop_flag_lookup_table[prop] & LV_STYLE_PROP_FLAG_INHERITABLE;
}
else {
if(_style_custom_prop_flag_lookup_table != NULL) {
inheritable = _style_custom_prop_flag_lookup_table[prop - _LV_STYLE_NUM_BUILT_IN_PROPS] &
LV_STYLE_PROP_FLAG_INHERITABLE;
}
}
if(inheritable) {
/*If not found, check the `MAIN` style first, if already on the MAIN part go to the parent*/
if(part != LV_PART_MAIN) part = LV_PART_MAIN;
else obj = obj->parent;
while(obj) {
#if LV_OBJ_STYLE_CACHE
if(obj->style_main_prop_is_set & prop_shifted)
#endif
{
selector = part | obj->state;
found = get_prop_core(obj, selector, prop, value_act);
if(found == LV_STYLE_RES_FOUND) return LV_STYLE_RES_FOUND;
}
/*Check the parent too.*/
obj = obj->parent;
}
}
else {
/*Get the width and height from the class.
* WIDTH and HEIGHT are not inherited so add them in the `else` to skip checking them for inherited properties */
if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) {
const lv_obj_class_t * cls = obj->class_p;
while(cls) {
if(prop == LV_STYLE_WIDTH) {
if(cls->width_def != 0) {
value_act->num = cls->width_def;
return LV_STYLE_RES_FOUND;
}
}
else {
if(cls->height_def != 0) {
value_act->num = cls->height_def;
return LV_STYLE_RES_FOUND;
}
}
cls = cls->base_class;
}
}
}
return LV_STYLE_RES_NOT_FOUND;
}

View File

@ -155,6 +155,15 @@ void lv_obj_enable_style_refresh(bool en);
*/
lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop);
/**
* Check if an object has a specified style property for a given style selector.
* @param obj pointer to an object
* @param selector the style selector to be checked, defining the scope of the style to be examined.
* @param prop the property to be checked.
* @return true if the object has the specified selector and property, false otherwise.
*/
bool lv_obj_has_style_prop(const struct _lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop);
/**
* Set local style property on an object's part and state.
* @param obj pointer to an object

View File

@ -117,4 +117,27 @@ void test_style_replacement(void)
lv_style_reset(&style_blue);
}
void test_style_has_prop(void)
{
lv_style_t style;
lv_style_init(&style);
lv_style_set_outline_color(&style, lv_color_white());
/*Create object with style*/
lv_obj_t * obj = lv_obj_create(lv_screen_active());
TEST_ASSERT_EQUAL(false, lv_obj_has_style_prop(obj, LV_PART_MAIN, LV_STYLE_OUTLINE_COLOR));
TEST_ASSERT_EQUAL(false, lv_obj_has_style_prop(obj, LV_PART_MAIN, LV_STYLE_OUTLINE_WIDTH));
TEST_ASSERT_EQUAL(false, lv_obj_has_style_prop(obj, LV_PART_INDICATOR, LV_STYLE_OUTLINE_COLOR));
lv_obj_add_style(obj, &style, LV_PART_MAIN);
lv_obj_set_style_outline_width(obj, 2, LV_PART_MAIN);
TEST_ASSERT_EQUAL(true, lv_obj_has_style_prop(obj, LV_PART_MAIN, LV_STYLE_OUTLINE_COLOR));
TEST_ASSERT_EQUAL(true, lv_obj_has_style_prop(obj, LV_PART_MAIN, LV_STYLE_OUTLINE_WIDTH));
TEST_ASSERT_EQUAL(false, lv_obj_has_style_prop(obj, LV_PART_INDICATOR, LV_STYLE_OUTLINE_COLOR));
lv_style_reset(&style);
}
#endif