From d3af29fada2b00fce47ec68168e4ef980bea1bef Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 24 Sep 2018 22:59:48 +0200 Subject: [PATCH] LV_INDEV_TYPE_ENCODER added --- lv_core/lv_group.c | 26 ------- lv_core/lv_group.h | 20 ------ lv_core/lv_indev.c | 154 ++++++++++++++++++++++++++++-------------- lv_hal/lv_hal_indev.h | 2 + lv_objx/lv_ddlist.c | 39 ++++++++--- lv_objx/lv_roller.c | 30 +++++--- lv_objx/lv_slider.c | 11 ++- 7 files changed, 168 insertions(+), 114 deletions(-) diff --git a/lv_core/lv_group.c b/lv_core/lv_group.c index 7d4910aa2..1ac1fd7b3 100644 --- a/lv_core/lv_group.c +++ b/lv_core/lv_group.c @@ -53,7 +53,6 @@ lv_group_t * lv_group_create(void) group->frozen = 0; group->focus_cb = NULL; group->click_focus = 1; - group->edit_mode_en = 0; group->editing = 0; return group; @@ -288,23 +287,8 @@ void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb) group->focus_cb = focus_cb; } -/** - * Enable the switching between edit and navigate mode on long press of LV_GROUP_KEY_ENTER. - * User can get the current mode and decide the whether to send - * LV_GROUP_KEY_PREV/NEXT or LV_GROUP_KEY_LEFT/RIGHT on left/right button. - * useful if there is only one encoder to navigate, - * (push: ENTER; long push: mode switch; left/right: focus or edit) - * @param group pointer to group - * @param en true or false to enable or disable this feature. - */ -void lv_group_enable_edit(lv_group_t * group, bool en) -{ - group->edit_mode_en = en ? 1 : 0; -} - /** * Manually set the current mode (edit or navigate). - * Edit mode needs to be enabled with `lv_group_set_edit_enabel`. * @param group pointer to group * @param edit: true: edit mode; false: navigate mode */ @@ -389,16 +373,6 @@ lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group) return group->focus_cb; } -/** - * Get the edit mode is enabled or not. - * @param group pointer to group - * @return true editing is enabled - */ -bool lv_group_get_edit_enable(const lv_group_t * group) -{ - return group->edit_mode_en ? true : false; -} - /** * Get the current mode (edit or navigate). * @param group pointer to group diff --git a/lv_core/lv_group.h b/lv_core/lv_group.h index f60d6536c..265384b90 100644 --- a/lv_core/lv_group.h +++ b/lv_core/lv_group.h @@ -54,7 +54,6 @@ typedef struct _lv_group_t lv_group_focus_cb_t focus_cb; /*A function to call when a new object is focused (optional)*/ lv_style_t style_tmp; /*Stores the modified style of the focused object */ uint8_t frozen :1; /*1: can't focus to new object*/ - uint8_t edit_mode_en :1; /*1: By the long press of `LV_GROP_KEY_ENTER` the object can go to edit mode*/ uint8_t editing :1; /*1: Edit mode, 0: Navigate mode*/ uint8_t click_focus :1; /*1: If an object in a group is clicked by an indev then it will be focused */ } lv_group_t; @@ -141,20 +140,8 @@ void lv_group_set_style_mod_edit_cb(lv_group_t * group, lv_group_style_mod_func_ */ void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb); -/** - * Enable the switching between edit and navigate mode on long press of LV_GROUP_KEY_ENTER. - * User can get the current mode and decide the whether to send - * LV_GROUP_KEY_PREV/NEXT or LV_GROUP_KEY_LEFT/RIGHT on left/right button. - * useful if there is only one encoder to navigate, - * (push: ENTER; long push: mode switch; left/right: focus or edit) - * @param group pointer to group - * @param en true or false to enable or disable this feature. - */ -void lv_group_enable_edit(lv_group_t * group, bool en); - /** * Manually set the current mode (edit or navigate). - * Edit mode needs to be enabled with `lv_group_set_edit_enable`. * @param group pointer to group * @param edit: true: edit mode; false: navigate mode */ @@ -203,13 +190,6 @@ lv_group_style_mod_func_t lv_group_get_style_mod_edit_cb(const lv_group_t * grou */ lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group); -/** - * Get the edit mode is enabled or not. - * @param group pointer to group - * @return true editing is enabled - */ -bool lv_group_get_edit_enable(const lv_group_t * group); - /** * Get the current mode (edit or navigate). * @param group pointer to group diff --git a/lv_core/lv_indev.c b/lv_core/lv_indev.c index 568fd22db..200749c9b 100644 --- a/lv_core/lv_indev.c +++ b/lv_core/lv_indev.c @@ -32,6 +32,7 @@ static void indev_proc_task(void * param); static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data); +static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_proc_press(lv_indev_proc_t * proc); static void indev_proc_release(lv_indev_proc_t * proc); @@ -150,7 +151,7 @@ void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj) */ void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group) { - if(indev->driver.type == LV_INDEV_TYPE_KEYPAD) indev->group = group; + if(indev->driver.type == LV_INDEV_TYPE_KEYPAD || indev->driver.type == LV_INDEV_TYPE_ENCODER) indev->group = group; } #endif @@ -294,6 +295,8 @@ static void indev_proc_task(void * param) indev_pointer_proc(i, &data); } else if(i->driver.type == LV_INDEV_TYPE_KEYPAD) { indev_keypad_proc(i, &data); + } else if(i->driver.type == LV_INDEV_TYPE_ENCODER) { + indev_encoder_proc(i, &data); } else if(i->driver.type == LV_INDEV_TYPE_BUTTON) { indev_button_proc(i, &data); } @@ -368,19 +371,7 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) { /*On enter long press leave edit mode.*/ lv_obj_t * focused = lv_group_get_focused(i->group); - bool editable = false; - focused->signal_func(focused, LV_SIGNAL_GET_EDITABLE, &editable); - - if (i->group->edit_mode_en && editable) { - i->group->editing = i->group->editing ? 0 : 1; - focused->signal_func(focused, LV_SIGNAL_FOCUS, NULL); /*Focus again. Some object do something on navigate->edit change*/ - LV_LOG_INFO("Edit mode changed (navigate)"); - if(focused) lv_obj_invalidate(focused); - } - /*If edit mode is disabled just send a long press signal*/ - else { - focused->signal_func(focused, LV_SIGNAL_LONG_PRESS, indev_act); - } + focused->signal_func(focused, LV_SIGNAL_LONG_PRESS, indev_act); i->proc.long_pr_sent = 1; } } @@ -389,50 +380,19 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) /*The user might clear the key when it was released. Always release the pressed key*/ data->key = i->proc.last_key; - if((data->key == LV_GROUP_KEY_NEXT) || - ((i->group->edit_mode_en && i->group->editing == 0) && - (data->key == LV_GROUP_KEY_RIGHT || data->key == LV_GROUP_KEY_DOWN))) + if(data->key == LV_GROUP_KEY_NEXT) { lv_group_focus_next(i->group); } - else if((data->key == LV_GROUP_KEY_PREV) || - ((i->group->edit_mode_en && i->group->editing == 0) && - (data->key == LV_GROUP_KEY_LEFT || data->key == LV_GROUP_KEY_UP))) + else if(data->key == LV_GROUP_KEY_PREV) { lv_group_focus_prev(i->group); } else if(data->key == LV_GROUP_KEY_ENTER) { - lv_obj_t * focused = lv_group_get_focused(i->group); - bool editable = false; - focused->signal_func(focused, LV_SIGNAL_GET_EDITABLE, &editable); - - /*Enter was released on a normal or non-editable object. Just send enter*/ - if (i->group->edit_mode_en == 0 || editable == 0) { - lv_group_send_data(i->group, data->key); - } - /*An editable object (e.g. button matrix) is being edited and enter released*/ - else if (i->group->editing) { - if(!i->proc.long_pr_sent) lv_group_send_data(i->group, data->key); /*Ignore long pressed enter release because it comes from mode switch*/ - } - /*If the focused object is editable and now in navigate mode then enter edit mode*/ - else if(i->group->edit_mode_en && editable && !i->group->editing && !i->proc.long_pr_sent) { - i->group->editing = i->group->editing ? 0 : 1; - focused->signal_func(focused, LV_SIGNAL_FOCUS, NULL); /*Focus again. Some object do something on navigate->edit change*/ - LV_LOG_INFO("Edit mode changed (edit)"); - if(focused) lv_obj_invalidate(focused); - } -// else if (){ -// lv_group_send_data(i->group, data->key); -// } - - - -// /* If an ENTER is released but not long pressed and we are in edit mode or the object is not editable then send the ENTER -// * In navigate mode to editable objects and after releasing the long press to change mode do not send ENTER*/ -// if(!i->proc.long_pr_sent && (i->group->editing || !editable)) { -// lv_group_send_data(i->group, data->key); -// } + if (!i->proc.long_pr_sent) { + lv_group_send_data(i->group, data->key); + } } else { lv_group_send_data(i->group, data->key); } @@ -448,6 +408,100 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) #endif } +/** + * Process a new point from LV_INDEV_TYPE_ENCODER input device + * @param i pointer to an input device + * @param data pointer to the data read from the input device + */ +static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) +{ +#if USE_LV_GROUP + if(i->group == NULL) return; + + /*Process the steps first. They are valid only with released button*/ + if(data->state == LV_INDEV_STATE_REL) { + lv_obj_t * focused = lv_group_get_focused(i->group); + bool editable = false; + focused->signal_func(focused, LV_SIGNAL_GET_EDITABLE, &editable); + /*In edit mode send LEFT/RIGHT keys*/ + if(lv_group_get_editing(i->group)) { + uint32_t s; + if(data->enc_diff < 0) { + for(s = 0; s < -data->enc_diff; s++) lv_group_send_data(i->group, LV_GROUP_KEY_LEFT); + } else if(data->enc_diff > 0) { + for(s = 0; s < data->enc_diff; s++) lv_group_send_data(i->group, LV_GROUP_KEY_RIGHT); + } + } + /*In navigate mode focus on the next/prev objects*/ + else {uint32_t s; + if(data->enc_diff < 0) { + for(s = 0; s < -data->enc_diff; s++) lv_group_focus_prev(i->group); + } else if(data->enc_diff > 0) { + for(s = 0; s < data->enc_diff; s++) lv_group_focus_next(i->group); + } + } + } + + /*Key press happened*/ + if(data->state == LV_INDEV_STATE_PR && + i->proc.last_state == LV_INDEV_STATE_REL) { + i->proc.pr_timestamp = lv_tick_get(); + } + /*Pressing*/ + else if(data->state == LV_INDEV_STATE_PR && i->proc.last_state == LV_INDEV_STATE_PR) { + if(i->proc.long_pr_sent == 0 && + lv_tick_elaps(i->proc.pr_timestamp) > LV_INDEV_LONG_PRESS_TIME ) + { + /*On enter long press leave edit mode.*/ + lv_obj_t * focused = lv_group_get_focused(i->group); + bool editable = false; + focused->signal_func(focused, LV_SIGNAL_GET_EDITABLE, &editable); + + if (editable) { + i->group->editing = i->group->editing ? 0 : 1; + focused->signal_func(focused, LV_SIGNAL_FOCUS, NULL); /*Focus again. Some object do something on navigate->edit change*/ + LV_LOG_INFO("Edit mode changed"); + if(focused) lv_obj_invalidate(focused); + } + /*If not editable then just send a long press signal*/ + else { + focused->signal_func(focused, LV_SIGNAL_LONG_PRESS, indev_act); + } + i->proc.long_pr_sent = 1; + } + } + /*Release happened*/ + else if(data->state == LV_INDEV_STATE_REL && i->proc.last_state == LV_INDEV_STATE_PR) { + lv_obj_t * focused = lv_group_get_focused(i->group); + bool editable = false; + focused->signal_func(focused, LV_SIGNAL_GET_EDITABLE, &editable); + + /*The button was released on a non-editable object. Just send enter*/ + if (!editable) { + lv_group_send_data(i->group, LV_GROUP_KEY_ENTER); + } + /*An object is being edited and the button is releases. Just send enter */ + else if (i->group->editing) { + if(!i->proc.long_pr_sent) lv_group_send_data(i->group, LV_GROUP_KEY_ENTER); /*Ignore long pressed enter release because it comes from mode switch*/ + } + /*If the focused object is editable and now in navigate mode then enter edit mode*/ + else if(editable && !i->group->editing && !i->proc.long_pr_sent) { + i->group->editing = i->group->editing ? 0 : 1; + focused->signal_func(focused, LV_SIGNAL_FOCUS, NULL); /*Focus again. Some object do something on navigate->edit change*/ + LV_LOG_INFO("Edit mode changed (edit)"); + if(focused) lv_obj_invalidate(focused); + } + + if(i->proc.reset_query) return; /*The object might be deleted in `focus_cb` or due to any other user event*/ + + i->proc.pr_timestamp = 0; + i->proc.long_pr_sent = 0; + } + + i->proc.last_state = data->state; + i->proc.last_key = data->key; +#endif +} /** * Process new points from a input device. indev->state.pressed has to be set diff --git a/lv_hal/lv_hal_indev.h b/lv_hal/lv_hal_indev.h index 43bef354a..c16c55e15 100644 --- a/lv_hal/lv_hal_indev.h +++ b/lv_hal/lv_hal_indev.h @@ -34,6 +34,7 @@ enum { LV_INDEV_TYPE_POINTER, /*Touch pad, mouse, external button*/ LV_INDEV_TYPE_KEYPAD, /*Keypad or keyboard*/ LV_INDEV_TYPE_BUTTON, /*External (hardware button) which is assinged to a specific point of the screen*/ + LV_INDEV_TYPE_ENCODER, /*Encoder with only Left, Right turn and a Button*/ }; typedef uint8_t lv_hal_indev_type_t; @@ -50,6 +51,7 @@ typedef struct { lv_point_t point; /*For LV_INDEV_TYPE_POINTER the currently pressed point*/ uint32_t key; /*For LV_INDEV_TYPE_KEYPAD the currently pressed key*/ uint32_t btn; /*For LV_INDEV_TYPE_BUTTON the currently pressed button*/ + int16_t enc_diff; /*For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/ }; void *user_data; /*'lv_indev_drv_t.priv' for this driver*/ lv_indev_state_t state; /*LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/ diff --git a/lv_objx/lv_ddlist.c b/lv_objx/lv_ddlist.c index a3936b0c9..1091cd671 100644 --- a/lv_objx/lv_ddlist.c +++ b/lv_objx/lv_ddlist.c @@ -526,19 +526,36 @@ static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_CLEANUP) { ext->label = NULL; } else if(sign == LV_SIGNAL_FOCUS) { - - /*Open the list if editing*/ lv_group_t * g = lv_obj_get_group(ddlist); - bool editing = true; - if(lv_group_get_edit_enable(g)) editing = lv_group_get_editing(g); + bool editing = lv_group_get_editing(g); + lv_hal_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); - if(ext->opened == false && editing) { - ext->opened = true; - lv_ddlist_refr_size(ddlist, true); - ext->sel_opt_id_ori = ext->sel_opt_id; + /*Encoders need special handling*/ + if(indev_type == LV_INDEV_TYPE_ENCODER) { + /*Open the list if editing*/ + if(editing) { + ext->opened = true; + ext->sel_opt_id_ori = ext->sel_opt_id; + lv_ddlist_refr_size(ddlist, true); + } + /*Close the lift if navigating*/ + else { + ext->opened = false; + ext->sel_opt_id = ext->sel_opt_id_ori; + lv_ddlist_refr_size(ddlist, true); + + } + } + else { + /*Open the list if closed*/ + if(!ext->opened) { + ext->opened = true; + ext->sel_opt_id_ori = ext->sel_opt_id; /*Save the current value. Used to revert this state if ENER wont't be pressed*/ + lv_ddlist_refr_size(ddlist, true); + } } } else if(sign == LV_SIGNAL_DEFOCUS) { - if(ext->opened != false) { + if(ext->opened) { ext->opened = false; ext->sel_opt_id = ext->sel_opt_id_ori; lv_ddlist_refr_size(ddlist, true); @@ -571,6 +588,10 @@ static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * par ext->sel_opt_id_ori = ext->sel_opt_id; ext->opened = 0; if(ext->action) ext->action(ddlist); + + lv_group_t * g = lv_obj_get_group(ddlist); + bool editing = lv_group_get_editing(g); + if(editing) lv_group_set_editing(g, false); /*In edit mode go to navigate mode if an option is selected*/ } else { ext->opened = 1; } diff --git a/lv_objx/lv_roller.c b/lv_objx/lv_roller.c index fc7f3dd59..64b55202e 100644 --- a/lv_objx/lv_roller.c +++ b/lv_objx/lv_roller.c @@ -316,17 +316,27 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par } } else if(sign == LV_SIGNAL_FOCUS) { lv_group_t * g = lv_obj_get_group(roller); - bool editing = true; - if(lv_group_get_edit_enable(g)) editing = lv_group_get_editing(g); + bool editing = lv_group_get_editing(g); + lv_hal_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); - if(editing) ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; - else { - /*Revert the original state. Important when moving from edit->navigate mode*/ - if(ext->ddlist.sel_opt_id != ext->ddlist.sel_opt_id_ori) { - ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id_ori; - refr_position(roller, true); + /*Encoders need special handling*/ + if(indev_type == LV_INDEV_TYPE_ENCODER) { + /*In navigate mode revert the original value*/ + if(!editing) { + if(ext->ddlist.sel_opt_id != ext->ddlist.sel_opt_id_ori) { + ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id_ori; + refr_position(roller, true); + } } + /*Save the current state when entered to edit mode*/ + else { + ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; + } + } else { + ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; /*Save the current value. Used to revert this state if ENER wont't be pressed*/ + } + } else if(sign == LV_SIGNAL_DEFOCUS) { /*Revert the original state*/ if(ext->ddlist.sel_opt_id != ext->ddlist.sel_opt_id_ori) { @@ -347,6 +357,10 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par } else if(c == LV_GROUP_KEY_ENTER) { if(ext->ddlist.action) ext->ddlist.action(roller); ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; /*Set the entered value as default*/ + + lv_group_t * g = lv_obj_get_group(roller); + bool editing = lv_group_get_editing(g); + if(editing) lv_group_set_editing(g, false); /*In edit mode go to navigate mode if an option is selected*/ } } else if(sign == LV_SIGNAL_GET_TYPE) { lv_obj_type_t * buf = param; diff --git a/lv_objx/lv_slider.c b/lv_objx/lv_slider.c index 143d83568..e5e37c8bb 100644 --- a/lv_objx/lv_slider.c +++ b/lv_objx/lv_slider.c @@ -486,7 +486,16 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par } } else if(sign == LV_SIGNAL_CONTROLL) { char c = *((char *)param); - if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_UP || c == LV_GROUP_KEY_ENTER) { + lv_group_t * g = lv_obj_get_group(slider); + bool editing = lv_group_get_editing(g); + lv_hal_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + + /*Encoders need special handling*/ + if(indev_type == LV_INDEV_TYPE_ENCODER && c == LV_GROUP_KEY_ENTER) { + if(editing) lv_group_set_editing(g, false); + } + + if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_UP) { lv_slider_set_value(slider, lv_slider_get_value(slider) + 1); if(ext->action != NULL) ext->action(slider); } else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_DOWN) {