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_flex.c (21866B)
1 /** 2 * @file lv_flex.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 *********************/ 9 #include "../lv_layouts.h" 10 11 #if LV_USE_FLEX 12 13 /********************* 14 * DEFINES 15 *********************/ 16 17 /********************** 18 * TYPEDEFS 19 **********************/ 20 typedef struct { 21 lv_flex_align_t main_place; 22 lv_flex_align_t cross_place; 23 lv_flex_align_t track_place; 24 uint8_t row : 1; 25 uint8_t wrap : 1; 26 uint8_t rev : 1; 27 } flex_t; 28 29 typedef struct { 30 lv_obj_t * item; 31 lv_coord_t min_size; 32 lv_coord_t max_size; 33 lv_coord_t final_size; 34 uint32_t grow_value; 35 uint32_t clamped : 1; 36 } grow_dsc_t; 37 38 typedef struct { 39 lv_coord_t track_cross_size; 40 lv_coord_t track_main_size; /*For all items*/ 41 lv_coord_t track_fix_main_size; /*For non grow items*/ 42 uint32_t item_cnt; 43 grow_dsc_t * grow_dsc; 44 uint32_t grow_item_cnt; 45 uint32_t grow_dsc_calc : 1; 46 } track_t; 47 48 49 /********************** 50 * GLOBAL PROTOTYPES 51 **********************/ 52 53 /********************** 54 * STATIC PROTOTYPES 55 **********************/ 56 static void flex_update(lv_obj_t * cont, void * user_data); 57 static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size, 58 lv_coord_t item_gap, track_t * t); 59 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, 60 lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t); 61 static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, 62 lv_coord_t * start_pos, lv_coord_t * gap); 63 static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id); 64 65 /********************** 66 * GLOBAL VARIABLES 67 **********************/ 68 uint16_t LV_LAYOUT_FLEX; 69 lv_style_prop_t LV_STYLE_FLEX_FLOW; 70 lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE; 71 lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE; 72 lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE; 73 lv_style_prop_t LV_STYLE_FLEX_GROW; 74 75 76 /********************** 77 * STATIC VARIABLES 78 **********************/ 79 80 /********************** 81 * MACROS 82 **********************/ 83 84 /********************** 85 * GLOBAL FUNCTIONS 86 **********************/ 87 88 /*===================== 89 * Setter functions 90 *====================*/ 91 92 void lv_flex_init(void) 93 { 94 LV_LAYOUT_FLEX = lv_layout_register(flex_update, NULL); 95 96 LV_STYLE_FLEX_FLOW = lv_style_register_prop(LV_STYLE_PROP_FLAG_NONE); 97 LV_STYLE_FLEX_MAIN_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 98 LV_STYLE_FLEX_CROSS_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 99 LV_STYLE_FLEX_TRACK_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); 100 } 101 102 void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow) 103 { 104 lv_obj_set_style_flex_flow(obj, flow, 0); 105 lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0); 106 } 107 108 void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, 109 lv_flex_align_t track_place) 110 { 111 lv_obj_set_style_flex_main_place(obj, main_place, 0); 112 lv_obj_set_style_flex_cross_place(obj, cross_place, 0); 113 lv_obj_set_style_flex_track_place(obj, track_place, 0); 114 lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0); 115 } 116 117 void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow) 118 { 119 lv_obj_set_style_flex_grow(obj, grow, 0); 120 lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj)); 121 } 122 123 124 void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value) 125 { 126 lv_style_value_t v = { 127 .num = (int32_t)value 128 }; 129 lv_style_set_prop(style, LV_STYLE_FLEX_FLOW, v); 130 } 131 132 void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value) 133 { 134 lv_style_value_t v = { 135 .num = (int32_t)value 136 }; 137 lv_style_set_prop(style, LV_STYLE_FLEX_MAIN_PLACE, v); 138 } 139 140 void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value) 141 { 142 lv_style_value_t v = { 143 .num = (int32_t)value 144 }; 145 lv_style_set_prop(style, LV_STYLE_FLEX_CROSS_PLACE, v); 146 } 147 148 void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value) 149 { 150 lv_style_value_t v = { 151 .num = (int32_t)value 152 }; 153 lv_style_set_prop(style, LV_STYLE_FLEX_TRACK_PLACE, v); 154 } 155 156 void lv_style_set_flex_grow(lv_style_t * style, uint8_t value) 157 { 158 lv_style_value_t v = { 159 .num = (int32_t)value 160 }; 161 lv_style_set_prop(style, LV_STYLE_FLEX_GROW, v); 162 } 163 164 165 void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector) 166 { 167 lv_style_value_t v = { 168 .num = (int32_t) value 169 }; 170 lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_FLOW, v, selector); 171 } 172 173 void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) 174 { 175 lv_style_value_t v = { 176 .num = (int32_t) value 177 }; 178 lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_MAIN_PLACE, v, selector); 179 } 180 181 void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) 182 { 183 lv_style_value_t v = { 184 .num = (int32_t) value 185 }; 186 lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_CROSS_PLACE, v, selector); 187 } 188 189 void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) 190 { 191 lv_style_value_t v = { 192 .num = (int32_t) value 193 }; 194 lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_TRACK_PLACE, v, selector); 195 } 196 197 void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector) 198 { 199 lv_style_value_t v = { 200 .num = (int32_t) value 201 }; 202 lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_GROW, v, selector); 203 } 204 205 /********************** 206 * STATIC FUNCTIONS 207 **********************/ 208 209 static void flex_update(lv_obj_t * cont, void * user_data) 210 { 211 LV_LOG_INFO("update %p container", (void *)cont); 212 LV_UNUSED(user_data); 213 214 flex_t f; 215 lv_flex_flow_t flow = lv_obj_get_style_flex_flow(cont, LV_PART_MAIN); 216 f.row = flow & _LV_FLEX_COLUMN ? 0 : 1; 217 f.wrap = flow & _LV_FLEX_WRAP ? 1 : 0; 218 f.rev = flow & _LV_FLEX_REVERSE ? 1 : 0; 219 f.main_place = lv_obj_get_style_flex_main_place(cont, LV_PART_MAIN); 220 f.cross_place = lv_obj_get_style_flex_cross_place(cont, LV_PART_MAIN); 221 f.track_place = lv_obj_get_style_flex_track_place(cont, LV_PART_MAIN); 222 223 bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; 224 lv_coord_t track_gap = !f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, 225 LV_PART_MAIN); 226 lv_coord_t item_gap = f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, 227 LV_PART_MAIN); 228 lv_coord_t max_main_size = (f.row ? lv_obj_get_content_width(cont) : lv_obj_get_content_height(cont)); 229 lv_coord_t border_width = lv_obj_get_style_border_width(cont, LV_PART_MAIN); 230 lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont, 231 LV_PART_MAIN) + border_width - lv_obj_get_scroll_y(cont); 232 lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont, 233 LV_PART_MAIN) + border_width - lv_obj_get_scroll_x(cont); 234 235 lv_flex_align_t track_cross_place = f.track_place; 236 lv_coord_t * cross_pos = (f.row ? &abs_y : &abs_x); 237 238 lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); 239 lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); 240 241 /*Content sized objects should squeezed the gap between the children, therefore any alignment will look like `START`*/ 242 if((f.row && h_set == LV_SIZE_CONTENT && cont->h_layout == 0) || 243 (!f.row && w_set == LV_SIZE_CONTENT && cont->w_layout == 0)) { 244 track_cross_place = LV_FLEX_ALIGN_START; 245 } 246 247 if(rtl && !f.row) { 248 if(track_cross_place == LV_FLEX_ALIGN_START) track_cross_place = LV_FLEX_ALIGN_END; 249 else if(track_cross_place == LV_FLEX_ALIGN_END) track_cross_place = LV_FLEX_ALIGN_START; 250 } 251 252 lv_coord_t total_track_cross_size = 0; 253 lv_coord_t gap = 0; 254 uint32_t track_cnt = 0; 255 int32_t track_first_item; 256 int32_t next_track_first_item; 257 258 if(track_cross_place != LV_FLEX_ALIGN_START) { 259 track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0; 260 track_t t; 261 while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) { 262 /*Search the first item of the next row*/ 263 t.grow_dsc_calc = 0; 264 next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t); 265 total_track_cross_size += t.track_cross_size + track_gap; 266 track_cnt++; 267 track_first_item = next_track_first_item; 268 } 269 270 if(track_cnt) total_track_cross_size -= track_gap; /*No gap after the last track*/ 271 272 /*Place the tracks to get the start position*/ 273 lv_coord_t max_cross_size = (f.row ? lv_obj_get_content_height(cont) : lv_obj_get_content_width(cont)); 274 place_content(track_cross_place, max_cross_size, total_track_cross_size, track_cnt, cross_pos, &gap); 275 } 276 277 track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0; 278 279 if(rtl && !f.row) { 280 *cross_pos += total_track_cross_size; 281 } 282 283 while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) { 284 track_t t; 285 t.grow_dsc_calc = 1; 286 /*Search the first item of the next row*/ 287 next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t); 288 289 if(rtl && !f.row) { 290 *cross_pos -= t.track_cross_size; 291 } 292 children_repos(cont, &f, track_first_item, next_track_first_item, abs_x, abs_y, max_main_size, item_gap, &t); 293 track_first_item = next_track_first_item; 294 lv_mem_buf_release(t.grow_dsc); 295 t.grow_dsc = NULL; 296 if(rtl && !f.row) { 297 *cross_pos -= gap + track_gap; 298 } 299 else { 300 *cross_pos += t.track_cross_size + gap + track_gap; 301 } 302 } 303 LV_ASSERT_MEM_INTEGRITY(); 304 305 if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) { 306 lv_obj_refr_size(cont); 307 } 308 309 lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL); 310 311 LV_TRACE_LAYOUT("finished"); 312 } 313 314 /** 315 * Find the last item of a track 316 */ 317 static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size, 318 lv_coord_t item_gap, track_t * t) 319 { 320 lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); 321 lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); 322 323 /*Can't wrap if the size if auto (i.e. the size depends on the children)*/ 324 if(f->wrap && ((f->row && w_set == LV_SIZE_CONTENT) || (!f->row && h_set == LV_SIZE_CONTENT))) { 325 f->wrap = false; 326 } 327 lv_coord_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width : lv_obj_get_height); 328 lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width : lv_obj_get_height); 329 330 t->track_main_size = 0; 331 t->track_fix_main_size = 0; 332 t->grow_item_cnt = 0; 333 t->track_cross_size = 0; 334 t->item_cnt = 0; 335 t->grow_dsc = NULL; 336 337 int32_t item_id = item_start_id; 338 339 lv_obj_t * item = lv_obj_get_child(cont, item_id); 340 while(item) { 341 if(item_id != item_start_id && lv_obj_has_flag(item, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK)) break; 342 343 if(!lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) { 344 uint8_t grow_value = lv_obj_get_style_flex_grow(item, LV_PART_MAIN); 345 if(grow_value) { 346 t->grow_item_cnt++; 347 t->track_fix_main_size += item_gap; 348 if(t->grow_dsc_calc) { 349 grow_dsc_t * new_dsc = lv_mem_buf_get(sizeof(grow_dsc_t) * (t->grow_item_cnt)); 350 LV_ASSERT_MALLOC(new_dsc); 351 if(new_dsc == NULL) return item_id; 352 353 if(t->grow_dsc) { 354 lv_memcpy(new_dsc, t->grow_dsc, sizeof(grow_dsc_t) * (t->grow_item_cnt - 1)); 355 lv_mem_buf_release(t->grow_dsc); 356 } 357 new_dsc[t->grow_item_cnt - 1].item = item; 358 new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item, 359 LV_PART_MAIN) : lv_obj_get_style_min_height(item, LV_PART_MAIN); 360 new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item, 361 LV_PART_MAIN) : lv_obj_get_style_max_height(item, LV_PART_MAIN); 362 new_dsc[t->grow_item_cnt - 1].grow_value = grow_value; 363 new_dsc[t->grow_item_cnt - 1].clamped = 0; 364 t->grow_dsc = new_dsc; 365 } 366 } 367 else { 368 lv_coord_t item_size = get_main_size(item); 369 if(f->wrap && t->track_fix_main_size + item_size > max_main_size) break; 370 t->track_fix_main_size += item_size + item_gap; 371 } 372 373 374 t->track_cross_size = LV_MAX(get_cross_size(item), t->track_cross_size); 375 t->item_cnt++; 376 } 377 378 item_id += f->rev ? -1 : +1; 379 if(item_id < 0) break; 380 item = lv_obj_get_child(cont, item_id); 381 } 382 383 if(t->track_fix_main_size > 0) t->track_fix_main_size -= item_gap; /*There is no gap after the last item*/ 384 385 /*If there is at least one "grow item" the track takes the full space*/ 386 t->track_main_size = t->grow_item_cnt ? max_main_size : t->track_fix_main_size; 387 388 /*Have at least one item in a row*/ 389 if(item && item_id == item_start_id) { 390 item = cont->spec_attr->children[item_id]; 391 get_next_item(cont, f->rev, &item_id); 392 if(item) { 393 t->track_cross_size = get_cross_size(item); 394 t->track_main_size = get_main_size(item); 395 t->item_cnt = 1; 396 } 397 } 398 399 return item_id; 400 } 401 402 /** 403 * Position the children in the same track 404 */ 405 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, 406 lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t) 407 { 408 void (*area_set_main_size)(lv_area_t *, lv_coord_t) = (f->row ? lv_area_set_width : lv_area_set_height); 409 lv_coord_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height); 410 lv_coord_t (*area_get_cross_size)(const lv_area_t *) = (!f->row ? lv_area_get_width : lv_area_get_height); 411 412 /*Calculate the size of grow items first*/ 413 uint32_t i; 414 bool grow_reiterate = true; 415 while(grow_reiterate) { 416 grow_reiterate = false; 417 lv_coord_t grow_value_sum = 0; 418 lv_coord_t grow_max_size = t->track_main_size - t->track_fix_main_size; 419 for(i = 0; i < t->grow_item_cnt; i++) { 420 if(t->grow_dsc[i].clamped == 0) { 421 grow_value_sum += t->grow_dsc[i].grow_value; 422 } 423 else { 424 grow_max_size -= t->grow_dsc[i].final_size; 425 } 426 } 427 lv_coord_t grow_unit; 428 429 for(i = 0; i < t->grow_item_cnt; i++) { 430 if(t->grow_dsc[i].clamped == 0) { 431 LV_ASSERT(grow_value_sum != 0); 432 grow_unit = grow_max_size / grow_value_sum; 433 lv_coord_t size = grow_unit * t->grow_dsc[i].grow_value; 434 lv_coord_t size_clamp = LV_CLAMP(t->grow_dsc[i].min_size, size, t->grow_dsc[i].max_size); 435 436 if(size_clamp != size) { 437 t->grow_dsc[i].clamped = 1; 438 grow_reiterate = true; 439 } 440 t->grow_dsc[i].final_size = size_clamp; 441 grow_value_sum -= t->grow_dsc[i].grow_value; 442 grow_max_size -= t->grow_dsc[i].final_size; 443 } 444 } 445 } 446 447 448 bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; 449 450 lv_coord_t main_pos = 0; 451 452 lv_coord_t place_gap = 0; 453 place_content(f->main_place, max_main_size, t->track_main_size, t->item_cnt, &main_pos, &place_gap); 454 if(f->row && rtl) main_pos += lv_obj_get_content_width(cont); 455 456 lv_obj_t * item = lv_obj_get_child(cont, item_first_id); 457 /*Reposition the children*/ 458 while(item && item_first_id != item_last_id) { 459 if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) { 460 item = get_next_item(cont, f->rev, &item_first_id); 461 continue; 462 } 463 lv_coord_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN); 464 if(grow_size) { 465 lv_coord_t s = 0; 466 for(i = 0; i < t->grow_item_cnt; i++) { 467 if(t->grow_dsc[i].item == item) { 468 s = t->grow_dsc[i].final_size; 469 break; 470 } 471 } 472 473 if(f->row) item->w_layout = 1; 474 else item->h_layout = 1; 475 476 if(s != area_get_main_size(&item->coords)) { 477 lv_obj_invalidate(item); 478 479 lv_area_t old_coords; 480 lv_area_copy(&old_coords, &item->coords); 481 area_set_main_size(&item->coords, s); 482 lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords); 483 lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item); 484 lv_obj_invalidate(item); 485 } 486 } 487 else { 488 item->w_layout = 0; 489 item->h_layout = 0; 490 } 491 492 lv_coord_t cross_pos = 0; 493 switch(f->cross_place) { 494 case LV_FLEX_ALIGN_CENTER: 495 /*Round up the cross size to avoid rounding error when dividing by 2 496 *The issue comes up e,g, with column direction with center cross direction if an element's width changes*/ 497 cross_pos = (((t->track_cross_size + 1) & (~1)) - area_get_cross_size(&item->coords)) / 2; 498 break; 499 case LV_FLEX_ALIGN_END: 500 cross_pos = t->track_cross_size - area_get_cross_size(&item->coords); 501 break; 502 default: 503 break; 504 } 505 506 if(f->row && rtl) main_pos -= area_get_main_size(&item->coords); 507 508 509 /*Handle percentage value of translate*/ 510 lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN); 511 lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN); 512 lv_coord_t w = lv_obj_get_width(item); 513 lv_coord_t h = lv_obj_get_height(item); 514 if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100; 515 if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100; 516 517 lv_coord_t diff_x = abs_x - item->coords.x1 + tr_x; 518 lv_coord_t diff_y = abs_y - item->coords.y1 + tr_y; 519 diff_x += f->row ? main_pos : cross_pos; 520 diff_y += f->row ? cross_pos : main_pos; 521 522 if(diff_x || diff_y) { 523 lv_obj_invalidate(item); 524 item->coords.x1 += diff_x; 525 item->coords.x2 += diff_x; 526 item->coords.y1 += diff_y; 527 item->coords.y2 += diff_y; 528 lv_obj_invalidate(item); 529 lv_obj_move_children_by(item, diff_x, diff_y, false); 530 } 531 532 if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap; 533 else main_pos -= item_gap + place_gap; 534 535 item = get_next_item(cont, f->rev, &item_first_id); 536 } 537 } 538 539 /** 540 * Tell a start coordinate and gap for a placement type. 541 */ 542 static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, 543 lv_coord_t * start_pos, lv_coord_t * gap) 544 { 545 if(item_cnt <= 1) { 546 switch(place) { 547 case LV_FLEX_ALIGN_SPACE_BETWEEN: 548 case LV_FLEX_ALIGN_SPACE_AROUND: 549 case LV_FLEX_ALIGN_SPACE_EVENLY: 550 place = LV_FLEX_ALIGN_CENTER; 551 break; 552 default: 553 break; 554 } 555 } 556 557 switch(place) { 558 case LV_FLEX_ALIGN_CENTER: 559 *gap = 0; 560 *start_pos += (max_size - content_size) / 2; 561 break; 562 case LV_FLEX_ALIGN_END: 563 *gap = 0; 564 *start_pos += max_size - content_size; 565 break; 566 case LV_FLEX_ALIGN_SPACE_BETWEEN: 567 *gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt - 1); 568 break; 569 case LV_FLEX_ALIGN_SPACE_AROUND: 570 *gap += (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt); 571 *start_pos += *gap / 2; 572 break; 573 case LV_FLEX_ALIGN_SPACE_EVENLY: 574 *gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt + 1); 575 *start_pos += *gap; 576 break; 577 default: 578 *gap = 0; 579 } 580 } 581 582 static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id) 583 { 584 if(rev) { 585 (*item_id)--; 586 if(*item_id >= 0) return cont->spec_attr->children[*item_id]; 587 else return NULL; 588 } 589 else { 590 (*item_id)++; 591 if((*item_id) < (int32_t)cont->spec_attr->child_cnt) return cont->spec_attr->children[*item_id]; 592 else return NULL; 593 } 594 } 595 596 #endif /*LV_USE_FLEX*/