feat(obj): add LV_OBJ_FLAG_OVERFLOW_VISIBLE
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
|
|||||||
@@ -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*/
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user