feat(flex) add min/max-width/height handling to flex
This commit is contained in:
@@ -27,10 +27,22 @@ typedef struct {
|
|||||||
}flex_t;
|
}flex_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
lv_coord_t grow_unit;
|
lv_obj_t * item;
|
||||||
|
lv_coord_t min_size;
|
||||||
|
lv_coord_t max_size;
|
||||||
|
lv_coord_t final_size;
|
||||||
|
uint32_t grow_value;
|
||||||
|
uint32_t clamped :1;
|
||||||
|
}grow_dsc_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
lv_coord_t track_cross_size;
|
lv_coord_t track_cross_size;
|
||||||
lv_coord_t track_main_size;
|
lv_coord_t track_main_size; /*For all items*/
|
||||||
|
lv_coord_t track_fix_main_size; /*For non grow items*/
|
||||||
uint32_t item_cnt;
|
uint32_t item_cnt;
|
||||||
|
grow_dsc_t * grow_dsc;
|
||||||
|
uint32_t grow_item_cnt;
|
||||||
|
uint32_t grow_dsc_calc :1;
|
||||||
}track_t;
|
}track_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -155,6 +167,7 @@ static void flex_update(lv_obj_t * cont)
|
|||||||
track_t t;
|
track_t t;
|
||||||
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
|
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
|
||||||
/*Search the first item of the next row*/
|
/*Search the first item of the next row*/
|
||||||
|
t.grow_dsc_calc = 0;
|
||||||
next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t);
|
next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t);
|
||||||
total_track_cross_size += t.track_cross_size + track_gap;
|
total_track_cross_size += t.track_cross_size + track_gap;
|
||||||
track_cnt++;
|
track_cnt++;
|
||||||
@@ -176,6 +189,7 @@ static void flex_update(lv_obj_t * cont)
|
|||||||
|
|
||||||
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
|
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
|
||||||
track_t t;
|
track_t t;
|
||||||
|
t.grow_dsc_calc = 1;
|
||||||
/*Search the first item of the next row*/
|
/*Search the first item of the next row*/
|
||||||
next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t);
|
next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t);
|
||||||
|
|
||||||
@@ -184,7 +198,8 @@ static void flex_update(lv_obj_t * cont)
|
|||||||
}
|
}
|
||||||
children_repos(cont, &f, track_first_item, next_track_first_item, abs_x, abs_y, max_main_size, item_gap, &t);
|
children_repos(cont, &f, track_first_item, next_track_first_item, abs_x, abs_y, max_main_size, item_gap, &t);
|
||||||
track_first_item = next_track_first_item;
|
track_first_item = next_track_first_item;
|
||||||
|
lv_mem_buf_release(t.grow_dsc);
|
||||||
|
t.grow_dsc = NULL;
|
||||||
if(rtl && !f.row) {
|
if(rtl && !f.row) {
|
||||||
*cross_pos -= gap + track_gap;
|
*cross_pos -= gap + track_gap;
|
||||||
} else {
|
} else {
|
||||||
@@ -217,10 +232,11 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id
|
|||||||
|
|
||||||
lv_coord_t grow_sum = 0;
|
lv_coord_t grow_sum = 0;
|
||||||
t->track_main_size = 0;
|
t->track_main_size = 0;
|
||||||
uint32_t grow_item_cnt = 0;
|
t->track_fix_main_size = 0;
|
||||||
|
t->grow_item_cnt = 0;
|
||||||
t->track_cross_size = 0;
|
t->track_cross_size = 0;
|
||||||
t->grow_unit = 0;
|
|
||||||
t->item_cnt = 0;
|
t->item_cnt = 0;
|
||||||
|
t->grow_dsc = NULL;
|
||||||
|
|
||||||
int32_t item_id = item_start_id;
|
int32_t item_id = item_start_id;
|
||||||
|
|
||||||
@@ -229,15 +245,29 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id
|
|||||||
if(item_id != item_start_id && lv_obj_has_flag(item, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK)) break;
|
if(item_id != item_start_id && lv_obj_has_flag(item, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK)) break;
|
||||||
|
|
||||||
if(!lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) {
|
if(!lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) {
|
||||||
uint8_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
|
uint8_t grow_value = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
|
||||||
if(grow_size) {
|
if(grow_value) {
|
||||||
grow_sum += grow_size;
|
grow_sum += grow_value;
|
||||||
grow_item_cnt++;
|
t->grow_item_cnt++;
|
||||||
t->track_main_size += item_gap;
|
t->track_fix_main_size += item_gap;
|
||||||
|
if(t->grow_dsc_calc) {
|
||||||
|
grow_dsc_t * new_dsc = lv_mem_buf_get(sizeof(grow_dsc_t) * (t->grow_item_cnt));
|
||||||
|
LV_ASSERT_MALLOC(new_dsc);
|
||||||
|
if(new_dsc == NULL) return item_id;
|
||||||
|
|
||||||
|
lv_memcpy(new_dsc, t->grow_dsc, sizeof(grow_dsc_t) * (t->grow_item_cnt - 1));
|
||||||
|
lv_mem_buf_release(t->grow_dsc);
|
||||||
|
new_dsc[t->grow_item_cnt - 1].item = item;
|
||||||
|
new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item, LV_PART_MAIN) : lv_obj_get_style_min_height(item, LV_PART_MAIN);
|
||||||
|
new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item, LV_PART_MAIN) : lv_obj_get_style_max_height(item, LV_PART_MAIN);
|
||||||
|
new_dsc[t->grow_item_cnt - 1].grow_value = grow_value;
|
||||||
|
new_dsc[t->grow_item_cnt - 1].clamped = 0;
|
||||||
|
t->grow_dsc = new_dsc;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lv_coord_t item_size = get_main_size(item);
|
lv_coord_t item_size = get_main_size(item);
|
||||||
if(f->wrap && t->track_main_size + item_size > max_main_size) break;
|
if(f->wrap && t->track_fix_main_size + item_size > max_main_size) break;
|
||||||
t->track_main_size += item_size + item_gap;
|
t->track_fix_main_size += item_size + item_gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -250,15 +280,10 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id
|
|||||||
item = lv_obj_get_child(cont, item_id);
|
item = lv_obj_get_child(cont, item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t->track_main_size > 0) t->track_main_size -= item_gap; /*There is no gap after the last item*/
|
if(t->track_fix_main_size > 0) t->track_fix_main_size -= item_gap; /*There is no gap after the last item*/
|
||||||
|
|
||||||
if(grow_item_cnt && grow_sum) {
|
/*If there is at least one "grow item" the track takes the full space*/
|
||||||
lv_coord_t s = max_main_size - t->track_main_size; /*The remaining size for grow items*/
|
t->track_main_size = t->grow_item_cnt ? max_main_size : t->track_fix_main_size;
|
||||||
t->grow_unit = s / grow_sum;
|
|
||||||
t->track_main_size = max_main_size; /*If there is at least one "grow item" the track takes the full space*/
|
|
||||||
} else {
|
|
||||||
t->grow_unit = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Have at least one item in a row*/
|
/*Have at least one item in a row*/
|
||||||
if(item && item_id == item_start_id) {
|
if(item && item_id == item_start_id) {
|
||||||
@@ -283,6 +308,40 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i
|
|||||||
lv_coord_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height);
|
lv_coord_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height);
|
||||||
lv_coord_t (*area_get_cross_size)(const lv_area_t *) = (!f->row ? lv_area_get_width : lv_area_get_height);
|
lv_coord_t (*area_get_cross_size)(const lv_area_t *) = (!f->row ? lv_area_get_width : lv_area_get_height);
|
||||||
|
|
||||||
|
/*Calculate the size of grow items first*/
|
||||||
|
uint32_t i;
|
||||||
|
bool grow_reiterate = true;
|
||||||
|
while(grow_reiterate) {
|
||||||
|
grow_reiterate = false;
|
||||||
|
lv_coord_t grow_value_sum = 0;
|
||||||
|
lv_coord_t grow_max_size = t->track_main_size - t->track_fix_main_size;
|
||||||
|
for(i = 0; i < t->grow_item_cnt; i++) {
|
||||||
|
if(t->grow_dsc[i].clamped == 0) {
|
||||||
|
grow_value_sum += t->grow_dsc[i].grow_value;
|
||||||
|
} else {
|
||||||
|
grow_max_size -= t->grow_dsc[i].final_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lv_coord_t grow_unit;
|
||||||
|
|
||||||
|
for(i = 0; i < t->grow_item_cnt; i++) {
|
||||||
|
if(t->grow_dsc[i].clamped == 0) {
|
||||||
|
grow_unit = grow_max_size / grow_value_sum;
|
||||||
|
lv_coord_t size = grow_unit * t->grow_dsc[i].grow_value;
|
||||||
|
lv_coord_t size_clamp = LV_CLAMP(t->grow_dsc[i].min_size, size, t->grow_dsc[i].max_size);
|
||||||
|
|
||||||
|
if(size_clamp != size) {
|
||||||
|
t->grow_dsc[i].clamped = 1;
|
||||||
|
grow_reiterate = true;
|
||||||
|
}
|
||||||
|
t->grow_dsc[i].final_size = size_clamp;
|
||||||
|
grow_value_sum -= t->grow_dsc[i].grow_value;
|
||||||
|
grow_max_size -= t->grow_dsc[i].final_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rtl = lv_obj_get_base_dir(cont) == LV_BIDI_DIR_RTL ? true : false;
|
bool rtl = lv_obj_get_base_dir(cont) == LV_BIDI_DIR_RTL ? true : false;
|
||||||
|
|
||||||
lv_coord_t main_pos = 0;
|
lv_coord_t main_pos = 0;
|
||||||
@@ -298,12 +357,15 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i
|
|||||||
item = get_next_item(cont, f->rev, &item_first_id);
|
item = get_next_item(cont, f->rev, &item_first_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
uint8_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
|
lv_coord_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
|
||||||
if(grow_size) {
|
if(grow_size) {
|
||||||
|
lv_coord_t s = 0;
|
||||||
|
for(i = 0; i < t->grow_item_cnt; i++) {
|
||||||
|
if(t->grow_dsc[i].item == item) s = t->grow_dsc[i].final_size;
|
||||||
|
}
|
||||||
lv_area_t old_coords;
|
lv_area_t old_coords;
|
||||||
lv_area_copy(&old_coords, &item->coords);
|
lv_area_copy(&old_coords, &item->coords);
|
||||||
|
|
||||||
lv_coord_t s = grow_size * t->grow_unit;
|
|
||||||
area_set_main_size(&item->coords, s);
|
area_set_main_size(&item->coords, s);
|
||||||
|
|
||||||
if(f->row) item->w_layout = 1;
|
if(f->row) item->w_layout = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user