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