diff --git a/src/widgets/lv_arc.c b/src/widgets/lv_arc.c index f50312c7c..d9740b9ea 100644 --- a/src/widgets/lv_arc.c +++ b/src/widgets/lv_arc.c @@ -92,10 +92,19 @@ void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start) LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; - inv_arc_area(obj, LV_MIN(arc->indic_angle_start >= 360 ? arc->indic_angle_start - 360 : arc->indic_angle_start, start), - LV_MAX(arc->indic_angle_start, start), - LV_PART_INDICATOR); - arc->indic_angle_start = start > 360 ? start - 360 : start; + if(start > 360) start -= 360; + + int16_t old_delta = arc->indic_angle_end - arc->indic_angle_start; + int16_t new_delta = arc->indic_angle_end - start; + + if(old_delta < 0) old_delta = 360 + old_delta; + if(new_delta < 0) new_delta = 360 + new_delta; + + if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj); + else if(new_delta < old_delta) inv_arc_area(obj, arc->indic_angle_start, start, LV_PART_INDICATOR); + else if(old_delta < new_delta) inv_arc_area(obj, start, arc->indic_angle_start, LV_PART_INDICATOR); + + arc->indic_angle_start = start; } /** @@ -107,11 +116,19 @@ void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; + if(end > 360) end -= 360; - inv_arc_area(obj, LV_MIN(arc->indic_angle_end, end), - LV_MAX(arc->indic_angle_end, end), - LV_PART_INDICATOR); - arc->indic_angle_end = end > 360 ? end - 360 : end; + int16_t old_delta = arc->indic_angle_end - arc->indic_angle_start; + int16_t new_delta = end - arc->indic_angle_start; + + if(old_delta < 0) old_delta = 360 + old_delta; + if(new_delta < 0) new_delta = 360 + new_delta; + + if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj); + else if(new_delta < old_delta) inv_arc_area(obj, end, arc->indic_angle_end, LV_PART_INDICATOR); + else if(old_delta < new_delta) inv_arc_area(obj, arc->indic_angle_end, end, LV_PART_INDICATOR); + + arc->indic_angle_end = end; } /** @@ -122,17 +139,8 @@ void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end) */ void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end) { - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - inv_arc_area(obj,arc->indic_angle_start, arc->indic_angle_end, LV_PART_INDICATOR); - - if(start > 360) start -= 360; - if(end > 360) end -= 360; - arc->indic_angle_start = start; - arc->indic_angle_end = end; - - inv_arc_area(obj,arc->indic_angle_start,arc->indic_angle_end, LV_PART_INDICATOR); + lv_arc_set_end_angle(obj, end); + lv_arc_set_start_angle(obj, start); } /** @@ -145,10 +153,19 @@ void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start) LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; - inv_arc_area(obj, LV_MIN(arc->bg_angle_start >= 360 ? arc->bg_angle_start - 360 : arc->bg_angle_start, start), - LV_MAX(arc->bg_angle_start, start), - LV_PART_INDICATOR); - arc->bg_angle_start = start > 360 ? start - 360 : start; + if(start > 360) start -= 360; + + int16_t old_delta = arc->bg_angle_end - arc->bg_angle_start; + int16_t new_delta = arc->bg_angle_end - start; + + if(old_delta < 0) old_delta = 360 + old_delta; + if(new_delta < 0) new_delta = 360 + new_delta; + + if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj); + else if(new_delta < old_delta) inv_arc_area(obj, arc->bg_angle_start, start, LV_PART_MAIN); + else if(old_delta < new_delta) inv_arc_area(obj, start, arc->bg_angle_start, LV_PART_MAIN); + + arc->bg_angle_start = start; value_update(obj); } @@ -163,10 +180,20 @@ void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end) LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; - inv_arc_area(obj, LV_MIN(arc->bg_angle_end >= 360 ? arc->bg_angle_end - 360 : arc->bg_angle_end, end), - LV_MAX(arc->bg_angle_end, end), - LV_PART_INDICATOR); - arc->bg_angle_end = end > 360 ? end - 360 : end; + if(end > 360) end -= 360; + + int16_t old_delta = arc->bg_angle_end - arc->bg_angle_start; + int16_t new_delta = end - arc->bg_angle_start; + + if(old_delta < 0) old_delta = 360 + old_delta; + if(new_delta < 0) new_delta = 360 + new_delta; + + if(LV_ABS(new_delta - old_delta) > 180) lv_obj_invalidate(obj); + else if(new_delta < old_delta) inv_arc_area(obj, end, arc->bg_angle_end, LV_PART_MAIN); + else if(old_delta < new_delta) inv_arc_area(obj, arc->bg_angle_end, end, LV_PART_MAIN); + + arc->bg_angle_end = end; + value_update(obj); } @@ -178,19 +205,8 @@ void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end) */ void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end) { - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_arc_t * arc = (lv_arc_t *)obj; - - inv_arc_area(obj,arc->bg_angle_start,arc->bg_angle_end, LV_PART_MAIN); - - if(start > 360) start -= 360; - if(end > 360) end -= 360; - arc->bg_angle_start = start; - arc->bg_angle_end = end; - - inv_arc_area(obj,arc->bg_angle_start,arc->bg_angle_end, LV_PART_MAIN); - - value_update(obj); + lv_arc_set_bg_end_angle(obj, end); + lv_arc_set_bg_start_angle(obj, start); } /** @@ -255,11 +271,11 @@ void lv_arc_set_value(lv_obj_t * obj, int16_t value) if(arc->value == value) return; int16_t new_value; - new_value = value >arc->max_value ?arc->max_value : value; - new_value = new_value min_value ?arc->min_value : new_value; + new_value = value > arc->max_value ? arc->max_value : value; + new_value = new_value < arc->min_value ? arc->min_value : new_value; if(arc->value == new_value) return; - arc->value = new_value; + arc->value = new_value; value_update(obj); } @@ -693,6 +709,9 @@ static void inv_arc_area(lv_obj_t * obj, uint16_t start_angle, uint16_t end_angl if(start_angle == end_angle) return; + if(start_angle > 360) start_angle -= 360; + if(end_angle > 360) end_angle -= 360; + /*Skip this complicated invalidation if the arc is not visible*/ if(lv_obj_is_visible(obj) == false) return; @@ -723,6 +742,9 @@ static void inv_arc_area(lv_obj_t * obj, uint16_t start_angle, uint16_t end_angl start_angle += arc->rotation; end_angle += arc->rotation; + if(start_angle > 360) start_angle -= 360; + if(end_angle > 360) end_angle -= 360; + lv_area_t inv_area; lv_draw_arc_get_area(x, y, rout, start_angle, end_angle, w, rounded, &inv_area); lv_obj_invalidate_area(obj, &inv_area); @@ -817,10 +839,14 @@ static void value_update(lv_obj_t * obj) angle = lv_map(arc->value,arc->min_value,arc->max_value,arc->bg_angle_start, bg_end); lv_arc_set_start_angle(obj, angle); break; - default: /** LV_ARC_TYPE_NORMAL*/ + case LV_ARC_MODE_NORMAL: angle = lv_map(arc->value,arc->min_value,arc->max_value,arc->bg_angle_start, bg_end); lv_arc_set_end_angle(obj, angle); lv_arc_set_start_angle(obj,arc->bg_angle_start); + break; + default: + LV_LOG_WARN("Invalid mode: %d", arc->type); + return; } arc->last_angle = angle; /*Cache angle for slew rate limiting*/ }