diff --git a/docs/overview/style-props.md b/docs/overview/style-props.md index 74a0cd5fa..b12a72474 100644 --- a/docs/overview/style-props.md +++ b/docs/overview/style-props.md @@ -213,6 +213,45 @@ Sets the padding between the columns. Used by the layouts.
  • Ext. draw No
  • +## Margin +Properties to describe spacing around an object. Very similar to the margin properties in HTML. + +### margin_top +Sets the margin on the top. It makes the object area bigger in this direction. + + +### margin_bottom +Sets the margin on the bottom. It makes the object area bigger in this direction. + + +### margin_left +Sets the margin on the left. It makes the object area bigger in this direction. + + +### margin_right +Sets the margin on the right. It makes the object area bigger in this direction. + + ## Background Properties to describe the background color and image of the objects. diff --git a/scripts/style_api_gen.py b/scripts/style_api_gen.py index 248fc0523..47744ac47 100755 --- a/scripts/style_api_gen.py +++ b/scripts/style_api_gen.py @@ -99,6 +99,23 @@ props = [ 'style_type': 'num', 'var_type': 'lv_coord_t', 'default':0, 'inherited': 0, 'layout': 1, 'ext_draw': 0, 'dsc': "Sets the padding between the columns. Used by the layouts."}, +{'section': 'Margin', 'dsc' : "Properties to describe spacing around an object. Very similar to the margin properties in HTML."}, +{'name': 'MARGIN_TOP', + 'style_type': 'num', 'var_type': 'lv_coord_t', 'default':0, 'inherited': 0, 'layout': 1, 'ext_draw': 0, + 'dsc': "Sets the margin on the top. The object will keep this space from its siblings in layouts. "}, + +{'name': 'MARGIN_BOTTOM', + 'style_type': 'num', 'var_type': 'lv_coord_t', 'default':0, 'inherited': 0, 'layout': 1, 'ext_draw': 0, + 'dsc': "Sets the margin on the bottom. The object will keep this space from its siblings in layouts."}, + +{'name': 'MARGIN_LEFT', + 'style_type': 'num', 'var_type': 'lv_coord_t', 'default':0, 'inherited': 0, 'layout': 1, 'ext_draw': 0, + 'dsc': "Sets the margin on the left. The object will keep this space from its siblings in layouts."}, + +{'name': 'MARGIN_RIGHT', + 'style_type': 'num', 'var_type': 'lv_coord_t', 'default':0, 'inherited': 0, 'layout': 1, 'ext_draw': 0, + 'dsc': "Sets the margin on the right. The object will keep this space from its siblings in layouts."}, + {'section': 'Background', 'dsc':'Properties to describe the background color and image of the objects.' }, {'name': 'BG_COLOR', 'style_type': 'color', 'var_type': 'lv_color_t', 'default':'`0xffffff`', 'inherited': 0, 'layout': 0, 'ext_draw': 0, 'filtered': 1, diff --git a/src/core/lv_obj_pos.c b/src/core/lv_obj_pos.c index adab8e6ad..706cc303f 100644 --- a/src/core/lv_obj_pos.c +++ b/src/core/lv_obj_pos.c @@ -112,6 +112,7 @@ bool lv_obj_refr_size(lv_obj_t * obj) } 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); } } @@ -144,6 +145,7 @@ bool lv_obj_refr_size(lv_obj_t * obj) } 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); } } @@ -363,10 +365,12 @@ void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; y = lv_obj_get_content_height(base) / 2 - lv_obj_get_height(obj) / 2 + btop; break; + case LV_ALIGN_TOP_LEFT: x = bleft; y = btop; break; + case LV_ALIGN_TOP_MID: x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; y = btop; @@ -649,45 +653,42 @@ void lv_obj_refr_pos(lv_obj_t * obj) else align = LV_ALIGN_TOP_LEFT; } - if(align == LV_ALIGN_TOP_LEFT) { - lv_obj_move_to(obj, x, y); + switch(align) { + case LV_ALIGN_TOP_LEFT: + break; + case LV_ALIGN_TOP_MID: + x += pw / 2 - w / 2; + break; + case LV_ALIGN_TOP_RIGHT: + x += pw - w; + break; + case LV_ALIGN_LEFT_MID: + y += ph / 2 - h / 2; + break; + case LV_ALIGN_BOTTOM_LEFT: + y += ph - h; + break; + case LV_ALIGN_BOTTOM_MID: + x += pw / 2 - w / 2; + y += ph - h; + break; + case LV_ALIGN_BOTTOM_RIGHT: + x += pw - w; + y += ph - h; + break; + case LV_ALIGN_RIGHT_MID: + x += pw - w; + y += ph / 2 - h / 2; + break; + case LV_ALIGN_CENTER: + x += pw / 2 - w / 2; + y += ph / 2 - h / 2; + break; + default: + break; } - else { - switch(align) { - case LV_ALIGN_TOP_MID: - x += pw / 2 - w / 2; - break; - case LV_ALIGN_TOP_RIGHT: - x += pw - w; - break; - case LV_ALIGN_LEFT_MID: - y += ph / 2 - h / 2; - break; - case LV_ALIGN_BOTTOM_LEFT: - y += ph - h; - break; - case LV_ALIGN_BOTTOM_MID: - x += pw / 2 - w / 2; - y += ph - h; - break; - case LV_ALIGN_BOTTOM_RIGHT: - x += pw - w; - y += ph - h; - break; - case LV_ALIGN_RIGHT_MID: - x += pw - w; - y += ph / 2 - h / 2; - break; - case LV_ALIGN_CENTER: - x += pw / 2 - w / 2; - y += ph / 2 - h / 2; - break; - default: - break; - } - lv_obj_move_to(obj, x, y); - } + lv_obj_move_to(obj, x, y); } void lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) @@ -987,6 +988,7 @@ static lv_coord_t calc_content_width(lv_obj_t * obj) /*With RTL find the left most coordinate*/ if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) { for(i = 0; i < child_cnt; i++) { + lv_coord_t child_res_tmp = LV_COORD_MIN; lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; @@ -998,19 +1000,22 @@ static lv_coord_t calc_content_width(lv_obj_t * obj) case LV_ALIGN_BOTTOM_RIGHT: case LV_ALIGN_RIGHT_MID: /*Normal right aligns. Other are ignored due to possible circular dependencies*/ - child_res = LV_MAX(child_res, obj->coords.x2 - child->coords.x1 + 1); + child_res_tmp = obj->coords.x2 - child->coords.x1 + 1; break; default: /* Consider other cases only if x=0 and use the width of the object. * With x!=0 circular dependency could occur. */ if(lv_obj_get_style_x(child, 0) == 0) { - child_res = LV_MAX(child_res, lv_area_get_width(&child->coords) + space_right); + child_res_tmp = lv_area_get_width(&child->coords) + space_right; + child_res_tmp += lv_obj_get_style_margin_left(child, LV_PART_MAIN); } + break; } } else { - child_res = LV_MAX(child_res, obj->coords.x2 - child->coords.x1 + 1); + child_res_tmp = obj->coords.x2 - child->coords.x1 + 1; } + child_res = LV_MAX(child_res, child_res_tmp + lv_obj_get_style_margin_left(child, LV_PART_MAIN)); } if(child_res != LV_COORD_MIN) { child_res += space_left; @@ -1019,6 +1024,7 @@ static lv_coord_t calc_content_width(lv_obj_t * obj) /*Else find the right most coordinate*/ else { for(i = 0; i < child_cnt; i++) { + lv_coord_t child_res_tmp = LV_COORD_MIN; lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; @@ -1030,19 +1036,23 @@ static lv_coord_t calc_content_width(lv_obj_t * obj) case LV_ALIGN_BOTTOM_LEFT: case LV_ALIGN_LEFT_MID: /*Normal left aligns.*/ - child_res = LV_MAX(child_res, child->coords.x2 - obj->coords.x1 + 1); + child_res_tmp = child->coords.x2 - obj->coords.x1 + 1; break; default: /* Consider other cases only if x=0 and use the width of the object. * With x!=0 circular dependency could occur. */ if(lv_obj_get_style_y(child, 0) == 0) { - child_res = LV_MAX(child_res, lv_area_get_width(&child->coords) + space_left); + child_res_tmp = lv_area_get_width(&child->coords) + space_left; + child_res_tmp += lv_obj_get_style_margin_right(child, LV_PART_MAIN); } + break; } } else { - child_res = LV_MAX(child_res, child->coords.x2 - obj->coords.x1 + 1); + child_res_tmp = child->coords.x2 - obj->coords.x1 + 1; } + + child_res = LV_MAX(child_res, child_res_tmp + lv_obj_get_style_margin_right(child, LV_PART_MAIN)); } if(child_res != LV_COORD_MIN) { @@ -1051,7 +1061,7 @@ static lv_coord_t calc_content_width(lv_obj_t * obj) } if(child_res == LV_COORD_MIN) return self_w; - else return LV_MAX(child_res, self_w); + return LV_MAX(child_res, self_w); } static lv_coord_t calc_content_height(lv_obj_t * obj) @@ -1068,10 +1078,10 @@ static lv_coord_t calc_content_height(lv_obj_t * obj) uint32_t i; uint32_t child_cnt = lv_obj_get_child_cnt(obj); for(i = 0; i < child_cnt; i++) { + lv_coord_t child_res_tmp = LV_COORD_MIN; lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - if(!lv_obj_is_layout_positioned(child)) { lv_align_t align = lv_obj_get_style_align(child, 0); switch(align) { @@ -1080,30 +1090,27 @@ static lv_coord_t calc_content_height(lv_obj_t * obj) case LV_ALIGN_TOP_MID: case LV_ALIGN_TOP_LEFT: /*Normal top aligns. */ - child_res = LV_MAX(child_res, child->coords.y2 - obj->coords.y1 + 1); + child_res_tmp = child->coords.y2 - obj->coords.y1 + 1; break; default: /* Consider other cases only if y=0 and use the height of the object. * With y!=0 circular dependency could occur. */ if(lv_obj_get_style_y(child, 0) == 0) { - child_res = LV_MAX(child_res, lv_area_get_height(&child->coords) + space_top); + child_res_tmp = lv_area_get_height(&child->coords) + space_top; + child_res_tmp += lv_obj_get_style_margin_top(child, LV_PART_MAIN); } break; } } else { - child_res = LV_MAX(child_res, child->coords.y2 - obj->coords.y1 + 1); + child_res_tmp = child->coords.y2 - obj->coords.y1 + 1; } + + child_res = LV_MAX(child_res, child_res_tmp + lv_obj_get_style_margin_bottom(child, LV_PART_MAIN)); } - if(child_res != LV_COORD_MIN) { - child_res += space_bottom; - return LV_MAX(child_res, self_h); - } - else { - return self_h; - } - + if(child_res == LV_COORD_MIN) return self_h; + return LV_MAX(self_h, child_res + space_bottom); } static void layout_update_core(lv_obj_t * obj) diff --git a/src/core/lv_obj_scroll.c b/src/core/lv_obj_scroll.c index 13bd30b5a..88d72f0be 100644 --- a/src/core/lv_obj_scroll.c +++ b/src/core/lv_obj_scroll.c @@ -141,7 +141,9 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj) for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - child_res = LV_MAX(child_res, child->coords.y2); + + lv_coord_t tmp_y = child->coords.y2 + lv_obj_get_style_margin_bottom(child, LV_PART_MAIN); + child_res = LV_MAX(child_res, tmp_y); } lv_coord_t space_top = lv_obj_get_style_space_top(obj, LV_PART_MAIN); @@ -180,8 +182,9 @@ lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj) for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - x1 = LV_MIN(x1, child->coords.x1); + lv_coord_t tmp_x = child->coords.x1 - lv_obj_get_style_margin_left(child, LV_PART_MAIN); + x1 = LV_MIN(x1, tmp_x); } if(x1 != LV_COORD_MAX) { @@ -217,7 +220,9 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj) for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - child_res = LV_MAX(child_res, child->coords.x2); + + lv_coord_t tmp_x = child->coords.x2 + lv_obj_get_style_margin_right(child, LV_PART_MAIN); + child_res = LV_MAX(child_res, tmp_x); } lv_coord_t space_right = lv_obj_get_style_space_right(obj, LV_PART_MAIN); diff --git a/src/core/lv_obj_style.h b/src/core/lv_obj_style.h index 711fe2b74..05cb1bb8e 100644 --- a/src/core/lv_obj_style.h +++ b/src/core/lv_obj_style.h @@ -222,6 +222,26 @@ static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t v lv_obj_set_style_pad_bottom(obj, value, selector); } +static inline void lv_obj_set_style_margin_all(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_margin_left(obj, value, selector); + lv_obj_set_style_margin_right(obj, value, selector); + lv_obj_set_style_margin_top(obj, value, selector); + lv_obj_set_style_margin_bottom(obj, value, selector); +} + +static inline void lv_obj_set_style_margin_hor(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_margin_left(obj, value, selector); + lv_obj_set_style_margin_right(obj, value, selector); +} + +static inline void lv_obj_set_style_margin_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_margin_top(obj, value, selector); + lv_obj_set_style_margin_bottom(obj, value, selector); +} + static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) { lv_obj_set_style_pad_row(obj, value, selector); diff --git a/src/core/lv_obj_style_gen.c b/src/core/lv_obj_style_gen.c index 64a0bb28c..dc0a480b3 100644 --- a/src/core/lv_obj_style_gen.c +++ b/src/core/lv_obj_style_gen.c @@ -184,6 +184,38 @@ void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_COLUMN, v, selector); } +void lv_obj_set_style_margin_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_TOP, v, selector); +} + +void lv_obj_set_style_margin_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_BOTTOM, v, selector); +} + +void lv_obj_set_style_margin_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_LEFT, v, selector); +} + +void lv_obj_set_style_margin_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_RIGHT, v, selector); +} + void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { diff --git a/src/core/lv_obj_style_gen.h b/src/core/lv_obj_style_gen.h index 51bd6d3cd..13d9e5347 100644 --- a/src/core/lv_obj_style_gen.h +++ b/src/core/lv_obj_style_gen.h @@ -139,6 +139,30 @@ static inline lv_coord_t lv_obj_get_style_pad_column(const struct _lv_obj_t * ob return (lv_coord_t)v.num; } +static inline lv_coord_t lv_obj_get_style_margin_top(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_TOP); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_margin_bottom(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_BOTTOM); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_margin_left(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_LEFT); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_margin_right(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_RIGHT); + return (lv_coord_t)v.num; +} + static inline lv_color_t lv_obj_get_style_bg_color(const struct _lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR); @@ -588,6 +612,10 @@ void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_styl void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_margin_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_margin_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_margin_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_margin_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); diff --git a/src/layouts/flex/lv_flex.c b/src/layouts/flex/lv_flex.c index 58244fa17..943a01eae 100644 --- a/src/layouts/flex/lv_flex.c +++ b/src/layouts/flex/lv_flex.c @@ -61,6 +61,8 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, lv_coord_t * start_pos, lv_coord_t * gap); static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id); +static lv_coord_t lv_obj_get_width_with_margin(const lv_obj_t * obj); +static lv_coord_t lv_obj_get_height_with_margin(const lv_obj_t * obj); /********************** * GLOBAL VARIABLES @@ -327,8 +329,9 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id if(f->wrap && ((f->row && w_set == LV_SIZE_CONTENT) || (!f->row && h_set == LV_SIZE_CONTENT))) { f->wrap = false; } - lv_coord_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width : lv_obj_get_height); - lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width : lv_obj_get_height); + lv_coord_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width_with_margin : lv_obj_get_height_with_margin); + lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width_with_margin : + lv_obj_get_height_with_margin); t->track_main_size = 0; t->track_fix_main_size = 0; @@ -408,6 +411,12 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i lv_coord_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height); lv_coord_t (*area_get_cross_size)(const lv_area_t *) = (!f->row ? lv_area_get_width : lv_area_get_height); + typedef lv_coord_t (*margin_func_t)(const struct _lv_obj_t *, uint32_t); + margin_func_t get_margin_main_start = (f->row ? lv_obj_get_style_margin_left : lv_obj_get_style_margin_top); + margin_func_t get_margin_main_end = (f->row ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom); + margin_func_t get_margin_cross_start = (!f->row ? lv_obj_get_style_margin_left : lv_obj_get_style_margin_top); + margin_func_t get_margin_cross_end = (!f->row ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom); + /*Calculate the size of grow items first*/ uint32_t i; bool grow_reiterate = true; @@ -500,11 +509,14 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i /*Round up the cross size to avoid rounding error when dividing by 2 *The issue comes up e,g, with column direction with center cross direction if an element's width changes*/ cross_pos = (((t->track_cross_size + 1) & (~1)) - area_get_cross_size(&item->coords)) / 2; + cross_pos += (get_margin_cross_start(item, LV_PART_MAIN) - get_margin_cross_end(item, LV_PART_MAIN)) / 2; break; case LV_FLEX_ALIGN_END: cross_pos = t->track_cross_size - area_get_cross_size(&item->coords); + cross_pos -= get_margin_cross_end(item, LV_PART_MAIN); break; default: + cross_pos += get_margin_cross_start(item, LV_PART_MAIN); break; } @@ -521,8 +533,8 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i lv_coord_t diff_x = abs_x - item->coords.x1 + tr_x; lv_coord_t diff_y = abs_y - item->coords.y1 + tr_y; - diff_x += f->row ? main_pos : cross_pos; - diff_y += f->row ? cross_pos : main_pos; + diff_x += f->row ? main_pos + get_margin_main_start(item, LV_PART_MAIN) : cross_pos; + diff_y += f->row ? cross_pos : main_pos + get_margin_main_start(item, LV_PART_MAIN); if(diff_x || diff_y) { lv_obj_invalidate(item); @@ -534,7 +546,9 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i lv_obj_move_children_by(item, diff_x, diff_y, false); } - if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap; + if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap + + get_margin_main_start(item, LV_PART_MAIN) + + get_margin_main_end(item, LV_PART_MAIN); else main_pos -= item_gap + place_gap; item = get_next_item(cont, f->rev, &item_first_id); @@ -598,4 +612,18 @@ static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id) } } +static lv_coord_t lv_obj_get_width_with_margin(const lv_obj_t * obj) +{ + return lv_obj_get_style_margin_left(obj, LV_PART_MAIN) + + lv_obj_get_width(obj) + + lv_obj_get_style_margin_right(obj, LV_PART_MAIN); +} + +static lv_coord_t lv_obj_get_height_with_margin(const lv_obj_t * obj) +{ + return lv_obj_get_style_margin_top(obj, LV_PART_MAIN) + + lv_obj_get_height(obj) + + lv_obj_get_style_margin_bottom(obj, LV_PART_MAIN); +} + #endif /*LV_USE_FLEX*/ diff --git a/src/layouts/grid/lv_grid.c b/src/layouts/grid/lv_grid.c index 60c463bd3..209617513 100644 --- a/src/layouts/grid/lv_grid.c +++ b/src/layouts/grid/lv_grid.c @@ -97,6 +97,16 @@ static inline uint8_t get_grid_row_align(lv_obj_t * obj) { return lv_obj_get_style_grid_row_align(obj, 0); } +static inline lv_coord_t get_margin_hor(lv_obj_t * obj) +{ + return lv_obj_get_style_margin_left(obj, LV_PART_MAIN) + + lv_obj_get_style_margin_right(obj, LV_PART_MAIN); +} +static inline lv_coord_t get_margin_ver(lv_obj_t * obj) +{ + return lv_obj_get_style_margin_top(obj, LV_PART_MAIN) + + lv_obj_get_style_margin_bottom(obj, LV_PART_MAIN); +} /********************** * GLOBAL VARIABLES @@ -618,20 +628,21 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * switch(col_align) { default: case LV_GRID_ALIGN_START: - x = c->x[col_pos]; + x = c->x[col_pos] + lv_obj_get_style_margin_left(item, LV_PART_MAIN); item->w_layout = 0; break; case LV_GRID_ALIGN_STRETCH: - x = c->x[col_pos]; - item_w = col_w; + x = c->x[col_pos] + lv_obj_get_style_margin_left(item, LV_PART_MAIN); + item_w = col_w - get_margin_hor(item); item->w_layout = 1; break; case LV_GRID_ALIGN_CENTER: - x = c->x[col_pos] + (col_w - item_w) / 2; + x = c->x[col_pos] + (col_w - item_w) / 2 + (lv_obj_get_style_margin_left(item, LV_PART_MAIN) - + lv_obj_get_style_margin_right(item, LV_PART_MAIN)) / 2; item->w_layout = 0; break; case LV_GRID_ALIGN_END: - x = c->x[col_pos] + col_w - lv_obj_get_width(item); + x = c->x[col_pos] + col_w - lv_obj_get_width(item) - lv_obj_get_style_margin_right(item, LV_PART_MAIN); item->w_layout = 0; break; } @@ -639,20 +650,21 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * switch(row_align) { default: case LV_GRID_ALIGN_START: - y = c->y[row_pos]; + y = c->y[row_pos] + lv_obj_get_style_margin_top(item, LV_PART_MAIN); item->h_layout = 0; break; case LV_GRID_ALIGN_STRETCH: - y = c->y[row_pos]; - item_h = row_h; + y = c->y[row_pos] + lv_obj_get_style_margin_top(item, LV_PART_MAIN); + item_h = row_h - get_margin_ver(item); item->h_layout = 1; break; case LV_GRID_ALIGN_CENTER: - y = c->y[row_pos] + (row_h - item_h) / 2; + y = c->y[row_pos] + (row_h - item_h) / 2 + (lv_obj_get_style_margin_top(item, LV_PART_MAIN) - + lv_obj_get_style_margin_bottom(item, LV_PART_MAIN)) / 2; item->h_layout = 0; break; case LV_GRID_ALIGN_END: - y = c->y[row_pos] + row_h - lv_obj_get_height(item); + y = c->y[row_pos] + row_h - lv_obj_get_height(item) - lv_obj_get_style_margin_bottom(item, LV_PART_MAIN); item->h_layout = 0; break; } diff --git a/src/misc/lv_style.c b/src/misc/lv_style.c index 5d8eb1605..39bd58189 100644 --- a/src/misc/lv_style.c +++ b/src/misc/lv_style.c @@ -60,6 +60,10 @@ const uint8_t _lv_style_builtin_prop_flag_lookup_table[_LV_STYLE_NUM_BUILT_IN_PR [LV_STYLE_PAD_RIGHT] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, [LV_STYLE_PAD_ROW] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, [LV_STYLE_PAD_COLUMN] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MARGIN_TOP] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MARGIN_BOTTOM] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MARGIN_LEFT] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MARGIN_RIGHT] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, [LV_STYLE_BG_COLOR] = 0, [LV_STYLE_BG_OPA] = 0, diff --git a/src/misc/lv_style.h b/src/misc/lv_style.h index 2646a985e..8e25011f7 100644 --- a/src/misc/lv_style.h +++ b/src/misc/lv_style.h @@ -202,6 +202,10 @@ enum { LV_STYLE_PAD_COLUMN = 21, LV_STYLE_BASE_DIR = 22, LV_STYLE_CLIP_CORNER = 23, + LV_STYLE_MARGIN_TOP = 24, + LV_STYLE_MARGIN_BOTTOM = 25, + LV_STYLE_MARGIN_LEFT = 26, + LV_STYLE_MARGIN_RIGHT = 27, /*Group 2*/ LV_STYLE_BG_COLOR = 32, diff --git a/src/misc/lv_style_gen.c b/src/misc/lv_style_gen.c index c06923ee8..c8dfcaa9b 100644 --- a/src/misc/lv_style_gen.c +++ b/src/misc/lv_style_gen.c @@ -230,6 +230,46 @@ void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value) const lv_style_prop_t _lv_style_const_prop_id_PAD_COLUMN = LV_STYLE_PAD_COLUMN; +void lv_style_set_margin_top(lv_style_t * style, lv_coord_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_MARGIN_TOP, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_MARGIN_TOP = LV_STYLE_MARGIN_TOP; + +void lv_style_set_margin_bottom(lv_style_t * style, lv_coord_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_MARGIN_BOTTOM, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_MARGIN_BOTTOM = LV_STYLE_MARGIN_BOTTOM; + +void lv_style_set_margin_left(lv_style_t * style, lv_coord_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_MARGIN_LEFT, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_MARGIN_LEFT = LV_STYLE_MARGIN_LEFT; + +void lv_style_set_margin_right(lv_style_t * style, lv_coord_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_MARGIN_RIGHT, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_MARGIN_RIGHT = LV_STYLE_MARGIN_RIGHT; + void lv_style_set_bg_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { diff --git a/src/misc/lv_style_gen.h b/src/misc/lv_style_gen.h index c206f08a7..70829daf9 100644 --- a/src/misc/lv_style_gen.h +++ b/src/misc/lv_style_gen.h @@ -44,6 +44,14 @@ void lv_style_set_pad_row(lv_style_t * style, lv_coord_t value); extern const lv_style_prop_t _lv_style_const_prop_id_PAD_ROW; void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value); extern const lv_style_prop_t _lv_style_const_prop_id_PAD_COLUMN; +void lv_style_set_margin_top(lv_style_t * style, lv_coord_t value); +extern const lv_style_prop_t _lv_style_const_prop_id_MARGIN_TOP; +void lv_style_set_margin_bottom(lv_style_t * style, lv_coord_t value); +extern const lv_style_prop_t _lv_style_const_prop_id_MARGIN_BOTTOM; +void lv_style_set_margin_left(lv_style_t * style, lv_coord_t value); +extern const lv_style_prop_t _lv_style_const_prop_id_MARGIN_LEFT; +void lv_style_set_margin_right(lv_style_t * style, lv_coord_t value); +extern const lv_style_prop_t _lv_style_const_prop_id_MARGIN_RIGHT; void lv_style_set_bg_color(lv_style_t * style, lv_color_t value); extern const lv_style_prop_t _lv_style_const_prop_id_BG_COLOR; void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value); @@ -282,6 +290,26 @@ extern const lv_style_prop_t _lv_style_const_prop_id_BASE_DIR; .prop_ptr = &_lv_style_const_prop_id_PAD_COLUMN, .value = { .num = (int32_t)val } \ } +#define LV_STYLE_CONST_MARGIN_TOP(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_MARGIN_TOP, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MARGIN_BOTTOM(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_MARGIN_BOTTOM, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MARGIN_LEFT(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_MARGIN_LEFT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MARGIN_RIGHT(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_MARGIN_RIGHT, .value = { .num = (int32_t)val } \ + } + #define LV_STYLE_CONST_BG_COLOR(val) \ { \ .prop_ptr = &_lv_style_const_prop_id_BG_COLOR, .value = { .color = val } \ diff --git a/tests/ref_imgs/margin_align_0.png b/tests/ref_imgs/margin_align_0.png new file mode 100644 index 000000000..0d63c7db3 Binary files /dev/null and b/tests/ref_imgs/margin_align_0.png differ diff --git a/tests/ref_imgs/margin_align_1.png b/tests/ref_imgs/margin_align_1.png new file mode 100644 index 000000000..da9952190 Binary files /dev/null and b/tests/ref_imgs/margin_align_1.png differ diff --git a/tests/ref_imgs/margin_flex_0.png b/tests/ref_imgs/margin_flex_0.png new file mode 100644 index 000000000..befe1fc5c Binary files /dev/null and b/tests/ref_imgs/margin_flex_0.png differ diff --git a/tests/ref_imgs/margin_flex_1.png b/tests/ref_imgs/margin_flex_1.png new file mode 100644 index 000000000..ea1b7f490 Binary files /dev/null and b/tests/ref_imgs/margin_flex_1.png differ diff --git a/tests/ref_imgs/margin_flex_2.png b/tests/ref_imgs/margin_flex_2.png new file mode 100644 index 000000000..166e8b5d8 Binary files /dev/null and b/tests/ref_imgs/margin_flex_2.png differ diff --git a/tests/ref_imgs/margin_flex_3.png b/tests/ref_imgs/margin_flex_3.png new file mode 100644 index 000000000..d547a03aa Binary files /dev/null and b/tests/ref_imgs/margin_flex_3.png differ diff --git a/tests/ref_imgs/margin_flex_4.png b/tests/ref_imgs/margin_flex_4.png new file mode 100644 index 000000000..760c26f2e Binary files /dev/null and b/tests/ref_imgs/margin_flex_4.png differ diff --git a/tests/ref_imgs/margin_flex_5.png b/tests/ref_imgs/margin_flex_5.png new file mode 100644 index 000000000..33cd5b7fe Binary files /dev/null and b/tests/ref_imgs/margin_flex_5.png differ diff --git a/tests/ref_imgs/margin_grid_0.png b/tests/ref_imgs/margin_grid_0.png new file mode 100644 index 000000000..03932a39a Binary files /dev/null and b/tests/ref_imgs/margin_grid_0.png differ diff --git a/tests/src/lv_test_conf_full.h b/tests/src/lv_test_conf_full.h index f0dc12f99..af01d7944 100644 --- a/tests/src/lv_test_conf_full.h +++ b/tests/src/lv_test_conf_full.h @@ -52,6 +52,9 @@ #define LV_USE_MEM_MONITOR 1 #define LV_LABEL_TEXT_SELECTION 1 +#define LV_USE_FLEX 1 +#define LV_USE_GRID 1 + #define LV_USE_FS_STDIO 1 #define LV_FS_STDIO_LETTER 'A' #define LV_USE_FS_POSIX 1 diff --git a/tests/src/test_cases/test_margin_align.c b/tests/src/test_cases/test_margin_align.c new file mode 100644 index 000000000..2f790bfbc --- /dev/null +++ b/tests/src/test_cases/test_margin_align.c @@ -0,0 +1,80 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" + +#include "unity/unity.h" + +static lv_obj_t * active_screen = NULL; + +void setUp(void) +{ + active_screen = lv_scr_act(); +} + +void tearDown(void) +{ + lv_obj_clean(active_screen); +} + +lv_obj_t * obj_create(lv_obj_t * parent, lv_color_t color) +{ + lv_obj_t * obj = lv_obj_create(parent); + lv_obj_set_style_bg_color(obj, color, LV_PART_MAIN); + lv_obj_set_width(obj, 150); + lv_obj_set_height(obj, 150); + + return obj; +} + +void obj_set_margin(lv_obj_t * obj, lv_coord_t left, lv_coord_t top, lv_coord_t right, lv_coord_t bottom) +{ + lv_obj_set_style_margin_left(obj, left, LV_PART_MAIN); + lv_obj_set_style_margin_top(obj, top, LV_PART_MAIN); + lv_obj_set_style_margin_right(obj, right, LV_PART_MAIN); + lv_obj_set_style_margin_bottom(obj, bottom, LV_PART_MAIN); +} + +// takes no effect on postiton but size. +void test_align(void) +{ + lv_obj_t * obj0 = active_screen; + + lv_obj_set_width(obj0, 800); + lv_obj_set_height(obj0, 400); + lv_obj_center(obj0); + lv_obj_set_style_pad_all(obj0, 0, LV_PART_MAIN); + lv_obj_set_style_border_width(obj0, 0, LV_PART_MAIN); + + lv_obj_t * obj0s[] = { + obj_create(obj0, lv_palette_main(LV_PALETTE_BLUE)), + obj_create(obj0, lv_palette_main(LV_PALETTE_RED)), + obj_create(obj0, lv_palette_main(LV_PALETTE_DEEP_PURPLE)), + obj_create(obj0, lv_palette_main(LV_PALETTE_GREEN)), + obj_create(obj0, lv_palette_main(LV_PALETTE_PINK)) + }; + + lv_obj_align(obj0s[0], LV_ALIGN_TOP_MID, 0, 0); + lv_obj_align_to(obj0s[1], obj0s[0], LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + lv_obj_align_to(obj0s[2], obj0s[1], LV_ALIGN_OUT_RIGHT_MID, 0, 0); + lv_obj_align_to(obj0s[3], obj0s[2], LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + lv_obj_update_layout(obj0); + + obj_set_margin(obj0s[0], 20, 50, 60, 50); + lv_obj_set_style_width(obj0s[0], LV_PCT(60), LV_PART_MAIN); + obj_set_margin(obj0s[1], 15, 12, 50, 20); + obj_set_margin(obj0s[2], 25, 25, 100, 20); + obj_set_margin(obj0s[3], 12, 50, 100, 100); + lv_obj_set_style_width(obj0s[3], LV_PCT(100), LV_PART_MAIN); + TEST_ASSERT_EQUAL_SCREENSHOT("margin_align_0.png"); + obj_set_margin(obj0s[4], 6, 100, 100, 100); + + + lv_obj_set_style_radius(obj0s[0], 0, LV_PART_MAIN); + + lv_obj_align(obj0s[4], LV_ALIGN_LEFT_MID, 0, 0); + + lv_obj_update_layout(obj0); + + TEST_ASSERT_EQUAL_SCREENSHOT("margin_align_1.png"); +} + +#endif diff --git a/tests/src/test_cases/test_margin_flex.c b/tests/src/test_cases/test_margin_flex.c new file mode 100644 index 000000000..ce18915da --- /dev/null +++ b/tests/src/test_cases/test_margin_flex.c @@ -0,0 +1,93 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" + +#include "unity/unity.h" + +static lv_obj_t * active_screen = NULL; + +void setUp(void) +{ + active_screen = lv_scr_act(); +} + +void tearDown(void) +{ + lv_obj_clean(active_screen); +} + +lv_obj_t * obj_create(lv_obj_t * parent, lv_color_t color) +{ + lv_obj_t * obj = lv_obj_create(parent); + lv_obj_set_style_bg_color(obj, color, LV_PART_MAIN); + lv_obj_set_width(obj, 150); + lv_obj_set_height(obj, 150); + + return obj; +} + +void obj_set_margin(lv_obj_t * obj, lv_coord_t left, lv_coord_t top, lv_coord_t right, lv_coord_t bottom) +{ + lv_obj_set_style_margin_left(obj, left, LV_PART_MAIN); + lv_obj_set_style_margin_top(obj, top, LV_PART_MAIN); + lv_obj_set_style_margin_right(obj, right, LV_PART_MAIN); + lv_obj_set_style_margin_bottom(obj, bottom, LV_PART_MAIN); +} + +void test_flex(void) +{ +#define N 5 + lv_obj_t * obj0 = active_screen; + + lv_obj_set_flex_flow(obj0, LV_FLEX_FLOW_ROW); + lv_obj_set_style_pad_all(obj0, 0, LV_PART_MAIN); + lv_obj_set_style_pad_gap(obj0, 0, LV_PART_MAIN); + lv_obj_set_style_border_width(obj0, 0, LV_PART_MAIN); + + lv_obj_t * obj0s[N] = { + obj_create(obj0, lv_palette_main(LV_PALETTE_BLUE)), + obj_create(obj0, lv_palette_main(LV_PALETTE_RED)), + obj_create(obj0, lv_palette_main(LV_PALETTE_PURPLE)), + obj_create(obj0, lv_palette_main(LV_PALETTE_GREEN)), + obj_create(obj0, lv_palette_main(LV_PALETTE_PINK)) + }; + + lv_obj_t * o; + for(int i = 0; i < N; i++) { + o = obj0s[i]; + lv_obj_set_style_radius(o, 0, LV_PART_MAIN); + lv_obj_set_scrollbar_mode(o, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_border_width(o, 0, LV_PART_MAIN); + } + + lv_obj_set_width(obj0s[0], LV_PCT(50)); + lv_obj_set_height(obj0s[0], LV_PCT(50)); + + obj_set_margin(obj0s[0], 50, 3, 10, 50); + obj_set_margin(obj0s[1], 25, 6, 20, 50); + obj_set_margin(obj0s[2], 12, 12, 30, 50); + obj_set_margin(obj0s[3], 12, 25, 30, 50); + obj_set_margin(obj0s[4], 24, 50, 50, 50); + + lv_obj_update_layout(obj0); + + TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_0.png"); + + lv_obj_set_flex_flow(obj0, LV_FLEX_FLOW_ROW_WRAP); + TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_1.png"); + + lv_obj_set_style_flex_main_place(obj0, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN); + TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_2.png"); + + lv_obj_set_style_flex_cross_place(obj0, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN); + TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_3.png"); + + lv_obj_set_style_flex_track_place(obj0, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN); + TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_4.png"); + + lv_obj_set_flex_flow(obj0, LV_FLEX_FLOW_COLUMN_WRAP); + TEST_ASSERT_EQUAL_SCREENSHOT("margin_flex_5.png"); + +#undef N +} + +#endif diff --git a/tests/src/test_cases/test_margin_grid.c b/tests/src/test_cases/test_margin_grid.c new file mode 100644 index 000000000..3a55e070a --- /dev/null +++ b/tests/src/test_cases/test_margin_grid.c @@ -0,0 +1,106 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" + +#include "unity/unity.h" + +static lv_obj_t * active_screen = NULL; + +void setUp(void) +{ + active_screen = lv_scr_act(); +} + +void tearDown(void) +{ + lv_obj_clean(active_screen); +} + +lv_obj_t * obj_create(lv_obj_t * parent, lv_color_t color) +{ + lv_obj_t * obj = lv_obj_create(parent); + lv_obj_set_style_bg_color(obj, color, LV_PART_MAIN); + lv_obj_set_width(obj, 150); + lv_obj_set_height(obj, 150); + + return obj; +} + +void obj_set_margin(lv_obj_t * obj, lv_coord_t left, lv_coord_t top, lv_coord_t right, lv_coord_t bottom) +{ + lv_obj_set_style_margin_left(obj, left, LV_PART_MAIN); + lv_obj_set_style_margin_top(obj, top, LV_PART_MAIN); + lv_obj_set_style_margin_right(obj, right, LV_PART_MAIN); + lv_obj_set_style_margin_bottom(obj, bottom, LV_PART_MAIN); +} + +void test_grid(void) +{ +#define M 5 +#define N 8 + + lv_obj_t * obj0 = active_screen; + + static lv_coord_t row_dsc[M + 1]; + static lv_coord_t col_dsc[N + 1]; + + row_dsc[M] = LV_GRID_TEMPLATE_LAST; + col_dsc[N] = LV_GRID_TEMPLATE_LAST; + for(int i = 0; i < M; ++i) { + row_dsc[i] = 80; + } + for(int i = 0; i < N; ++i) { + col_dsc[i] = 80; + } + + static lv_palette_t colors[] = { + LV_PALETTE_BLUE, + LV_PALETTE_PURPLE, + LV_PALETTE_GREEN, + LV_PALETTE_PINK, + LV_PALETTE_AMBER, + LV_PALETTE_BLUE_GREY, + LV_PALETTE_INDIGO + }; + + lv_obj_set_layout(obj0, LV_LAYOUT_GRID); + lv_obj_set_grid_align(obj0, LV_GRID_ALIGN_CENTER, LV_GRID_ALIGN_CENTER); + lv_obj_set_grid_dsc_array(obj0, col_dsc, row_dsc); + + lv_obj_set_style_pad_gap(obj0, 0, LV_PART_MAIN); + lv_obj_set_style_pad_row(obj0, 0, LV_PART_MAIN); + lv_obj_set_style_pad_column(obj0, 0, LV_PART_MAIN); + + lv_obj_t * obj0s[M][N]; + + for(int i = 0; i < M; ++i) { + for(int j = 0; j < N; ++j) { + obj0s[i][j] = obj_create(obj0, + lv_palette_main(colors[(i * M + j) % ((sizeof colors) / (sizeof(lv_palette_t)))])); + } + } + + lv_obj_t * o; + for(int i = 0; i < M; i++) { + for(int j = 0; j < N; ++j) { + o = obj0s[i][j]; + lv_obj_set_style_radius(o, 0, LV_PART_MAIN); + lv_obj_set_style_border_width(o, 0, LV_PART_MAIN); + lv_obj_set_scrollbar_mode(o, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_width(o, 30); + + lv_obj_set_grid_cell(o, LV_GRID_ALIGN_CENTER, j, 1, LV_GRID_ALIGN_STRETCH, i, 1); + + lv_obj_set_style_margin_top(o, i * 5, LV_PART_MAIN); + lv_obj_set_style_margin_left(o, i * 5 + j * 5, LV_PART_MAIN); + lv_obj_set_style_margin_right(o, i * 5, LV_PART_MAIN); + lv_obj_set_style_margin_bottom(o, i * 5 + j * 5, LV_PART_MAIN); + } + } + + lv_obj_update_layout(obj0); + TEST_ASSERT_EQUAL_SCREENSHOT("margin_grid_0.png"); + +#undef M +#undef N +} +#endif