diff --git a/src/lv_widgets/lv_meter.c b/src/lv_widgets/lv_meter.c index b4a04ad9a..df759bcc2 100644 --- a/src/lv_widgets/lv_meter.c +++ b/src/lv_widgets/lv_meter.c @@ -35,6 +35,7 @@ static void draw_ticks_and_labels(lv_obj_t * obj, const lv_area_t * clip_area, c static void draw_needles(lv_obj_t * obj, const lv_area_t * clip_area, const lv_area_t * scale_area); static lv_meter_scale_t * get_scale_of_indic(lv_obj_t * obj, lv_meter_indicator_t * indic); static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_value, int32_t new_value); +static void inv_line(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); /********************** * STATIC VARIABLES @@ -197,6 +198,11 @@ void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { inv_arc(obj, indic, old_start, value); inv_arc(obj, indic, old_end, value); + } + else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { + inv_line(obj, indic, old_start); + inv_line(obj, indic, old_end); + inv_line(obj, indic, value); } else { lv_obj_invalidate(obj); } @@ -209,7 +215,12 @@ void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * i if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { inv_arc(obj, indic, old_value, value); - } else { + } + else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { + inv_line(obj, indic, old_value); + inv_line(obj, indic, value); + } + else { lv_obj_invalidate(obj); } } @@ -221,7 +232,12 @@ void lv_meter_set_indicator_end_value(lv_obj_t * obj, lv_meter_indicator_t * ind if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { inv_arc(obj, indic, old_value, value); - } else { + } + else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { + inv_line(obj, indic, old_value); + inv_line(obj, indic, value); + } + else { lv_obj_invalidate(obj); } } @@ -285,11 +301,7 @@ static lv_draw_res_t lv_meter_draw(lv_obj_t * obj, const lv_area_t * clip_area, lv_obj_draw_base(MY_CLASS, obj, clip_area, mode); lv_area_t scale_area; - lv_obj_get_coords(obj, &scale_area); - scale_area.x1 += lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - scale_area.y1 += lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - scale_area.x2 -= lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - scale_area.y2 -= lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + lv_obj_get_coords_fit(obj, &scale_area); draw_arcs(obj, clip_area, &scale_area); draw_ticks_and_labels(obj, clip_area, &scale_area); @@ -577,7 +589,6 @@ static void draw_needles(lv_obj_t * obj, const lv_area_t * clip_area, const lv_a line_dsc.width = indic->type_data.needle_line.width; line_dsc.opa = indic->opa > LV_OPA_MAX ? opa_main : (opa_main * indic->opa) >> 8; lv_draw_line(&scale_center, &p_end, clip_area, &line_dsc); - } else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG) { if(indic->type_data.needle_img.src == NULL) continue; @@ -625,11 +636,7 @@ static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_va bool rounded = lv_obj_get_style_arc_rounded(obj, LV_PART_ITEMS); lv_area_t scale_area; - lv_obj_get_coords(obj, &scale_area); - scale_area.x1 += lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - scale_area.y1 += lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - scale_area.x2 -= lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - scale_area.y2 -= lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + lv_obj_get_coords_fit(obj, &scale_area); lv_coord_t r_out = lv_area_get_width(&scale_area) / 2; lv_point_t scale_center; @@ -647,4 +654,50 @@ static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_va lv_obj_invalidate_area(obj, &a); } + +static void inv_line(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) +{ + lv_area_t scale_area; + lv_obj_get_coords_fit(obj, &scale_area); + + lv_coord_t r_out = lv_area_get_width(&scale_area) / 2; + lv_point_t scale_center; + scale_center.x = scale_area.x1 + r_out; + scale_center.y = scale_area.y1 + r_out; + + lv_meter_scale_t * scale = get_scale_of_indic(obj, indic); + + if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { + int32_t angle = lv_map(value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); + r_out += scale->r_mod + indic->type_data.needle_line.r_mod; + lv_point_t p_end; + p_end.y = (lv_trigo_sin(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.y; + p_end.x = (lv_trigo_cos(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.x; + + lv_area_t a; + a.x1 = LV_MIN(scale_center.x, p_end.x) - indic->type_data.needle_line.width - 2; + a.y1 = LV_MIN(scale_center.y, p_end.y) - indic->type_data.needle_line.width - 2; + a.x2 = LV_MAX(scale_center.x, p_end.x) + indic->type_data.needle_line.width + 2; + a.y2 = LV_MAX(scale_center.y, p_end.y) + indic->type_data.needle_line.width + 2; + + lv_obj_invalidate_area(obj, &a); + } + else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG) { + int32_t angle = lv_map(value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); + lv_img_header_t info; + lv_img_decoder_get_info(indic->type_data.needle_img.src, &info); + + angle = angle * 10; + if(angle > 3600) angle -= 3600; + + lv_area_t a; + _lv_img_buf_get_transformed_area(&a, info.w, info.h, angle, LV_IMG_ZOOM_NONE, &indic->type_data.needle_img.pivot); + a.x1 += scale_center.x; + a.y1 += scale_center.y; + a.x2 += scale_center.x; + a.y2 += scale_center.y; + + lv_obj_invalidate_area(obj, &a); + } +} #endif