From dfa4f5cff561a60b4ffcec17e025f1e056854fff Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 19 Oct 2021 12:52:27 +0200 Subject: [PATCH] feat(arc) add support to LV_OBJ_FLAG_ADV_HITTEST --- docs/widgets/core/arc.md | 7 +++++++ src/widgets/lv_arc.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/docs/widgets/core/arc.md b/docs/widgets/core/arc.md index 7f20acc7d..7018bff73 100644 --- a/docs/widgets/core/arc.md +++ b/docs/widgets/core/arc.md @@ -58,6 +58,13 @@ lv_obj_remove_style(arc, NULL, LV_PART_KNOB); lv_obj_clear_flag(arc, LV_OBJ_FLAG_CLICKABLE); ``` +### Advanced hit test + +If the `LV_OBJ_FLAG_ADV_HITTEST` flag is enabled the arc can be clicked through in the middle. Clicks are recognized only on the ring of the background arc. `lv_obj_set_ext_click_size()` makes the sensitive area larger inside and outside with the given number of pixels. + + + + ## Events - `LV_EVENT_VALUE_CHANGED` sent when the arc is pressed/dragged to set a new value. - `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` are sent with the following types: diff --git a/src/widgets/lv_arc.c b/src/widgets/lv_arc.c index 5af367fce..08cfe03f5 100644 --- a/src/widgets/lv_arc.c +++ b/src/widgets/lv_arc.c @@ -379,7 +379,16 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) if(arc->dragging == false) { lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); r -= indic_width; - r -= r / 2; /*Add some more sensitive area*/ + /*Add some more sensitive area if there is no advanced git testing. + * (Advanced hit testing is more precise)*/ + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_ADV_HITTEST)) { + r -= indic_width; + + } else { + r -= LV_MAX(r / 4, indic_width); + } + if(r < 1) r = 1; + if(p.x * p.x + p.y * p.y > r * r) { arc->dragging = true; arc->last_tick = lv_tick_get(); /*Capture timestamp at dragging start*/ @@ -488,6 +497,31 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) if(res != LV_RES_OK) return; } } + else if(code == LV_EVENT_HIT_TEST) { + lv_hit_test_info_t * info = lv_event_get_param(e);; + + lv_point_t p; + lv_coord_t r; + get_center(obj, &p, &r); + + lv_coord_t ext_click_area = 0; + if(obj->spec_attr) ext_click_area = obj->spec_attr->ext_click_pad; + + lv_coord_t w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN); + r -= w + ext_click_area; + + lv_area_t a; + /*Invalid if clicked inside*/ + lv_area_set(&a, p.x - r, p.y - r, p.x + r, p.y + r); + if(_lv_area_is_point_on(&a, info->point, LV_RADIUS_CIRCLE)) { + info->res = false; + return; + } + + /*Valid if no clicked outside*/ + lv_area_increase(&a, w + ext_click_area * 2, w + ext_click_area * 2); + info->res = _lv_area_is_point_on(&a, info->point, LV_RADIUS_CIRCLE); + } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);