feat(obj): allow LV_SIZE_CONTENT for min and max width/height (#8448)

This commit is contained in:
Andy Everitt
2025-07-29 09:48:55 -03:00
committed by GitHub
parent ffaa7ccd26
commit 29ac863d14
8 changed files with 88 additions and 54 deletions
+66 -54
View File
@@ -84,6 +84,56 @@ void lv_obj_set_y(lv_obj_t * obj, int32_t y)
}
}
static int32_t calc_dynamic_width(lv_obj_t * obj, int32_t width, int32_t * const content_width)
{
if(width == LV_SIZE_CONTENT) {
if(*content_width < 0) {
*content_width = calc_content_width(obj);
}
width = *content_width;
}
else if(LV_COORD_IS_PCT(width)) {
lv_obj_t * parent = lv_obj_get_parent(obj);
if(parent->w_layout == 0 && lv_obj_get_style_width(parent, 0) == LV_SIZE_CONTENT) {
/*If parent has content size and the child has pct size
*a circular dependency will occur. To solve it keep child size at zero */
width = lv_obj_get_style_space_left(obj, 0) + lv_obj_get_style_space_right(obj, 0);
}
else {
int32_t parent_w = lv_obj_get_content_width(parent);
width = (LV_COORD_GET_PCT(width) * parent_w) / 100;
width -= lv_obj_get_style_margin_left(obj, LV_PART_MAIN) + lv_obj_get_style_margin_right(obj, LV_PART_MAIN);
}
}
return width;
}
static int32_t calc_dynamic_height(lv_obj_t * obj, int32_t height, int32_t * const content_height)
{
if(height == LV_SIZE_CONTENT) {
if(*content_height < 0) {
*content_height = calc_content_height(obj);
}
height = *content_height;
}
else if(LV_COORD_IS_PCT(height)) {
lv_obj_t * parent = lv_obj_get_parent(obj);
if(parent->h_layout == 0 && lv_obj_get_style_height(parent, 0) == LV_SIZE_CONTENT) {
/*If parent has content size and the child has pct size
*a circular dependency will occur. To solve it keep child size at zero */
height = lv_obj_get_style_space_top(obj, 0) + lv_obj_get_style_space_bottom(obj, 0);
}
else {
int32_t parent_h = lv_obj_get_content_height(parent);
height = (LV_COORD_GET_PCT(height) * parent_h) / 100;
height -=
lv_obj_get_style_margin_top(obj, LV_PART_MAIN) + lv_obj_get_style_margin_bottom(obj, LV_PART_MAIN);
}
}
return height;
}
bool lv_obj_refr_size(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
@@ -94,74 +144,34 @@ bool lv_obj_refr_size(lv_obj_t * obj)
lv_obj_t * parent = lv_obj_get_parent(obj);
if(parent == NULL) return false;
bool w_is_content = false;
bool w_is_pct = false;
int32_t w;
if(obj->w_layout) {
w = lv_obj_get_width(obj);
}
else {
w = lv_obj_get_style_width(obj, LV_PART_MAIN);
w_is_content = w == LV_SIZE_CONTENT;
w_is_pct = LV_COORD_IS_PCT(w);
int32_t parent_w = lv_obj_get_content_width(parent);
if(w_is_content) {
w = calc_content_width(obj);
}
else if(w_is_pct) {
/*If parent has content size and the child has pct size
*a circular dependency will occur. To solve it keep child size at zero */
if(parent->w_layout == 0 && lv_obj_get_style_width(parent, 0) == LV_SIZE_CONTENT) {
w = lv_obj_get_style_space_left(obj, 0) + lv_obj_get_style_space_right(obj, 0);
}
else {
w = (LV_COORD_GET_PCT(w) * parent_w) / 100;
w -= lv_obj_get_style_margin_left(obj, LV_PART_MAIN) + lv_obj_get_style_margin_right(obj, LV_PART_MAIN);
}
}
int32_t minw = lv_obj_get_style_min_width(obj, LV_PART_MAIN);
int32_t maxw = lv_obj_get_style_max_width(obj, LV_PART_MAIN);
w = lv_clamp_width(w, minw, maxw, parent_w);
int32_t content_width = -1;
w = calc_dynamic_width(obj, lv_obj_get_style_width(obj, LV_PART_MAIN), &content_width);
int32_t minw = calc_dynamic_width(obj, lv_obj_get_style_min_width(obj, LV_PART_MAIN), &content_width);
int32_t maxw = calc_dynamic_width(obj, lv_obj_get_style_max_width(obj, LV_PART_MAIN), &content_width);
w = LV_CLAMP(minw, w, maxw);
}
int32_t h;
bool h_is_content = false;
bool h_is_pct = false;
if(obj->h_layout) {
h = lv_obj_get_height(obj);
}
else {
h = lv_obj_get_style_height(obj, LV_PART_MAIN);
h_is_content = h == LV_SIZE_CONTENT;
h_is_pct = LV_COORD_IS_PCT(h);
int32_t parent_h = lv_obj_get_content_height(parent);
if(h_is_content) {
h = calc_content_height(obj);
}
else if(h_is_pct) {
/*If parent has content size and the child has pct size
*a circular dependency will occur. To solve it keep child size at zero */
if(parent->h_layout == 0 && lv_obj_get_style_height(parent, 0) == LV_SIZE_CONTENT) {
h = lv_obj_get_style_space_top(obj, 0) + lv_obj_get_style_space_bottom(obj, 0);
}
else {
h = (LV_COORD_GET_PCT(h) * parent_h) / 100;
h -= lv_obj_get_style_margin_top(obj, LV_PART_MAIN) + lv_obj_get_style_margin_bottom(obj, LV_PART_MAIN);
}
}
int32_t minh = lv_obj_get_style_min_height(obj, LV_PART_MAIN);
int32_t maxh = lv_obj_get_style_max_height(obj, LV_PART_MAIN);
h = lv_clamp_height(h, minh, maxh, parent_h);
int32_t content_height = -1;
h = calc_dynamic_height(obj, lv_obj_get_style_height(obj, LV_PART_MAIN), &content_height);
int32_t minh = calc_dynamic_height(obj, lv_obj_get_style_min_height(obj, LV_PART_MAIN), &content_height);
int32_t maxh = calc_dynamic_height(obj, lv_obj_get_style_max_height(obj, LV_PART_MAIN), &content_height);
h = LV_CLAMP(minh, h, maxh);
}
/*Do nothing if the size is not changed*/
/*It is very important else recursive resizing can occur without size change*/
if(lv_obj_get_width(obj) == w && lv_obj_get_height(obj) == h) return false;
if(lv_obj_get_width(obj) == w && lv_obj_get_height(obj) == h)
return false;
/*Invalidate the original area*/
lv_obj_invalidate(obj);
@@ -177,7 +187,8 @@ bool lv_obj_refr_size(lv_obj_t * obj)
/*If the object is already out of the parent and its position is changes
*surely the scrollbars also changes so invalidate them*/
bool on1 = lv_area_is_in(&ori, &parent_fit_area, 0);
if(!on1) lv_obj_scrollbar_invalidate(parent);
if(!on1)
lv_obj_scrollbar_invalidate(parent);
/*Set the length and height
*Be sure the content is not scrolled in an invalid position on the new size*/
@@ -203,7 +214,8 @@ bool lv_obj_refr_size(lv_obj_t * obj)
/*If the object was out of the parent invalidate the new scrollbar area too.
*If it wasn't out of the parent but out now, also invalidate the scrollbars*/
bool on2 = lv_area_is_in(&obj->coords, &parent_fit_area, 0);
if(on1 || (!on1 && on2)) lv_obj_scrollbar_invalidate(parent);
if(on1 || (!on1 && on2))
lv_obj_scrollbar_invalidate(parent);
lv_obj_refresh_ext_draw_size(obj);
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -51,4 +51,26 @@ void test_content_parent_pct_child_pos_1(void)
TEST_ASSERT_EQUAL_INT32(0, lv_obj_get_y(child2));
}
void test_style_min_size(void)
{
lv_obj_t * parent = lv_obj_create(lv_scr_act());
lv_obj_set_size(parent, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
// lv_obj_set_style_pad_all(parent, 10, 0);
lv_obj_t * child = lv_button_create(parent);
lv_obj_t * label = lv_label_create(child);
lv_label_set_text(label, "Button");
lv_obj_set_size(child, LV_PCT(100), LV_PCT(100));
lv_obj_set_size(label, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_pos_no_min_size.png");
lv_obj_set_style_min_width(child, 200, 0);
lv_obj_set_style_min_height(child, 300, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_pos_fixed_min_size.png");
lv_obj_set_style_min_width(child, LV_SIZE_CONTENT, 0);
lv_obj_set_style_min_height(child, LV_SIZE_CONTENT, 0);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/obj_pos_content_min_size.png");
}
#endif