mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
refactor(event) simplify cover check realted event functions
This commit is contained in:
parent
b7f875aba6
commit
94a47dc6d9
@ -177,37 +177,25 @@ Finish the drawing of a part. It's a good place to draw extra content on the par
|
||||
|
||||
This event is used to check whether an object fully covers an area or not.
|
||||
|
||||
`lv_event_get_cover_check_info(event)` returns an pointer to an `lv_cover_check_info_t` variable. Its `res` field should be set to the following values considering the `area` field:
|
||||
- `LV_DRAW_RES_COVER` the areas is fully covered by the object
|
||||
- `LV_DRAW_RES_NOT_COVER` the areas is not covered by the object
|
||||
- `LV_DRAW_RES_MASKED` there is a mask on the object so it can not covert the area
|
||||
`lv_event_get_cover_area(event)` returns an pointer to an area to check and `lv_event_set_cover_res(event, res)` can be used to set one of these results:
|
||||
- `LV_COVER_RES_COVER` the areas is fully covered by the object
|
||||
- `LV_COVER_RES_NOT_COVER` the areas is not covered by the object
|
||||
- `LV_COVER_RES_MASKED` there is a mask on the object so it can not covert the area
|
||||
|
||||
Here are some cases why can't an object fully cover an area:
|
||||
- It's simply not fully on the that area
|
||||
- It has radius
|
||||
- It has not 100% background opacity
|
||||
- It's an ARGB or chroma keyed image
|
||||
- It's a text
|
||||
- It has not normal blending mode. In this case LVGL needs to know the colors under the object to make the blending properly
|
||||
- It's a text, etc
|
||||
|
||||
In short if for any reason the the area below the object is visible than it doesn't cover that area.
|
||||
|
||||
Some guideline how to set the `res` field in `lv_cover_check_info_t`:
|
||||
- Before sending this event LVGL checks if at least the widget's coordinates fully cover the area or not. If not the event is not called.
|
||||
- You need to check only the drawing you have added. The existing properties known by widget are handled in the widget's internal events.
|
||||
Before sending this event LVGL checks if at least the widget's coordinates fully cover the area or not. If not the event is not called.
|
||||
|
||||
You need to check only the drawing you have added. The existing properties known by widget are handled in the widget's internal events.
|
||||
E.g. if a widget has > 0 radius it might not cover an area but you need to handle `radius` only if you will modify it and widget can't know about it.
|
||||
- If `res` is already set to `LV_DRAW_RES_MASKED` do nothing. In this case an other event already set it and it's the "strongest" state that shouldn't be overwritten.
|
||||
- If you added a draw mask on the object set `res` to `LV_DRAW_RES_MASKED`
|
||||
- If there is no draw masks but the object simply not covers the area for any reason set `LV_DRAW_RES_NOT_COVER`
|
||||
- If the area is fully covered by the object leave `res` unchanged.
|
||||
|
||||
In the practice probably you need to set only `LV_DRAW_RES_MASKED`if you added masks in a MAIN or POST draw events because "normal" cover checks are handles by the widgets.
|
||||
|
||||
However, if you really added masks in MAIN or POST draw events you need to handle `LV_EVENT_COVER_CHECK` event and tell LVGL there are masks on this object.
|
||||
|
||||
If masks are added and removed in `LV_EVENT_DRAW_PART_BEGIN/END`, `LV_EVENT_COVER_CHECK` doesn't need to know about it except the masks affects `LV_PART_MAIN`.
|
||||
It's because LVGL checks the main part to decide whether an object covers an area or not.
|
||||
So it doesn't matter e.g. if a tabel's cell is masked because the tables background already covered the area or not.
|
||||
|
||||
#### LV_EVENT_REFR_EXT_DRAW_SIZE
|
||||
|
||||
|
@ -319,13 +319,25 @@ lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e)
|
||||
}
|
||||
}
|
||||
|
||||
lv_cover_check_info_t * lv_event_get_cover_check_info(lv_event_t * e)
|
||||
const lv_area_t * lv_event_get_cover_area(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_COVER_CHECK) {
|
||||
return lv_event_get_param(e);
|
||||
lv_cover_check_info_t * p = lv_event_get_param(e);
|
||||
return p->area;
|
||||
} else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res)
|
||||
{
|
||||
if(e->code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * p = lv_event_get_param(e);
|
||||
if(p->res == LV_COVER_RES_MASKED) return; /*Do not overwrite masked result*/
|
||||
if(res == LV_COVER_RES_NOT_COVER) p->res = res;
|
||||
} else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,15 +113,12 @@ typedef struct {
|
||||
|
||||
/**
|
||||
* Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not.
|
||||
* `res` should be set like this:
|
||||
* - If already set to ::LV_DRAW_RES_MASKED do nothing
|
||||
* - If there is a draw mask on the object set to ::LV_DRAW_RES_MASKED
|
||||
* - If there is no draw mask but the object simply not covers the area set ::LV_DRAW_RES_NOT_COVER
|
||||
* - If the area is fully covered by the object leave `res` unchanged.
|
||||
* In the event use `const lv_area_t * area = lv_event_get_cover_area(e)` to get the area to check
|
||||
* and `lv_event_set_cover_res(e, res)` to set the result.
|
||||
*/
|
||||
typedef struct {
|
||||
lv_draw_res_t res; /**< Set to ::LV_DRAW_RES_NOT_COVER or ::LV_DRAW_RES_MASKED. */
|
||||
const lv_area_t * area; /**< The area to check */
|
||||
lv_cover_res_t res;
|
||||
const lv_area_t * area;
|
||||
} lv_cover_check_info_t;
|
||||
|
||||
/**********************
|
||||
@ -290,12 +287,19 @@ lv_point_t * lv_event_get_self_size_info(lv_event_t * e);
|
||||
lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get a pointer to an `lv_cover_check_info_t` variable in which the area cover information should be saved.
|
||||
* Can be used in `LV_EVENT_COVER_CHECK`
|
||||
* Get a pointer to an area which should be examined whether the object fully covers it or not.
|
||||
* Can be used in `LV_EVENT_HIT_TEST`
|
||||
* @param e pointer to an event
|
||||
* @return pointer to `lv_cover_check_info_t` or NULL if called on an unrelated event
|
||||
* @return an area with absolute coordinates to check
|
||||
*/
|
||||
lv_cover_check_info_t * lv_event_get_cover_check_info(lv_event_t * e);
|
||||
const lv_area_t * lv_event_get_cover_area(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Set the result of cover checking. Can be used in `LV_EVENT_COVER_CHECK`
|
||||
* @param e pointer to an event
|
||||
* @param res an element of ::lv_cover_check_info_t
|
||||
*/
|
||||
void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
@ -454,9 +454,9 @@ static void lv_obj_draw(lv_event_t * e)
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
if(code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * info = lv_event_get_param(e);
|
||||
if(info->res == LV_DRAW_RES_MASKED) return;
|
||||
if(info->res == LV_COVER_RES_MASKED) return;
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
info->res = LV_DRAW_RES_MASKED;
|
||||
info->res = LV_COVER_RES_MASKED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -472,27 +472,27 @@ static void lv_obj_draw(lv_event_t * e)
|
||||
coords.y2 += h;
|
||||
|
||||
if(_lv_area_is_in(info->area, &coords, r) == false) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
if(lv_obj_get_style_bg_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_blend_mode(obj, LV_PART_MAIN) != LV_BLEND_MODE_NORMAL) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(lv_obj_get_style_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
info->res = LV_DRAW_RES_COVER;
|
||||
info->res = LV_COVER_RES_COVER;
|
||||
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN) {
|
||||
|
@ -25,12 +25,12 @@ extern "C" {
|
||||
|
||||
struct _lv_obj_t;
|
||||
|
||||
/** Design results*/
|
||||
/** Cover check results*/
|
||||
typedef enum {
|
||||
LV_DRAW_RES_COVER, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is fully covered*/
|
||||
LV_DRAW_RES_NOT_COVER, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is not covered*/
|
||||
LV_DRAW_RES_MASKED, /**< Returned on `LV_DRAW_COVER_CHK` if the areas is masked out*/
|
||||
}lv_draw_res_t;
|
||||
LV_COVER_RES_COVER,
|
||||
LV_COVER_RES_NOT_COVER,
|
||||
LV_COVER_RES_MASKED,
|
||||
}lv_cover_res_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -574,10 +574,10 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
|
||||
/*If this object is fully cover the draw area check the children too*/
|
||||
if(_lv_area_is_in(area_p, &obj->coords, 0) && lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN) == false) {
|
||||
lv_cover_check_info_t info;
|
||||
info.res = LV_DRAW_RES_COVER;
|
||||
info.res = LV_COVER_RES_COVER;
|
||||
info.area = area_p;
|
||||
lv_event_send(obj, LV_EVENT_COVER_CHECK, &info);
|
||||
if(info.res == LV_DRAW_RES_MASKED) return NULL;
|
||||
if(info.res == LV_COVER_RES_MASKED) return NULL;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < lv_obj_get_child_cnt(obj); i++) {
|
||||
@ -592,7 +592,7 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
|
||||
|
||||
/*If no better children use this object*/
|
||||
if(found_p == NULL) {
|
||||
if(info.res == LV_DRAW_RES_COVER) {
|
||||
if(info.res == LV_COVER_RES_COVER) {
|
||||
found_p = obj;
|
||||
}
|
||||
}
|
||||
|
@ -520,7 +520,7 @@ static void lv_colorwheel_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
}
|
||||
else if(code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * info = lv_event_get_param(e);
|
||||
if(info->res != LV_DRAW_RES_MASKED) info->res = LV_DRAW_RES_NOT_COVER;
|
||||
if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ static void lv_imgbtn_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
}
|
||||
else if(code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * info = lv_event_get_param(e);
|
||||
if(info->res != LV_DRAW_RES_MASKED) info->res = LV_DRAW_RES_NOT_COVER;
|
||||
if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,21 +490,21 @@ static void draw_img(lv_event_t * e)
|
||||
lv_img_t * img = (lv_img_t *)obj;
|
||||
if(code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * info = lv_event_get_param(e);
|
||||
if(info->res == LV_DRAW_RES_MASKED) return;
|
||||
if(info->res == LV_COVER_RES_MASKED) return;
|
||||
if(img->src_type == LV_IMG_SRC_UNKNOWN || img->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
/*Non true color format might have "holes"*/
|
||||
if(img->cf != LV_IMG_CF_TRUE_COLOR && img->cf != LV_IMG_CF_RAW) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
/*With not LV_OPA_COVER images can't cover an area */
|
||||
if(lv_obj_get_style_img_opa(obj, LV_PART_MAIN) != LV_OPA_COVER) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -512,7 +512,7 @@ static void draw_img(lv_event_t * e)
|
||||
angle_final += img->angle;
|
||||
|
||||
if(angle_final != 0) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -523,7 +523,7 @@ static void draw_img(lv_event_t * e)
|
||||
const lv_area_t * clip_area = lv_event_get_param(e);
|
||||
if(zoom_final == LV_IMG_ZOOM_NONE) {
|
||||
if(_lv_area_is_in(clip_area, &obj->coords, 0) == false) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -536,7 +536,7 @@ static void draw_img(lv_event_t * e)
|
||||
a.y2 += obj->coords.y1;
|
||||
|
||||
if(_lv_area_is_in(clip_area, &a, 0) == false) {
|
||||
info->res = LV_DRAW_RES_NOT_COVER;
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ static lv_draw_res_t lv_templ_draw(lv_obj_t * templ, const lv_area_t * clip_area
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DRAW_COVER_CHK) {
|
||||
return LV_DRAW_RES_NOT_COVER;
|
||||
return LV_COVER_RES_NOT_COVER;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DRAW_DRAW_MAIN) {
|
||||
@ -206,7 +206,7 @@ static lv_draw_res_t lv_templ_draw(lv_obj_t * templ, const lv_area_t * clip_area
|
||||
else if(mode == LV_DRAW_DRAW_POST) {
|
||||
}
|
||||
|
||||
return LV_DRAW_RES_OK;
|
||||
return LV_COVER_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user