acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_grid.c (25245B)
1 /** 2 * @file lv_grid.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 *********************/ 9 #include "../lv_layouts.h" 10 11 #if LV_USE_GRID 12 13 /********************* 14 * DEFINES 15 *********************/ 16 /** 17 * Some helper defines 18 */ 19 #define IS_FR(x) (x >= LV_COORD_MAX - 100) 20 #define IS_CONTENT(x) (x == LV_COORD_MAX - 101) 21 #define GET_FR(x) (x - (LV_COORD_MAX - 100)) 22 23 /********************** 24 * TYPEDEFS 25 **********************/ 26 typedef struct { 27 uint32_t col; 28 uint32_t row; 29 lv_point_t grid_abs; 30 } item_repos_hint_t; 31 32 typedef struct { 33 lv_coord_t * x; 34 lv_coord_t * y; 35 lv_coord_t * w; 36 lv_coord_t * h; 37 uint32_t col_num; 38 uint32_t row_num; 39 lv_coord_t grid_w; 40 lv_coord_t grid_h; 41 } _lv_grid_calc_t; 42 43 44 /********************** 45 * GLOBAL PROTOTYPES 46 **********************/ 47 48 /********************** 49 * STATIC PROTOTYPES 50 **********************/ 51 static void grid_update(lv_obj_t * cont, void * user_data); 52 static void calc(lv_obj_t * obj, _lv_grid_calc_t * calc); 53 static void calc_free(_lv_grid_calc_t * calc); 54 static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c); 55 static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c); 56 static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint); 57 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, 58 lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse); 59 static uint32_t count_tracks(const lv_coord_t * templ); 60 61 static inline const lv_coord_t * get_col_dsc(lv_obj_t * obj) 62 { 63 return lv_obj_get_style_grid_column_dsc_array(obj, 0); 64 } 65 static inline const lv_coord_t * get_row_dsc(lv_obj_t * obj) 66 { 67 return lv_obj_get_style_grid_row_dsc_array(obj, 0); 68 } 69 static inline uint8_t get_col_pos(lv_obj_t * obj) 70 { 71 return lv_obj_get_style_grid_cell_column_pos(obj, 0); 72 } 73 static inline uint8_t get_row_pos(lv_obj_t * obj) 74 { 75 return lv_obj_get_style_grid_cell_row_pos(obj, 0); 76 } 77 static inline uint8_t get_col_span(lv_obj_t * obj) 78 { 79 return lv_obj_get_style_grid_cell_column_span(obj, 0); 80 } 81 static inline uint8_t get_row_span(lv_obj_t * obj) 82 { 83 return lv_obj_get_style_grid_cell_row_span(obj, 0); 84 } 85 static inline uint8_t get_cell_col_align(lv_obj_t * obj) 86 { 87 return lv_obj_get_style_grid_cell_x_align(obj, 0); 88 } 89 static inline uint8_t get_cell_row_align(lv_obj_t * obj) 90 { 91 return lv_obj_get_style_grid_cell_y_align(obj, 0); 92 } 93 static inline uint8_t get_grid_col_align(lv_obj_t * obj) 94 { 95 return lv_obj_get_style_grid_column_align(obj, 0); 96 } 97 static inline uint8_t get_grid_row_align(lv_obj_t * obj) 98 { 99 return lv_obj_get_style_grid_row_align(obj, 0); 100 } 101 102 /********************** 103 * GLOBAL VARIABLES 104 **********************/ 105 uint16_t LV_LAYOUT_GRID; 106 lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY; 107 lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN; 108 lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY; 109 lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN; 110 lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS; 111 lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN; 112 lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN; 113 lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS; 114 lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN; 115 lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN; 116 117 /********************** 118 * STATIC VARIABLES 119 **********************/ 120 121 /********************** 122 * MACROS 123 **********************/ 124 125 /********************** 126 * GLOBAL FUNCTIONS 127 **********************/ 128 129 130 void lv_grid_init(void) 131 { 132 LV_LAYOUT_GRID = lv_layout_register(grid_update, NULL); 133 134 LV_STYLE_GRID_COLUMN_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 135 LV_STYLE_GRID_ROW_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 136 LV_STYLE_GRID_COLUMN_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 137 LV_STYLE_GRID_ROW_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 138 139 LV_STYLE_GRID_CELL_ROW_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 140 LV_STYLE_GRID_CELL_ROW_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 141 LV_STYLE_GRID_CELL_COLUMN_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 142 LV_STYLE_GRID_CELL_COLUMN_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 143 LV_STYLE_GRID_CELL_X_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 144 LV_STYLE_GRID_CELL_Y_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 145 } 146 147 void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]) 148 { 149 lv_obj_set_style_grid_column_dsc_array(obj, col_dsc, 0); 150 lv_obj_set_style_grid_row_dsc_array(obj, row_dsc, 0); 151 lv_obj_set_style_layout(obj, LV_LAYOUT_GRID, 0); 152 } 153 154 void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align) 155 { 156 lv_obj_set_style_grid_column_align(obj, column_align, 0); 157 lv_obj_set_style_grid_row_align(obj, row_align, 0); 158 159 } 160 161 void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t x_align, uint8_t col_pos, uint8_t col_span, 162 lv_grid_align_t y_align, uint8_t row_pos, uint8_t row_span) 163 164 { 165 lv_obj_set_style_grid_cell_column_pos(obj, col_pos, 0); 166 lv_obj_set_style_grid_cell_row_pos(obj, row_pos, 0); 167 lv_obj_set_style_grid_cell_x_align(obj, x_align, 0); 168 lv_obj_set_style_grid_cell_column_span(obj, col_span, 0); 169 lv_obj_set_style_grid_cell_row_span(obj, row_span, 0); 170 lv_obj_set_style_grid_cell_y_align(obj, y_align, 0); 171 172 lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj)); 173 } 174 175 176 void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]) 177 { 178 lv_style_value_t v = { 179 .ptr = (const void *)value 180 }; 181 lv_style_set_prop(style, LV_STYLE_GRID_ROW_DSC_ARRAY, v); 182 } 183 184 void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]) 185 { 186 lv_style_value_t v = { 187 .ptr = (const void *)value 188 }; 189 lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v); 190 } 191 192 void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value) 193 { 194 lv_style_value_t v = { 195 .num = (lv_grid_align_t)value 196 }; 197 lv_style_set_prop(style, LV_STYLE_GRID_ROW_ALIGN, v); 198 } 199 200 void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value) 201 { 202 lv_style_value_t v = { 203 .num = (lv_grid_align_t)value 204 }; 205 lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_ALIGN, v); 206 } 207 208 209 void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value) 210 { 211 lv_style_value_t v = { 212 .num = value 213 }; 214 lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_POS, v); 215 } 216 217 void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value) 218 { 219 lv_style_value_t v = { 220 .num = value 221 }; 222 lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_SPAN, v); 223 } 224 225 void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value) 226 { 227 lv_style_value_t v = { 228 .num = value 229 }; 230 lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_POS, v); 231 } 232 233 void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value) 234 { 235 lv_style_value_t v = { 236 .num = value 237 }; 238 lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_SPAN, v); 239 } 240 241 void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value) 242 { 243 lv_style_value_t v = { 244 .num = value 245 }; 246 lv_style_set_prop(style, LV_STYLE_GRID_CELL_X_ALIGN, v); 247 } 248 249 void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value) 250 { 251 lv_style_value_t v = { 252 .num = value 253 }; 254 lv_style_set_prop(style, LV_STYLE_GRID_CELL_Y_ALIGN, v); 255 } 256 257 void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) 258 { 259 lv_style_value_t v = { 260 .ptr = (const void *)value 261 }; 262 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector); 263 } 264 265 void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) 266 { 267 lv_style_value_t v = { 268 .ptr = (const void *)value 269 }; 270 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v, selector); 271 } 272 273 274 void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) 275 { 276 lv_style_value_t v = { 277 .num = (int32_t) value 278 }; 279 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_ALIGN, v, selector); 280 } 281 282 void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) 283 { 284 lv_style_value_t v = { 285 .num = (int32_t) value 286 }; 287 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_ALIGN, v, selector); 288 } 289 290 291 void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) 292 { 293 lv_style_value_t v = { 294 .num = value 295 }; 296 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_POS, v, selector); 297 } 298 299 void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) 300 { 301 lv_style_value_t v = { 302 .num = value 303 }; 304 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector); 305 } 306 307 void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) 308 { 309 lv_style_value_t v = { 310 .num = value 311 }; 312 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_POS, v, selector); 313 } 314 315 void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) 316 { 317 lv_style_value_t v = { 318 .num = value 319 }; 320 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_SPAN, v, selector); 321 } 322 323 void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) 324 { 325 lv_style_value_t v = { 326 .num = value 327 }; 328 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_X_ALIGN, v, selector); 329 } 330 331 void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) 332 { 333 lv_style_value_t v = { 334 .num = value 335 }; 336 lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_Y_ALIGN, v, selector); 337 } 338 339 340 /********************** 341 * STATIC FUNCTIONS 342 **********************/ 343 344 static void grid_update(lv_obj_t * cont, void * user_data) 345 { 346 LV_LOG_INFO("update %p container", (void *)cont); 347 LV_UNUSED(user_data); 348 349 const lv_coord_t * col_templ = get_col_dsc(cont); 350 const lv_coord_t * row_templ = get_row_dsc(cont); 351 if(col_templ == NULL || row_templ == NULL) return; 352 353 _lv_grid_calc_t c; 354 calc(cont, &c); 355 356 item_repos_hint_t hint; 357 lv_memset_00(&hint, sizeof(hint)); 358 359 /*Calculate the grids absolute x and y coordinates. 360 *It will be used as helper during item repositioning to avoid calculating this value for every children*/ 361 lv_coord_t border_widt = lv_obj_get_style_border_width(cont, LV_PART_MAIN); 362 lv_coord_t pad_left = lv_obj_get_style_pad_left(cont, LV_PART_MAIN) + border_widt; 363 lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_PART_MAIN) + border_widt; 364 hint.grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_x(cont); 365 hint.grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_y(cont); 366 367 uint32_t i; 368 for(i = 0; i < cont->spec_attr->child_cnt; i++) { 369 lv_obj_t * item = cont->spec_attr->children[i]; 370 item_repos(item, &c, &hint); 371 } 372 calc_free(&c); 373 374 lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); 375 lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); 376 if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) { 377 lv_obj_refr_size(cont); 378 } 379 380 lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL); 381 382 LV_TRACE_LAYOUT("finished"); 383 } 384 385 /** 386 * Calculate the grid cells coordinates 387 * @param cont an object that has a grid 388 * @param calc store the calculated cells sizes here 389 * @note `_lv_grid_calc_free(calc_out)` needs to be called when `calc_out` is not needed anymore 390 */ 391 static void calc(lv_obj_t * cont, _lv_grid_calc_t * calc_out) 392 { 393 if(lv_obj_get_child(cont, 0) == NULL) { 394 lv_memset_00(calc_out, sizeof(_lv_grid_calc_t)); 395 return; 396 } 397 398 calc_rows(cont, calc_out); 399 calc_cols(cont, calc_out); 400 401 lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); 402 lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); 403 404 bool rev = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; 405 406 lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); 407 lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); 408 bool auto_w = (w_set == LV_SIZE_CONTENT && !cont->w_layout) ? true : false; 409 lv_coord_t cont_w = lv_obj_get_content_width(cont); 410 calc_out->grid_w = grid_align(cont_w, auto_w, get_grid_col_align(cont), col_gap, calc_out->col_num, calc_out->w, 411 calc_out->x, rev); 412 413 bool auto_h = (h_set == LV_SIZE_CONTENT && !cont->h_layout) ? true : false; 414 lv_coord_t cont_h = lv_obj_get_content_height(cont); 415 calc_out->grid_h = grid_align(cont_h, auto_h, get_grid_row_align(cont), row_gap, calc_out->row_num, calc_out->h, 416 calc_out->y, false); 417 418 LV_ASSERT_MEM_INTEGRITY(); 419 } 420 421 /** 422 * Free the a grid calculation's data 423 * @param calc pointer to the calculated grid cell coordinates 424 */ 425 static void calc_free(_lv_grid_calc_t * calc) 426 { 427 lv_mem_buf_release(calc->x); 428 lv_mem_buf_release(calc->y); 429 lv_mem_buf_release(calc->w); 430 lv_mem_buf_release(calc->h); 431 } 432 433 static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c) 434 { 435 const lv_coord_t * col_templ = get_col_dsc(cont); 436 lv_coord_t cont_w = lv_obj_get_content_width(cont); 437 438 c->col_num = count_tracks(col_templ); 439 c->x = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num); 440 c->w = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num); 441 442 /*Set sizes for CONTENT cells*/ 443 uint32_t i; 444 for(i = 0; i < c->col_num; i++) { 445 lv_coord_t size = LV_COORD_MIN; 446 if(IS_CONTENT(col_templ[i])) { 447 /*Check the size of children of this cell*/ 448 uint32_t ci; 449 for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) { 450 lv_obj_t * item = lv_obj_get_child(cont, ci); 451 if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; 452 uint32_t col_span = get_col_span(item); 453 if(col_span != 1) continue; 454 455 uint32_t col_pos = get_col_pos(item); 456 if(col_pos != i) continue; 457 458 size = LV_MAX(size, lv_obj_get_width(item)); 459 } 460 if(size >= 0) c->w[i] = size; 461 else c->w[i] = 0; 462 } 463 } 464 465 uint32_t col_fr_cnt = 0; 466 lv_coord_t grid_w = 0; 467 468 for(i = 0; i < c->col_num; i++) { 469 lv_coord_t x = col_templ[i]; 470 if(IS_FR(x)) { 471 col_fr_cnt += GET_FR(x); 472 } 473 else if(IS_CONTENT(x)) { 474 grid_w += c->w[i]; 475 } 476 else { 477 c->w[i] = x; 478 grid_w += x; 479 } 480 } 481 482 lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); 483 cont_w -= col_gap * (c->col_num - 1); 484 lv_coord_t free_w = cont_w - grid_w; 485 if(free_w < 0) free_w = 0; 486 487 int32_t last_fr_i = -1; 488 int32_t last_fr_x = 0; 489 for(i = 0; i < c->col_num; i++) { 490 lv_coord_t x = col_templ[i]; 491 if(IS_FR(x)) { 492 lv_coord_t f = GET_FR(x); 493 c->w[i] = (free_w * f) / col_fr_cnt; 494 last_fr_i = i; 495 last_fr_x = f; 496 } 497 } 498 499 /*To avoid rounding errors set the last FR track to the remaining size */ 500 if(last_fr_i >= 0) { 501 c->w[last_fr_i] = free_w - ((free_w * (col_fr_cnt - last_fr_x)) / col_fr_cnt); 502 } 503 } 504 505 static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c) 506 { 507 uint32_t i; 508 const lv_coord_t * row_templ = get_row_dsc(cont); 509 c->row_num = count_tracks(row_templ); 510 c->y = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num); 511 c->h = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num); 512 /*Set sizes for CONTENT cells*/ 513 for(i = 0; i < c->row_num; i++) { 514 lv_coord_t size = LV_COORD_MIN; 515 if(IS_CONTENT(row_templ[i])) { 516 /*Check the size of children of this cell*/ 517 uint32_t ci; 518 for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) { 519 lv_obj_t * item = lv_obj_get_child(cont, ci); 520 if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; 521 uint32_t row_span = get_row_span(item); 522 if(row_span != 1) continue; 523 524 uint32_t row_pos = get_row_pos(item); 525 if(row_pos != i) continue; 526 527 size = LV_MAX(size, lv_obj_get_height(item)); 528 } 529 if(size >= 0) c->h[i] = size; 530 else c->h[i] = 0; 531 } 532 } 533 534 uint32_t row_fr_cnt = 0; 535 lv_coord_t grid_h = 0; 536 537 for(i = 0; i < c->row_num; i++) { 538 lv_coord_t x = row_templ[i]; 539 if(IS_FR(x)) { 540 row_fr_cnt += GET_FR(x); 541 } 542 else if(IS_CONTENT(x)) { 543 grid_h += c->h[i]; 544 } 545 else { 546 c->h[i] = x; 547 grid_h += x; 548 } 549 } 550 551 552 lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); 553 lv_coord_t cont_h = lv_obj_get_content_height(cont) - row_gap * (c->row_num - 1); 554 lv_coord_t free_h = cont_h - grid_h; 555 if(free_h < 0) free_h = 0; 556 557 int32_t last_fr_i = -1; 558 int32_t last_fr_x = 0; 559 for(i = 0; i < c->row_num; i++) { 560 lv_coord_t x = row_templ[i]; 561 if(IS_FR(x)) { 562 lv_coord_t f = GET_FR(x); 563 c->h[i] = (free_h * f) / row_fr_cnt; 564 } 565 } 566 567 /*To avoid rounding errors set the last FR track to the remaining size */ 568 if(last_fr_i >= 0) { 569 c->h[last_fr_i] = free_h - ((free_h * (row_fr_cnt - last_fr_x)) / row_fr_cnt); 570 } 571 } 572 573 /** 574 * Reposition a grid item in its cell 575 * @param item a grid item to reposition 576 * @param calc the calculated grid of `cont` 577 * @param child_id_ext helper value if the ID of the child is know (order from the oldest) else -1 578 * @param grid_abs helper value, the absolute position of the grid, NULL if unknown 579 */ 580 static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint) 581 { 582 if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) return; 583 uint32_t col_span = get_col_span(item); 584 uint32_t row_span = get_row_span(item); 585 if(row_span == 0 || col_span == 0) return; 586 587 uint32_t col_pos = get_col_pos(item); 588 uint32_t row_pos = get_row_pos(item); 589 lv_grid_align_t col_align = get_cell_col_align(item); 590 lv_grid_align_t row_align = get_cell_row_align(item); 591 592 593 lv_coord_t col_x1 = c->x[col_pos]; 594 lv_coord_t col_x2 = c->x[col_pos + col_span - 1] + c->w[col_pos + col_span - 1]; 595 lv_coord_t col_w = col_x2 - col_x1; 596 597 lv_coord_t row_y1 = c->y[row_pos]; 598 lv_coord_t row_y2 = c->y[row_pos + row_span - 1] + c->h[row_pos + row_span - 1]; 599 lv_coord_t row_h = row_y2 - row_y1; 600 601 602 /*If the item has RTL base dir switch start and end*/ 603 if(lv_obj_get_style_base_dir(item, LV_PART_MAIN) == LV_BASE_DIR_RTL) { 604 if(col_align == LV_GRID_ALIGN_START) col_align = LV_GRID_ALIGN_END; 605 else if(col_align == LV_GRID_ALIGN_END) col_align = LV_GRID_ALIGN_START; 606 } 607 608 lv_coord_t x; 609 lv_coord_t y; 610 lv_coord_t item_w = lv_area_get_width(&item->coords); 611 lv_coord_t item_h = lv_area_get_height(&item->coords); 612 613 switch(col_align) { 614 default: 615 case LV_GRID_ALIGN_START: 616 x = c->x[col_pos]; 617 item->w_layout = 0; 618 break; 619 case LV_GRID_ALIGN_STRETCH: 620 x = c->x[col_pos]; 621 item_w = col_w; 622 item->w_layout = 1; 623 break; 624 case LV_GRID_ALIGN_CENTER: 625 x = c->x[col_pos] + (col_w - item_w) / 2; 626 item->w_layout = 0; 627 break; 628 case LV_GRID_ALIGN_END: 629 x = c->x[col_pos] + col_w - lv_obj_get_width(item); 630 item->w_layout = 0; 631 break; 632 } 633 634 switch(row_align) { 635 default: 636 case LV_GRID_ALIGN_START: 637 y = c->y[row_pos]; 638 item->h_layout = 0; 639 break; 640 case LV_GRID_ALIGN_STRETCH: 641 y = c->y[row_pos]; 642 item_h = row_h; 643 item->h_layout = 1; 644 break; 645 case LV_GRID_ALIGN_CENTER: 646 y = c->y[row_pos] + (row_h - item_h) / 2; 647 item->h_layout = 0; 648 break; 649 case LV_GRID_ALIGN_END: 650 y = c->y[row_pos] + row_h - lv_obj_get_height(item); 651 item->h_layout = 0; 652 break; 653 } 654 655 /*Set a new size if required*/ 656 if(lv_obj_get_width(item) != item_w || lv_obj_get_height(item) != item_h) { 657 lv_area_t old_coords; 658 lv_area_copy(&old_coords, &item->coords); 659 lv_obj_invalidate(item); 660 lv_area_set_width(&item->coords, item_w); 661 lv_area_set_height(&item->coords, item_h); 662 lv_obj_invalidate(item); 663 lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords); 664 lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item); 665 666 } 667 668 /*Handle percentage value of translate*/ 669 lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN); 670 lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN); 671 lv_coord_t w = lv_obj_get_width(item); 672 lv_coord_t h = lv_obj_get_height(item); 673 if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100; 674 if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100; 675 676 x += tr_x; 677 y += tr_y; 678 679 lv_coord_t diff_x = hint->grid_abs.x + x - item->coords.x1; 680 lv_coord_t diff_y = hint->grid_abs.y + y - item->coords.y1; 681 if(diff_x || diff_y) { 682 lv_obj_invalidate(item); 683 item->coords.x1 += diff_x; 684 item->coords.x2 += diff_x; 685 item->coords.y1 += diff_y; 686 item->coords.y2 += diff_y; 687 lv_obj_invalidate(item); 688 lv_obj_move_children_by(item, diff_x, diff_y, false); 689 } 690 } 691 692 /** 693 * Place the grid track according to align methods. It keeps the track sizes but sets their position. 694 * It can process both columns or rows according to the passed parameters. 695 * @param cont_size size of the containers content area (width/height) 696 * @param auto_size true: the container has auto size in the current direction 697 * @param align align method 698 * @param gap grid gap 699 * @param track_num number of tracks 700 * @param size_array array with the track sizes 701 * @param pos_array write the positions of the tracks here 702 * @return the total size of the grid 703 */ 704 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, 705 lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse) 706 { 707 lv_coord_t grid_size = 0; 708 uint32_t i; 709 710 if(auto_size) { 711 pos_array[0] = 0; 712 } 713 else { 714 /*With spaced alignment gap will be calculated from the remaining space*/ 715 if(align == LV_GRID_ALIGN_SPACE_AROUND || align == LV_GRID_ALIGN_SPACE_BETWEEN || align == LV_GRID_ALIGN_SPACE_EVENLY) { 716 gap = 0; 717 if(track_num == 1) align = LV_GRID_ALIGN_CENTER; 718 } 719 720 /*Get the full grid size with gap*/ 721 for(i = 0; i < track_num; i++) { 722 grid_size += size_array[i] + gap; 723 } 724 grid_size -= gap; 725 726 /*Calculate the position of the first item and set gap is necessary*/ 727 switch(align) { 728 case LV_GRID_ALIGN_START: 729 pos_array[0] = 0; 730 break; 731 case LV_GRID_ALIGN_CENTER: 732 pos_array[0] = (cont_size - grid_size) / 2; 733 break; 734 case LV_GRID_ALIGN_END: 735 pos_array[0] = cont_size - grid_size; 736 break; 737 case LV_GRID_ALIGN_SPACE_BETWEEN: 738 pos_array[0] = 0; 739 gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num - 1); 740 break; 741 case LV_GRID_ALIGN_SPACE_AROUND: 742 gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num); 743 pos_array[0] = gap / 2; 744 break; 745 case LV_GRID_ALIGN_SPACE_EVENLY: 746 gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num + 1); 747 pos_array[0] = gap; 748 break; 749 750 } 751 } 752 753 /*Set the position of all tracks from the start position, gaps and track sizes*/ 754 for(i = 0; i < track_num - 1; i++) { 755 pos_array[i + 1] = pos_array[i] + size_array[i] + gap; 756 } 757 758 lv_coord_t total_gird_size = pos_array[track_num - 1] + size_array[track_num - 1] - pos_array[0]; 759 760 if(reverse) { 761 for(i = 0; i < track_num; i++) { 762 pos_array[i] = cont_size - pos_array[i] - size_array[i]; 763 } 764 765 } 766 767 /*Return the full size of the grid*/ 768 return total_gird_size; 769 } 770 771 static uint32_t count_tracks(const lv_coord_t * templ) 772 { 773 uint32_t i; 774 for(i = 0; templ[i] != LV_GRID_TEMPLATE_LAST; i++); 775 776 return i; 777 } 778 779 780 #endif /*LV_USE_GRID*/