From 1a41f13fd633d522cc4e4f1e96f72a5ff30771bd Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 18 Jun 2020 17:06:24 -0700 Subject: [PATCH 01/97] Initial lv_rotary work extending lv_arc with stubbed signal handler. --- lv_conf_template.h | 3 + src/lv_conf_internal.h | 3 + src/lv_misc/lv_math.h | 2 + src/lv_themes/lv_theme_material.c | 57 ++++ src/lv_widgets/lv_rotary.c | 458 ++++++++++++++++++++++++++++++ src/lv_widgets/lv_rotary.h | 281 ++++++++++++++++++ 6 files changed, 804 insertions(+) create mode 100644 src/lv_widgets/lv_rotary.c create mode 100644 src/lv_widgets/lv_rotary.h diff --git a/lv_conf_template.h b/lv_conf_template.h index de2287cf4..629e0bf62 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -654,6 +654,9 @@ typedef void * lv_obj_user_data_t; # define LV_ROLLER_INF_PAGES 7 #endif +/*Rotary (dependencies: lv_arc, lv_btn)*/ +#define LV_USE_ROTARY 1 + /*Slider (dependencies: lv_bar)*/ #define LV_USE_SLIDER 1 diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index da8f7d8d1..9ea1abbd7 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -991,6 +991,9 @@ #endif #endif +/*Rotary (dependencies: lv_arc, lv_btn)*/ +#define LV_USE_ROTARY 1 + /*Slider (dependencies: lv_bar)*/ #ifndef LV_USE_SLIDER #define LV_USE_SLIDER 1 diff --git a/src/lv_misc/lv_math.h b/src/lv_misc/lv_math.h index 499176244..dc45ad630 100644 --- a/src/lv_misc/lv_math.h +++ b/src/lv_misc/lv_math.h @@ -31,6 +31,8 @@ extern "C" { #define LV_MATH_UDIV255(x) ((uint32_t)((uint32_t) (x) * 0x8081) >> 0x17) +#define LV_MATH_MAP(a, min_in, max_in, min, max) (min - (((max - min) / (max_in - min_in)) * min_in) + (((max - min) / (max_in - min_in)) * a)) + #define LV_IS_SIGNED(t) (((t)(-1)) < ((t) 0)) #define LV_UMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0xFULL << ((sizeof(t) * 8ULL) - 4ULL))) #define LV_SMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL))) diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index 33d6f4985..e0b0e9762 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -147,6 +147,10 @@ typedef struct { lv_style_t roller_bg, roller_sel; #endif +#if LV_USE_ROTARY + lv_style_t rotary_bg, rotary_indic, rotary_knob; +#endif + #if LV_USE_SLIDER lv_style_t slider_knob, slider_bg; #endif @@ -789,6 +793,38 @@ static void roller_init(void) #endif } +static void rotary_init(void) +{ +#if LV_USE_ROTARY != 0 + style_init_reset(&styles->rotary_bg); + lv_style_set_clip_corner(&styles->rotary_bg, LV_STATE_DEFAULT, true); + lv_style_set_pad_left(&styles->rotary_bg, LV_STATE_DEFAULT, 0); + lv_style_set_pad_right(&styles->rotary_bg, LV_STATE_DEFAULT, 0); + lv_style_set_pad_top(&styles->rotary_bg, LV_STATE_DEFAULT, 0); + lv_style_set_pad_bottom(&styles->rotary_bg, LV_STATE_DEFAULT, 0); + lv_style_set_pad_inner(&styles->rotary_bg, LV_STATE_DEFAULT, 0); + lv_style_set_border_width(&styles->rotary_bg, LV_STATE_DEFAULT, 0); + lv_style_set_line_color(&styles->rotary_bg, LV_STATE_DEFAULT, COLOR_BG_SEC); + lv_style_set_line_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(8)); + lv_style_set_line_rounded(&styles->rotary_bg, LV_STATE_DEFAULT, true); + + style_init_reset(&styles->rotary_indic); + lv_style_set_line_color(&styles->rotary_indic, LV_STATE_DEFAULT, theme.color_primary); + lv_style_set_line_width(&styles->rotary_indic, LV_STATE_DEFAULT, LV_DPX(8)); + lv_style_set_line_rounded(&styles->rotary_indic, LV_STATE_DEFAULT, true); + + style_init_reset(&styles->rotary_knob); + lv_style_set_bg_opa(&styles->rotary_knob, LV_STATE_DEFAULT, LV_OPA_COVER); + lv_style_set_bg_color(&styles->rotary_knob, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_style_set_radius(&styles->rotary_knob, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_style_set_pad_top(&styles->rotary_knob, LV_STATE_DEFAULT, - LV_DPX(4)); + lv_style_set_pad_bottom(&styles->rotary_knob, LV_STATE_DEFAULT, - LV_DPX(4)); + lv_style_set_pad_left(&styles->rotary_knob, LV_STATE_DEFAULT, - LV_DPX(4)); + lv_style_set_pad_right(&styles->rotary_knob, LV_STATE_DEFAULT, - LV_DPX(4)); + lv_style_set_pad_inner(&styles->rotary_knob, LV_STATE_DEFAULT, LV_DPX(6)); +#endif +} + static void tabview_init(void) { #if LV_USE_TABVIEW != 0 @@ -923,6 +959,7 @@ lv_theme_t * lv_theme_material_init(lv_color_t color_primary, lv_color_t color_s list_init(); ddlist_init(); roller_init(); + rotary_init(); tabview_init(); tileview_init(); table_init(); @@ -1223,6 +1260,26 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name) break; #endif +#if LV_USE_ROTARY + case LV_THEME_ROTARY: + lv_obj_clean_style_list(obj, LV_ROTARY_PART_BG); + list = lv_obj_get_style_list(obj, LV_ROTARY_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->arc_bg); + _lv_style_list_add_style(list, &styles->rotary_bg); + + lv_obj_clean_style_list(obj, LV_ROTARY_PART_INDIC); + list = lv_obj_get_style_list(obj, LV_ROTARY_PART_INDIC); + _lv_style_list_add_style(list, &styles->arc_indic); + _lv_style_list_add_style(list, &styles->rotary_indic); + + lv_obj_clean_style_list(obj, LV_ROTARY_PART_KNOB); + list = lv_obj_get_style_list(obj, LV_ROTARY_PART_KNOB); + _lv_style_list_add_style(list, &styles->btn); + _lv_style_list_add_style(list, &styles->rotary_knob); + + break; +#endif #if LV_USE_OBJMASK case LV_THEME_OBJMASK: diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c new file mode 100644 index 000000000..c3ef76683 --- /dev/null +++ b/src/lv_widgets/lv_rotary.c @@ -0,0 +1,458 @@ + +/** + * @file lv_rotary.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_rotary.h" +#if LV_USE_ROTARY != 0 + +#include "../lv_core/lv_debug.h" +#include "../lv_core/lv_group.h" +#include "../lv_core/lv_indev.h" +#include "../lv_draw/lv_draw.h" +#include "../lv_themes/lv_theme.h" +#include "../lv_misc/lv_math.h" +#include "lv_img.h" + +/********************* + * DEFINES + *********************/ +#define LV_OBJX_NAME "lv_rotary" + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_design_res_t lv_rotary_design(lv_obj_t * rotary, const lv_area_t * clip_area, lv_design_mode_t mode); +static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * param); +static lv_style_list_t * lv_rotary_get_style(lv_obj_t * rotary, uint8_t part); +// static void draw_bg(lv_obj_t * rotary, const lv_area_t * clip_area); +// static void draw_indic(lv_obj_t * rotary, const lv_area_t * clip_area); +static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area); + +/********************** + * STATIC VARIABLES + **********************/ +static lv_design_cb_t ancestor_design; +static lv_signal_cb_t ancestor_signal; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Create a rotary objects + * @param par pointer to an object, it will be the parent of the new rotary + * @param copy pointer to a rotary object, if not NULL then the new object will be copied from it + * @return pointer to the created rotary + */ +lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) +{ + LV_LOG_TRACE("rotary create started"); + + /*Create the ancestor rotary*/ + lv_obj_t * rotary = lv_arc_create(par, copy); + LV_ASSERT_MEM(rotary); + if(rotary == NULL) return NULL; + + if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(rotary); + if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(rotary); + + /*Allocate the rotary type specific extended data*/ + lv_rotary_ext_t * ext = lv_obj_allocate_ext_attr(rotary, sizeof(lv_rotary_ext_t)); + LV_ASSERT_MEM(ext); + if(ext == NULL) { + lv_obj_del(rotary); + return NULL; + } + + /*Initialize the allocated 'ext' */ + ext->arc.rotation_angle = 0; + ext->arc.bg_angle_start = 135; + ext->arc.bg_angle_end = 45; + ext->arc.arc_angle_start = 135; + ext->arc.arc_angle_end = 270; + ext->cur_value = 0; + ext->min_value = 0; + ext->max_value = 0; + ext->start_value = 0; + ext->dragging = false; + lv_style_list_init(&ext->style_bg); + lv_style_list_init(&ext->style_indic); + lv_style_list_init(&ext->style_knob); + + /*The signal and design functions are not copied so set them here*/ + lv_obj_set_signal_cb(rotary, lv_rotary_signal); + lv_obj_set_design_cb(rotary, lv_rotary_design); + + /*Init the new rotary rotary*/ + if(copy == NULL) { + lv_obj_set_click(rotary, true); + lv_obj_add_protect(rotary, LV_PROTECT_PRESS_LOST); + lv_obj_set_ext_click_area(rotary, 0, 0, LV_DPI / 10, LV_DPI / 10); + + lv_theme_apply(rotary, LV_THEME_ROTARY); + lv_obj_set_height(rotary, LV_DPI / 15); + } + /*Copy an existing rotary*/ + else { + lv_rotary_ext_t * copy_ext = lv_obj_get_ext_attr(copy); + ext->cur_value = copy_ext->cur_value; + ext->min_value = copy_ext->min_value; + ext->max_value = copy_ext->max_value; + ext->start_value = copy_ext->start_value; + ext->dragging = copy_ext->dragging; + lv_style_list_copy(&ext->style_bg, ©_ext->style_bg); + lv_style_list_copy(&ext->style_indic, ©_ext->style_indic); + lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); + + lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); + } + + LV_LOG_INFO("rotary created"); + + return rotary; +} + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new value on the rotary + * @param rotary pointer to a rotary object + * @param value new value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + */ +void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + if(ext->cur_value == value) return; + + int16_t new_value; + new_value = value > ext->max_value ? ext->max_value : value; + new_value = new_value < ext->min_value ? ext->min_value : new_value; + + if(ext->cur_value == new_value) return; + + ext->cur_value = new_value; + + lv_arc_set_end_angle( + rotary, + LV_MATH_MAP( + ext->cur_value, + ext->min_value, + ext->max_value, + ext->arc.arc_angle_start, + ext->arc.arc_angle_start + 360 + ) + ); +} + +/** + * Set a new value for the left knob of a rotary + * @param rotary pointer to a rotary object + * @param left_value new value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + */ +void lv_rotary_set_start_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + ext->start_value = value; +} + +/** + * Set minimum and the maximum values of a rotary + * @param rotary pointer to the rotary object + * @param min minimum value + * @param max maximum value + */ +void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + if(ext->min_value == min && ext->max_value == max) return; + + ext->min_value = min; + ext->max_value = max; + + if(ext->cur_value < min) { + ext->cur_value = min; + } + if(ext->cur_value > max) { + ext->cur_value = max; + } + + lv_rotary_set_value(rotary, ext->cur_value, false); +} + +/** + * Make the rotary symmetric to zero. The indicator will grow from zero instead of the minimum + * position. + * @param rotary pointer to a rotary object + * @param en true: enable disable symmetric behavior; false: disable + */ +void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + ext->type = type; + + lv_obj_invalidate(rotary); +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the value of a rotary + * @param rotary pointer to a rotary object + * @return the value of the rotary + */ +int16_t lv_rotary_get_value(const lv_obj_t * rotary) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); + return ext->cur_value; +} + +/** + * Get the value of the left knob of a rotary + * @param rotary pointer to a rotary object + * @return the start value of the rotary + */ +int16_t lv_rotary_get_start_value(const lv_obj_t * rotary) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + return ext->start_value; +} + +/** + * Get the minimum value of a rotary + * @param rotary pointer to a rotary object + * @return the minimum value of the rotary + */ +int16_t lv_rotary_get_min_value(const lv_obj_t * rotary) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + return ext->min_value; +} + +/** + * Get the maximum value of a rotary + * @param rotary pointer to a rotary object + * @return the maximum value of the rotary + */ +int16_t lv_rotary_get_max_value(const lv_obj_t * rotary) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + return ext->max_value; +} + +/** + * Give the rotary is being dragged or not + * @param rotary pointer to a rotary object + * @return true: drag in progress false: not dragged + */ +bool lv_rotary_is_dragged(const lv_obj_t * rotary) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); + return ext->dragging; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Handle the drawing related tasks of the rotarys + * @param rotary pointer to an object + * @param clip_area the object will be drawn only in this area + * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area + * (return 'true' if yes) + * LV_DESIGN_DRAW: draw the object (always return 'true') + * LV_DESIGN_DRAW_POST: drawing after every children are drawn + * @param return an element of `lv_design_res_t` + */ +static lv_design_res_t lv_rotary_design(lv_obj_t * rotary, const lv_area_t * clip_area, lv_design_mode_t mode) +{ + /*Return false if the object is not covers the mask_p area*/ + if(mode == LV_DESIGN_COVER_CHK) { + return LV_DESIGN_RES_NOT_COVER; + } + /*Draw the object*/ + else if(mode == LV_DESIGN_DRAW_MAIN) { + /*The ancestor design function will draw the background and the indicator.*/ + ancestor_design(rotary, clip_area, mode); + draw_knob(rotary, clip_area); + } + /*Post draw when the children are drawn*/ + else if(mode == LV_DESIGN_DRAW_POST) { + return ancestor_design(rotary, clip_area, mode); + } + + return LV_DESIGN_RES_OK; +} + +/** + * Signal function of the rotary + * @param rotary pointer to a rotary object + * @param sign a signal type from lv_signal_t enum + * @param param pointer to a signal specific variable + * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted + */ +static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * param) +{ + lv_res_t res; + + if(sign == LV_SIGNAL_GET_STYLE) { + lv_get_style_info_t * info = param; + info->result = lv_rotary_get_style(rotary, info->part); + if(info->result != NULL) return LV_RES_OK; + else return ancestor_signal(rotary, sign, param); + } + + /* Include the ancient signal function */ + res = ancestor_signal(rotary, sign, param); + if(res != LV_RES_OK) return res; + if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); + lv_point_t p; + + if(sign == LV_SIGNAL_PRESSED) { + ext->dragging = true; + if(lv_rotary_get_type(rotary) == LV_ROTARY_TYPE_NORMAL) { + ext->value_to_set = &ext->cur_value; + } + } + else if(sign == LV_SIGNAL_PRESSING && ext->value_to_set != NULL) { + lv_indev_get_point(param, &p); + + // TODO: get new_value and set + } + else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { + ext->dragging = false; + ext->value_to_set = NULL; + +#if LV_USE_GROUP + /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ + lv_group_t * g = lv_obj_get_group(rotary); + bool editing = lv_group_get_editing(g); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + if(indev_type == LV_INDEV_TYPE_ENCODER) { + if(editing) lv_group_set_editing(g, false); + } +#endif + + } + else if(sign == LV_SIGNAL_CONTROL) { + char c = *((char *)param); + + if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + 1, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - 1, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + } + else if(sign == LV_SIGNAL_CLEANUP) { + lv_obj_clean_style_list(rotary, LV_ROTARY_PART_KNOB); + } + else if(sign == LV_SIGNAL_GET_EDITABLE) { + bool * editable = (bool *)param; + *editable = true; + } + + return res; +} + + +static lv_style_list_t * lv_rotary_get_style(lv_obj_t * rotary, uint8_t part) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); + lv_style_list_t * style_dsc_p; + + switch(part) { + case LV_ROTARY_PART_BG: + style_dsc_p = &ext->style_bg; + break; + case LV_ROTARY_PART_INDIC: + style_dsc_p = &ext->style_indic; + break; + case LV_ROTARY_PART_KNOB: + style_dsc_p = &ext->style_knob; + break; + default: + style_dsc_p = NULL; + } + + return style_dsc_p; +} + +static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) +{ + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(rotary); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + + lv_coord_t left_bg = lv_obj_get_style_pad_left(rotary, LV_ROTARY_PART_BG); + lv_coord_t right_bg = lv_obj_get_style_pad_right(rotary, LV_ROTARY_PART_BG); + lv_coord_t top_bg = lv_obj_get_style_pad_top(rotary, LV_ROTARY_PART_BG); + lv_coord_t bottom_bg = lv_obj_get_style_pad_bottom(rotary, LV_ROTARY_PART_BG); + lv_coord_t r = (LV_MATH_MIN(lv_obj_get_width(rotary) - left_bg - right_bg, + lv_obj_get_height(rotary) - top_bg - bottom_bg)) / 2; + lv_coord_t indic_width = lv_obj_get_style_line_width(rotary, LV_ROTARY_PART_INDIC); + lv_area_t knob_area; + lv_draw_rect_dsc_t knob_rect_dsc; + lv_coord_t center_x = rotary->coords.x1 + r + left_bg; + lv_coord_t center_y = rotary->coords.y1 + r + top_bg; + + + if(r > 0) { + knob_area.x1 = center_x - r + indic_width + lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); + knob_area.x2 = center_x + r - indic_width - lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); + knob_area.y1 = center_y - r + indic_width + lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); + knob_area.y2 = center_y + r - indic_width - lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); + + lv_draw_rect_dsc_init(&knob_rect_dsc); + lv_obj_init_draw_rect_dsc(rotary, LV_ROTARY_PART_KNOB, &knob_rect_dsc); + + lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); + } +} + +#endif diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h new file mode 100644 index 000000000..14e5b1de7 --- /dev/null +++ b/src/lv_widgets/lv_rotary.h @@ -0,0 +1,281 @@ +/** + * @file lv_rotary.h + * + */ + +#ifndef LV_ROTARY_H +#define LV_ROTARY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_ROTARY != 0 + +/*Testing of dependencies*/ +#if LV_USE_ARC == 0 +#error "lv_rotary: lv_arc is required. Enable it in lv_conf.h (LV_USE_ARC 1) " +#endif + +#if LV_USE_BTN == 0 +#error "lv_rotary: lv_btn is required. Enable it in lv_conf.h (LV_USE_BTN 1) " +#endif + +#define LV_ROTARY_KNOB_SIZE_MIN 4 /* cannot make the knob smaller then this [px] */ + +#include "../lv_core/lv_obj.h" +#include "lv_arc.h" +#include "lv_btn.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_ROTARY_TYPE_NORMAL +}; +typedef uint8_t lv_rotary_type_t; + +/*Data of rotary*/ +typedef struct { + /*Ext. of ancestor*/ + lv_arc_ext_t arc; + /*New data for this type*/ + lv_btn_ext_t btn; + lv_rotary_type_t type; + lv_style_list_t style_bg; /* Style of the background */ + lv_style_list_t style_indic; /* Style of the indicator */ + lv_style_list_t style_knob; /* Style of the knob */ + int16_t cur_value; /*Current value of the rotary*/ + int16_t min_value; /*Minimum value of the rotary*/ + int16_t max_value; /*Maximum value of the rotary*/ + int16_t start_value; /*Start value of the rotary*/ + int16_t value_to_set; /*Start value of the rotary*/ + bool dragging; +} lv_rotary_ext_t; + +/** Built-in styles of rotary*/ +enum { + LV_ROTARY_PART_BG, /** Rotary background style. */ + LV_ROTARY_PART_INDIC, /** Rotary indicator (filled area) style. */ + LV_ROTARY_PART_KNOB, /** Rotary knob style. */ +}; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a rotary objects + * @param par pointer to an object, it will be the parent of the new rotary + * @param copy pointer to a rotary object, if not NULL then the new object will be copied from it + * @return pointer to the created rotary + */ +lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new value on the rotary + * @param rotary pointer to a rotary object + * @param value new value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + */ +void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim); + +/** + * Set a new value for the left knob of a rotary + * @param rotary pointer to a rotary object + * @param left_value new value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + */ +void lv_rotary_set_start_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim); + +/** + * Set minimum and the maximum values of a rotary + * @param rotary pointer to the rotary object + * @param min minimum value + * @param max maximum value + */ +void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max); + +/** + * Make the rotary symmetric to zero. The indicator will grow from zero instead of the minimum + * position. + * @param rotary pointer to a rotary object + * @param en true: enable disable symmetric behavior; false: disable + */ +void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type); + +/** + * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. + * @param arc pointer to an arc object + * @param start the start angle + */ +static inline void lv_rotary_set_start_angle(lv_obj_t * rotary, uint16_t start) { + lv_arc_set_start_angle(rotary, start); +} + +/** + * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. + * @param rotary pointer to an rotary object + * @param end the end angle + */ +static inline void lv_rotary_set_end_angle(lv_obj_t * rotary, uint16_t end) { + lv_arc_set_end_angle(rotary, end); +} + +/** + * Set the start and end angles + * @param rotary pointer to an rotary object + * @param start the start angle + * @param end the end angle + */ +static inline void lv_rotary_set_angles(lv_obj_t * rotary, uint16_t start, uint16_t end) { + lv_arc_set_angles(rotary, start, end); +} + +/** + * Set the start angle of ar otary indicator background. 0 deg: right, 90 bottom, etc. + * @param rotary pointer to an rotary object + * @param start the start angle + */ +static inline void lv_rotary_set_bg_start_angle(lv_obj_t * rotary, uint16_t start) { + lv_arc_set_bg_start_angle(rotary, start); +} + +/** + * Set the start angle of rotary indicator background. 0 deg: right, 90 bottom etc. + * @param rotary pointer to an rotary object + * @param end the end angle + */ +static inline void lv_rotary_set_bg_end_angle(lv_obj_t * rotary, uint16_t end) { + lv_arc_set_bg_end_angle(rotary, end); +} + +/** + * Set the start and end angles of the rotary indicator background + * @param rotary pointer to an rotary object + * @param start the start angle + * @param end the end angle + */ +static inline void lv_rotary_set_bg_angles(lv_obj_t * rotary, uint16_t start, uint16_t end) { + lv_arc_set_bg_angles(rotary, start, end); +} + +/** + * Set the rotation for the whole rotary indicator + * @param rotary pointer to an rotary object + * @param rotation_angle rotation angle + */ +static inline void lv_rotary_set_rotation(lv_obj_t * rotary, uint16_t rotation_angle) { + lv_arc_set_rotation(rotary, rotation_angle); +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the start angle of a rotary indicator. + * @param rotary pointer to an rotary object + * @return the start angle [0..360] + */ +static inline uint16_t lv_rotary_get_angle_start(lv_obj_t * rotary) { + return lv_rotary_get_angle_start(rotary); +} + +/** + * Get the end angle of a rotary indicator. + * @param rotary pointer to an rotary object + * @return the end angle [0..360] + */ +static inline uint16_t lv_rotary_get_angle_end(lv_obj_t * rotary) { + return lv_arc_get_angle_end(rotary); +} + +/** + * Get the start angle of a rotary indicator background. + * @param rotary pointer to an rotary object + * @return the start angle [0..360] + */ +static inline uint16_t lv_rotary_get_bg_angle_start(lv_obj_t * rotary) { + return lv_arc_get_bg_angle_start(rotary); +} + +/** + * Get the end angle of a rotary indicator background. + * @param rotary pointer to an rotary object + * @return the end angle [0..360] + */ +static inline uint16_t lv_rotary_get_bg_angle_end(lv_obj_t * rotary) { + return lv_arc_get_bg_angle_end(rotary); +} + +/** + * Get the value of the of a rotary + * @param rotary pointer to a rotary object + * @return the value of the of the rotary + */ +int16_t lv_rotary_get_value(const lv_obj_t * rotary); + +/** + * Get the value of the left knob of a rotary + * @param rotary pointer to a rotary object + * @return the start value of the rotary + */ +int16_t lv_rotary_get_start_value(const lv_obj_t * rotary); + +/** + * Get the minimum value of a rotary + * @param rotary pointer to a rotary object + * @return the minimum value of the rotary + */ +int16_t lv_rotary_get_min_value(const lv_obj_t * rotary); + +/** + * Get the maximum value of a rotary + * @param rotary pointer to a rotary object + * @return the maximum value of the rotary + */ +int16_t lv_rotary_get_max_value(const lv_obj_t * rotary); + +/** + * Give the rotary is being dragged or not + * @param rotary pointer to a rotary object + * @return true: drag in progress false: not dragged + */ +bool lv_rotary_is_dragged(const lv_obj_t * rotary); + +/** + * Get whether the rotary is symmetric or not. + * @param rotary pointer to a rotary object + * @return true: symmetric is enabled; false: disable + */ +static inline lv_rotary_type_t lv_rotary_get_type(lv_obj_t * rotary) +{ + return LV_ROTARY_TYPE_NORMAL; +} + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_rotary*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_ROTARY_H*/ From 2908a74b42cd73c0fc8efe1bba92847e43ab2e89 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 18 Jun 2020 17:11:15 -0700 Subject: [PATCH 02/97] Reduce knob pad get logic --- src/lv_widgets/lv_rotary.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index c3ef76683..3f3f6eb70 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -440,13 +440,13 @@ static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) lv_draw_rect_dsc_t knob_rect_dsc; lv_coord_t center_x = rotary->coords.x1 + r + left_bg; lv_coord_t center_y = rotary->coords.y1 + r + top_bg; - + lv_coord_t knob_inner = lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB) if(r > 0) { - knob_area.x1 = center_x - r + indic_width + lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); - knob_area.x2 = center_x + r - indic_width - lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); - knob_area.y1 = center_y - r + indic_width + lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); - knob_area.y2 = center_y + r - indic_width - lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); + knob_area.x1 = center_x - r + indic_width + knob_inner; + knob_area.x2 = center_x + r - indic_width - knob_inner; + knob_area.y1 = center_y - r + indic_width + knob_inner; + knob_area.y2 = center_y + r - indic_width - knob_inner; lv_draw_rect_dsc_init(&knob_rect_dsc); lv_obj_init_draw_rect_dsc(rotary, LV_ROTARY_PART_KNOB, &knob_rect_dsc); From 2dc14fc7e57d11a78e4a0bc21d1473c1065fb96f Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 18 Jun 2020 22:22:22 -0700 Subject: [PATCH 03/97] Add missing rotary widget import --- lvgl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lvgl.h b/lvgl.h index 5165a598b..eabad3f7a 100644 --- a/lvgl.h +++ b/lvgl.h @@ -53,6 +53,7 @@ extern "C" { #include "src/lv_widgets/lv_keyboard.h" #include "src/lv_widgets/lv_dropdown.h" #include "src/lv_widgets/lv_roller.h" +#include "src/lv_widgets/lv_rotary.h" #include "src/lv_widgets/lv_textarea.h" #include "src/lv_widgets/lv_canvas.h" #include "src/lv_widgets/lv_win.h" From b9d92236e3e0b87cde0354847d4f728daca8c4b1 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 18 Jun 2020 22:25:41 -0700 Subject: [PATCH 04/97] Add rotary to build.py defines --- tests/build.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/build.py b/tests/build.py index 73a06148f..f014027c7 100755 --- a/tests/build.py +++ b/tests/build.py @@ -120,6 +120,7 @@ minimal_monochrome = { "LV_USE_PAGE":0, "LV_USE_SPINNER":0, "LV_USE_ROLLER":0, + "LV_USE_ROTARY":0, "LV_USE_SLIDER":0, "LV_USE_SPINBOX":0, "LV_USE_SWITCH":0, @@ -196,6 +197,7 @@ all_obj_minimal_features = { "LV_USE_PAGE":1, "LV_USE_SPINNER":0, #Disabled beacsue needs anim "LV_USE_ROLLER":1, + "LV_USE_ROTARY":1, "LV_USE_SLIDER":1, "LV_USE_SPINBOX":1, "LV_USE_SWITCH":1, @@ -274,6 +276,7 @@ all_obj_all_features = { "LV_USE_PAGE":1, "LV_USE_SPINNER":1, "LV_USE_ROLLER":1, + "LV_USE_ROTARY":1, "LV_USE_SLIDER":1, "LV_USE_SPINBOX":1, "LV_USE_SWITCH":1, @@ -365,6 +368,7 @@ advanced_features = { "LV_USE_PAGE":1, "LV_USE_SPINNER":1, "LV_USE_ROLLER":1, + "LV_USE_ROTARY":1, "LV_USE_SLIDER":1, "LV_USE_SPINBOX":1, "LV_USE_SWITCH":1, From 6dddbde38757f1905a2e28b1d6584b205aec1fc1 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 18 Jun 2020 22:27:51 -0700 Subject: [PATCH 05/97] Add ifndef to internal conf --- src/lv_conf_internal.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 9ea1abbd7..30325b5ed 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -992,8 +992,9 @@ #endif /*Rotary (dependencies: lv_arc, lv_btn)*/ -#define LV_USE_ROTARY 1 - +#ifndef LV_USE_ROTARY +#define LV_USE_ROTARY 1 +#endif /*Slider (dependencies: lv_bar)*/ #ifndef LV_USE_SLIDER #define LV_USE_SLIDER 1 From a696aef9593bdb727a9b19208144746e5f6ff44c Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 18 Jun 2020 22:43:38 -0700 Subject: [PATCH 06/97] Use rotary param in type getter --- src/lv_widgets/lv_rotary.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 14e5b1de7..a62983b13 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -265,7 +265,9 @@ bool lv_rotary_is_dragged(const lv_obj_t * rotary); */ static inline lv_rotary_type_t lv_rotary_get_type(lv_obj_t * rotary) { - return LV_ROTARY_TYPE_NORMAL; + lv_bar_type_t type = lv_bar_get_type(rotary); + if(type == LV_ROTARY_TYPE_NORMAL) + return LV_ROTARY_TYPE_NORMAL; } /********************** From 168a7c4c456b96c2977e0640aac1ad63cb6feec8 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 18 Jun 2020 22:46:30 -0700 Subject: [PATCH 07/97] Add theme define --- src/lv_themes/lv_theme.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lv_themes/lv_theme.h b/src/lv_themes/lv_theme.h index 7b4f65b3d..13d5a1ccd 100644 --- a/src/lv_themes/lv_theme.h +++ b/src/lv_themes/lv_theme.h @@ -109,6 +109,9 @@ typedef enum { #if LV_USE_ROLLER LV_THEME_ROLLER, #endif +#if LV_USE_ROTARY + LV_THEME_ROTARY, +#endif #if LV_USE_SLIDER LV_THEME_SLIDER, #endif From 884be64d1745223af3e40b7065ee4b7734aa32cb Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 11:38:22 -0700 Subject: [PATCH 08/97] Fix rotary type getter. --- src/lv_widgets/lv_rotary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index a62983b13..0a0aef5cd 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -265,7 +265,7 @@ bool lv_rotary_is_dragged(const lv_obj_t * rotary); */ static inline lv_rotary_type_t lv_rotary_get_type(lv_obj_t * rotary) { - lv_bar_type_t type = lv_bar_get_type(rotary); + lv_rotary_type_t type = lv_rotary_get_type(rotary); if(type == LV_ROTARY_TYPE_NORMAL) return LV_ROTARY_TYPE_NORMAL; } From 1396fce9615302c6028a01b1f7718ac76e55155c Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 11:42:55 -0700 Subject: [PATCH 09/97] Fix debug import --- src/lv_widgets/lv_rotary.c | 2 +- src/lv_widgets/lv_rotary.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 3f3f6eb70..ad4cb85c8 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -10,7 +10,7 @@ #include "lv_rotary.h" #if LV_USE_ROTARY != 0 -#include "../lv_core/lv_debug.h" +#include "../lv_misc/lv_debug.h" #include "../lv_core/lv_group.h" #include "../lv_core/lv_indev.h" #include "../lv_draw/lv_draw.h" diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 0a0aef5cd..ddac0ccb0 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -26,8 +26,6 @@ extern "C" { #error "lv_rotary: lv_btn is required. Enable it in lv_conf.h (LV_USE_BTN 1) " #endif -#define LV_ROTARY_KNOB_SIZE_MIN 4 /* cannot make the knob smaller then this [px] */ - #include "../lv_core/lv_obj.h" #include "lv_arc.h" #include "lv_btn.h" @@ -36,6 +34,8 @@ extern "C" { * DEFINES *********************/ +#define LV_ROTARY_KNOB_SIZE_MIN 4 /* cannot make the knob smaller then this [px] */ + /********************** * TYPEDEFS **********************/ From b9dc9e81de2b4f6ca89e5cd56fcb8d5cfd6bf4de Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 11:44:29 -0700 Subject: [PATCH 10/97] Missing ; --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index ad4cb85c8..ba182ba2c 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -440,7 +440,7 @@ static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) lv_draw_rect_dsc_t knob_rect_dsc; lv_coord_t center_x = rotary->coords.x1 + r + left_bg; lv_coord_t center_y = rotary->coords.y1 + r + top_bg; - lv_coord_t knob_inner = lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB) + lv_coord_t knob_inner = lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); if(r > 0) { knob_area.x1 = center_x - r + indic_width + knob_inner; From 95b07a2d234662f290f67c31f9398aeb6d4a07b5 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 19 Jun 2020 23:25:17 +0200 Subject: [PATCH 11/97] rotary: clean up --- src/lv_widgets/lv_rotary.c | 48 ++++---------------------------------- src/lv_widgets/lv_rotary.h | 41 +++++++++----------------------- 2 files changed, 15 insertions(+), 74 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index ba182ba2c..b3f20785a 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -86,10 +86,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->cur_value = 0; ext->min_value = 0; ext->max_value = 0; - ext->start_value = 0; ext->dragging = false; - lv_style_list_init(&ext->style_bg); - lv_style_list_init(&ext->style_indic); lv_style_list_init(&ext->style_knob); /*The signal and design functions are not copied so set them here*/ @@ -111,10 +108,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->cur_value = copy_ext->cur_value; ext->min_value = copy_ext->min_value; ext->max_value = copy_ext->max_value; - ext->start_value = copy_ext->start_value; ext->dragging = copy_ext->dragging; - lv_style_list_copy(&ext->style_bg, ©_ext->style_bg); - lv_style_list_copy(&ext->style_indic, ©_ext->style_indic); lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); @@ -162,20 +156,6 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim ); } -/** - * Set a new value for the left knob of a rotary - * @param rotary pointer to a rotary object - * @param left_value new value - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately - */ -void lv_rotary_set_start_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - ext->start_value = value; -} - /** * Set minimum and the maximum values of a rotary * @param rotary pointer to the rotary object @@ -208,12 +188,12 @@ void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max) * @param rotary pointer to a rotary object * @param en true: enable disable symmetric behavior; false: disable */ -void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) +void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en) { LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - ext->type = type; + ext->sym = en; lv_obj_invalidate(rotary); } @@ -235,19 +215,6 @@ int16_t lv_rotary_get_value(const lv_obj_t * rotary) return ext->cur_value; } -/** - * Get the value of the left knob of a rotary - * @param rotary pointer to a rotary object - * @return the start value of the rotary - */ -int16_t lv_rotary_get_start_value(const lv_obj_t * rotary) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - return ext->start_value; -} - /** * Get the minimum value of a rotary * @param rotary pointer to a rotary object @@ -349,9 +316,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(sign == LV_SIGNAL_PRESSED) { ext->dragging = true; - if(lv_rotary_get_type(rotary) == LV_ROTARY_TYPE_NORMAL) { - ext->value_to_set = &ext->cur_value; - } } else if(sign == LV_SIGNAL_PRESSING && ext->value_to_set != NULL) { lv_indev_get_point(param, &p); @@ -408,10 +372,10 @@ static lv_style_list_t * lv_rotary_get_style(lv_obj_t * rotary, uint8_t part) switch(part) { case LV_ROTARY_PART_BG: - style_dsc_p = &ext->style_bg; + style_dsc_p = lv_obj_get_style_list(rotary, LV_ARC_PART_BG); break; case LV_ROTARY_PART_INDIC: - style_dsc_p = &ext->style_indic; + style_dsc_p = lv_obj_get_style_list(rotary, LV_ARC_PART_INDIC); break; case LV_ROTARY_PART_KNOB: style_dsc_p = &ext->style_knob; @@ -425,10 +389,6 @@ static lv_style_list_t * lv_rotary_get_style(lv_obj_t * rotary, uint8_t part) static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) { - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(rotary); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - lv_coord_t left_bg = lv_obj_get_style_pad_left(rotary, LV_ROTARY_PART_BG); lv_coord_t right_bg = lv_obj_get_style_pad_right(rotary, LV_ROTARY_PART_BG); lv_coord_t top_bg = lv_obj_get_style_pad_top(rotary, LV_ROTARY_PART_BG); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index ddac0ccb0..7d614d499 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -50,24 +50,21 @@ typedef struct { /*Ext. of ancestor*/ lv_arc_ext_t arc; /*New data for this type*/ - lv_btn_ext_t btn; - lv_rotary_type_t type; - lv_style_list_t style_bg; /* Style of the background */ - lv_style_list_t style_indic; /* Style of the indicator */ lv_style_list_t style_knob; /* Style of the knob */ int16_t cur_value; /*Current value of the rotary*/ int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ - int16_t start_value; /*Start value of the rotary*/ - int16_t value_to_set; /*Start value of the rotary*/ - bool dragging; + int16_t * value_to_set; /*Start value of the rotary*/ + uint16_t dragging :1; + uint16_t sym :1; } lv_rotary_ext_t; /** Built-in styles of rotary*/ enum { - LV_ROTARY_PART_BG, /** Rotary background style. */ - LV_ROTARY_PART_INDIC, /** Rotary indicator (filled area) style. */ - LV_ROTARY_PART_KNOB, /** Rotary knob style. */ + LV_ROTARY_PART_BG = LV_ARC_PART_BG, /** Rotary background style. */ + LV_ROTARY_PART_INDIC = LV_ARC_PART_INDIC, /** Rotary indicator (filled area) style. */ + LV_ROTARY_PART_KNOB = _LV_ARC_PART_VIRTUAL_LAST, /** Rotary knob style. */ + _LV_ROTARY_PART_VIRTUAL_LAST }; /********************** @@ -94,14 +91,6 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy); */ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim); -/** - * Set a new value for the left knob of a rotary - * @param rotary pointer to a rotary object - * @param left_value new value - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately - */ -void lv_rotary_set_start_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim); - /** * Set minimum and the maximum values of a rotary * @param rotary pointer to the rotary object @@ -116,7 +105,7 @@ void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max); * @param rotary pointer to a rotary object * @param en true: enable disable symmetric behavior; false: disable */ -void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type); +void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en); /** * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. @@ -230,13 +219,6 @@ static inline uint16_t lv_rotary_get_bg_angle_end(lv_obj_t * rotary) { */ int16_t lv_rotary_get_value(const lv_obj_t * rotary); -/** - * Get the value of the left knob of a rotary - * @param rotary pointer to a rotary object - * @return the start value of the rotary - */ -int16_t lv_rotary_get_start_value(const lv_obj_t * rotary); - /** * Get the minimum value of a rotary * @param rotary pointer to a rotary object @@ -263,11 +245,10 @@ bool lv_rotary_is_dragged(const lv_obj_t * rotary); * @param rotary pointer to a rotary object * @return true: symmetric is enabled; false: disable */ -static inline lv_rotary_type_t lv_rotary_get_type(lv_obj_t * rotary) +static inline bool lv_rotary_get_symmetric(lv_obj_t * rotary) { - lv_rotary_type_t type = lv_rotary_get_type(rotary); - if(type == LV_ROTARY_TYPE_NORMAL) - return LV_ROTARY_TYPE_NORMAL; + lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); + return ext->sym; } /********************** From 75a27e4cc778531180c091d31470f2568ccb23b0 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 19 Jun 2020 23:41:29 +0200 Subject: [PATCH 12/97] rotary: leave the default size from arc + fix style get --- src/lv_widgets/lv_rotary.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index b3f20785a..eb91dbebe 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -100,7 +100,6 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_ext_click_area(rotary, 0, 0, LV_DPI / 10, LV_DPI / 10); lv_theme_apply(rotary, LV_THEME_ROTARY); - lv_obj_set_height(rotary, LV_DPI / 15); } /*Copy an existing rotary*/ else { @@ -371,12 +370,6 @@ static lv_style_list_t * lv_rotary_get_style(lv_obj_t * rotary, uint8_t part) lv_style_list_t * style_dsc_p; switch(part) { - case LV_ROTARY_PART_BG: - style_dsc_p = lv_obj_get_style_list(rotary, LV_ARC_PART_BG); - break; - case LV_ROTARY_PART_INDIC: - style_dsc_p = lv_obj_get_style_list(rotary, LV_ARC_PART_INDIC); - break; case LV_ROTARY_PART_KNOB: style_dsc_p = &ext->style_knob; break; From 4e13d6ae4d5f616b06e23d9790c7374aa80ae633 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 15:59:04 -0700 Subject: [PATCH 13/97] Cast ext --- src/lv_widgets/lv_rotary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 7d614d499..f7f137407 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -247,7 +247,7 @@ bool lv_rotary_is_dragged(const lv_obj_t * rotary); */ static inline bool lv_rotary_get_symmetric(lv_obj_t * rotary) { - lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); + lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); return ext->sym; } From 7a7e1668fafdbccfd9f011e6af343ff7d92bdfce Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 17:15:15 -0700 Subject: [PATCH 14/97] Make value setter indic mapping from arc start to bg end. --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index eb91dbebe..04f2d939e 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -150,7 +150,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim ext->min_value, ext->max_value, ext->arc.arc_angle_start, - ext->arc.arc_angle_start + 360 + ext->arc.bg_angle_end ) ); } From f5d9e4bff4464c592821fe2edf768f1351a95a90 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 17:39:50 -0700 Subject: [PATCH 15/97] Fix range mapping for value setter assuming left to right indic --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 04f2d939e..7ea1cfa22 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -150,7 +150,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim ext->min_value, ext->max_value, ext->arc.arc_angle_start, - ext->arc.bg_angle_end + 360 + ext->arc.bg_angle_end ) ); } From e100565c673044947194a72a29c10b5fd36b3305 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 17:49:02 -0700 Subject: [PATCH 16/97] Move map function to proper func to avoid recalc of slope --- src/lv_misc/lv_math.c | 17 ++++++++++++++++- src/lv_misc/lv_math.h | 12 ++++++++++-- src/lv_widgets/lv_rotary.c | 9 ++------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index 230d79990..1b338ebd4 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -128,7 +128,6 @@ LV_ATTRIBUTE_FAST_MEM void _lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask q->f = (uint32_t)(root & 0xf) << 4; } - /** * Calculate the atan2 of a vector. * @param x @@ -232,6 +231,22 @@ int64_t _lv_pow(int64_t base, int8_t exp) return result; } +/** + * Get the mapped of a number given an imput and output range + * @param x integer which mapped value should be calculated + * @param min_in min input range + * @param max_in max input range + * @param in min output range + * @param out max output range + */ +LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max) +{ + int16_t slope = (max - min) / (max_in - min_in); + int16_t bias = min - slope * min_in; + + return bias + slope * x; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/lv_misc/lv_math.h b/src/lv_misc/lv_math.h index dc45ad630..0d72fb5af 100644 --- a/src/lv_misc/lv_math.h +++ b/src/lv_misc/lv_math.h @@ -31,8 +31,6 @@ extern "C" { #define LV_MATH_UDIV255(x) ((uint32_t)((uint32_t) (x) * 0x8081) >> 0x17) -#define LV_MATH_MAP(a, min_in, max_in, min, max) (min - (((max - min) / (max_in - min_in)) * min_in) + (((max - min) / (max_in - min_in)) * a)) - #define LV_IS_SIGNED(t) (((t)(-1)) < ((t) 0)) #define LV_UMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0xFULL << ((sizeof(t) * 8ULL) - 4ULL))) #define LV_SMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL))) @@ -114,6 +112,16 @@ LV_ATTRIBUTE_FAST_MEM void _lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask */ int64_t _lv_pow(int64_t base, int8_t exp); +/** + * Get the mapped of a number given an imput and output range + * @param x integer which mapped value should be calculated + * @param min_in min input range + * @param max_in max input range + * @param in min output range + * @param out max output range + */ +LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max); + /********************** * MACROS **********************/ diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 7ea1cfa22..309b263dc 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -145,13 +145,8 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim lv_arc_set_end_angle( rotary, - LV_MATH_MAP( - ext->cur_value, - ext->min_value, - ext->max_value, - ext->arc.arc_angle_start, - 360 + ext->arc.bg_angle_end - ) + _lv_map(ext->cur_value, ext->min_value, ext->max_value, + ext->arc.arc_angle_start, 360 + ext->arc.bg_angle_end) ); } From c8546700625f29e1c125c627715224a176a1db80 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 18:00:28 -0700 Subject: [PATCH 17/97] Test float for mapping --- src/lv_misc/lv_math.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index 1b338ebd4..c0ea6ec78 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -239,7 +239,7 @@ int64_t _lv_pow(int64_t base, int8_t exp) * @param in min output range * @param out max output range */ -LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max) +LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, float min_in, float max_in, float min, float max) { int16_t slope = (max - min) / (max_in - min_in); int16_t bias = min - slope * min_in; From cf4db992063c7f51b2688e5f085561f2e5fa29a5 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 18:01:15 -0700 Subject: [PATCH 18/97] Test float for mapping --- src/lv_misc/lv_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_misc/lv_math.h b/src/lv_misc/lv_math.h index 0d72fb5af..aeb9e4d7a 100644 --- a/src/lv_misc/lv_math.h +++ b/src/lv_misc/lv_math.h @@ -120,7 +120,7 @@ int64_t _lv_pow(int64_t base, int8_t exp); * @param in min output range * @param out max output range */ -LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max); +LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, float min_in, float max_in, float min, float max); /********************** * MACROS From 446b0b6429d2c619cc0f3e0ef42dfdc35c658c7a Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 19 Jun 2020 18:05:55 -0700 Subject: [PATCH 19/97] Floats working fro value mapping --- src/lv_misc/lv_math.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index c0ea6ec78..7c467b5f1 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -241,8 +241,8 @@ int64_t _lv_pow(int64_t base, int8_t exp) */ LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, float min_in, float max_in, float min, float max) { - int16_t slope = (max - min) / (max_in - min_in); - int16_t bias = min - slope * min_in; + float slope = (max - min) / (max_in - min_in); + float bias = min - slope * min_in; return bias + slope * x; } From 1dfdabd638d7624455f8e8b0e97c6d507b3cdc1b Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 11:06:06 -0700 Subject: [PATCH 20/97] Test btn extension --- src/lv_themes/lv_theme_material.c | 14 +++++++------- src/lv_widgets/lv_rotary.h | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index e0b0e9762..54399c540 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -798,14 +798,14 @@ static void rotary_init(void) #if LV_USE_ROTARY != 0 style_init_reset(&styles->rotary_bg); lv_style_set_clip_corner(&styles->rotary_bg, LV_STATE_DEFAULT, true); - lv_style_set_pad_left(&styles->rotary_bg, LV_STATE_DEFAULT, 0); - lv_style_set_pad_right(&styles->rotary_bg, LV_STATE_DEFAULT, 0); - lv_style_set_pad_top(&styles->rotary_bg, LV_STATE_DEFAULT, 0); - lv_style_set_pad_bottom(&styles->rotary_bg, LV_STATE_DEFAULT, 0); - lv_style_set_pad_inner(&styles->rotary_bg, LV_STATE_DEFAULT, 0); - lv_style_set_border_width(&styles->rotary_bg, LV_STATE_DEFAULT, 0); + lv_style_set_pad_left(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); + lv_style_set_pad_right(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); + lv_style_set_pad_top(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); + lv_style_set_pad_bottom(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); + lv_style_set_pad_inner(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); + lv_style_set_border_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(2)); lv_style_set_line_color(&styles->rotary_bg, LV_STATE_DEFAULT, COLOR_BG_SEC); - lv_style_set_line_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(8)); + lv_style_set_line_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(2)); lv_style_set_line_rounded(&styles->rotary_bg, LV_STATE_DEFAULT, true); style_init_reset(&styles->rotary_indic); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index f7f137407..49b5856e0 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -45,6 +45,18 @@ enum { }; typedef uint8_t lv_rotary_type_t; +/** Possible states of a rotary.*/ +enum { + LV_ROTARY_STATE_RELEASED = LV_BTN_STATE_RELEASED, + LV_ROTARY_STATE_PRESSED = LV_BTN_STATE_PRESSED, + LV_ROTARY_STATE_DISABLED = LV_BTN_STATE_DISABLED, + LV_ROTARY_STATE_CHECKED_RELEASED = LV_BTN_STATE_CHECKED_RELEASED, + LV_ROTARY_STATE_CHECKED_PRESSED = LV_BTN_STATE_CHECKED_PRESSED, + LV_ROTARY_STATE_CHECKED_DISABLED = LV_BTN_STATE_CHECKED_DISABLED, + _LV_ROTARY_STATE_LAST = _LV_BTN_STATE_LAST, /* Number of states*/ +}; +typedef uint8_t lv_btn_state_t; + /*Data of rotary*/ typedef struct { /*Ext. of ancestor*/ @@ -172,6 +184,16 @@ static inline void lv_rotary_set_rotation(lv_obj_t * rotary, uint16_t rotation_a lv_arc_set_rotation(rotary, rotation_angle); } +/** + * Set the state of the rotary + * @param rotary pointer to a rotary object + * @param state the new state of the rotary (from lv_rotary_state_t enum) + */ +void lv_rotary_set_state(lv_obj_t * rotary, lv_rotary_state_t state) +{ + lv_btn_set_state(rotary, state); +} + /*===================== * Getter functions *====================*/ From b1afc3f34d101b3ec5ec45dbf6fc14e3e3893d4d Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 11:11:26 -0700 Subject: [PATCH 21/97] Add rotary state --- src/lv_widgets/lv_rotary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 49b5856e0..fa584e0fd 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -55,7 +55,7 @@ enum { LV_ROTARY_STATE_CHECKED_DISABLED = LV_BTN_STATE_CHECKED_DISABLED, _LV_ROTARY_STATE_LAST = _LV_BTN_STATE_LAST, /* Number of states*/ }; -typedef uint8_t lv_btn_state_t; +typedef uint8_t lv_rotary_state_t; /*Data of rotary*/ typedef struct { From 9b38b3542032ebed46cf6b8fdf3c352dcbf7d324 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 11:13:37 -0700 Subject: [PATCH 22/97] Static state setter --- src/lv_widgets/lv_rotary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index fa584e0fd..5ddd1a485 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -189,7 +189,7 @@ static inline void lv_rotary_set_rotation(lv_obj_t * rotary, uint16_t rotation_a * @param rotary pointer to a rotary object * @param state the new state of the rotary (from lv_rotary_state_t enum) */ -void lv_rotary_set_state(lv_obj_t * rotary, lv_rotary_state_t state) +static inline void lv_rotary_set_state(lv_obj_t * rotary, lv_rotary_state_t state) { lv_btn_set_state(rotary, state); } From f6d75e759c63136b8a9f5023642ddc5a8bb732ae Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 12:12:42 -0700 Subject: [PATCH 23/97] Add btn like signal handling for knob part. Add custom event to distuinguish from VALUE_CHANGED --- src/lv_core/lv_obj.h | 1 + src/lv_widgets/lv_rotary.c | 49 ++++++++++++++++++++++++++++++++++++++ src/lv_widgets/lv_rotary.h | 43 +++++++++++++++++++++++++++++++-- 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 88b71cb99..9d5edffb5 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -102,6 +102,7 @@ enum { LV_EVENT_APPLY, /**< "Ok", "Apply" or similar specific button has clicked*/ LV_EVENT_CANCEL, /**< "Close", "Cancel" or similar specific button has clicked*/ LV_EVENT_DELETE, /**< Object is being deleted */ + _LV_EVENT_LAST /** Number of events*/ }; typedef uint8_t lv_event_t; /**< Type of event being sent to the object. */ diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 309b263dc..0fd4b5cc3 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -87,6 +87,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->min_value = 0; ext->max_value = 0; ext->dragging = false; + ext->checkable = 0; lv_style_list_init(&ext->style_knob); /*The signal and design functions are not copied so set them here*/ @@ -108,6 +109,8 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->min_value = copy_ext->min_value; ext->max_value = copy_ext->max_value; ext->dragging = copy_ext->dragging; + ext->sym = copy_ext->sym; + ext->checkable = copy_ext->checkable; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); @@ -192,6 +195,20 @@ void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en) lv_obj_invalidate(rotary); } +/** + * Enable the toggled states + * @param rotary pointer to a button object + * @param tgl true: enable toggled states, false: disable + */ +void lv_rotary_set_checkable(lv_obj_t * rotary, bool tgl) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + + ext->checkable = tgl != false ? 1 : 0; +} + /*===================== * Getter functions *====================*/ @@ -248,6 +265,20 @@ bool lv_rotary_is_dragged(const lv_obj_t * rotary) return ext->dragging; } +/** + * Get the toggle enable attribute of the rotary + * @param rotary pointer to a rotary object + * @return true: toggle enabled, false: disabled + */ +bool lv_rotary_get_checkable(const lv_obj_t * rotary) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + + return ext->checkable != 0 ? true : false; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -305,6 +336,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(res != LV_RES_OK) return res; if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); + bool tgl = lv_rotary_get_checkable(rotary); lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); lv_point_t p; @@ -320,6 +352,23 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par ext->dragging = false; ext->value_to_set = NULL; + /*If not dragged and it was not long press action then + *change state and run the action*/ + if(lv_indev_is_dragging(param) == false && tgl) { + uint32_t toggled = 0; + if(lv_obj_get_state(rotary, LV_ROTARY_PART_KNOB) & LV_STATE_CHECKED) { + lv_btn_set_state(rotary, LV_ROTARY_STATE_RELEASED); + toggled = 0; + } + else { + lv_btn_set_state(rotary, LV_ROTARY_STATE_CHECKED_RELEASED); + toggled = 1; + } + + res = lv_event_send(rotary, LV_EVENT_ROTARY_TOGGLED, &toggled); + if(res != LV_RES_OK) return res; + } + #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ lv_group_t * g = lv_obj_get_group(rotary); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 5ddd1a485..f833902c8 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -69,6 +69,7 @@ typedef struct { int16_t * value_to_set; /*Start value of the rotary*/ uint16_t dragging :1; uint16_t sym :1; + uint8_t checkable :1; /* 1: Toggle enabled*/ } lv_rotary_ext_t; /** Built-in styles of rotary*/ @@ -79,6 +80,13 @@ enum { _LV_ROTARY_PART_VIRTUAL_LAST }; +/** Custom events of rotary*/ +enum { + LV_EVENT_ROTARY_TOGGLED = _LV_EVENT_LAST +}; +typedef uint8_t lv_rotary_event_t; + + /********************** * GLOBAL PROTOTYPES **********************/ @@ -184,16 +192,30 @@ static inline void lv_rotary_set_rotation(lv_obj_t * rotary, uint16_t rotation_a lv_arc_set_rotation(rotary, rotation_angle); } +/** + * Enable the toggled states + * @param rotary pointer to a rotary object + * @param tgl true: enable toggled states, false: disable + */ +void lv_rotary_set_checkable(lv_obj_t * rotary, bool tgl) + /** * Set the state of the rotary * @param rotary pointer to a rotary object * @param state the new state of the rotary (from lv_rotary_state_t enum) */ -static inline void lv_rotary_set_state(lv_obj_t * rotary, lv_rotary_state_t state) -{ +static inline void lv_rotary_set_state(lv_obj_t * rotary, lv_rotary_state_t state) { lv_btn_set_state(rotary, state); } +/** + * Toggle the state of the rotary (ON->OFF, OFF->ON) + * @param rotary pointer to a rotary object + */ +static inline void lv_rotary_toggle(lv_obj_t * rotary) { + lv_btn_toggle(rotary); +} + /*===================== * Getter functions *====================*/ @@ -273,6 +295,23 @@ static inline bool lv_rotary_get_symmetric(lv_obj_t * rotary) return ext->sym; } +/** + * Get the current state of the rotary + * @param rotary pointer to a rotary object + * @return the state of the rotary (from lv_rotary_state_t enum). + * If the rotary is in disabled state `LV_ROTARY_STATE_DISABLED` will be ORed to the other rotary states. + */ +static inline lv_btn_state_t lv_rotary_get_state(const lv_obj_t * rotary) { + return lv_btn_get_state(rotary); +} + +/** + * Get the toggle enable attribute of the rotary + * @param rotary pointer to a rotary object + * @return true: toggle enabled, false: disabled + */ +bool lv_rotary_get_checkable(const lv_obj_t * rotary) + /********************** * MACROS **********************/ From 1860742c1349aa618e83cb5e217e7b11b644ed49 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 12:14:17 -0700 Subject: [PATCH 24/97] Fix missing ;. Add custom event last --- src/lv_widgets/lv_rotary.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index f833902c8..51be3ea04 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -82,7 +82,8 @@ enum { /** Custom events of rotary*/ enum { - LV_EVENT_ROTARY_TOGGLED = _LV_EVENT_LAST + LV_EVENT_ROTARY_TOGGLED = _LV_EVENT_LAST, + _LV_EVENT_ROTARY_LAST }; typedef uint8_t lv_rotary_event_t; @@ -197,7 +198,7 @@ static inline void lv_rotary_set_rotation(lv_obj_t * rotary, uint16_t rotation_a * @param rotary pointer to a rotary object * @param tgl true: enable toggled states, false: disable */ -void lv_rotary_set_checkable(lv_obj_t * rotary, bool tgl) +void lv_rotary_set_checkable(lv_obj_t * rotary, bool tgl); /** * Set the state of the rotary From f3773694bcfeb74d705c88dfd1229c2b8115b59a Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 12:17:15 -0700 Subject: [PATCH 25/97] Remove custom event in favor or NULL diff --- src/lv_widgets/lv_rotary.c | 2 +- src/lv_widgets/lv_rotary.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 0fd4b5cc3..37bcb70fe 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -365,7 +365,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par toggled = 1; } - res = lv_event_send(rotary, LV_EVENT_ROTARY_TOGGLED, &toggled); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, &toggled); /** non-NULL indicates toggle event*/ if(res != LV_RES_OK) return res; } diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 51be3ea04..b0217d80e 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -80,13 +80,6 @@ enum { _LV_ROTARY_PART_VIRTUAL_LAST }; -/** Custom events of rotary*/ -enum { - LV_EVENT_ROTARY_TOGGLED = _LV_EVENT_LAST, - _LV_EVENT_ROTARY_LAST -}; -typedef uint8_t lv_rotary_event_t; - /********************** * GLOBAL PROTOTYPES From fa8deb524d34b3985eb98220fc0b6f17e47070e4 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 12:18:53 -0700 Subject: [PATCH 26/97] Mising ; --- src/lv_widgets/lv_rotary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index b0217d80e..7ca0beb88 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -304,7 +304,7 @@ static inline lv_btn_state_t lv_rotary_get_state(const lv_obj_t * rotary) { * @param rotary pointer to a rotary object * @return true: toggle enabled, false: disabled */ -bool lv_rotary_get_checkable(const lv_obj_t * rotary) +bool lv_rotary_get_checkable(const lv_obj_t * rotary); /********************** * MACROS From 35c0cfcfea30b0c8ed92ba88fef7f691bf87981d Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 12:23:24 -0700 Subject: [PATCH 27/97] Use custom event as data is not transfered to CB --- src/lv_widgets/lv_rotary.c | 2 +- src/lv_widgets/lv_rotary.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 37bcb70fe..0fd4b5cc3 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -365,7 +365,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par toggled = 1; } - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, &toggled); /** non-NULL indicates toggle event*/ + res = lv_event_send(rotary, LV_EVENT_ROTARY_TOGGLED, &toggled); if(res != LV_RES_OK) return res; } diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 7ca0beb88..70f48ad84 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -80,6 +80,12 @@ enum { _LV_ROTARY_PART_VIRTUAL_LAST }; +/** Custom events of rotary*/ +enum { + LV_EVENT_ROTARY_TOGGLED = _LV_EVENT_LAST, + _LV_EVENT_ROTARY_LAST +}; +typedef uint8_t lv_rotary_event_t; /********************** * GLOBAL PROTOTYPES From 3e079a47aedd379184a4fa7e819c269207724ca9 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 16:40:47 -0700 Subject: [PATCH 28/97] Pull btn functionality out for now, make checked state make DEAFULT. Add dragging value setters. --- src/lv_themes/lv_theme_material.c | 4 ++++ src/lv_widgets/lv_rotary.c | 32 +++++++++++-------------------- src/lv_widgets/lv_rotary.h | 13 +++---------- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index 54399c540..f02e122c7 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -814,6 +814,10 @@ static void rotary_init(void) lv_style_set_line_rounded(&styles->rotary_indic, LV_STATE_DEFAULT, true); style_init_reset(&styles->rotary_knob); + lv_style_set_bg_color(&styles->rotary_knob, LV_STATE_CHECKED, COLOR_BTN); + lv_style_set_border_opa(&styles->rotary_knob, LV_STATE_CHECKED, COLOR_BTN_BORDER); + lv_style_set_text_color(&styles->rotary_knob, LV_STATE_CHECKED, IS_LIGHT ? lv_color_hex(0x31404f) : lv_color_hex(0xffffff)); + lv_style_set_value_color(&styles->rotary_knob, LV_STATE_CHECKED, IS_LIGHT ? lv_color_hex(0x31404f) : lv_color_hex(0xffffff)); lv_style_set_bg_opa(&styles->rotary_knob, LV_STATE_DEFAULT, LV_OPA_COVER); lv_style_set_bg_color(&styles->rotary_knob, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_style_set_radius(&styles->rotary_knob, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 0fd4b5cc3..f948ce7d5 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -33,8 +33,6 @@ static lv_design_res_t lv_rotary_design(lv_obj_t * rotary, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * param); static lv_style_list_t * lv_rotary_get_style(lv_obj_t * rotary, uint8_t part); -// static void draw_bg(lv_obj_t * rotary, const lv_area_t * clip_area); -// static void draw_indic(lv_obj_t * rotary, const lv_area_t * clip_area); static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area); /********************** @@ -343,32 +341,24 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(sign == LV_SIGNAL_PRESSED) { ext->dragging = true; } - else if(sign == LV_SIGNAL_PRESSING && ext->value_to_set != NULL) { + else if(sign == LV_SIGNAL_PRESSING && ext->last_drag_x != NULL) { lv_indev_get_point(param, &p); - // TODO: get new_value and set + if (ext->right_knob_area.y1 < p.y && p.y < ext->right_knob_area.y2) { + if (p.x > ext->last_drag_x && p.x < ext->right_knob_area.x2) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + 1, LV_ANIM_ON); + } + else if (p.x < ext->last_drag_x && p.x > ext->right_knob_area.x1) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - 1, LV_ANIM_ON); + } + } + + ext->last_drag_x = p.x; } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; ext->value_to_set = NULL; - /*If not dragged and it was not long press action then - *change state and run the action*/ - if(lv_indev_is_dragging(param) == false && tgl) { - uint32_t toggled = 0; - if(lv_obj_get_state(rotary, LV_ROTARY_PART_KNOB) & LV_STATE_CHECKED) { - lv_btn_set_state(rotary, LV_ROTARY_STATE_RELEASED); - toggled = 0; - } - else { - lv_btn_set_state(rotary, LV_ROTARY_STATE_CHECKED_RELEASED); - toggled = 1; - } - - res = lv_event_send(rotary, LV_EVENT_ROTARY_TOGGLED, &toggled); - if(res != LV_RES_OK) return res; - } - #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ lv_group_t * g = lv_obj_get_group(rotary); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 70f48ad84..f0fcdecb7 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -66,10 +66,9 @@ typedef struct { int16_t cur_value; /*Current value of the rotary*/ int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ - int16_t * value_to_set; /*Start value of the rotary*/ uint16_t dragging :1; + lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ uint16_t sym :1; - uint8_t checkable :1; /* 1: Toggle enabled*/ } lv_rotary_ext_t; /** Built-in styles of rotary*/ @@ -77,16 +76,10 @@ enum { LV_ROTARY_PART_BG = LV_ARC_PART_BG, /** Rotary background style. */ LV_ROTARY_PART_INDIC = LV_ARC_PART_INDIC, /** Rotary indicator (filled area) style. */ LV_ROTARY_PART_KNOB = _LV_ARC_PART_VIRTUAL_LAST, /** Rotary knob style. */ - _LV_ROTARY_PART_VIRTUAL_LAST + _LV_ROTARY_PART_VIRTUAL_LAST, + _LV_ROTARY_PART_REAL_LAST = _LV_ARC_PART_REAL_LAST }; -/** Custom events of rotary*/ -enum { - LV_EVENT_ROTARY_TOGGLED = _LV_EVENT_LAST, - _LV_EVENT_ROTARY_LAST -}; -typedef uint8_t lv_rotary_event_t; - /********************** * GLOBAL PROTOTYPES **********************/ From 5a0c0e2e97ac560ca1eaa559da9e41e3193b7e6b Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 16:43:53 -0700 Subject: [PATCH 29/97] Add value change event calls for dragging --- src/lv_widgets/lv_rotary.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index f948ce7d5..69c41812e 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -346,14 +346,19 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if (ext->right_knob_area.y1 < p.y && p.y < ext->right_knob_area.y2) { if (p.x > ext->last_drag_x && p.x < ext->right_knob_area.x2) { + ext->last_drag_x = p.x; lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + 1, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; } else if (p.x < ext->last_drag_x && p.x > ext->right_knob_area.x1) { + ext->last_drag_x = p.x; lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - 1, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; } } - ext->last_drag_x = p.x; } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; From 71f8497ee6632970fb4620113538de36f8d09027 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 16:47:23 -0700 Subject: [PATCH 30/97] Add knob_area ext --- src/lv_widgets/lv_rotary.c | 8 +++++--- src/lv_widgets/lv_rotary.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 69c41812e..76cc24d2d 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -344,14 +344,14 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par else if(sign == LV_SIGNAL_PRESSING && ext->last_drag_x != NULL) { lv_indev_get_point(param, &p); - if (ext->right_knob_area.y1 < p.y && p.y < ext->right_knob_area.y2) { - if (p.x > ext->last_drag_x && p.x < ext->right_knob_area.x2) { + if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { + if (p.x > ext->last_drag_x && p.x < ext->knob_area.x2) { ext->last_drag_x = p.x; lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + 1, LV_ANIM_ON); res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } - else if (p.x < ext->last_drag_x && p.x > ext->right_knob_area.x1) { + else if (p.x < ext->last_drag_x && p.x > ext->knob_area.x1) { ext->last_drag_x = p.x; lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - 1, LV_ANIM_ON); res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); @@ -445,6 +445,8 @@ static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); } + + lv_area_copy(&ext->knob_area, &knob_area); } #endif diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index f0fcdecb7..7870e3eb6 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -63,6 +63,7 @@ typedef struct { lv_arc_ext_t arc; /*New data for this type*/ lv_style_list_t style_knob; /* Style of the knob */ + lv_area_t knob_area; /* Area of the knob */ int16_t cur_value; /*Current value of the rotary*/ int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ From fc14c2c01c4d5c90c22ff3dfcc75e5dd28b9e06f Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 17:11:12 -0700 Subject: [PATCH 31/97] Remove chechable and toggle --- src/lv_widgets/lv_rotary.c | 31 ------------------------------- src/lv_widgets/lv_rotary.h | 22 ---------------------- 2 files changed, 53 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 76cc24d2d..626fef2af 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -85,7 +85,6 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->min_value = 0; ext->max_value = 0; ext->dragging = false; - ext->checkable = 0; lv_style_list_init(&ext->style_knob); /*The signal and design functions are not copied so set them here*/ @@ -108,7 +107,6 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->max_value = copy_ext->max_value; ext->dragging = copy_ext->dragging; ext->sym = copy_ext->sym; - ext->checkable = copy_ext->checkable; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); @@ -193,20 +191,6 @@ void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en) lv_obj_invalidate(rotary); } -/** - * Enable the toggled states - * @param rotary pointer to a button object - * @param tgl true: enable toggled states, false: disable - */ -void lv_rotary_set_checkable(lv_obj_t * rotary, bool tgl) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - - ext->checkable = tgl != false ? 1 : 0; -} - /*===================== * Getter functions *====================*/ @@ -263,20 +247,6 @@ bool lv_rotary_is_dragged(const lv_obj_t * rotary) return ext->dragging; } -/** - * Get the toggle enable attribute of the rotary - * @param rotary pointer to a rotary object - * @return true: toggle enabled, false: disabled - */ -bool lv_rotary_get_checkable(const lv_obj_t * rotary) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - - return ext->checkable != 0 ? true : false; -} - /********************** * STATIC FUNCTIONS **********************/ @@ -334,7 +304,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(res != LV_RES_OK) return res; if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - bool tgl = lv_rotary_get_checkable(rotary); lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); lv_point_t p; diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 7870e3eb6..9b4b73985 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -186,13 +186,6 @@ static inline void lv_rotary_set_rotation(lv_obj_t * rotary, uint16_t rotation_a lv_arc_set_rotation(rotary, rotation_angle); } -/** - * Enable the toggled states - * @param rotary pointer to a rotary object - * @param tgl true: enable toggled states, false: disable - */ -void lv_rotary_set_checkable(lv_obj_t * rotary, bool tgl); - /** * Set the state of the rotary * @param rotary pointer to a rotary object @@ -202,14 +195,6 @@ static inline void lv_rotary_set_state(lv_obj_t * rotary, lv_rotary_state_t stat lv_btn_set_state(rotary, state); } -/** - * Toggle the state of the rotary (ON->OFF, OFF->ON) - * @param rotary pointer to a rotary object - */ -static inline void lv_rotary_toggle(lv_obj_t * rotary) { - lv_btn_toggle(rotary); -} - /*===================== * Getter functions *====================*/ @@ -299,13 +284,6 @@ static inline lv_btn_state_t lv_rotary_get_state(const lv_obj_t * rotary) { return lv_btn_get_state(rotary); } -/** - * Get the toggle enable attribute of the rotary - * @param rotary pointer to a rotary object - * @return true: toggle enabled, false: disabled - */ -bool lv_rotary_get_checkable(const lv_obj_t * rotary); - /********************** * MACROS **********************/ From 15ec0f8e2fd070510eee2a2a7d58cd731c9b78cd Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 17:15:09 -0700 Subject: [PATCH 32/97] Remove value_to_set remnant. Do not override checked opacity --- src/lv_themes/lv_theme_material.c | 1 - src/lv_widgets/lv_rotary.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index f02e122c7..edb106c6f 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -815,7 +815,6 @@ static void rotary_init(void) style_init_reset(&styles->rotary_knob); lv_style_set_bg_color(&styles->rotary_knob, LV_STATE_CHECKED, COLOR_BTN); - lv_style_set_border_opa(&styles->rotary_knob, LV_STATE_CHECKED, COLOR_BTN_BORDER); lv_style_set_text_color(&styles->rotary_knob, LV_STATE_CHECKED, IS_LIGHT ? lv_color_hex(0x31404f) : lv_color_hex(0xffffff)); lv_style_set_value_color(&styles->rotary_knob, LV_STATE_CHECKED, IS_LIGHT ? lv_color_hex(0x31404f) : lv_color_hex(0xffffff)); lv_style_set_bg_opa(&styles->rotary_knob, LV_STATE_DEFAULT, LV_OPA_COVER); diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 626fef2af..bcd85721a 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -331,7 +331,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; - ext->value_to_set = NULL; + ext->last_drag_x = NULL; #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ From 866e088f988f8c19acd0f99c35fc8ab14f7b03bc Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 17:16:57 -0700 Subject: [PATCH 33/97] Copy knob_area to ext --- src/lv_widgets/lv_rotary.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index bcd85721a..d725756be 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -402,6 +402,8 @@ static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) lv_coord_t center_x = rotary->coords.x1 + r + left_bg; lv_coord_t center_y = rotary->coords.y1 + r + top_bg; lv_coord_t knob_inner = lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); + + lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); if(r > 0) { knob_area.x1 = center_x - r + indic_width + knob_inner; @@ -414,7 +416,7 @@ static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); } - + lv_area_copy(&ext->knob_area, &knob_area); } From c93ef97ab9796f341a6ab9a942c8ac218a8eb202 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 17:18:53 -0700 Subject: [PATCH 34/97] Remove NULL comp --- src/lv_widgets/lv_rotary.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index d725756be..a1f127894 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -308,9 +308,13 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_point_t p; if(sign == LV_SIGNAL_PRESSED) { + lv_indev_get_point(param, &p); + + ext->last_drag_x = p.x; ext->dragging = true; + } - else if(sign == LV_SIGNAL_PRESSING && ext->last_drag_x != NULL) { + else if(sign == LV_SIGNAL_PRESSING) { lv_indev_get_point(param, &p); if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { @@ -331,7 +335,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; - ext->last_drag_x = NULL; #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ From a7350282f08ff00c6e11b4654fbc074e6dc6f0c3 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 17:24:34 -0700 Subject: [PATCH 35/97] Use drag diff for value setting --- src/lv_widgets/lv_rotary.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index a1f127894..fc04ef80c 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -316,17 +316,18 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_PRESSING) { lv_indev_get_point(param, &p); - + lv_coord_t drag_x_diff = ext->last_drag - p.x; + + ext->last_drag_x = p.x; if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - if (p.x > ext->last_drag_x && p.x < ext->knob_area.x2) { - ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + 1, LV_ANIM_ON); + if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff, LV_ANIM_ON); res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } - else if (p.x < ext->last_drag_x && p.x > ext->knob_area.x1) { + else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - 1, LV_ANIM_ON); + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff, LV_ANIM_ON); res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } From 3721fc52a8ab7ea2bede18a0a2a852bd0d4febb3 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 17:25:14 -0700 Subject: [PATCH 36/97] Typo --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index fc04ef80c..b4e5142b8 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -316,7 +316,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_PRESSING) { lv_indev_get_point(param, &p); - lv_coord_t drag_x_diff = ext->last_drag - p.x; + lv_coord_t drag_x_diff = ext->last_drag_x - p.x; ext->last_drag_x = p.x; if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { From 3a315775927826ccea5e05c867db109d11aa4243 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 23:20:12 -0700 Subject: [PATCH 37/97] Add sesitivty setter --- src/lv_widgets/lv_rotary.c | 23 +++++++++++++++++++---- src/lv_widgets/lv_rotary.h | 14 ++++++++++++-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index b4e5142b8..0d596e000 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -107,6 +107,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->max_value = copy_ext->max_value; ext->dragging = copy_ext->dragging; ext->sym = copy_ext->sym; + ext->sensitivity = copy_ext->sensitivity; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); @@ -191,6 +192,20 @@ void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en) lv_obj_invalidate(rotary); } +/** + * Set the sesitivity of rotary knob increments + * position. + * @param rotary pointer to a rotary object + * @param sensitivity increment multiplier + */ +void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + ext->sensitivity = sensitivity; +} + /*===================== * Getter functions *====================*/ @@ -321,13 +336,13 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par ext->last_drag_x = p.x; if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff, LV_ANIM_ON); + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff, LV_ANIM_ON); + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } @@ -352,12 +367,12 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par char c = *((char *)param); if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + 1, LV_ANIM_ON); + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + ext->sensitivity, LV_ANIM_ON); res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - 1, LV_ANIM_ON); + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - ext->sensitivity, LV_ANIM_ON); res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 9b4b73985..3b7f718fc 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -67,9 +67,11 @@ typedef struct { int16_t cur_value; /*Current value of the rotary*/ int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ - uint16_t dragging :1; lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ - uint16_t sym :1; + uint16_t dragging :1; + uint16_t sym :1; + uint16_t sensitivity :1; + } lv_rotary_ext_t; /** Built-in styles of rotary*/ @@ -121,6 +123,14 @@ void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max); */ void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en); +/** + * Set the sesitivity of rotary knob increments + * position. + * @param rotary pointer to a rotary object + * @param sensitivity increment multiplier + */ +void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity); + /** * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. * @param arc pointer to an arc object From fe483e8e21f821ff9d897b1f4516c56ee4582202 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 23:26:22 -0700 Subject: [PATCH 38/97] Add sensitivity default explicit --- src/lv_widgets/lv_rotary.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 0d596e000..be3ea0b86 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -85,6 +85,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->min_value = 0; ext->max_value = 0; ext->dragging = false; + ext->sensitivity = 1; lv_style_list_init(&ext->style_knob); /*The signal and design functions are not copied so set them here*/ From dc873966e97dc6c9ecb9560476d3681244801b74 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 23:33:18 -0700 Subject: [PATCH 39/97] Make sensitivity an int --- src/lv_widgets/lv_rotary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 3b7f718fc..32e3d4c0e 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -67,10 +67,10 @@ typedef struct { int16_t cur_value; /*Current value of the rotary*/ int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ + nt16_t sensitivity; /*Increment multiplier of the rotary*/ lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ uint16_t dragging :1; uint16_t sym :1; - uint16_t sensitivity :1; } lv_rotary_ext_t; From 6836947e672d7c9d74b6c5054d16db3efa8d8ef4 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 23:33:50 -0700 Subject: [PATCH 40/97] typo --- src/lv_widgets/lv_rotary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 32e3d4c0e..65766812e 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -67,7 +67,7 @@ typedef struct { int16_t cur_value; /*Current value of the rotary*/ int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ - nt16_t sensitivity; /*Increment multiplier of the rotary*/ + int16_t sensitivity; /*Increment multiplier of the rotary*/ lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ uint16_t dragging :1; uint16_t sym :1; From 247b5b6f0c05637dcc38f95427f2023f98e9b044 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 23:43:40 -0700 Subject: [PATCH 41/97] Fix drag diff calc --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index be3ea0b86..7ac680304 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -332,7 +332,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_PRESSING) { lv_indev_get_point(param, &p); - lv_coord_t drag_x_diff = ext->last_drag_x - p.x; + lv_coord_t drag_x_diff = p.x - ext->last_drag_x; ext->last_drag_x = p.x; if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { From ad990994d08615f5835a791128682ba780026c89 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 23:54:25 -0700 Subject: [PATCH 42/97] Fix release drag hoping better checking for -1 last drag x --- src/lv_widgets/lv_rotary.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 7ac680304..668a6a40e 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -332,26 +332,31 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_PRESSING) { lv_indev_get_point(param, &p); - lv_coord_t drag_x_diff = p.x - ext->last_drag_x; - ext->last_drag_x = p.x; - if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { - ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; + if (ext->last_drag_x == -1) { + ext->last_drag_x = p.x; + } else { + lv_coord_t drag_x_diff = p.x - ext->last_drag_x; + ext->last_drag_x = p.x; + + if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { + if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { + ext->last_drag_x = p.x; + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } } } - } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; + ext->last_drag_x = -1; /** Reset drag diff calc */ #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ From 856368284e937c5302ce23410af76584f3d30684 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sat, 20 Jun 2020 23:58:03 -0700 Subject: [PATCH 43/97] Test sensitivity threshold for value jumping --- src/lv_widgets/lv_rotary.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 668a6a40e..7dc88d4cc 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -332,31 +332,31 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_PRESSING) { lv_indev_get_point(param, &p); + lv_coord_t drag_x_diff = p.x -ext->last_drag_x; + + if (abs(drag_x_diff) > abs(ext->sensitivity)) { + if (drag_x_diff > 0) drag_x_diff = ext->sensitivity; + else drag_x_diff = -ext->sensitivity; + } + ext->last_drag_x = p.x; - if (ext->last_drag_x == -1) { - ext->last_drag_x = p.x; - } else { - lv_coord_t drag_x_diff = p.x - ext->last_drag_x; - ext->last_drag_x = p.x; - - if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { - ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } + if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { + if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { + ext->last_drag_x = p.x; + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; } } + } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; - ext->last_drag_x = -1; /** Reset drag diff calc */ #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ From e1761d50a1a3ad066ce3d03644a082d9a25bd5cc Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 00:05:09 -0700 Subject: [PATCH 44/97] Test threshold for value jupming --- src/lv_widgets/lv_rotary.c | 11 +++++++---- src/lv_widgets/lv_rotary.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 7dc88d4cc..d6a3253ec 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -109,6 +109,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->dragging = copy_ext->dragging; ext->sym = copy_ext->sym; ext->sensitivity = copy_ext->sensitivity; + ext->threshold = copy_ext->threshold; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); @@ -173,6 +174,8 @@ void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max) if(ext->cur_value > max) { ext->cur_value = max; } + + ext->threshold = (abs(ext->min_value) + abs(ext->max_value)) / 10; lv_rotary_set_value(rotary, ext->cur_value, false); } @@ -334,12 +337,12 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_indev_get_point(param, &p); lv_coord_t drag_x_diff = p.x -ext->last_drag_x; - if (abs(drag_x_diff) > abs(ext->sensitivity)) { - if (drag_x_diff > 0) drag_x_diff = ext->sensitivity; - else drag_x_diff = -ext->sensitivity; + if (abs(drag_x_diff) > ext->threshold) { + if (drag_x_diff > 0) drag_x_diff = ext->threshold; + else drag_x_diff = -ext->threshold; } ext->last_drag_x = p.x; - + if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 65766812e..07dc308cd 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -68,6 +68,7 @@ typedef struct { int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ int16_t sensitivity; /*Increment multiplier of the rotary*/ + int16_t threshold; /*Increment threshold of the rotary*/ lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ uint16_t dragging :1; uint16_t sym :1; From 4bedc57b7d7237a86c6e768b78bedab0a3c5eb88 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 00:08:49 -0700 Subject: [PATCH 45/97] Add setter for threshold --- src/lv_widgets/lv_rotary.c | 17 +++++++++++++++-- src/lv_widgets/lv_rotary.h | 8 ++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index d6a3253ec..8b07a09bd 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -86,6 +86,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->max_value = 0; ext->dragging = false; ext->sensitivity = 1; + ext->threshold = 1; lv_style_list_init(&ext->style_knob); /*The signal and design functions are not copied so set them here*/ @@ -175,8 +176,6 @@ void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max) ext->cur_value = max; } - ext->threshold = (abs(ext->min_value) + abs(ext->max_value)) / 10; - lv_rotary_set_value(rotary, ext->cur_value, false); } @@ -210,6 +209,20 @@ void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity) ext->sensitivity = sensitivity; } +/** + * Set the threshold of rotary knob increments + * position. + * @param rotary pointer to a rotary object + * @param threshold increment threshold + */ +void lv_rotary_set_threshold(lv_obj_t * rotary, uint16_t threshold) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + ext->threshold = threshold; +} + /*===================== * Getter functions *====================*/ diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 07dc308cd..8f5e2e45f 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -132,6 +132,14 @@ void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en); */ void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity); +/** + * Set the threshold of rotary knob increments + * position. + * @param rotary pointer to a rotary object + * @param threshold increment threshold + */ +void lv_rotary_set_threshold(lv_obj_t * rotary, uint16_t threshold); + /** * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. * @param arc pointer to an arc object From d60a6cbc7614a5052d9e6b88c9f23bda9bdce0bc Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 00:26:20 -0700 Subject: [PATCH 46/97] Add reverse value mapping and arc tracking --- src/lv_widgets/lv_rotary.c | 46 +++++++++++++++++++++++++++++++------- src/lv_widgets/lv_rotary.h | 9 ++++++++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 8b07a09bd..599406d3a 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -84,9 +84,9 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->cur_value = 0; ext->min_value = 0; ext->max_value = 0; - ext->dragging = false; ext->sensitivity = 1; ext->threshold = 1; + ext->dragging = false; lv_style_list_init(&ext->style_knob); /*The signal and design functions are not copied so set them here*/ @@ -107,10 +107,11 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->cur_value = copy_ext->cur_value; ext->min_value = copy_ext->min_value; ext->max_value = copy_ext->max_value; - ext->dragging = copy_ext->dragging; - ext->sym = copy_ext->sym; ext->sensitivity = copy_ext->sensitivity; ext->threshold = copy_ext->threshold; + ext->dragging = copy_ext->dragging; + ext->sym = copy_ext->sym; + ext->reverse = copy_ext->reverse; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); @@ -146,11 +147,19 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim ext->cur_value = new_value; - lv_arc_set_end_angle( - rotary, - _lv_map(ext->cur_value, ext->min_value, ext->max_value, - ext->arc.arc_angle_start, 360 + ext->arc.bg_angle_end) - ); + if (ext->reverse) { + lv_arc_set_start_angle( + rotary, + _lv_map(ext->cur_value, ext->min_value, ext->max_value, + ext->arc.arc_angle_start, ext->arc.bg_angle_start) + ); + } else { + lv_arc_set_end_angle( + rotary, + _lv_map(ext->cur_value, ext->min_value, ext->max_value, + ext->arc.arc_angle_start, 360 + ext->arc.bg_angle_end) + ); + } } /** @@ -195,6 +204,27 @@ void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en) lv_obj_invalidate(rotary); } +/** + * Reverse rotary behavior. The indicator will grow from arc end instead of arc start. + * position. + * @param rotary pointer to a rotary object + * @param reverse true: enable disable reverse behavior; false: disable + */ +void lv_rotary_set_reverse(lv_obj_t * rotary, bool reverse) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + ext->reverse = reverse; + + uint16_t end = ext->arc.arc_angle_end; + + ext->arc.arc_angle_end = ext->arc.bg_angle_end; + ext->arc.arc_angle_start= end; + + lv_obj_invalidate(rotary); +} + /** * Set the sesitivity of rotary knob increments * position. diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 8f5e2e45f..bf96820fc 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -72,6 +72,7 @@ typedef struct { lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ uint16_t dragging :1; uint16_t sym :1; + uint16_t reverse :1; } lv_rotary_ext_t; @@ -124,6 +125,14 @@ void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max); */ void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en); +/** + * Reverse rotary behavior. The indicator will grow from arc end instead of arc start. + * position. + * @param rotary pointer to a rotary object + * @param reverse true: enable disable reverse behavior; false: disable + */ +void lv_rotary_set_reverse(lv_obj_t * rotary, bool reverse); + /** * Set the sesitivity of rotary knob increments * position. From 4ab8520bfbb3ca7c90fd38c32a5485ac18e4891a Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 00:29:03 -0700 Subject: [PATCH 47/97] Use lv math abs --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 599406d3a..f18694f2b 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -380,7 +380,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_indev_get_point(param, &p); lv_coord_t drag_x_diff = p.x -ext->last_drag_x; - if (abs(drag_x_diff) > ext->threshold) { + if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { if (drag_x_diff > 0) drag_x_diff = ext->threshold; else drag_x_diff = -ext->threshold; } From 6c014903721464ead6b21fa5bafd41a2275ffc01 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 00:34:08 -0700 Subject: [PATCH 48/97] Use value setter for reverse start angle setting --- src/lv_widgets/lv_rotary.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index f18694f2b..afcffe3d2 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -151,7 +151,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim lv_arc_set_start_angle( rotary, _lv_map(ext->cur_value, ext->min_value, ext->max_value, - ext->arc.arc_angle_start, ext->arc.bg_angle_start) + ext->arc.arc_angle_end, ext->arc.bg_angle_start) ); } else { lv_arc_set_end_angle( @@ -220,9 +220,8 @@ void lv_rotary_set_reverse(lv_obj_t * rotary, bool reverse) uint16_t end = ext->arc.arc_angle_end; ext->arc.arc_angle_end = ext->arc.bg_angle_end; - ext->arc.arc_angle_start= end; - - lv_obj_invalidate(rotary); + + lv_rotary_set_value(rotary, ext->cur_value, false); } /** From 0d6b8a86d483a5a46fbcc31c1e9f2e205023c9a5 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 00:36:39 -0700 Subject: [PATCH 49/97] Try reverse mapping --- src/lv_widgets/lv_rotary.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index afcffe3d2..f8cc7641e 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -151,7 +151,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim lv_arc_set_start_angle( rotary, _lv_map(ext->cur_value, ext->min_value, ext->max_value, - ext->arc.arc_angle_end, ext->arc.bg_angle_start) + 360 + ext->arc.bg_angle_end, ext->arc.bg_angle_start) ); } else { lv_arc_set_end_angle( @@ -215,10 +215,8 @@ void lv_rotary_set_reverse(lv_obj_t * rotary, bool reverse) LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + ext->reverse = reverse; - - uint16_t end = ext->arc.arc_angle_end; - ext->arc.arc_angle_end = ext->arc.bg_angle_end; lv_rotary_set_value(rotary, ext->cur_value, false); From 5359a762b8a47a66791b130e670c63abf98abd1f Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 10:59:41 -0700 Subject: [PATCH 50/97] Reverse min and max in mapping reverse --- src/lv_widgets/lv_rotary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index f8cc7641e..629ade3aa 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -150,8 +150,8 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim if (ext->reverse) { lv_arc_set_start_angle( rotary, - _lv_map(ext->cur_value, ext->min_value, ext->max_value, - 360 + ext->arc.bg_angle_end, ext->arc.bg_angle_start) + _lv_map(ext->cur_value, ext->max_value, ext->min_value, + ext->arc.arc_angle_start, 360 + ext->arc.bg_angle_end) ); } else { lv_arc_set_end_angle( From 19a1afbd89e258f8b4f38e2220466241cbe8c737 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 11:05:24 -0700 Subject: [PATCH 51/97] Fix reverse mapping --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 629ade3aa..fe459587f 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -151,7 +151,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim lv_arc_set_start_angle( rotary, _lv_map(ext->cur_value, ext->max_value, ext->min_value, - ext->arc.arc_angle_start, 360 + ext->arc.bg_angle_end) + 360 + ext->arc.bg_angle_end, ext->arc.bg_angle_start) ); } else { lv_arc_set_end_angle( From af7134269e3186f1fc32ce7d55caea706f8a7803 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 21 Jun 2020 11:15:48 -0700 Subject: [PATCH 52/97] Force set_value handling in reverse --- src/lv_widgets/lv_rotary.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index fe459587f..e57461669 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -215,11 +215,13 @@ void lv_rotary_set_reverse(lv_obj_t * rotary, bool reverse) LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - - ext->reverse = reverse; - ext->arc.arc_angle_end = ext->arc.bg_angle_end; + int16_t val = ext->cur_value; - lv_rotary_set_value(rotary, ext->cur_value, false); + ext->cur_value = -1; /** Force set_value handling*/ + ext->reverse = reverse; + + lv_rotary_set_end_angle(rotary, ext->arc.bg_angle_end); + lv_rotary_set_value(rotary, val, false); } /** From ba10671b2b553f6330b136d84779aefd939976d2 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Mon, 22 Jun 2020 21:50:21 -0700 Subject: [PATCH 53/97] Rotary types. Add symmetric value setter --- src/lv_widgets/lv_rotary.c | 134 ++++++++++++++++++++++++------------- src/lv_widgets/lv_rotary.h | 34 +++++----- 2 files changed, 101 insertions(+), 67 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index e57461669..b67c5f954 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -147,18 +147,43 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim ext->cur_value = new_value; - if (ext->reverse) { - lv_arc_set_start_angle( - rotary, - _lv_map(ext->cur_value, ext->max_value, ext->min_value, - 360 + ext->arc.bg_angle_end, ext->arc.bg_angle_start) - ); - } else { - lv_arc_set_end_angle( - rotary, - _lv_map(ext->cur_value, ext->min_value, ext->max_value, - ext->arc.arc_angle_start, 360 + ext->arc.bg_angle_end) - ); + switch(ext->type) { + case LV_ROTARY_TYPE_SYMMETRIC: + unint16_t bg_midpoint; + if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { + bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end + 360) / 2; + } else { + bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end) / 2; + } + + int16_t range_midpoint = (ext->min_value + ext->max_value) / 2; + if (ext->cur_value < range_midpoint) { + lv_arc_set_start_angle( + rotary, + _lv_map(ext->cur_value, ext->max_value, ext->min_value, + ext->arc.bg_angle_start, bg_midpoint) + ); + } else if (ext->cur_value > range_midpoint) { + lv_arc_set_start_angle( + rotary, + _lv_map(ext->cur_value, ext->max_value, ext->min_value, + ext->arc.bg_angle_start, bg_midpoint) + ); + } + break; + case LV_ROTARY_TYPE_REVERSE: + lv_arc_set_start_angle( + rotary, + _lv_map(ext->cur_value, ext->max_value, ext->min_value, + 360 + ext->arc.bg_angle_end, ext->arc.bg_angle_start) + ); + break; + default: /** LV_ROTARY_TYPE_NORMAL*/ + lv_arc_set_end_angle( + rotary, + _lv_map(ext->cur_value, ext->min_value, ext->max_value, + ext->arc.arc_angle_start, 360 + ext->arc.bg_angle_end) + ); } } @@ -188,42 +213,6 @@ void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max) lv_rotary_set_value(rotary, ext->cur_value, false); } -/** - * Make the rotary symmetric to zero. The indicator will grow from zero instead of the minimum - * position. - * @param rotary pointer to a rotary object - * @param en true: enable disable symmetric behavior; false: disable - */ -void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - ext->sym = en; - - lv_obj_invalidate(rotary); -} - -/** - * Reverse rotary behavior. The indicator will grow from arc end instead of arc start. - * position. - * @param rotary pointer to a rotary object - * @param reverse true: enable disable reverse behavior; false: disable - */ -void lv_rotary_set_reverse(lv_obj_t * rotary, bool reverse) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - int16_t val = ext->cur_value; - - ext->cur_value = -1; /** Force set_value handling*/ - ext->reverse = reverse; - - lv_rotary_set_end_angle(rotary, ext->arc.bg_angle_end); - lv_rotary_set_value(rotary, val, false); -} - /** * Set the sesitivity of rotary knob increments * position. @@ -252,6 +241,42 @@ void lv_rotary_set_threshold(lv_obj_t * rotary, uint16_t threshold) ext->threshold = threshold; } +/** + * Set the type of rotary. + * @param rotary pointer to rotary object + * @param type rotary type + */ +void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + int16_t val = ext->cur_value; + + ext->type = type; + ext->cur_value = -1; /** Force set_value handling*/ + + switch(ext->type) { + case LV_ROTARY_TYPE_SYMMETRIC: + unint16_t bg_midpoint; + if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { + bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end + 360) / 2; + } else { + bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end) / 2; + } + lv_rotary_set_start_angle(rotary, bg_midpoint); + lv_rotary_set_start_angle(rotary, bg_midpoint); + break; + case LV_ROTARY_TYPE_REVERSE: + lv_rotary_set_end_angle(rotary, ext->arc.bg_angle_end); + break; + default: /** LV_ROTARY_TYPE_NORMAL*/ + lv_rotary_set_start_angle(rotary, ext->arc.bg_angle_start); + } + + lv_rotary_set_value(rotary, val, false); +} + /*===================== * Getter functions *====================*/ @@ -308,6 +333,19 @@ bool lv_rotary_is_dragged(const lv_obj_t * rotary) return ext->dragging; } +/** + * Get whether the rotary is type or not. + * @param rotary pointer to a rotary object + * @return rotary type + */ +lv_rotary_type_t lv_rotary_get_type(const lv_obj_t * rotary) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + return ext->type; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index bf96820fc..a9b85d40a 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -41,7 +41,9 @@ extern "C" { **********************/ enum { - LV_ROTARY_TYPE_NORMAL + LV_ROTARY_TYPE_NORMAL, + LV_ROTARY_TYPE_SYMMETRIC, + LV_ROTARY_TYPE_REVERSE }; typedef uint8_t lv_rotary_type_t; @@ -71,8 +73,7 @@ typedef struct { int16_t threshold; /*Increment threshold of the rotary*/ lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ uint16_t dragging :1; - uint16_t sym :1; - uint16_t reverse :1; + uint16_t type :2; } lv_rotary_ext_t; @@ -117,14 +118,6 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim */ void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max); -/** - * Make the rotary symmetric to zero. The indicator will grow from zero instead of the minimum - * position. - * @param rotary pointer to a rotary object - * @param en true: enable disable symmetric behavior; false: disable - */ -void lv_rotary_set_symmetric(lv_obj_t * rotary, bool en); - /** * Reverse rotary behavior. The indicator will grow from arc end instead of arc start. * position. @@ -149,6 +142,13 @@ void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity); */ void lv_rotary_set_threshold(lv_obj_t * rotary, uint16_t threshold); +/** + * Set the type of rotary. + * @param rotary pointer to rotary object + * @param type rotary type + */ +void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type); + /** * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. * @param arc pointer to an arc object @@ -292,15 +292,11 @@ int16_t lv_rotary_get_max_value(const lv_obj_t * rotary); bool lv_rotary_is_dragged(const lv_obj_t * rotary); /** - * Get whether the rotary is symmetric or not. + * Get whether the rotary is type or not. * @param rotary pointer to a rotary object - * @return true: symmetric is enabled; false: disable + * @return rotary type */ -static inline bool lv_rotary_get_symmetric(lv_obj_t * rotary) -{ - lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - return ext->sym; -} +lv_rotary_type_t lv_rotary_get_type(const lv_obj_t * rotary); /** * Get the current state of the rotary @@ -308,7 +304,7 @@ static inline bool lv_rotary_get_symmetric(lv_obj_t * rotary) * @return the state of the rotary (from lv_rotary_state_t enum). * If the rotary is in disabled state `LV_ROTARY_STATE_DISABLED` will be ORed to the other rotary states. */ -static inline lv_btn_state_t lv_rotary_get_state(const lv_obj_t * rotary) { +static inline lv_rotary_state_t lv_rotary_get_state(const lv_obj_t * rotary) { return lv_btn_get_state(rotary); } From 1c071530adc7f509a463fa558bfdd670d058c93a Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Mon, 22 Jun 2020 21:54:03 -0700 Subject: [PATCH 54/97] Remove sym references --- src/lv_widgets/lv_rotary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index b67c5f954..b4d895d2b 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -87,6 +87,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->sensitivity = 1; ext->threshold = 1; ext->dragging = false; + ext->type = LV_ROTARY_TYPE_NORMAL; lv_style_list_init(&ext->style_knob); /*The signal and design functions are not copied so set them here*/ @@ -110,8 +111,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->sensitivity = copy_ext->sensitivity; ext->threshold = copy_ext->threshold; ext->dragging = copy_ext->dragging; - ext->sym = copy_ext->sym; - ext->reverse = copy_ext->reverse; + ext->type = copy_ext->type; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); From 9ede4ba7079dc795703a2f7dde6e27e3ddf3f974 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Mon, 22 Jun 2020 21:54:47 -0700 Subject: [PATCH 55/97] typo --- src/lv_widgets/lv_rotary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index b4d895d2b..09f1cdcce 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -149,7 +149,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim switch(ext->type) { case LV_ROTARY_TYPE_SYMMETRIC: - unint16_t bg_midpoint; + uint16_t bg_midpoint; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end + 360) / 2; } else { @@ -258,7 +258,7 @@ void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) switch(ext->type) { case LV_ROTARY_TYPE_SYMMETRIC: - unint16_t bg_midpoint; + uint16_t bg_midpoint; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end + 360) / 2; } else { From 46f7dff9e2faafb22dfb7f2282a9aa71cce8bd70 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Mon, 22 Jun 2020 21:56:31 -0700 Subject: [PATCH 56/97] Fix statement declaration --- src/lv_widgets/lv_rotary.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 09f1cdcce..4f5255cfb 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -147,16 +147,16 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim ext->cur_value = new_value; + uint16_t bg_midpoint, range_midpoint; switch(ext->type) { case LV_ROTARY_TYPE_SYMMETRIC: - uint16_t bg_midpoint; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end + 360) / 2; } else { bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end) / 2; } - int16_t range_midpoint = (ext->min_value + ext->max_value) / 2; + range_midpoint = (ext->min_value + ext->max_value) / 2; if (ext->cur_value < range_midpoint) { lv_arc_set_start_angle( rotary, @@ -256,9 +256,9 @@ void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) ext->type = type; ext->cur_value = -1; /** Force set_value handling*/ + uint16_t bg_midpoint; switch(ext->type) { case LV_ROTARY_TYPE_SYMMETRIC: - uint16_t bg_midpoint; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end + 360) / 2; } else { From f0cae0057483bfb2672f4ac3553c57ea1f885d8a Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Mon, 22 Jun 2020 22:47:01 -0700 Subject: [PATCH 57/97] Rearrange type call for clarity. Fix symmetric arc setters --- src/lv_widgets/lv_rotary.c | 97 ++++++++++++++++++-------------------- src/lv_widgets/lv_rotary.h | 30 ++++++------ 2 files changed, 61 insertions(+), 66 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 4f5255cfb..e79ff94ac 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -126,6 +126,40 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) * Setter functions *====================*/ +/** + * Set the type of rotary. + * @param rotary pointer to rotary object + * @param type rotary type + */ +void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) +{ + LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); + + lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); + int16_t val = ext->cur_value; + + ext->type = type; + ext->cur_value = -1; /** Force set_value handling*/ + + int16_t bg_end, bg_midpoint; + if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) bg_end = ext->arc.bg_angle_end + 360; + + switch(ext->type) { + case LV_ROTARY_TYPE_SYMMETRIC: + bg_midpoint = (ext->arc.bg_angle_start + bg_end) / 2; + lv_rotary_set_start_angle(rotary, bg_midpoint); + lv_rotary_set_end_angle(rotary, bg_midpoint); + break; + case LV_ROTARY_TYPE_REVERSE: + lv_rotary_set_end_angle(rotary, ext->arc.bg_angle_end); + break; + default: /** LV_ROTARY_TYPE_NORMAL*/ + lv_rotary_set_start_angle(rotary, ext->arc.bg_angle_start); + } + + lv_rotary_set_value(rotary, val, false); +} + /** * Set a new value on the rotary * @param rotary pointer to a rotary object @@ -144,30 +178,27 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim new_value = new_value < ext->min_value ? ext->min_value : new_value; if(ext->cur_value == new_value) return; - ext->cur_value = new_value; - uint16_t bg_midpoint, range_midpoint; + int16_t bg_end, bg_midpoint, range_midpoint; + if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) bg_end = ext->arc.bg_angle_end + 360; + switch(ext->type) { case LV_ROTARY_TYPE_SYMMETRIC: - if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { - bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end + 360) / 2; - } else { - bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end) / 2; - } - - range_midpoint = (ext->min_value + ext->max_value) / 2; + bg_midpoint = (ext->arc.bg_angle_start + bg_end) / 2; + range_midpoint = (int32_t)(ext->min_value + ext->max_value) / 2; + if (ext->cur_value < range_midpoint) { lv_arc_set_start_angle( rotary, - _lv_map(ext->cur_value, ext->max_value, ext->min_value, + _lv_map(ext->cur_value, ext->min_value, range_midpoint, ext->arc.bg_angle_start, bg_midpoint) ); - } else if (ext->cur_value > range_midpoint) { + } else { lv_arc_set_start_angle( rotary, - _lv_map(ext->cur_value, ext->max_value, ext->min_value, - ext->arc.bg_angle_start, bg_midpoint) + _lv_map(ext->cur_value, range_midpoint, ext->max_value, + bg_midpoint, bg_end) ); } break; @@ -175,14 +206,14 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim lv_arc_set_start_angle( rotary, _lv_map(ext->cur_value, ext->max_value, ext->min_value, - 360 + ext->arc.bg_angle_end, ext->arc.bg_angle_start) + bg_end, ext->arc.bg_angle_start) ); break; default: /** LV_ROTARY_TYPE_NORMAL*/ lv_arc_set_end_angle( rotary, _lv_map(ext->cur_value, ext->min_value, ext->max_value, - ext->arc.arc_angle_start, 360 + ext->arc.bg_angle_end) + ext->arc.bg_angle_start, bg_end) ); } } @@ -241,42 +272,6 @@ void lv_rotary_set_threshold(lv_obj_t * rotary, uint16_t threshold) ext->threshold = threshold; } -/** - * Set the type of rotary. - * @param rotary pointer to rotary object - * @param type rotary type - */ -void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - int16_t val = ext->cur_value; - - ext->type = type; - ext->cur_value = -1; /** Force set_value handling*/ - - uint16_t bg_midpoint; - switch(ext->type) { - case LV_ROTARY_TYPE_SYMMETRIC: - if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { - bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end + 360) / 2; - } else { - bg_midpoint = (ext->arc.bg_angle_start + ext->arc.bg_angle_end) / 2; - } - lv_rotary_set_start_angle(rotary, bg_midpoint); - lv_rotary_set_start_angle(rotary, bg_midpoint); - break; - case LV_ROTARY_TYPE_REVERSE: - lv_rotary_set_end_angle(rotary, ext->arc.bg_angle_end); - break; - default: /** LV_ROTARY_TYPE_NORMAL*/ - lv_rotary_set_start_angle(rotary, ext->arc.bg_angle_start); - } - - lv_rotary_set_value(rotary, val, false); -} - /*===================== * Getter functions *====================*/ diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index a9b85d40a..6a45f04ab 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -66,6 +66,7 @@ typedef struct { /*New data for this type*/ lv_style_list_t style_knob; /* Style of the knob */ lv_area_t knob_area; /* Area of the knob */ + uint16_t type :2; int16_t cur_value; /*Current value of the rotary*/ int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ @@ -73,7 +74,6 @@ typedef struct { int16_t threshold; /*Increment threshold of the rotary*/ lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ uint16_t dragging :1; - uint16_t type :2; } lv_rotary_ext_t; @@ -102,6 +102,13 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy); * Setter functions *====================*/ +/** + * Set the type of rotary. + * @param rotary pointer to rotary object + * @param type rotary type + */ +void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type); + /** * Set a new value on the rotary * @param rotary pointer to a rotary object @@ -142,13 +149,6 @@ void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity); */ void lv_rotary_set_threshold(lv_obj_t * rotary, uint16_t threshold); -/** - * Set the type of rotary. - * @param rotary pointer to rotary object - * @param type rotary type - */ -void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type); - /** * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. * @param arc pointer to an arc object @@ -263,6 +263,13 @@ static inline uint16_t lv_rotary_get_bg_angle_end(lv_obj_t * rotary) { return lv_arc_get_bg_angle_end(rotary); } +/** + * Get whether the rotary is type or not. + * @param rotary pointer to a rotary object + * @return rotary type + */ +lv_rotary_type_t lv_rotary_get_type(const lv_obj_t * rotary); + /** * Get the value of the of a rotary * @param rotary pointer to a rotary object @@ -291,13 +298,6 @@ int16_t lv_rotary_get_max_value(const lv_obj_t * rotary); */ bool lv_rotary_is_dragged(const lv_obj_t * rotary); -/** - * Get whether the rotary is type or not. - * @param rotary pointer to a rotary object - * @return rotary type - */ -lv_rotary_type_t lv_rotary_get_type(const lv_obj_t * rotary); - /** * Get the current state of the rotary * @param rotary pointer to a rotary object From 83d05f945f71c92d43a91b7b2f62e2d1ca0aba4f Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Mon, 22 Jun 2020 22:49:23 -0700 Subject: [PATCH 58/97] Fix bg_end init --- src/lv_widgets/lv_rotary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index e79ff94ac..5c1011e4a 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -141,7 +141,7 @@ void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) ext->type = type; ext->cur_value = -1; /** Force set_value handling*/ - int16_t bg_end, bg_midpoint; + int16_t bg_midpoint, bg_end = ext->arc.bg_angle_end; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) bg_end = ext->arc.bg_angle_end + 360; switch(ext->type) { @@ -180,7 +180,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim if(ext->cur_value == new_value) return; ext->cur_value = new_value; - int16_t bg_end, bg_midpoint, range_midpoint; + int16_t bg_midpoint, range_midpoint, bg_end = ext->arc.bg_angle_end; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) bg_end = ext->arc.bg_angle_end + 360; switch(ext->type) { From 0aeb49d28a1f3e8144df60b48060dc9de6d9df3b Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Mon, 22 Jun 2020 22:53:58 -0700 Subject: [PATCH 59/97] Fix Set sym end angle --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 5c1011e4a..0dfd0ef73 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -195,7 +195,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim ext->arc.bg_angle_start, bg_midpoint) ); } else { - lv_arc_set_start_angle( + lv_arc_set_end_angle( rotary, _lv_map(ext->cur_value, range_midpoint, ext->max_value, bg_midpoint, bg_end) From 663af3dfb32ef81bf7bc45d926721e8d48d31587 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Tue, 23 Jun 2020 12:54:06 -0700 Subject: [PATCH 60/97] Shift mapping math out of floating point --- src/lv_misc/lv_math.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index 7c467b5f1..9e8a91b80 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -239,12 +239,12 @@ int64_t _lv_pow(int64_t base, int8_t exp) * @param in min output range * @param out max output range */ -LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, float min_in, float max_in, float min, float max) +LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max) { - float slope = (max - min) / (max_in - min_in); - float bias = min - slope * min_in; + uint32_t slope = ((uint32_t)(max - min) * 1000) / (uint32_t)(max_in - min_in); /** times 1000 to avoid rounding errors*/ + uint32_t bias = min - (slope * min_in) / 1000; - return bias + slope * x; + return bias + (slope * x) / 1000; } /********************** From 5961800fe0a12855281a9a677c00aaf1a5ddba0d Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Tue, 23 Jun 2020 12:56:07 -0700 Subject: [PATCH 61/97] Fix map contract --- src/lv_misc/lv_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_misc/lv_math.h b/src/lv_misc/lv_math.h index aeb9e4d7a..0d72fb5af 100644 --- a/src/lv_misc/lv_math.h +++ b/src/lv_misc/lv_math.h @@ -120,7 +120,7 @@ int64_t _lv_pow(int64_t base, int8_t exp); * @param in min output range * @param out max output range */ -LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, float min_in, float max_in, float min, float max); +LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max); /********************** * MACROS From b414aa755d1e111407b343a962b9d4f0f9079aca Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Tue, 23 Jun 2020 13:33:25 -0700 Subject: [PATCH 62/97] int32 fix to mapping logic --- src/lv_misc/lv_math.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index 9e8a91b80..b2c914f2b 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -241,10 +241,10 @@ int64_t _lv_pow(int64_t base, int8_t exp) */ LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max) { - uint32_t slope = ((uint32_t)(max - min) * 1000) / (uint32_t)(max_in - min_in); /** times 1000 to avoid rounding errors*/ - uint32_t bias = min - (slope * min_in) / 1000; + int32_t slope = ((int32_t)(max - min) * 10000) / (int32_t)(max_in - min_in); /** times 10000 to avoid rounding errors*/ + int32_t bias = (int32_t)(min * 10000) - slope * min_in; - return bias + (slope * x) / 1000; + return (bias + slope * x) / 10000; } /********************** From f75428e52b5b4af13b21967a93331a53557262b2 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Tue, 23 Jun 2020 23:06:56 -0700 Subject: [PATCH 63/97] Match rotary_bg line width to indicator width --- src/lv_themes/lv_theme_material.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index edb106c6f..7ba501949 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -805,7 +805,7 @@ static void rotary_init(void) lv_style_set_pad_inner(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); lv_style_set_border_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(2)); lv_style_set_line_color(&styles->rotary_bg, LV_STATE_DEFAULT, COLOR_BG_SEC); - lv_style_set_line_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(2)); + lv_style_set_line_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(8)); lv_style_set_line_rounded(&styles->rotary_bg, LV_STATE_DEFAULT, true); style_init_reset(&styles->rotary_indic); From 92ecff3fc0a41ea236c6168a39561085302b15b4 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 21:18:42 -0700 Subject: [PATCH 64/97] WIP: dragging on ring only using lv_atan --- src/lv_widgets/lv_rotary.c | 70 +++++++++++++++++++++++++------------- src/lv_widgets/lv_rotary.h | 2 +- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 0dfd0ef73..0b188bc59 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -404,38 +404,63 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(sign == LV_SIGNAL_PRESSED) { lv_indev_get_point(param, &p); - ext->last_drag_x = p.x; + lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); + res = double_click_reset(cpicker); + if(res != LV_RES_OK) return res; ext->dragging = true; - } else if(sign == LV_SIGNAL_PRESSING) { - lv_indev_get_point(param, &p); - lv_coord_t drag_x_diff = p.x -ext->last_drag_x; + lv_indev_t * indev = lv_indev_get_act(); + if(indev == NULL) return res; - if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { - if (drag_x_diff > 0) drag_x_diff = ext->threshold; - else drag_x_diff = -ext->threshold; + lv_indev_type_t indev_type = lv_indev_get_type(indev); + lv_point_t p; + if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) { + p.x = rotary->coords.x1 + lv_obj_get_width(rotary) / 2; + p.y = rotary->coords.y1 + lv_obj_get_height(rotary) / 2; } - ext->last_drag_x = p.x; - - if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { - ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } + else { + lv_indev_get_point(indev, &p); } + if((LV_MATH_ABS(p.x - ext->last_press_point.x) > indev->driver.drag_limit / 2) || + (LV_MATH_ABS(p.y - ext->last_press_point.y) > indev->driver.drag_limit / 2)) { + ext->last_change_time = lv_tick_get(); + ext->last_press_point.x = p.x; + ext->last_press_point.y = p.y; + } + + /*Make point 0 relative to the rotary*/ + p.x -= rotary->coords.x1; + p.y -= rotary->coords.y1; + + /*Ignore pressing in the inner area*/ + uint16_t w = lv_obj_get_width(rotary); + int16_t angle; + lv_coord_t r_in = lv_area_get_width(ext->knob_area) / 2; + + p.x -= r_in; + p.y -= r_in; + bool on_ring = true; + if(p.x * p.x + p.y * p.y < r_in * r_in) { + return res; /*Set the angle only if pressed on the ring*/ + } + angle = _lv_atan2(p.x, p.y) % 360; + + int16_t bg_end = ext->arc.bg_angle_end; + if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { + bg_end = ext->arc.bg_angle_end + 360; + if (angle < ext->arc.bg_angle_start) angle += 360; + } + + lv_rotary_set_value( + rotary, + _lv_map(angle, ext->arc.bg_angle_start, bg_end, + ext->min_value, ext->max_value) + ); } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; - #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ lv_group_t * g = lv_obj_get_group(rotary); @@ -445,7 +470,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(editing) lv_group_set_editing(g, false); } #endif - } else if(sign == LV_SIGNAL_CONTROL) { char c = *((char *)param); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 6a45f04ab..1a8972a2b 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -72,7 +72,7 @@ typedef struct { int16_t max_value; /*Maximum value of the rotary*/ int16_t sensitivity; /*Increment multiplier of the rotary*/ int16_t threshold; /*Increment threshold of the rotary*/ - lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ + lv_point_t last_press_point; /*Last drag x coordintate of the rotary*/ uint16_t dragging :1; } lv_rotary_ext_t; From 2d4c709a88ddef3c825779dbc5c5a14e645f8dbb Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 21:22:37 -0700 Subject: [PATCH 65/97] Get area width using pointer --- src/lv_widgets/lv_rotary.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 0b188bc59..9fc0fa1f0 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -435,9 +435,8 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par p.y -= rotary->coords.y1; /*Ignore pressing in the inner area*/ - uint16_t w = lv_obj_get_width(rotary); int16_t angle; - lv_coord_t r_in = lv_area_get_width(ext->knob_area) / 2; + lv_coord_t r_in = lv_area_get_width(&ext->knob_area) / 2; p.x -= r_in; p.y -= r_in; @@ -456,7 +455,8 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_rotary_set_value( rotary, _lv_map(angle, ext->arc.bg_angle_start, bg_end, - ext->min_value, ext->max_value) + ext->min_value, ext->max_value), + LV_ANIM_OFF ); } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { From 9e3d8c90908146534cd9f5758561b7b5eb3afb43 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 21:23:14 -0700 Subject: [PATCH 66/97] Remove undeclared --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 9fc0fa1f0..f55151304 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -405,7 +405,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_indev_get_point(param, &p); lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); - res = double_click_reset(cpicker); + res = double_click_reset(rotary); if(res != LV_RES_OK) return res; ext->dragging = true; } From 70a22875684bd13e3e19180e862ab09b6c6594db Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 21:24:19 -0700 Subject: [PATCH 67/97] Remove undeclared --- src/lv_widgets/lv_rotary.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index f55151304..02d28729d 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -425,7 +425,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if((LV_MATH_ABS(p.x - ext->last_press_point.x) > indev->driver.drag_limit / 2) || (LV_MATH_ABS(p.y - ext->last_press_point.y) > indev->driver.drag_limit / 2)) { - ext->last_change_time = lv_tick_get(); ext->last_press_point.x = p.x; ext->last_press_point.y = p.y; } From a73b3166813a9b967d151ec805956a2196d11b76 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 21:27:18 -0700 Subject: [PATCH 68/97] Remove undeclared --- src/lv_widgets/lv_rotary.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 02d28729d..3fcffdada 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -403,10 +403,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(sign == LV_SIGNAL_PRESSED) { lv_indev_get_point(param, &p); - lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); - res = double_click_reset(rotary); - if(res != LV_RES_OK) return res; ext->dragging = true; } else if(sign == LV_SIGNAL_PRESSING) { From 6d07effbc32e846aadb96238922929e46f1f9672 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 21:39:19 -0700 Subject: [PATCH 69/97] Revert arc tracking --- src/lv_widgets/lv_rotary.c | 68 ++++++++++++++------------------------ src/lv_widgets/lv_rotary.h | 2 +- 2 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 3fcffdada..0dfd0ef73 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -403,60 +403,39 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(sign == LV_SIGNAL_PRESSED) { lv_indev_get_point(param, &p); - lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); + + ext->last_drag_x = p.x; ext->dragging = true; + } else if(sign == LV_SIGNAL_PRESSING) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev == NULL) return res; + lv_indev_get_point(param, &p); + lv_coord_t drag_x_diff = p.x -ext->last_drag_x; - lv_indev_type_t indev_type = lv_indev_get_type(indev); - lv_point_t p; - if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) { - p.x = rotary->coords.x1 + lv_obj_get_width(rotary) / 2; - p.y = rotary->coords.y1 + lv_obj_get_height(rotary) / 2; + if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { + if (drag_x_diff > 0) drag_x_diff = ext->threshold; + else drag_x_diff = -ext->threshold; } - else { - lv_indev_get_point(indev, &p); + ext->last_drag_x = p.x; + + if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { + if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { + ext->last_drag_x = p.x; + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } } - if((LV_MATH_ABS(p.x - ext->last_press_point.x) > indev->driver.drag_limit / 2) || - (LV_MATH_ABS(p.y - ext->last_press_point.y) > indev->driver.drag_limit / 2)) { - ext->last_press_point.x = p.x; - ext->last_press_point.y = p.y; - } - - /*Make point 0 relative to the rotary*/ - p.x -= rotary->coords.x1; - p.y -= rotary->coords.y1; - - /*Ignore pressing in the inner area*/ - int16_t angle; - lv_coord_t r_in = lv_area_get_width(&ext->knob_area) / 2; - - p.x -= r_in; - p.y -= r_in; - bool on_ring = true; - if(p.x * p.x + p.y * p.y < r_in * r_in) { - return res; /*Set the angle only if pressed on the ring*/ - } - angle = _lv_atan2(p.x, p.y) % 360; - - int16_t bg_end = ext->arc.bg_angle_end; - if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { - bg_end = ext->arc.bg_angle_end + 360; - if (angle < ext->arc.bg_angle_start) angle += 360; - } - - lv_rotary_set_value( - rotary, - _lv_map(angle, ext->arc.bg_angle_start, bg_end, - ext->min_value, ext->max_value), - LV_ANIM_OFF - ); } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; + #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ lv_group_t * g = lv_obj_get_group(rotary); @@ -466,6 +445,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(editing) lv_group_set_editing(g, false); } #endif + } else if(sign == LV_SIGNAL_CONTROL) { char c = *((char *)param); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 1a8972a2b..6a45f04ab 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -72,7 +72,7 @@ typedef struct { int16_t max_value; /*Maximum value of the rotary*/ int16_t sensitivity; /*Increment multiplier of the rotary*/ int16_t threshold; /*Increment threshold of the rotary*/ - lv_point_t last_press_point; /*Last drag x coordintate of the rotary*/ + lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ uint16_t dragging :1; } lv_rotary_ext_t; From f836e908697b72c64c769ed4b8e32db3f062ced5 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 22:40:03 -0700 Subject: [PATCH 70/97] Account for indev drag limit --- src/lv_widgets/lv_rotary.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 0dfd0ef73..5c37a38f3 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -409,6 +409,9 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_PRESSING) { + lv_indev_t * indev = lv_indev_get_act(); + if(indev == NULL) return res; + lv_indev_get_point(param, &p); lv_coord_t drag_x_diff = p.x -ext->last_drag_x; @@ -416,22 +419,23 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if (drag_x_diff > 0) drag_x_diff = ext->threshold; else drag_x_diff = -ext->threshold; } - ext->last_drag_x = p.x; + if (LV_MATH_ABS(drag_x_diff) > indev->driver.drag_limit) { + ext->last_drag_x = p.x; - if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { - ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; + if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { + if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { + ext->last_drag_x = p.x; + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } } } - } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; From 7ce9a969c8fb8ea626a297099084584d4cfbeb23 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 22:43:54 -0700 Subject: [PATCH 71/97] Rever drag limit integration as it makes rotary control too granular --- src/lv_widgets/lv_rotary.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 5c37a38f3..233f5d134 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -409,9 +409,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_PRESSING) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev == NULL) return res; - lv_indev_get_point(param, &p); lv_coord_t drag_x_diff = p.x -ext->last_drag_x; @@ -419,21 +416,19 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if (drag_x_diff > 0) drag_x_diff = ext->threshold; else drag_x_diff = -ext->threshold; } - if (LV_MATH_ABS(drag_x_diff) > indev->driver.drag_limit) { - ext->last_drag_x = p.x; + ext->last_drag_x = p.x; - if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { - ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } + if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { + if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { + ext->last_drag_x = p.x; + lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; } } } From 8bcbceef08b28bae3bcda032551e7180d3a49aa3 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Thu, 25 Jun 2020 23:05:48 -0700 Subject: [PATCH 72/97] Send event on if the value really does change --- src/lv_widgets/lv_rotary.c | 35 ++++++++++++++++++++--------------- src/lv_widgets/lv_rotary.h | 3 ++- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 233f5d134..613b34708 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -166,18 +166,18 @@ void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) * @param value new value * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately */ -void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim) +bool lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim) { LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - if(ext->cur_value == value) return; + if(ext->cur_value == value) return false; int16_t new_value; new_value = value > ext->max_value ? ext->max_value : value; new_value = new_value < ext->min_value ? ext->min_value : new_value; - if(ext->cur_value == new_value) return; + if(ext->cur_value == new_value) return false; ext->cur_value = new_value; int16_t bg_midpoint, range_midpoint, bg_end = ext->arc.bg_angle_end; @@ -216,6 +216,7 @@ void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim ext->arc.bg_angle_start, bg_end) ); } + return true; } /** @@ -420,15 +421,17 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; + if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON)) { + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } } else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { ext->last_drag_x = p.x; - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; + if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON)) { + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } } } } @@ -450,14 +453,16 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par char c = *((char *)param); if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; + if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + ext->sensitivity, LV_ANIM_ON)) { + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } } else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - ext->sensitivity, LV_ANIM_ON); - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; + if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - ext->sensitivity, LV_ANIM_ON)) { + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } } } else if(sign == LV_SIGNAL_CLEANUP) { diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 6a45f04ab..83576c4e7 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -114,8 +114,9 @@ void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type); * @param rotary pointer to a rotary object * @param value new value * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + * @return true if value changed, otw false */ -void lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim); +bool lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim); /** * Set minimum and the maximum values of a rotary From 4011d546684f09096e96d4d5022d569131d8764f Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 08:40:30 -0700 Subject: [PATCH 73/97] Use the max x and y drag diff to control drag --- src/lv_widgets/lv_rotary.c | 26 ++++++++++++++------------ src/lv_widgets/lv_rotary.h | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 613b34708..2cc8ac7f2 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -403,32 +403,34 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_point_t p; if(sign == LV_SIGNAL_PRESSED) { - lv_indev_get_point(param, &p); - - ext->last_drag_x = p.x; + lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); ext->dragging = true; - } else if(sign == LV_SIGNAL_PRESSING) { lv_indev_get_point(param, &p); - lv_coord_t drag_x_diff = p.x -ext->last_drag_x; + lv_coord_t drag_diff; + lv_coord_t drag_x_diff = p.x -ext->last_press_point.x; + lv_coord_t drag_y_diff = p.y -ext->last_press_point.y; - if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { - if (drag_x_diff > 0) drag_x_diff = ext->threshold; - else drag_x_diff = -ext->threshold; + if (LV_MATH_ABS(drag_x_diff) > LV_MATH_ABS(drag_y_diff)) drag_diff = drag_x_diff; + else drag_diff = drag_y_diff; + + if (LV_MATH_ABS(drag_diff) > ext->threshold) { + if (drag_diff > 0) drag_diff = ext->threshold; + else drag_diff = -ext->threshold; } ext->last_drag_x = p.x; if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - if (drag_x_diff > 0 && p.x < ext->knob_area.x2) { - if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON)) { + if (drag_diff > 0 && p.x < ext->knob_area.x2) { + if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } } - else if (drag_x_diff < 0 && p.x > ext->knob_area.x1) { + else if (drag_diff < 0 && p.x > ext->knob_area.x1) { ext->last_drag_x = p.x; - if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_x_diff * ext->sensitivity, LV_ANIM_ON)) { + if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 83576c4e7..426af0307 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -72,7 +72,7 @@ typedef struct { int16_t max_value; /*Maximum value of the rotary*/ int16_t sensitivity; /*Increment multiplier of the rotary*/ int16_t threshold; /*Increment threshold of the rotary*/ - lv_coord_t last_drag_x; /*Last drag x coordintate of the rotary*/ + lv_point_t last_press_point; /*Last drag point of the rotary*/ uint16_t dragging :1; } lv_rotary_ext_t; From 7de60867ef25baff809fda1c5afc772045be53a4 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 08:45:41 -0700 Subject: [PATCH 74/97] Set last drag point based on diffs --- src/lv_widgets/lv_rotary.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 2cc8ac7f2..a06749cd0 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -412,15 +412,20 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_coord_t drag_x_diff = p.x -ext->last_press_point.x; lv_coord_t drag_y_diff = p.y -ext->last_press_point.y; + if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { + if (drag_x_diff > 0) drag_x_diff = ext->threshold; + else drag_x_diff = -ext->threshold; + } + if (LV_MATH_ABS(drag_y_diff) > ext->threshold) { + if (drag_y_diff > 0) drag_x_diff = ext->threshold; + else drag_y_diff = -ext->threshold; + } + ext->last_press_point.x = ext->last_press_point.x + drag_x_diff; + ext->last_press_point.y = ext->last_press_point.y + drag_y_diff; + if (LV_MATH_ABS(drag_x_diff) > LV_MATH_ABS(drag_y_diff)) drag_diff = drag_x_diff; else drag_diff = drag_y_diff; - if (LV_MATH_ABS(drag_diff) > ext->threshold) { - if (drag_diff > 0) drag_diff = ext->threshold; - else drag_diff = -ext->threshold; - } - ext->last_drag_x = p.x; - if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { if (drag_diff > 0 && p.x < ext->knob_area.x2) { if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { From ec4cc14bf97dd9f67b13dd78a17bebe45a355963 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 08:46:56 -0700 Subject: [PATCH 75/97] Remove unsec x setter --- src/lv_widgets/lv_rotary.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index a06749cd0..53480ac39 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -434,7 +434,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } } else if (drag_diff < 0 && p.x > ext->knob_area.x1) { - ext->last_drag_x = p.x; if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; From 849d3d32555f5a4c21e08374589097e89ed89b47 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 08:48:12 -0700 Subject: [PATCH 76/97] Use point as last point --- src/lv_widgets/lv_rotary.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 53480ac39..33a932377 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -420,8 +420,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if (drag_y_diff > 0) drag_x_diff = ext->threshold; else drag_y_diff = -ext->threshold; } - ext->last_press_point.x = ext->last_press_point.x + drag_x_diff; - ext->last_press_point.y = ext->last_press_point.y + drag_y_diff; + ext->last_press_point = p; if (LV_MATH_ABS(drag_x_diff) > LV_MATH_ABS(drag_y_diff)) drag_diff = drag_x_diff; else drag_diff = drag_y_diff; From c36f73131638f091860b5015d7e273f327bb7e00 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 08:50:24 -0700 Subject: [PATCH 77/97] Only drag in one dimension because its too jumpy --- src/lv_widgets/lv_rotary.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 33a932377..149a41064 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -410,21 +410,14 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_indev_get_point(param, &p); lv_coord_t drag_diff; lv_coord_t drag_x_diff = p.x -ext->last_press_point.x; - lv_coord_t drag_y_diff = p.y -ext->last_press_point.y; if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { if (drag_x_diff > 0) drag_x_diff = ext->threshold; else drag_x_diff = -ext->threshold; } - if (LV_MATH_ABS(drag_y_diff) > ext->threshold) { - if (drag_y_diff > 0) drag_x_diff = ext->threshold; - else drag_y_diff = -ext->threshold; - } + drag_diff = drag_x_diff; ext->last_press_point = p; - if (LV_MATH_ABS(drag_x_diff) > LV_MATH_ABS(drag_y_diff)) drag_diff = drag_x_diff; - else drag_diff = drag_y_diff; - if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { if (drag_diff > 0 && p.x < ext->knob_area.x2) { if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { From 7e4b8aa49b5acb9f620684e79941dd1314116951 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 09:46:55 -0700 Subject: [PATCH 78/97] Second attempt arc drag --- src/lv_widgets/lv_rotary.c | 100 +++++++++++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 21 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 149a41064..61b5996c6 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -98,7 +98,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) if(copy == NULL) { lv_obj_set_click(rotary, true); lv_obj_add_protect(rotary, LV_PROTECT_PRESS_LOST); - lv_obj_set_ext_click_area(rotary, 0, 0, LV_DPI / 10, LV_DPI / 10); + lv_theme_apply(rotary, LV_THEME_ROTARY); } @@ -407,31 +407,88 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par ext->dragging = true; } else if(sign == LV_SIGNAL_PRESSING) { - lv_indev_get_point(param, &p); - lv_coord_t drag_diff; - lv_coord_t drag_x_diff = p.x -ext->last_press_point.x; + // lv_indev_get_point(param, &p); + // lv_coord_t drag_diff; + // lv_coord_t drag_x_diff = p.x -ext->last_press_point.x; + + // if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { + // if (drag_x_diff > 0) drag_x_diff = ext->threshold; + // else drag_x_diff = -ext->threshold; + // } + // drag_diff = drag_x_diff; + // ext->last_press_point = p; + + // if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { + // if (drag_diff > 0 && p.x < ext->knob_area.x2) { + // if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { + // res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + // if(res != LV_RES_OK) return res; + // } + // } + // else if (drag_diff < 0 && p.x > ext->knob_area.x1) { + // if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { + // res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + // if(res != LV_RES_OK) return res; + // } + // } + // } + + lv_indev_t * indev = lv_indev_get_act(); + if(indev == NULL) return res; + + lv_indev_type_t indev_type = lv_indev_get_type(indev); + lv_point_t p; + if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) { + p.x = rotary->coords.x1 + lv_obj_get_width(rotary) / 2; + p.y = rotary->coords.y1 + lv_obj_get_height(rotary) / 2; + } + else { + lv_indev_get_point(indev, &p); + } + + lv_coord_t drag_x_diff = p.x - ext->last_press_point.x; + lv_coord_t drag_y_diff = p.y - ext->last_press_point.y; if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { - if (drag_x_diff > 0) drag_x_diff = ext->threshold; - else drag_x_diff = -ext->threshold; + if (drag_x_diff > 0) p.x = ext->last_press_point.x + ext->threshold; + else p.x = ext->last_press_point.x - ext->threshold; + } + if (LV_MATH_ABS(drag_y_diff) > ext->threshold) { + if (drag_y_diff > 0) p.y = ext->last_press_point.y + ext->threshold; + else p.y = ext->last_press_point.y - ext->threshold; } - drag_diff = drag_x_diff; - ext->last_press_point = p; - if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - if (drag_diff > 0 && p.x < ext->knob_area.x2) { - if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - else if (drag_diff < 0 && p.x > ext->knob_area.x1) { - if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } + ext->last_press_point.x = p.x; + ext->last_press_point.y = p.y; + + /*Make point 0 relative to the rotary*/ + p.x -= rotary->coords.x1; + p.y -= rotary->coords.y1; + + /*Ignore pressing in the inner area*/ + int16_t angle; + lv_coord_t r_in = lv_area_get_width(&ext->knob_area) / 2; + + p.x -= r_in; + p.y -= r_in; + bool on_ring = true; + if(p.x * p.x + p.y * p.y < r_in * r_in) { + return res; /*Set the angle only if pressed on the ring*/ } + angle = _lv_atan2(p.x, p.y) % 360; + + int16_t bg_end = ext->arc.bg_angle_end; + if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { + bg_end = ext->arc.bg_angle_end + 360; + if (angle < ext->arc.bg_angle_start) angle += 360; + } + + lv_rotary_set_value( + rotary, + _lv_map(angle, ext->arc.bg_angle_start, bg_end, + ext->min_value, ext->max_value), + LV_ANIM_OFF + ); } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; @@ -522,6 +579,7 @@ static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); } + lv_obj_set_ext_click_area(rotary, knob_area.x1, knob_area.x2, knob_area.y1, knob_area.y2); lv_area_copy(&ext->knob_area, &knob_area); } From d271fd6108196e517cd91bef6f2e8c6892b691c9 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 12:35:41 -0700 Subject: [PATCH 79/97] Adjust click area extension --- src/lv_widgets/lv_rotary.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 61b5996c6..bce1754fa 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -98,7 +98,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) if(copy == NULL) { lv_obj_set_click(rotary, true); lv_obj_add_protect(rotary, LV_PROTECT_PRESS_LOST); - + lv_obj_set_ext_click_area(rotary, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10); lv_theme_apply(rotary, LV_THEME_ROTARY); } @@ -579,7 +579,6 @@ static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); } - lv_obj_set_ext_click_area(rotary, knob_area.x1, knob_area.x2, knob_area.y1, knob_area.y2); lv_area_copy(&ext->knob_area, &knob_area); } From 200c1e788fc3d35370b4b7343e3ab6196cd8e004 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 16:54:36 -0700 Subject: [PATCH 80/97] Second pass at angle based drag. Working with proper threshold setting with knowledge of rotary range. --- src/lv_widgets/lv_rotary.c | 56 ++++++++++++-------------------------- src/lv_widgets/lv_rotary.h | 7 +++-- 2 files changed, 21 insertions(+), 42 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index bce1754fa..f64ab63e7 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -85,7 +85,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->min_value = 0; ext->max_value = 0; ext->sensitivity = 1; - ext->threshold = 1; + ext->threshold = 10; ext->dragging = false; ext->type = LV_ROTARY_TYPE_NORMAL; lv_style_list_init(&ext->style_knob); @@ -194,7 +194,9 @@ bool lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim _lv_map(ext->cur_value, ext->min_value, range_midpoint, ext->arc.bg_angle_start, bg_midpoint) ); + lv_arc_set_end_angle(rotary, bg_midpoint); } else { + lv_arc_set_start_angle(rotary, bg_midpoint); lv_arc_set_end_angle( rotary, _lv_map(ext->cur_value, range_midpoint, ext->max_value, @@ -407,32 +409,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par ext->dragging = true; } else if(sign == LV_SIGNAL_PRESSING) { - // lv_indev_get_point(param, &p); - // lv_coord_t drag_diff; - // lv_coord_t drag_x_diff = p.x -ext->last_press_point.x; - - // if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { - // if (drag_x_diff > 0) drag_x_diff = ext->threshold; - // else drag_x_diff = -ext->threshold; - // } - // drag_diff = drag_x_diff; - // ext->last_press_point = p; - - // if (ext->knob_area.y1 < p.y && p.y < ext->knob_area.y2) { - // if (drag_diff > 0 && p.x < ext->knob_area.x2) { - // if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { - // res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - // if(res != LV_RES_OK) return res; - // } - // } - // else if (drag_diff < 0 && p.x > ext->knob_area.x1) { - // if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + drag_diff * ext->sensitivity, LV_ANIM_ON)) { - // res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - // if(res != LV_RES_OK) return res; - // } - // } - // } - lv_indev_t * indev = lv_indev_get_act(); if(indev == NULL) return res; @@ -471,24 +447,26 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par p.x -= r_in; p.y -= r_in; - bool on_ring = true; if(p.x * p.x + p.y * p.y < r_in * r_in) { return res; /*Set the angle only if pressed on the ring*/ } - angle = _lv_atan2(p.x, p.y) % 360; - - int16_t bg_end = ext->arc.bg_angle_end; + + int16_t bg_midpoint, bg_zero, bg_end = ext->arc.bg_angle_end; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { bg_end = ext->arc.bg_angle_end + 360; - if (angle < ext->arc.bg_angle_start) angle += 360; - } + } + bg_zero = (((ext->arc.bg_angle_start + bg_end) / 2) + 180) % 360; - lv_rotary_set_value( - rotary, - _lv_map(angle, ext->arc.bg_angle_start, bg_end, - ext->min_value, ext->max_value), - LV_ANIM_OFF - ); + angle = (_lv_atan2(p.x, p.y) + bg_zero) % 360; + if (bg_end > 360 && angle < ext->arc.bg_angle_start) angle += 360; + + int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->max_value, ext->min_value); + if (LV_MATH_ABS(ext->cur_value - new_value) < ext->threshold) { + if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + } } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { ext->dragging = false; diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 426af0307..32c0c87b9 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -70,9 +70,10 @@ typedef struct { int16_t cur_value; /*Current value of the rotary*/ int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ - int16_t sensitivity; /*Increment multiplier of the rotary*/ - int16_t threshold; /*Increment threshold of the rotary*/ - lv_point_t last_press_point; /*Last drag point of the rotary*/ + int16_t sensitivity; /*Control signal increment multiplier of the rotary*/ + int16_t threshold; /*Drag increment threshold of the rotary*/ + lv_point_t last_press_point; /*Last press point of the rotary*/ + uint16_t last_press_angle; /*Last press angle of the rotary*/ uint16_t dragging :1; } lv_rotary_ext_t; From 3af55796d9936910fd04f288205ef73267fe73ba Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Fri, 26 Jun 2020 19:39:10 -0700 Subject: [PATCH 81/97] Remove uneeded point manupulaton --- src/lv_widgets/lv_rotary.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index f64ab63e7..3b2d2241b 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -402,7 +402,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); - lv_point_t p; if(sign == LV_SIGNAL_PRESSED) { lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); @@ -422,18 +421,6 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_indev_get_point(indev, &p); } - lv_coord_t drag_x_diff = p.x - ext->last_press_point.x; - lv_coord_t drag_y_diff = p.y - ext->last_press_point.y; - - if (LV_MATH_ABS(drag_x_diff) > ext->threshold) { - if (drag_x_diff > 0) p.x = ext->last_press_point.x + ext->threshold; - else p.x = ext->last_press_point.x - ext->threshold; - } - if (LV_MATH_ABS(drag_y_diff) > ext->threshold) { - if (drag_y_diff > 0) p.y = ext->last_press_point.y + ext->threshold; - else p.y = ext->last_press_point.y - ext->threshold; - } - ext->last_press_point.x = p.x; ext->last_press_point.y = p.y; @@ -451,7 +438,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par return res; /*Set the angle only if pressed on the ring*/ } - int16_t bg_midpoint, bg_zero, bg_end = ext->arc.bg_angle_end; + int16_t bg_zero, bg_end = ext->arc.bg_angle_end; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { bg_end = ext->arc.bg_angle_end + 360; } From 3aa35a77cbdcb89529a1cb2dc4f51f18c8e99274 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 28 Jun 2020 22:03:20 +0200 Subject: [PATCH 82/97] rotary: minor fixes on dragging --- src/lv_misc/lv_math.c | 26 +++++++++++----- src/lv_misc/lv_math.h | 9 +++--- src/lv_widgets/lv_rotary.c | 63 ++++++++++++++++++-------------------- src/lv_widgets/lv_rotary.h | 3 -- 4 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index b2c914f2b..b0ecfaad7 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -232,19 +232,29 @@ int64_t _lv_pow(int64_t base, int8_t exp) } /** - * Get the mapped of a number given an imput and output range + * Get the mapped of a number given an input and output range * @param x integer which mapped value should be calculated * @param min_in min input range * @param max_in max input range - * @param in min output range - * @param out max output range + * @param min_out max output range + * @param max_out max output range + * @return the mapped number */ -LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max) +int16_t _lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out) { - int32_t slope = ((int32_t)(max - min) * 10000) / (int32_t)(max_in - min_in); /** times 10000 to avoid rounding errors*/ - int32_t bias = (int32_t)(min * 10000) - slope * min_in; - - return (bias + slope * x) / 10000; + if(x <= min_in) return min_out; + if(x >= max_in) return max_out; + + /* The equation should be: + * ((x - min_in) / delta in) * delta_out + min_out + * To avoid rounding error reorder the operations: + * (((x - min_in) * delta_out) / delta in) + min_out + */ + + int32_t delta_in = max_in - min_in; + int32_t delta_out = max_out - min_out; + + return ((x - min_in) * delta_out) / delta_in + min_out; } /********************** diff --git a/src/lv_misc/lv_math.h b/src/lv_misc/lv_math.h index 0d72fb5af..d4d626ef9 100644 --- a/src/lv_misc/lv_math.h +++ b/src/lv_misc/lv_math.h @@ -113,14 +113,15 @@ LV_ATTRIBUTE_FAST_MEM void _lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask int64_t _lv_pow(int64_t base, int8_t exp); /** - * Get the mapped of a number given an imput and output range + * Get the mapped of a number given an input and output range * @param x integer which mapped value should be calculated * @param min_in min input range * @param max_in max input range - * @param in min output range - * @param out max output range + * @param min_out max output range + * @param max_out max output range + * @return the mapped number */ -LV_ATTRIBUTE_FAST_MEM int16_t _lv_map(int16_t x, int16_t min_in, int16_t max_in, int16_t min, int16_t max); +int16_t _lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min, int32_t max); /********************** * MACROS diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 3b2d2241b..e4c0e5c62 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -207,8 +207,8 @@ bool lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim case LV_ROTARY_TYPE_REVERSE: lv_arc_set_start_angle( rotary, - _lv_map(ext->cur_value, ext->max_value, ext->min_value, - bg_end, ext->arc.bg_angle_start) + _lv_map(ext->cur_value, ext->min_value, ext->max_value, + ext->arc.bg_angle_start, bg_end) ); break; default: /** LV_ROTARY_TYPE_NORMAL*/ @@ -403,51 +403,48 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); - if(sign == LV_SIGNAL_PRESSED) { - lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); - ext->dragging = true; - } - else if(sign == LV_SIGNAL_PRESSING) { + if(sign == LV_SIGNAL_PRESSING) { lv_indev_t * indev = lv_indev_get_act(); if(indev == NULL) return res; + /*Handle only pointers here*/ lv_indev_type_t indev_type = lv_indev_get_type(indev); + if(indev_type != LV_INDEV_TYPE_POINTER) return res; + lv_point_t p; - if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) { - p.x = rotary->coords.x1 + lv_obj_get_width(rotary) / 2; - p.y = rotary->coords.y1 + lv_obj_get_height(rotary) / 2; - } - else { - lv_indev_get_point(indev, &p); + lv_indev_get_point(indev, &p); + + /*Make point relative to the rotary's center*/ + lv_coord_t w_half = lv_obj_get_width(rotary) / 2; + p.x -= rotary->coords.x1 + w_half; + p.y -= rotary->coords.y1 + w_half; + + /*Enter dragging mode if pressed out of the knob*/ + if(ext->dragging == false) { + lv_coord_t r_in = lv_area_get_width(&ext->knob_area) / 2; + + if(p.x * p.x + p.y * p.y > r_in * r_in) { + ext->dragging = true; + } } - ext->last_press_point.x = p.x; - ext->last_press_point.y = p.y; + /*It must be in "dragging" mode to turn the arc*/ + if(ext->dragging == false) return res; - /*Make point 0 relative to the rotary*/ - p.x -= rotary->coords.x1; - p.y -= rotary->coords.y1; - - /*Ignore pressing in the inner area*/ + /*Calculate the angle of the pressed point*/ int16_t angle; - lv_coord_t r_in = lv_area_get_width(&ext->knob_area) / 2; - - p.x -= r_in; - p.y -= r_in; - if(p.x * p.x + p.y * p.y < r_in * r_in) { - return res; /*Set the angle only if pressed on the ring*/ - } - - int16_t bg_zero, bg_end = ext->arc.bg_angle_end; + int16_t bg_end = ext->arc.bg_angle_end; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { bg_end = ext->arc.bg_angle_end + 360; } - bg_zero = (((ext->arc.bg_angle_start + bg_end) / 2) + 180) % 360; - angle = (_lv_atan2(p.x, p.y) + bg_zero) % 360; - if (bg_end > 360 && angle < ext->arc.bg_angle_start) angle += 360; + angle = 360 - _lv_atan2(p.x, p.y) + 90; /*Some transformation is required*/ + if(angle < ext->arc.bg_angle_start) angle = ext->arc.bg_angle_start; + if(angle > bg_end) angle = bg_end; - int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->max_value, ext->min_value); + int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); + + /*Set the new value if it's larger than the threshold*/ if (LV_MATH_ABS(ext->cur_value - new_value) < ext->threshold) { if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 32c0c87b9..a74c6a925 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -72,10 +72,7 @@ typedef struct { int16_t max_value; /*Maximum value of the rotary*/ int16_t sensitivity; /*Control signal increment multiplier of the rotary*/ int16_t threshold; /*Drag increment threshold of the rotary*/ - lv_point_t last_press_point; /*Last press point of the rotary*/ - uint16_t last_press_angle; /*Last press angle of the rotary*/ uint16_t dragging :1; - } lv_rotary_ext_t; /** Built-in styles of rotary*/ From e256a27b5a07c71839a42e30a0e67c82d0700f15 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 12:25:44 -0700 Subject: [PATCH 83/97] Add slew rate limited angle delta based on threshold of degress/sec --- src/lv_widgets/lv_rotary.c | 14 ++++++++++++++ src/lv_widgets/lv_rotary.h | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index e4c0e5c62..a4cc31c35 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -442,6 +442,20 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(angle < ext->arc.bg_angle_start) angle = ext->arc.bg_angle_start; if(angle > bg_end) angle = bg_end; + /*Calculate the slew rate limited angle delta the threshold (degrees/sec)*/ + int16_t delta_angle = angle - ext->last_angle; + uint16_t delta_ts_milli = lv_tick_get() - ext->last_timestamp; + int16_t delta_angle_threshold = (ext->threshold * 1000) / delta_ts_milli; + + if (delta_angle > delta_angle_threshold) { + delta_angle = delta_angle_threshold; + } else if (delta_angle < -delta_angle_threshold) { + delta_angle = -delta_angle_threshold; + } + + angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ + ext->last_angle = angle; /*Cache angle for the next iteration*/ + int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); /*Set the new value if it's larger than the threshold*/ diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index a74c6a925..e59e81b92 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -71,8 +71,10 @@ typedef struct { int16_t min_value; /*Minimum value of the rotary*/ int16_t max_value; /*Maximum value of the rotary*/ int16_t sensitivity; /*Control signal increment multiplier of the rotary*/ - int16_t threshold; /*Drag increment threshold of the rotary*/ uint16_t dragging :1; + uint16_t threshold; /*Drag angle rate of change threshold of the rotary (degrees/sec)*/ + int16_t last_timestamp; /*Last dragging event timestamp of the rotary*/ + int16_t last_angle; /*Last dragging angle of the rotary*/ } lv_rotary_ext_t; /** Built-in styles of rotary*/ From e3f4c1150097f0f5e8eb5996376bb1c91b7dc439 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 12:49:27 -0700 Subject: [PATCH 84/97] Remove previous thresholding and add creation defaults. Move angle caching to set value to cache last angel for type changes and external value setters. --- src/lv_widgets/lv_rotary.c | 57 +++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index a4cc31c35..969011722 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -81,13 +81,15 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->arc.bg_angle_end = 45; ext->arc.arc_angle_start = 135; ext->arc.arc_angle_end = 270; + ext->type = LV_ROTARY_TYPE_NORMAL; ext->cur_value = 0; ext->min_value = 0; ext->max_value = 0; ext->sensitivity = 1; - ext->threshold = 10; ext->dragging = false; - ext->type = LV_ROTARY_TYPE_NORMAL; + ext->threshold = 360; + ext->last_timestamp = lv_tick_get(); + ext->last_angle = ext->arc.arc_angle_end; lv_style_list_init(&ext->style_knob); /*The signal and design functions are not copied so set them here*/ @@ -105,13 +107,15 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) /*Copy an existing rotary*/ else { lv_rotary_ext_t * copy_ext = lv_obj_get_ext_attr(copy); + ext->type = copy_ext->type; ext->cur_value = copy_ext->cur_value; ext->min_value = copy_ext->min_value; ext->max_value = copy_ext->max_value; ext->sensitivity = copy_ext->sensitivity; - ext->threshold = copy_ext->threshold; ext->dragging = copy_ext->dragging; - ext->type = copy_ext->type; + ext->threshold = copy_ext->threshold; + ext->last_timestamp = copy_ext->last_timestamp; + ext->last_angle = copy_ext->last_angle; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); @@ -183,41 +187,32 @@ bool lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim int16_t bg_midpoint, range_midpoint, bg_end = ext->arc.bg_angle_end; if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) bg_end = ext->arc.bg_angle_end + 360; + int16_t angle; switch(ext->type) { case LV_ROTARY_TYPE_SYMMETRIC: bg_midpoint = (ext->arc.bg_angle_start + bg_end) / 2; range_midpoint = (int32_t)(ext->min_value + ext->max_value) / 2; if (ext->cur_value < range_midpoint) { - lv_arc_set_start_angle( - rotary, - _lv_map(ext->cur_value, ext->min_value, range_midpoint, - ext->arc.bg_angle_start, bg_midpoint) - ); + angle = _lv_map(ext->cur_value, ext->min_value, range_midpoint, ext->arc.bg_angle_start, bg_midpoint); + lv_arc_set_start_angle(rotary, angle); lv_arc_set_end_angle(rotary, bg_midpoint); } else { + angle = _lv_map(ext->cur_value, range_midpoint, ext->max_value, bg_midpoint, bg_end); lv_arc_set_start_angle(rotary, bg_midpoint); - lv_arc_set_end_angle( - rotary, - _lv_map(ext->cur_value, range_midpoint, ext->max_value, - bg_midpoint, bg_end) - ); + lv_arc_set_end_angle(rotary, angle); } break; case LV_ROTARY_TYPE_REVERSE: - lv_arc_set_start_angle( - rotary, - _lv_map(ext->cur_value, ext->min_value, ext->max_value, - ext->arc.bg_angle_start, bg_end) - ); + angle = _lv_map(ext->cur_value, ext->min_value, ext->max_value, ext->arc.bg_angle_start, bg_end); + lv_arc_set_start_angle(rotary, angle); break; default: /** LV_ROTARY_TYPE_NORMAL*/ - lv_arc_set_end_angle( - rotary, - _lv_map(ext->cur_value, ext->min_value, ext->max_value, - ext->arc.bg_angle_start, bg_end) - ); + angle = _lv_map(ext->cur_value, ext->min_value, ext->max_value, ext->arc.bg_angle_start, bg_end); + lv_arc_set_end_angle(rotary, angle); } + ext->last_angle = angle; /*Cache angle slew rate limiting*/ + return true; } @@ -442,7 +437,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(angle < ext->arc.bg_angle_start) angle = ext->arc.bg_angle_start; if(angle > bg_end) angle = bg_end; - /*Calculate the slew rate limited angle delta the threshold (degrees/sec)*/ + /*Calculate the slew rate limited angle based on threshold (degrees/sec)*/ int16_t delta_angle = angle - ext->last_angle; uint16_t delta_ts_milli = lv_tick_get() - ext->last_timestamp; int16_t delta_angle_threshold = (ext->threshold * 1000) / delta_ts_milli; @@ -454,16 +449,14 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ - ext->last_angle = angle; /*Cache angle for the next iteration*/ + // ext->last_angle = angle; /*Cache angle for the next iteration*/ int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); - /*Set the new value if it's larger than the threshold*/ - if (LV_MATH_ABS(ext->cur_value - new_value) < ext->threshold) { - if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } + /*Set the new value*/ + if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; } } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { From aea84d8d79a3616ea7d761cc22b0bf2d54fb193e Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 13:18:08 -0700 Subject: [PATCH 85/97] Cache timestamp for slew rate limit interation --- src/lv_widgets/lv_rotary.c | 4 ++-- src/lv_widgets/lv_rotary.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 969011722..83340c363 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -439,7 +439,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par /*Calculate the slew rate limited angle based on threshold (degrees/sec)*/ int16_t delta_angle = angle - ext->last_angle; - uint16_t delta_ts_milli = lv_tick_get() - ext->last_timestamp; + uint32_t delta_ts_milli = lv_tick_elaps(ext->last_timestamp); int16_t delta_angle_threshold = (ext->threshold * 1000) / delta_ts_milli; if (delta_angle > delta_angle_threshold) { @@ -449,7 +449,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ - // ext->last_angle = angle; /*Cache angle for the next iteration*/ + ext->last_timestamp = lv_tick_get(); /*Cache timestamp for the next iteration*/ int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index e59e81b92..ad72a4a4c 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -73,7 +73,7 @@ typedef struct { int16_t sensitivity; /*Control signal increment multiplier of the rotary*/ uint16_t dragging :1; uint16_t threshold; /*Drag angle rate of change threshold of the rotary (degrees/sec)*/ - int16_t last_timestamp; /*Last dragging event timestamp of the rotary*/ + int32_t last_timestamp; /*Last dragging event timestamp of the rotary*/ int16_t last_angle; /*Last dragging angle of the rotary*/ } lv_rotary_ext_t; From 7a10b700e2acd8e597aa6ef3fed5de849938c942 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 13:21:54 -0700 Subject: [PATCH 86/97] Remove use of tick_elaspe --- src/lv_widgets/lv_rotary.c | 10 +++++----- src/lv_widgets/lv_rotary.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 83340c363..4fa4c8885 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -88,7 +88,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->sensitivity = 1; ext->dragging = false; ext->threshold = 360; - ext->last_timestamp = lv_tick_get(); + ext->last_tick = lv_tick_get(); ext->last_angle = ext->arc.arc_angle_end; lv_style_list_init(&ext->style_knob); @@ -114,7 +114,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->sensitivity = copy_ext->sensitivity; ext->dragging = copy_ext->dragging; ext->threshold = copy_ext->threshold; - ext->last_timestamp = copy_ext->last_timestamp; + ext->last_tick = copy_ext->last_tick; ext->last_angle = copy_ext->last_angle; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); @@ -439,8 +439,8 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par /*Calculate the slew rate limited angle based on threshold (degrees/sec)*/ int16_t delta_angle = angle - ext->last_angle; - uint32_t delta_ts_milli = lv_tick_elaps(ext->last_timestamp); - int16_t delta_angle_threshold = (ext->threshold * 1000) / delta_ts_milli; + uint32_t delta_tick = lv_get_tick() - ext->last_tick; + int16_t delta_angle_threshold = (ext->threshold * 1000) / delta_tick; if (delta_angle > delta_angle_threshold) { delta_angle = delta_angle_threshold; @@ -449,7 +449,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ - ext->last_timestamp = lv_tick_get(); /*Cache timestamp for the next iteration*/ + ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index ad72a4a4c..104b4d77d 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -73,7 +73,7 @@ typedef struct { int16_t sensitivity; /*Control signal increment multiplier of the rotary*/ uint16_t dragging :1; uint16_t threshold; /*Drag angle rate of change threshold of the rotary (degrees/sec)*/ - int32_t last_timestamp; /*Last dragging event timestamp of the rotary*/ + int32_t last_tick; /*Last dragging event timestamp of the rotary*/ int16_t last_angle; /*Last dragging angle of the rotary*/ } lv_rotary_ext_t; From a0bf57f5295418184ce9531f07cd1e0365b1891c Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 13:22:37 -0700 Subject: [PATCH 87/97] tick type --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 4fa4c8885..2550eef20 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -439,7 +439,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par /*Calculate the slew rate limited angle based on threshold (degrees/sec)*/ int16_t delta_angle = angle - ext->last_angle; - uint32_t delta_tick = lv_get_tick() - ext->last_tick; + uint32_t delta_tick = lv_tick_get() - ext->last_tick; int16_t delta_angle_threshold = (ext->threshold * 1000) / delta_tick; if (delta_angle > delta_angle_threshold) { From cf39677dfa223815200e575fd637294d0092c6b9 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 13:30:07 -0700 Subject: [PATCH 88/97] Use tick elps --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 2550eef20..34e8c16c7 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -439,7 +439,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par /*Calculate the slew rate limited angle based on threshold (degrees/sec)*/ int16_t delta_angle = angle - ext->last_angle; - uint32_t delta_tick = lv_tick_get() - ext->last_tick; + uint32_t delta_tick = lv_tick_elaps(ext->last_tick); int16_t delta_angle_threshold = (ext->threshold * 1000) / delta_tick; if (delta_angle > delta_angle_threshold) { From b371bd3d05191bdd640833b8b91a990ab1e3f75f Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 13:50:05 -0700 Subject: [PATCH 89/97] Capture tick at drap start --- src/lv_widgets/lv_rotary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 34e8c16c7..84e9bad34 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -420,6 +420,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(p.x * p.x + p.y * p.y > r_in * r_in) { ext->dragging = true; + ext->last_tick = lv_tick_get(); /*Capture timestamp at dragging start*/ } } @@ -451,9 +452,8 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ - int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); - /*Set the new value*/ + int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; From 085a6499a71955a3d89002ff14cae4893dcc254e Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 13:59:03 -0700 Subject: [PATCH 90/97] Comment updates for clarity --- src/lv_widgets/lv_rotary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 84e9bad34..28001e53b 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -211,7 +211,7 @@ bool lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim angle = _lv_map(ext->cur_value, ext->min_value, ext->max_value, ext->arc.bg_angle_start, bg_end); lv_arc_set_end_angle(rotary, angle); } - ext->last_angle = angle; /*Cache angle slew rate limiting*/ + ext->last_angle = angle; /*Cache angle for slew rate limiting*/ return true; } @@ -454,7 +454,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par /*Set the new value*/ int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); - if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { + if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { /*set_value caches the last_angle for the next interation*/ res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } From 83bdb6c34777c680fbd9735d333e4578e2459d84 Mon Sep 17 00:00:00 2001 From: Adam Martini Date: Sun, 5 Jul 2020 14:44:11 -0700 Subject: [PATCH 91/97] Reverse angle delta logic --- src/lv_widgets/lv_rotary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index 28001e53b..f28e4efd8 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -441,7 +441,7 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par /*Calculate the slew rate limited angle based on threshold (degrees/sec)*/ int16_t delta_angle = angle - ext->last_angle; uint32_t delta_tick = lv_tick_elaps(ext->last_tick); - int16_t delta_angle_threshold = (ext->threshold * 1000) / delta_tick; + int16_t delta_angle_threshold = (ext->threshold * delta_tick) / 1000; if (delta_angle > delta_angle_threshold) { delta_angle = delta_angle_threshold; From 96728e7ed92ffe12fc8a22c5fdbf773213d9277a Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 6 Jul 2020 11:51:26 +0200 Subject: [PATCH 92/97] rotary: minor refactoring --- src/lv_widgets/lv_rotary.c | 26 +++++++++++++------------- src/lv_widgets/lv_rotary.h | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index f28e4efd8..fdea7f606 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -82,12 +82,12 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->arc.arc_angle_start = 135; ext->arc.arc_angle_end = 270; ext->type = LV_ROTARY_TYPE_NORMAL; - ext->cur_value = 0; + ext->cur_value = -1; ext->min_value = 0; - ext->max_value = 0; + ext->max_value = 100; ext->sensitivity = 1; ext->dragging = false; - ext->threshold = 360; + ext->chg_rate = 360; ext->last_tick = lv_tick_get(); ext->last_angle = ext->arc.arc_angle_end; lv_style_list_init(&ext->style_knob); @@ -101,7 +101,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_click(rotary, true); lv_obj_add_protect(rotary, LV_PROTECT_PRESS_LOST); lv_obj_set_ext_click_area(rotary, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10); - + lv_rotary_set_value(rotary, ext->min_value, LV_ANIM_OFF); lv_theme_apply(rotary, LV_THEME_ROTARY); } /*Copy an existing rotary*/ @@ -113,7 +113,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->max_value = copy_ext->max_value; ext->sensitivity = copy_ext->sensitivity; ext->dragging = copy_ext->dragging; - ext->threshold = copy_ext->threshold; + ext->chg_rate = copy_ext->chg_rate; ext->last_tick = copy_ext->last_tick; ext->last_angle = copy_ext->last_angle; lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); @@ -262,12 +262,12 @@ void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity) * @param rotary pointer to a rotary object * @param threshold increment threshold */ -void lv_rotary_set_threshold(lv_obj_t * rotary, uint16_t threshold) +void lv_rotary_set_chg_rate(lv_obj_t * rotary, uint16_t rate) { LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - ext->threshold = threshold; + ext->chg_rate = rate; } /*===================== @@ -438,15 +438,15 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par if(angle < ext->arc.bg_angle_start) angle = ext->arc.bg_angle_start; if(angle > bg_end) angle = bg_end; - /*Calculate the slew rate limited angle based on threshold (degrees/sec)*/ + /*Calculate the slew rate limited angle based on change rate (degrees/sec)*/ int16_t delta_angle = angle - ext->last_angle; uint32_t delta_tick = lv_tick_elaps(ext->last_tick); - int16_t delta_angle_threshold = (ext->threshold * delta_tick) / 1000; + int16_t delta_angle_max = (ext->chg_rate * delta_tick) / 1000; - if (delta_angle > delta_angle_threshold) { - delta_angle = delta_angle_threshold; - } else if (delta_angle < -delta_angle_threshold) { - delta_angle = -delta_angle_threshold; + if (delta_angle > delta_angle_max) { + delta_angle = delta_angle_max; + } else if (delta_angle < -delta_angle_max) { + delta_angle = -delta_angle_max; } angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h index 104b4d77d..81c9bc488 100644 --- a/src/lv_widgets/lv_rotary.h +++ b/src/lv_widgets/lv_rotary.h @@ -72,7 +72,7 @@ typedef struct { int16_t max_value; /*Maximum value of the rotary*/ int16_t sensitivity; /*Control signal increment multiplier of the rotary*/ uint16_t dragging :1; - uint16_t threshold; /*Drag angle rate of change threshold of the rotary (degrees/sec)*/ + uint16_t chg_rate; /*Drag angle rate of change of the rotary (degrees/sec)*/ int32_t last_tick; /*Last dragging event timestamp of the rotary*/ int16_t last_angle; /*Last dragging angle of the rotary*/ } lv_rotary_ext_t; @@ -148,7 +148,7 @@ void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity); * @param rotary pointer to a rotary object * @param threshold increment threshold */ -void lv_rotary_set_threshold(lv_obj_t * rotary, uint16_t threshold); +void lv_rotary_set_chg_rate(lv_obj_t * rotary, uint16_t threshold); /** * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. From cae5132038d68e7407ade195cb90dbbc0e91cb6c Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 7 Jul 2020 12:35:23 +0200 Subject: [PATCH 93/97] rotary: fix with low chg_rate --- src/lv_widgets/lv_rotary.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c index fdea7f606..92ac3172b 100644 --- a/src/lv_widgets/lv_rotary.c +++ b/src/lv_widgets/lv_rotary.c @@ -87,7 +87,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) ext->max_value = 100; ext->sensitivity = 1; ext->dragging = false; - ext->chg_rate = 360; + ext->chg_rate = 540; ext->last_tick = lv_tick_get(); ext->last_angle = ext->arc.arc_angle_end; lv_style_list_init(&ext->style_knob); @@ -101,7 +101,7 @@ lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_click(rotary, true); lv_obj_add_protect(rotary, LV_PROTECT_PRESS_LOST); lv_obj_set_ext_click_area(rotary, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10); - lv_rotary_set_value(rotary, ext->min_value, LV_ANIM_OFF); + lv_rotary_set_value(rotary, 50, LV_ANIM_OFF); lv_theme_apply(rotary, LV_THEME_ROTARY); } /*Copy an existing rotary*/ @@ -450,13 +450,25 @@ static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * par } angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ - ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ + + /*Rounding for symmetry*/ + int32_t round = ((bg_end - ext->arc.bg_angle_start) * 8) / (ext->max_value - ext->min_value); + round = (round + 4) >> 4; + angle += round; /*Set the new value*/ int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); - if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { /*set_value caches the last_angle for the next interation*/ - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; + if(new_value != lv_rotary_get_value(rotary)) { + ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ + if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { /*set_value caches the last_angle for the next interation*/ + res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + } + + /*Don1't let the elapsed time to big while sitting on an end point*/ + if(new_value == ext->min_value || new_value == ext->max_value) { + ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ } } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { From 14a4c190c91686dd7cd9deb25ff5a7d759313ff7 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 11 Aug 2020 14:17:05 +0200 Subject: [PATCH 94/97] merge rotary to arc --- CHANGELOG.md | 2 +- lvgl.h | 1 - src/lv_themes/lv_theme_material.c | 75 +--- src/lv_widgets/lv_arc.c | 398 ++++++++++++++++++++- src/lv_widgets/lv_arc.h | 94 ++++- src/lv_widgets/lv_rotary.c | 566 ------------------------------ src/lv_widgets/lv_rotary.h | 322 ----------------- 7 files changed, 490 insertions(+), 968 deletions(-) delete mode 100644 src/lv_widgets/lv_rotary.c delete mode 100644 src/lv_widgets/lv_rotary.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e4b928be..b9e472b24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## v7.4.0 (planned on 01.09.2020) -*Available in the `dev` branch* +- arc: add set value by click feature ## v7.3.1 (planned on 18.08.2020) diff --git a/lvgl.h b/lvgl.h index 4edd6d364..ae383e640 100644 --- a/lvgl.h +++ b/lvgl.h @@ -53,7 +53,6 @@ extern "C" { #include "src/lv_widgets/lv_keyboard.h" #include "src/lv_widgets/lv_dropdown.h" #include "src/lv_widgets/lv_roller.h" -#include "src/lv_widgets/lv_rotary.h" #include "src/lv_widgets/lv_textarea.h" #include "src/lv_widgets/lv_canvas.h" #include "src/lv_widgets/lv_win.h" diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index 45911d074..85a24c881 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -86,6 +86,7 @@ typedef struct { #if LV_USE_ARC lv_style_t arc_indic; lv_style_t arc_bg; + lv_style_t arc_knob; #endif #if LV_USE_BAR @@ -148,10 +149,6 @@ typedef struct { lv_style_t roller_bg, roller_sel; #endif -#if LV_USE_ROTARY - lv_style_t rotary_bg, rotary_indic, rotary_knob; -#endif - #if LV_USE_SLIDER lv_style_t slider_knob, slider_bg; #endif @@ -509,6 +506,14 @@ static void arc_init(void) lv_style_set_line_color(&styles->arc_bg, LV_STATE_DEFAULT, COLOR_BG_SEC); lv_style_set_line_width(&styles->arc_bg, LV_STATE_DEFAULT, LV_DPX(25)); lv_style_set_line_rounded(&styles->arc_bg, LV_STATE_DEFAULT, true); + + style_init_reset(&styles->arc_knob); + lv_style_set_radius(&styles->arc_knob, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_style_set_pad_top(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(10)); + lv_style_set_pad_bottom(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(10)); + lv_style_set_pad_left(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(10)); + lv_style_set_pad_right(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(10)); + #endif } @@ -795,41 +800,6 @@ static void roller_init(void) #endif } -static void rotary_init(void) -{ -#if LV_USE_ROTARY != 0 - style_init_reset(&styles->rotary_bg); - lv_style_set_clip_corner(&styles->rotary_bg, LV_STATE_DEFAULT, true); - lv_style_set_pad_left(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); - lv_style_set_pad_right(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); - lv_style_set_pad_top(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); - lv_style_set_pad_bottom(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); - lv_style_set_pad_inner(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(6)); - lv_style_set_border_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(2)); - lv_style_set_line_color(&styles->rotary_bg, LV_STATE_DEFAULT, COLOR_BG_SEC); - lv_style_set_line_width(&styles->rotary_bg, LV_STATE_DEFAULT, LV_DPX(8)); - lv_style_set_line_rounded(&styles->rotary_bg, LV_STATE_DEFAULT, true); - - style_init_reset(&styles->rotary_indic); - lv_style_set_line_color(&styles->rotary_indic, LV_STATE_DEFAULT, theme.color_primary); - lv_style_set_line_width(&styles->rotary_indic, LV_STATE_DEFAULT, LV_DPX(8)); - lv_style_set_line_rounded(&styles->rotary_indic, LV_STATE_DEFAULT, true); - - style_init_reset(&styles->rotary_knob); - lv_style_set_bg_color(&styles->rotary_knob, LV_STATE_CHECKED, COLOR_BTN); - lv_style_set_text_color(&styles->rotary_knob, LV_STATE_CHECKED, IS_LIGHT ? lv_color_hex(0x31404f) : lv_color_hex(0xffffff)); - lv_style_set_value_color(&styles->rotary_knob, LV_STATE_CHECKED, IS_LIGHT ? lv_color_hex(0x31404f) : lv_color_hex(0xffffff)); - lv_style_set_bg_opa(&styles->rotary_knob, LV_STATE_DEFAULT, LV_OPA_COVER); - lv_style_set_bg_color(&styles->rotary_knob, LV_STATE_DEFAULT, LV_COLOR_WHITE); - lv_style_set_radius(&styles->rotary_knob, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); - lv_style_set_pad_top(&styles->rotary_knob, LV_STATE_DEFAULT, - LV_DPX(4)); - lv_style_set_pad_bottom(&styles->rotary_knob, LV_STATE_DEFAULT, - LV_DPX(4)); - lv_style_set_pad_left(&styles->rotary_knob, LV_STATE_DEFAULT, - LV_DPX(4)); - lv_style_set_pad_right(&styles->rotary_knob, LV_STATE_DEFAULT, - LV_DPX(4)); - lv_style_set_pad_inner(&styles->rotary_knob, LV_STATE_DEFAULT, LV_DPX(6)); -#endif -} - static void tabview_init(void) { #if LV_USE_TABVIEW != 0 @@ -969,7 +939,6 @@ lv_theme_t * lv_theme_material_init(lv_color_t color_primary, lv_color_t color_s list_init(); ddlist_init(); roller_init(); - rotary_init(); tabview_init(); tileview_init(); table_init(); @@ -1099,6 +1068,11 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) list = lv_obj_get_style_list(obj, LV_ARC_PART_INDIC); _lv_style_list_add_style(list, &styles->arc_indic); + + list = lv_obj_get_style_list(obj, LV_ARC_PART_KNOB); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->bg_click); + _lv_style_list_add_style(list, &styles->arc_knob); break; #endif @@ -1225,27 +1199,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) break; #endif -#if LV_USE_ROTARY - case LV_THEME_ROTARY: - lv_obj_clean_style_list(obj, LV_ROTARY_PART_BG); - list = lv_obj_get_style_list(obj, LV_ROTARY_PART_BG); - _lv_style_list_add_style(list, &styles->bg); - _lv_style_list_add_style(list, &styles->arc_bg); - _lv_style_list_add_style(list, &styles->rotary_bg); - - lv_obj_clean_style_list(obj, LV_ROTARY_PART_INDIC); - list = lv_obj_get_style_list(obj, LV_ROTARY_PART_INDIC); - _lv_style_list_add_style(list, &styles->arc_indic); - _lv_style_list_add_style(list, &styles->rotary_indic); - - lv_obj_clean_style_list(obj, LV_ROTARY_PART_KNOB); - list = lv_obj_get_style_list(obj, LV_ROTARY_PART_KNOB); - _lv_style_list_add_style(list, &styles->btn); - _lv_style_list_add_style(list, &styles->rotary_knob); - - break; -#endif - #if LV_USE_OBJMASK case LV_THEME_OBJMASK: list = lv_obj_get_style_list(obj, LV_OBJMASK_PART_MAIN); diff --git a/src/lv_widgets/lv_arc.c b/src/lv_widgets/lv_arc.c index 4dd7d9f45..8849d3895 100644 --- a/src/lv_widgets/lv_arc.c +++ b/src/lv_widgets/lv_arc.c @@ -9,6 +9,8 @@ #include "lv_arc.h" #if LV_USE_ARC != 0 +#include "../lv_core/lv_group.h" +#include "../lv_core/lv_indev.h" #include "../lv_misc/lv_debug.h" #include "../lv_misc/lv_math.h" #include "../lv_draw/lv_draw_arc.h" @@ -30,6 +32,7 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param); static lv_style_list_t * lv_arc_get_style(lv_obj_t * arc, uint8_t part); static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle); +static void get_areas(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r, lv_area_t * knob_area); /********************** * STATIC VARIABLES @@ -78,7 +81,16 @@ lv_obj_t * lv_arc_create(lv_obj_t * par, const lv_obj_t * copy) ext->bg_angle_end = 45; ext->arc_angle_start = 135; ext->arc_angle_end = 270; + ext->type = LV_ARC_TYPE_NORMAL; + ext->cur_value = -1; + ext->min_value = 0; + ext->max_value = 100; + ext->dragging = false; + ext->chg_rate = 540; + ext->last_tick = lv_tick_get(); + ext->last_angle = ext->arc_angle_end; lv_style_list_init(&ext->style_arc); + lv_style_list_init(&ext->style_knob); lv_obj_set_size(arc, LV_DPI, LV_DPI); @@ -88,6 +100,10 @@ lv_obj_t * lv_arc_create(lv_obj_t * par, const lv_obj_t * copy) /*Init the new arc arc*/ if(copy == NULL) { + lv_obj_set_click(arc, true); + lv_obj_add_protect(arc, LV_PROTECT_PRESS_LOST); + lv_obj_set_ext_click_area(arc, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10); + lv_arc_set_value(arc, ext->min_value); lv_theme_apply(arc, LV_THEME_ARC); } /*Copy an existing arc*/ @@ -97,7 +113,15 @@ lv_obj_t * lv_arc_create(lv_obj_t * par, const lv_obj_t * copy) ext->arc_angle_end = copy_ext->arc_angle_end; ext->bg_angle_start = copy_ext->bg_angle_start; ext->bg_angle_end = copy_ext->bg_angle_end; - + ext->type = copy_ext->type; + ext->cur_value = copy_ext->cur_value; + ext->min_value = copy_ext->min_value; + ext->max_value = copy_ext->max_value; + ext->dragging = copy_ext->dragging; + ext->chg_rate = copy_ext->chg_rate; + ext->last_tick = copy_ext->last_tick; + ext->last_angle = copy_ext->last_angle; + lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); lv_style_list_copy(&ext->style_arc, ©_ext->style_arc); /*Refresh the style with new signal function*/ @@ -316,6 +340,131 @@ void lv_arc_set_rotation(lv_obj_t * arc, uint16_t rotation_angle) lv_obj_invalidate(arc); } + +/** + * Set the type of arc. + * @param arc pointer to arc object + * @param type arc type + */ +void lv_arc_set_type(lv_obj_t * arc, lv_arc_type_t type) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t *ext = (lv_arc_ext_t *)lv_obj_get_ext_attr(arc); + int16_t val = ext->cur_value; + + ext->type = type; + ext->cur_value = -1; /** Force set_value handling*/ + + int16_t bg_midpoint, bg_end = ext->bg_angle_end; + if (ext->bg_angle_end < ext->bg_angle_start) bg_end = ext->bg_angle_end + 360; + + switch(ext->type) { + case LV_ARC_TYPE_SYMMETRIC: + bg_midpoint = (ext->bg_angle_start + bg_end) / 2; + lv_arc_set_start_angle(arc, bg_midpoint); + lv_arc_set_end_angle(arc, bg_midpoint); + break; + case LV_ARC_TYPE_REVERSE: + lv_arc_set_end_angle(arc, ext->bg_angle_end); + break; + default: /** LV_ARC_TYPE_NORMAL*/ + lv_arc_set_start_angle(arc, ext->bg_angle_start); + } + + lv_arc_set_value(arc, val); +} + +/** + * Set a new value on the arc + * @param arc pointer to a arc object + * @param value new value + */ +void lv_arc_set_value(lv_obj_t * arc, int16_t value) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t * ext = (lv_arc_ext_t *)lv_obj_get_ext_attr(arc); + if(ext->cur_value == value) return; + + int16_t new_value; + new_value = value > ext->max_value ? ext->max_value : value; + new_value = new_value < ext->min_value ? ext->min_value : new_value; + + if(ext->cur_value == new_value) return; + ext->cur_value = new_value; + + int16_t bg_midpoint, range_midpoint, bg_end = ext->bg_angle_end; + if (ext->bg_angle_end < ext->bg_angle_start) bg_end = ext->bg_angle_end + 360; + + int16_t angle; + switch(ext->type) { + case LV_ARC_TYPE_SYMMETRIC: + bg_midpoint = (ext->bg_angle_start + bg_end) / 2; + range_midpoint = (int32_t)(ext->min_value + ext->max_value) / 2; + + if (ext->cur_value < range_midpoint) { + angle = _lv_map(ext->cur_value, ext->min_value, range_midpoint, ext->bg_angle_start, bg_midpoint); + lv_arc_set_start_angle(arc, angle); + lv_arc_set_end_angle(arc, bg_midpoint); + } else { + angle = _lv_map(ext->cur_value, range_midpoint, ext->max_value, bg_midpoint, bg_end); + lv_arc_set_start_angle(arc, bg_midpoint); + lv_arc_set_end_angle(arc, angle); + } + break; + case LV_ARC_TYPE_REVERSE: + angle = _lv_map(ext->cur_value, ext->min_value, ext->max_value, ext->bg_angle_start, bg_end); + lv_arc_set_start_angle(arc, angle); + break; + default: /** LV_ARC_TYPE_NORMAL*/ + angle = _lv_map(ext->cur_value, ext->min_value, ext->max_value, ext->bg_angle_start, bg_end); + lv_arc_set_end_angle(arc, angle); + } + ext->last_angle = angle; /*Cache angle for slew rate limiting*/ +} + +/** + * Set minimum and the maximum values of a arc + * @param arc pointer to the arc object + * @param min minimum value + * @param max maximum value + */ +void lv_arc_set_range(lv_obj_t * arc, int16_t min, int16_t max) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t * ext = (lv_arc_ext_t *)lv_obj_get_ext_attr(arc); + if(ext->min_value == min && ext->max_value == max) return; + + ext->min_value = min; + ext->max_value = max; + + if(ext->cur_value < min) { + ext->cur_value = min; + } + if(ext->cur_value > max) { + ext->cur_value = max; + } + + lv_arc_set_value(arc, ext->cur_value); +} + +/** + * Set the threshold of arc knob increments + * position. + * @param arc pointer to a arc object + * @param threshold increment threshold + */ +void lv_arc_set_chg_rate(lv_obj_t * arc, uint16_t rate) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t *ext = (lv_arc_ext_t *)lv_obj_get_ext_attr(arc); + ext->chg_rate = rate; +} + + /*===================== * Getter functions *====================*/ @@ -376,6 +525,72 @@ uint16_t lv_arc_get_bg_angle_end(lv_obj_t * arc) return ext->bg_angle_end; } + +/** + * Get the value of a arc + * @param arc pointer to a arc object + * @return the value of the arc + */ +int16_t lv_arc_get_value(const lv_obj_t * arc) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); + return ext->cur_value; +} + +/** + * Get the minimum value of a arc + * @param arc pointer to a arc object + * @return the minimum value of the arc + */ +int16_t lv_arc_get_min_value(const lv_obj_t * arc) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t *ext = (lv_arc_ext_t *)lv_obj_get_ext_attr(arc); + return ext->min_value; +} + +/** + * Get the maximum value of a arc + * @param arc pointer to a arc object + * @return the maximum value of the arc + */ +int16_t lv_arc_get_max_value(const lv_obj_t * arc) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t *ext = (lv_arc_ext_t *)lv_obj_get_ext_attr(arc); + return ext->max_value; +} + +/** + * Give the arc is being dragged or not + * @param arc pointer to a arc object + * @return true: drag in progress false: not dragged + */ +bool lv_arc_is_dragged(const lv_obj_t * arc) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); + return ext->dragging; +} + +/** + * Get whether the arc is type or not. + * @param arc pointer to a arc object + * @return arc type + */ +lv_arc_type_t lv_arc_get_type(const lv_obj_t * arc) +{ + LV_ASSERT_OBJ(arc, LV_OBJX_NAME); + + lv_arc_ext_t * ext = (lv_arc_ext_t *)lv_obj_get_ext_attr(arc); + return ext->type; +} + /*===================== * Other functions *====================*/ @@ -414,21 +629,18 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area lv_draw_rect(&arc->coords, clip_area, &bg_dsc); - lv_coord_t left_bg = lv_obj_get_style_pad_left(arc, LV_ARC_PART_BG); - lv_coord_t right_bg = lv_obj_get_style_pad_right(arc, LV_ARC_PART_BG); - lv_coord_t top_bg = lv_obj_get_style_pad_top(arc, LV_ARC_PART_BG); - lv_coord_t bottom_bg = lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_BG); - lv_coord_t r = (LV_MATH_MIN(lv_obj_get_width(arc) - left_bg - right_bg, - lv_obj_get_height(arc) - top_bg - bottom_bg)) / 2; - lv_draw_line_dsc_t arc_dsc; - lv_coord_t x = arc->coords.x1 + r + left_bg; - lv_coord_t y = arc->coords.y1 + r + top_bg; + lv_point_t center; + lv_coord_t arc_r; + lv_area_t knob_area; + get_areas(arc, ¢er, &arc_r, &knob_area); - if(r > 0) { + /*Draw the background arc*/ + lv_draw_line_dsc_t arc_dsc; + if(arc_r > 0) { lv_draw_line_dsc_init(&arc_dsc); lv_obj_init_draw_line_dsc(arc, LV_ARC_PART_BG, &arc_dsc); - lv_draw_arc(x, y, r, ext->bg_angle_start + ext->rotation_angle, ext->bg_angle_end + ext->rotation_angle, clip_area, + lv_draw_arc(center.x, center.y, arc_r, ext->bg_angle_start + ext->rotation_angle, ext->bg_angle_end + ext->rotation_angle, clip_area, &arc_dsc); } @@ -438,15 +650,23 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area lv_coord_t right_indic = lv_obj_get_style_pad_right(arc, LV_ARC_PART_INDIC); lv_coord_t top_indic = lv_obj_get_style_pad_top(arc, LV_ARC_PART_INDIC); lv_coord_t bottom_indic = lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_INDIC); - r -= LV_MATH_MAX4(left_indic, right_indic, top_indic, bottom_indic); + arc_r -= LV_MATH_MAX4(left_indic, right_indic, top_indic, bottom_indic); - if(r > 0) { + if(arc_r > 0) { lv_draw_line_dsc_init(&arc_dsc); lv_obj_init_draw_line_dsc(arc, LV_ARC_PART_INDIC, &arc_dsc); - lv_draw_arc(x, y, r, ext->arc_angle_start + ext->rotation_angle, ext->arc_angle_end + ext->rotation_angle, clip_area, + lv_draw_arc(center.x, center.y, arc_r, ext->arc_angle_start + ext->rotation_angle, ext->arc_angle_end + ext->rotation_angle, clip_area, &arc_dsc); } + + + lv_draw_rect_dsc_t knob_rect_dsc; + lv_draw_rect_dsc_init(&knob_rect_dsc); + lv_obj_init_draw_rect_dsc(arc, LV_ARC_PART_KNOB, &knob_rect_dsc); + + lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); + } /*Post draw when the children are drawn*/ else if(mode == LV_DESIGN_DRAW_POST) { @@ -478,7 +698,118 @@ static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param) if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - if(sign == LV_SIGNAL_CLEANUP) { + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); + + if(sign == LV_SIGNAL_PRESSING) { + lv_indev_t * indev = lv_indev_get_act(); + if(indev == NULL) return res; + + /*Handle only pointers here*/ + lv_indev_type_t indev_type = lv_indev_get_type(indev); + if(indev_type != LV_INDEV_TYPE_POINTER) return res; + + lv_point_t p; + lv_indev_get_point(indev, &p); + + /*Make point relative to the arc's center*/ + lv_point_t center; + lv_coord_t r; + lv_area_t knob_area; + get_areas(arc, ¢er, &r, &knob_area); + + p.x -= center.x; + p.y -= center.y; + + /*Enter dragging mode if pressed out of the knob*/ + if(ext->dragging == false) { + lv_coord_t indic_width = lv_obj_get_style_line_width(arc, LV_ARC_PART_INDIC); + r -= indic_width; + if(p.x * p.x + p.y * p.y > r * r) { + ext->dragging = true; + ext->last_tick = lv_tick_get(); /*Capture timestamp at dragging start*/ + } + } + + /*It must be in "dragging" mode to turn the arc*/ + if(ext->dragging == false) return res; + + /*Calculate the angle of the pressed point*/ + int16_t angle; + int16_t bg_end = ext->bg_angle_end; + if (ext->bg_angle_end < ext->bg_angle_start) { + bg_end = ext->bg_angle_end + 360; + } + + angle = 360 - _lv_atan2(p.x, p.y) + 90; /*Some transformation is required*/ + if(angle < ext->bg_angle_start) angle = ext->bg_angle_start; + if(angle > bg_end) angle = bg_end; + + /*Calculate the slew rate limited angle based on change rate (degrees/sec)*/ + int16_t delta_angle = angle - ext->last_angle; + uint32_t delta_tick = lv_tick_elaps(ext->last_tick); + int16_t delta_angle_max = (ext->chg_rate * delta_tick) / 1000; + + if (delta_angle > delta_angle_max) { + delta_angle = delta_angle_max; + } else if (delta_angle < -delta_angle_max) { + delta_angle = -delta_angle_max; + } + + angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ + + /*Rounding for symmetry*/ + int32_t round = ((bg_end - ext->bg_angle_start) * 8) / (ext->max_value - ext->min_value); + round = (round + 4) >> 4; + angle += round; + + /*Set the new value*/ + int16_t new_value = _lv_map(angle, ext->bg_angle_start, bg_end, ext->min_value, ext->max_value); + if(new_value != lv_arc_get_value(arc)) { + ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ + lv_arc_set_value(arc, new_value); /*set_value caches the last_angle for the next iteration*/ + if(new_value != ext->cur_value) { + res = lv_event_send(arc, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + } + + /*Don1't let the elapsed time to big while sitting on an end point*/ + if(new_value == ext->min_value || new_value == ext->max_value) { + ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ + } + } + else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { + ext->dragging = false; + +#if LV_USE_GROUP + /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ + lv_group_t * g = lv_obj_get_group(arc); + bool editing = lv_group_get_editing(g); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + if(indev_type == LV_INDEV_TYPE_ENCODER) { + if(editing) lv_group_set_editing(g, false); + } +#endif + + } + else if(sign == LV_SIGNAL_CONTROL) { + char c = *((char *)param); + + int16_t old_value = ext->cur_value; + if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { + lv_arc_set_value(arc, lv_arc_get_value(arc) + 1); + } + else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { + lv_arc_set_value(arc, lv_arc_get_value(arc) - 1); + } + + if (old_value != ext->cur_value) { + res = lv_event_send(arc, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + } + else if(sign == LV_SIGNAL_CLEANUP) { + lv_obj_clean_style_list(arc, LV_ARC_PART_KNOB); lv_obj_clean_style_list(arc, LV_ARC_PART_INDIC); } @@ -506,6 +837,9 @@ static lv_style_list_t * lv_arc_get_style(lv_obj_t * arc, uint8_t part) case LV_ARC_PART_INDIC: style_dsc_p = &ext->style_arc; break; + case LV_ARC_PART_KNOB: + style_dsc_p = &ext->style_knob; + break; default: style_dsc_p = NULL; } @@ -617,4 +951,36 @@ static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angl lv_obj_invalidate(arc); } } + + +static void get_areas(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r, lv_area_t * knob_area) +{ + lv_coord_t left_bg = lv_obj_get_style_pad_left(arc, LV_ARC_PART_BG); + lv_coord_t right_bg = lv_obj_get_style_pad_right(arc, LV_ARC_PART_BG); + lv_coord_t top_bg = lv_obj_get_style_pad_top(arc, LV_ARC_PART_BG); + lv_coord_t bottom_bg = lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_BG); + + lv_coord_t r = (LV_MATH_MIN(lv_obj_get_width(arc) - left_bg - right_bg, + lv_obj_get_height(arc) - top_bg - bottom_bg)) / 2; + + *arc_r = r; + center->x = arc->coords.x1 + r + left_bg; + center->y = arc->coords.y1 + r + top_bg; + + + lv_coord_t indic_width = lv_obj_get_style_line_width(arc, LV_ARC_PART_INDIC); + r -= indic_width; + + lv_coord_t left_knob = lv_obj_get_style_pad_left(arc, LV_ARC_PART_KNOB); + lv_coord_t right_knob = lv_obj_get_style_pad_right(arc, LV_ARC_PART_KNOB); + lv_coord_t top_knob = lv_obj_get_style_pad_top(arc, LV_ARC_PART_KNOB); + lv_coord_t bottom_knob = lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_KNOB); + + knob_area->x1 = center->x - r + left_knob; + knob_area->x2 = center->x + r - right_knob; + knob_area->y1 = center->y - r + top_knob; + knob_area->y2 = center->y + r - bottom_knob; +} + + #endif diff --git a/src/lv_widgets/lv_arc.h b/src/lv_widgets/lv_arc.h index 10481f405..94f711661 100644 --- a/src/lv_widgets/lv_arc.h +++ b/src/lv_widgets/lv_arc.h @@ -26,6 +26,14 @@ extern "C" { /********************** * TYPEDEFS **********************/ + +enum { + LV_ARC_TYPE_NORMAL, + LV_ARC_TYPE_SYMMETRIC, + LV_ARC_TYPE_REVERSE +}; +typedef uint8_t lv_arc_type_t; + /*Data of arc*/ typedef struct { /*New data for this type */ @@ -35,14 +43,24 @@ typedef struct { uint16_t bg_angle_start; uint16_t bg_angle_end; lv_style_list_t style_arc; + lv_style_list_t style_knob; /* Style of the knob */ + + int16_t cur_value; /*Current value of the arc*/ + int16_t min_value; /*Minimum value of the arc*/ + int16_t max_value; /*Maximum value of the arc*/ + uint16_t dragging :1; + uint16_t type :2; + uint16_t chg_rate; /*Drag angle rate of change of the arc (degrees/sec)*/ + uint32_t last_tick; /*Last dragging event timestamp of the arc*/ + int16_t last_angle; /*Last dragging angle of the arc*/ } lv_arc_ext_t; /*Parts of the arc*/ enum { LV_ARC_PART_BG = LV_OBJ_PART_MAIN, LV_ARC_PART_INDIC, + LV_ARC_PART_KNOB, _LV_ARC_PART_VIRTUAL_LAST, - _LV_ARC_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST, }; typedef uint8_t lv_arc_part_t; @@ -118,6 +136,45 @@ void lv_arc_set_bg_angles(lv_obj_t * arc, uint16_t start, uint16_t end); */ void lv_arc_set_rotation(lv_obj_t * arc, uint16_t rotation_angle); + +/** + * Set the type of arc. + * @param arc pointer to arc object + * @param type arc type + */ +void lv_arc_set_type(lv_obj_t * arc, lv_arc_type_t type); + +/** + * Set a new value on the arc + * @param arc pointer to a arc object + * @param value new value + */ +void lv_arc_set_value(lv_obj_t * arc, int16_t value); + +/** + * Set minimum and the maximum values of a arc + * @param arc pointer to the arc object + * @param min minimum value + * @param max maximum value + */ +void lv_arc_set_range(lv_obj_t * arc, int16_t min, int16_t max); + +/** + * Reverse arc behavior. The indicator will grow from arc end instead of arc start. + * position. + * @param arc pointer to a arc object + * @param reverse true: enable disable reverse behavior; false: disable + */ +void lv_arc_set_reverse(lv_obj_t * arc, bool reverse); + +/** + * Set the threshold of arc knob increments + * position. + * @param arc pointer to a arc object + * @param threshold increment threshold + */ +void lv_arc_set_chg_rate(lv_obj_t * arc, uint16_t threshold); + /*===================== * Getter functions *====================*/ @@ -150,6 +207,41 @@ uint16_t lv_arc_get_bg_angle_start(lv_obj_t * arc); */ uint16_t lv_arc_get_bg_angle_end(lv_obj_t * arc); +/** + * Get whether the arc is type or not. + * @param arc pointer to a arc object + * @return arc type + */ +lv_arc_type_t lv_arc_get_type(const lv_obj_t * arc); + +/** + * Get the value of the of a arc + * @param arc pointer to a arc object + * @return the value of the of the arc + */ +int16_t lv_arc_get_value(const lv_obj_t * arc); + +/** + * Get the minimum value of a arc + * @param arc pointer to a arc object + * @return the minimum value of the arc + */ +int16_t lv_arc_get_min_value(const lv_obj_t * arc); + +/** + * Get the maximum value of a arc + * @param arc pointer to a arc object + * @return the maximum value of the arc + */ +int16_t lv_arc_get_max_value(const lv_obj_t * arc); + +/** + * Give the arc is being dragged or not + * @param arc pointer to a arc object + * @return true: drag in progress false: not dragged + */ +bool lv_arc_is_dragged(const lv_obj_t * arc); + /*===================== * Other functions *====================*/ diff --git a/src/lv_widgets/lv_rotary.c b/src/lv_widgets/lv_rotary.c deleted file mode 100644 index 92ac3172b..000000000 --- a/src/lv_widgets/lv_rotary.c +++ /dev/null @@ -1,566 +0,0 @@ - -/** - * @file lv_rotary.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_rotary.h" -#if LV_USE_ROTARY != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_core/lv_group.h" -#include "../lv_core/lv_indev.h" -#include "../lv_draw/lv_draw.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_misc/lv_math.h" -#include "lv_img.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_rotary" - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_design_res_t lv_rotary_design(lv_obj_t * rotary, const lv_area_t * clip_area, lv_design_mode_t mode); -static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * param); -static lv_style_list_t * lv_rotary_get_style(lv_obj_t * rotary, uint8_t part); -static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_design_cb_t ancestor_design; -static lv_signal_cb_t ancestor_signal; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a rotary objects - * @param par pointer to an object, it will be the parent of the new rotary - * @param copy pointer to a rotary object, if not NULL then the new object will be copied from it - * @return pointer to the created rotary - */ -lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("rotary create started"); - - /*Create the ancestor rotary*/ - lv_obj_t * rotary = lv_arc_create(par, copy); - LV_ASSERT_MEM(rotary); - if(rotary == NULL) return NULL; - - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(rotary); - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(rotary); - - /*Allocate the rotary type specific extended data*/ - lv_rotary_ext_t * ext = lv_obj_allocate_ext_attr(rotary, sizeof(lv_rotary_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(rotary); - return NULL; - } - - /*Initialize the allocated 'ext' */ - ext->arc.rotation_angle = 0; - ext->arc.bg_angle_start = 135; - ext->arc.bg_angle_end = 45; - ext->arc.arc_angle_start = 135; - ext->arc.arc_angle_end = 270; - ext->type = LV_ROTARY_TYPE_NORMAL; - ext->cur_value = -1; - ext->min_value = 0; - ext->max_value = 100; - ext->sensitivity = 1; - ext->dragging = false; - ext->chg_rate = 540; - ext->last_tick = lv_tick_get(); - ext->last_angle = ext->arc.arc_angle_end; - lv_style_list_init(&ext->style_knob); - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(rotary, lv_rotary_signal); - lv_obj_set_design_cb(rotary, lv_rotary_design); - - /*Init the new rotary rotary*/ - if(copy == NULL) { - lv_obj_set_click(rotary, true); - lv_obj_add_protect(rotary, LV_PROTECT_PRESS_LOST); - lv_obj_set_ext_click_area(rotary, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10, LV_DPI / 10); - lv_rotary_set_value(rotary, 50, LV_ANIM_OFF); - lv_theme_apply(rotary, LV_THEME_ROTARY); - } - /*Copy an existing rotary*/ - else { - lv_rotary_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->type = copy_ext->type; - ext->cur_value = copy_ext->cur_value; - ext->min_value = copy_ext->min_value; - ext->max_value = copy_ext->max_value; - ext->sensitivity = copy_ext->sensitivity; - ext->dragging = copy_ext->dragging; - ext->chg_rate = copy_ext->chg_rate; - ext->last_tick = copy_ext->last_tick; - ext->last_angle = copy_ext->last_angle; - lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); - - lv_obj_refresh_style(rotary, LV_OBJ_PART_ALL); - } - - LV_LOG_INFO("rotary created"); - - return rotary; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the type of rotary. - * @param rotary pointer to rotary object - * @param type rotary type - */ -void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - int16_t val = ext->cur_value; - - ext->type = type; - ext->cur_value = -1; /** Force set_value handling*/ - - int16_t bg_midpoint, bg_end = ext->arc.bg_angle_end; - if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) bg_end = ext->arc.bg_angle_end + 360; - - switch(ext->type) { - case LV_ROTARY_TYPE_SYMMETRIC: - bg_midpoint = (ext->arc.bg_angle_start + bg_end) / 2; - lv_rotary_set_start_angle(rotary, bg_midpoint); - lv_rotary_set_end_angle(rotary, bg_midpoint); - break; - case LV_ROTARY_TYPE_REVERSE: - lv_rotary_set_end_angle(rotary, ext->arc.bg_angle_end); - break; - default: /** LV_ROTARY_TYPE_NORMAL*/ - lv_rotary_set_start_angle(rotary, ext->arc.bg_angle_start); - } - - lv_rotary_set_value(rotary, val, false); -} - -/** - * Set a new value on the rotary - * @param rotary pointer to a rotary object - * @param value new value - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately - */ -bool lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - if(ext->cur_value == value) return false; - - int16_t new_value; - new_value = value > ext->max_value ? ext->max_value : value; - new_value = new_value < ext->min_value ? ext->min_value : new_value; - - if(ext->cur_value == new_value) return false; - ext->cur_value = new_value; - - int16_t bg_midpoint, range_midpoint, bg_end = ext->arc.bg_angle_end; - if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) bg_end = ext->arc.bg_angle_end + 360; - - int16_t angle; - switch(ext->type) { - case LV_ROTARY_TYPE_SYMMETRIC: - bg_midpoint = (ext->arc.bg_angle_start + bg_end) / 2; - range_midpoint = (int32_t)(ext->min_value + ext->max_value) / 2; - - if (ext->cur_value < range_midpoint) { - angle = _lv_map(ext->cur_value, ext->min_value, range_midpoint, ext->arc.bg_angle_start, bg_midpoint); - lv_arc_set_start_angle(rotary, angle); - lv_arc_set_end_angle(rotary, bg_midpoint); - } else { - angle = _lv_map(ext->cur_value, range_midpoint, ext->max_value, bg_midpoint, bg_end); - lv_arc_set_start_angle(rotary, bg_midpoint); - lv_arc_set_end_angle(rotary, angle); - } - break; - case LV_ROTARY_TYPE_REVERSE: - angle = _lv_map(ext->cur_value, ext->min_value, ext->max_value, ext->arc.bg_angle_start, bg_end); - lv_arc_set_start_angle(rotary, angle); - break; - default: /** LV_ROTARY_TYPE_NORMAL*/ - angle = _lv_map(ext->cur_value, ext->min_value, ext->max_value, ext->arc.bg_angle_start, bg_end); - lv_arc_set_end_angle(rotary, angle); - } - ext->last_angle = angle; /*Cache angle for slew rate limiting*/ - - return true; -} - -/** - * Set minimum and the maximum values of a rotary - * @param rotary pointer to the rotary object - * @param min minimum value - * @param max maximum value - */ -void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - if(ext->min_value == min && ext->max_value == max) return; - - ext->min_value = min; - ext->max_value = max; - - if(ext->cur_value < min) { - ext->cur_value = min; - } - if(ext->cur_value > max) { - ext->cur_value = max; - } - - lv_rotary_set_value(rotary, ext->cur_value, false); -} - -/** - * Set the sesitivity of rotary knob increments - * position. - * @param rotary pointer to a rotary object - * @param sensitivity increment multiplier - */ -void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - ext->sensitivity = sensitivity; -} - -/** - * Set the threshold of rotary knob increments - * position. - * @param rotary pointer to a rotary object - * @param threshold increment threshold - */ -void lv_rotary_set_chg_rate(lv_obj_t * rotary, uint16_t rate) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - ext->chg_rate = rate; -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the value of a rotary - * @param rotary pointer to a rotary object - * @return the value of the rotary - */ -int16_t lv_rotary_get_value(const lv_obj_t * rotary) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); - return ext->cur_value; -} - -/** - * Get the minimum value of a rotary - * @param rotary pointer to a rotary object - * @return the minimum value of the rotary - */ -int16_t lv_rotary_get_min_value(const lv_obj_t * rotary) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - return ext->min_value; -} - -/** - * Get the maximum value of a rotary - * @param rotary pointer to a rotary object - * @return the maximum value of the rotary - */ -int16_t lv_rotary_get_max_value(const lv_obj_t * rotary) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t *ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - return ext->max_value; -} - -/** - * Give the rotary is being dragged or not - * @param rotary pointer to a rotary object - * @return true: drag in progress false: not dragged - */ -bool lv_rotary_is_dragged(const lv_obj_t * rotary) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); - return ext->dragging; -} - -/** - * Get whether the rotary is type or not. - * @param rotary pointer to a rotary object - * @return rotary type - */ -lv_rotary_type_t lv_rotary_get_type(const lv_obj_t * rotary) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = (lv_rotary_ext_t *)lv_obj_get_ext_attr(rotary); - return ext->type; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Handle the drawing related tasks of the rotarys - * @param rotary pointer to an object - * @param clip_area the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @param return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_rotary_design(lv_obj_t * rotary, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - /*Return false if the object is not covers the mask_p area*/ - if(mode == LV_DESIGN_COVER_CHK) { - return LV_DESIGN_RES_NOT_COVER; - } - /*Draw the object*/ - else if(mode == LV_DESIGN_DRAW_MAIN) { - /*The ancestor design function will draw the background and the indicator.*/ - ancestor_design(rotary, clip_area, mode); - draw_knob(rotary, clip_area); - } - /*Post draw when the children are drawn*/ - else if(mode == LV_DESIGN_DRAW_POST) { - return ancestor_design(rotary, clip_area, mode); - } - - return LV_DESIGN_RES_OK; -} - -/** - * Signal function of the rotary - * @param rotary pointer to a rotary object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_rotary_signal(lv_obj_t * rotary, lv_signal_t sign, void * param) -{ - lv_res_t res; - - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_rotary_get_style(rotary, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(rotary, sign, param); - } - - /* Include the ancient signal function */ - res = ancestor_signal(rotary, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); - - if(sign == LV_SIGNAL_PRESSING) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev == NULL) return res; - - /*Handle only pointers here*/ - lv_indev_type_t indev_type = lv_indev_get_type(indev); - if(indev_type != LV_INDEV_TYPE_POINTER) return res; - - lv_point_t p; - lv_indev_get_point(indev, &p); - - /*Make point relative to the rotary's center*/ - lv_coord_t w_half = lv_obj_get_width(rotary) / 2; - p.x -= rotary->coords.x1 + w_half; - p.y -= rotary->coords.y1 + w_half; - - /*Enter dragging mode if pressed out of the knob*/ - if(ext->dragging == false) { - lv_coord_t r_in = lv_area_get_width(&ext->knob_area) / 2; - - if(p.x * p.x + p.y * p.y > r_in * r_in) { - ext->dragging = true; - ext->last_tick = lv_tick_get(); /*Capture timestamp at dragging start*/ - } - } - - /*It must be in "dragging" mode to turn the arc*/ - if(ext->dragging == false) return res; - - /*Calculate the angle of the pressed point*/ - int16_t angle; - int16_t bg_end = ext->arc.bg_angle_end; - if (ext->arc.bg_angle_end < ext->arc.bg_angle_start) { - bg_end = ext->arc.bg_angle_end + 360; - } - - angle = 360 - _lv_atan2(p.x, p.y) + 90; /*Some transformation is required*/ - if(angle < ext->arc.bg_angle_start) angle = ext->arc.bg_angle_start; - if(angle > bg_end) angle = bg_end; - - /*Calculate the slew rate limited angle based on change rate (degrees/sec)*/ - int16_t delta_angle = angle - ext->last_angle; - uint32_t delta_tick = lv_tick_elaps(ext->last_tick); - int16_t delta_angle_max = (ext->chg_rate * delta_tick) / 1000; - - if (delta_angle > delta_angle_max) { - delta_angle = delta_angle_max; - } else if (delta_angle < -delta_angle_max) { - delta_angle = -delta_angle_max; - } - - angle = ext->last_angle + delta_angle; /*Apply the limited angle change*/ - - /*Rounding for symmetry*/ - int32_t round = ((bg_end - ext->arc.bg_angle_start) * 8) / (ext->max_value - ext->min_value); - round = (round + 4) >> 4; - angle += round; - - /*Set the new value*/ - int16_t new_value = _lv_map(angle, ext->arc.bg_angle_start, bg_end, ext->min_value, ext->max_value); - if(new_value != lv_rotary_get_value(rotary)) { - ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ - if (lv_rotary_set_value(rotary, new_value, LV_ANIM_OFF)) { /*set_value caches the last_angle for the next interation*/ - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - - /*Don1't let the elapsed time to big while sitting on an end point*/ - if(new_value == ext->min_value || new_value == ext->max_value) { - ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ - } - } - else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { - ext->dragging = false; - -#if LV_USE_GROUP - /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ - lv_group_t * g = lv_obj_get_group(rotary); - bool editing = lv_group_get_editing(g); - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); - if(indev_type == LV_INDEV_TYPE_ENCODER) { - if(editing) lv_group_set_editing(g, false); - } -#endif - - } - else if(sign == LV_SIGNAL_CONTROL) { - char c = *((char *)param); - - if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) + ext->sensitivity, LV_ANIM_ON)) { - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - if (lv_rotary_set_value(rotary, lv_rotary_get_value(rotary) - ext->sensitivity, LV_ANIM_ON)) { - res = lv_event_send(rotary, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - } - else if(sign == LV_SIGNAL_CLEANUP) { - lv_obj_clean_style_list(rotary, LV_ROTARY_PART_KNOB); - } - else if(sign == LV_SIGNAL_GET_EDITABLE) { - bool * editable = (bool *)param; - *editable = true; - } - - return res; -} - - -static lv_style_list_t * lv_rotary_get_style(lv_obj_t * rotary, uint8_t part) -{ - LV_ASSERT_OBJ(rotary, LV_OBJX_NAME); - - lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); - lv_style_list_t * style_dsc_p; - - switch(part) { - case LV_ROTARY_PART_KNOB: - style_dsc_p = &ext->style_knob; - break; - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - -static void draw_knob(lv_obj_t * rotary, const lv_area_t * clip_area) -{ - lv_coord_t left_bg = lv_obj_get_style_pad_left(rotary, LV_ROTARY_PART_BG); - lv_coord_t right_bg = lv_obj_get_style_pad_right(rotary, LV_ROTARY_PART_BG); - lv_coord_t top_bg = lv_obj_get_style_pad_top(rotary, LV_ROTARY_PART_BG); - lv_coord_t bottom_bg = lv_obj_get_style_pad_bottom(rotary, LV_ROTARY_PART_BG); - lv_coord_t r = (LV_MATH_MIN(lv_obj_get_width(rotary) - left_bg - right_bg, - lv_obj_get_height(rotary) - top_bg - bottom_bg)) / 2; - lv_coord_t indic_width = lv_obj_get_style_line_width(rotary, LV_ROTARY_PART_INDIC); - lv_area_t knob_area; - lv_draw_rect_dsc_t knob_rect_dsc; - lv_coord_t center_x = rotary->coords.x1 + r + left_bg; - lv_coord_t center_y = rotary->coords.y1 + r + top_bg; - lv_coord_t knob_inner = lv_obj_get_style_pad_inner(rotary, LV_ROTARY_PART_KNOB); - - lv_rotary_ext_t * ext = lv_obj_get_ext_attr(rotary); - - if(r > 0) { - knob_area.x1 = center_x - r + indic_width + knob_inner; - knob_area.x2 = center_x + r - indic_width - knob_inner; - knob_area.y1 = center_y - r + indic_width + knob_inner; - knob_area.y2 = center_y + r - indic_width - knob_inner; - - lv_draw_rect_dsc_init(&knob_rect_dsc); - lv_obj_init_draw_rect_dsc(rotary, LV_ROTARY_PART_KNOB, &knob_rect_dsc); - - lv_draw_rect(&knob_area, clip_area, &knob_rect_dsc); - } - - lv_area_copy(&ext->knob_area, &knob_area); -} - -#endif diff --git a/src/lv_widgets/lv_rotary.h b/src/lv_widgets/lv_rotary.h deleted file mode 100644 index 81c9bc488..000000000 --- a/src/lv_widgets/lv_rotary.h +++ /dev/null @@ -1,322 +0,0 @@ -/** - * @file lv_rotary.h - * - */ - -#ifndef LV_ROTARY_H -#define LV_ROTARY_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_ROTARY != 0 - -/*Testing of dependencies*/ -#if LV_USE_ARC == 0 -#error "lv_rotary: lv_arc is required. Enable it in lv_conf.h (LV_USE_ARC 1) " -#endif - -#if LV_USE_BTN == 0 -#error "lv_rotary: lv_btn is required. Enable it in lv_conf.h (LV_USE_BTN 1) " -#endif - -#include "../lv_core/lv_obj.h" -#include "lv_arc.h" -#include "lv_btn.h" - -/********************* - * DEFINES - *********************/ - -#define LV_ROTARY_KNOB_SIZE_MIN 4 /* cannot make the knob smaller then this [px] */ - -/********************** - * TYPEDEFS - **********************/ - -enum { - LV_ROTARY_TYPE_NORMAL, - LV_ROTARY_TYPE_SYMMETRIC, - LV_ROTARY_TYPE_REVERSE -}; -typedef uint8_t lv_rotary_type_t; - -/** Possible states of a rotary.*/ -enum { - LV_ROTARY_STATE_RELEASED = LV_BTN_STATE_RELEASED, - LV_ROTARY_STATE_PRESSED = LV_BTN_STATE_PRESSED, - LV_ROTARY_STATE_DISABLED = LV_BTN_STATE_DISABLED, - LV_ROTARY_STATE_CHECKED_RELEASED = LV_BTN_STATE_CHECKED_RELEASED, - LV_ROTARY_STATE_CHECKED_PRESSED = LV_BTN_STATE_CHECKED_PRESSED, - LV_ROTARY_STATE_CHECKED_DISABLED = LV_BTN_STATE_CHECKED_DISABLED, - _LV_ROTARY_STATE_LAST = _LV_BTN_STATE_LAST, /* Number of states*/ -}; -typedef uint8_t lv_rotary_state_t; - -/*Data of rotary*/ -typedef struct { - /*Ext. of ancestor*/ - lv_arc_ext_t arc; - /*New data for this type*/ - lv_style_list_t style_knob; /* Style of the knob */ - lv_area_t knob_area; /* Area of the knob */ - uint16_t type :2; - int16_t cur_value; /*Current value of the rotary*/ - int16_t min_value; /*Minimum value of the rotary*/ - int16_t max_value; /*Maximum value of the rotary*/ - int16_t sensitivity; /*Control signal increment multiplier of the rotary*/ - uint16_t dragging :1; - uint16_t chg_rate; /*Drag angle rate of change of the rotary (degrees/sec)*/ - int32_t last_tick; /*Last dragging event timestamp of the rotary*/ - int16_t last_angle; /*Last dragging angle of the rotary*/ -} lv_rotary_ext_t; - -/** Built-in styles of rotary*/ -enum { - LV_ROTARY_PART_BG = LV_ARC_PART_BG, /** Rotary background style. */ - LV_ROTARY_PART_INDIC = LV_ARC_PART_INDIC, /** Rotary indicator (filled area) style. */ - LV_ROTARY_PART_KNOB = _LV_ARC_PART_VIRTUAL_LAST, /** Rotary knob style. */ - _LV_ROTARY_PART_VIRTUAL_LAST, - _LV_ROTARY_PART_REAL_LAST = _LV_ARC_PART_REAL_LAST -}; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a rotary objects - * @param par pointer to an object, it will be the parent of the new rotary - * @param copy pointer to a rotary object, if not NULL then the new object will be copied from it - * @return pointer to the created rotary - */ -lv_obj_t * lv_rotary_create(lv_obj_t * par, const lv_obj_t * copy); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the type of rotary. - * @param rotary pointer to rotary object - * @param type rotary type - */ -void lv_rotary_set_type(lv_obj_t * rotary, lv_rotary_type_t type); - -/** - * Set a new value on the rotary - * @param rotary pointer to a rotary object - * @param value new value - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately - * @return true if value changed, otw false - */ -bool lv_rotary_set_value(lv_obj_t * rotary, int16_t value, lv_anim_enable_t anim); - -/** - * Set minimum and the maximum values of a rotary - * @param rotary pointer to the rotary object - * @param min minimum value - * @param max maximum value - */ -void lv_rotary_set_range(lv_obj_t * rotary, int16_t min, int16_t max); - -/** - * Reverse rotary behavior. The indicator will grow from arc end instead of arc start. - * position. - * @param rotary pointer to a rotary object - * @param reverse true: enable disable reverse behavior; false: disable - */ -void lv_rotary_set_reverse(lv_obj_t * rotary, bool reverse); - -/** - * Set the sesitivity of rotary knob increments - * position. - * @param rotary pointer to a rotary object - * @param sensitivity increment multiplier - */ -void lv_rotary_set_sensitivity(lv_obj_t * rotary, uint16_t sensitivity); - -/** - * Set the threshold of rotary knob increments - * position. - * @param rotary pointer to a rotary object - * @param threshold increment threshold - */ -void lv_rotary_set_chg_rate(lv_obj_t * rotary, uint16_t threshold); - -/** - * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. - * @param arc pointer to an arc object - * @param start the start angle - */ -static inline void lv_rotary_set_start_angle(lv_obj_t * rotary, uint16_t start) { - lv_arc_set_start_angle(rotary, start); -} - -/** - * Set the start angle of rotary indicator. 0 deg: right, 90 bottom, etc. - * @param rotary pointer to an rotary object - * @param end the end angle - */ -static inline void lv_rotary_set_end_angle(lv_obj_t * rotary, uint16_t end) { - lv_arc_set_end_angle(rotary, end); -} - -/** - * Set the start and end angles - * @param rotary pointer to an rotary object - * @param start the start angle - * @param end the end angle - */ -static inline void lv_rotary_set_angles(lv_obj_t * rotary, uint16_t start, uint16_t end) { - lv_arc_set_angles(rotary, start, end); -} - -/** - * Set the start angle of ar otary indicator background. 0 deg: right, 90 bottom, etc. - * @param rotary pointer to an rotary object - * @param start the start angle - */ -static inline void lv_rotary_set_bg_start_angle(lv_obj_t * rotary, uint16_t start) { - lv_arc_set_bg_start_angle(rotary, start); -} - -/** - * Set the start angle of rotary indicator background. 0 deg: right, 90 bottom etc. - * @param rotary pointer to an rotary object - * @param end the end angle - */ -static inline void lv_rotary_set_bg_end_angle(lv_obj_t * rotary, uint16_t end) { - lv_arc_set_bg_end_angle(rotary, end); -} - -/** - * Set the start and end angles of the rotary indicator background - * @param rotary pointer to an rotary object - * @param start the start angle - * @param end the end angle - */ -static inline void lv_rotary_set_bg_angles(lv_obj_t * rotary, uint16_t start, uint16_t end) { - lv_arc_set_bg_angles(rotary, start, end); -} - -/** - * Set the rotation for the whole rotary indicator - * @param rotary pointer to an rotary object - * @param rotation_angle rotation angle - */ -static inline void lv_rotary_set_rotation(lv_obj_t * rotary, uint16_t rotation_angle) { - lv_arc_set_rotation(rotary, rotation_angle); -} - -/** - * Set the state of the rotary - * @param rotary pointer to a rotary object - * @param state the new state of the rotary (from lv_rotary_state_t enum) - */ -static inline void lv_rotary_set_state(lv_obj_t * rotary, lv_rotary_state_t state) { - lv_btn_set_state(rotary, state); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the start angle of a rotary indicator. - * @param rotary pointer to an rotary object - * @return the start angle [0..360] - */ -static inline uint16_t lv_rotary_get_angle_start(lv_obj_t * rotary) { - return lv_rotary_get_angle_start(rotary); -} - -/** - * Get the end angle of a rotary indicator. - * @param rotary pointer to an rotary object - * @return the end angle [0..360] - */ -static inline uint16_t lv_rotary_get_angle_end(lv_obj_t * rotary) { - return lv_arc_get_angle_end(rotary); -} - -/** - * Get the start angle of a rotary indicator background. - * @param rotary pointer to an rotary object - * @return the start angle [0..360] - */ -static inline uint16_t lv_rotary_get_bg_angle_start(lv_obj_t * rotary) { - return lv_arc_get_bg_angle_start(rotary); -} - -/** - * Get the end angle of a rotary indicator background. - * @param rotary pointer to an rotary object - * @return the end angle [0..360] - */ -static inline uint16_t lv_rotary_get_bg_angle_end(lv_obj_t * rotary) { - return lv_arc_get_bg_angle_end(rotary); -} - -/** - * Get whether the rotary is type or not. - * @param rotary pointer to a rotary object - * @return rotary type - */ -lv_rotary_type_t lv_rotary_get_type(const lv_obj_t * rotary); - -/** - * Get the value of the of a rotary - * @param rotary pointer to a rotary object - * @return the value of the of the rotary - */ -int16_t lv_rotary_get_value(const lv_obj_t * rotary); - -/** - * Get the minimum value of a rotary - * @param rotary pointer to a rotary object - * @return the minimum value of the rotary - */ -int16_t lv_rotary_get_min_value(const lv_obj_t * rotary); - -/** - * Get the maximum value of a rotary - * @param rotary pointer to a rotary object - * @return the maximum value of the rotary - */ -int16_t lv_rotary_get_max_value(const lv_obj_t * rotary); - -/** - * Give the rotary is being dragged or not - * @param rotary pointer to a rotary object - * @return true: drag in progress false: not dragged - */ -bool lv_rotary_is_dragged(const lv_obj_t * rotary); - -/** - * Get the current state of the rotary - * @param rotary pointer to a rotary object - * @return the state of the rotary (from lv_rotary_state_t enum). - * If the rotary is in disabled state `LV_ROTARY_STATE_DISABLED` will be ORed to the other rotary states. - */ -static inline lv_rotary_state_t lv_rotary_get_state(const lv_obj_t * rotary) { - return lv_btn_get_state(rotary); -} - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_rotary*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_ROTARY_H*/ From d95cf0a3d6f808094c08766be34983c60bac0c4c Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 11 Aug 2020 15:03:57 +0200 Subject: [PATCH 95/97] arc: rework knob to indicate the current positoin --- src/lv_core/lv_disp.h | 2 +- src/lv_themes/lv_theme_material.c | 8 ++-- src/lv_widgets/lv_arc.c | 72 +++++++++++++++++++++++++------ 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/lv_core/lv_disp.h b/src/lv_core/lv_disp.h index a0757accf..888a0c093 100644 --- a/src/lv_core/lv_disp.h +++ b/src/lv_core/lv_disp.h @@ -209,7 +209,7 @@ static inline void lv_scr_load(lv_obj_t * scr) * 1 dip is 2 px on a 320 DPI screen * https://stackoverflow.com/questions/2025282/what-is-the-difference-between-px-dip-dp-and-sp */ -#define LV_DPX(n) LV_MATH_MAX((( lv_disp_get_dpi(NULL) * (n) + 80) / 160), 1) /*+80 for rounding*/ +#define LV_DPX(n) (n == 0 ? 0 :LV_MATH_MAX((( lv_disp_get_dpi(NULL) * (n) + 80) / 160), 1)) /*+80 for rounding*/ static inline lv_coord_t lv_dpx(lv_coord_t n) { diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index 85a24c881..a28d69766 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -509,10 +509,10 @@ static void arc_init(void) style_init_reset(&styles->arc_knob); lv_style_set_radius(&styles->arc_knob, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); - lv_style_set_pad_top(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(10)); - lv_style_set_pad_bottom(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(10)); - lv_style_set_pad_left(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(10)); - lv_style_set_pad_right(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(10)); + lv_style_set_pad_top(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(0)); + lv_style_set_pad_bottom(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(0)); + lv_style_set_pad_left(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(0)); + lv_style_set_pad_right(&styles->arc_knob, LV_STATE_DEFAULT, LV_DPX(0)); #endif } diff --git a/src/lv_widgets/lv_arc.c b/src/lv_widgets/lv_arc.c index 8849d3895..58d5df0fc 100644 --- a/src/lv_widgets/lv_arc.c +++ b/src/lv_widgets/lv_arc.c @@ -32,7 +32,9 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param); static lv_style_list_t * lv_arc_get_style(lv_obj_t * arc, uint8_t part); static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle); -static void get_areas(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r, lv_area_t * knob_area); +static void get_center(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r); +static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area); +static bool has_large_knob(lv_obj_t * arc); /********************** * STATIC VARIABLES @@ -631,8 +633,7 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area lv_point_t center; lv_coord_t arc_r; - lv_area_t knob_area; - get_areas(arc, ¢er, &arc_r, &knob_area); + get_center(arc, ¢er, &arc_r); /*Draw the background arc*/ lv_draw_line_dsc_t arc_dsc; @@ -650,16 +651,18 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area lv_coord_t right_indic = lv_obj_get_style_pad_right(arc, LV_ARC_PART_INDIC); lv_coord_t top_indic = lv_obj_get_style_pad_top(arc, LV_ARC_PART_INDIC); lv_coord_t bottom_indic = lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_INDIC); - arc_r -= LV_MATH_MAX4(left_indic, right_indic, top_indic, bottom_indic); + lv_coord_t indic_r = arc_r - LV_MATH_MAX4(left_indic, right_indic, top_indic, bottom_indic); - if(arc_r > 0) { + if(indic_r > 0) { lv_draw_line_dsc_init(&arc_dsc); lv_obj_init_draw_line_dsc(arc, LV_ARC_PART_INDIC, &arc_dsc); - lv_draw_arc(center.x, center.y, arc_r, ext->arc_angle_start + ext->rotation_angle, ext->arc_angle_end + ext->rotation_angle, clip_area, + lv_draw_arc(center.x, center.y, indic_r, ext->arc_angle_start + ext->rotation_angle, ext->arc_angle_end + ext->rotation_angle, clip_area, &arc_dsc); } + lv_area_t knob_area; + get_knob_area(arc, ¢er, arc_r, &knob_area); lv_draw_rect_dsc_t knob_rect_dsc; lv_draw_rect_dsc_init(&knob_rect_dsc); @@ -714,8 +717,7 @@ static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param) /*Make point relative to the arc's center*/ lv_point_t center; lv_coord_t r; - lv_area_t knob_area; - get_areas(arc, ¢er, &r, &knob_area); + get_center(arc, ¢er, &r); p.x -= center.x; p.y -= center.y; @@ -724,6 +726,7 @@ static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param) if(ext->dragging == false) { lv_coord_t indic_width = lv_obj_get_style_line_width(arc, LV_ARC_PART_INDIC); r -= indic_width; + r -= r / 2; /*Add some more sensitive area*/ if(p.x * p.x + p.y * p.y > r * r) { ext->dragging = true; ext->last_tick = lv_tick_get(); /*Capture timestamp at dragging start*/ @@ -849,6 +852,13 @@ static lv_style_list_t * lv_arc_get_style(lv_obj_t * arc, uint8_t part) static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle) { + /* If the knob is large it's much harder to find which area to invalidate. + * For simplicity invalidate the whole arc in this case*/ + if(has_large_knob(arc)) { + lv_obj_invalidate(arc); + return; + } + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); start_angle += ext->rotation_angle; @@ -953,7 +963,7 @@ static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angl } -static void get_areas(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r, lv_area_t * knob_area) +static void get_center(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r) { lv_coord_t left_bg = lv_obj_get_style_pad_left(arc, LV_ARC_PART_BG); lv_coord_t right_bg = lv_obj_get_style_pad_right(arc, LV_ARC_PART_BG); @@ -970,17 +980,53 @@ static void get_areas(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r, l lv_coord_t indic_width = lv_obj_get_style_line_width(arc, LV_ARC_PART_INDIC); r -= indic_width; +} + +static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area) +{ + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); + + lv_coord_t indic_width = lv_obj_get_style_line_width(arc, LV_ARC_PART_INDIC); + lv_coord_t indic_width_half = indic_width / 2; + r -= indic_width_half; + + uint16_t angle = ext->rotation_angle; + if(ext->type == LV_ARC_TYPE_NORMAL) { + angle += ext->arc_angle_end; + } else if(ext->type == LV_ARC_TYPE_REVERSE) { + angle += ext->arc_angle_start; + } else if(ext->type == LV_ARC_TYPE_SYMMETRIC) { + int32_t range_midpoint = (int32_t)(ext->min_value + ext->max_value) / 2; + if(ext->cur_value < range_midpoint) angle += ext->arc_angle_start; + else angle += ext->arc_angle_end; + } + lv_coord_t knob_x = (r * _lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; + lv_coord_t knob_y = (r * _lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; lv_coord_t left_knob = lv_obj_get_style_pad_left(arc, LV_ARC_PART_KNOB); lv_coord_t right_knob = lv_obj_get_style_pad_right(arc, LV_ARC_PART_KNOB); lv_coord_t top_knob = lv_obj_get_style_pad_top(arc, LV_ARC_PART_KNOB); lv_coord_t bottom_knob = lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_KNOB); - knob_area->x1 = center->x - r + left_knob; - knob_area->x2 = center->x + r - right_knob; - knob_area->y1 = center->y - r + top_knob; - knob_area->y2 = center->y + r - bottom_knob; + knob_area->x1 = center->x + knob_x - left_knob - indic_width_half; + knob_area->x2 = center->x + knob_x + right_knob + indic_width_half; + knob_area->y1 = center->y + knob_y - top_knob - indic_width_half; + knob_area->y2 = center->y + knob_y + bottom_knob + indic_width_half; } +static bool has_large_knob(lv_obj_t * arc) +{ + if(lv_obj_get_style_pad_left(arc, LV_ARC_PART_KNOB) > 0) return true; + if(lv_obj_get_style_pad_right(arc, LV_ARC_PART_KNOB) > 0) return true; + if(lv_obj_get_style_pad_top(arc, LV_ARC_PART_KNOB) > 0) return true; + if(lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_KNOB) > 0) return true; + if(lv_obj_get_style_shadow_width(arc, LV_ARC_PART_KNOB) > 0) return true; + if(lv_obj_get_style_shadow_ofs_x(arc, LV_ARC_PART_KNOB) > 0) return true; + if(lv_obj_get_style_shadow_ofs_y(arc, LV_ARC_PART_KNOB) > 0) return true; + if(lv_obj_get_style_outline_width(arc, LV_ARC_PART_KNOB) > 0) return true; + if(lv_obj_get_style_value_str(arc, LV_ARC_PART_KNOB) != NULL) return true; + + return false; +} #endif From cfee7e8b8aab211e35242ba9a676c16d1e23ade9 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 13 Aug 2020 11:03:04 +0200 Subject: [PATCH 96/97] arc knob invalidation fix --- src/lv_widgets/lv_arc.c | 74 ++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/src/lv_widgets/lv_arc.c b/src/lv_widgets/lv_arc.c index 58d5df0fc..d9d1b2383 100644 --- a/src/lv_widgets/lv_arc.c +++ b/src/lv_widgets/lv_arc.c @@ -31,10 +31,9 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param); static lv_style_list_t * lv_arc_get_style(lv_obj_t * arc, uint8_t part); -static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle); +static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle, lv_arc_part_t part); static void get_center(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r); static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area); -static bool has_large_knob(lv_obj_t * arc); /********************** * STATIC VARIABLES @@ -166,11 +165,11 @@ void lv_arc_set_start_angle(lv_obj_t * arc, uint16_t start) } /*Only a smaller incremental move*/ else if(ext->arc_angle_start > ext->arc_angle_end && start > ext->arc_angle_end) { - inv_arc_area(arc, LV_MATH_MIN(ext->arc_angle_start, start), LV_MATH_MAX(ext->arc_angle_start, start)); + inv_arc_area(arc, LV_MATH_MIN(ext->arc_angle_start, start), LV_MATH_MAX(ext->arc_angle_start, start), LV_ARC_PART_INDIC); } /*Only a smaller incremental move*/ else if(ext->arc_angle_start < ext->arc_angle_end && start < ext->arc_angle_end) { - inv_arc_area(arc, LV_MATH_MIN(ext->arc_angle_start, start), LV_MATH_MAX(ext->arc_angle_start, start)); + inv_arc_area(arc, LV_MATH_MIN(ext->arc_angle_start, start), LV_MATH_MAX(ext->arc_angle_start, start), LV_ARC_PART_INDIC); } /*Crossing the start angle makes the whole arc change*/ else { @@ -199,11 +198,11 @@ void lv_arc_set_end_angle(lv_obj_t * arc, uint16_t end) } /*Only a smaller incremental move*/ else if(ext->arc_angle_end > ext->arc_angle_start && end > ext->arc_angle_start) { - inv_arc_area(arc, LV_MATH_MIN(ext->arc_angle_end, end), LV_MATH_MAX(ext->arc_angle_end, end)); + inv_arc_area(arc, LV_MATH_MIN(ext->arc_angle_end, end), LV_MATH_MAX(ext->arc_angle_end, end), LV_ARC_PART_INDIC); } /*Only a smaller incremental move*/ else if(ext->arc_angle_end < ext->arc_angle_start && end < ext->arc_angle_start) { - inv_arc_area(arc, LV_MATH_MIN(ext->arc_angle_end, end), LV_MATH_MAX(ext->arc_angle_end, end)); + inv_arc_area(arc, LV_MATH_MIN(ext->arc_angle_end, end), LV_MATH_MAX(ext->arc_angle_end, end), LV_ARC_PART_INDIC); } /*Crossing the end angle makes the whole arc change*/ else { @@ -229,12 +228,12 @@ void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end) if(start > 360) start -= 360; if(end > (start + 360)) end = start + 360; - inv_arc_area(arc, ext->arc_angle_start, ext->arc_angle_end); + inv_arc_area(arc, ext->arc_angle_start, ext->arc_angle_end, LV_ARC_PART_INDIC); ext->arc_angle_start = start; ext->arc_angle_end = end; - inv_arc_area(arc, ext->arc_angle_start, ext->arc_angle_end); + inv_arc_area(arc, ext->arc_angle_start, ext->arc_angle_end, LV_ARC_PART_INDIC); } /** @@ -256,11 +255,11 @@ void lv_arc_set_bg_start_angle(lv_obj_t * arc, uint16_t start) } /*Only a smaller incremental move*/ else if(ext->bg_angle_start > ext->bg_angle_end && start > ext->bg_angle_end) { - inv_arc_area(arc, LV_MATH_MIN(ext->bg_angle_start, start), LV_MATH_MAX(ext->bg_angle_start, start)); + inv_arc_area(arc, LV_MATH_MIN(ext->bg_angle_start, start), LV_MATH_MAX(ext->bg_angle_start, start), LV_ARC_PART_BG); } /*Only a smaller incremental move*/ else if(ext->bg_angle_start < ext->bg_angle_end && start < ext->bg_angle_end) { - inv_arc_area(arc, LV_MATH_MIN(ext->bg_angle_start, start), LV_MATH_MAX(ext->bg_angle_start, start)); + inv_arc_area(arc, LV_MATH_MIN(ext->bg_angle_start, start), LV_MATH_MAX(ext->bg_angle_start, start), LV_ARC_PART_BG); } /*Crossing the start angle makes the whole arc change*/ else { @@ -289,11 +288,11 @@ void lv_arc_set_bg_end_angle(lv_obj_t * arc, uint16_t end) } /*Only a smaller incremental move*/ else if(ext->bg_angle_end > ext->bg_angle_start && end > ext->bg_angle_start) { - inv_arc_area(arc, LV_MATH_MIN(ext->bg_angle_end, end), LV_MATH_MAX(ext->bg_angle_end, end)); + inv_arc_area(arc, LV_MATH_MIN(ext->bg_angle_end, end), LV_MATH_MAX(ext->bg_angle_end, end), LV_ARC_PART_BG); } /*Only a smaller incremental move*/ else if(ext->bg_angle_end < ext->bg_angle_start && end < ext->bg_angle_start) { - inv_arc_area(arc, LV_MATH_MIN(ext->bg_angle_end, end), LV_MATH_MAX(ext->bg_angle_end, end)); + inv_arc_area(arc, LV_MATH_MIN(ext->bg_angle_end, end), LV_MATH_MAX(ext->bg_angle_end, end), LV_ARC_PART_BG); } /*Crossing the end angle makes the whole arc change*/ else { @@ -318,12 +317,12 @@ void lv_arc_set_bg_angles(lv_obj_t * arc, uint16_t start, uint16_t end) if(start > 360) start -= 360; if(end > (start + 360)) end = start + 360; - inv_arc_area(arc, ext->bg_angle_start, ext->bg_angle_end); + inv_arc_area(arc, ext->bg_angle_start, ext->bg_angle_end, LV_ARC_PART_BG); ext->bg_angle_start = start; ext->bg_angle_end = end; - inv_arc_area(arc, ext->bg_angle_start, ext->bg_angle_end); + inv_arc_area(arc, ext->bg_angle_start, ext->bg_angle_end, LV_ARC_PART_BG); } /** @@ -850,15 +849,8 @@ static lv_style_list_t * lv_arc_get_style(lv_obj_t * arc, uint8_t part) return style_dsc_p; } -static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle) +static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle, lv_arc_part_t part) { - /* If the knob is large it's much harder to find which area to invalidate. - * For simplicity invalidate the whole arc in this case*/ - if(has_large_knob(arc)) { - lv_obj_invalidate(arc); - return; - } - lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); start_angle += ext->rotation_angle; @@ -877,10 +869,26 @@ static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angl lv_coord_t rout = (LV_MATH_MIN(lv_obj_get_width(arc) - left - right, lv_obj_get_height(arc) - top - bottom)) / 2; lv_coord_t x = arc->coords.x1 + rout + left; lv_coord_t y = arc->coords.y1 + rout + top; - lv_style_int_t w = lv_obj_get_style_line_width(arc, LV_ARC_PART_INDIC); - lv_style_int_t rounded = lv_obj_get_style_line_rounded(arc, LV_ARC_PART_INDIC); + lv_style_int_t w = lv_obj_get_style_line_width(arc, part); + lv_style_int_t rounded = lv_obj_get_style_line_rounded(arc, part); lv_coord_t rin = rout - w; - lv_coord_t extra_area = rounded ? w / 2 + 2 : 0; + lv_coord_t extra_area = 0; + + extra_area = rounded ? w / 2 + 2 : 0; + + if(part == LV_ARC_PART_INDIC && lv_style_list_get_style(&ext->style_knob, 0) != NULL) { + lv_coord_t knob_extra_size = lv_obj_get_draw_rect_ext_pad_size(arc, LV_ARC_PART_KNOB); + + lv_coord_t knob_left = lv_obj_get_style_pad_left(arc, LV_ARC_PART_KNOB); + lv_coord_t knob_right = lv_obj_get_style_pad_right(arc, LV_ARC_PART_KNOB); + lv_coord_t knob_top = lv_obj_get_style_pad_top(arc, LV_ARC_PART_KNOB); + lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_KNOB); + + knob_extra_size += LV_MATH_MAX4(knob_left, knob_right, knob_top, knob_bottom); + + extra_area = LV_MATH_MAX(extra_area, w / 2 + 2 + knob_extra_size); + + } lv_area_t inv_area; @@ -962,7 +970,6 @@ static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angl } } - static void get_center(lv_obj_t * arc, lv_point_t * center, lv_coord_t * arc_r) { lv_coord_t left_bg = lv_obj_get_style_pad_left(arc, LV_ARC_PART_BG); @@ -1014,19 +1021,4 @@ static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t knob_area->y2 = center->y + knob_y + bottom_knob + indic_width_half; } -static bool has_large_knob(lv_obj_t * arc) -{ - if(lv_obj_get_style_pad_left(arc, LV_ARC_PART_KNOB) > 0) return true; - if(lv_obj_get_style_pad_right(arc, LV_ARC_PART_KNOB) > 0) return true; - if(lv_obj_get_style_pad_top(arc, LV_ARC_PART_KNOB) > 0) return true; - if(lv_obj_get_style_pad_bottom(arc, LV_ARC_PART_KNOB) > 0) return true; - if(lv_obj_get_style_shadow_width(arc, LV_ARC_PART_KNOB) > 0) return true; - if(lv_obj_get_style_shadow_ofs_x(arc, LV_ARC_PART_KNOB) > 0) return true; - if(lv_obj_get_style_shadow_ofs_y(arc, LV_ARC_PART_KNOB) > 0) return true; - if(lv_obj_get_style_outline_width(arc, LV_ARC_PART_KNOB) > 0) return true; - if(lv_obj_get_style_value_str(arc, LV_ARC_PART_KNOB) != NULL) return true; - - return false; -} - #endif From c2b5979e91f6015f51ec0cdf1b5061482f0dfc42 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 13 Aug 2020 12:00:57 +0200 Subject: [PATCH 97/97] arc: fix event sending --- src/lv_widgets/lv_arc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lv_widgets/lv_arc.c b/src/lv_widgets/lv_arc.c index d9d1b2383..fad51e7a5 100644 --- a/src/lv_widgets/lv_arc.c +++ b/src/lv_widgets/lv_arc.c @@ -765,11 +765,12 @@ static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param) angle += round; /*Set the new value*/ + int16_t old_value = ext->cur_value; int16_t new_value = _lv_map(angle, ext->bg_angle_start, bg_end, ext->min_value, ext->max_value); if(new_value != lv_arc_get_value(arc)) { ext->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ lv_arc_set_value(arc, new_value); /*set_value caches the last_angle for the next iteration*/ - if(new_value != ext->cur_value) { + if(new_value != old_value) { res = lv_event_send(arc, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; }