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.
+
+- Default 0
+- Inherited No
+- Layout Yes
+- Ext. draw No
+
+
+### margin_bottom
+Sets the margin on the bottom. It makes the object area bigger in this direction.
+
+- Default 0
+- Inherited No
+- Layout Yes
+- Ext. draw No
+
+
+### margin_left
+Sets the margin on the left. It makes the object area bigger in this direction.
+
+- Default 0
+- Inherited No
+- Layout Yes
+- Ext. draw No
+
+
+### margin_right
+Sets the margin on the right. It makes the object area bigger in this direction.
+
+- Default 0
+- Inherited No
+- Layout Yes
+- Ext. draw No
+
+
## 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