feat(grid): add a basic subgrid implementation
This commit is contained in:
@@ -5,7 +5,7 @@ Grid
|
||||
Overview
|
||||
********
|
||||
|
||||
The Grid layout is a subset of `CSS Flexbox <https://css-tricks.com/snippets/css/complete-guide-grid/>`__.
|
||||
The Grid layout is a subset of `CSS Grid <https://css-tricks.com/snippets/css/complete-guide-grid/>`__.
|
||||
|
||||
It can arrange items into a 2D "table" that has rows or columns
|
||||
(tracks). The item can span through multiple columns or rows. The
|
||||
@@ -99,6 +99,24 @@ If there are some empty space the track can be aligned several ways:
|
||||
To set the track's alignment use
|
||||
:c:expr:`lv_obj_set_grid_align(obj, column_align, row_align)`.
|
||||
|
||||
|
||||
Sub grid
|
||||
--------
|
||||
|
||||
If you set the column and/or row grid descriptors of a widget to ``NULL`` it will use the grid descriptor(s) from it's parent.
|
||||
For example if you create a grid item on 2..6 columns and 1..3 rows of the parent,
|
||||
the grid item will see 5 columns and 4 rows with the corresponding track size from the parent.
|
||||
|
||||
This way even if a wrapper item is used on the grid and can be made "transparent" from the grid's point of view.
|
||||
|
||||
Limitations:
|
||||
|
||||
- The sub grid is resolved only in one level depth. That is a grid can have a sub grid children, but a sub grid can't have an other sub grid.
|
||||
- ``LV_GRID_CONTENT`` tracks on the are not handled in the sub grid, only in the its own grid.
|
||||
|
||||
The sub grid feature works the same as in CSS. For further reference see `this description <https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Subgrid>`__.
|
||||
|
||||
|
||||
Style interface
|
||||
***************
|
||||
|
||||
|
||||
@@ -180,9 +180,9 @@ 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;
|
||||
// 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);
|
||||
@@ -265,7 +265,28 @@ static void calc_free(_lv_grid_calc_t * calc)
|
||||
|
||||
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c)
|
||||
{
|
||||
const lv_coord_t * col_templ = get_col_dsc(cont);
|
||||
|
||||
const lv_coord_t * col_templ;
|
||||
col_templ = get_col_dsc(cont);
|
||||
bool subgrid = false;
|
||||
if(col_templ == NULL) {
|
||||
lv_obj_t * parent = lv_obj_get_parent(cont);
|
||||
col_templ = get_col_dsc(parent);
|
||||
if(col_templ == NULL) {
|
||||
LV_LOG_WARN("No col descriptor found even on the parent");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_coord_t pos = get_col_pos(cont);
|
||||
lv_coord_t span = get_col_span(cont);
|
||||
|
||||
lv_coord_t * col_templ_sub = lv_malloc(sizeof(lv_coord_t) * (span + 1));
|
||||
lv_memcpy(col_templ_sub, &col_templ[pos], sizeof(lv_coord_t) * span);
|
||||
col_templ_sub[span] = LV_GRID_TEMPLATE_LAST;
|
||||
col_templ = col_templ_sub;
|
||||
subgrid = true;
|
||||
}
|
||||
|
||||
lv_coord_t cont_w = lv_obj_get_content_width(cont);
|
||||
|
||||
c->col_num = count_tracks(col_templ);
|
||||
@@ -333,16 +354,41 @@ static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c)
|
||||
if(last_fr_i >= 0) {
|
||||
c->w[last_fr_i] = free_w - ((free_w * (col_fr_cnt - last_fr_x)) / col_fr_cnt);
|
||||
}
|
||||
|
||||
|
||||
if(subgrid) {
|
||||
lv_free((void *)col_templ);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
const lv_coord_t * row_templ;
|
||||
row_templ = get_row_dsc(cont);
|
||||
bool subgrid = false;
|
||||
if(row_templ == NULL) {
|
||||
lv_obj_t * parent = lv_obj_get_parent(cont);
|
||||
row_templ = get_row_dsc(parent);
|
||||
if(row_templ == NULL) {
|
||||
LV_LOG_WARN("No row descriptor found even on the parent");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_coord_t pos = get_row_pos(cont);
|
||||
lv_coord_t span = get_row_span(cont);
|
||||
|
||||
lv_coord_t * row_templ_sub = lv_malloc(sizeof(lv_coord_t) * (span + 1));
|
||||
lv_memcpy(row_templ_sub, &row_templ[pos], sizeof(lv_coord_t) * span);
|
||||
row_templ_sub[span] = LV_GRID_TEMPLATE_LAST;
|
||||
row_templ = row_templ_sub;
|
||||
subgrid = true;
|
||||
}
|
||||
|
||||
c->row_num = count_tracks(row_templ);
|
||||
c->y = lv_malloc(sizeof(lv_coord_t) * c->row_num);
|
||||
c->h = lv_malloc(sizeof(lv_coord_t) * c->row_num);
|
||||
/*Set sizes for CONTENT cells*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < c->row_num; i++) {
|
||||
lv_coord_t size = LV_COORD_MIN;
|
||||
if(IS_CONTENT(row_templ[i])) {
|
||||
@@ -403,6 +449,10 @@ static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c)
|
||||
if(last_fr_i >= 0) {
|
||||
c->h[last_fr_i] = free_h - ((free_h * (row_fr_cnt - last_fr_x)) / row_fr_cnt);
|
||||
}
|
||||
|
||||
if(subgrid) {
|
||||
lv_free((void *)row_templ);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
BIN
tests/ref_imgs/subgrid_col.png
Normal file
BIN
tests/ref_imgs/subgrid_col.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
tests/ref_imgs/subgrid_row.png
Normal file
BIN
tests/ref_imgs/subgrid_row.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
93
tests/src/test_cases/test_grid.c
Normal file
93
tests/src/test_cases/test_grid.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
/* Function run before every test */
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
/* Function run after every test */
|
||||
}
|
||||
|
||||
static void button_create(lv_obj_t * parent, const char * text, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
lv_obj_t * btn = lv_button_create(parent);
|
||||
lv_obj_set_grid_cell(btn, LV_GRID_ALIGN_STRETCH, x, 1, LV_GRID_ALIGN_STRETCH, y, 1);
|
||||
|
||||
lv_obj_t * label = lv_label_create(btn);
|
||||
lv_label_set_text(label, text);
|
||||
lv_obj_center(label);
|
||||
|
||||
}
|
||||
|
||||
void test_subgrid_row(void)
|
||||
{
|
||||
|
||||
const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
const lv_coord_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
lv_obj_t * cont_main = lv_obj_create(lv_scr_act());
|
||||
lv_obj_set_size(cont_main, 700, 300);
|
||||
lv_obj_center(cont_main);
|
||||
lv_obj_set_grid_dsc_array(cont_main, col_dsc, row_dsc);
|
||||
|
||||
const lv_coord_t col_dsc2[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
lv_obj_t * cont_sub = lv_obj_create(cont_main);
|
||||
lv_obj_set_grid_cell(cont_sub, LV_GRID_ALIGN_STRETCH, 1, 2, LV_GRID_ALIGN_STRETCH, 1, 2);
|
||||
lv_obj_set_grid_dsc_array(cont_sub, col_dsc2, NULL);
|
||||
lv_obj_set_style_pad_all(cont_sub, 0, 0);
|
||||
|
||||
|
||||
button_create(cont_main, "Main 0,0", 0, 0);
|
||||
button_create(cont_main, "Main 3,3", 3, 3);
|
||||
button_create(cont_main, "Main 2,2", 2, 2);
|
||||
button_create(cont_sub, "Sub 0,0", 0, 0);
|
||||
button_create(cont_sub, "Sub 1,0", 1, 0);
|
||||
button_create(cont_sub, "Sub 2,0", 2, 0);
|
||||
button_create(cont_sub, "Sub 3,0", 3, 0);
|
||||
button_create(cont_sub, "Sub 1,1", 1, 1);
|
||||
button_create(cont_sub, "Sub 0,1", 0, 1);
|
||||
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("subgrid_row.png");
|
||||
}
|
||||
|
||||
|
||||
void test_subgrid_col(void)
|
||||
{
|
||||
|
||||
const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
const lv_coord_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
lv_obj_t * cont_main = lv_obj_create(lv_scr_act());
|
||||
lv_obj_set_size(cont_main, 700, 300);
|
||||
lv_obj_center(cont_main);
|
||||
lv_obj_set_grid_dsc_array(cont_main, col_dsc, row_dsc);
|
||||
|
||||
const lv_coord_t row_dsc2[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
lv_obj_t * cont_sub = lv_obj_create(cont_main);
|
||||
lv_obj_set_grid_cell(cont_sub, LV_GRID_ALIGN_STRETCH, 1, 2, LV_GRID_ALIGN_STRETCH, 1, 2);
|
||||
lv_obj_set_grid_dsc_array(cont_sub, NULL, row_dsc2);
|
||||
lv_obj_set_style_pad_all(cont_sub, 0, 0);
|
||||
|
||||
|
||||
button_create(cont_main, "Main 0,0", 0, 0);
|
||||
button_create(cont_main, "Main 3,3", 3, 3);
|
||||
button_create(cont_main, "Main 2,2", 2, 2);
|
||||
button_create(cont_sub, "Sub 0,0", 0, 0);
|
||||
button_create(cont_sub, "Sub 0,1", 0, 1);
|
||||
button_create(cont_sub, "Sub 0,2", 0, 2);
|
||||
button_create(cont_sub, "Sub 0,3", 0, 3);
|
||||
button_create(cont_sub, "Sub 1,0", 1, 0);
|
||||
button_create(cont_sub, "Sub 1,1", 1, 1);
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("subgrid_col.png");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user