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
lv_bar_create(lv_obj_t * parent)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
lv_bar_set_value(lv_obj_t * obj,int32_t value,lv_anim_enable_t anim)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
lv_bar_set_start_value(lv_obj_t * obj,int32_t value,lv_anim_enable_t anim)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
lv_bar_set_range(lv_obj_t * obj,int32_t min,int32_t max)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
lv_bar_set_mode(lv_obj_t * obj,lv_bar_mode_t mode)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
lv_bar_get_value(const lv_obj_t * obj)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
lv_bar_get_start_value(const lv_obj_t * obj)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
lv_bar_get_min_value(const lv_obj_t * obj)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
lv_bar_get_max_value(const lv_obj_t * obj)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
lv_bar_get_mode(lv_obj_t * obj)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
lv_bar_constructor(const lv_obj_class_t * class_p,lv_obj_t * obj)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
lv_bar_destructor(const lv_obj_class_t * class_p,lv_obj_t * obj)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
draw_indic(lv_event_t * e)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
lv_bar_event(const lv_obj_class_t * class_p,lv_event_t * e)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
lv_bar_anim(void * var,int32_t value)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
lv_bar_anim_ready(lv_anim_t * a)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
lv_bar_set_value_with_anim(lv_obj_t * obj,int32_t new_value,int32_t * value_ptr,_lv_bar_anim_t * anim_info,lv_anim_enable_t en)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
lv_bar_init_anim(lv_obj_t * obj,_lv_bar_anim_t * bar_anim)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
612