From 285ff7d3b428af50b94cb9ab11a038d79522e676 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 24 Feb 2019 06:24:36 +0100 Subject: [PATCH 1/3] lv_cont: improve fit with TIGHT, FLOOD, FILL --- lv_core/lv_obj.c | 7 ++ lv_core/lv_obj.h | 1 + lv_misc/lv_ll.c | 15 +++ lv_misc/lv_ll.h | 7 ++ lv_objx/lv_btn.h | 74 ++++++++++++--- lv_objx/lv_cb.c | 2 +- lv_objx/lv_cont.c | 212 ++++++++++++++++++++++++++++-------------- lv_objx/lv_cont.h | 78 +++++++++++++--- lv_objx/lv_ddlist.c | 11 +-- lv_objx/lv_ddlist.h | 5 +- lv_objx/lv_list.c | 3 +- lv_objx/lv_mbox.c | 4 +- lv_objx/lv_page.c | 14 +-- lv_objx/lv_page.h | 83 +++++++++++++---- lv_objx/lv_roller.c | 6 +- lv_objx/lv_ta.c | 13 +-- lv_objx/lv_tabview.c | 2 +- lv_objx/lv_tileview.c | 2 +- 18 files changed, 388 insertions(+), 151 deletions(-) diff --git a/lv_core/lv_obj.c b/lv_core/lv_obj.c index 41049bdfd..16e7433f2 100644 --- a/lv_core/lv_obj.c +++ b/lv_core/lv_obj.c @@ -624,6 +624,13 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) lv_obj_t * par = lv_obj_get_parent(obj); if(par != NULL) par->signal_func(par, LV_SIGNAL_CHILD_CHG, obj); + + /*Tell the children the paren's size has changed*/ + lv_obj_t * i; + LL_READ(obj->child_ll, i) { + i->signal_func(i, LV_SIGNAL_PARENT_SIZE_CHG, NULL); + } + /*Invalidate the new area*/ lv_obj_invalidate(obj); diff --git a/lv_core/lv_obj.h b/lv_core/lv_obj.h index cfd8a8ac3..c5e6068a3 100644 --- a/lv_core/lv_obj.h +++ b/lv_core/lv_obj.h @@ -89,6 +89,7 @@ enum LV_SIGNAL_CLEANUP, LV_SIGNAL_CHILD_CHG, LV_SIGNAL_CORD_CHG, + LV_SIGNAL_PARENT_SIZE_CHG, LV_SIGNAL_STYLE_CHG, LV_SIGNAL_REFR_EXT_SIZE, LV_SIGNAL_LANG_CHG, diff --git a/lv_misc/lv_ll.c b/lv_misc/lv_ll.c index 43d8847d4..297b5a5f0 100644 --- a/lv_misc/lv_ll.c +++ b/lv_misc/lv_ll.c @@ -340,6 +340,21 @@ void lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after) if(n_after == NULL) ll_p->tail = n_act; } +/** + * Check if a linked list is empty + * @param ll_p pointer to a linked list + * @return true: the linked list is empty; false: not empty + */ +bool lv_ll_is_empty(lv_ll_t * ll_p) +{ + if(ll_p == NULL) return true; + + if(ll_p->head == NULL && ll_p->tail == NULL) return true; + + return false; +} + + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lv_misc/lv_ll.h b/lv_misc/lv_ll.h index 086ba4057..b49d0ea36 100644 --- a/lv_misc/lv_ll.h +++ b/lv_misc/lv_ll.h @@ -17,6 +17,7 @@ extern "C" { #include "lv_mem.h" #include #include +#include /********************* * DEFINES @@ -130,6 +131,12 @@ void * lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act); */ void lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after); +/** + * Check if a linked list is empty + * @param ll_p pointer to a linked list + * @return true: the linked list is empty; false: not empty + */ +bool lv_ll_is_empty(lv_ll_t * ll_p); /********************** * MACROS **********************/ diff --git a/lv_objx/lv_btn.h b/lv_objx/lv_btn.h index 097aff32b..b8e6932f8 100644 --- a/lv_objx/lv_btn.h +++ b/lv_objx/lv_btn.h @@ -142,15 +142,40 @@ static inline void lv_btn_set_layout(lv_obj_t * btn, lv_layout_t layout) } /** - * Enable the horizontal or vertical fit. - * The button size will be set to involve the children horizontally or vertically. + * Set the fit policy in all 4 directions separately. + * It tell how to change the button size automatically. * @param btn pointer to a button object - * @param hor_en true: enable the horizontal fit - * @param ver_en true: enable the vertical fit + * @param left left fit policy from `lv_fit_t` + * @param right right fit policy from `lv_fit_t` + * @param top bottom fit policy from `lv_fit_t` + * @param bottom bottom fit policy from `lv_fit_t` */ -static inline void lv_btn_set_fit(lv_obj_t * btn, bool hor_en, bool ver_en) +static inline void lv_btn_set_fit4(lv_obj_t * btn, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom) { - lv_cont_set_fit(btn, hor_en, ver_en); + lv_cont_set_fit4(btn, left, right, top, bottom); +} + +/** + * Set the fit policy horizontally and vertically separately. + * It tell how to change the button size automatically. + * @param btn pointer to a button object + * @param hot horizontal fit policy from `lv_fit_t` + * @param ver vertical fit policy from `lv_fit_t` + */ +static inline void lv_btn_set_fit2(lv_obj_t * btn, lv_fit_t hor, lv_fit_t ver) +{ + lv_cont_set_fit2(btn, hor, ver); +} + +/** + * Set the fit policy in all 4 direction at once. + * It tell how to change the button size automatically. + * @param btn pointer to a button object + * @param fit fit policy from `lv_fit_t` + */ +static inline void lv_btn_set_fit(lv_obj_t * cont, lv_fit_t fit) +{ + lv_cont_set_fit(cont, fit); } /** @@ -218,25 +243,46 @@ static inline lv_layout_t lv_btn_get_layout(const lv_obj_t * btn) } /** - * Get horizontal fit enable attribute of a button + * Get the left fit mode * @param btn pointer to a button object - * @return true: horizontal fit is enabled; false: disabled + * @return an element of `lv_fit_t` */ -static inline bool lv_btn_get_hor_fit(const lv_obj_t * btn) +static inline lv_fit_t lv_btn_get_fit_left(const lv_obj_t * btn) { - return lv_cont_get_hor_fit(btn); + return lv_cont_get_fit_left(btn); } /** - * Get vertical fit enable attribute of a container + * Get the right fit mode * @param btn pointer to a button object - * @return true: vertical fit is enabled; false: disabled + * @return an element of `lv_fit_t` */ -static inline bool lv_btn_get_ver_fit(const lv_obj_t * btn) +static inline lv_fit_t lv_btn_get_fit_right(const lv_obj_t * btn) { - return lv_cont_get_ver_fit(btn); + return lv_cont_get_fit_right(btn); } +/** + * Get the top fit mode + * @param btn pointer to a button object + * @return an element of `lv_fit_t` + */ +static inline lv_fit_t lv_btn_get_fit_top(const lv_obj_t * btn) +{ + return lv_cont_get_fit_top(btn); +} + +/** + * Get the bottom fit mode + * @param btn pointer to a button object + * @return an element of `lv_fit_t` + */ +static inline lv_fit_t lv_btn_get_fit_bottom(const lv_obj_t * btn) +{ + return lv_cont_get_fit_bottom(btn); +} + + /** * Get time of the ink in effect (draw a circle on click to animate in the new state) * @param btn pointer to a button object diff --git a/lv_objx/lv_cb.c b/lv_objx/lv_cb.c index 7943ba6b2..e6fc49454 100644 --- a/lv_objx/lv_cb.c +++ b/lv_objx/lv_cb.c @@ -81,7 +81,7 @@ lv_obj_t * lv_cb_create(lv_obj_t * par, const lv_obj_t * copy) lv_cb_set_text(new_cb, "Check box"); lv_btn_set_layout(new_cb, LV_LAYOUT_ROW_M); - lv_btn_set_fit(new_cb, true, true); + lv_btn_set_fit(new_cb, LV_FIT_TIGHT); lv_btn_set_toggle(new_cb, true); lv_obj_set_protect(new_cb, LV_PROTECT_PRESS_LOST); diff --git a/lv_objx/lv_cont.c b/lv_objx/lv_cont.c index b6bbe0128..41255b789 100644 --- a/lv_objx/lv_cont.c +++ b/lv_objx/lv_cont.c @@ -78,8 +78,10 @@ lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy) if(ext == NULL) return NULL; lv_mem_assert(ext); - ext->hor_fit = 0; - ext->ver_fit = 0; + ext->fit_left = LV_FIT_NONE; + ext->fit_right = LV_FIT_NONE; + ext->fit_top = LV_FIT_NONE; + ext->fit_bottom = LV_FIT_NONE; ext->layout = LV_LAYOUT_OFF; lv_obj_set_signal_func(new_cont, lv_cont_signal); @@ -97,8 +99,10 @@ lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy) /*Copy an existing object*/ else { lv_cont_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->hor_fit = copy_ext->hor_fit; - ext->ver_fit = copy_ext->ver_fit; + ext->fit_left = copy_ext->fit_left; + ext->fit_right = copy_ext->fit_right; + ext->fit_top = copy_ext->fit_top; + ext->fit_bottom = copy_ext->fit_bottom; ext->layout = copy_ext->layout; /*Refresh the style with new signal function*/ @@ -107,7 +111,6 @@ lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy) LV_LOG_INFO("container created"); - return new_cont; } @@ -131,22 +134,31 @@ void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout) cont->signal_func(cont, LV_SIGNAL_CHILD_CHG, NULL); } - /** - * Enable the horizontal or vertical fit. - * The container size will be set to involve the children horizontally or vertically. + * Set the fit policy in all 4 directions separately. + * It tell how to change the container's size automatically. * @param cont pointer to a container object - * @param hor_en true: enable the horizontal fit - * @param ver_en true: enable the vertical fit + * @param left left fit policy from `lv_fit_t` + * @param right right fit policy from `lv_fit_t` + * @param top bottom fit policy from `lv_fit_t` + * @param bottom bottom fit policy from `lv_fit_t` */ -void lv_cont_set_fit(lv_obj_t * cont, bool hor_en, bool ver_en) +void lv_cont_set_fit4(lv_obj_t * cont, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom) { lv_obj_invalidate(cont); lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - if(ext->hor_fit == hor_en && ext->ver_fit == ver_en) return; + if(ext->fit_left == left && + ext->fit_right == right && + ext->fit_top == top && + ext->fit_bottom == bottom) + { + return; + } - ext->hor_fit = hor_en == false ? 0 : 1; - ext->ver_fit = ver_en == false ? 0 : 1; + ext->fit_left = left; + ext->fit_right = right; + ext->fit_top = top; + ext->fit_bottom = bottom; /*Send a signal to refresh the layout*/ cont->signal_func(cont, LV_SIGNAL_CHILD_CHG, NULL); @@ -168,25 +180,47 @@ lv_layout_t lv_cont_get_layout(const lv_obj_t * cont) } /** - * Get horizontal fit enable attribute of a container + * Get left fit mode of a container * @param cont pointer to a container object - * @return true: horizontal fit is enabled; false: disabled + * @return an element of `lv_fit_t` */ -bool lv_cont_get_hor_fit(const lv_obj_t * cont) +lv_fit_t lv_cont_get_fit_left(const lv_obj_t * cont) { lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - return ext->hor_fit == 0 ? false : true; + return ext->fit_left; } /** - * Get vertical fit enable attribute of a container + * Get right fit mode of a container * @param cont pointer to a container object - * @return true: vertical fit is enabled; false: disabled + * @return an element of `lv_fit_t` */ -bool lv_cont_get_ver_fit(const lv_obj_t * cont) +lv_fit_t lv_cont_get_fit_right(const lv_obj_t * cont) { lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - return ext->ver_fit == 0 ? false : true; + return ext->fit_right; +} + +/** + * Get top fit mode of a container + * @param cont pointer to a container object + * @return an element of `lv_fit_t` + */ +lv_fit_t lv_cont_get_fit_top(const lv_obj_t * cont) +{ + lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); + return ext->fit_top; +} + +/** + * Get bottom fit mode of a container + * @param cont pointer to a container object + * @return an element of `lv_fit_t` + */ +lv_fit_t lv_cont_get_fit_bottom(const lv_obj_t * cont) +{ + lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); + return ext->fit_bottom; } /** @@ -244,6 +278,10 @@ static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param) lv_cont_refr_layout(cont); lv_cont_refr_autofit(cont); } + } else if(sign == LV_SIGNAL_PARENT_SIZE_CHG) { + /*FLOOD and FILL fit needs to be refreshed if the parent size has changed*/ + lv_cont_refr_autofit(cont); + } else if(sign == LV_SIGNAL_GET_TYPE) { lv_obj_type_t * buf = param; uint8_t i; @@ -574,70 +612,106 @@ static void lv_cont_refr_autofit(lv_obj_t * cont) { lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - if(ext->hor_fit == 0 && - ext->ver_fit == 0) { + if(ext->fit_left == LV_FIT_NONE && + ext->fit_right == LV_FIT_NONE && + ext->fit_top == LV_FIT_NONE && + ext->fit_bottom == LV_FIT_NONE) + { return; } - lv_area_t new_cords; + lv_area_t tight_area; lv_area_t ori; lv_style_t * style = lv_obj_get_style(cont); lv_obj_t * i; lv_coord_t hpad = style->body.padding.hor; lv_coord_t vpad = style->body.padding.ver; + lv_obj_t * par = lv_obj_get_parent(cont); + lv_style_t * par_style = lv_obj_get_style(par); + lv_area_t flood_area; + lv_area_copy(&flood_area, &par->coords); + flood_area.x1 += par_style->body.padding.hor; + flood_area.x2 -= par_style->body.padding.hor; + flood_area.y1 += par_style->body.padding.ver; + flood_area.y2 -= par_style->body.padding.ver; + /*Search the side coordinates of the children*/ lv_obj_get_coords(cont, &ori); - lv_obj_get_coords(cont, &new_cords); + lv_obj_get_coords(cont, &tight_area); - new_cords.x1 = LV_COORD_MAX; - new_cords.y1 = LV_COORD_MAX; - new_cords.x2 = LV_COORD_MIN; - new_cords.y2 = LV_COORD_MIN; + bool has_children = lv_ll_is_empty(&cont->child_ll) ? false : true; - LL_READ(cont->child_ll, i) { - if(lv_obj_get_hidden(i) != false) continue; - new_cords.x1 = LV_MATH_MIN(new_cords.x1, i->coords.x1); - new_cords.y1 = LV_MATH_MIN(new_cords.y1, i->coords.y1); - new_cords.x2 = LV_MATH_MAX(new_cords.x2, i->coords.x2); - new_cords.y2 = LV_MATH_MAX(new_cords.y2, i->coords.y2); + if(has_children) { + tight_area.x1 = LV_COORD_MAX; + tight_area.y1 = LV_COORD_MAX; + tight_area.x2 = LV_COORD_MIN; + tight_area.y2 = LV_COORD_MIN; + + LL_READ(cont->child_ll, i) { + if(lv_obj_get_hidden(i) != false) continue; + tight_area.x1 = LV_MATH_MIN(tight_area.x1, i->coords.x1); + tight_area.y1 = LV_MATH_MIN(tight_area.y1, i->coords.y1); + tight_area.x2 = LV_MATH_MAX(tight_area.x2, i->coords.x2); + tight_area.y2 = LV_MATH_MAX(tight_area.y2, i->coords.y2); + } + + tight_area.x1 -= hpad; + tight_area.x2 += hpad; + tight_area.y1 -= vpad; + tight_area.y2 += vpad; } - /*If the value is not the init value then the page has >=1 child.*/ - if(new_cords.x1 != LV_COORD_MAX) { - if(ext->hor_fit != 0) { - new_cords.x1 -= hpad; - new_cords.x2 += hpad; - } else { - new_cords.x1 = cont->coords.x1; - new_cords.x2 = cont->coords.x2; - } - if(ext->ver_fit != 0) { - new_cords.y1 -= vpad; - new_cords.y2 += vpad; - } else { - new_cords.y1 = cont->coords.y1; - new_cords.y2 = cont->coords.y2; - } + lv_area_t new_area; + lv_area_copy(&new_area, &ori); - /*Do nothing if the coordinates are not changed*/ - if(cont->coords.x1 != new_cords.x1 || - cont->coords.y1 != new_cords.y1 || - cont->coords.x2 != new_cords.x2 || - cont->coords.y2 != new_cords.y2) { - - lv_obj_invalidate(cont); - lv_area_copy(&cont->coords, &new_cords); - lv_obj_invalidate(cont); - - /*Notify the object about its new coordinates*/ - cont->signal_func(cont, LV_SIGNAL_CORD_CHG, &ori); - - /*Inform the parent about the new coordinates*/ - lv_obj_t * par = lv_obj_get_parent(cont); - par->signal_func(par, LV_SIGNAL_CHILD_CHG, cont); - } + switch(ext->fit_left) { + case LV_FIT_TIGHT: new_area.x1 = tight_area.x1; break; + case LV_FIT_FLOOD: new_area.x1 = flood_area.x1; break; + case LV_FIT_FILL: new_area.x1 = has_children ? LV_MATH_MIN(tight_area.x1, flood_area.x1) : flood_area.x1; break; + default: break; } + + switch(ext->fit_right) { + case LV_FIT_TIGHT: new_area.x2 = tight_area.x2; break; + case LV_FIT_FLOOD: new_area.x2 = flood_area.x2; break; + case LV_FIT_FILL: new_area.x2 = has_children ? LV_MATH_MAX(tight_area.x2, flood_area.x2) : flood_area.x2; break; + default: break; + } + + switch(ext->fit_top) { + case LV_FIT_TIGHT: new_area.y1 = tight_area.y1; break; + case LV_FIT_FLOOD: new_area.y1 = flood_area.y1; break; + case LV_FIT_FILL: new_area.y1 = has_children ? LV_MATH_MIN(tight_area.y1, flood_area.y1) : flood_area.y1; break; + default: break; + } + + switch(ext->fit_bottom) { + case LV_FIT_TIGHT: new_area.y2 = tight_area.y2; break; + case LV_FIT_FLOOD: new_area.y2 = flood_area.y2; break; + case LV_FIT_FILL: new_area.y2 = has_children ? LV_MATH_MAX(tight_area.y2, flood_area.y2) : flood_area.y2; break; + default: break; + } + + /*Do nothing if the coordinates are not changed*/ + if(cont->coords.x1 != new_area.x1 || + cont->coords.y1 != new_area.y1 || + cont->coords.x2 != new_area.x2 || + cont->coords.y2 != new_area.y2) + { + + lv_obj_invalidate(cont); + lv_area_copy(&cont->coords, &new_area); + lv_obj_invalidate(cont); + + /*Notify the object about its new coordinates*/ + cont->signal_func(cont, LV_SIGNAL_CORD_CHG, &ori); + + /*Inform the parent about the new coordinates*/ + lv_obj_t * par = lv_obj_get_parent(cont); + par->signal_func(par, LV_SIGNAL_CHILD_CHG, cont); + } + } #endif diff --git a/lv_objx/lv_cont.h b/lv_objx/lv_cont.h index 3259c772f..7fa5370c2 100644 --- a/lv_objx/lv_cont.h +++ b/lv_objx/lv_cont.h @@ -47,13 +47,23 @@ enum }; typedef uint8_t lv_layout_t; + +typedef enum { + LV_FIT_NONE, + LV_FIT_TIGHT, + LV_FIT_FLOOD, + LV_FIT_FILL, +}lv_fit_t; + typedef struct { /*Inherited from 'base_obj' so no inherited ext. */ /*Ext. of ancestor*/ /*New data for this type */ - uint8_t layout :4; /*A layout from 'lv_cont_layout_t' enum*/ - uint8_t hor_fit :1; /*1: Enable horizontal fit to involve all children*/ - uint8_t ver_fit :1; /*1: Enable horizontal fit to involve all children*/ + uint8_t layout :4; /*A layout from 'lv_layout_t' enum*/ + uint8_t fit_left :2; /*A fit type from `lv_fit_t` enum */ + uint8_t fit_right :2; /*A fit type from `lv_fit_t` enum */ + uint8_t fit_top :2; /*A fit type from `lv_fit_t` enum */ + uint8_t fit_bottom :2; /*A fit type from `lv_fit_t` enum */ } lv_cont_ext_t; @@ -80,15 +90,41 @@ lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy); */ void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout); +/** + * Set the fit policy in all 4 directions separately. + * It tell how to change the container's size automatically. + * @param cont pointer to a container object + * @param left left fit policy from `lv_fit_t` + * @param right right fit policy from `lv_fit_t` + * @param top bottom fit policy from `lv_fit_t` + * @param bottom bottom fit policy from `lv_fit_t` + */ +void lv_cont_set_fit4(lv_obj_t * cont, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom); /** - * Enable the horizontal or vertical fit. - * The container size will be set to involve the children horizontally or vertically. + * Set the fit policy horizontally and vertically separately. + * It tell how to change the container's size automatically. * @param cont pointer to a container object - * @param hor_en true: enable the horizontal fit - * @param ver_en true: enable the vertical fit + * @param hot horizontal fit policy from `lv_fit_t` + * @param ver vertical fit policy from `lv_fit_t` */ -void lv_cont_set_fit(lv_obj_t * cont, bool hor_en, bool ver_en); +static inline void lv_cont_set_fit2(lv_obj_t * cont, lv_fit_t hor, lv_fit_t ver) +{ + lv_cont_set_fit4(cont, hor, hor, ver, ver); +} + + +/** + * Set the fit policyin all 4 direction at once. + * It tell how to change the container's size automatically. + * @param cont pointer to a container object + * @param fit fit policy from `lv_fit_t` + */ +static inline void lv_cont_set_fit(lv_obj_t * cont, lv_fit_t fit) +{ + lv_cont_set_fit4(cont, fit, fit, fit, fit); +} + /** * Set the style of a container @@ -112,18 +148,32 @@ static inline void lv_cont_set_style(lv_obj_t *cont, lv_style_t * style) lv_layout_t lv_cont_get_layout(const lv_obj_t * cont); /** - * Get horizontal fit enable attribute of a container + * Get left fit mode of a container * @param cont pointer to a container object - * @return true: horizontal fit is enabled; false: disabled + * @return an element of `lv_fit_t` */ -bool lv_cont_get_hor_fit(const lv_obj_t * cont); +lv_fit_t lv_cont_get_fit_left(const lv_obj_t * cont); /** - * Get vertical fit enable attribute of a container + * Get right fit mode of a container * @param cont pointer to a container object - * @return true: vertical fit is enabled; false: disabled + * @return an element of `lv_fit_t` */ -bool lv_cont_get_ver_fit(const lv_obj_t * cont); +lv_fit_t lv_cont_get_fit_right(const lv_obj_t * cont); + +/** + * Get top fit mode of a container + * @param cont pointer to a container object + * @return an element of `lv_fit_t` + */ +lv_fit_t lv_cont_get_fit_top(const lv_obj_t * cont); + +/** + * Get bottom fit mode of a container + * @param cont pointer to a container object + * @return an element of `lv_fit_t` + */ +lv_fit_t lv_cont_get_fit_bottom(const lv_obj_t * cont); /** diff --git a/lv_objx/lv_ddlist.c b/lv_objx/lv_ddlist.c index bd506c705..96ff47e6e 100644 --- a/lv_objx/lv_ddlist.c +++ b/lv_objx/lv_ddlist.c @@ -104,10 +104,10 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy) if(copy == NULL) { lv_obj_t * scrl = lv_page_get_scrl(new_ddlist); lv_obj_set_drag(scrl, false); - lv_page_set_scrl_fit(new_ddlist, true, true); + lv_page_set_scrl_fit2(new_ddlist, LV_FIT_TIGHT, LV_FIT_TIGHT); ext->label = lv_label_create(new_ddlist, NULL); - lv_cont_set_fit(new_ddlist, true, false); + lv_cont_set_fit2(new_ddlist, LV_FIT_TIGHT, LV_FIT_NONE); lv_page_set_rel_action(new_ddlist, lv_ddlist_release_action); lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_DRAG); lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_HIDE); @@ -238,12 +238,11 @@ void lv_ddlist_set_fix_height(lv_obj_t * ddlist, lv_coord_t h) /** * Enable or disable the horizontal fit to the content * @param ddlist pointer to a drop down list - * @param en true: enable auto fit; false: disable auto fit + * @param fit fit mode fron `lv_fit_t` (Typically `LV_FIT_NONE` or `LV_FIT_TIGHT`) */ -void lv_ddlist_set_hor_fit(lv_obj_t * ddlist, bool en) +void lv_ddlist_set_hor_fit(lv_obj_t * ddlist, lv_fit_t fit) { - lv_cont_set_fit(ddlist, en, lv_cont_get_ver_fit(ddlist)); - lv_page_set_scrl_fit(ddlist, en, lv_page_get_scrl_fit_ver(ddlist)); + lv_cont_set_fit2(ddlist, fit, lv_cont_get_fit_top(ddlist)); lv_ddlist_refr_size(ddlist, false); } diff --git a/lv_objx/lv_ddlist.h b/lv_objx/lv_ddlist.h index a0aa62cbb..8d3a6599f 100644 --- a/lv_objx/lv_ddlist.h +++ b/lv_objx/lv_ddlist.h @@ -117,12 +117,13 @@ void lv_ddlist_set_action(lv_obj_t * ddlist, lv_action_t action); */ void lv_ddlist_set_fix_height(lv_obj_t * ddlist, lv_coord_t h); + /** * Enable or disable the horizontal fit to the content * @param ddlist pointer to a drop down list - * @param en true: enable auto fit; false: disable auto fit + * @param fit fit mode fron `lv_fit_t` (Typically `LV_FIT_NONE` or `LV_FIT_TIGHT`) */ -void lv_ddlist_set_hor_fit(lv_obj_t * ddlist, bool en); +void lv_ddlist_set_hor_fit(lv_obj_t * ddlist, lv_fit_t fit); /** * Set the scroll bar mode of a drop down list diff --git a/lv_objx/lv_list.c b/lv_objx/lv_list.c index 9bfdb2379..04cf51f06 100644 --- a/lv_objx/lv_list.c +++ b/lv_objx/lv_list.c @@ -102,6 +102,7 @@ lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy) /*Init the new list object*/ if(copy == NULL) { + lv_page_set_scrl_fit2(new_list, LV_FIT_FLOOD, LV_FIT_TIGHT); lv_obj_set_size(new_list, 2 * LV_DPI, 3 * LV_DPI); lv_page_set_scrl_layout(new_list, LV_LIST_LAYOUT_DEF); lv_list_set_sb_mode(new_list, LV_SB_MODE_DRAG); @@ -198,7 +199,7 @@ lv_obj_t * lv_list_add(lv_obj_t * list, const void * img_src, const char * txt, lv_btn_set_action(liste, LV_BTN_ACTION_CLICK, rel_action); lv_page_glue_obj(liste, true); lv_btn_set_layout(liste, LV_LAYOUT_ROW_M); - lv_btn_set_fit(liste, false, true); + lv_btn_set_fit2(liste, LV_FIT_FLOOD, LV_FIT_TIGHT); lv_obj_set_protect(liste, LV_PROTECT_PRESS_LOST); lv_obj_set_signal_func(liste, lv_list_btn_signal); diff --git a/lv_objx/lv_mbox.c b/lv_objx/lv_mbox.c index 06f15d015..1f09c1dbd 100644 --- a/lv_objx/lv_mbox.c +++ b/lv_objx/lv_mbox.c @@ -90,7 +90,7 @@ lv_obj_t * lv_mbox_create(lv_obj_t * par, const lv_obj_t * copy) lv_label_set_text(ext->text, "Message"); lv_cont_set_layout(new_mbox, LV_LAYOUT_COL_M); - lv_cont_set_fit(new_mbox, false, true); + lv_cont_set_fit2(new_mbox, LV_FIT_NONE, LV_FIT_TIGHT); lv_obj_set_width(new_mbox, LV_HOR_RES / 2); lv_obj_align(new_mbox, NULL, LV_ALIGN_CENTER, 0, 0); @@ -220,7 +220,7 @@ void lv_mbox_start_auto_close(lv_obj_t * mbox, uint16_t delay) lv_obj_animate(mbox, LV_ANIM_GROW_V | LV_ANIM_OUT, ext->anim_time, delay, lv_mbox_close_end_cb); /*Disable fit to let shrinking work*/ - lv_cont_set_fit(mbox, false, false); + lv_cont_set_fit(mbox, LV_FIT_NONE); } else { lv_obj_animate(mbox, LV_ANIM_NONE, ext->anim_time, delay, lv_mbox_close_end_cb); } diff --git a/lv_objx/lv_page.c b/lv_objx/lv_page.c index e36ca7f48..26d517cf6 100644 --- a/lv_objx/lv_page.c +++ b/lv_objx/lv_page.c @@ -103,7 +103,7 @@ lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_drag(ext->scrl, true); lv_obj_set_drag_throw(ext->scrl, true); lv_obj_set_protect(ext->scrl, LV_PROTECT_PARENT | LV_PROTECT_PRESS_LOST); - lv_cont_set_fit(ext->scrl, false, true); + lv_cont_set_fit4(ext->scrl, LV_FIT_NONE, LV_FIT_FILL, LV_FIT_NONE, LV_FIT_FILL); /* Add the signal function only if 'scrolling' is created * because everything has to be ready before any signal is received*/ @@ -765,7 +765,6 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) if(res != LV_RES_OK) return res; lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - lv_style_t * style = lv_obj_get_style(page); lv_obj_t * child; if(sign == LV_SIGNAL_CHILD_CHG) { /*Automatically move children to the scrollable object*/ child = lv_obj_get_child(page, NULL); @@ -779,12 +778,7 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) } } } else if(sign == LV_SIGNAL_STYLE_CHG) { - /*If no hor_fit enabled set the scrollable's width to the page's width*/ - if(lv_cont_get_hor_fit(ext->scrl) == false) { - lv_obj_set_width(ext->scrl, lv_obj_get_width(page) - 2 * style->body.padding.hor); - } else { - ext->scrl->signal_func(ext->scrl, LV_SIGNAL_CORD_CHG, &ext->scrl->coords); - } + ext->scrl->signal_func(ext->scrl, LV_SIGNAL_CORD_CHG, &ext->scrl->coords); /*The scrollbars are important only if they are visible now*/ if(ext->sb.hor_draw || ext->sb.ver_draw) lv_page_sb_refresh(page); @@ -796,10 +790,6 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) if(ext->scrl != NULL && (lv_obj_get_width(page) != lv_area_get_width(param) || lv_obj_get_height(page) != lv_area_get_height(param))) { /*If no hor_fit enabled set the scrollable's width to the page's width*/ - if(lv_cont_get_hor_fit(ext->scrl) == false) { - lv_obj_set_width(ext->scrl, lv_obj_get_width(page) - 2 * style->body.padding.hor); - } - ext->scrl->signal_func(ext->scrl, LV_SIGNAL_CORD_CHG, &ext->scrl->coords); /*The scrollbars are important only if they are visible now*/ diff --git a/lv_objx/lv_page.h b/lv_objx/lv_page.h index 32f6104db..4382aafc9 100644 --- a/lv_objx/lv_page.h +++ b/lv_objx/lv_page.h @@ -173,17 +173,42 @@ void lv_page_set_scroll_propagation(lv_obj_t * page, bool en); */ void lv_page_set_edge_flash(lv_obj_t * page, bool en); + /** - * Set the fit attribute of the scrollable part of a page. - * It means it can set its size automatically to involve all children. - * (Can be set separately horizontally and vertically) + * Set the fit policy in all 4 directions separately. + * It tell how to change the page size automatically. * @param page pointer to a page object - * @param hor_en true: enable horizontal fit - * @param ver_en true: enable vertical fit + * @param left left fit policy from `lv_fit_t` + * @param right right fit policy from `lv_fit_t` + * @param top bottom fit policy from `lv_fit_t` + * @param bottom bottom fit policy from `lv_fit_t` */ -static inline void lv_page_set_scrl_fit(lv_obj_t *page, bool hor_en, bool ver_en) +static inline void lv_page_set_scrl_fit4(lv_obj_t * page, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom) { - lv_cont_set_fit(lv_page_get_scrl(page), hor_en, ver_en); + lv_cont_set_fit4(lv_page_get_scrl(page), left, right, top, bottom); +} + +/** + * Set the fit policy horizontally and vertically separately. + * It tell how to change the page size automatically. + * @param page pointer to a page object + * @param hot horizontal fit policy from `lv_fit_t` + * @param ver vertical fit policy from `lv_fit_t` + */ +static inline void lv_page_set_scrl_fit2(lv_obj_t * page, lv_fit_t hor, lv_fit_t ver) +{ + lv_cont_set_fit2(lv_page_get_scrl(page), hor, ver); +} + +/** + * Set the fit policyin all 4 direction at once. + * It tell how to change the page size automatically. + * @param page pointer to a button object + * @param fit fit policy from `lv_fit_t` + */ +static inline void lv_page_set_scrl_fit(lv_obj_t * page, lv_fit_t fit) +{ + lv_cont_set_fit(lv_page_get_scrl(page), fit); } /** @@ -303,23 +328,43 @@ static inline lv_layout_t lv_page_get_scrl_layout(const lv_obj_t * page) } /** -* Get horizontal fit attribute of the scrollable part of a page -* @param page pointer to a page object -* @return true: horizontal fit is enabled; false: disabled -*/ -static inline bool lv_page_get_scrl_hor_fit(const lv_obj_t * page) + * Get the left fit mode + * @param page pointer to a page object + * @return an element of `lv_fit_t` + */ +static inline lv_fit_t lv_page_get_scrl_fit_left(const lv_obj_t * page) { - return lv_cont_get_hor_fit(lv_page_get_scrl(page)); + return lv_cont_get_fit_left(lv_page_get_scrl(page)); } /** -* Get vertical fit attribute of the scrollable part of a page -* @param page pointer to a page object -* @return true: vertical fit is enabled; false: disabled -*/ -static inline bool lv_page_get_scrl_fit_ver(const lv_obj_t * page) + * Get the right fit mode + * @param page pointer to a page object + * @return an element of `lv_fit_t` + */ +static inline lv_fit_t lv_page_get_scrl_fit_right(const lv_obj_t * page) { - return lv_cont_get_ver_fit(lv_page_get_scrl(page)); + return lv_cont_get_fit_right(lv_page_get_scrl(page)); +} + +/** + * Get the top fit mode + * @param page pointer to a page object + * @return an element of `lv_fit_t` + */ +static inline lv_fit_t lv_page_get_scrl_get_fit_top(const lv_obj_t * page) +{ + return lv_cont_get_fit_top(lv_page_get_scrl(page)); +} + +/** + * Get the bottom fit mode + * @param page pointer to a page object + * @return an element of `lv_fit_t` + */ +static inline lv_fit_t lv_page_get_scrl_fit_bottom(const lv_obj_t * page) +{ + return lv_cont_get_fit_bottom(lv_page_get_scrl(page)); } /** diff --git a/lv_objx/lv_roller.c b/lv_objx/lv_roller.c index 1f8a75e2e..cb5960d20 100644 --- a/lv_objx/lv_roller.c +++ b/lv_objx/lv_roller.c @@ -84,8 +84,8 @@ lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy) if(copy == NULL) { lv_obj_t * scrl = lv_page_get_scrl(new_roller); lv_obj_set_drag(scrl, true); /*In ddlist is might be disabled*/ - lv_page_set_rel_action(new_roller, NULL); /*Roller don't uses it (like ddlist)*/ - lv_page_set_scrl_fit(new_roller, true, false); /*Height is specified directly*/ + lv_page_set_rel_action(new_roller, NULL); /*Roller don't uses it (like ddlist)*/ + lv_page_set_scrl_fit2(new_roller, LV_FIT_TIGHT, LV_FIT_NONE); /*Height is specified directly*/ lv_ddlist_open(new_roller, false); lv_ddlist_set_anim_time(new_roller, LV_ROLLER_ANIM_TIME); lv_roller_set_visible_row_count(new_roller, 3); @@ -209,7 +209,7 @@ lv_label_align_t lv_roller_get_align(const lv_obj_t * roller) */ bool lv_roller_get_hor_fit(const lv_obj_t * roller) { - return lv_page_get_scrl_hor_fit(roller); + return lv_page_get_scrl_fit_left(roller); } /** diff --git a/lv_objx/lv_ta.c b/lv_objx/lv_ta.c index 6ec094b7d..43e12c072 100644 --- a/lv_objx/lv_ta.c +++ b/lv_objx/lv_ta.c @@ -115,6 +115,8 @@ lv_obj_t * lv_ta_create(lv_obj_t * par, const lv_obj_t * copy) /*Init the new text area object*/ if(copy == NULL) { + lv_page_set_scrl_fit2(new_ta, LV_FIT_FLOOD, LV_FIT_TIGHT); + ext->label = lv_label_create(new_ta, NULL); lv_obj_set_design_func(ext->page.scrl, lv_ta_scrollable_design); @@ -607,7 +609,7 @@ void lv_ta_set_one_line(lv_obj_t * ta, bool en) lv_coord_t font_h = lv_font_get_height(style_label->text.font); ext->one_line = 1; - lv_page_set_scrl_fit(ta, true, true); + lv_page_set_scrl_fit2(ta, LV_FIT_TIGHT, LV_FIT_FLOOD); lv_obj_set_height(ta, font_h + (style_ta->body.padding.ver + style_scrl->body.padding.ver) * 2); lv_label_set_long_mode(ext->label, LV_LABEL_LONG_EXPAND); if(ext->placeholder) lv_label_set_long_mode(ext->placeholder, LV_LABEL_LONG_EXPAND); @@ -616,7 +618,7 @@ void lv_ta_set_one_line(lv_obj_t * ta, bool en) lv_style_t * style_ta = lv_obj_get_style(ta); ext->one_line = 0; - lv_page_set_scrl_fit(ta, false, true); + lv_page_set_scrl_fit2(ta, LV_FIT_FLOOD, LV_FIT_TIGHT); lv_label_set_long_mode(ext->label, LV_LABEL_LONG_BREAK); if(ext->placeholder) lv_label_set_long_mode(ext->placeholder, LV_LABEL_LONG_BREAK); @@ -645,19 +647,18 @@ void lv_ta_set_text_align(lv_obj_t * ta, lv_label_align_t align) /*Normal left align. Just let the text expand*/ if(align == LV_LABEL_ALIGN_LEFT) { lv_label_set_long_mode(label, LV_LABEL_LONG_EXPAND); - lv_page_set_scrl_fit(ta, true, false); + lv_page_set_scrl_fit2(ta, LV_FIT_TIGHT, LV_FIT_FLOOD); lv_label_set_align(label, align); } /*Else use fix label width equal to the Text area width*/ else { lv_label_set_long_mode(label, LV_LABEL_LONG_CROP); - lv_page_set_scrl_fit(ta, false, false); - lv_page_set_scrl_width(ta, 1); /*To refresh the scrollable's width*/ + lv_page_set_scrl_fit2(ta, LV_FIT_FLOOD, LV_FIT_FLOOD); lv_label_set_align(label, align); lv_style_t * bg_style = lv_ta_get_style(ta, LV_TA_STYLE_BG); - lv_obj_set_width(label, lv_obj_get_width(ta) - 2 * bg_style->body.padding.hor); + lv_obj_set_width(label, lv_page_get_fit_width(ta)); } } diff --git a/lv_objx/lv_tabview.c b/lv_objx/lv_tabview.c index 9c66e6224..1ba09268f 100644 --- a/lv_objx/lv_tabview.c +++ b/lv_objx/lv_tabview.c @@ -120,7 +120,7 @@ lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_click(ext->indic, false); ext->content = lv_cont_create(new_tabview, NULL); - lv_cont_set_fit(ext->content, true, false); + lv_cont_set_fit2(ext->content, LV_FIT_TIGHT, LV_FIT_NONE); lv_cont_set_layout(ext->content, LV_LAYOUT_ROW_T); lv_cont_set_style(ext->content, &lv_style_transp_tight); lv_obj_set_height(ext->content, LV_VER_RES - lv_obj_get_height(ext->btns)); diff --git a/lv_objx/lv_tileview.c b/lv_objx/lv_tileview.c index c6c0ed98a..9528a17ed 100644 --- a/lv_objx/lv_tileview.c +++ b/lv_objx/lv_tileview.c @@ -91,7 +91,7 @@ lv_obj_t * lv_tileview_create(lv_obj_t * par, const lv_obj_t * copy) if(copy == NULL) { lv_obj_set_size(new_tileview, LV_HOR_RES, LV_VER_RES); lv_obj_set_drag_throw(lv_page_get_scrl(new_tileview), false); - lv_page_set_scrl_fit(new_tileview, true, true); + lv_page_set_scrl_fit(new_tileview, LV_FIT_TIGHT); /*Set the default styles*/ lv_theme_t * th = lv_theme_get_current(); if(th) { From ddbd8386d2b9b77aa9474ede5abee0393ba60a00 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 24 Feb 2019 06:41:00 +0100 Subject: [PATCH 2/3] lv_page: fixes when child is added --- lv_objx/lv_cont.h | 8 ++++---- lv_objx/lv_page.c | 10 +++++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lv_objx/lv_cont.h b/lv_objx/lv_cont.h index 7fa5370c2..cf78574b5 100644 --- a/lv_objx/lv_cont.h +++ b/lv_objx/lv_cont.h @@ -49,10 +49,10 @@ typedef uint8_t lv_layout_t; typedef enum { - LV_FIT_NONE, - LV_FIT_TIGHT, - LV_FIT_FLOOD, - LV_FIT_FILL, + LV_FIT_NONE, /*Do not change the size automatically*/ + LV_FIT_TIGHT, /*Involve the children*/ + LV_FIT_FLOOD, /*Align the size to the parent's edge*/ + LV_FIT_FILL, /*Align the size to the parent's edge first but if there is an object out of it then involve it*/ }lv_fit_t; typedef struct diff --git a/lv_objx/lv_page.c b/lv_objx/lv_page.c index 26d517cf6..46b9a2c33 100644 --- a/lv_objx/lv_page.c +++ b/lv_objx/lv_page.c @@ -103,7 +103,7 @@ lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_drag(ext->scrl, true); lv_obj_set_drag_throw(ext->scrl, true); lv_obj_set_protect(ext->scrl, LV_PROTECT_PARENT | LV_PROTECT_PRESS_LOST); - lv_cont_set_fit4(ext->scrl, LV_FIT_NONE, LV_FIT_FILL, LV_FIT_NONE, LV_FIT_FILL); + lv_cont_set_fit4(ext->scrl, LV_FIT_FILL, LV_FIT_FILL, LV_FIT_FILL, LV_FIT_FILL); /* Add the signal function only if 'scrolling' is created * because everything has to be ready before any signal is received*/ @@ -772,6 +772,14 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) if(lv_obj_is_protected(child, LV_PROTECT_PARENT) == false) { lv_obj_t * tmp = child; child = lv_obj_get_child(page, child); /*Get the next child before move this*/ + + /*Reposition the child to take padding into account*/ + lv_style_t * style = lv_page_get_style(page, LV_PAGE_STYLE_SCRL); + child->coords.x1 += style->body.padding.hor; + child->coords.x2 += style->body.padding.hor; + child->coords.y1 += style->body.padding.ver; + child->coords.y2 += style->body.padding.ver; + lv_obj_set_parent(tmp, ext->scrl); } else { child = lv_obj_get_child(page, child); From 9141d95865a84b0d225b3d293d8803e10a414de7 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 24 Feb 2019 07:06:22 +0100 Subject: [PATCH 3/3] lv_cont: inform children about parent size change on autofit --- lv_core/lv_obj.c | 3 +-- lv_objx/lv_cont.c | 6 ++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lv_core/lv_obj.c b/lv_core/lv_obj.c index 16e7433f2..914ef64de 100644 --- a/lv_core/lv_obj.c +++ b/lv_core/lv_obj.c @@ -624,8 +624,7 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) lv_obj_t * par = lv_obj_get_parent(obj); if(par != NULL) par->signal_func(par, LV_SIGNAL_CHILD_CHG, obj); - - /*Tell the children the paren's size has changed*/ + /*Tell the children the parent's size has changed*/ lv_obj_t * i; LL_READ(obj->child_ll, i) { i->signal_func(i, LV_SIGNAL_PARENT_SIZE_CHG, NULL); diff --git a/lv_objx/lv_cont.c b/lv_objx/lv_cont.c index 41255b789..f45a9cb01 100644 --- a/lv_objx/lv_cont.c +++ b/lv_objx/lv_cont.c @@ -710,6 +710,12 @@ static void lv_cont_refr_autofit(lv_obj_t * cont) /*Inform the parent about the new coordinates*/ lv_obj_t * par = lv_obj_get_parent(cont); par->signal_func(par, LV_SIGNAL_CHILD_CHG, cont); + + /*Tell the children the parent's size has changed*/ + lv_obj_t * i; + LL_READ(cont->child_ll, i) { + i->signal_func(i, LV_SIGNAL_PARENT_SIZE_CHG, NULL); + } } }