mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
minor fixes
This commit is contained in:
parent
872bbc7e3e
commit
9fc88b6535
@ -20,8 +20,8 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_dir_t main_dir, lv_coord_t max_size, lv_coord_t * grow_unit, lv_coord_t * track_cross_size);
|
||||
static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * item_last, lv_dir_t main_dir, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t track_size, lv_coord_t grow_unit);
|
||||
static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coord_t max_size, lv_coord_t * grow_unit, lv_coord_t * track_cross_size);
|
||||
static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * item_last, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t track_size, lv_coord_t grow_unit);
|
||||
static void place_content(lv_coord_t place, lv_coord_t max_size, lv_coord_t track_size, lv_coord_t track_cnt, lv_coord_t * start_pos, lv_coord_t * gap);
|
||||
|
||||
/**********************
|
||||
@ -38,10 +38,21 @@ static void place_content(lv_coord_t place, lv_coord_t max_size, lv_coord_t trac
|
||||
|
||||
void lv_obj_set_flex_cont(lv_obj_t * obj, lv_flex_dir_t flex_dir, lv_flex_place_t flex_place)
|
||||
{
|
||||
if(obj->flex_dir == flex_dir) return;
|
||||
if(obj->flex_cont.dir == flex_dir && obj->flex_cont.place == flex_place) return;
|
||||
|
||||
obj->flex_cont.dir = flex_dir;
|
||||
obj->flex_cont.place = flex_place;
|
||||
|
||||
_lv_flex_refresh(obj);
|
||||
}
|
||||
|
||||
void lv_obj_set_flex_gap(lv_obj_t * obj, lv_coord_t gap)
|
||||
{
|
||||
|
||||
if(obj->flex_cont.gap == gap) return;
|
||||
|
||||
obj->flex_cont.gap = gap;
|
||||
|
||||
obj->flex_dir = flex_dir;
|
||||
obj->flex_place = flex_place;
|
||||
_lv_flex_refresh(obj);
|
||||
}
|
||||
|
||||
@ -53,18 +64,24 @@ void lv_obj_set_flex_item(lv_obj_t * obj, lv_flex_place_t place)
|
||||
|
||||
void _lv_flex_refresh(lv_obj_t * cont)
|
||||
{
|
||||
if(cont->flex_dir == LV_FLEX_DIR_NONE) return;
|
||||
|
||||
lv_dir_t main_dir = cont->flex_dir & LV_FLEX_DIR_ROW ? LV_DIR_HOR : LV_DIR_VER;
|
||||
if(cont->flex_cont.dir == LV_FLEX_DIR_NONE) return;
|
||||
|
||||
lv_flex_dir_t dir = cont->flex_cont.dir;
|
||||
bool row = dir == LV_FLEX_DIR_ROW ? true : false;
|
||||
/*Count the grow units and free space*/
|
||||
lv_coord_t max_main_size = (main_dir == LV_DIR_HOR ? lv_obj_get_width_fit(cont) : lv_obj_get_height_fit(cont));
|
||||
lv_coord_t max_main_size = (row ? lv_obj_get_width_fit(cont) : lv_obj_get_height_fit(cont));
|
||||
lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont, LV_OBJ_PART_MAIN) - lv_obj_get_scroll_left(cont);
|
||||
lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont, LV_OBJ_PART_MAIN) - lv_obj_get_scroll_top(cont);
|
||||
|
||||
lv_coord_t * cross_pos = (main_dir == LV_DIR_HOR ? &abs_y : &abs_x);
|
||||
lv_coord_t * cross_pos = (dir == LV_FLEX_DIR_ROW ? &abs_y : &abs_x);
|
||||
|
||||
lv_coord_t place = cont->flex_cont.place;
|
||||
if((row && cont->h_set == LV_SIZE_AUTO) ||
|
||||
(!row && cont->w_set == LV_SIZE_AUTO))
|
||||
{
|
||||
place = LV_FLEX_START;
|
||||
}
|
||||
|
||||
lv_coord_t place = cont->flex_place;
|
||||
lv_coord_t all_track_size = 0;
|
||||
lv_coord_t gap = 0;
|
||||
uint32_t row_cnt = 0;
|
||||
@ -72,29 +89,29 @@ void _lv_flex_refresh(lv_obj_t * cont)
|
||||
lv_coord_t track_size;
|
||||
lv_obj_t * track_first_item;
|
||||
lv_obj_t * next_track_first_item;
|
||||
bool rev = cont->flex_dir & LV_FLEX_REVERSE;
|
||||
bool rev = cont->flex_cont.dir & LV_FLEX_REVERSE;
|
||||
|
||||
if(place != LV_FLEX_START) {
|
||||
track_first_item = rev ? _lv_ll_get_head(&cont->child_ll) : _lv_ll_get_tail(&cont->child_ll);
|
||||
|
||||
while(track_first_item) {
|
||||
/*Search the first item of the next row */
|
||||
next_track_first_item = find_track_end(cont, track_first_item, main_dir, max_main_size, &grow_unit, &track_size);
|
||||
next_track_first_item = find_track_end(cont, track_first_item, max_main_size, &grow_unit, &track_size);
|
||||
all_track_size += track_size;
|
||||
row_cnt++;
|
||||
track_first_item = next_track_first_item;
|
||||
}
|
||||
|
||||
lv_coord_t max_cross_size = (main_dir == LV_DIR_HOR ? lv_obj_get_height_fit(cont) : lv_obj_get_width_fit(cont));
|
||||
lv_coord_t max_cross_size = (row ? lv_obj_get_height_fit(cont) : lv_obj_get_width_fit(cont));
|
||||
place_content(place, max_cross_size, all_track_size,row_cnt, cross_pos, &gap);
|
||||
}
|
||||
|
||||
track_first_item = rev ? _lv_ll_get_head(&cont->child_ll) : _lv_ll_get_tail(&cont->child_ll);
|
||||
while(track_first_item) {
|
||||
/*Search the first item of the next row */
|
||||
next_track_first_item = find_track_end(cont, track_first_item, main_dir, max_main_size, &grow_unit, &track_size);
|
||||
next_track_first_item = find_track_end(cont, track_first_item, max_main_size, &grow_unit, &track_size);
|
||||
|
||||
children_repos(cont, track_first_item, next_track_first_item, main_dir, abs_x, abs_y, track_size, grow_unit);
|
||||
children_repos(cont, track_first_item, next_track_first_item, abs_x, abs_y, track_size, grow_unit);
|
||||
|
||||
track_first_item = next_track_first_item;
|
||||
*cross_pos += track_size + gap;
|
||||
@ -105,43 +122,54 @@ void _lv_flex_refresh(lv_obj_t * cont)
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_dir_t main_dir, lv_coord_t max_size, lv_coord_t * grow_unit, lv_coord_t * track_cross_size)
|
||||
static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coord_t max_size, lv_coord_t * grow_unit, lv_coord_t * track_cross_size)
|
||||
{
|
||||
lv_coord_t(*get_main_size)(const lv_obj_t *) = (main_dir == LV_DIR_HOR ? lv_obj_get_width_margin : lv_obj_get_height_margin);
|
||||
lv_coord_t(*get_cross_size)(const lv_obj_t *) = (main_dir == LV_DIR_VER ? lv_obj_get_width_margin : lv_obj_get_height_margin);
|
||||
void * (*ll_iter)(const lv_ll_t * , const void *) = cont->flex_dir & LV_FLEX_REVERSE ? _lv_ll_get_next : _lv_ll_get_prev;
|
||||
bool wrap = cont->flex_dir & LV_FLEX_WRAP ? true : false;
|
||||
lv_flex_dir_t dir = cont->flex_cont.dir;
|
||||
bool row = dir == LV_FLEX_DIR_ROW ? true : false;
|
||||
lv_coord_t(*get_main_size)(const lv_obj_t *) = (row ? lv_obj_get_width_margin : lv_obj_get_height_margin);
|
||||
lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!row ? lv_obj_get_width_margin : lv_obj_get_height_margin);
|
||||
void * (*ll_iter)(const lv_ll_t * , const void *) = dir & LV_FLEX_REVERSE ? _lv_ll_get_next : _lv_ll_get_prev;
|
||||
bool wrap = dir & LV_FLEX_WRAP ? true : false;
|
||||
|
||||
lv_coord_t grow_sum = 0;
|
||||
lv_coord_t used_size = 0;
|
||||
lv_coord_t gap = cont->flex_cont.gap;
|
||||
uint32_t grow_item_cnt = 0;
|
||||
*track_cross_size = 0;
|
||||
*grow_unit = 0;
|
||||
|
||||
lv_obj_t * item = item_start;
|
||||
while(item) {
|
||||
/*Ignore non-flex items*/
|
||||
lv_coord_t main_set = (main_dir == LV_DIR_HOR ? item->x_set : item->y_set);
|
||||
lv_coord_t main_set = (row ? item->x_set : item->y_set);
|
||||
if(LV_COORD_IS_FLEX(main_set) == false) {
|
||||
item = ll_iter(&cont->child_ll, item);
|
||||
continue;
|
||||
}
|
||||
|
||||
lv_coord_t main_size = (main_dir == LV_DIR_HOR ? item->w_set : item->h_set);
|
||||
lv_coord_t main_size = (row ? item->w_set : item->h_set);
|
||||
if(_LV_FLEX_GET_GROW(main_size)) {
|
||||
grow_sum += _LV_FLEX_GET_GROW(main_size);
|
||||
grow_item_cnt++;
|
||||
} else {
|
||||
lv_coord_t item_size = get_main_size(item);
|
||||
lv_coord_t item_size = get_main_size(item) + gap;
|
||||
if(wrap && used_size + item_size > max_size) break;
|
||||
used_size += item_size;
|
||||
}
|
||||
|
||||
*track_cross_size = LV_MATH_MAX(get_cross_size(item), *track_cross_size);
|
||||
|
||||
item = ll_iter(&cont->child_ll, item);
|
||||
}
|
||||
|
||||
*grow_unit = grow_sum ? (max_size - used_size) / grow_sum : 0;
|
||||
if(*grow_unit < 0) *grow_unit = 0;
|
||||
if(used_size > 0) used_size -= gap; /*There is no gap after the last item*/
|
||||
|
||||
if(grow_item_cnt && grow_sum) {
|
||||
lv_coord_t s = max_size - used_size;
|
||||
s -= grow_item_cnt * gap;
|
||||
*grow_unit = s / grow_sum;
|
||||
} else {
|
||||
*grow_unit = 0;
|
||||
}
|
||||
|
||||
/*Have at least one item in a row*/
|
||||
if(item && item == item_start) {
|
||||
@ -153,29 +181,32 @@ static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_dir_
|
||||
}
|
||||
|
||||
|
||||
static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * item_last, lv_dir_t main_dir, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t track_size, lv_coord_t grow_unit)
|
||||
static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * item_last, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t track_size, lv_coord_t grow_unit)
|
||||
{
|
||||
lv_coord_t(*obj_get_main_size)(const lv_obj_t *) = (main_dir == LV_DIR_HOR ? lv_obj_get_width_margin : lv_obj_get_height_margin);
|
||||
lv_coord_t(*obj_get_cross_size)(const lv_obj_t *) = (main_dir == LV_DIR_VER ? lv_obj_get_width_margin : lv_obj_get_height_margin);
|
||||
void (*area_set_main_size)(lv_area_t *, lv_coord_t) = (main_dir == LV_DIR_HOR ? lv_area_set_width : lv_area_set_height);
|
||||
lv_coord_t (*area_get_main_size)(const lv_area_t *) = (main_dir == LV_DIR_HOR ? lv_area_get_width : lv_area_get_height);
|
||||
lv_coord_t (*get_margin_start)(const lv_obj_t *, uint8_t part) = (main_dir == LV_DIR_HOR ? lv_obj_get_style_margin_left : lv_obj_get_style_margin_top);
|
||||
lv_coord_t (*get_margin_end)(const lv_obj_t *, uint8_t part) = (main_dir == LV_DIR_HOR ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom);
|
||||
void * (*ll_iter)(const lv_ll_t * , const void *) = cont->flex_dir & LV_FLEX_REVERSE ? _lv_ll_get_next : _lv_ll_get_prev;
|
||||
lv_flex_dir_t dir = cont->flex_cont.dir;
|
||||
bool row = dir == LV_FLEX_DIR_ROW ? true : false;
|
||||
lv_coord_t(*obj_get_main_size)(const lv_obj_t *) = (row ? lv_obj_get_width_margin : lv_obj_get_height_margin);
|
||||
lv_coord_t(*obj_get_cross_size)(const lv_obj_t *) = (!row ? lv_obj_get_width_margin : lv_obj_get_height_margin);
|
||||
void (*area_set_main_size)(lv_area_t *, lv_coord_t) = (row ? lv_area_set_width : lv_area_set_height);
|
||||
lv_coord_t (*area_get_main_size)(const lv_area_t *) = (!row ? lv_area_get_width : lv_area_get_height);
|
||||
lv_style_int_t (*get_margin_start)(const lv_obj_t *, uint8_t part) = (row ? lv_obj_get_style_margin_left : lv_obj_get_style_margin_top);
|
||||
lv_style_int_t (*get_margin_end)(const lv_obj_t *, uint8_t part) = (row ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom);
|
||||
void * (*ll_iter)(const lv_ll_t * , const void *) = dir & LV_FLEX_REVERSE ? _lv_ll_get_next : _lv_ll_get_prev;
|
||||
|
||||
lv_coord_t gap = cont->flex_cont.gap;
|
||||
lv_coord_t main_pos = 0;
|
||||
/*Reposition the children*/
|
||||
lv_obj_t * item = item_first; /*Just to use a shorter name*/
|
||||
while(item != item_last) {
|
||||
|
||||
/*Ignore non-flex items*/
|
||||
lv_coord_t main_set = (main_dir == LV_DIR_HOR ? item->x_set : item->y_set);
|
||||
lv_coord_t main_set = (row ? item->x_set : item->y_set);
|
||||
if(LV_COORD_IS_FLEX(main_set) == false) {
|
||||
item = ll_iter(&cont->child_ll, item);
|
||||
continue;
|
||||
}
|
||||
|
||||
lv_coord_t main_size = (main_dir == LV_DIR_HOR ? item->w_set : item->h_set);
|
||||
lv_coord_t main_size = (row ? item->w_set : item->h_set);
|
||||
if(_LV_FLEX_GET_GROW(main_size)) {
|
||||
lv_coord_t s = _LV_FLEX_GET_GROW(main_size) * grow_unit;
|
||||
s -= get_margin_start(item, LV_OBJ_PART_MAIN) + get_margin_end(item, LV_OBJ_PART_MAIN);
|
||||
@ -190,8 +221,8 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it
|
||||
}
|
||||
|
||||
lv_coord_t cross_pos = 0;
|
||||
lv_coord_t cross_set = (main_dir == LV_DIR_HOR ? item->y_set : item->x_set);
|
||||
switch(cross_set) {
|
||||
lv_coord_t cross_set = (row ? item->y_set : item->x_set);
|
||||
switch(LV_COORD_GET_FLEX(cross_set)) {
|
||||
case LV_FLEX_CENTER:
|
||||
cross_pos = (track_size - obj_get_cross_size(item)) / 2;
|
||||
break;
|
||||
@ -202,7 +233,7 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it
|
||||
|
||||
lv_coord_t diff_x;
|
||||
lv_coord_t diff_y;
|
||||
if(main_dir == LV_DIR_HOR) {
|
||||
if(row) {
|
||||
diff_x = abs_x + main_pos - item->coords.x1;
|
||||
diff_y = abs_y + cross_pos - item->coords.y1;
|
||||
} else {
|
||||
@ -217,7 +248,7 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it
|
||||
item->coords.y2 += diff_y;
|
||||
_lv_obj_move_children_by(item, diff_x, diff_y);
|
||||
}
|
||||
main_pos += obj_get_main_size(item);
|
||||
main_pos += obj_get_main_size(item) + gap;
|
||||
item = ll_iter(&cont->child_ll, item);
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ extern "C" {
|
||||
|
||||
#define _LV_FLEX_GET_GROW(v) (LV_COORD_IS_FLEX(v) ? LV_COORD_GET_FLEX(v) : 0)
|
||||
|
||||
#define LV_FLEX_WRAP (1 << 6)
|
||||
#define LV_FLEX_REVERSE (1 << 7)
|
||||
#define LV_FLEX_WRAP (1 << 2)
|
||||
#define LV_FLEX_REVERSE (1 << 3)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@ -44,13 +44,20 @@ typedef enum {
|
||||
LV_FLEX_DIR_NONE,
|
||||
LV_FLEX_DIR_ROW,
|
||||
LV_FLEX_DIR_COLUMN,
|
||||
} lv_flex_dir_t;
|
||||
}lv_flex_dir_t;
|
||||
|
||||
typedef struct {
|
||||
lv_coord_t gap;
|
||||
uint32_t place :4;
|
||||
uint32_t dir :4;
|
||||
}lv_flex_cont_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_obj_set_flex_cont(lv_obj_t * obj, lv_flex_dir_t flex_dir, lv_flex_place_t flex_place);
|
||||
void lv_obj_set_flex_gap(lv_obj_t * obj, lv_coord_t gap);
|
||||
void lv_obj_set_flex_item(lv_obj_t * obj, lv_flex_place_t place);
|
||||
void _lv_flex_refresh(lv_obj_t * cont);
|
||||
|
||||
|
@ -1140,7 +1140,7 @@ lv_obj_t * lv_obj_get_child_back(const lv_obj_t * obj, const lv_obj_t * child)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Nth child of a an object. 0th is the lastly created.
|
||||
* Get the Nth child of an object. 0th is the lastly created.
|
||||
* @param obj pointer to an object whose children should be get
|
||||
* @param id of a child
|
||||
* @return the child or `NULL` if `id` was greater then the `number of children - 1`
|
||||
@ -1149,14 +1149,39 @@ lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, uint32_t id)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_t * child = lv_obj_get_child(obj, NULL);
|
||||
lv_obj_t * child = lv_obj_get_child_back(obj, NULL);
|
||||
uint32_t i;
|
||||
for(i = 0; i < id; i++) {
|
||||
child = lv_obj_get_child(obj, child);
|
||||
child = lv_obj_get_child_back(obj, child);
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the child index of an object.
|
||||
* If this object is the firstly created child of its parent 0 will be return.
|
||||
* If its the second child return 1, etc.
|
||||
* @param obj pointer to an object whose index should be get
|
||||
* @return the child index of the object.
|
||||
*/
|
||||
uint32_t lv_obj_get_child_id(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent == NULL) return 0;
|
||||
|
||||
uint32_t id = 0;
|
||||
lv_obj_t * child = lv_obj_get_child_back(parent, NULL);
|
||||
while(child) {
|
||||
if(child == obj) return id;
|
||||
id++;
|
||||
child = lv_obj_get_child_back(parent, child);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the children of an object (only children directly on 'obj')
|
||||
* @param obj pointer to an object
|
||||
@ -1924,7 +1949,7 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
|
||||
}
|
||||
}
|
||||
if(obj->grid) _lv_grid_full_refresh(obj);
|
||||
if(obj->flex_dir) _lv_flex_refresh(obj);
|
||||
if(obj->flex_cont.dir) _lv_flex_refresh(obj);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CHILD_CHG) {
|
||||
|
@ -256,10 +256,7 @@ struct _lv_obj_t {
|
||||
|
||||
const lv_grid_t * grid;
|
||||
|
||||
uint8_t flex_dir : 4;
|
||||
uint8_t flex_place : 4;
|
||||
|
||||
|
||||
lv_flex_cont_t flex_cont;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -605,6 +602,15 @@ lv_obj_t * lv_obj_get_child_back(const lv_obj_t * obj, const lv_obj_t * child);
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, uint32_t id);
|
||||
|
||||
/**
|
||||
* Get the child index of an object.
|
||||
* If this object is the firstly created child of its parent 0 will be return.
|
||||
* If its the second child return 1, etc.
|
||||
* @param obj pointer to an object whose index should be get
|
||||
* @return the child index of the object.
|
||||
*/
|
||||
uint32_t lv_obj_get_child_id(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Count the children of an object (only children directly on 'obj')
|
||||
* @param obj pointer to an object
|
||||
|
@ -732,7 +732,7 @@ bool _lv_obj_is_flex_item(struct _lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_t * cont = lv_obj_get_parent(obj);
|
||||
if(cont == NULL) return false;
|
||||
if(cont->flex_dir == LV_FLEX_DIR_NONE) return false;
|
||||
if(cont->flex_cont.dir == LV_FLEX_DIR_NONE) return false;
|
||||
if(LV_COORD_IS_FLEX(obj->x_set) == false || LV_COORD_IS_FLEX(obj->y_set) == false) return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -207,9 +207,6 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
|
||||
self_h = self_h - (lv_obj_get_height(obj) - pad_top - pad_bottom);
|
||||
self_h += obj->scroll.y;
|
||||
return LV_MATH_MAX(child_res, self_h);
|
||||
|
||||
|
||||
return child_res - obj->coords.y2 + lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,8 +48,8 @@
|
||||
|
||||
#define COLOR_BG_BORDER (IS_LIGHT ? lv_color_hex(0xd6dde3) : lv_color_hex(0x808a97)) /*dfe7ed*/
|
||||
#define COLOR_BG_BORDER_PR (IS_LIGHT ? lv_color_hex3(0xccc) : lv_color_hex(0x5f656e))
|
||||
#define COLOR_BG_BORDER_CHK (IS_LIGHT ? lv_color_hex(0x3b3e42) : lv_color_hex(0x5f656e))
|
||||
#define COLOR_BG_BORDER_CHK_PR (IS_LIGHT ? lv_color_hex(0x3b3e42) : lv_color_hex(0x5f656e))
|
||||
#define COLOR_BG_BORDER_CHK (IS_LIGHT ? lv_color_hex(0xd6dde3) : lv_color_hex(0x5f656e))
|
||||
#define COLOR_BG_BORDER_CHK_PR (IS_LIGHT ? lv_color_hex3(0xccc) : lv_color_hex(0x5f656e))
|
||||
#define COLOR_BG_BORDER_DIS (IS_LIGHT ? lv_color_hex(0xd6dde3) : lv_color_hex(0x5f656e))
|
||||
|
||||
#define COLOR_BG_TEXT (IS_LIGHT ? lv_color_hex(0x3b3e42) : lv_color_hex(0xffffff))
|
||||
@ -64,7 +64,7 @@
|
||||
#define COLOR_BG_SEC_TEXT (IS_LIGHT ? lv_color_hex(0x31404f) : lv_color_hex(0xa5a8ad))
|
||||
#define COLOR_BG_SEC_TEXT_DIS (IS_LIGHT ? lv_color_hex(0xaaaaaa) : lv_color_hex(0xa5a8ad))
|
||||
|
||||
#define TRANSITION_TIME 0/*((theme.flags & LV_THEME_MATERIAL_FLAG_NO_TRANSITION) ? 0 : 150)*/
|
||||
#define TRANSITION_TIME ((theme.flags & LV_THEME_MATERIAL_FLAG_NO_TRANSITION) ? 0 : 150)
|
||||
#define BORDER_WIDTH LV_DPX(2)
|
||||
#define OUTLINE_WIDTH ((theme.flags & LV_THEME_MATERIAL_FLAG_NO_FOCUS) ? 0 : LV_DPX(2))
|
||||
#define IS_LIGHT (theme.flags & LV_THEME_MATERIAL_FLAG_LIGHT)
|
||||
@ -1006,6 +1006,11 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
|
||||
_lv_style_list_add_style(list, &styles->bg);
|
||||
_lv_style_list_add_style(list, &styles->bg_click);
|
||||
_lv_style_list_add_style(list, &styles->btnmatrix_btn);
|
||||
|
||||
list = _lv_obj_get_style_list(obj, LV_BTNMATRIX_PART_BTN_2);
|
||||
_lv_style_list_add_style(list, &styles->bg);
|
||||
_lv_style_list_add_style(list, &styles->bg_click);
|
||||
_lv_style_list_add_style(list, &styles->btnmatrix_btn);
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -101,6 +101,7 @@ lv_obj_t * lv_btnmatrix_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_style_list_init(&ext->style_btn);
|
||||
lv_style_list_init(&ext->style_btn2);
|
||||
ext->style_btn.ignore_trans = 1;
|
||||
ext->style_btn2.ignore_trans = 1;
|
||||
|
||||
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_cb(btnm);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,805 +0,0 @@
|
||||
/**
|
||||
* @file lv_cont.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_cont.h"
|
||||
#if LV_USE_CONT != 0
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_draw/lv_draw_mask.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_cont"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param);
|
||||
static lv_style_list_t * lv_cont_get_style(lv_obj_t * cont, uint8_t type);
|
||||
static void lv_cont_refr_layout(lv_obj_t * cont);
|
||||
static void lv_cont_layout_col(lv_obj_t * cont);
|
||||
static void lv_cont_layout_row(lv_obj_t * cont);
|
||||
static void lv_cont_layout_center(lv_obj_t * cont);
|
||||
static void lv_cont_layout_pretty(lv_obj_t * cont);
|
||||
static void lv_cont_layout_grid(lv_obj_t * cont);
|
||||
static void lv_cont_refr_autofit(lv_obj_t * cont);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_cb_t ancestor_design;
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a container objects
|
||||
* @param par pointer to an object, it will be the parent of the new container
|
||||
* @param copy pointer to a container object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created container
|
||||
*/
|
||||
lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
|
||||
LV_LOG_TRACE("container create started");
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * cont = lv_obj_create(par, copy);
|
||||
LV_ASSERT_MEM(cont);
|
||||
if(cont == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(cont);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(cont);
|
||||
|
||||
lv_obj_allocate_ext_attr(cont, sizeof(lv_cont_ext_t));
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(cont);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM(ext);
|
||||
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_cb(cont, lv_cont_signal);
|
||||
|
||||
/*Init the new container*/
|
||||
if(copy == NULL) {
|
||||
/*Set the default styles if it's not screen*/
|
||||
if(par != NULL) {
|
||||
lv_theme_apply(cont, LV_THEME_CONT);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_cont_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
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*/
|
||||
lv_obj_refresh_style(cont, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("container created");
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a layout on a container
|
||||
* @param cont pointer to a container object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext->layout == layout) return;
|
||||
|
||||
ext->layout = layout;
|
||||
|
||||
/*Send a signal to refresh the layout*/
|
||||
cont->signal_cb(cont, LV_SIGNAL_CHILD_CHG, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_invalidate(cont);
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext->fit_left == left && ext->fit_right == right && ext->fit_top == top && ext->fit_bottom == bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
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_cb(cont, LV_SIGNAL_CHILD_CHG, NULL);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the layout of a container
|
||||
* @param cont pointer to container object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
lv_layout_t lv_cont_get_layout(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get left 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_left(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get right 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_right(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
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_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
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_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_bottom;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the container
|
||||
* @param cont pointer to a container object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param)
|
||||
{
|
||||
if(sign == LV_SIGNAL_GET_STYLE) {
|
||||
lv_get_style_info_t * info = param;
|
||||
info->result = lv_cont_get_style(cont, info->part);
|
||||
if(info->result != NULL) return LV_RES_OK;
|
||||
else return ancestor_signal(cont, sign, param);
|
||||
}
|
||||
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(cont, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) { /*Recalculate the padding if the style changed*/
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CHILD_CHG) {
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_COORD_CHG) {
|
||||
if(lv_obj_get_width(cont) != lv_area_get_width(param) || lv_obj_get_height(cont) != lv_area_get_height(param)) {
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PARENT_SIZE_CHG) {
|
||||
/*MAX and EDGE fit needs to be refreshed if the parent's size has changed*/
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static lv_style_list_t * lv_cont_get_style(lv_obj_t * cont, uint8_t type)
|
||||
{
|
||||
lv_style_list_t * style_dsc_p;
|
||||
switch(type) {
|
||||
case LV_CONT_PART_MAIN:
|
||||
style_dsc_p = &cont->style_list;
|
||||
break;
|
||||
default:
|
||||
style_dsc_p = NULL;
|
||||
}
|
||||
|
||||
return style_dsc_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the layout of a container
|
||||
* @param cont pointer to an object which layout should be refreshed
|
||||
*/
|
||||
static void lv_cont_refr_layout(lv_obj_t * cont)
|
||||
{
|
||||
if(lv_obj_is_protected(cont, LV_PROTECT_CHILD_CHG)) return;
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
|
||||
/*'cont' has to be at least 1 child*/
|
||||
if(lv_obj_get_child(cont, NULL) == NULL) return;
|
||||
|
||||
if(type == LV_LAYOUT_OFF) return;
|
||||
|
||||
if(type == LV_LAYOUT_CENTER) {
|
||||
lv_cont_layout_center(cont);
|
||||
}
|
||||
else if(type == LV_LAYOUT_COLUMN_LEFT || type == LV_LAYOUT_COLUMN_MID || type == LV_LAYOUT_COLUMN_RIGHT) {
|
||||
lv_cont_layout_col(cont);
|
||||
}
|
||||
else if(type == LV_LAYOUT_ROW_TOP || type == LV_LAYOUT_ROW_MID || type == LV_LAYOUT_ROW_BOTTOM) {
|
||||
lv_cont_layout_row(cont);
|
||||
}
|
||||
else if(type == LV_LAYOUT_PRETTY_MID || type == LV_LAYOUT_PRETTY_TOP || type == LV_LAYOUT_PRETTY_BOTTOM) {
|
||||
lv_cont_layout_pretty(cont);
|
||||
}
|
||||
else if(type == LV_LAYOUT_GRID) {
|
||||
lv_cont_layout_grid(cont);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle column type layouts
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_col(lv_obj_t * cont)
|
||||
{
|
||||
lv_coord_t left = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t right = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t top = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
lv_obj_t * child;
|
||||
|
||||
/*Adjust margin and get the alignment type*/
|
||||
lv_align_t align;
|
||||
lv_coord_t hpad_corr;
|
||||
|
||||
switch(type) {
|
||||
case LV_LAYOUT_COLUMN_LEFT:
|
||||
hpad_corr = left;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
case LV_LAYOUT_COLUMN_MID:
|
||||
hpad_corr = 0;
|
||||
align = LV_ALIGN_IN_TOP_MID;
|
||||
break;
|
||||
case LV_LAYOUT_COLUMN_RIGHT:
|
||||
hpad_corr = -right;
|
||||
align = LV_ALIGN_IN_TOP_RIGHT;
|
||||
break;
|
||||
default:
|
||||
hpad_corr = 0;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord = top;
|
||||
_LV_LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
lv_style_int_t mtop = lv_obj_get_style_margin_top(child, LV_OBJ_PART_MAIN);
|
||||
lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(child, LV_OBJ_PART_MAIN);
|
||||
lv_style_int_t mleft = lv_obj_get_style_margin_left(child, LV_OBJ_PART_MAIN);
|
||||
lv_obj_align(child, cont, align, hpad_corr + mleft, last_cord + mtop);
|
||||
last_cord += lv_obj_get_height(child) + inner + mtop + mbottom;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle row type layouts
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_row(lv_obj_t * cont)
|
||||
{
|
||||
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
lv_obj_t * child;
|
||||
|
||||
/*Adjust margin and get the alignment type*/
|
||||
lv_align_t align;
|
||||
lv_coord_t vpad_corr;
|
||||
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(cont);
|
||||
switch(type) {
|
||||
case LV_LAYOUT_ROW_TOP:
|
||||
vpad_corr = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
case LV_LAYOUT_ROW_MID:
|
||||
vpad_corr = 0;
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_RIGHT_MID : LV_ALIGN_IN_LEFT_MID;
|
||||
break;
|
||||
case LV_LAYOUT_ROW_BOTTOM:
|
||||
vpad_corr = -lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN);
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_BOTTOM_RIGHT : LV_ALIGN_IN_BOTTOM_LEFT;
|
||||
break;
|
||||
default:
|
||||
vpad_corr = 0;
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord;
|
||||
if(base_dir == LV_BIDI_DIR_RTL) last_cord = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN);
|
||||
else last_cord = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
|
||||
lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
|
||||
_LV_LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
if(base_dir == LV_BIDI_DIR_RTL) lv_obj_align(child, cont, align, -last_cord, vpad_corr);
|
||||
else lv_obj_align(child, cont, align, last_cord, vpad_corr);
|
||||
|
||||
last_cord += lv_obj_get_width(child) + inner;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the center layout
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_center(lv_obj_t * cont)
|
||||
{
|
||||
lv_obj_t * child;
|
||||
uint32_t obj_num = 0;
|
||||
lv_coord_t h_tot = 0;
|
||||
|
||||
lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
_LV_LL_READ(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
h_tot += lv_obj_get_height(child) + inner;
|
||||
obj_num++;
|
||||
}
|
||||
|
||||
if(obj_num == 0) return;
|
||||
|
||||
h_tot -= inner;
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord = -(h_tot / 2);
|
||||
_LV_LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
lv_obj_align(child, cont, LV_ALIGN_CENTER, 0, last_cord + lv_obj_get_height(child) / 2);
|
||||
last_cord += lv_obj_get_height(child) + inner;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the pretty layout. Put as many object as possible in row
|
||||
* then begin a new row
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_pretty(lv_obj_t * cont)
|
||||
{
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
|
||||
lv_obj_t * child_rs; /* Row starter child */
|
||||
lv_obj_t * child_rc; /* Row closer child */
|
||||
lv_obj_t * child_tmp; /* Temporary child */
|
||||
lv_coord_t w_obj = lv_obj_get_width(cont);
|
||||
lv_coord_t act_y = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
|
||||
child_rs = _lv_ll_get_tail(&cont->child_ll); /*Set the row starter child*/
|
||||
if(child_rs == NULL) return; /*Return if no child*/
|
||||
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
lv_coord_t pleft = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t pright = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t pinner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
|
||||
child_rc = child_rs; /*Initially the the row starter and closer is the same*/
|
||||
while(child_rs != NULL) {
|
||||
lv_coord_t h_row = 0;
|
||||
lv_coord_t w_row = pleft + pright; /*The width is at least the left+right pad*/
|
||||
uint32_t obj_num = 0;
|
||||
|
||||
/*Find the row closer object and collect some data*/
|
||||
do {
|
||||
if(lv_obj_get_hidden(child_rc) == false && lv_obj_is_protected(child_rc, LV_PROTECT_POS) == false) {
|
||||
/*If this object is already not fit then break*/
|
||||
lv_coord_t w = lv_obj_get_width(child_rc);
|
||||
w += lv_obj_get_style_margin_left(child_rc, LV_OBJ_PART_MAIN);
|
||||
w += lv_obj_get_style_margin_right(child_rc, LV_OBJ_PART_MAIN);
|
||||
if(w_row + w > w_obj) {
|
||||
/*Step back one child because the last already not fit, so the previous is the
|
||||
* closer*/
|
||||
if(child_rc != NULL && obj_num != 0) {
|
||||
child_rc = _lv_ll_get_next(&cont->child_ll, child_rc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
w_row += w + pinner; /*Add the object width + inner padding*/
|
||||
|
||||
lv_coord_t h = lv_obj_get_height(child_rc);
|
||||
h += lv_obj_get_style_margin_top(child_rc, LV_OBJ_PART_MAIN);
|
||||
h += lv_obj_get_style_margin_bottom(child_rc, LV_OBJ_PART_MAIN);
|
||||
h_row = LV_MATH_MAX(h_row, h); /*Search the highest object*/
|
||||
obj_num++;
|
||||
if(lv_obj_is_protected(child_rc, LV_PROTECT_FOLLOW))
|
||||
break; /*If can not be followed by an other object then break here*/
|
||||
}
|
||||
child_rc = _lv_ll_get_prev(&cont->child_ll, child_rc); /*Load the next object*/
|
||||
if(obj_num == 0)
|
||||
child_rs = child_rc; /*If the first object was hidden (or too long) then set the
|
||||
next as first */
|
||||
} while(child_rc != NULL);
|
||||
|
||||
/*If the object is too long then align it to the middle*/
|
||||
if(obj_num == 0) {
|
||||
if(child_rc != NULL) {
|
||||
lv_style_int_t mtop = lv_obj_get_style_margin_top(child_rc, LV_OBJ_PART_MAIN);
|
||||
|
||||
lv_obj_align(child_rc, cont, LV_ALIGN_IN_TOP_MID, 0, act_y + mtop);
|
||||
h_row = lv_obj_get_height(child_rc); /*Not set previously because of the early break*/
|
||||
h_row += mtop;
|
||||
h_row += lv_obj_get_style_margin_bottom(child_rc, LV_OBJ_PART_MAIN);
|
||||
}
|
||||
}
|
||||
/*If there is only one object in the row then align it to the middle*/
|
||||
else if(obj_num == 1) {
|
||||
lv_obj_align(child_rs, cont, LV_ALIGN_IN_TOP_MID,
|
||||
0,
|
||||
act_y + lv_obj_get_style_margin_top(child_rs, LV_OBJ_PART_MAIN));
|
||||
}
|
||||
/* Align the children (from child_rs to child_rc)*/
|
||||
else {
|
||||
w_row -= pinner * obj_num;
|
||||
lv_coord_t new_pinner = (w_obj - w_row) / (obj_num - 1);
|
||||
lv_coord_t act_x = pleft; /*x init*/
|
||||
child_tmp = child_rs;
|
||||
lv_align_t align;
|
||||
int32_t inv;
|
||||
if(lv_obj_get_base_dir(cont) == LV_BIDI_DIR_RTL) {
|
||||
align = LV_ALIGN_IN_TOP_RIGHT;
|
||||
inv = -1;
|
||||
}
|
||||
else {
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
inv = 1;
|
||||
}
|
||||
while(child_tmp != NULL) {
|
||||
if(lv_obj_get_hidden(child_tmp) == false && lv_obj_is_protected(child_tmp, LV_PROTECT_POS) == false) {
|
||||
lv_coord_t mleft = lv_obj_get_style_margin_left(child_tmp, LV_OBJ_PART_MAIN);
|
||||
lv_coord_t mright = lv_obj_get_style_margin_right(child_tmp, LV_OBJ_PART_MAIN);
|
||||
switch(type) {
|
||||
case LV_LAYOUT_PRETTY_TOP:
|
||||
lv_obj_align(child_tmp, cont, align,
|
||||
inv * (act_x + mleft),
|
||||
act_y + lv_obj_get_style_margin_top(child_tmp, LV_OBJ_PART_MAIN));
|
||||
break;
|
||||
case LV_LAYOUT_PRETTY_MID:
|
||||
lv_obj_align(child_tmp, cont, align,
|
||||
inv * (act_x + mleft),
|
||||
act_y + (h_row - lv_obj_get_height(child_tmp)) / 2);
|
||||
|
||||
break;
|
||||
case LV_LAYOUT_PRETTY_BOTTOM:
|
||||
lv_obj_align(child_tmp, cont, align,
|
||||
inv * (act_x + mleft),
|
||||
act_y + h_row - lv_obj_get_height(child_tmp) - lv_obj_get_style_margin_bottom(child_tmp, LV_OBJ_PART_MAIN));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
act_x += lv_obj_get_width(child_tmp) + new_pinner + mleft + mright;
|
||||
}
|
||||
if(child_tmp == child_rc) break;
|
||||
child_tmp = _lv_ll_get_prev(&cont->child_ll, child_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if(child_rc == NULL) break;
|
||||
act_y += pinner + h_row; /*y increment*/
|
||||
child_rs = _lv_ll_get_prev(&cont->child_ll, child_rc); /*Go to the next object*/
|
||||
child_rc = child_rs;
|
||||
}
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the grid layout. Align same-sized objects in a grid
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_grid(lv_obj_t * cont)
|
||||
{
|
||||
lv_coord_t w_fit = lv_obj_get_width_fit(cont);
|
||||
lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t y_ofs = inner + lv_obj_get_height(lv_obj_get_child(cont, NULL));
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t left = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t act_x = left;
|
||||
lv_coord_t act_y = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
lv_obj_t * child;
|
||||
_LV_LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
lv_coord_t obj_w = lv_obj_get_width(child);
|
||||
if(act_x + obj_w > w_fit + left) {
|
||||
act_x = left;
|
||||
act_y += y_ofs;
|
||||
}
|
||||
|
||||
lv_obj_set_pos(child, act_x, act_y);
|
||||
act_x += inner + obj_w;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle auto fit. Set the size of the object to involve all children.
|
||||
* @param cont pointer to an object which size will be modified
|
||||
*/
|
||||
static void lv_cont_refr_autofit(lv_obj_t * cont)
|
||||
{
|
||||
if(lv_obj_is_protected(cont, LV_PROTECT_CHILD_CHG)) return;
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
|
||||
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 tight_area;
|
||||
lv_area_t ori;
|
||||
lv_obj_t * child_i;
|
||||
|
||||
lv_obj_t * par = lv_obj_get_parent(cont);
|
||||
lv_area_t parent_area;
|
||||
lv_area_copy(&parent_area, &par->coords);
|
||||
parent_area.x1 += lv_obj_get_style_pad_left(par, LV_OBJ_PART_MAIN);
|
||||
parent_area.x2 -= lv_obj_get_style_pad_right(par, LV_OBJ_PART_MAIN);
|
||||
parent_area.y1 += lv_obj_get_style_pad_top(par, LV_OBJ_PART_MAIN);
|
||||
parent_area.y2 -= lv_obj_get_style_pad_bottom(par, LV_OBJ_PART_MAIN);
|
||||
|
||||
/*Search the side coordinates of the children*/
|
||||
lv_obj_get_coords(cont, &ori);
|
||||
lv_obj_get_coords(cont, &tight_area);
|
||||
|
||||
bool has_children = _lv_ll_is_empty(&cont->child_ll) ? false : true;
|
||||
|
||||
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;
|
||||
|
||||
_LV_LL_READ(cont->child_ll, child_i) {
|
||||
if(lv_obj_get_hidden(child_i) != false) continue;
|
||||
|
||||
if(ext->fit_left != LV_FIT_PARENT) {
|
||||
lv_style_int_t mleft = lv_obj_get_style_margin_left(child_i, LV_OBJ_PART_MAIN);
|
||||
tight_area.x1 = LV_MATH_MIN(tight_area.x1, child_i->coords.x1 - mleft);
|
||||
}
|
||||
|
||||
if(ext->fit_right != LV_FIT_PARENT) {
|
||||
lv_style_int_t mright = lv_obj_get_style_margin_right(child_i, LV_OBJ_PART_MAIN);
|
||||
tight_area.x2 = LV_MATH_MAX(tight_area.x2, child_i->coords.x2 + mright);
|
||||
}
|
||||
|
||||
if(ext->fit_top != LV_FIT_PARENT) {
|
||||
lv_style_int_t mtop = lv_obj_get_style_margin_top(child_i, LV_OBJ_PART_MAIN);
|
||||
tight_area.y1 = LV_MATH_MIN(tight_area.y1, child_i->coords.y1 - mtop);
|
||||
}
|
||||
|
||||
if(ext->fit_bottom != LV_FIT_PARENT) {
|
||||
lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(child_i, LV_OBJ_PART_MAIN);
|
||||
tight_area.y2 = LV_MATH_MAX(tight_area.y2, child_i->coords.y2 + mbottom);
|
||||
}
|
||||
}
|
||||
|
||||
tight_area.x1 -= lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
tight_area.x2 += lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN);
|
||||
tight_area.y1 -= lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
tight_area.y2 += lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN);
|
||||
}
|
||||
|
||||
lv_area_t new_area;
|
||||
lv_area_copy(&new_area, &ori);
|
||||
|
||||
switch(ext->fit_left) {
|
||||
case LV_FIT_TIGHT:
|
||||
new_area.x1 = tight_area.x1;
|
||||
break;
|
||||
case LV_FIT_PARENT:
|
||||
new_area.x1 = parent_area.x1;
|
||||
break;
|
||||
case LV_FIT_MAX:
|
||||
new_area.x1 = has_children ? LV_MATH_MIN(tight_area.x1, parent_area.x1) : parent_area.x1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(ext->fit_right) {
|
||||
case LV_FIT_TIGHT:
|
||||
new_area.x2 = tight_area.x2;
|
||||
break;
|
||||
case LV_FIT_PARENT:
|
||||
new_area.x2 = parent_area.x2;
|
||||
break;
|
||||
case LV_FIT_MAX:
|
||||
new_area.x2 = has_children ? LV_MATH_MAX(tight_area.x2, parent_area.x2) : parent_area.x2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(ext->fit_top) {
|
||||
case LV_FIT_TIGHT:
|
||||
new_area.y1 = tight_area.y1;
|
||||
break;
|
||||
case LV_FIT_PARENT:
|
||||
new_area.y1 = parent_area.y1;
|
||||
break;
|
||||
case LV_FIT_MAX:
|
||||
new_area.y1 = has_children ? LV_MATH_MIN(tight_area.y1, parent_area.y1) : parent_area.y1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(ext->fit_bottom) {
|
||||
case LV_FIT_TIGHT:
|
||||
new_area.y2 = tight_area.y2;
|
||||
break;
|
||||
case LV_FIT_PARENT:
|
||||
new_area.y2 = parent_area.y2;
|
||||
break;
|
||||
case LV_FIT_MAX:
|
||||
new_area.y2 = has_children ? LV_MATH_MAX(tight_area.y2, parent_area.y2) : parent_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_cb(cont, LV_SIGNAL_COORD_CHG, &ori);
|
||||
|
||||
/*Inform the parent about the new coordinates*/
|
||||
par->signal_cb(par, LV_SIGNAL_CHILD_CHG, cont);
|
||||
|
||||
if(lv_obj_get_auto_realign(cont)) {
|
||||
lv_obj_realign(cont);
|
||||
}
|
||||
|
||||
/*Tell the children the parent's size has changed*/
|
||||
_LV_LL_READ(cont->child_ll, child_i) {
|
||||
child_i->signal_cb(child_i, LV_SIGNAL_PARENT_SIZE_CHG, &ori);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user