demo工程暂存 优化菜单界面UI和功能
This commit is contained in:
602
MCU/components/modules/lvgl/src/extra/layouts/flex/lv_flex.c
Normal file
602
MCU/components/modules/lvgl/src/extra/layouts/flex/lv_flex.c
Normal file
@ -0,0 +1,602 @@
|
||||
/**
|
||||
* @file lv_flex.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_layouts.h"
|
||||
|
||||
#if LV_USE_FLEX
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_flex_align_t main_place;
|
||||
lv_flex_align_t cross_place;
|
||||
lv_flex_align_t track_place;
|
||||
uint8_t row : 1;
|
||||
uint8_t wrap : 1;
|
||||
uint8_t rev : 1;
|
||||
} flex_t;
|
||||
|
||||
typedef struct {
|
||||
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_main_size; /*For all items*/
|
||||
lv_coord_t track_fix_main_size; /*For non grow items*/
|
||||
uint32_t item_cnt;
|
||||
grow_dsc_t * grow_dsc;
|
||||
uint32_t grow_item_cnt;
|
||||
uint32_t grow_dsc_calc : 1;
|
||||
} track_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void flex_update(lv_obj_t * cont, void * user_data);
|
||||
static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size,
|
||||
lv_coord_t item_gap, track_t * t);
|
||||
static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x,
|
||||
lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t);
|
||||
static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt,
|
||||
lv_coord_t * start_pos, lv_coord_t * gap);
|
||||
static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id);
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
uint16_t LV_LAYOUT_FLEX;
|
||||
lv_style_prop_t LV_STYLE_FLEX_FLOW;
|
||||
lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE;
|
||||
lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE;
|
||||
lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE;
|
||||
lv_style_prop_t LV_STYLE_FLEX_GROW;
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
void lv_flex_init(void)
|
||||
{
|
||||
LV_LAYOUT_FLEX = lv_layout_register(flex_update, NULL);
|
||||
|
||||
LV_STYLE_FLEX_FLOW = lv_style_register_prop(LV_STYLE_PROP_FLAG_NONE);
|
||||
LV_STYLE_FLEX_MAIN_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_FLEX_CROSS_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_FLEX_TRACK_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
}
|
||||
|
||||
void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow)
|
||||
{
|
||||
lv_obj_set_style_flex_flow(obj, flow, 0);
|
||||
lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0);
|
||||
}
|
||||
|
||||
void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place,
|
||||
lv_flex_align_t track_place)
|
||||
{
|
||||
lv_obj_set_style_flex_main_place(obj, main_place, 0);
|
||||
lv_obj_set_style_flex_cross_place(obj, cross_place, 0);
|
||||
lv_obj_set_style_flex_track_place(obj, track_place, 0);
|
||||
lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0);
|
||||
}
|
||||
|
||||
void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow)
|
||||
{
|
||||
lv_obj_set_style_flex_grow(obj, grow, 0);
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
|
||||
|
||||
void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_FLOW, v);
|
||||
}
|
||||
|
||||
void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_MAIN_PLACE, v);
|
||||
}
|
||||
|
||||
void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_CROSS_PLACE, v);
|
||||
}
|
||||
|
||||
void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_TRACK_PLACE, v);
|
||||
}
|
||||
|
||||
void lv_style_set_flex_grow(lv_style_t * style, uint8_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_GROW, v);
|
||||
}
|
||||
|
||||
|
||||
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_FLOW, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_MAIN_PLACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_CROSS_PLACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_TRACK_PLACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_GROW, v, selector);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void flex_update(lv_obj_t * cont, void * user_data)
|
||||
{
|
||||
LV_LOG_INFO("update %p container", (void *)cont);
|
||||
LV_UNUSED(user_data);
|
||||
|
||||
flex_t f;
|
||||
lv_flex_flow_t flow = lv_obj_get_style_flex_flow(cont, LV_PART_MAIN);
|
||||
f.row = flow & _LV_FLEX_COLUMN ? 0 : 1;
|
||||
f.wrap = flow & _LV_FLEX_WRAP ? 1 : 0;
|
||||
f.rev = flow & _LV_FLEX_REVERSE ? 1 : 0;
|
||||
f.main_place = lv_obj_get_style_flex_main_place(cont, LV_PART_MAIN);
|
||||
f.cross_place = lv_obj_get_style_flex_cross_place(cont, LV_PART_MAIN);
|
||||
f.track_place = lv_obj_get_style_flex_track_place(cont, LV_PART_MAIN);
|
||||
|
||||
bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
|
||||
lv_coord_t track_gap = !f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont,
|
||||
LV_PART_MAIN);
|
||||
lv_coord_t item_gap = f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont,
|
||||
LV_PART_MAIN);
|
||||
lv_coord_t max_main_size = (f.row ? lv_obj_get_content_width(cont) : lv_obj_get_content_height(cont));
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont,
|
||||
LV_PART_MAIN) + border_width - lv_obj_get_scroll_y(cont);
|
||||
lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont,
|
||||
LV_PART_MAIN) + border_width - lv_obj_get_scroll_x(cont);
|
||||
|
||||
lv_flex_align_t track_cross_place = f.track_place;
|
||||
lv_coord_t * cross_pos = (f.row ? &abs_y : &abs_x);
|
||||
|
||||
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
|
||||
|
||||
/*Content sized objects should squeezed the gap between the children, therefore any alignment will look like `START`*/
|
||||
if((f.row && h_set == LV_SIZE_CONTENT && cont->h_layout == 0) ||
|
||||
(!f.row && w_set == LV_SIZE_CONTENT && cont->w_layout == 0)) {
|
||||
track_cross_place = LV_FLEX_ALIGN_START;
|
||||
}
|
||||
|
||||
if(rtl && !f.row) {
|
||||
if(track_cross_place == LV_FLEX_ALIGN_START) track_cross_place = LV_FLEX_ALIGN_END;
|
||||
else if(track_cross_place == LV_FLEX_ALIGN_END) track_cross_place = LV_FLEX_ALIGN_START;
|
||||
}
|
||||
|
||||
lv_coord_t total_track_cross_size = 0;
|
||||
lv_coord_t gap = 0;
|
||||
uint32_t track_cnt = 0;
|
||||
int32_t track_first_item;
|
||||
int32_t next_track_first_item;
|
||||
|
||||
if(track_cross_place != LV_FLEX_ALIGN_START) {
|
||||
track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0;
|
||||
track_t t;
|
||||
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
|
||||
/*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);
|
||||
total_track_cross_size += t.track_cross_size + track_gap;
|
||||
track_cnt++;
|
||||
track_first_item = next_track_first_item;
|
||||
}
|
||||
|
||||
if(track_cnt) total_track_cross_size -= track_gap; /*No gap after the last track*/
|
||||
|
||||
/*Place the tracks to get the start position*/
|
||||
lv_coord_t max_cross_size = (f.row ? lv_obj_get_content_height(cont) : lv_obj_get_content_width(cont));
|
||||
place_content(track_cross_place, max_cross_size, total_track_cross_size, track_cnt, cross_pos, &gap);
|
||||
}
|
||||
|
||||
track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0;
|
||||
|
||||
if(rtl && !f.row) {
|
||||
*cross_pos += total_track_cross_size;
|
||||
}
|
||||
|
||||
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
|
||||
track_t t;
|
||||
t.grow_dsc_calc = 1;
|
||||
/*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);
|
||||
|
||||
if(rtl && !f.row) {
|
||||
*cross_pos -= t.track_cross_size;
|
||||
}
|
||||
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;
|
||||
lv_mem_buf_release(t.grow_dsc);
|
||||
t.grow_dsc = NULL;
|
||||
if(rtl && !f.row) {
|
||||
*cross_pos -= gap + track_gap;
|
||||
}
|
||||
else {
|
||||
*cross_pos += t.track_cross_size + gap + track_gap;
|
||||
}
|
||||
}
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
|
||||
if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) {
|
||||
lv_obj_refr_size(cont);
|
||||
}
|
||||
|
||||
lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL);
|
||||
|
||||
LV_TRACE_LAYOUT("finished");
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the last item of a track
|
||||
*/
|
||||
static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size,
|
||||
lv_coord_t item_gap, track_t * t)
|
||||
{
|
||||
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
|
||||
|
||||
/*Can't wrap if the size if auto (i.e. the size depends on the children)*/
|
||||
if(f->wrap && ((f->row && w_set == LV_SIZE_CONTENT) || (!f->row && h_set == LV_SIZE_CONTENT))) {
|
||||
f->wrap = false;
|
||||
}
|
||||
lv_coord_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width : lv_obj_get_height);
|
||||
lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width : lv_obj_get_height);
|
||||
|
||||
t->track_main_size = 0;
|
||||
t->track_fix_main_size = 0;
|
||||
t->grow_item_cnt = 0;
|
||||
t->track_cross_size = 0;
|
||||
t->item_cnt = 0;
|
||||
t->grow_dsc = NULL;
|
||||
|
||||
int32_t item_id = item_start_id;
|
||||
|
||||
lv_obj_t * item = lv_obj_get_child(cont, item_id);
|
||||
while(item) {
|
||||
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)) {
|
||||
uint8_t grow_value = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
|
||||
if(grow_value) {
|
||||
t->grow_item_cnt++;
|
||||
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;
|
||||
|
||||
if(t->grow_dsc) {
|
||||
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 {
|
||||
lv_coord_t item_size = get_main_size(item);
|
||||
if(f->wrap && t->track_fix_main_size + item_size > max_main_size) break;
|
||||
t->track_fix_main_size += item_size + item_gap;
|
||||
}
|
||||
|
||||
|
||||
t->track_cross_size = LV_MAX(get_cross_size(item), t->track_cross_size);
|
||||
t->item_cnt++;
|
||||
}
|
||||
|
||||
item_id += f->rev ? -1 : +1;
|
||||
if(item_id < 0) break;
|
||||
item = lv_obj_get_child(cont, item_id);
|
||||
}
|
||||
|
||||
if(t->track_fix_main_size > 0) t->track_fix_main_size -= item_gap; /*There is no gap after the last item*/
|
||||
|
||||
/*If there is at least one "grow item" the track takes the full space*/
|
||||
t->track_main_size = t->grow_item_cnt ? max_main_size : t->track_fix_main_size;
|
||||
|
||||
/*Have at least one item in a row*/
|
||||
if(item && item_id == item_start_id) {
|
||||
item = cont->spec_attr->children[item_id];
|
||||
get_next_item(cont, f->rev, &item_id);
|
||||
if(item) {
|
||||
t->track_cross_size = get_cross_size(item);
|
||||
t->track_main_size = get_main_size(item);
|
||||
t->item_cnt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return item_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Position the children in the same track
|
||||
*/
|
||||
static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x,
|
||||
lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t)
|
||||
{
|
||||
void (*area_set_main_size)(lv_area_t *, lv_coord_t) = (f->row ? lv_area_set_width : lv_area_set_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);
|
||||
|
||||
/*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) {
|
||||
LV_ASSERT(grow_value_sum != 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_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
|
||||
|
||||
lv_coord_t main_pos = 0;
|
||||
|
||||
lv_coord_t place_gap = 0;
|
||||
place_content(f->main_place, max_main_size, t->track_main_size, t->item_cnt, &main_pos, &place_gap);
|
||||
if(f->row && rtl) main_pos += lv_obj_get_content_width(cont);
|
||||
|
||||
lv_obj_t * item = lv_obj_get_child(cont, item_first_id);
|
||||
/*Reposition the children*/
|
||||
while(item && item_first_id != item_last_id) {
|
||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) {
|
||||
item = get_next_item(cont, f->rev, &item_first_id);
|
||||
continue;
|
||||
}
|
||||
lv_coord_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(f->row) {
|
||||
item->w_layout = 1;
|
||||
item->h_layout = 0;
|
||||
}
|
||||
else {
|
||||
item->h_layout = 1;
|
||||
item->w_layout = 0;
|
||||
}
|
||||
|
||||
if(s != area_get_main_size(&item->coords)) {
|
||||
lv_obj_invalidate(item);
|
||||
|
||||
lv_area_t old_coords;
|
||||
lv_area_copy(&old_coords, &item->coords);
|
||||
area_set_main_size(&item->coords, s);
|
||||
lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords);
|
||||
lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item);
|
||||
lv_obj_invalidate(item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
item->w_layout = 0;
|
||||
item->h_layout = 0;
|
||||
}
|
||||
|
||||
lv_coord_t cross_pos = 0;
|
||||
switch(f->cross_place) {
|
||||
case LV_FLEX_ALIGN_CENTER:
|
||||
/*Round up the cross size to avoid rounding error when dividing by 2
|
||||
*The issue comes up e,g, with column direction with center cross direction if an element's width changes*/
|
||||
cross_pos = (((t->track_cross_size + 1) & (~1)) - area_get_cross_size(&item->coords)) / 2;
|
||||
break;
|
||||
case LV_FLEX_ALIGN_END:
|
||||
cross_pos = t->track_cross_size - area_get_cross_size(&item->coords);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(f->row && rtl) main_pos -= area_get_main_size(&item->coords);
|
||||
|
||||
|
||||
/*Handle percentage value of translate*/
|
||||
lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN);
|
||||
lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN);
|
||||
lv_coord_t w = lv_obj_get_width(item);
|
||||
lv_coord_t h = lv_obj_get_height(item);
|
||||
if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100;
|
||||
if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100;
|
||||
|
||||
lv_coord_t diff_x = abs_x - item->coords.x1 + tr_x;
|
||||
lv_coord_t diff_y = abs_y - item->coords.y1 + tr_y;
|
||||
diff_x += f->row ? main_pos : cross_pos;
|
||||
diff_y += f->row ? cross_pos : main_pos;
|
||||
|
||||
if(diff_x || diff_y) {
|
||||
lv_obj_invalidate(item);
|
||||
item->coords.x1 += diff_x;
|
||||
item->coords.x2 += diff_x;
|
||||
item->coords.y1 += diff_y;
|
||||
item->coords.y2 += diff_y;
|
||||
lv_obj_invalidate(item);
|
||||
lv_obj_move_children_by(item, diff_x, diff_y, false);
|
||||
}
|
||||
|
||||
if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap;
|
||||
else main_pos -= item_gap + place_gap;
|
||||
|
||||
item = get_next_item(cont, f->rev, &item_first_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell a start coordinate and gap for a placement type.
|
||||
*/
|
||||
static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt,
|
||||
lv_coord_t * start_pos, lv_coord_t * gap)
|
||||
{
|
||||
if(item_cnt <= 1) {
|
||||
switch(place) {
|
||||
case LV_FLEX_ALIGN_SPACE_BETWEEN:
|
||||
case LV_FLEX_ALIGN_SPACE_AROUND:
|
||||
case LV_FLEX_ALIGN_SPACE_EVENLY:
|
||||
place = LV_FLEX_ALIGN_CENTER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(place) {
|
||||
case LV_FLEX_ALIGN_CENTER:
|
||||
*gap = 0;
|
||||
*start_pos += (max_size - content_size) / 2;
|
||||
break;
|
||||
case LV_FLEX_ALIGN_END:
|
||||
*gap = 0;
|
||||
*start_pos += max_size - content_size;
|
||||
break;
|
||||
case LV_FLEX_ALIGN_SPACE_BETWEEN:
|
||||
*gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt - 1);
|
||||
break;
|
||||
case LV_FLEX_ALIGN_SPACE_AROUND:
|
||||
*gap += (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt);
|
||||
*start_pos += *gap / 2;
|
||||
break;
|
||||
case LV_FLEX_ALIGN_SPACE_EVENLY:
|
||||
*gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt + 1);
|
||||
*start_pos += *gap;
|
||||
break;
|
||||
default:
|
||||
*gap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id)
|
||||
{
|
||||
if(rev) {
|
||||
(*item_id)--;
|
||||
if(*item_id >= 0) return cont->spec_attr->children[*item_id];
|
||||
else return NULL;
|
||||
}
|
||||
else {
|
||||
(*item_id)++;
|
||||
if((*item_id) < (int32_t)cont->spec_attr->child_cnt) return cont->spec_attr->children[*item_id];
|
||||
else return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FLEX*/
|
152
MCU/components/modules/lvgl/src/extra/layouts/flex/lv_flex.h
Normal file
152
MCU/components/modules/lvgl/src/extra/layouts/flex/lv_flex.h
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file lv_flex.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_FLEX_H
|
||||
#define LV_FLEX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../core/lv_obj.h"
|
||||
#if LV_USE_FLEX
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_OBJ_FLAG_FLEX_IN_NEW_TRACK LV_OBJ_FLAG_LAYOUT_1
|
||||
LV_EXPORT_CONST_INT(LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
|
||||
|
||||
#define _LV_FLEX_COLUMN (1 << 0)
|
||||
#define _LV_FLEX_WRAP (1 << 2)
|
||||
#define _LV_FLEX_REVERSE (1 << 3)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
struct _lv_obj_t;
|
||||
|
||||
typedef enum {
|
||||
LV_FLEX_ALIGN_START,
|
||||
LV_FLEX_ALIGN_END,
|
||||
LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_SPACE_EVENLY,
|
||||
LV_FLEX_ALIGN_SPACE_AROUND,
|
||||
LV_FLEX_ALIGN_SPACE_BETWEEN,
|
||||
} lv_flex_align_t;
|
||||
|
||||
typedef enum {
|
||||
LV_FLEX_FLOW_ROW = 0x00,
|
||||
LV_FLEX_FLOW_COLUMN = _LV_FLEX_COLUMN,
|
||||
LV_FLEX_FLOW_ROW_WRAP = LV_FLEX_FLOW_ROW | _LV_FLEX_WRAP,
|
||||
LV_FLEX_FLOW_ROW_REVERSE = LV_FLEX_FLOW_ROW | _LV_FLEX_REVERSE,
|
||||
LV_FLEX_FLOW_ROW_WRAP_REVERSE = LV_FLEX_FLOW_ROW | _LV_FLEX_WRAP | _LV_FLEX_REVERSE,
|
||||
LV_FLEX_FLOW_COLUMN_WRAP = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP,
|
||||
LV_FLEX_FLOW_COLUMN_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_REVERSE,
|
||||
LV_FLEX_FLOW_COLUMN_WRAP_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP | _LV_FLEX_REVERSE,
|
||||
} lv_flex_flow_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
extern uint16_t LV_LAYOUT_FLEX;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_FLOW;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_GROW;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize a flex layout the default values
|
||||
* @param flex pointer to a flex layout descriptor
|
||||
*/
|
||||
void lv_flex_init(void);
|
||||
|
||||
/**
|
||||
* Set hot the item should flow
|
||||
* @param flex pointer to a flex layout descriptor
|
||||
* @param flow an element of `lv_flex_flow_t`.
|
||||
*/
|
||||
void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow);
|
||||
|
||||
/**
|
||||
* Set how to place (where to align) the items and tracks
|
||||
* @param flex pointer: to a flex layout descriptor
|
||||
* @param main_place where to place the items on main axis (in their track). Any value of `lv_flex_align_t`.
|
||||
* @param cross_place where to place the item in their track on the cross axis. `LV_FLEX_ALIGN_START/END/CENTER`
|
||||
* @param track_place where to place the tracks in the cross direction. Any value of `lv_flex_align_t`.
|
||||
*/
|
||||
void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place,
|
||||
lv_flex_align_t track_cross_place);
|
||||
|
||||
/**
|
||||
* Sets the width or height (on main axis) to grow the object in order fill the free space
|
||||
* @param obj pointer to an object. The parent must have flex layout else nothing will happen.
|
||||
* @param grow a value to set how much free space to take proportionally to other growing items.
|
||||
*/
|
||||
void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow);
|
||||
|
||||
void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value);
|
||||
void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value);
|
||||
void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value);
|
||||
void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value);
|
||||
void lv_style_set_flex_grow(lv_style_t * style, uint8_t value);
|
||||
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector);
|
||||
|
||||
static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_FLOW);
|
||||
return (lv_flex_flow_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_MAIN_PLACE);
|
||||
return (lv_flex_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_CROSS_PLACE);
|
||||
return (lv_flex_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_TRACK_PLACE);
|
||||
return (lv_flex_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_GROW);
|
||||
return (uint8_t)v.num;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_FLEX*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_FLEX_H*/
|
782
MCU/components/modules/lvgl/src/extra/layouts/grid/lv_grid.c
Normal file
782
MCU/components/modules/lvgl/src/extra/layouts/grid/lv_grid.c
Normal file
@ -0,0 +1,782 @@
|
||||
/**
|
||||
* @file lv_grid.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_layouts.h"
|
||||
|
||||
#if LV_USE_GRID
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/**
|
||||
* Some helper defines
|
||||
*/
|
||||
#define IS_FR(x) (x >= LV_COORD_MAX - 100)
|
||||
#define IS_CONTENT(x) (x == LV_COORD_MAX - 101)
|
||||
#define GET_FR(x) (x - (LV_COORD_MAX - 100))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
uint32_t col;
|
||||
uint32_t row;
|
||||
lv_point_t grid_abs;
|
||||
} item_repos_hint_t;
|
||||
|
||||
typedef struct {
|
||||
lv_coord_t * x;
|
||||
lv_coord_t * y;
|
||||
lv_coord_t * w;
|
||||
lv_coord_t * h;
|
||||
uint32_t col_num;
|
||||
uint32_t row_num;
|
||||
lv_coord_t grid_w;
|
||||
lv_coord_t grid_h;
|
||||
} _lv_grid_calc_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void grid_update(lv_obj_t * cont, void * user_data);
|
||||
static void calc(lv_obj_t * obj, _lv_grid_calc_t * calc);
|
||||
static void calc_free(_lv_grid_calc_t * calc);
|
||||
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c);
|
||||
static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c);
|
||||
static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint);
|
||||
static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num,
|
||||
lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse);
|
||||
static uint32_t count_tracks(const lv_coord_t * templ);
|
||||
|
||||
static inline const lv_coord_t * get_col_dsc(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_column_dsc_array(obj, 0);
|
||||
}
|
||||
static inline const lv_coord_t * get_row_dsc(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_row_dsc_array(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_col_pos(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_column_pos(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_row_pos(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_row_pos(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_col_span(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_column_span(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_row_span(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_row_span(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_cell_col_align(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_x_align(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_cell_row_align(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_y_align(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_grid_col_align(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_column_align(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_grid_row_align(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_row_align(obj, 0);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
uint16_t LV_LAYOUT_GRID;
|
||||
lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY;
|
||||
lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN;
|
||||
lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY;
|
||||
lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN;
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
void lv_grid_init(void)
|
||||
{
|
||||
LV_LAYOUT_GRID = lv_layout_register(grid_update, NULL);
|
||||
|
||||
LV_STYLE_GRID_COLUMN_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_GRID_ROW_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_GRID_COLUMN_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_GRID_ROW_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
|
||||
LV_STYLE_GRID_CELL_ROW_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_GRID_CELL_ROW_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_GRID_CELL_COLUMN_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_GRID_CELL_COLUMN_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_GRID_CELL_X_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
LV_STYLE_GRID_CELL_Y_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR);
|
||||
}
|
||||
|
||||
void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[])
|
||||
{
|
||||
lv_obj_set_style_grid_column_dsc_array(obj, col_dsc, 0);
|
||||
lv_obj_set_style_grid_row_dsc_array(obj, row_dsc, 0);
|
||||
lv_obj_set_style_layout(obj, LV_LAYOUT_GRID, 0);
|
||||
}
|
||||
|
||||
void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align)
|
||||
{
|
||||
lv_obj_set_style_grid_column_align(obj, column_align, 0);
|
||||
lv_obj_set_style_grid_row_align(obj, row_align, 0);
|
||||
|
||||
}
|
||||
|
||||
void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t x_align, uint8_t col_pos, uint8_t col_span,
|
||||
lv_grid_align_t y_align, uint8_t row_pos, uint8_t row_span)
|
||||
|
||||
{
|
||||
lv_obj_set_style_grid_cell_column_pos(obj, col_pos, 0);
|
||||
lv_obj_set_style_grid_cell_row_pos(obj, row_pos, 0);
|
||||
lv_obj_set_style_grid_cell_x_align(obj, x_align, 0);
|
||||
lv_obj_set_style_grid_cell_column_span(obj, col_span, 0);
|
||||
lv_obj_set_style_grid_cell_row_span(obj, row_span, 0);
|
||||
lv_obj_set_style_grid_cell_y_align(obj, y_align, 0);
|
||||
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
|
||||
|
||||
void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[])
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = (const void *)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_ROW_DSC_ARRAY, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[])
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = (const void *)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (lv_grid_align_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_ROW_ALIGN, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (lv_grid_align_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_ALIGN, v);
|
||||
}
|
||||
|
||||
|
||||
void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_POS, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_SPAN, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_POS, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_SPAN, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_X_ALIGN, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_Y_ALIGN, v);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = (const void *)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = (const void *)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v, selector);
|
||||
}
|
||||
|
||||
|
||||
void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
|
||||
void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_POS, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_POS, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_SPAN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_X_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_Y_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void grid_update(lv_obj_t * cont, void * user_data)
|
||||
{
|
||||
LV_LOG_INFO("update %p container", (void *)cont);
|
||||
LV_UNUSED(user_data);
|
||||
|
||||
const lv_coord_t * col_templ = get_col_dsc(cont);
|
||||
const lv_coord_t * row_templ = get_row_dsc(cont);
|
||||
if(col_templ == NULL || row_templ == NULL) return;
|
||||
|
||||
_lv_grid_calc_t c;
|
||||
calc(cont, &c);
|
||||
|
||||
item_repos_hint_t hint;
|
||||
lv_memset_00(&hint, sizeof(hint));
|
||||
|
||||
/*Calculate the grids absolute x and y coordinates.
|
||||
*It will be used as helper during item repositioning to avoid calculating this value for every children*/
|
||||
lv_coord_t border_widt = lv_obj_get_style_border_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(cont, LV_PART_MAIN) + border_widt;
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_PART_MAIN) + border_widt;
|
||||
hint.grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_x(cont);
|
||||
hint.grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_y(cont);
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < cont->spec_attr->child_cnt; i++) {
|
||||
lv_obj_t * item = cont->spec_attr->children[i];
|
||||
item_repos(item, &c, &hint);
|
||||
}
|
||||
calc_free(&c);
|
||||
|
||||
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
|
||||
if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) {
|
||||
lv_obj_refr_size(cont);
|
||||
}
|
||||
|
||||
lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL);
|
||||
|
||||
LV_TRACE_LAYOUT("finished");
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the grid cells coordinates
|
||||
* @param cont an object that has a grid
|
||||
* @param calc store the calculated cells sizes here
|
||||
* @note `_lv_grid_calc_free(calc_out)` needs to be called when `calc_out` is not needed anymore
|
||||
*/
|
||||
static void calc(lv_obj_t * cont, _lv_grid_calc_t * calc_out)
|
||||
{
|
||||
if(lv_obj_get_child(cont, 0) == NULL) {
|
||||
lv_memset_00(calc_out, sizeof(_lv_grid_calc_t));
|
||||
return;
|
||||
}
|
||||
|
||||
calc_rows(cont, calc_out);
|
||||
calc_cols(cont, calc_out);
|
||||
|
||||
lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN);
|
||||
lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN);
|
||||
|
||||
bool rev = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
|
||||
|
||||
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
|
||||
bool auto_w = (w_set == LV_SIZE_CONTENT && !cont->w_layout) ? true : false;
|
||||
lv_coord_t cont_w = lv_obj_get_content_width(cont);
|
||||
calc_out->grid_w = grid_align(cont_w, auto_w, get_grid_col_align(cont), col_gap, calc_out->col_num, calc_out->w,
|
||||
calc_out->x, rev);
|
||||
|
||||
bool auto_h = (h_set == LV_SIZE_CONTENT && !cont->h_layout) ? true : false;
|
||||
lv_coord_t cont_h = lv_obj_get_content_height(cont);
|
||||
calc_out->grid_h = grid_align(cont_h, auto_h, get_grid_row_align(cont), row_gap, calc_out->row_num, calc_out->h,
|
||||
calc_out->y, false);
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the a grid calculation's data
|
||||
* @param calc pointer to the calculated grid cell coordinates
|
||||
*/
|
||||
static void calc_free(_lv_grid_calc_t * calc)
|
||||
{
|
||||
lv_mem_buf_release(calc->x);
|
||||
lv_mem_buf_release(calc->y);
|
||||
lv_mem_buf_release(calc->w);
|
||||
lv_mem_buf_release(calc->h);
|
||||
}
|
||||
|
||||
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c)
|
||||
{
|
||||
const lv_coord_t * col_templ = get_col_dsc(cont);
|
||||
lv_coord_t cont_w = lv_obj_get_content_width(cont);
|
||||
|
||||
c->col_num = count_tracks(col_templ);
|
||||
c->x = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num);
|
||||
c->w = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num);
|
||||
|
||||
/*Set sizes for CONTENT cells*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < c->col_num; i++) {
|
||||
lv_coord_t size = LV_COORD_MIN;
|
||||
if(IS_CONTENT(col_templ[i])) {
|
||||
/*Check the size of children of this cell*/
|
||||
uint32_t ci;
|
||||
for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) {
|
||||
lv_obj_t * item = lv_obj_get_child(cont, ci);
|
||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
uint32_t col_span = get_col_span(item);
|
||||
if(col_span != 1) continue;
|
||||
|
||||
uint32_t col_pos = get_col_pos(item);
|
||||
if(col_pos != i) continue;
|
||||
|
||||
size = LV_MAX(size, lv_obj_get_width(item));
|
||||
}
|
||||
if(size >= 0) c->w[i] = size;
|
||||
else c->w[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t col_fr_cnt = 0;
|
||||
lv_coord_t grid_w = 0;
|
||||
|
||||
for(i = 0; i < c->col_num; i++) {
|
||||
lv_coord_t x = col_templ[i];
|
||||
if(IS_FR(x)) {
|
||||
col_fr_cnt += GET_FR(x);
|
||||
}
|
||||
else if(IS_CONTENT(x)) {
|
||||
grid_w += c->w[i];
|
||||
}
|
||||
else {
|
||||
c->w[i] = x;
|
||||
grid_w += x;
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN);
|
||||
cont_w -= col_gap * (c->col_num - 1);
|
||||
lv_coord_t free_w = cont_w - grid_w;
|
||||
if(free_w < 0) free_w = 0;
|
||||
|
||||
int32_t last_fr_i = -1;
|
||||
int32_t last_fr_x = 0;
|
||||
for(i = 0; i < c->col_num; i++) {
|
||||
lv_coord_t x = col_templ[i];
|
||||
if(IS_FR(x)) {
|
||||
lv_coord_t f = GET_FR(x);
|
||||
c->w[i] = (free_w * f) / col_fr_cnt;
|
||||
last_fr_i = i;
|
||||
last_fr_x = f;
|
||||
}
|
||||
}
|
||||
|
||||
/*To avoid rounding errors set the last FR track to the remaining size */
|
||||
if(last_fr_i >= 0) {
|
||||
c->w[last_fr_i] = free_w - ((free_w * (col_fr_cnt - last_fr_x)) / col_fr_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c)
|
||||
{
|
||||
uint32_t i;
|
||||
const lv_coord_t * row_templ = get_row_dsc(cont);
|
||||
c->row_num = count_tracks(row_templ);
|
||||
c->y = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num);
|
||||
c->h = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num);
|
||||
/*Set sizes for CONTENT cells*/
|
||||
for(i = 0; i < c->row_num; i++) {
|
||||
lv_coord_t size = LV_COORD_MIN;
|
||||
if(IS_CONTENT(row_templ[i])) {
|
||||
/*Check the size of children of this cell*/
|
||||
uint32_t ci;
|
||||
for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) {
|
||||
lv_obj_t * item = lv_obj_get_child(cont, ci);
|
||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
uint32_t row_span = get_row_span(item);
|
||||
if(row_span != 1) continue;
|
||||
|
||||
uint32_t row_pos = get_row_pos(item);
|
||||
if(row_pos != i) continue;
|
||||
|
||||
size = LV_MAX(size, lv_obj_get_height(item));
|
||||
}
|
||||
if(size >= 0) c->h[i] = size;
|
||||
else c->h[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t row_fr_cnt = 0;
|
||||
lv_coord_t grid_h = 0;
|
||||
|
||||
for(i = 0; i < c->row_num; i++) {
|
||||
lv_coord_t x = row_templ[i];
|
||||
if(IS_FR(x)) {
|
||||
row_fr_cnt += GET_FR(x);
|
||||
}
|
||||
else if(IS_CONTENT(x)) {
|
||||
grid_h += c->h[i];
|
||||
}
|
||||
else {
|
||||
c->h[i] = x;
|
||||
grid_h += x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN);
|
||||
lv_coord_t cont_h = lv_obj_get_content_height(cont) - row_gap * (c->row_num - 1);
|
||||
lv_coord_t free_h = cont_h - grid_h;
|
||||
if(free_h < 0) free_h = 0;
|
||||
|
||||
int32_t last_fr_i = -1;
|
||||
int32_t last_fr_x = 0;
|
||||
for(i = 0; i < c->row_num; i++) {
|
||||
lv_coord_t x = row_templ[i];
|
||||
if(IS_FR(x)) {
|
||||
lv_coord_t f = GET_FR(x);
|
||||
c->h[i] = (free_h * f) / row_fr_cnt;
|
||||
last_fr_i = i;
|
||||
last_fr_x = f;
|
||||
}
|
||||
}
|
||||
|
||||
/*To avoid rounding errors set the last FR track to the remaining size */
|
||||
if(last_fr_i >= 0) {
|
||||
c->h[last_fr_i] = free_h - ((free_h * (row_fr_cnt - last_fr_x)) / row_fr_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reposition a grid item in its cell
|
||||
* @param item a grid item to reposition
|
||||
* @param calc the calculated grid of `cont`
|
||||
* @param child_id_ext helper value if the ID of the child is know (order from the oldest) else -1
|
||||
* @param grid_abs helper value, the absolute position of the grid, NULL if unknown
|
||||
*/
|
||||
static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint)
|
||||
{
|
||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) return;
|
||||
uint32_t col_span = get_col_span(item);
|
||||
uint32_t row_span = get_row_span(item);
|
||||
if(row_span == 0 || col_span == 0) return;
|
||||
|
||||
uint32_t col_pos = get_col_pos(item);
|
||||
uint32_t row_pos = get_row_pos(item);
|
||||
lv_grid_align_t col_align = get_cell_col_align(item);
|
||||
lv_grid_align_t row_align = get_cell_row_align(item);
|
||||
|
||||
|
||||
lv_coord_t col_x1 = c->x[col_pos];
|
||||
lv_coord_t col_x2 = c->x[col_pos + col_span - 1] + c->w[col_pos + col_span - 1];
|
||||
lv_coord_t col_w = col_x2 - col_x1;
|
||||
|
||||
lv_coord_t row_y1 = c->y[row_pos];
|
||||
lv_coord_t row_y2 = c->y[row_pos + row_span - 1] + c->h[row_pos + row_span - 1];
|
||||
lv_coord_t row_h = row_y2 - row_y1;
|
||||
|
||||
|
||||
/*If the item has RTL base dir switch start and end*/
|
||||
if(lv_obj_get_style_base_dir(item, LV_PART_MAIN) == LV_BASE_DIR_RTL) {
|
||||
if(col_align == LV_GRID_ALIGN_START) col_align = LV_GRID_ALIGN_END;
|
||||
else if(col_align == LV_GRID_ALIGN_END) col_align = LV_GRID_ALIGN_START;
|
||||
}
|
||||
|
||||
lv_coord_t x;
|
||||
lv_coord_t y;
|
||||
lv_coord_t item_w = lv_area_get_width(&item->coords);
|
||||
lv_coord_t item_h = lv_area_get_height(&item->coords);
|
||||
|
||||
switch(col_align) {
|
||||
default:
|
||||
case LV_GRID_ALIGN_START:
|
||||
x = c->x[col_pos];
|
||||
item->w_layout = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_STRETCH:
|
||||
x = c->x[col_pos];
|
||||
item_w = col_w;
|
||||
item->w_layout = 1;
|
||||
break;
|
||||
case LV_GRID_ALIGN_CENTER:
|
||||
x = c->x[col_pos] + (col_w - item_w) / 2;
|
||||
item->w_layout = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_END:
|
||||
x = c->x[col_pos] + col_w - lv_obj_get_width(item);
|
||||
item->w_layout = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(row_align) {
|
||||
default:
|
||||
case LV_GRID_ALIGN_START:
|
||||
y = c->y[row_pos];
|
||||
item->h_layout = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_STRETCH:
|
||||
y = c->y[row_pos];
|
||||
item_h = row_h;
|
||||
item->h_layout = 1;
|
||||
break;
|
||||
case LV_GRID_ALIGN_CENTER:
|
||||
y = c->y[row_pos] + (row_h - item_h) / 2;
|
||||
item->h_layout = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_END:
|
||||
y = c->y[row_pos] + row_h - lv_obj_get_height(item);
|
||||
item->h_layout = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Set a new size if required*/
|
||||
if(lv_obj_get_width(item) != item_w || lv_obj_get_height(item) != item_h) {
|
||||
lv_area_t old_coords;
|
||||
lv_area_copy(&old_coords, &item->coords);
|
||||
lv_obj_invalidate(item);
|
||||
lv_area_set_width(&item->coords, item_w);
|
||||
lv_area_set_height(&item->coords, item_h);
|
||||
lv_obj_invalidate(item);
|
||||
lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords);
|
||||
lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item);
|
||||
|
||||
}
|
||||
|
||||
/*Handle percentage value of translate*/
|
||||
lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN);
|
||||
lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN);
|
||||
lv_coord_t w = lv_obj_get_width(item);
|
||||
lv_coord_t h = lv_obj_get_height(item);
|
||||
if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100;
|
||||
if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100;
|
||||
|
||||
x += tr_x;
|
||||
y += tr_y;
|
||||
|
||||
lv_coord_t diff_x = hint->grid_abs.x + x - item->coords.x1;
|
||||
lv_coord_t diff_y = hint->grid_abs.y + y - item->coords.y1;
|
||||
if(diff_x || diff_y) {
|
||||
lv_obj_invalidate(item);
|
||||
item->coords.x1 += diff_x;
|
||||
item->coords.x2 += diff_x;
|
||||
item->coords.y1 += diff_y;
|
||||
item->coords.y2 += diff_y;
|
||||
lv_obj_invalidate(item);
|
||||
lv_obj_move_children_by(item, diff_x, diff_y, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Place the grid track according to align methods. It keeps the track sizes but sets their position.
|
||||
* It can process both columns or rows according to the passed parameters.
|
||||
* @param cont_size size of the containers content area (width/height)
|
||||
* @param auto_size true: the container has auto size in the current direction
|
||||
* @param align align method
|
||||
* @param gap grid gap
|
||||
* @param track_num number of tracks
|
||||
* @param size_array array with the track sizes
|
||||
* @param pos_array write the positions of the tracks here
|
||||
* @return the total size of the grid
|
||||
*/
|
||||
static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num,
|
||||
lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse)
|
||||
{
|
||||
lv_coord_t grid_size = 0;
|
||||
uint32_t i;
|
||||
|
||||
if(auto_size) {
|
||||
pos_array[0] = 0;
|
||||
}
|
||||
else {
|
||||
/*With spaced alignment gap will be calculated from the remaining space*/
|
||||
if(align == LV_GRID_ALIGN_SPACE_AROUND || align == LV_GRID_ALIGN_SPACE_BETWEEN || align == LV_GRID_ALIGN_SPACE_EVENLY) {
|
||||
gap = 0;
|
||||
if(track_num == 1) align = LV_GRID_ALIGN_CENTER;
|
||||
}
|
||||
|
||||
/*Get the full grid size with gap*/
|
||||
for(i = 0; i < track_num; i++) {
|
||||
grid_size += size_array[i] + gap;
|
||||
}
|
||||
grid_size -= gap;
|
||||
|
||||
/*Calculate the position of the first item and set gap is necessary*/
|
||||
switch(align) {
|
||||
case LV_GRID_ALIGN_START:
|
||||
pos_array[0] = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_CENTER:
|
||||
pos_array[0] = (cont_size - grid_size) / 2;
|
||||
break;
|
||||
case LV_GRID_ALIGN_END:
|
||||
pos_array[0] = cont_size - grid_size;
|
||||
break;
|
||||
case LV_GRID_ALIGN_SPACE_BETWEEN:
|
||||
pos_array[0] = 0;
|
||||
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num - 1);
|
||||
break;
|
||||
case LV_GRID_ALIGN_SPACE_AROUND:
|
||||
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num);
|
||||
pos_array[0] = gap / 2;
|
||||
break;
|
||||
case LV_GRID_ALIGN_SPACE_EVENLY:
|
||||
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num + 1);
|
||||
pos_array[0] = gap;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*Set the position of all tracks from the start position, gaps and track sizes*/
|
||||
for(i = 0; i < track_num - 1; i++) {
|
||||
pos_array[i + 1] = pos_array[i] + size_array[i] + gap;
|
||||
}
|
||||
|
||||
lv_coord_t total_gird_size = pos_array[track_num - 1] + size_array[track_num - 1] - pos_array[0];
|
||||
|
||||
if(reverse) {
|
||||
for(i = 0; i < track_num; i++) {
|
||||
pos_array[i] = cont_size - pos_array[i] - size_array[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*Return the full size of the grid*/
|
||||
return total_gird_size;
|
||||
}
|
||||
|
||||
static uint32_t count_tracks(const lv_coord_t * templ)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; templ[i] != LV_GRID_TEMPLATE_LAST; i++);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
#endif /*LV_USE_GRID*/
|
194
MCU/components/modules/lvgl/src/extra/layouts/grid/lv_grid.h
Normal file
194
MCU/components/modules/lvgl/src/extra/layouts/grid/lv_grid.h
Normal file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* @file lv_grid.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GRID_H
|
||||
#define LV_GRID_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../core/lv_obj.h"
|
||||
#if LV_USE_GRID
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/**
|
||||
* Can be used track size to make the track fill the free space.
|
||||
* @param x how much space to take proportionally to other FR tracks
|
||||
* @return a special track size
|
||||
*/
|
||||
#define LV_GRID_FR(x) (LV_COORD_MAX - 100 + x)
|
||||
|
||||
#define LV_GRID_CONTENT (LV_COORD_MAX - 101)
|
||||
LV_EXPORT_CONST_INT(LV_GRID_CONTENT);
|
||||
|
||||
#define LV_GRID_TEMPLATE_LAST (LV_COORD_MAX)
|
||||
LV_EXPORT_CONST_INT(LV_GRID_TEMPLATE_LAST);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
struct _lv_obj_t;
|
||||
|
||||
typedef enum {
|
||||
LV_GRID_ALIGN_START,
|
||||
LV_GRID_ALIGN_CENTER,
|
||||
LV_GRID_ALIGN_END,
|
||||
LV_GRID_ALIGN_STRETCH,
|
||||
LV_GRID_ALIGN_SPACE_EVENLY,
|
||||
LV_GRID_ALIGN_SPACE_AROUND,
|
||||
LV_GRID_ALIGN_SPACE_BETWEEN,
|
||||
} lv_grid_align_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
extern uint16_t LV_LAYOUT_GRID;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_grid_init(void);
|
||||
|
||||
void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]);
|
||||
|
||||
void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align);
|
||||
|
||||
/**
|
||||
* Set the cell of an object. The object's parent needs to have grid layout, else nothing will happen
|
||||
* @param obj pointer to an object
|
||||
* @param column_align the vertical alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH`
|
||||
* @param col_pos column ID
|
||||
* @param col_span number of columns to take (>= 1)
|
||||
* @param row_align the horizontal alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH`
|
||||
* @param row_pos row ID
|
||||
* @param row_span number of rows to take (>= 1)
|
||||
*/
|
||||
void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span,
|
||||
lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span);
|
||||
|
||||
/**
|
||||
* Just a wrapper to `LV_GRID_FR` for bindings.
|
||||
*/
|
||||
static inline lv_coord_t lv_grid_fr(uint8_t x)
|
||||
{
|
||||
return LV_GRID_FR(x);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]);
|
||||
void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]);
|
||||
void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value);
|
||||
void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value);
|
||||
void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value);
|
||||
|
||||
void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
|
||||
static inline const lv_coord_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_DSC_ARRAY);
|
||||
return (const lv_coord_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline const lv_coord_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_DSC_ARRAY);
|
||||
return (const lv_coord_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_ALIGN);
|
||||
return (lv_grid_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_ALIGN);
|
||||
return (lv_grid_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_POS);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_SPAN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_POS);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_SPAN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_X_ALIGN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_Y_ALIGN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_GRID*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GRID_H*/
|
44
MCU/components/modules/lvgl/src/extra/layouts/lv_layouts.h
Normal file
44
MCU/components/modules/lvgl/src/extra/layouts/lv_layouts.h
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file lv_layouts.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LAYOUTS_H
|
||||
#define LV_LAYOUTS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "flex/lv_flex.h"
|
||||
#include "grid/lv_grid.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_USE_LOG && LV_LOG_TRACE_LAYOUT
|
||||
# define LV_TRACE_LAYOUT(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
# define LV_TRACE_LAYOUT(...)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_LAYOUTS_H*/
|
Reference in New Issue
Block a user