From d797d1037646f211ccb7cb3818a00059ebbf8466 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 22 Nov 2018 14:59:38 +0100 Subject: [PATCH 1/3] add realign feature --- lv_conf_templ.h | 1 + lv_core/lv_obj.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++- lv_core/lv_obj.h | 86 +++++++++++++------ 3 files changed, 278 insertions(+), 27 deletions(-) diff --git a/lv_conf_templ.h b/lv_conf_templ.h index 1cf4903a9..0b55a134a 100644 --- a/lv_conf_templ.h +++ b/lv_conf_templ.h @@ -175,6 +175,7 @@ *==================*/ #define LV_OBJ_FREE_NUM_TYPE uint32_t /*Type of free number attribute (comment out disable free number)*/ #define LV_OBJ_FREE_PTR 1 /*Enable the free pointer attribute*/ +#define LV_OBJ_REAILGN 1 /*Enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ /*================== * LV OBJ X USAGE diff --git a/lv_core/lv_obj.c b/lv_core/lv_obj.c index 7871bed76..9e4b4dad0 100644 --- a/lv_core/lv_obj.c +++ b/lv_core/lv_obj.c @@ -200,6 +200,14 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) LV_OBJ_DEF_HEIGHT; new_obj->ext_size = 0; + /*Init realign*/ +#if LV_OBJ_REAILGN + new_obj->realign.align = LV_ALIGN_CENTER; + new_obj->realign.xofs = 0; + new_obj->realign.yofs = 0; + new_obj->realign.base = NULL; + new_obj->realign.auto_realign = 0; +#endif /*Set appearance*/ lv_theme_t * th = lv_theme_get_current(); if(th) { @@ -581,6 +589,11 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) /*Invalidate the new area*/ lv_obj_invalidate(obj); + + /*Automatically realign the object if required*/ +#if LV_OBJ_REAILGN + if(obj->realign.auto_realign) lv_obj_realign(obj); +#endif } /** @@ -737,6 +750,195 @@ void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_co new_y -= par_abs_y; lv_obj_set_pos(obj, new_x, new_y); + +#if LV_OBJ_REAILGN + /*Save the last align parameters to use them in `lv_obj_realign`*/ + obj->realign.align = align; + obj->realign.xofs = x_mod; + obj->realign.yofs = y_mod; + obj->realign.base = base; + obj->realign.origo_align = 0; +#endif +} + + +/** + * Align an object to an other object. + * @param obj pointer to an object to align + * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. + * @param align type of alignment (see 'lv_align_t' enum) + * @param x_mod x coordinate shift after alignment + * @param y_mod y coordinate shift after alignment + */ +void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_mod, lv_coord_t y_mod) +{ + lv_coord_t new_x = lv_obj_get_x(obj); + lv_coord_t new_y = lv_obj_get_y(obj); + + lv_coord_t obj_w_half = lv_obj_get_width(obj) / 2; + lv_coord_t obj_h_half = lv_obj_get_height(obj) / 2; + + if(base == NULL) { + base = lv_obj_get_parent(obj); + } + + switch(align) { + case LV_ALIGN_CENTER: + new_x = lv_obj_get_width(base) / 2 - obj_w_half; + new_y = lv_obj_get_height(base) / 2 - obj_h_half; + break; + + case LV_ALIGN_IN_TOP_LEFT: + new_x = -obj_w_half; + new_y = -obj_h_half; + break; + case LV_ALIGN_IN_TOP_MID: + new_x = lv_obj_get_width(base) / 2 - obj_w_half; + new_y = -obj_h_half; + break; + + case LV_ALIGN_IN_TOP_RIGHT: + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = -obj_h_half; + break; + + case LV_ALIGN_IN_BOTTOM_LEFT: + new_x = -obj_w_half; + new_y = lv_obj_get_height(base) - obj_h_half; + break; + case LV_ALIGN_IN_BOTTOM_MID: + new_x = lv_obj_get_width(base) / 2 - obj_w_half; + new_y = lv_obj_get_height(base) - obj_h_half; + break; + + case LV_ALIGN_IN_BOTTOM_RIGHT: + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = lv_obj_get_height(base) - obj_h_half; + break; + + case LV_ALIGN_IN_LEFT_MID: + new_x = -obj_w_half; + new_y = lv_obj_get_height(base) / 2 - obj_h_half; + break; + + case LV_ALIGN_IN_RIGHT_MID: + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = lv_obj_get_height(base) / 2 - obj_h_half; + break; + + case LV_ALIGN_OUT_TOP_LEFT: + new_x = -obj_w_half; + new_y = -obj_h_half; + break; + + case LV_ALIGN_OUT_TOP_MID: + new_x = lv_obj_get_width(base) / 2 - obj_w_half; + new_y = -obj_h_half; + break; + + case LV_ALIGN_OUT_TOP_RIGHT: + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = - obj_h_half; + break; + + case LV_ALIGN_OUT_BOTTOM_LEFT: + new_x = -obj_w_half; + new_y = lv_obj_get_height(base) - obj_h_half; + break; + + case LV_ALIGN_OUT_BOTTOM_MID: + new_x = lv_obj_get_width(base) / 2 - obj_w_half; + new_y = lv_obj_get_height(base) - obj_h_half; + break; + + case LV_ALIGN_OUT_BOTTOM_RIGHT: + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = lv_obj_get_height(base) - obj_h_half; + break; + + case LV_ALIGN_OUT_LEFT_TOP: + new_x = - obj_w_half ; + new_y = - obj_h_half; + break; + + case LV_ALIGN_OUT_LEFT_MID: + new_x = - obj_w_half; + new_y = lv_obj_get_height(base) / 2 - obj_h_half; + break; + + case LV_ALIGN_OUT_LEFT_BOTTOM: + new_x = - obj_w_half; + new_y = lv_obj_get_height(base) - obj_h_half; + break; + + case LV_ALIGN_OUT_RIGHT_TOP: + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = -obj_h_half; + break; + + case LV_ALIGN_OUT_RIGHT_MID: + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = lv_obj_get_height(base) / 2 - obj_h_half; + break; + + case LV_ALIGN_OUT_RIGHT_BOTTOM: + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = lv_obj_get_height(base) - obj_h_half; + break; + } + + /*Bring together the coordination system of base and obj*/ + lv_obj_t * par = lv_obj_get_parent(obj); + lv_coord_t base_abs_x = base->coords.x1; + lv_coord_t base_abs_y = base->coords.y1; + lv_coord_t par_abs_x = par->coords.x1; + lv_coord_t par_abs_y = par->coords.y1; + new_x += x_mod + base_abs_x; + new_y += y_mod + base_abs_y; + new_x -= par_abs_x; + new_y -= par_abs_y; + + lv_obj_set_pos(obj, new_x, new_y); + +#if LV_OBJ_REAILGN + /*Save the last align parameters to use them in `lv_obj_realign`*/ + obj->realign.align = align; + obj->realign.xofs = x_mod; + obj->realign.yofs = y_mod; + obj->realign.base = base; + obj->realign.origo_align = 1; +#endif +} + +/** + * Realign the object based on the last `lv_obj_align` parameters. + * @param obj pointer to an object + */ +void lv_obj_realign(lv_obj_t * obj) +{ +#if LV_OBJ_REAILGN + if(obj->realign.origo_align) lv_obj_align_origo(obj, obj->realign.base, obj->realign.align, obj->realign.xofs, obj->realign.yofs); + else lv_obj_align(obj, obj->realign.base, obj->realign.align, obj->realign.xofs, obj->realign.yofs); +#else + (void) obj; + LV_LOG_WARN("lv_obj_realaign: no effect because LV_OBJ_REAILGN = 0"); +#endif +} + +/** + * Enable the automatic realign of the object when its size has changed based on the last `lv_obj_align` parameters. + * @param obj pointer to an object + * @param en true: enable auto realign; false: disable auto realign + */ +void lv_obj_set_auto_realign(lv_obj_t * obj, bool en) +{ +#if LV_OBJ_REAILGN + obj->realign.auto_realign = en ? 1 : 0; +#else + (void) obj; + (void) en; + LV_LOG_WARN("lv_obj_set_auto_realign: no effect because LV_OBJ_REAILGN = 0"); +#endif } /*--------------------- @@ -757,7 +959,6 @@ void lv_obj_set_style(lv_obj_t * obj, lv_style_t * style) /*Notify the object about the style change too*/ lv_obj_refresh_style(obj); - } /** @@ -1259,6 +1460,21 @@ lv_coord_t lv_obj_get_ext_size(const lv_obj_t * obj) return obj->ext_size; } +/** + * Get the automatic realign property of the object. + * @param obj pointer to an object + * @return true: auto realign is enabled; false: auto realign is disabled + */ +bool lv_obj_get_auto_realign(lv_obj_t * obj) +{ +#if LV_OBJ_REAILGN + return obj->realign.auto_realign ? true : false; +#else + (void) obj; + return false; +#endif +} + /*----------------- * Appearance get *---------------*/ diff --git a/lv_core/lv_obj.h b/lv_core/lv_obj.h index 9ebc7a633..afab82a35 100644 --- a/lv_core/lv_obj.h +++ b/lv_core/lv_obj.h @@ -112,6 +112,44 @@ typedef uint8_t lv_signal_t; typedef lv_res_t (* lv_signal_func_t) (struct _lv_obj_t * obj, lv_signal_t sign, void * param); +enum +{ + LV_ALIGN_CENTER = 0, + LV_ALIGN_IN_TOP_LEFT, + LV_ALIGN_IN_TOP_MID, + LV_ALIGN_IN_TOP_RIGHT, + LV_ALIGN_IN_BOTTOM_LEFT, + LV_ALIGN_IN_BOTTOM_MID, + LV_ALIGN_IN_BOTTOM_RIGHT, + LV_ALIGN_IN_LEFT_MID, + LV_ALIGN_IN_RIGHT_MID, + LV_ALIGN_OUT_TOP_LEFT, + LV_ALIGN_OUT_TOP_MID, + LV_ALIGN_OUT_TOP_RIGHT, + LV_ALIGN_OUT_BOTTOM_LEFT, + LV_ALIGN_OUT_BOTTOM_MID, + LV_ALIGN_OUT_BOTTOM_RIGHT, + LV_ALIGN_OUT_LEFT_TOP, + LV_ALIGN_OUT_LEFT_MID, + LV_ALIGN_OUT_LEFT_BOTTOM, + LV_ALIGN_OUT_RIGHT_TOP, + LV_ALIGN_OUT_RIGHT_MID, + LV_ALIGN_OUT_RIGHT_BOTTOM, +}; +typedef uint8_t lv_align_t; + +#if LV_OBJ_REAILGN +typedef struct { + struct _lv_obj_t * base; + lv_coord_t xofs; + lv_coord_t yofs; + lv_align_t align; + uint8_t auto_realign :1; + uint8_t origo_align :1; /*1: the oigo (center of the object) was aligned with `lv_obj_align_origo`*/ +}lv_reailgn_t; +#endif + + typedef struct _lv_obj_t { struct _lv_obj_t * par; /*Pointer to the parent object*/ @@ -144,6 +182,9 @@ typedef struct _lv_obj_t lv_opa_t opa_scale; /*Scale down the opacity by this factor. Effects all children as well*/ lv_coord_t ext_size; /*EXTtend the size of the object in every direction. E.g. for shadow drawing*/ +#if LV_OBJ_REAILGN + lv_reailgn_t realign; +#endif #ifdef LV_OBJ_FREE_NUM_TYPE LV_OBJ_FREE_NUM_TYPE free_num; /*Application specific identifier (set it freely)*/ @@ -171,32 +212,6 @@ typedef struct { const char * type[LV_MAX_ANCESTOR_NUM]; /*[0]: the actual type, [1]: ancestor, [2] #1's ancestor ... [x]: "lv_obj" */ } lv_obj_type_t; -enum -{ - LV_ALIGN_CENTER = 0, - LV_ALIGN_IN_TOP_LEFT, - LV_ALIGN_IN_TOP_MID, - LV_ALIGN_IN_TOP_RIGHT, - LV_ALIGN_IN_BOTTOM_LEFT, - LV_ALIGN_IN_BOTTOM_MID, - LV_ALIGN_IN_BOTTOM_RIGHT, - LV_ALIGN_IN_LEFT_MID, - LV_ALIGN_IN_RIGHT_MID, - LV_ALIGN_OUT_TOP_LEFT, - LV_ALIGN_OUT_TOP_MID, - LV_ALIGN_OUT_TOP_RIGHT, - LV_ALIGN_OUT_BOTTOM_LEFT, - LV_ALIGN_OUT_BOTTOM_MID, - LV_ALIGN_OUT_BOTTOM_RIGHT, - LV_ALIGN_OUT_LEFT_TOP, - LV_ALIGN_OUT_LEFT_MID, - LV_ALIGN_OUT_LEFT_BOTTOM, - LV_ALIGN_OUT_RIGHT_TOP, - LV_ALIGN_OUT_RIGHT_MID, - LV_ALIGN_OUT_RIGHT_BOTTOM, -}; -typedef uint8_t lv_align_t; - enum { LV_ANIM_NONE = 0, @@ -333,6 +348,18 @@ void lv_obj_set_height(lv_obj_t * obj, lv_coord_t h); */ void lv_obj_align(lv_obj_t * obj,const lv_obj_t * base, lv_align_t align, lv_coord_t x_mod, lv_coord_t y_mod); +/** + * Realign the object based on the last `lv_obj_align` parameters. + * @param obj pointer to an object + */ +void lv_obj_realign(lv_obj_t * obj); + +/** + * Enable the automatic realign of the object when its size has changed based on the last `lv_obj_align` parameters. + * @param obj pointer to an object + * @param en true: enable auto realign; false: disable auto realign + */ +void lv_obj_set_auto_realign(lv_obj_t * obj, bool en); /*--------------------- * Appearance set @@ -623,6 +650,13 @@ lv_coord_t lv_obj_get_height(const lv_obj_t * obj); */ lv_coord_t lv_obj_get_ext_size(const lv_obj_t * obj); +/** + * Get the automatic realign property of the object. + * @param obj pointer to an object + * @return true: auto realign is enabled; false: auto realign is disabled + */ +bool lv_obj_get_auto_realign(lv_obj_t * obj); + /*----------------- * Appearance get *---------------*/ From ce1a1f749af028964594e3d40338493e9e774e53 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 22 Nov 2018 15:19:22 +0100 Subject: [PATCH 2/3] realign: fix typo --- lv_conf_templ.h | 2 +- lv_core/lv_obj.c | 18 +++++++++--------- lv_core/lv_obj.h | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lv_conf_templ.h b/lv_conf_templ.h index 0b55a134a..4df2d869f 100644 --- a/lv_conf_templ.h +++ b/lv_conf_templ.h @@ -175,7 +175,7 @@ *==================*/ #define LV_OBJ_FREE_NUM_TYPE uint32_t /*Type of free number attribute (comment out disable free number)*/ #define LV_OBJ_FREE_PTR 1 /*Enable the free pointer attribute*/ -#define LV_OBJ_REAILGN 1 /*Enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ +#define LV_OBJ_REALIGN 1 /*Enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ /*================== * LV OBJ X USAGE diff --git a/lv_core/lv_obj.c b/lv_core/lv_obj.c index 9e4b4dad0..0c289c221 100644 --- a/lv_core/lv_obj.c +++ b/lv_core/lv_obj.c @@ -201,7 +201,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->ext_size = 0; /*Init realign*/ -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN new_obj->realign.align = LV_ALIGN_CENTER; new_obj->realign.xofs = 0; new_obj->realign.yofs = 0; @@ -591,7 +591,7 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) lv_obj_invalidate(obj); /*Automatically realign the object if required*/ -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN if(obj->realign.auto_realign) lv_obj_realign(obj); #endif } @@ -751,7 +751,7 @@ void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_co lv_obj_set_pos(obj, new_x, new_y); -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN /*Save the last align parameters to use them in `lv_obj_realign`*/ obj->realign.align = align; obj->realign.xofs = x_mod; @@ -900,7 +900,7 @@ void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_obj_set_pos(obj, new_x, new_y); -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN /*Save the last align parameters to use them in `lv_obj_realign`*/ obj->realign.align = align; obj->realign.xofs = x_mod; @@ -916,12 +916,12 @@ void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, */ void lv_obj_realign(lv_obj_t * obj) { -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN if(obj->realign.origo_align) lv_obj_align_origo(obj, obj->realign.base, obj->realign.align, obj->realign.xofs, obj->realign.yofs); else lv_obj_align(obj, obj->realign.base, obj->realign.align, obj->realign.xofs, obj->realign.yofs); #else (void) obj; - LV_LOG_WARN("lv_obj_realaign: no effect because LV_OBJ_REAILGN = 0"); + LV_LOG_WARN("lv_obj_realaign: no effect because LV_OBJ_REALIGN = 0"); #endif } @@ -932,12 +932,12 @@ void lv_obj_realign(lv_obj_t * obj) */ void lv_obj_set_auto_realign(lv_obj_t * obj, bool en) { -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN obj->realign.auto_realign = en ? 1 : 0; #else (void) obj; (void) en; - LV_LOG_WARN("lv_obj_set_auto_realign: no effect because LV_OBJ_REAILGN = 0"); + LV_LOG_WARN("lv_obj_set_auto_realign: no effect because LV_OBJ_REALIGN = 0"); #endif } @@ -1467,7 +1467,7 @@ lv_coord_t lv_obj_get_ext_size(const lv_obj_t * obj) */ bool lv_obj_get_auto_realign(lv_obj_t * obj) { -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN return obj->realign.auto_realign ? true : false; #else (void) obj; diff --git a/lv_core/lv_obj.h b/lv_core/lv_obj.h index afab82a35..9c4a0409f 100644 --- a/lv_core/lv_obj.h +++ b/lv_core/lv_obj.h @@ -138,7 +138,7 @@ enum }; typedef uint8_t lv_align_t; -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN typedef struct { struct _lv_obj_t * base; lv_coord_t xofs; @@ -182,7 +182,7 @@ typedef struct _lv_obj_t lv_opa_t opa_scale; /*Scale down the opacity by this factor. Effects all children as well*/ lv_coord_t ext_size; /*EXTtend the size of the object in every direction. E.g. for shadow drawing*/ -#if LV_OBJ_REAILGN +#if LV_OBJ_REALIGN lv_reailgn_t realign; #endif From f30f3ea8ed2ef1c8be5eda37b576db8b2032de94 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 23 Nov 2018 11:35:13 +0100 Subject: [PATCH 3/3] realign: fix warnings --- lv_core/lv_obj.c | 1 - lv_core/lv_obj.h | 12 +++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lv_core/lv_obj.c b/lv_core/lv_obj.c index 0c289c221..3e576d602 100644 --- a/lv_core/lv_obj.c +++ b/lv_core/lv_obj.c @@ -761,7 +761,6 @@ void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_co #endif } - /** * Align an object to an other object. * @param obj pointer to an object to align diff --git a/lv_core/lv_obj.h b/lv_core/lv_obj.h index 9c4a0409f..6ac7170fa 100644 --- a/lv_core/lv_obj.h +++ b/lv_core/lv_obj.h @@ -140,7 +140,7 @@ typedef uint8_t lv_align_t; #if LV_OBJ_REALIGN typedef struct { - struct _lv_obj_t * base; + const struct _lv_obj_t * base; lv_coord_t xofs; lv_coord_t yofs; lv_align_t align; @@ -348,6 +348,16 @@ void lv_obj_set_height(lv_obj_t * obj, lv_coord_t h); */ void lv_obj_align(lv_obj_t * obj,const lv_obj_t * base, lv_align_t align, lv_coord_t x_mod, lv_coord_t y_mod); +/** + * Align an object to an other object. + * @param obj pointer to an object to align + * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. + * @param align type of alignment (see 'lv_align_t' enum) + * @param x_mod x coordinate shift after alignment + * @param y_mod y coordinate shift after alignment + */ +void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_mod, lv_coord_t y_mod); + /** * Realign the object based on the last `lv_obj_align` parameters. * @param obj pointer to an object