feat(obj): add LV_OBJ_FLAG_OVERFLOW_VISIBLE

This commit is contained in:
Gabor Kiss-Vamosi
2022-01-05 16:18:19 +01:00
parent 2d8476438b
commit e7ac0e4198
7 changed files with 71 additions and 53 deletions

View File

@@ -91,6 +91,9 @@ If a child is partially or fully outside of its parent then the parts outside wi
lv_obj_set_x(obj1, -30); /*Move the child a little bit off the parent*/ lv_obj_set_x(obj1, -30); /*Move the child a little bit off the parent*/
``` ```
This behavior can be overwritten with `lv_obj_add_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE);` which allow the children to be drawn out of the parent.
### Create and delete objects ### Create and delete objects
In LVGL, objects can be created and deleted dynamically at run time. It means only the currently created (existing) objects consume RAM. In LVGL, objects can be created and deleted dynamically at run time. It means only the currently created (existing) objects consume RAM.

View File

@@ -124,6 +124,7 @@ There are some attributes which can be enabled/disabled by `lv_obj_add/clear_fla
- `LV_OBJ_FLAG_ADV_HITTEST` Allow performing more accurate hit (click) test. E.g. accounting for rounded corners - `LV_OBJ_FLAG_ADV_HITTEST` Allow performing more accurate hit (click) test. E.g. accounting for rounded corners
- `LV_OBJ_FLAG_IGNORE_LAYOUT` Make the object positionable by the layouts - `LV_OBJ_FLAG_IGNORE_LAYOUT` Make the object positionable by the layouts
- `LV_OBJ_FLAG_FLOATING` Do not scroll the object when the parent scrolls and ignore layout - `LV_OBJ_FLAG_FLOATING` Do not scroll the object when the parent scrolls and ignore layout
- `LV_OBJ_FLAG_OVERFLOW_VISIBLE` Do not clip the children's content to the parent's boundary
- `LV_OBJ_FLAG_LAYOUT_1` Custom flag, free to use by layouts - `LV_OBJ_FLAG_LAYOUT_1` Custom flag, free to use by layouts
- `LV_OBJ_FLAG_LAYOUT_2` Custom flag, free to use by layouts - `LV_OBJ_FLAG_LAYOUT_2` Custom flag, free to use by layouts

View File

@@ -290,32 +290,27 @@ lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point)
{ {
lv_obj_t * found_p = NULL; lv_obj_t * found_p = NULL;
/*If the point is on this object check its children too*/ /*If this obj is hidden the children are hidden too so return immediately*/
if(lv_obj_hit_test(obj, point)) { if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL;
bool hit_test_ok = lv_obj_hit_test(obj, point);
/*If the point is on this object or has overflow visible check its children too*/
if(_lv_area_is_point_on(&obj->coords, point, 0) || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
int32_t i; int32_t i;
uint32_t child_cnt = lv_obj_get_child_cnt(obj); uint32_t child_cnt = lv_obj_get_child_cnt(obj);
/*If a child matches use it*/
for(i = child_cnt - 1; i >= 0; i--) { for(i = child_cnt - 1; i >= 0; i--) {
lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_t * child = obj->spec_attr->children[i];
found_p = lv_indev_search_obj(child, point); found_p = lv_indev_search_obj(child, point);
if(found_p) return found_p;
/*If a child was found then break*/
if(found_p != NULL) break;
}
/*If then the children was not ok, and this obj is clickable
* and it or its parent is not hidden then save this object*/
if(found_p == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CLICKABLE)) {
lv_obj_t * hidden_i = obj;
while(hidden_i != NULL) {
if(lv_obj_has_flag(hidden_i, LV_OBJ_FLAG_HIDDEN) == true) break;
hidden_i = lv_obj_get_parent(hidden_i);
}
/*No parent found with hidden == true*/
if(hidden_i == NULL && (lv_obj_get_state(obj) & LV_STATE_DISABLED) == false) found_p = obj;
} }
} }
return found_p; /*If not return earlier for a clicked child and this obj's hittest was ok use it
*else return NULL*/
if(hit_test_ok) return obj;
else return NULL;
} }
/********************** /**********************

View File

@@ -106,6 +106,7 @@ enum {
LV_OBJ_FLAG_ADV_HITTEST = (1L << 16), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/ LV_OBJ_FLAG_ADV_HITTEST = (1L << 16), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/
LV_OBJ_FLAG_IGNORE_LAYOUT = (1L << 17), /**< Make the object position-able by the layouts*/ LV_OBJ_FLAG_IGNORE_LAYOUT = (1L << 17), /**< Make the object position-able by the layouts*/
LV_OBJ_FLAG_FLOATING = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/ LV_OBJ_FLAG_FLOATING = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/
LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 19), /**< Do not clip the children's content to the parent's boundary*/
LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/ LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/
LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/ LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/

View File

@@ -807,6 +807,12 @@ void lv_obj_invalidate(const lv_obj_t * obj)
{ {
LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_OBJ(obj, MY_CLASS);
/*If the object has overflow visible it can be drawn anywhere on its parent
*It needs to be checked recursively*/
while(lv_obj_get_parent(obj) && lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
obj = lv_obj_get_parent(obj);
}
/*Truncate the area to the object*/ /*Truncate the area to the object*/
lv_area_t obj_coords; lv_area_t obj_coords;
lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj);
@@ -824,7 +830,7 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area)
{ {
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return false; if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return false;
/*Invalidate the object only if it belongs to the current or previous'*/ /*Invalidate the object only if it belongs to the current or previous or one of the layers'*/
lv_obj_t * obj_scr = lv_obj_get_screen(obj); lv_obj_t * obj_scr = lv_obj_get_screen(obj);
lv_disp_t * disp = lv_obj_get_disp(obj_scr); lv_disp_t * disp = lv_obj_get_disp(obj_scr);
if(obj_scr != lv_disp_get_scr_act(disp) && if(obj_scr != lv_disp_get_scr_act(disp) &&
@@ -835,6 +841,7 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area)
} }
/*Truncate the area to the object*/ /*Truncate the area to the object*/
if(!lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
lv_area_t obj_coords; lv_area_t obj_coords;
lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj);
lv_area_copy(&obj_coords, &obj->coords); lv_area_copy(&obj_coords, &obj->coords);
@@ -843,18 +850,20 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area)
obj_coords.x2 += ext_size; obj_coords.x2 += ext_size;
obj_coords.y2 += ext_size; obj_coords.y2 += ext_size;
bool is_common; /*The area is not on the object*/
if(!_lv_area_intersect(area, area, &obj_coords)) return false;
is_common = _lv_area_intersect(area, area, &obj_coords); }
if(is_common == false) return false; /*The area is not on the object*/
/*Truncate recursively to the parents*/ /*Truncate recursively to the parents*/
lv_obj_t * par = lv_obj_get_parent(obj); lv_obj_t * par = lv_obj_get_parent(obj);
while(par != NULL) { while(par != NULL) {
is_common = _lv_area_intersect(area, area, &par->coords); /*If the parent is hidden then the child is hidden and won't be drawn*/
if(is_common == false) return false; /*If no common parts with parent break;*/ if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return false;
if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return
false; /*If the parent is hidden then the child is hidden and won't be drawn*/ /*Truncate to the parent and if no common parts break*/
if(!lv_obj_has_flag(par, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
if(!_lv_area_intersect(area, area, &par->coords)) return false;
}
par = lv_obj_get_parent(par); par = lv_obj_get_parent(par);
} }
@@ -899,6 +908,9 @@ void lv_obj_get_click_area(const lv_obj_t * obj, lv_area_t * area)
bool lv_obj_hit_test(lv_obj_t * obj, const lv_point_t * point) bool lv_obj_hit_test(lv_obj_t * obj, const lv_point_t * point)
{ {
if(!lv_obj_has_flag(obj, LV_OBJ_FLAG_CLICKABLE)) return false;
if(lv_obj_has_state(obj, LV_STATE_DISABLED)) return false;
lv_area_t a; lv_area_t a;
lv_obj_get_click_area(obj, &a); lv_obj_get_click_area(obj, &a);
bool res = _lv_area_is_point_on(&a, point, 0); bool res = _lv_area_is_point_on(&a, point, 0);

View File

@@ -130,16 +130,18 @@ void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj)
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return; if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return;
const lv_area_t * clip_area_ori = draw_ctx->clip_area; const lv_area_t * clip_area_ori = draw_ctx->clip_area;
lv_area_t clip_coords_for_obj;
/*Truncate the clip area to `obj size + ext size` area*/
lv_area_t obj_coords_ext; lv_area_t obj_coords_ext;
lv_area_t obj_ext_clip_coords;
lv_obj_get_coords(obj, &obj_coords_ext); lv_obj_get_coords(obj, &obj_coords_ext);
lv_coord_t ext_draw_size = _lv_obj_get_ext_draw_size(obj); lv_coord_t ext_draw_size = _lv_obj_get_ext_draw_size(obj);
lv_area_increase(&obj_coords_ext, ext_draw_size, ext_draw_size); lv_area_increase(&obj_coords_ext, ext_draw_size, ext_draw_size);
if(!_lv_area_intersect(&obj_ext_clip_coords, clip_area_ori, &obj_coords_ext)) return; if(!_lv_area_intersect(&clip_coords_for_obj, clip_area_ori, &obj_coords_ext)) return;
draw_ctx->clip_area = &obj_ext_clip_coords; draw_ctx->clip_area = &clip_coords_for_obj;
/*Redraw the object*/ /*Draw the object*/
lv_event_send(obj, LV_EVENT_DRAW_MAIN_BEGIN, draw_ctx); lv_event_send(obj, LV_EVENT_DRAW_MAIN_BEGIN, draw_ctx);
lv_event_send(obj, LV_EVENT_DRAW_MAIN, draw_ctx); lv_event_send(obj, LV_EVENT_DRAW_MAIN, draw_ctx);
lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, draw_ctx); lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, draw_ctx);
@@ -156,27 +158,29 @@ void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj)
lv_draw_rect(&obj_ext_mask, &obj_ext_mask, &draw_dsc); lv_draw_rect(&obj_ext_mask, &obj_ext_mask, &draw_dsc);
#endif #endif
/*Create a new 'obj_clip' without 'ext_size' because the children can't be visible there*/ /*With overflow visible keep the previous clip area to let the children visible out of this object too
lv_area_t obj_clip_coords; *With not overflow visible limit the clip are to the object's coordinates to clip the children*/
if(_lv_area_intersect(&obj_clip_coords, clip_area_ori, &obj->coords)) { bool refr_children = true;
lv_area_t clip_coords_for_children;
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
clip_coords_for_children = *clip_area_ori;
}
else {
if(!_lv_area_intersect(&clip_coords_for_children, clip_area_ori, &obj->coords)) {
refr_children = false;
}
}
if(refr_children) {
uint32_t i; uint32_t i;
uint32_t child_cnt = lv_obj_get_child_cnt(obj); uint32_t child_cnt = lv_obj_get_child_cnt(obj);
for(i = 0; i < child_cnt; i++) { for(i = 0; i < child_cnt; i++) {
lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_t * child = obj->spec_attr->children[i];
lv_area_t child_coords;
lv_obj_get_coords(child, &child_coords);
ext_draw_size = _lv_obj_get_ext_draw_size(child);
lv_area_increase(&child_coords, ext_draw_size, ext_draw_size);
lv_area_t child_clip;
if(_lv_area_intersect(&child_clip, &obj_clip_coords, &child_coords)) {
/*Refresh the next child*/
draw_ctx->clip_area = &child_clip;
lv_refr_obj(draw_ctx, child); lv_refr_obj(draw_ctx, child);
} }
} }
}
draw_ctx->clip_area = &obj_ext_clip_coords; draw_ctx->clip_area = &clip_coords_for_obj;
/*If all the children are redrawn make 'post draw' draw*/ /*If all the children are redrawn make 'post draw' draw*/
lv_event_send(obj, LV_EVENT_DRAW_POST_BEGIN, draw_ctx); lv_event_send(obj, LV_EVENT_DRAW_POST_BEGIN, draw_ctx);
@@ -664,7 +668,7 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
{ {
lv_obj_t * found_p = NULL; lv_obj_t * found_p = NULL;
/*If this object is fully cover the draw area check the children too*/ /*If this object is fully cover the draw area then check the children too*/
if(_lv_area_is_in(area_p, &obj->coords, 0) && lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN) == false) { 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; lv_cover_check_info_t info;
info.res = LV_COVER_RES_COVER; info.res = LV_COVER_RES_COVER;

View File

@@ -89,6 +89,8 @@ void lv_obj_set_tile(lv_obj_t * obj, lv_obj_t * tile_obj, lv_anim_enable_t anim_
void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en) void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en)
{ {
lv_obj_update_layout(tv);
lv_coord_t w = lv_obj_get_content_width(tv); lv_coord_t w = lv_obj_get_content_width(tv);
lv_coord_t h = lv_obj_get_content_height(tv); lv_coord_t h = lv_obj_get_content_height(tv);