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