diff --git a/lv_core/lv_group.c b/lv_core/lv_group.c index 7ada31e55..a6f911dc2 100644 --- a/lv_core/lv_group.c +++ b/lv_core/lv_group.c @@ -50,6 +50,9 @@ lv_group_t * lv_group_create(void) group->obj_focus = NULL; group->frozen = 0; group->focus_cb = NULL; + group->click_focus = 1; + group->edit_mode_en = 0; + group->editing = 0; return group; } @@ -141,6 +144,7 @@ void lv_group_focus_obj(lv_obj_t * obj) lv_obj_t ** i; LL_READ(g->obj_ll, i) { if(*i == obj) { + if(g->obj_focus == i) return; /*Don't focus the already focused object again*/ if(g->obj_focus != NULL) { (*g->obj_focus)->signal_func(*g->obj_focus, LV_SIGNAL_DEFOCUS, NULL); lv_obj_invalidate(*g->obj_focus); @@ -150,6 +154,7 @@ void lv_group_focus_obj(lv_obj_t * obj) if(g->obj_focus != NULL) { (*g->obj_focus)->signal_func(*g->obj_focus, LV_SIGNAL_FOCUS, NULL); + if(g->focus_cb) g->focus_cb(g); lv_obj_invalidate(*g->obj_focus); } break; @@ -295,6 +300,16 @@ void lv_group_set_editing(lv_group_t * group, bool edit) group->editing = edit ? 1 : 0; } +/** + * Set the `click_focus` attribute. If enabled then the object will be focused then it is clicked. + * @param group pointer to group + * @param en: true: enable `click_focus` + */ +void lv_group_set_click_focus(lv_group_t * group, bool en) +{ + group->click_focus = en ? 1 : 0; +} + /** * Modify a style with the set 'style_mod' function. The input style remains unchanged. * @param group pointer to group @@ -322,7 +337,7 @@ lv_style_t * lv_group_mod_style(lv_group_t * group, const lv_style_t * style) */ lv_obj_t * lv_group_get_focused(lv_group_t * group) { - if(group == NULL) return NULL; + if(!group) return NULL; if(group->obj_focus == NULL) return NULL; return *group->obj_focus; @@ -335,6 +350,7 @@ lv_obj_t * lv_group_get_focused(lv_group_t * group) */ lv_group_style_mod_func_t lv_group_get_style_mod_cb(lv_group_t * group) { + if(!group) return false; return group->style_mod ; } @@ -345,6 +361,7 @@ lv_group_style_mod_func_t lv_group_get_style_mod_cb(lv_group_t * group) */ lv_group_style_mod_func_t lv_group_get_style_mod_edit_cb(lv_group_t * group) { + if(!group) return false; return group->style_mod_edit; } @@ -355,6 +372,7 @@ lv_group_style_mod_func_t lv_group_get_style_mod_edit_cb(lv_group_t * group) */ lv_group_focus_cb_t lv_group_get_focus_cb(lv_group_t * group) { + if(!group) return false; return group->focus_cb; } @@ -365,9 +383,21 @@ lv_group_focus_cb_t lv_group_get_focus_cb(lv_group_t * group) */ bool lv_group_get_editing(lv_group_t * group) { + if(!group) return false; return group->editing ? true : false; } +/** + * Get the `click_focus` attribute. + * @param group pointer to group + * @return true: `click_focus` is enabled; false: disabled + */ +bool lv_group_get_click_focus(lv_group_t * group) +{ + if(!group) return false; + return group->click_focus ? true : false; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lv_core/lv_group.h b/lv_core/lv_group.h index fbe3e9556..d5828bb56 100644 --- a/lv_core/lv_group.h +++ b/lv_core/lv_group.h @@ -52,9 +52,10 @@ typedef struct _lv_group_t lv_group_style_mod_func_t style_mod_edit;/*A function which modifies the style of the focused object*/ 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 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; /********************** @@ -152,12 +153,19 @@ void lv_group_set_edit_enable(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_enabel`. + * 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 */ void lv_group_set_editing(lv_group_t * group, bool edit); +/** + * Set the `click_focus` attribute. If enabled then the object will be focused then it is clicked. + * @param group pointer to group + * @param en: true: enable `click_focus` + */ +void lv_group_set_click_focus(lv_group_t * group, bool en); + /** * Modify a style with the set 'style_mod' function. The input style remains unchanged. * @param group pointer to group @@ -200,6 +208,15 @@ lv_group_focus_cb_t lv_group_get_focus_cb(lv_group_t * group); * @return true: edit mode; false: navigate mode */ bool lv_group_get_editing(lv_group_t * group); + +/** + * Get the `click_focus` attribute. + * @param group pointer to group + * @return true: `click_focus` is enabled; false: disabled + */ +bool lv_group_get_click_focus(lv_group_t * group); + + /********************** * MACROS **********************/ diff --git a/lv_core/lv_indev.c b/lv_core/lv_indev.c index f0279df42..756b906d5 100644 --- a/lv_core/lv_indev.c +++ b/lv_core/lv_indev.c @@ -542,6 +542,23 @@ static void indev_proc_release(lv_indev_proc_t * proc) /*Forgot the act obj and send a released signal */ if(proc->act_obj != NULL) { proc->act_obj->signal_func(proc->act_obj, LV_SIGNAL_RELEASED, indev_act); + + /*Handle click focus*/ +#if USE_LV_GROUP + lv_group_t * g = lv_obj_get_group(proc->act_obj); + lv_obj_t * parent = proc->act_obj; + while(g == NULL) { + parent = lv_obj_get_parent(parent); + if(parent == NULL) break; + g = lv_obj_get_group(parent); + } + + if(g != NULL && parent != NULL) + if(lv_group_get_click_focus(g)) { + lv_group_focus_obj(parent); + } +#endif + if(proc->reset_query != 0) return; proc->act_obj = NULL; proc->pr_timestamp = 0; diff --git a/lv_draw/lv_draw_line.c b/lv_draw/lv_draw_line.c index f84250aeb..0a2e0dea8 100644 --- a/lv_draw/lv_draw_line.c +++ b/lv_draw/lv_draw_line.c @@ -219,7 +219,6 @@ static void line_draw_skew(line_draw_t * main_line, const lv_area_t * mask, cons vect_norm.x = vect_norm.x << 4; vect_norm.y = vect_norm.y << 4; - printf("width %d\n", width); #if LV_COMPILER_VLA_SUPPORTED lv_point_t pattern[width_safe]; #else diff --git a/lv_objx/lv_btnm.c b/lv_objx/lv_btnm.c index da82be8c8..ad98475fc 100644 --- a/lv_objx/lv_btnm.c +++ b/lv_objx/lv_btnm.c @@ -569,7 +569,17 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param) ext->btn_id_tgl = ext->btn_id_pr; } + + +#if USE_LV_GROUP + /*Leave the clicked button as pressed if this the focused object in a group*/ + lv_group_t * g = lv_obj_get_group(btnm); + if(lv_group_get_focused(g) != btnm) { + ext->btn_id_pr = LV_BTNM_PR_NONE; + } +#else ext->btn_id_pr = LV_BTNM_PR_NONE; +#endif } } else if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_DEFOCUS) { ext->btn_id_pr = LV_BTNM_PR_NONE; diff --git a/lv_objx/lv_list.c b/lv_objx/lv_list.c index 1c6c5917f..20a385bbe 100644 --- a/lv_objx/lv_list.c +++ b/lv_objx/lv_list.c @@ -532,14 +532,14 @@ static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param) btn = get_next_btn(list, btn); } if(btn_prev != NULL) { - lv_btn_set_state(btn_prev, LV_BTN_STATE_TGL_REL); + lv_btn_set_state(btn_prev, LV_BTN_STATE_PR); } } else if(sign == LV_SIGNAL_DEFOCUS) { /*Get the 'pressed' button*/ lv_obj_t * btn = NULL; btn = get_next_btn(list, btn); while(btn != NULL) { - if(lv_btn_get_state(btn) == LV_BTN_STATE_TGL_REL) break; + if(lv_btn_get_state(btn) == LV_BTN_STATE_PR) break; btn = get_next_btn(list, btn); } @@ -555,40 +555,58 @@ static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param) lv_list_ext_t * ext = lv_obj_get_ext_attr(list); btn = get_next_btn(list, btn); while(btn != NULL) { - if(lv_btn_get_state(btn) == LV_BTN_STATE_TGL_REL) break; + if(lv_btn_get_state(btn) == LV_BTN_STATE_PR) break; btn_prev = btn; btn = get_next_btn(list, btn); } + /*If there is a valid "pressed" button the make the next "pressed"*/ if(btn_prev != NULL && btn != NULL) { lv_btn_set_state(btn, LV_BTN_STATE_REL); - lv_btn_set_state(btn_prev, LV_BTN_STATE_TGL_REL); + lv_btn_set_state(btn_prev, LV_BTN_STATE_PR); lv_page_focus(list, btn_prev, ext->anim_time); } + /*If there is no "pressed" button the make the first "pressed"*/ + else { + btn = get_next_btn(list, NULL); + if(btn) { /*If there are no buttons on the list hen there is no first button*/ + lv_btn_set_state(btn, LV_BTN_STATE_PR); + lv_page_focus(list, btn, ext->anim_time); + } + } } else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_UP) { /*Get the last pressed button*/ lv_obj_t * btn = NULL; lv_list_ext_t * ext = lv_obj_get_ext_attr(list); btn = get_next_btn(list, btn); while(btn != NULL) { - if(lv_btn_get_state(btn) == LV_BTN_STATE_TGL_REL) break; + if(lv_btn_get_state(btn) == LV_BTN_STATE_PR) break; btn = get_next_btn(list, btn); } + /*If there is a valid "pressed" button the make the next "pressed"*/ if(btn != NULL) { - lv_obj_t * btn_prev = get_next_btn(list, btn); - if(btn_prev != NULL) { + lv_obj_t * btn_next = get_next_btn(list, btn); + if(btn_next != NULL) { lv_btn_set_state(btn, LV_BTN_STATE_REL); - lv_btn_set_state(btn_prev, LV_BTN_STATE_TGL_REL); - lv_page_focus(list, btn_prev, ext->anim_time); + lv_btn_set_state(btn_next, LV_BTN_STATE_PR); + lv_page_focus(list, btn_next, ext->anim_time); } } + /*If there is no "pressed" button the make the first "pressed"*/ + else { + btn = get_next_btn(list, NULL); + if(btn) { /*If there are no buttons on the list hen there is no first button*/ + lv_btn_set_state(btn, LV_BTN_STATE_PR); + lv_page_focus(list, btn, ext->anim_time); + } + } } else if(c == LV_GROUP_KEY_ENTER) { /*Get the 'pressed' button*/ lv_obj_t * btn = NULL; btn = get_next_btn(list, btn); while(btn != NULL) { - if(lv_btn_get_state(btn) == LV_BTN_STATE_TGL_REL) break; + if(lv_btn_get_state(btn) == LV_BTN_STATE_PR) break; btn = get_next_btn(list, btn); } diff --git a/lv_objx/lv_page.c b/lv_objx/lv_page.c index 18081d910..8e966f9f4 100644 --- a/lv_objx/lv_page.c +++ b/lv_objx/lv_page.c @@ -73,6 +73,7 @@ lv_obj_t * lv_page_create(lv_obj_t * par, lv_obj_t * copy) ext->sb.ver_draw = 0; ext->sb.style = &lv_style_pretty; ext->sb.mode = LV_SB_MODE_AUTO; + ext->arrow_scroll = 0; /*Init the new page object*/ if(copy == NULL) { @@ -117,6 +118,8 @@ lv_obj_t * lv_page_create(lv_obj_t * par, lv_obj_t * copy) lv_page_set_pr_action(new_page, copy_ext->pr_action); lv_page_set_rel_action(new_page, copy_ext->rel_action); lv_page_set_sb_mode(new_page, copy_ext->sb.mode); + lv_page_set_arrow_scroll(new_page, copy_ext->arrow_scroll); + lv_page_set_style(new_page, LV_PAGE_STYLE_BG, lv_page_get_style(copy, LV_PAGE_STYLE_BG)); lv_page_set_style(new_page, LV_PAGE_STYLE_SCRL, lv_page_get_style(copy, LV_PAGE_STYLE_SCRL)); @@ -175,7 +178,7 @@ void lv_page_set_pr_action(lv_obj_t * page, lv_action_t pr_action) /** * Set the scroll bar mode on a page * @param page pointer to a page object - * @param sb.mode the new mode from 'lv_page_sb.mode_t' enum + * @param sb_mode the new mode from 'lv_page_sb.mode_t' enum */ void lv_page_set_sb_mode(lv_obj_t * page, lv_sb_mode_t sb_mode) { @@ -189,6 +192,17 @@ void lv_page_set_sb_mode(lv_obj_t * page, lv_sb_mode_t sb_mode) lv_obj_invalidate(page); } +/** + * Enable/Disable scrolling with arrows if the page is in group (arrows: LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN) + * @param page pointer to a page object + * @param en true: enable scrolling with arrows + */ +void lv_page_set_arrow_scroll(lv_obj_t * page, bool en) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + ext->arrow_scroll = en ? 1 : 0; +} + /** * Set a style of a page * @param page pointer to a page object @@ -244,6 +258,17 @@ lv_sb_mode_t lv_page_get_sb_mode(lv_obj_t * page) return ext->sb.mode; } +/** + * Get the the scrolling with arrows (LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN) is enabled or not + * @param page pointer to a page object + * @return true: scrolling with arrows is enabled + */ +bool lv_page_get_arrow_scroll(lv_obj_t * page, bool en) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + return ext->arrow_scroll ? true : false; +} + /** * Get a style of a page * @param page pointer to page object @@ -538,12 +563,13 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) } else if(sign == LV_SIGNAL_CONTROLL) { uint32_t c = *((uint32_t *) param); lv_obj_t * scrl = lv_page_get_scrl(page); - if(c == LV_GROUP_KEY_DOWN || c == LV_GROUP_KEY_RIGHT) { + + if((c == LV_GROUP_KEY_DOWN || c == LV_GROUP_KEY_RIGHT) && ext->arrow_scroll) { #if USE_LV_ANIMATION lv_anim_t a; a.var = scrl; a.start = lv_obj_get_y(scrl); - a.end = a.start - LV_DPI / 2; + a.end = a.start - lv_obj_get_height(page) / 4; a.fp = (lv_anim_fp_t)lv_obj_set_y; a.path = lv_anim_path_linear; a.end_cb = NULL; @@ -555,15 +581,15 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) a.repeat_pause = 0; lv_anim_create(&a); #else - lv_obj_set_y(scrl, lv_obj_get_y(scrl) - LV_DPI / 2); + lv_obj_set_y(scrl, lv_obj_get_y(scrl) - lv_obj_get_height(page) / 4); #endif - } else if(c == LV_GROUP_KEY_UP || c == LV_GROUP_KEY_LEFT) { + } else if((c == LV_GROUP_KEY_UP || c == LV_GROUP_KEY_LEFT) && ext->arrow_scroll) { #if USE_LV_ANIMATION lv_anim_t a; a.var = scrl; a.start = lv_obj_get_y(scrl); - a.end = a.start + LV_DPI / 2; + a.end = a.start + lv_obj_get_height(page) / 4; a.fp = (lv_anim_fp_t)lv_obj_set_y; a.path = lv_anim_path_linear; a.end_cb = NULL; @@ -575,7 +601,7 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) a.repeat_pause = 0; lv_anim_create(&a); #else - lv_obj_set_y(scrl, lv_obj_get_y(scrl) - LV_DPI / 2); + lv_obj_set_y(scrl, lv_obj_get_y(scrl) + lv_obj_get_height(page) / 4); #endif } } else if(sign == LV_SIGNAL_GET_TYPE) { diff --git a/lv_objx/lv_page.h b/lv_objx/lv_page.h index f6c746516..afd89aae1 100644 --- a/lv_objx/lv_page.h +++ b/lv_objx/lv_page.h @@ -62,6 +62,7 @@ typedef struct uint8_t ver_draw :1; /*1: vertical scrollbar is visible now (Handled by the library)*/ uint8_t mode :3; /*Scrollbar visibility from 'lv_page_sb_mode_t'*/ } sb; + uint8_t arrow_scroll :1; /*1: Enable scrolling with LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN*/ } lv_page_ext_t; typedef enum { @@ -118,10 +119,17 @@ void lv_page_set_pr_action(lv_obj_t * page, lv_action_t pr_action); /** * Set the scroll bar mode on a page * @param page pointer to a page object - * @param sb.mode the new mode from 'lv_page_sb.mode_t' enum + * @param sb_mode the new mode from 'lv_page_sb.mode_t' enum */ void lv_page_set_sb_mode(lv_obj_t * page, lv_sb_mode_t sb_mode); +/** + * Enable/Disable scrolling with arrows if the page is in group (arrows: LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN) + * @param page pointer to a page object + * @param en true: enable scrolling with arrows + */ +void lv_page_set_arrow_scroll(lv_obj_t * page, bool en); + /** * Set the fit attribute of the scrollable part of a page. * It means it can set its size automatically to involve all children. @@ -185,6 +193,14 @@ void lv_page_set_style(lv_obj_t *page, lv_page_style_t type, lv_style_t *style); */ lv_sb_mode_t lv_page_get_sb_mode(lv_obj_t * page); + +/** + * Get the the scrolling with arrows (LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN) is enabled or not + * @param page pointer to a page object + * @return true: scrolling with arrows is enabled + */ +bool lv_page_get_arrow_scroll(lv_obj_t * page, bool en); + /** * Get width of the scrollable part of a page * @param page pointer to a page object