1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

add flexbox layout and percentage size

This commit is contained in:
Gabor Kiss-Vamosi 2020-10-16 13:00:53 +02:00
parent 7b48464241
commit ae452cbc22
13 changed files with 688 additions and 398 deletions

262
src/lv_core/lv_flex.c Normal file
View File

@ -0,0 +1,262 @@
/**
* @file lv_flex.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_flex.h"
#include "lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* 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 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);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_obj_set_flex_cont(lv_obj_t * obj, lv_flex_dir_t flex_dir)
{
if(obj->flex_dir != flex_dir) return;
obj->flex_dir = flex_dir;
_lv_flex_refresh(obj);
}
void lv_obj_set_flex_item(lv_obj_t * obj, lv_flex_place_t place)
{
lv_obj_set_pos(obj, place, place);
}
void _lv_flex_refresh(lv_obj_t * cont)
{
if(cont->flex_dir == LV_FLEX_DIR_NONE) return;
lv_dir_t main_dir;
switch(cont->flex_dir) {
case LV_FLEX_DIR_ROW:
main_dir = LV_DIR_HOR;
break;
case LV_FLEX_DIR_ROW_WRAP:
main_dir = LV_DIR_HOR;
break;
case LV_FLEX_DIR_COLUMN:
main_dir = LV_DIR_VER;
break;
case LV_FLEX_DIR_COLUMN_WRAP:
main_dir = LV_DIR_VER;
break;
}
/*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 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 row_place = LV_FLEX_START;
lv_coord_t all_track_size = 0;
lv_coord_t gap = 0;
uint32_t row_cnt = 0;
lv_coord_t grow_unit;
lv_coord_t track_size;
lv_obj_t * track_first_item;
lv_obj_t * next_track_first_item;
if(row_place != LV_FLEX_START) {
track_first_item = _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);
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));
place_content(row_place, max_cross_size, all_track_size,row_cnt, cross_pos, &gap);
}
track_first_item = _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);
children_repos(cont, track_first_item, next_track_first_item, main_dir, abs_x, abs_y, track_size, grow_unit);
track_first_item = next_track_first_item;
*cross_pos += track_size + gap;
}
}
/**********************
* 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)
{
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);
bool wrap;
if(cont->flex_dir == LV_FLEX_DIR_ROW_WRAP || cont->flex_dir == LV_FLEX_DIR_COLUMN_WRAP) {
wrap = true;
} else {
wrap = false;
}
lv_coord_t grow_sum = 0;
lv_coord_t used_size = 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);
if(LV_COORD_IS_FLEX(main_set) == false) {
item = _lv_ll_get_prev(&cont->child_ll, item);
continue;
}
lv_coord_t main_size = (main_dir == LV_DIR_HOR ? item->w_set : item->h_set);
if(_LV_FLEX_GET_GROW(main_size)) {
grow_sum += _LV_FLEX_GET_GROW(main_size);
} else {
lv_coord_t item_size = get_main_size(item);
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 = _lv_ll_get_prev(&cont->child_ll, item);
}
*grow_unit = grow_sum ? (max_size - used_size) / grow_sum : 0;
if(*grow_unit < 0) *grow_unit = 0;
/*Have at least one item in a row*/
if(item && item == item_start) {
item = _lv_ll_get_prev(&cont->child_ll, item);
if(item) *track_cross_size = get_cross_size(item);
}
return item;
}
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)
{
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);
void (*set_main_size)(lv_obj_t *, lv_coord_t) = (main_dir == LV_DIR_HOR ? lv_obj_set_width_margin : lv_obj_set_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);
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);
if(LV_COORD_IS_FLEX(main_set) == false) {
item = _lv_ll_get_prev(&cont->child_ll, item);
continue;
}
lv_coord_t main_size = (main_dir == LV_DIR_HOR ? 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;
set_main_size(item, s);
}
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) {
case LV_FLEX_CENTER:
cross_pos = (track_size - get_cross_size(item)) / 2;
break;
case LV_FLEX_END:
cross_pos = track_size - get_cross_size(item);
break;
}
lv_coord_t diff_x;
lv_coord_t diff_y;
if(main_dir == LV_DIR_HOR) {
diff_x = abs_x + main_pos - item->coords.x1;
diff_y = abs_y + cross_pos - item->coords.y1;
} else {
diff_x = abs_x + cross_pos - item->coords.x1;
diff_y = abs_y + main_pos - item->coords.y1;
}
if(diff_x || diff_y) {
item->coords.x1 += diff_x;
item->coords.x2 += diff_x;
item->coords.y1 += diff_y;
item->coords.y2 += diff_y;
_lv_obj_move_children_by(item, diff_x, diff_y);
}
main_pos += get_main_size(item);
item = _lv_ll_get_prev(&cont->child_ll, item);
}
}
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)
{
if(track_cnt <= 1) {
switch(place) {
case LV_FLEX_SPACE_BETWEEN:
case LV_FLEX_SPACE_AROUND:
case LV_FLEX_SPACE_EVENLY:
place = LV_FLEX_CENTER;
break;
}
}
switch(place) {
case LV_FLEX_CENTER:
*start_pos += (max_size - track_size) / 2;
break;
case LV_FLEX_END:
*start_pos += max_size - track_size;
break;
case LV_FLEX_SPACE_BETWEEN:
*gap = (lv_coord_t)(max_size - track_size) / (lv_coord_t)(track_cnt - 1);
break;
case LV_FLEX_SPACE_AROUND:
*gap += (lv_coord_t)(max_size - track_size) / (lv_coord_t)(track_cnt);
*start_pos += *gap / 2;
break;
case LV_FLEX_SPACE_EVENLY:
*gap = (lv_coord_t)(max_size - track_size) / (lv_coord_t)(track_cnt + 1);
*start_pos += *gap;
break;
default:
*gap = 0;
}
}

64
src/lv_core/lv_flex.h Normal file
View File

@ -0,0 +1,64 @@
/**
* @file lv_flex.h
*
*/
#ifndef LV_FLEX_H
#define LV_FLEX_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_grid.h"
/*********************
* DEFINES
*********************/
/** Can be set as width or height (on main axis) to grow the object in order fill the free space*/
#define LV_FLEX_GROW(grow) (_LV_COORD_FELX(grow))
#define _LV_FLEX_GET_GROW(v) (LV_COORD_IS_FLEX(v) ? LV_COORD_GET_FLEX(v) : 0)
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_FLEX_START = _LV_COORD_FELX(0),
LV_FLEX_END = _LV_COORD_FELX(1),
LV_FLEX_CENTER = _LV_COORD_FELX(2),
LV_FLEX_SPACE_EVENLY = _LV_COORD_FELX(3),
LV_FLEX_SPACE_AROUND = _LV_COORD_FELX(4),
LV_FLEX_SPACE_BETWEEN = _LV_COORD_FELX(5),
}lv_flex_place_t;
typedef enum {
LV_FLEX_DIR_NONE,
LV_FLEX_DIR_ROW,
LV_FLEX_DIR_ROW_WRAP,
LV_FLEX_DIR_COLUMN,
LV_FLEX_DIR_COLUMN_WRAP,
} lv_flex_dir_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_obj_set_flex_cont(lv_obj_t * obj, lv_flex_dir_t flex_dir);
void lv_obj_set_flex_item(lv_obj_t * obj, lv_flex_place_t place);
void _lv_flex_refresh(lv_obj_t * cont);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_FLEX_H*/

View File

@ -26,10 +26,8 @@ typedef struct {
/**********************
* STATIC PROTOTYPES
**********************/
static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void calc_implicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc, item_repos_hint_t * hint);
static lv_coord_t grid_place(lv_coord_t cont_size, bool auto_size, uint8_t place, lv_coord_t gap, uint32_t track_num, lv_coord_t * size_array, lv_coord_t * pos_array);
static void report_grid_change_core(const lv_grid_t * grid, lv_obj_t * obj);
@ -99,24 +97,17 @@ void lv_obj_report_grid_change(const lv_grid_t * grid)
void _lv_grid_calc(struct _lv_obj_t * cont, _lv_grid_calc_t * calc_out)
{
if(cont->grid == NULL) return;
if(cont->grid->col_dsc == NULL || cont->grid->row_dsc == NULL) return;
if(cont->grid->col_dsc_len == 0 || cont->grid->row_dsc_len == 0) return;
if(lv_obj_get_child(cont, NULL) == NULL) {
_lv_memset_00(calc_out, sizeof(_lv_grid_calc_t));
return;
}
// printf("calc: %d, %d\n", obj->grid->col_dsc_len, obj->grid->row_dsc_len);
if(cont->grid->col_dsc && cont->grid->row_dsc) {
calc_explicit_rows(cont, calc_out);
calc_explicit_cols(cont, calc_out);
}
else if(cont->grid->col_dsc && !cont->grid->row_dsc) {
calc_explicit_cols(cont, calc_out);
calc_implicit_rows(cont, calc_out);
}
else if(!cont->grid->col_dsc && cont->grid->row_dsc) {
calc_explicit_rows(cont, calc_out);
calc_implicit_cols(cont, calc_out);
}
calc_rows(cont, calc_out);
calc_cols(cont, calc_out);
bool auto_w = cont->w_set == LV_SIZE_AUTO ? true : false;
lv_coord_t cont_w = lv_obj_get_width_fit(cont);
@ -153,7 +144,7 @@ bool _lv_grid_has_fr_col(struct _lv_obj_t * obj)
uint32_t i;
for(i = 0; i < obj->grid->col_dsc_len; i++) {
if(_GRID_IS_FR(obj->grid->col_dsc[i])) return true;
if(LV_GRID_IS_FR(obj->grid->col_dsc[i])) return true;
}
return false;
@ -171,43 +162,12 @@ bool _lv_grid_has_fr_row(struct _lv_obj_t * obj)
uint32_t i;
for(i = 0; i < obj->grid->row_dsc_len; i++) {
if(_GRID_IS_FR(obj->grid->row_dsc[i])) return true;
if(LV_GRID_IS_FR(obj->grid->row_dsc[i])) return true;
}
return false;
}
/**
* Check if the object's grid columns are "fill" type
* @param obj pointer to an object
* @return true: fill type; false: not fill type
*/
bool _lv_grid_has_fill_col(struct _lv_obj_t * obj)
{
if(obj->grid == NULL) return false;
if(obj->grid->col_dsc == NULL) return false;
if(obj->grid->col_dsc_len != 1) return false;
if(_GRID_IS_FILL(obj->grid->col_dsc[0]) == false) return false;
return true;
}
/**
* Check if the object's grid rows are "fill" type
* @param obj pointer to an object
* @return true: fill type; false: not fill type
*/
bool _lv_grid_has_fill_row(struct _lv_obj_t * obj)
{
if(obj->grid == NULL) return false;
if(obj->grid->row_dsc == NULL) return false;
if(obj->grid->row_dsc_len != 1) return false;
if(_GRID_IS_FILL(obj->grid->row_dsc[0]) == false) return false;
return true;
}
/**
* Refresh the all grid item on a container
* @param cont pointer to a grid container object
@ -232,7 +192,7 @@ void _lv_grid_full_refresh(lv_obj_t * cont)
lv_obj_t * item = lv_obj_get_child_back(cont, NULL);
while(item) {
if(_GRID_IS_CELL(item->x_set) && _GRID_IS_CELL(item->y_set)) {
if(LV_COORD_IS_GRID(item->x_set) && LV_COORD_IS_GRID(item->y_set)) {
item_repos(cont, item, &calc, &hint);
}
item = lv_obj_get_child_back(cont, item);
@ -266,80 +226,46 @@ void lv_grid_item_refr_pos(lv_obj_t * item)
* STATIC FUNCTIONS
**********************/
static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc)
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * calc)
{
const lv_grid_t * grid = cont->grid;
uint32_t i;
lv_coord_t cont_w = lv_obj_get_width_fit(cont);
bool fill = false;
bool all = false;
if(grid->col_dsc_len == 1 && _GRID_IS_FILL(grid->col_dsc[0])) fill = true;
if(grid->col_dsc_len == 1 && _GRID_IS_REPEAT(grid->col_dsc[0])) all = true;
if(fill) {
lv_coord_t fill_w = _GRID_GET_FILL(grid->col_dsc[0]);
/* Get number of tracks fitting to the content
* Add the gap to cont_w because here is no gap after the last track so compensate it*/
calc->col_num = (cont_w + grid->col_gap) / (fill_w + grid->col_gap);
}
if(all) {
calc->col_num = lv_obj_count_children(cont);
}
else {
calc->col_num = grid->col_dsc_len;
}
calc->col_num = grid->col_dsc_len;
calc->x = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->col_num);
calc->w = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->col_num);
/*If filled, it's simple: every track has fill size*/
if(fill) {
lv_coord_t fill_w = _GRID_GET_FILL(grid->col_dsc[0]);
for(i = 0; i < calc->col_num; i++) {
calc->w[i] = fill_w;
uint32_t col_fr_cnt = 0;
lv_coord_t grid_w = 0;
bool auto_w = cont->w_set == LV_SIZE_AUTO ? true : false;
for(i = 0; i < calc->col_num; i++) {
lv_coord_t x = grid->col_dsc[i];
if(LV_GRID_IS_FR(x)) col_fr_cnt += LV_GRID_GET_FR(x);
else {
calc->w[i] = x;
grid_w += x;
}
}
/*If repeated, it's simple: every track has the "repeat size"*/
else if(all) {
lv_coord_t rep_w;
if(grid->col_dsc[0] == LV_GRID_REPEAT_FIT) rep_w = lv_obj_get_width_fit(cont);
else rep_w = _GRID_GET_REPEAT(grid->col_dsc[0]);
for(i = 0; i < calc->col_num; i++) {
calc->w[i] = rep_w;
}
}
else {
uint32_t col_fr_cnt = 0;
lv_coord_t grid_w = 0;
bool auto_w = cont->w_set == LV_SIZE_AUTO ? true : false;
cont_w -= grid->col_gap * (calc->col_num - 1);
lv_coord_t free_w = cont_w - grid_w;
for(i = 0; i < calc->col_num; i++) {
lv_coord_t x = grid->col_dsc[i];
if(_GRID_IS_FR(x)) col_fr_cnt += _GRID_GET_FR(x);
for(i = 0; i < calc->col_num; i++) {
lv_coord_t x = grid->col_dsc[i];
if(LV_GRID_IS_FR(x)) {
if(auto_w) calc->w[i] = 0; /*Fr is considered zero if the cont has auto width*/
else {
calc->w[i] = x;
grid_w += x;
}
}
cont_w -= grid->col_gap * (calc->col_num - 1);
lv_coord_t free_w = cont_w - grid_w;
for(i = 0; i < calc->col_num; i++) {
lv_coord_t x = grid->col_dsc[i];
if(_GRID_IS_FR(x)) {
if(auto_w) calc->w[i] = 0; /*Fr is considered zero if the cont has auto width*/
else {
lv_coord_t f = _GRID_GET_FR(x);
calc->w[i] = (free_w * f) / col_fr_cnt;
}
lv_coord_t f = LV_GRID_GET_FR(x);
calc->w[i] = (free_w * f) / col_fr_cnt;
}
}
}
}
static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
{
const lv_grid_t * grid = cont->grid;
uint32_t i;
@ -356,7 +282,7 @@ static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
for(i = 0; i < grid->row_dsc_len; i++) {
lv_coord_t x = grid->row_dsc[i];
if(_GRID_IS_FR(x)) row_fr_cnt += _GRID_GET_FR(x);
if(LV_GRID_IS_FR(x)) row_fr_cnt += LV_GRID_GET_FR(x);
else {
calc->h[i] = x;
grid_h += x;
@ -368,86 +294,16 @@ static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
for(i = 0; i < grid->row_dsc_len; i++) {
lv_coord_t x = grid->row_dsc[i];
if(_GRID_IS_FR(x)) {
if(LV_GRID_IS_FR(x)) {
if(auto_h) calc->h[i] = 0; /*Fr is considered zero if the obj has auto height*/
else {
lv_coord_t f = _GRID_GET_FR(x);
lv_coord_t f = LV_GRID_GET_FR(x);
calc->h[i] = (free_h * f) / row_fr_cnt;
}
}
}
}
static void calc_implicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc)
{
const lv_grid_t * grid = cont->grid;
uint32_t child_cnt = lv_obj_count_children(cont);
calc->col_num = ((child_cnt + grid->row_dsc_len - 1) / grid->row_dsc_len); /*+ grid->row_dsc_len - 1 to round up*/
calc->w = _lv_mem_buf_get(sizeof(lv_coord_t) * (calc->col_num + 1)); /*+1 to allow some limit checks later*/
calc->x = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->col_num);
lv_obj_t * child = lv_obj_get_child_back(cont, NULL);
uint32_t row_i = 0;
uint32_t col_i = 0;
calc->w[0] = 0;
while(child) {
if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) {
lv_coord_t w;
if(_GRID_GET_CELL_FLAG(child->x_set) == LV_GRID_STRETCH) {
lv_obj_scroll_to_x(child, 0, LV_ANIM_OFF);
_lv_obj_calc_auto_size(child, &w, NULL);
}
else w = lv_obj_get_width(child);
calc->w[col_i] = LV_MATH_MAX(calc->w[col_i], w);
row_i++;
if(row_i == grid->row_dsc_len) {
row_i = 0;
col_i++;
calc->w[col_i] = 0;
}
}
child = lv_obj_get_child_back(cont, child);
}
}
static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
{
const lv_grid_t * grid = cont->grid;
uint32_t child_cnt = lv_obj_count_children(cont);
calc->row_num = ((child_cnt + calc->col_num - 1) / calc->col_num); /*+ grid->col_dsc_len - 1 to round up*/
calc->h = _lv_mem_buf_get(sizeof(lv_coord_t) * (calc->row_num + 1)); /*+1 to allow some limit checks later*/
calc->y = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->row_num);
lv_obj_t * child = lv_obj_get_child_back(cont, NULL);
uint32_t col_i = 0;
uint32_t row_i = 0;
calc->h[0] = 0;
while(child) {
if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) {
lv_coord_t h;
if(_GRID_GET_CELL_FLAG(child->y_set) == LV_GRID_STRETCH) {
lv_obj_scroll_to_y(child, 0, LV_ANIM_OFF);
_lv_obj_calc_auto_size(child, NULL, &h);
}
else h = lv_obj_get_height(child);
calc->h[row_i] = LV_MATH_MAX(calc->h[row_i], h);
col_i++;
if(col_i == calc->col_num) {
col_i = 0;
row_i++;
calc->h[row_i] = 0;
}
}
child = lv_obj_get_child_back(cont, child);
}
}
/**
* Reposition a grid item in its cell
* @param cont a grid container object
@ -460,60 +316,10 @@ static void item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc,
{
if(_lv_obj_is_grid_item(item) == false) return;
uint32_t col_pos;
uint32_t col_span;
uint32_t row_pos;
uint32_t row_span;
if(cont->grid->row_dsc && cont->grid->col_dsc) {
col_pos = _GRID_GET_CELL_POS(item->x_set);
col_span = _GRID_GET_CELL_SPAN(item->x_set);
row_pos = _GRID_GET_CELL_POS(item->y_set);
row_span = _GRID_GET_CELL_SPAN(item->y_set);
} else {
col_span = 1;
row_span = 1;
if(hint) {
col_pos = hint->col;
row_pos = hint->row;
if(cont->grid->row_dsc == NULL) {
hint->col++;
if(hint->col >= calc->col_num) {
hint->col = 0;
hint->row++;
}
} else {
hint->row++;
if(hint->row >= calc->row_num) {
hint->row = 0;
hint->col++;
}
}
}
/*No hint -> find the child ID and calculate its col and row position */
else {
uint32_t child_id = 0;
lv_obj_t * child = lv_obj_get_child_back(cont, NULL);
while(child) {
if(child == item) break;
if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) {
child_id++;
}
child = lv_obj_get_child_back(cont, child);
}
if(cont->grid->row_dsc == NULL) {
col_pos = child_id % calc->col_num;
row_pos = child_id / calc->col_num;
} else {
col_pos = child_id / calc->row_num;
row_pos = child_id % calc->row_num;
}
}
}
uint32_t col_pos = LV_GRID_GET_CELL_POS(item->x_set);
uint32_t col_span = LV_GRID_GET_CELL_SPAN(item->x_set);
uint32_t row_pos = LV_GRID_GET_CELL_POS(item->y_set);
uint32_t row_span = LV_GRID_GET_CELL_SPAN(item->y_set);
lv_coord_t col_x1 = calc->x[col_pos];
lv_coord_t col_x2 = calc->x[col_pos + col_span - 1] + calc->w[col_pos + col_span - 1];
@ -523,8 +329,8 @@ static void item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc,
lv_coord_t row_y2 = calc->y[row_pos + row_span - 1] + calc->h[row_pos + row_span - 1];
lv_coord_t row_h = row_y2 - row_y1;
uint8_t x_flag = _GRID_GET_CELL_FLAG(item->x_set);
uint8_t y_flag = _GRID_GET_CELL_FLAG(item->y_set);
uint8_t x_flag = LV_GRID_GET_CELL_PLACE(item->x_set);
uint8_t y_flag = LV_GRID_GET_CELL_PLACE(item->y_set);
lv_coord_t x;
lv_coord_t y;
@ -575,15 +381,6 @@ static void item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc,
lv_obj_invalidate(item);
item->signal_cb(item, LV_SIGNAL_COORD_CHG, &old_coords);
/* If a children is a grid container and has an FR field it also needs to be updated
* because the FR cell size will change with child size change. */
lv_obj_t * child = lv_obj_get_child(item, NULL);
while(child) {
if(_lv_grid_has_fr_col(child) || _lv_grid_has_fr_row(child)) {
_lv_grid_full_refresh(child);
}
child = lv_obj_get_child(item, child);
}
}
bool moved = true;
if(hint) {
@ -613,7 +410,6 @@ static lv_coord_t grid_place(lv_coord_t cont_size, bool auto_size, uint8_t plac
if(auto_size) {
pos_array[0] = 0;
} else {
/*With spaced placements gap will be calculated from the remaining space*/
if(place == LV_GRID_SPACE_AROUND || place == LV_GRID_SPACE_BETWEEN || place == LV_GRID_SPACE_EVENLY) {
gap = 0;

View File

@ -19,6 +19,15 @@ extern "C" {
* DEFINES
*********************/
/**
* Some helper defines
* */
#define _LV_GRID_CELL_SHIFT 4
#define _LV_GRID_CELL_POS_MASK ((1 << _LV_GRID_CELL_SHIFT) - 1)
#define _LV_GRID_CELL_SPAN_MASK (_LV_GRID_CELL_POS_MASK << _LV_GRID_CELL_SHIFT)
#define _LV_GRID_CELL_FLAG_MASK (_LV_GRID_CELL_POS_MASK << (2 * _LV_GRID_CELL_SHIFT))
#define _LV_GRID_CELL_PLACE(b) ((b) << (_LV_GRID_CELL_SHIFT * 2))
#define LV_GRID_START 0
#define LV_GRID_CENTER 1
#define LV_GRID_END 2
@ -27,61 +36,18 @@ extern "C" {
#define LV_GRID_SPACE_AROUND 5
#define LV_GRID_SPACE_BETWEEN 6
/**
* Some helper defines
* */
#define _GRID_IS_CELL(c) ((c) >= LV_COORD_MAX ? true : false)
#define _GRID_CELL_SHIFT 5
#define _GRID_CELL_MAX ((1 << _GRID_CELL_SHIFT) - 1)
#define _GRID_CELL_POS_MASK ((1 << _GRID_CELL_SHIFT) - 1)
#define _GRID_CELL_SPAN_MASK (_GRID_CELL_POS_MASK << _GRID_CELL_SHIFT)
#define _GRID_CELL_FLAG_MASK (_GRID_CELL_POS_MASK << (2 * _GRID_CELL_SHIFT))
#define _GRID_CELL_FLAG(b) ((b) << (_GRID_CELL_SHIFT * 2))
#define _GRID_CELL_AUTO _GRID_CELL_MAX
#define _GRID_GET_CELL_POS(c) ((c) & _GRID_CELL_POS_MASK)
#define _GRID_GET_CELL_SPAN(c) (((c) & _GRID_CELL_SPAN_MASK) >> _GRID_CELL_SHIFT)
#define _GRID_GET_CELL_FLAG(c) ((c) >> (_GRID_CELL_SHIFT * 2) & 0x3)
#define LV_GRID_CELL_START(pos, span) (_LV_COORD_GRID((pos) | ((span) << (_LV_GRID_CELL_SHIFT)) | _LV_GRID_CELL_PLACE(LV_GRID_START)))
#define LV_GRID_CELL_END(pos, span) (_LV_COORD_GRID((pos) | ((span) << (_LV_GRID_CELL_SHIFT)) | _LV_GRID_CELL_PLACE(LV_GRID_END)))
#define LV_GRID_CELL_CENTER(pos, span) (_LV_COORD_GRID((pos) | ((span) << (_LV_GRID_CELL_SHIFT)) | _LV_GRID_CELL_PLACE(LV_GRID_CENTER)))
#define LV_GRID_CELL_STRETCH(pos, span) (_LV_COORD_GRID((pos) | ((span) << (_LV_GRID_CELL_SHIFT)) | _LV_GRID_CELL_PLACE(LV_GRID_STRETCH)))
#define _GRID_CELL_SIZE_PX 0 /* The cell size is set in pixels*/
#define _GRID_CELL_SIZE_FR 1 /* The cell size is set in free units*/
#define LV_GRID_GET_CELL_POS(c) ((c) & _LV_GRID_CELL_POS_MASK)
#define LV_GRID_GET_CELL_SPAN(c) (((c) & _LV_GRID_CELL_SPAN_MASK) >> _LV_GRID_CELL_SHIFT)
#define LV_GRID_GET_CELL_PLACE(c) ((c) >> (_LV_GRID_CELL_SHIFT * 2) & 0x7)
#define _GRID_FR_MAX 256
#define _GRID_FILL_MAX 2048
#define _GRID_REPEAT_MAX 2048
#define _GRID_FR_START (LV_COORD_MAX)
#define _GRID_FILL_START (_GRID_FR_START + _GRID_FR_MAX)
#define _GRID_REPEAT_START (_GRID_FILL_START + _GRID_FILL_MAX)
#define LV_GRID_FR(x) (_GRID_FR_START + (x))
#define LV_GRID_FILL(x) (_GRID_FILL_START + (x))
#define LV_GRID_REPEAT(x) (_GRID_REPEAT_START + (x))
#define LV_GRID_REPEAT_FIT (_GRID_REPEAT_START + _GRID_REPEAT_MAX - 1)
#define _GRID_IS_PX(x) ((_GRID_IS_FR(x) == false) && (_GRID_IS_AUTO(x) == false) ? true : false)
#define _GRID_IS_FR(x) ((x) > _GRID_FR_START && (x) < _GRID_FILL_START ? true : false)
#define _GRID_IS_FILL(x) ((x) > _GRID_FILL_START && (x) < _GRID_REPEAT_START ? true : false)
#define _GRID_IS_REPEAT(x) ((x) > _GRID_REPEAT_START ? true : false)
#define _GRID_IS_AUTO(x) (x == LV_GRID_AUTO ? true : false)
#define _GRID_GET_FR(x) ((x) - LV_COORD_MAX)
#define _GRID_GET_FILL(x) ((x) - _GRID_FILL_START)
#define _GRID_GET_REPEAT(x) ((x) - _GRID_REPEAT_START)
/**
* Define a grid cell with position and span.
* Can be used like `lv_obj_set_pos(btn, LV_GRID_CELL(3,2), LV_GRID_CELL(2,1))`
*/
#define LV_GRID_CELL_START(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_START))
#define LV_GRID_CELL_END(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_END))
#define LV_GRID_CELL_CENTER(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_CENTER))
#define LV_GRID_CELL_STRETCH(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_STRETCH))
/**
* Special LV_GRID_CELL position to flow the object automatically.
* Both X (column) and Y (row) value needs to be AUTO or explicitly specified*/
#define LV_GRID_AUTO_START LV_GRID_CELL_START(_GRID_CELL_AUTO, 0)
#define LV_GRID_AUTO_END LV_GRID_CELL_END(_GRID_CELL_AUTO, 0)
#define LV_GRID_AUTO_CENTER LV_GRID_CELL_CENTER(_GRID_CELL_AUTO, 0)
#define LV_GRID_AUTO_STRETCH LV_GRID_CELL_STRETCH(_GRID_CELL_AUTO, 0)
#define LV_GRID_FR(x) (_LV_COORD_GRID(x))
#define LV_GRID_IS_FR(x) (LV_COORD_IS_GRID(x))
#define LV_GRID_GET_FR(x) (LV_COORD_GET_GRID(x))
/**********************
* TYPEDEFS
@ -154,19 +120,6 @@ bool _lv_grid_has_fr_col(struct _lv_obj_t * obj);
bool _lv_grid_has_fr_row(struct _lv_obj_t * obj);
/**
* Check if the object's grid columns are "fill" type
* @param obj pointer to an object
* @return true: fill type; false: not fill type
*/
bool _lv_grid_has_fill_col(struct _lv_obj_t * obj);
/**
* Check if the object's grid rows are "fill" type
* @param obj pointer to an object
* @return true: fill type; false: not fill type
*/
bool _lv_grid_has_fill_row(struct _lv_obj_t * obj);
void _lv_grid_full_refresh(lv_obj_t * cont);
void lv_grid_item_refr_pos(lv_obj_t * item);

View File

@ -1906,19 +1906,31 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED);
}
else if(sign == LV_SIGNAL_COORD_CHG) {
bool col_fr = _lv_grid_has_fr_col(obj);
bool col_fill = _lv_grid_has_fill_col(obj);
bool row_fr = _lv_grid_has_fr_row(obj);
bool row_fill = _lv_grid_has_fill_row(obj);
if(param == NULL ||
(lv_area_get_width(param) != lv_obj_get_width(obj) && (col_fr || col_fill)) ||
(lv_area_get_height(param) != lv_obj_get_height(obj) && (row_fr || row_fill)))
{
_lv_grid_full_refresh(obj);
bool w_new = true;
bool h_new = true;
if(param) {
if(lv_area_get_width(param) == lv_obj_get_width(obj)) w_new = false;
if(lv_area_get_height(param) == lv_obj_get_height(obj)) h_new = false;
}
if(w_new || h_new) {
lv_coord_t cont_w = lv_obj_get_width_fit(obj);
lv_coord_t cont_h = lv_obj_get_height_fit(obj);
lv_obj_t * child;
_LV_LL_READ(obj->child_ll, child) {
if(LV_COORD_IS_PCT(child->w_set) && w_new) lv_obj_set_width(child, (LV_COORD_GET_PCT(child->w_set) * cont_w) / 100);
if(LV_COORD_IS_PCT(child->h_set) && h_new) lv_obj_set_height(child, (LV_COORD_GET_PCT(child->h_set) * cont_h) / 100);
}
if(obj->grid) _lv_grid_full_refresh(obj);
if(obj->flex_dir) _lv_flex_refresh(obj);
}
}
else if(sign == LV_SIGNAL_CHILD_CHG) {
if(param == NULL || _lv_obj_is_flex_item(param)) {
_lv_flex_refresh(obj);
}
if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) {
lv_obj_set_size(obj, obj->w_set, obj->h_set);
}
@ -1933,16 +1945,6 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
}
}
/* If the parent has an implicit grid in a direction and this object (whose child has changed)
* is stretched in that direction then the grid of the parent might have changed because
* the track size of implicit grids with stretched cells is calculated from the children bounding box.*/
lv_obj_t * par = lv_obj_get_parent(obj);
if(par && _lv_obj_is_grid_item(obj) &&
((par->grid->col_dsc == NULL && _GRID_GET_CELL_FLAG(obj->x_set) == LV_GRID_STRETCH) ||
(par->grid->row_dsc == NULL && _GRID_GET_CELL_FLAG(obj->y_set) == LV_GRID_STRETCH))) {
_lv_grid_full_refresh(par);
}
}
else if(sign == LV_SIGNAL_SCROLL) {
res = lv_event_send(obj, LV_EVENT_SCROLL, NULL);
@ -1965,7 +1967,7 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
/*Reposition non grid objects on by one*/
lv_obj_t * child = lv_obj_get_child(obj, NULL);
while(child) {
if(!_GRID_IS_CELL(child->x_set) || !_GRID_IS_CELL(child->y_set)) {
if(!LV_COORD_IS_GRID(child->x_set) || !LV_COORD_IS_GRID(child->y_set)) {
lv_obj_set_pos(child, child->x_set, child->y_set);
}
child = lv_obj_get_child(obj, child);

View File

@ -19,6 +19,7 @@ extern "C" {
#include <stdbool.h>
#include "lv_style.h"
#include "lv_grid.h"
#include "lv_flex.h"
#include "../lv_misc/lv_types.h"
#include "../lv_misc/lv_area.h"
#include "../lv_misc/lv_color.h"
@ -255,6 +256,8 @@ typedef struct _lv_obj_t {
const lv_grid_t * grid;
uint8_t flex_dir;
} lv_obj_t;
enum {

View File

@ -54,36 +54,30 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
obj->y_set = y;
bool gi = _lv_obj_is_grid_item(obj);
bool fi = _lv_obj_is_flex_item(obj);
/*For consistency set the size to stretched if the objects is stretched on the grid*/
if(gi) {
if(_GRID_GET_CELL_FLAG(obj->x_set) == LV_GRID_STRETCH) obj->w_set = LV_SIZE_STRETCH;
if(_GRID_GET_CELL_FLAG(obj->y_set) == LV_GRID_STRETCH) obj->h_set = LV_SIZE_STRETCH;
if(LV_GRID_GET_CELL_PLACE(obj->x_set) == LV_GRID_STRETCH) obj->w_set = LV_SIZE_STRETCH;
if(LV_GRID_GET_CELL_PLACE(obj->y_set) == LV_GRID_STRETCH) obj->h_set = LV_SIZE_STRETCH;
}
/*If not grid item but has grid position set the position to 0*/
/*If not grid or flex item but has grid or flex position set the position to 0*/
if(!gi) {
if(_GRID_IS_CELL(x)) {
x = 0;
}
if(_GRID_IS_CELL(y)) {
y = 0;
}
if(LV_COORD_IS_GRID(x)) x = 0;
if(LV_COORD_IS_GRID(y)) y = 0;
}
if(!fi) {
if(LV_COORD_IS_FLEX(x)) x = 0;
if(LV_COORD_IS_FLEX(y)) y = 0;
}
/*If the object is on a grid item let the grid to position it. */
if(gi) {
lv_obj_t * cont = lv_obj_get_parent(obj);
/*If the item was moved on an implicit grid the whole grid can change so refresh the full grid.*/
if(cont->grid->col_dsc == NULL || cont->grid->row_dsc == NULL)
{
_lv_grid_full_refresh(cont);
}
/*On explicit grids the grid itself doesn't depend on the items, so just position the item*/
else {
lv_grid_item_refr_pos(obj);
}
lv_grid_item_refr_pos(obj);
} else if(fi) {
_lv_flex_refresh(lv_obj_get_parent(obj));
} else {
_lv_obj_move_to(obj, x, y, true);
}
@ -124,12 +118,13 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h)
LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
bool gi = _lv_obj_is_grid_item(obj);
bool fi = _lv_obj_is_flex_item(obj);
bool x_stretch = false;
bool y_stretch = false;
if(gi) {
x_stretch = _GRID_GET_CELL_FLAG(obj->x_set) == LV_GRID_STRETCH ? true : false;
y_stretch = _GRID_GET_CELL_FLAG(obj->y_set) == LV_GRID_STRETCH ? true : false;
x_stretch = LV_GRID_GET_CELL_PLACE(obj->x_set) == LV_GRID_STRETCH ? true : false;
y_stretch = LV_GRID_GET_CELL_PLACE(obj->y_set) == LV_GRID_STRETCH ? true : false;
if(x_stretch) w = LV_SIZE_STRETCH;
if(y_stretch) h = LV_SIZE_STRETCH;
}
@ -137,7 +132,7 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h)
obj->w_set = w;
obj->h_set = h;
/*If both stretched it was already managed by the grid*/
/*If both stretched the size is managed by the grid*/
if(x_stretch && y_stretch) return;
if(x_stretch) w = lv_obj_get_width(obj);
@ -151,20 +146,20 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h)
if(x_auto) lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF);
if(y_auto) lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF);
lv_coord_t auto_w;
lv_coord_t auto_h;
if(x_auto && y_auto) {
_lv_obj_calc_auto_size(obj, &auto_w, &auto_h);
w = auto_w;
h = auto_h;
}
else if(x_auto) {
_lv_obj_calc_auto_size(obj, &auto_w, NULL);
w = auto_w;
}
else if(y_auto) {
_lv_obj_calc_auto_size(obj, NULL, &auto_h);
h = auto_h;
if(x_auto && y_auto) _lv_obj_calc_auto_size(obj, &w, &h);
else if(x_auto) _lv_obj_calc_auto_size(obj, &w, NULL);
else if(y_auto) _lv_obj_calc_auto_size(obj, NULL, &h);
/*Calculate the required auto sizes*/
bool pct_w = LV_COORD_IS_PCT(obj->w_set) ? true : false;
bool pct_h = LV_COORD_IS_PCT(obj->h_set) ? true : false;
lv_obj_t * parent = lv_obj_get_parent(obj);
if(parent) {
lv_coord_t cont_w = lv_obj_get_width_fit(parent);
lv_coord_t cont_h = lv_obj_get_height_fit(parent);
if(pct_w) w = (LV_COORD_GET_PCT(obj->w_set) * cont_w) / 100;
if(pct_h) h = (LV_COORD_GET_PCT(obj->h_set) * cont_h) / 100;
}
refr_size(obj, w, h);
@ -523,7 +518,7 @@ lv_coord_t lv_obj_get_height_fit(const lv_obj_t * obj)
* @param obj pointer to an object
* @return the height including the margins
*/
lv_coord_t lv_obj_get_height_margin(lv_obj_t * obj)
lv_coord_t lv_obj_get_height_margin(const lv_obj_t * obj)
{
lv_style_int_t mtop = lv_obj_get_style_margin_top(obj, LV_OBJ_PART_MAIN);
lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(obj, LV_OBJ_PART_MAIN);
@ -537,7 +532,7 @@ lv_coord_t lv_obj_get_height_margin(lv_obj_t * obj)
* @param obj pointer to an object
* @return the height including the margins
*/
lv_coord_t lv_obj_get_width_margin(lv_obj_t * obj)
lv_coord_t lv_obj_get_width_margin(const lv_obj_t * obj)
{
lv_style_int_t mleft = lv_obj_get_style_margin_left(obj, LV_OBJ_PART_MAIN);
lv_style_int_t mright = lv_obj_get_style_margin_right(obj, LV_OBJ_PART_MAIN);
@ -550,7 +545,7 @@ lv_coord_t lv_obj_get_width_margin(lv_obj_t * obj)
* @param obj pointer to an objects
* @return the width of the virtually drawn content
*/
lv_coord_t _lv_obj_get_self_width(lv_obj_t * obj)
lv_coord_t _lv_obj_get_self_width(struct _lv_obj_t * obj)
{
lv_point_t p = {0, LV_COORD_MIN};
lv_signal_send((lv_obj_t * )obj, LV_SIGNAL_GET_SELF_SIZE, &p);
@ -562,7 +557,7 @@ lv_coord_t _lv_obj_get_self_width(lv_obj_t * obj)
* @param obj pointer to an objects
* @return the width of the virtually drawn content
*/
lv_coord_t _lv_obj_get_self_height(lv_obj_t * obj)
lv_coord_t _lv_obj_get_self_height(struct _lv_obj_t * obj)
{
lv_point_t p = {LV_COORD_MIN, 0};
lv_signal_send((lv_obj_t * )obj, LV_SIGNAL_GET_SELF_SIZE, &p);
@ -574,7 +569,7 @@ lv_coord_t _lv_obj_get_self_height(lv_obj_t * obj)
* @param obj pointer to an object
* @return false: nothing happened; true: refresh happened
*/
bool _lv_obj_handle_self_size_chg(lv_obj_t * obj)
bool _lv_obj_handle_self_size_chg(struct _lv_obj_t * obj)
{
if(obj->w_set != LV_SIZE_AUTO && obj->h_set == LV_SIZE_AUTO) return false;
@ -650,7 +645,7 @@ void _lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, bool notify_par
y += pad_top + parent->coords.y1 - lv_obj_get_scroll_top(parent);
} else {
/*If no parent then it's screen but screen can't be on a grid*/
if(_GRID_IS_CELL(obj->x_set) || _GRID_IS_CELL(obj->x_set)) {
if(LV_COORD_IS_GRID(obj->x_set) || LV_COORD_IS_GRID(obj->x_set)) {
obj->x_set = 0;
obj->y_set = 0;
x = 0;
@ -722,10 +717,30 @@ bool _lv_obj_is_grid_item(lv_obj_t * obj)
lv_obj_t * cont = lv_obj_get_parent(obj);
if(cont == NULL) return false;
if(cont->grid == NULL) return false;
if(_GRID_IS_CELL(obj->x_set) && _GRID_IS_CELL(obj->y_set)) return true;
return false;
if(cont->grid->col_dsc == NULL) return false;
if(cont->grid->row_dsc == NULL) return false;
if(cont->grid->row_dsc_len == 0) return false;
if(cont->grid->col_dsc_len == 0) return false;
if(LV_COORD_IS_GRID(obj->x_set) == false || LV_COORD_IS_GRID(obj->y_set) == false) return false;
return true;
}
/**
* Check if an object is valid grid item or not.
* @param obj pointer to an object to check
* @return true: grid item; false: not grid item
*/
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(LV_COORD_IS_FLEX(obj->x_set) == false || LV_COORD_IS_FLEX(obj->y_set) == false) return false;
return true;
}
/**********************
* STATIC FUNCTIONS
**********************/
@ -753,6 +768,13 @@ static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h)
lv_area_t ori;
lv_obj_get_coords(obj, &ori);
/* Grow size is managed by the flexbox in `LV_SIGNAL_CHILD_CHG`
* So the real current value now.
* w or h has `LV_FLEX_GROW(x)` value which is a very large special value
* so it should be avoided to use such a special value as width*/
if(_LV_FLEX_GET_GROW(obj->w_set)) w = lv_obj_get_width(obj);
if(_LV_FLEX_GET_GROW(obj->h_set)) h = lv_obj_get_height(obj);
/* Set the length and height
* Be sure the content is not scrolled in an invalid position on the new size*/
obj->coords.y2 = obj->coords.y1 + h - 1;

View File

@ -33,11 +33,11 @@ struct _lv_obj_t;
* @param obj pointer to an object
* @param x new distance from the left side of the parent plus the parent's left padding or a grid cell
* @param y new distance from the top side of the parent plus the parent's right padding or a grid cell
* @note Zero value value means place the object is on the left padding of the parent, and not on the left edge.
* @note A grid cell can be and explicit placement with cell position and span:
* `LV_GRID_CELL_START/END/CENTER/STRETCH(pos, span)`
* or "auto" to place the object on the grid in the creation order of other children
* `LV_GRID_AUTO_START/END/CENTER/STRETCH`
* @note Zero value value means place the object on the left/top padding of the parent, and not on the left/top edge.
* @note For grid cells: `LV_GRID_CELL_START/END/CENTER/STRETCH(pos, span)`
* For flex items: `LV_FLEX_POS/START/END/CENTER`
* For percentage size: `LV_SIZE_PCT(pct)`
* For auto size (to set size to children size): `LV_SIZE_AUTO`
* @note to use grid placement the parent needs have a defined grid with `lv_obj_set_grid`
*/
void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
@ -188,7 +188,7 @@ lv_coord_t lv_obj_get_height_fit(const struct _lv_obj_t * obj);
* @param obj pointer to an object
* @return the height including the margins
*/
lv_coord_t lv_obj_get_height_margin(struct _lv_obj_t * obj);
lv_coord_t lv_obj_get_height_margin(const struct _lv_obj_t * obj);
/**
* Get the width of an object by taking the left and right margin into account.
@ -196,28 +196,28 @@ lv_coord_t lv_obj_get_height_margin(struct _lv_obj_t * obj);
* @param obj pointer to an object
* @return the height including the margins
*/
lv_coord_t lv_obj_get_width_margin(struct _lv_obj_t * obj);
lv_coord_t lv_obj_get_width_margin(const struct _lv_obj_t * obj);
/**
* Get the width of the virtual content of an object
* @param obj pointer to an objects
* @return the width of the virtually drawn content
*/
lv_coord_t _lv_obj_get_self_width(lv_obj_t * obj);
lv_coord_t _lv_obj_get_self_width(struct _lv_obj_t * obj);
/**
* Get the height of the virtual content of an object
* @param obj pointer to an objects
* @return the width of the virtually drawn content
*/
lv_coord_t _lv_obj_get_self_height(lv_obj_t * obj);
lv_coord_t _lv_obj_get_self_height(struct _lv_obj_t * obj);
/**
* Handle if the size of the internal (virtual) content of an object has changed.
* @param obj pointer to an object
* @return false: nothing happened; true: refresh happened
*/
bool _lv_obj_handle_self_size_chg(lv_obj_t * obj);
bool _lv_obj_handle_self_size_chg(struct _lv_obj_t * obj);
/**
* Calculate the "auto size". It's `auto_size = max(gird_size, children_size)`
@ -252,6 +252,8 @@ void _lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coor
*/
bool _lv_obj_is_grid_item(struct _lv_obj_t * obj);
bool _lv_obj_is_flex_item(struct _lv_obj_t * obj);
/**********************
* MACROS
**********************/

View File

@ -209,13 +209,33 @@ void _lv_area_align(const lv_area_t * base, const lv_area_t * to_align, lv_align
* MACROS
**********************/
#define LV_COORD_PX(x) (x)
#define LV_SIZE_AUTO (LV_COORD_MAX - 1)
#define LV_SIZE_STRETCH (LV_COORD_MAX - 2)
#define _LV_COORD_TYPE_SHIFT (13)
#define _LV_COORD_TYPE_MASK (3 << _LV_COORD_TYPE_SHIFT)
#define _LV_COORD_TYPE_PX (0 << _LV_COORD_TYPE_SHIFT)
#define _LV_COORD_TYPE_GRID (1 << _LV_COORD_TYPE_SHIFT)
#define _LV_COORD_TYPE_FLEX (2 << _LV_COORD_TYPE_SHIFT)
#define _LV_COORD_TYPE_SPEC (3 << _LV_COORD_TYPE_SHIFT)
#define LV_COORD_IS_PX(x) (((x) < LV_COORD_MAX - 2) ? true : false)
#define LV_COORD_IS_AUTO(x) (((x) == LV_SIZE_AUTO) ? true : false)
#define LV_COORD_IS_PX(x) ((((x) & _LV_COORD_TYPE_MASK) == _LV_COORD_TYPE_PX) ? true : false)
#define LV_COORD_IS_GRID(x) ((((x) & _LV_COORD_TYPE_MASK) == _LV_COORD_TYPE_GRID) ? true : false)
#define LV_COORD_IS_FLEX(x) ((((x) & _LV_COORD_TYPE_MASK) == _LV_COORD_TYPE_FLEX) ? true : false)
#define LV_COORD_IS_SPEC(x) ((((x) & _LV_COORD_TYPE_MASK) == _LV_COORD_TYPE_SPEC) ? true : false)
#define LV_COORD_GET_PX(x) ((x) & ~(_LV_COORD_TYPE_MASK))
#define LV_COORD_GET_GRID(x) ((x) & ~(_LV_COORD_TYPE_MASK))
#define LV_COORD_GET_FLEX(x) ((x) & ~(_LV_COORD_TYPE_MASK))
#define LV_COORD_GET_SPEC(x) ((x) & ~(_LV_COORD_TYPE_MASK))
#define _LV_COORD_GRID(x) (_LV_COORD_TYPE_GRID | (x))
#define _LV_COORD_FELX(x) (_LV_COORD_TYPE_FLEX | (x))
#define _LV_COORD_SPEC(x) (_LV_COORD_TYPE_SPEC | (x))
/*Special coordinates*/
#define LV_COORD_PCT(x) _LV_COORD_SPEC((x))
#define LV_COORD_IS_PCT(x) ((LV_COORD_IS_SPEC(x) && LV_COORD_GET_SPEC(x) <= 1000) ? true : false)
#define LV_COORD_GET_PCT(x) LV_COORD_GET_SPEC(x)
#define LV_SIZE_AUTO _LV_COORD_SPEC(1001)
#define LV_SIZE_STRETCH _LV_COORD_SPEC(1002)
#ifdef __cplusplus
} /* extern "C" */

View File

@ -25,7 +25,7 @@
*********************/
/*Add memory junk on alloc (0xaa) and free(0xbb) (just for testing purposes)*/
#ifndef LV_MEM_ADD_JUNK
#define LV_MEM_ADD_JUNK 1
#define LV_MEM_ADD_JUNK 0
#endif
#ifndef LV_MEM_FULL_DEFRAG_CNT

View File

@ -118,9 +118,7 @@ void lv_checkbox_set_text(lv_obj_t * cb, const char * txt)
strcpy(ext->txt, txt);
ext->static_txt = 0;
if(cb->w_set == LV_SIZE_AUTO || cb->h_set == LV_SIZE_AUTO) {
lv_obj_set_size(cb, cb->w_set, cb->h_set);
}
_lv_obj_handle_self_size_chg(cb);
}
/**
@ -138,9 +136,7 @@ void lv_checkbox_set_text_static(lv_obj_t * cb, const char * txt)
ext->txt = txt;
ext->static_txt = 1;
if(cb->w_set == LV_SIZE_AUTO || cb->h_set == LV_SIZE_AUTO) {
lv_obj_set_size(cb, cb->w_set, cb->h_set);
}
_lv_obj_handle_self_size_chg(cb);
}
/**

View File

@ -0,0 +1,170 @@
/**
* @file lv_linemeter.h
*
*/
#ifndef LV_LINEMETER_H
#define LV_LINEMETER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#if LV_USE_LINEMETER != 0
#include "../lv_core/lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/*Data of line meter*/
typedef struct {
/*No inherited ext.*/ /*Ext. of ancestor*/
/*New data for this type */
uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/
uint16_t angle_ofs;
uint16_t line_cnt; /*Count of lines */
int32_t cur_value;
int32_t min_value;
int32_t max_value;
uint8_t mirrored : 1;
} lv_linemeter_ext_t;
/*Styles*/
enum {
LV_LINEMETER_PART_MAIN,
_LV_LINEMETER_PART_VIRTUAL_LAST,
_LV_LINEMETER_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST,
};
typedef uint8_t lv_linemeter_part_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Create a line meter objects
* @param par pointer to an object, it will be the parent of the new line meter
* @param copy pointer to a line meter object, if not NULL then the new object will be copied from
* it
* @return pointer to the created line meter
*/
lv_obj_t * lv_linemeter_create(lv_obj_t * par, const lv_obj_t * copy);
/*=====================
* Setter functions
*====================*/
/**
* Set a new value on the line meter
* @param lmeter pointer to a line meter object
* @param value new value
*/
void lv_linemeter_set_value(lv_obj_t * lmeter, int32_t value);
/**
* Set minimum and the maximum values of a line meter
* @param lmeter pointer to he line meter object
* @param min minimum value
* @param max maximum value
*/
void lv_linemeter_set_range(lv_obj_t * lmeter, int32_t min, int32_t max);
/**
* Set the scale settings of a line meter
* @param lmeter pointer to a line meter object
* @param angle angle of the scale (0..360)
* @param line_cnt number of lines
*/
void lv_linemeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint16_t line_cnt);
/**
* Set the set an offset for the line meter's angles to rotate it.
* @param lmeter pointer to a line meter object
* @param angle angle offset (0..360), rotates clockwise
*/
void lv_linemeter_set_angle_offset(lv_obj_t * lmeter, uint16_t angle);
/**
* Set the orientation of the meter growth, clockwise or counterclockwise (mirrored)
* @param lmeter pointer to a line meter object
* @param mirror mirror setting
*/
void lv_linemeter_set_mirror(lv_obj_t * lmeter, bool mirror);
/*=====================
* Getter functions
*====================*/
/**
* Get the value of a line meter
* @param lmeter pointer to a line meter object
* @return the value of the line meter
*/
int32_t lv_linemeter_get_value(const lv_obj_t * lmeter);
/**
* Get the minimum value of a line meter
* @param lmeter pointer to a line meter object
* @return the minimum value of the line meter
*/
int32_t lv_linemeter_get_min_value(const lv_obj_t * lmeter);
/**
* Get the maximum value of a line meter
* @param lmeter pointer to a line meter object
* @return the maximum value of the line meter
*/
int32_t lv_linemeter_get_max_value(const lv_obj_t * lmeter);
/**
* Get the scale number of a line meter
* @param lmeter pointer to a line meter object
* @return number of the scale units
*/
uint16_t lv_linemeter_get_line_count(const lv_obj_t * lmeter);
/**
* Get the scale angle of a line meter
* @param lmeter pointer to a line meter object
* @return angle of the scale
*/
uint16_t lv_linemeter_get_scale_angle(const lv_obj_t * lmeter);
/**
* Get the offset for the line meter.
* @param lmeter pointer to a line meter object
* @return angle offset (0..360)
*/
uint16_t lv_linemeter_get_angle_offset(lv_obj_t * lmeter);
void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uint8_t part);
/**
* get the mirror setting for the line meter
* @param lmeter pointer to a line meter object
* @return mirror (true or false)
*/
bool lv_linemeter_get_mirror(lv_obj_t * lmeter);
/**********************
* MACROS
**********************/
#endif /*LV_USE_LINEMETER*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_LINEMETER_H*/

View File

@ -597,7 +597,7 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par
lv_obj_t * label = get_label(roller);
/*Be sure the label's style is updated before processing the roller*/
if(label) lv_signal_send(label, LV_SIGNAL_STYLE_CHG, NULL);
lv_obj_set_width(roller, roller->w_set);
_lv_obj_handle_self_size_chg(roller);
refr_position(roller, false);
}
else if(sign == LV_SIGNAL_COORD_CHG) {