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_bar.c (20254B)
1 /** 2 * @file lv_bar.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 *********************/ 9 #include "lv_bar.h" 10 #if LV_USE_BAR != 0 11 12 #include "../misc/lv_assert.h" 13 #include "../draw/lv_draw.h" 14 #include "../misc/lv_anim.h" 15 #include "../misc/lv_math.h" 16 17 /********************* 18 * DEFINES 19 *********************/ 20 #define MY_CLASS &lv_bar_class 21 22 /** hor. pad and ver. pad cannot make the indicator smaller than this [px]*/ 23 #define LV_BAR_SIZE_MIN 4 24 25 #define LV_BAR_IS_ANIMATING(anim_struct) (((anim_struct).anim_state) != LV_BAR_ANIM_STATE_INV) 26 #define LV_BAR_GET_ANIM_VALUE(orig_value, anim_struct) (LV_BAR_IS_ANIMATING(anim_struct) ? ((anim_struct).anim_end) : (orig_value)) 27 28 /** Bar animation start value. (Not the real value of the Bar just indicates process animation)*/ 29 #define LV_BAR_ANIM_STATE_START 0 30 31 /** Bar animation end value. (Not the real value of the Bar just indicates process animation)*/ 32 #define LV_BAR_ANIM_STATE_END 256 33 34 /** Mark no animation is in progress*/ 35 #define LV_BAR_ANIM_STATE_INV -1 36 37 /** log2(LV_BAR_ANIM_STATE_END) used to normalize data*/ 38 #define LV_BAR_ANIM_STATE_NORM 8 39 40 /********************** 41 * TYPEDEFS 42 **********************/ 43 44 /********************** 45 * STATIC PROTOTYPES 46 **********************/ 47 static void lv_bar_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); 48 static void lv_bar_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); 49 static void lv_bar_event(const lv_obj_class_t * class_p, lv_event_t * e); 50 static void draw_indic(lv_event_t * e); 51 static void lv_bar_set_value_with_anim(lv_obj_t * obj, int32_t new_value, int32_t * value_ptr, 52 _lv_bar_anim_t * anim_info, lv_anim_enable_t en); 53 static void lv_bar_init_anim(lv_obj_t * bar, _lv_bar_anim_t * bar_anim); 54 static void lv_bar_anim(void * bar, int32_t value); 55 static void lv_bar_anim_ready(lv_anim_t * a); 56 57 /********************** 58 * STATIC VARIABLES 59 **********************/ 60 const lv_obj_class_t lv_bar_class = { 61 .constructor_cb = lv_bar_constructor, 62 .destructor_cb = lv_bar_destructor, 63 .event_cb = lv_bar_event, 64 .width_def = LV_DPI_DEF * 2, 65 .height_def = LV_DPI_DEF / 10, 66 .instance_size = sizeof(lv_bar_t), 67 .base_class = &lv_obj_class 68 }; 69 70 /********************** 71 * MACROS 72 **********************/ 73 74 /********************** 75 * GLOBAL FUNCTIONS 76 **********************/ 77 78 lv_obj_t * lv_bar_create(lv_obj_t * parent) 79 { 80 LV_LOG_INFO("begin"); 81 lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); 82 lv_obj_class_init_obj(obj); 83 return obj; 84 } 85 86 /*===================== 87 * Setter functions 88 *====================*/ 89 90 void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) 91 { 92 LV_ASSERT_OBJ(obj, MY_CLASS); 93 lv_bar_t * bar = (lv_bar_t *)obj; 94 95 if(bar->cur_value == value) return; 96 97 value = LV_CLAMP(bar->min_value, value, bar->max_value); 98 value = value < bar->start_value ? bar->start_value : value; /*Can't be smaller than the left value*/ 99 100 if(bar->cur_value == value) return; 101 lv_bar_set_value_with_anim(obj, value, &bar->cur_value, &bar->cur_value_anim, anim); 102 } 103 104 void lv_bar_set_start_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) 105 { 106 LV_ASSERT_OBJ(obj, MY_CLASS); 107 108 lv_bar_t * bar = (lv_bar_t *)obj; 109 110 if(bar->mode != LV_BAR_MODE_RANGE) { 111 return; 112 } 113 114 value = LV_CLAMP(bar->min_value, value, bar->max_value); 115 value = value > bar->cur_value ? bar->cur_value : value; /*Can't be greater than the right value*/ 116 117 if(bar->start_value == value) return; 118 lv_bar_set_value_with_anim(obj, value, &bar->start_value, &bar->start_value_anim, anim); 119 } 120 121 void lv_bar_set_range(lv_obj_t * obj, int32_t min, int32_t max) 122 { 123 LV_ASSERT_OBJ(obj, MY_CLASS); 124 125 lv_bar_t * bar = (lv_bar_t *)obj; 126 127 if(bar->min_value == min && bar->max_value == max) return; 128 129 bar->max_value = max; 130 bar->min_value = min; 131 132 if(lv_bar_get_mode(obj) != LV_BAR_MODE_RANGE) 133 bar->start_value = min; 134 135 if(bar->cur_value > max) { 136 bar->cur_value = max; 137 lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF); 138 } 139 if(bar->cur_value < min) { 140 bar->cur_value = min; 141 lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF); 142 } 143 lv_obj_invalidate(obj); 144 } 145 146 void lv_bar_set_mode(lv_obj_t * obj, lv_bar_mode_t mode) 147 { 148 LV_ASSERT_OBJ(obj, MY_CLASS); 149 lv_bar_t * bar = (lv_bar_t *)obj; 150 151 bar->mode = mode; 152 if(bar->mode != LV_BAR_MODE_RANGE) { 153 bar->start_value = bar->min_value; 154 } 155 156 lv_obj_invalidate(obj); 157 } 158 159 /*===================== 160 * Getter functions 161 *====================*/ 162 163 int32_t lv_bar_get_value(const lv_obj_t * obj) 164 { 165 LV_ASSERT_OBJ(obj, MY_CLASS); 166 lv_bar_t * bar = (lv_bar_t *)obj; 167 168 return LV_BAR_GET_ANIM_VALUE(bar->cur_value, bar->cur_value_anim); 169 } 170 171 int32_t lv_bar_get_start_value(const lv_obj_t * obj) 172 { 173 LV_ASSERT_OBJ(obj, MY_CLASS); 174 lv_bar_t * bar = (lv_bar_t *)obj; 175 176 if(bar->mode != LV_BAR_MODE_RANGE) return bar->min_value; 177 178 return LV_BAR_GET_ANIM_VALUE(bar->start_value, bar->start_value_anim); 179 } 180 181 int32_t lv_bar_get_min_value(const lv_obj_t * obj) 182 { 183 LV_ASSERT_OBJ(obj, MY_CLASS); 184 lv_bar_t * bar = (lv_bar_t *)obj; 185 return bar->min_value; 186 } 187 188 int32_t lv_bar_get_max_value(const lv_obj_t * obj) 189 { 190 LV_ASSERT_OBJ(obj, MY_CLASS); 191 lv_bar_t * bar = (lv_bar_t *)obj; 192 193 return bar->max_value; 194 } 195 196 lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj) 197 { 198 LV_ASSERT_OBJ(obj, MY_CLASS); 199 lv_bar_t * bar = (lv_bar_t *)obj; 200 201 return bar->mode; 202 } 203 204 /********************** 205 * STATIC FUNCTIONS 206 **********************/ 207 208 static void lv_bar_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) 209 { 210 LV_UNUSED(class_p); 211 LV_TRACE_OBJ_CREATE("begin"); 212 213 lv_bar_t * bar = (lv_bar_t *)obj; 214 bar->min_value = 0; 215 bar->max_value = 100; 216 bar->start_value = 0; 217 bar->cur_value = 0; 218 bar->indic_area.x1 = 0; 219 bar->indic_area.x2 = 0; 220 bar->indic_area.y1 = 0; 221 bar->indic_area.y2 = 0; 222 bar->mode = LV_BAR_MODE_NORMAL; 223 224 lv_bar_init_anim(obj, &bar->cur_value_anim); 225 lv_bar_init_anim(obj, &bar->start_value_anim); 226 227 lv_obj_clear_flag(obj, LV_OBJ_FLAG_CHECKABLE); 228 lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); 229 lv_bar_set_value(obj, 0, LV_ANIM_OFF); 230 231 LV_TRACE_OBJ_CREATE("finished"); 232 } 233 234 static void lv_bar_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) 235 { 236 LV_UNUSED(class_p); 237 lv_bar_t * bar = (lv_bar_t *)obj; 238 239 lv_anim_del(&bar->cur_value_anim, NULL); 240 lv_anim_del(&bar->start_value_anim, NULL); 241 } 242 243 static void draw_indic(lv_event_t * e) 244 { 245 lv_obj_t * obj = lv_event_get_target(e); 246 lv_bar_t * bar = (lv_bar_t *)obj; 247 248 lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); 249 250 lv_area_t bar_coords; 251 lv_obj_get_coords(obj, &bar_coords); 252 253 lv_coord_t transf_w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); 254 lv_coord_t transf_h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); 255 bar_coords.x1 -= transf_w; 256 bar_coords.x2 += transf_w; 257 bar_coords.y1 -= transf_h; 258 bar_coords.y2 += transf_h; 259 lv_coord_t barw = lv_area_get_width(&bar_coords); 260 lv_coord_t barh = lv_area_get_height(&bar_coords); 261 int32_t range = bar->max_value - bar->min_value; 262 bool hor = barw >= barh ? true : false; 263 bool sym = false; 264 if(bar->mode == LV_BAR_MODE_SYMMETRICAL && bar->min_value < 0 && bar->max_value > 0 && 265 bar->start_value == bar->min_value) sym = true; 266 267 /*Calculate the indicator area*/ 268 lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); 269 lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); 270 lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); 271 lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); 272 /*Respect padding and minimum width/height too*/ 273 lv_area_copy(&bar->indic_area, &bar_coords); 274 bar->indic_area.x1 += bg_left; 275 bar->indic_area.x2 -= bg_right; 276 bar->indic_area.y1 += bg_top; 277 bar->indic_area.y2 -= bg_bottom; 278 279 if(hor && lv_area_get_height(&bar->indic_area) < LV_BAR_SIZE_MIN) { 280 bar->indic_area.y1 = obj->coords.y1 + (barh / 2) - (LV_BAR_SIZE_MIN / 2); 281 bar->indic_area.y2 = bar->indic_area.y1 + LV_BAR_SIZE_MIN; 282 } 283 else if(!hor && lv_area_get_width(&bar->indic_area) < LV_BAR_SIZE_MIN) { 284 bar->indic_area.x1 = obj->coords.x1 + (barw / 2) - (LV_BAR_SIZE_MIN / 2); 285 bar->indic_area.x2 = bar->indic_area.x1 + LV_BAR_SIZE_MIN; 286 } 287 288 lv_coord_t indicw = lv_area_get_width(&bar->indic_area); 289 lv_coord_t indich = lv_area_get_height(&bar->indic_area); 290 291 /*Calculate the indicator length*/ 292 lv_coord_t anim_length = hor ? indicw : indich; 293 294 lv_coord_t anim_cur_value_x, anim_start_value_x; 295 296 lv_coord_t * axis1, * axis2; 297 lv_coord_t (*indic_length_calc)(const lv_area_t * area); 298 299 if(hor) { 300 axis1 = &bar->indic_area.x1; 301 axis2 = &bar->indic_area.x2; 302 indic_length_calc = lv_area_get_width; 303 } 304 else { 305 axis1 = &bar->indic_area.y1; 306 axis2 = &bar->indic_area.y2; 307 indic_length_calc = lv_area_get_height; 308 } 309 310 if(LV_BAR_IS_ANIMATING(bar->start_value_anim)) { 311 lv_coord_t anim_start_value_start_x = 312 (int32_t)((int32_t)anim_length * (bar->start_value_anim.anim_start - bar->min_value)) / range; 313 lv_coord_t anim_start_value_end_x = 314 (int32_t)((int32_t)anim_length * (bar->start_value_anim.anim_end - bar->min_value)) / range; 315 316 anim_start_value_x = (((anim_start_value_end_x - anim_start_value_start_x) * bar->start_value_anim.anim_state) / 317 LV_BAR_ANIM_STATE_END); 318 319 anim_start_value_x += anim_start_value_start_x; 320 } 321 else { 322 anim_start_value_x = (int32_t)((int32_t)anim_length * (bar->start_value - bar->min_value)) / range; 323 } 324 325 if(LV_BAR_IS_ANIMATING(bar->cur_value_anim)) { 326 lv_coord_t anim_cur_value_start_x = 327 (int32_t)((int32_t)anim_length * (bar->cur_value_anim.anim_start - bar->min_value)) / range; 328 lv_coord_t anim_cur_value_end_x = 329 (int32_t)((int32_t)anim_length * (bar->cur_value_anim.anim_end - bar->min_value)) / range; 330 331 anim_cur_value_x = anim_cur_value_start_x + (((anim_cur_value_end_x - anim_cur_value_start_x) * 332 bar->cur_value_anim.anim_state) / 333 LV_BAR_ANIM_STATE_END); 334 } 335 else { 336 anim_cur_value_x = (int32_t)((int32_t)anim_length * (bar->cur_value - bar->min_value)) / range; 337 } 338 339 lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); 340 if(hor && base_dir == LV_BASE_DIR_RTL) { 341 /*Swap axes*/ 342 lv_coord_t * tmp; 343 tmp = axis1; 344 axis1 = axis2; 345 axis2 = tmp; 346 anim_cur_value_x = -anim_cur_value_x; 347 anim_start_value_x = -anim_start_value_x; 348 } 349 350 /*Set the indicator length*/ 351 if(hor) { 352 *axis2 = *axis1 + anim_cur_value_x; 353 *axis1 += anim_start_value_x; 354 } 355 else { 356 *axis1 = *axis2 - anim_cur_value_x + 1; 357 *axis2 -= anim_start_value_x; 358 } 359 if(sym) { 360 lv_coord_t zero, shift; 361 shift = (-bar->min_value * anim_length) / range; 362 if(hor) { 363 zero = *axis1 + shift; 364 if(*axis2 > zero) 365 *axis1 = zero; 366 else { 367 *axis1 = *axis2; 368 *axis2 = zero; 369 } 370 } 371 else { 372 zero = *axis2 - shift + 1; 373 if(*axis1 > zero) 374 *axis2 = zero; 375 else { 376 *axis2 = *axis1; 377 *axis1 = zero; 378 } 379 if(*axis2 < *axis1) { 380 /*swap*/ 381 zero = *axis1; 382 *axis1 = *axis2; 383 *axis2 = zero; 384 } 385 } 386 } 387 388 /*Do not draw a zero length indicator but at least call the draw part events*/ 389 if(!sym && indic_length_calc(&bar->indic_area) <= 1) { 390 391 lv_obj_draw_part_dsc_t part_draw_dsc; 392 lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); 393 part_draw_dsc.part = LV_PART_INDICATOR; 394 part_draw_dsc.class_p = MY_CLASS; 395 part_draw_dsc.type = LV_BAR_DRAW_PART_INDICATOR; 396 part_draw_dsc.draw_area = &bar->indic_area; 397 398 lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); 399 lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); 400 return; 401 } 402 403 lv_area_t indic_area; 404 lv_area_copy(&indic_area, &bar->indic_area); 405 406 lv_draw_rect_dsc_t draw_rect_dsc; 407 lv_draw_rect_dsc_init(&draw_rect_dsc); 408 lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &draw_rect_dsc); 409 410 lv_obj_draw_part_dsc_t part_draw_dsc; 411 lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); 412 part_draw_dsc.part = LV_PART_INDICATOR; 413 part_draw_dsc.class_p = MY_CLASS; 414 part_draw_dsc.type = LV_BAR_DRAW_PART_INDICATOR; 415 part_draw_dsc.rect_dsc = &draw_rect_dsc; 416 part_draw_dsc.draw_area = &bar->indic_area; 417 418 lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); 419 420 lv_coord_t bg_radius = lv_obj_get_style_radius(obj, LV_PART_MAIN); 421 lv_coord_t short_side = LV_MIN(barw, barh); 422 if(bg_radius > short_side >> 1) bg_radius = short_side >> 1; 423 424 lv_coord_t indic_radius = draw_rect_dsc.radius; 425 short_side = LV_MIN(indicw, indich); 426 if(indic_radius > short_side >> 1) indic_radius = short_side >> 1; 427 428 /*Draw only the shadow and outline only if the indicator is long enough. 429 *The radius of the bg and the indicator can make a strange shape where 430 *it'd be very difficult to draw shadow.*/ 431 if((hor && lv_area_get_width(&bar->indic_area) > indic_radius * 2) || 432 (!hor && lv_area_get_height(&bar->indic_area) > indic_radius * 2)) { 433 lv_opa_t bg_opa = draw_rect_dsc.bg_opa; 434 lv_opa_t bg_img_opa = draw_rect_dsc.bg_img_opa; 435 lv_opa_t border_opa = draw_rect_dsc.border_opa; 436 draw_rect_dsc.bg_opa = LV_OPA_TRANSP; 437 draw_rect_dsc.bg_img_opa = LV_OPA_TRANSP; 438 draw_rect_dsc.border_opa = LV_OPA_TRANSP; 439 440 lv_draw_rect(draw_ctx, &draw_rect_dsc, &bar->indic_area); 441 442 draw_rect_dsc.bg_opa = bg_opa; 443 draw_rect_dsc.bg_img_opa = bg_img_opa; 444 draw_rect_dsc.border_opa = border_opa; 445 } 446 447 #if LV_DRAW_COMPLEX 448 lv_draw_mask_radius_param_t mask_bg_param; 449 lv_area_t bg_mask_area; 450 bg_mask_area.x1 = obj->coords.x1 + bg_left; 451 bg_mask_area.x2 = obj->coords.x2 - bg_right; 452 bg_mask_area.y1 = obj->coords.y1 + bg_top; 453 bg_mask_area.y2 = obj->coords.y2 - bg_bottom; 454 455 lv_draw_mask_radius_init(&mask_bg_param, &bg_mask_area, bg_radius, false); 456 lv_coord_t mask_bg_id = lv_draw_mask_add(&mask_bg_param, NULL); 457 #endif 458 459 /*Draw_only the background and background image*/ 460 lv_opa_t shadow_opa = draw_rect_dsc.shadow_opa; 461 lv_opa_t border_opa = draw_rect_dsc.border_opa; 462 draw_rect_dsc.border_opa = LV_OPA_TRANSP; 463 draw_rect_dsc.shadow_opa = LV_OPA_TRANSP; 464 465 /*Get the max possible indicator area. The gradient should be applied on this*/ 466 lv_area_t mask_indic_max_area; 467 lv_area_copy(&mask_indic_max_area, &bar_coords); 468 mask_indic_max_area.x1 += bg_left; 469 mask_indic_max_area.y1 += bg_top; 470 mask_indic_max_area.x2 -= bg_right; 471 mask_indic_max_area.y2 -= bg_bottom; 472 if(hor && lv_area_get_height(&mask_indic_max_area) < LV_BAR_SIZE_MIN) { 473 mask_indic_max_area.y1 = obj->coords.y1 + (barh / 2) - (LV_BAR_SIZE_MIN / 2); 474 mask_indic_max_area.y2 = mask_indic_max_area.y1 + LV_BAR_SIZE_MIN; 475 } 476 else if(!hor && lv_area_get_width(&mask_indic_max_area) < LV_BAR_SIZE_MIN) { 477 mask_indic_max_area.x1 = obj->coords.x1 + (barw / 2) - (LV_BAR_SIZE_MIN / 2); 478 mask_indic_max_area.x2 = mask_indic_max_area.x1 + LV_BAR_SIZE_MIN; 479 } 480 481 #if LV_DRAW_COMPLEX 482 /*Create a mask to the current indicator area to see only this part from the whole gradient.*/ 483 lv_draw_mask_radius_param_t mask_indic_param; 484 lv_draw_mask_radius_init(&mask_indic_param, &bar->indic_area, draw_rect_dsc.radius, false); 485 int16_t mask_indic_id = lv_draw_mask_add(&mask_indic_param, NULL); 486 #endif 487 488 lv_draw_rect(draw_ctx, &draw_rect_dsc, &mask_indic_max_area); 489 draw_rect_dsc.border_opa = border_opa; 490 draw_rect_dsc.shadow_opa = shadow_opa; 491 492 /*Draw the border*/ 493 draw_rect_dsc.bg_opa = LV_OPA_TRANSP; 494 draw_rect_dsc.bg_img_opa = LV_OPA_TRANSP; 495 draw_rect_dsc.shadow_opa = LV_OPA_TRANSP; 496 lv_draw_rect(draw_ctx, &draw_rect_dsc, &bar->indic_area); 497 498 #if LV_DRAW_COMPLEX 499 lv_draw_mask_free_param(&mask_indic_param); 500 lv_draw_mask_free_param(&mask_bg_param); 501 lv_draw_mask_remove_id(mask_indic_id); 502 lv_draw_mask_remove_id(mask_bg_id); 503 #endif 504 505 lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); 506 } 507 508 static void lv_bar_event(const lv_obj_class_t * class_p, lv_event_t * e) 509 { 510 LV_UNUSED(class_p); 511 512 lv_res_t res; 513 514 /*Call the ancestor's event handler*/ 515 res = lv_obj_event_base(MY_CLASS, e); 516 if(res != LV_RES_OK) return; 517 518 lv_event_code_t code = lv_event_get_code(e); 519 lv_obj_t * obj = lv_event_get_target(e); 520 521 if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { 522 lv_coord_t indic_size; 523 indic_size = lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR); 524 525 /*Bg size is handled by lv_obj*/ 526 lv_coord_t * s = lv_event_get_param(e); 527 *s = LV_MAX(*s, indic_size); 528 529 /*Calculate the indicator area*/ 530 lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); 531 lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); 532 lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); 533 lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); 534 535 lv_coord_t pad = LV_MIN4(bg_left, bg_right, bg_top, bg_bottom); 536 if(pad < 0) { 537 *s = LV_MAX(*s, -pad); 538 } 539 } 540 else if(code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED) { 541 lv_bar_t * bar = (lv_bar_t *)obj; 542 lv_obj_invalidate_area(obj, &bar->indic_area); 543 } 544 else if(code == LV_EVENT_DRAW_MAIN) { 545 draw_indic(e); 546 } 547 } 548 549 static void lv_bar_anim(void * var, int32_t value) 550 { 551 _lv_bar_anim_t * bar_anim = var; 552 bar_anim->anim_state = value; 553 lv_obj_invalidate(bar_anim->bar); 554 } 555 556 static void lv_bar_anim_ready(lv_anim_t * a) 557 { 558 _lv_bar_anim_t * var = a->var; 559 lv_obj_t * obj = (lv_obj_t *)var->bar; 560 lv_bar_t * bar = (lv_bar_t *)obj; 561 562 var->anim_state = LV_BAR_ANIM_STATE_INV; 563 if(var == &bar->cur_value_anim) 564 bar->cur_value = var->anim_end; 565 else if(var == &bar->start_value_anim) 566 bar->start_value = var->anim_end; 567 lv_obj_invalidate(var->bar); 568 } 569 570 static void lv_bar_set_value_with_anim(lv_obj_t * obj, int32_t new_value, int32_t * value_ptr, 571 _lv_bar_anim_t * anim_info, lv_anim_enable_t en) 572 { 573 if(en == LV_ANIM_OFF) { 574 *value_ptr = new_value; 575 lv_obj_invalidate((lv_obj_t *)obj); 576 } 577 else { 578 /*No animation in progress -> simply set the values*/ 579 if(anim_info->anim_state == LV_BAR_ANIM_STATE_INV) { 580 anim_info->anim_start = *value_ptr; 581 anim_info->anim_end = new_value; 582 } 583 /*Animation in progress. Start from the animation end value*/ 584 else { 585 anim_info->anim_start = anim_info->anim_end; 586 anim_info->anim_end = new_value; 587 } 588 *value_ptr = new_value; 589 /*Stop the previous animation if it exists*/ 590 lv_anim_del(anim_info, NULL); 591 592 lv_anim_t a; 593 lv_anim_init(&a); 594 lv_anim_set_var(&a, anim_info); 595 lv_anim_set_exec_cb(&a, lv_bar_anim); 596 lv_anim_set_values(&a, LV_BAR_ANIM_STATE_START, LV_BAR_ANIM_STATE_END); 597 lv_anim_set_ready_cb(&a, lv_bar_anim_ready); 598 lv_anim_set_time(&a, lv_obj_get_style_anim_time(obj, LV_PART_MAIN)); 599 lv_anim_start(&a); 600 } 601 } 602 603 static void lv_bar_init_anim(lv_obj_t * obj, _lv_bar_anim_t * bar_anim) 604 { 605 bar_anim->bar = obj; 606 bar_anim->anim_start = 0; 607 bar_anim->anim_end = 0; 608 bar_anim->anim_state = LV_BAR_ANIM_STATE_INV; 609 } 610 611 #endif