diff --git a/.github/ISSUE_TEMPLATE/all-other-issues.md b/.github/ISSUE_TEMPLATE/all-other-issues.md new file mode 100644 index 0000000000..b3f7a35e06 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/all-other-issues.md @@ -0,0 +1,14 @@ +--- +name: All other issues +about: Questions and enhancement requests should go to the forum. +title: '' +labels: stale +assignees: '' + +--- + +# All enhancement requests or questions should be directed to the Forum. + + +We use GitHub issues for development related discussions. +Please use the [forum](https://forum.littlevgl.com/) to ask questions. diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000000..db2b0be8c3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** + +A clear and concise description of what the bug is. + +**To Reproduce** + +Please provide a small, independent code sample that can be used to reproduce the issue. Ideally this should work in the PC simulator unless the problem is specific to one platform. + +**Expected behavior** + +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** + +Add any other context about the problem here. diff --git a/README.md b/README.md index 66ef90a676..d7d19c9997 100644 --- a/README.md +++ b/README.md @@ -126,11 +126,7 @@ bool my_touchpad_read(lv_indev_t * indev, lv_indev_data_t * data) return false; /*Return `false` because we are not buffering and no more data to read*/ } ``` -<<<<<<< HEAD -6. Call `lv_task_handler()` periodically every few milliseconds in the main `while(1)` loop, in a Timer interrupt or in an Operation system task. -======= 6. Call `lv_task_handler()` periodically every few milliseconds in the main `while(1)` loop, in Timer interrupt or in an Operation system task. It will redraw the screen if required, handle input devices etc. ->>>>>>> master For a detailed description check the [Documentation](https://docs.littlevgl.com/#Porting) or the [Porting examples](https://github.com/littlevgl/lvgl/tree/multi-disp/lv_porting). diff --git a/porting/lv_port_disp_template.c b/porting/lv_port_disp_template.c index 7fdfa79bc0..1f45027209 100644 --- a/porting/lv_port_disp_template.c +++ b/porting/lv_port_disp_template.c @@ -24,7 +24,7 @@ **********************/ static void disp_init(void); -static void disp_flush(lv_disp_t * disp, const lv_area_t * area, lv_color_t * color_p); +static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); #if LV_USE_GPU static void mem_blend(lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa); static void mem_fill(lv_color_t * dest, uint32_t length, lv_color_t color); @@ -135,7 +135,7 @@ static void disp_init(void) /* Flush the content of the internal buffer the specific area on the display * You can use DMA or any hardware acceleration to do this operation in the background but * 'lv_disp_flush_ready()' has to be called when finished. */ -static void disp_flush(lv_disp_t * disp, const lv_area_t * area, lv_color_t * color_p) +static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/ diff --git a/porting/lv_port_indev_template.c b/porting/lv_port_indev_template.c index 98fe79b1de..2e243190f8 100644 --- a/porting/lv_port_indev_template.c +++ b/porting/lv_port_indev_template.c @@ -24,25 +24,25 @@ **********************/ static void touchpad_init(void); -static bool touchpad_read(lv_indev_t * indev, lv_indev_data_t * data); +static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); static bool touchpad_is_pressed(void); static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y); static void mouse_init(void); -static bool mouse_read(lv_indev_t * indev, lv_indev_data_t * data); +static bool mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); static bool mouse_is_pressed(void); static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y); static void keypad_init(void); -static bool keypad_read(lv_indev_t * indev, lv_indev_data_t * data); +static bool keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); static uint32_t keypad_get_key(void); static void encoder_init(void); -static bool encoder_read(lv_indev_t * indev, lv_indev_data_t * data); +static bool encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); static void encoder_handler(void); static void button_init(void); -static bool button_read(lv_indev_t * indev, lv_indev_data_t * data); +static bool button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); static int8_t button_get_pressed_id(void); static bool button_is_pressed(uint8_t id); @@ -187,7 +187,7 @@ static void touchpad_init(void) } /* Will be called by the library to read the touchpad */ -static bool touchpad_read(lv_indev_t * indev, lv_indev_data_t * data) +static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { static lv_coord_t last_x = 0; static lv_coord_t last_y = 0; @@ -237,7 +237,7 @@ static void mouse_init(void) } /* Will be called by the library to read the mouse */ -static bool mouse_read(lv_indev_t * indev, lv_indev_data_t * data) +static bool mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { /*Get the current x and y coordinates*/ mouse_get_xy(&data->point.x, &data->point.y); @@ -281,7 +281,7 @@ static void keypad_init(void) } /* Will be called by the library to read the mouse */ -static bool keypad_read(lv_indev_t * indev, lv_indev_data_t * data) +static bool keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { static uint32_t last_key = 0; @@ -342,7 +342,7 @@ static void encoder_init(void) } /* Will be called by the library to read the encoder */ -static bool encoder_read(lv_indev_t * indev, lv_indev_data_t * data) +static bool encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { data->enc_diff = encoder_diff; @@ -373,7 +373,7 @@ static void button_init(void) } /* Will be called by the library to read the button */ -static bool button_read(lv_indev_t * indev, lv_indev_data_t * data) +static bool button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { static uint8_t last_btn = 0; diff --git a/src/lv_objx/lv_btnm.c b/src/lv_objx/lv_btnm.c index a37eea9f9e..1594cf7818 100644 --- a/src/lv_objx/lv_btnm.c +++ b/src/lv_objx/lv_btnm.c @@ -39,6 +39,7 @@ static uint16_t get_button_from_point(lv_obj_t * btnm, lv_point_t * p); static void allocate_btn_areas_and_controls(const lv_obj_t * btnm, const char ** map); static void invalidate_button_area(const lv_obj_t * btnm, uint16_t btn_idx); static bool maps_are_identical(const char ** map1, const char ** map2); +static void make_one_button_toggled(lv_obj_t *btnm, uint16_t btn_idx); /********************** * STATIC VARIABLES @@ -87,6 +88,7 @@ lv_obj_t * lv_btnm_create(lv_obj_t * par, const lv_obj_t * copy) ext->ctrl_bits = NULL; ext->map_p = NULL; ext->recolor = 0; + ext->one_toggle = 0; ext->styles_btn[LV_BTN_STATE_REL] = &lv_style_btn_rel; ext->styles_btn[LV_BTN_STATE_PR] = &lv_style_btn_pr; ext->styles_btn[LV_BTN_STATE_TGL_REL] = &lv_style_btn_tgl_rel; @@ -401,6 +403,19 @@ void lv_btnm_set_btn_width(const lv_obj_t * btnm, uint16_t btn_id, uint8_t width lv_btnm_set_map(btnm, ext->map_p); } +/** + * Make the button matrix like a selector widget (only one button may be toggled at a time). + * @param btnm Button matrix object + * @param one_toggle Whether "one toggle" mode is enabled + */ +void lv_btnm_set_one_toggle(lv_obj_t *btnm, bool one_toggle) { + lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm); + ext->one_toggle = one_toggle; + + /*If more than one button is toggled only the first one should be*/ + make_one_button_toggled(btnm, 0); +} + /*===================== * Getter functions *====================*/ @@ -549,6 +564,17 @@ lv_style_t * lv_btnm_get_style(const lv_obj_t * btnm, lv_btnm_style_t type) return style; } +/** + * Find whether "one toggle" mode is enabled. + * @param btnm Button matrix object + * @return whether "one toggle" mode is enabled + */ +bool lv_btnm_get_one_toggle(const lv_obj_t *btnm) { + lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm); + + return ext->one_toggle; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -739,6 +765,8 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param) } else { ext->ctrl_bits[ext->btn_id_pr] |= LV_BTNM_CTRL_TGL_STATE; } + if(ext->one_toggle) + make_one_button_toggled(btnm, ext->btn_id_pr); } /*Invalidate to old pressed area*/; @@ -1034,5 +1062,21 @@ static bool maps_are_identical(const char ** map1, const char ** map2) return map1[i][0] == '\0' && map2[i][0] == '\0'; } +/** + * Enforces a single button being toggled on the button matrix. + * It simply clears the toggle flag on other buttons. + * @param btnm Button matrix object + * @param btn_idx Button that should remain toggled + */ +static void make_one_button_toggled(lv_obj_t *btnm, uint16_t btn_idx) +{ + /*Save whether the button was toggled*/ + bool was_toggled = lv_btnm_get_btn_ctrl(btnm, btn_idx, LV_BTNM_CTRL_TGL_STATE); + + lv_btnm_set_btn_ctrl_all(btnm, LV_BTNM_CTRL_TGL_STATE, false); + + if(was_toggled) + lv_btnm_set_btn_ctrl(btnm, btn_idx, LV_BTNM_CTRL_TGL_STATE, true); +} #endif diff --git a/src/lv_objx/lv_btnm.h b/src/lv_objx/lv_btnm.h index 6cdc8f3fd3..edadc03c7d 100644 --- a/src/lv_objx/lv_btnm.h +++ b/src/lv_objx/lv_btnm.h @@ -60,6 +60,7 @@ typedef struct uint16_t btn_id_pr; /*Index of the currently pressed button or LV_BTNM_BTN_NONE*/ uint16_t btn_id_act; /*Index of the active button (being pressed/released etc) or LV_BTNM_BTN_NONE */ uint8_t recolor :1; /*Enable button recoloring*/ + uint8_t one_toggle :1; /*Single button toggled at once*/ } lv_btnm_ext_t; enum { @@ -166,6 +167,12 @@ void lv_btnm_set_btn_ctrl_all(lv_obj_t * btnm, lv_btnm_ctrl_t ctrl, bool en); */ void lv_btnm_set_btn_width(const lv_obj_t * btnm, uint16_t btn_id, uint8_t width); +/** + * Make the button matrix like a selector widget (only one button may be toggled at a time). + * @param btnm Button matrix object + * @param one_toggle Whether "one toggle" mode is enabled + */ +void lv_btnm_set_one_toggle(lv_obj_t *btnm, bool one_toggle); /*===================== * Getter functions @@ -233,6 +240,13 @@ bool lv_btnm_get_btn_ctrl(lv_obj_t * btnm, uint16_t btn_id, lv_btnm_ctrl_t ctrl) * @return style pointer to a style */ lv_style_t * lv_btnm_get_style(const lv_obj_t * btnm, lv_btnm_style_t type); + +/** + * Find whether "one toggle" mode is enabled. + * @param btnm Button matrix object + * @return whether "one toggle" mode is enabled + */ +bool lv_btnm_get_one_toggle(const lv_obj_t *btnm); /********************** * MACROS **********************/ diff --git a/src/lv_objx/lv_chart.c b/src/lv_objx/lv_chart.c index 43b7cf1d6a..92f545d533 100644 --- a/src/lv_objx/lv_chart.c +++ b/src/lv_objx/lv_chart.c @@ -566,6 +566,7 @@ static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_ if(ext->type & LV_CHART_TYPE_POINT) lv_chart_draw_points(chart, mask); if(ext->type & LV_CHART_TYPE_VERTICAL_LINE) lv_chart_draw_vertical_lines(chart, mask); if(ext->type & LV_CHART_TYPE_AREA) lv_chart_draw_areas(chart, mask); + lv_chart_draw_axes(chart, mask); } return true; @@ -623,8 +624,8 @@ static void lv_chart_draw_div(lv_obj_t * chart, const lv_area_t * mask) uint8_t div_i_start; lv_point_t p1; lv_point_t p2; - lv_coord_t w = lv_obj_get_width(chart); - lv_coord_t h = lv_obj_get_height(chart); + lv_coord_t w = lv_obj_get_width(chart) - 1; + lv_coord_t h = lv_obj_get_height(chart) - 1; lv_coord_t x_ofs = chart->coords.x1; lv_coord_t y_ofs = chart->coords.y1; diff --git a/src/lv_objx/lv_ddlist.c b/src/lv_objx/lv_ddlist.c index 205272aa8a..23c43dc62f 100644 --- a/src/lv_objx/lv_ddlist.c +++ b/src/lv_objx/lv_ddlist.c @@ -44,6 +44,8 @@ static lv_res_t lv_ddlist_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * static lv_res_t release_handler(lv_obj_t * ddlist); static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en); static void lv_ddlist_pos_current_option(lv_obj_t * ddlist); +static void lv_ddlist_anim_cb(lv_obj_t * ddlist); +static void lv_ddlist_adjust_height(lv_obj_t * ddlist, int32_t height); /********************** * STATIC VARIABLES @@ -523,7 +525,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist); lv_opa_t opa_scale = lv_obj_get_opa_scale(ddlist); /*If the list is opened draw a rectangle under the selected item*/ - if(ext->opened != 0) { + if(ext->opened != 0 || ext->force_sel) { lv_style_t * style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG); const lv_font_t * font = style->text.font; lv_coord_t font_h = lv_font_get_height(font); @@ -548,7 +550,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig lv_opa_t opa_scale = lv_obj_get_opa_scale(ddlist); /*Redraw only in opened state*/ - if(ext->opened) { + if(ext->opened || ext->force_sel) { lv_style_t * style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG); const lv_font_t * font = style->text.font; lv_coord_t font_h = lv_font_get_height(font); @@ -785,7 +787,6 @@ static lv_res_t release_handler(lv_obj_t * ddlist) if(lv_indev_get_type(indev) == LV_INDEV_TYPE_POINTER || lv_indev_get_type(indev) == LV_INDEV_TYPE_BUTTON) { lv_point_t p; lv_indev_get_point(indev, &p); - p.x -= ext->label->coords.x1; p.y -= ext->label->coords.y1; uint16_t letter_i; letter_i = lv_label_get_letter_on(ext->label, &p); @@ -801,6 +802,7 @@ static lv_res_t release_handler(lv_obj_t * ddlist) } ext->sel_opt_id = new_opt; + printf("rid: %d\n", new_opt); } ext->sel_opt_id_ori = ext->sel_opt_id; @@ -839,7 +841,6 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en) style->body.padding.top + style->body.padding.bottom; else new_height = ext->fix_height; - lv_page_set_sb_mode(ddlist, LV_SB_MODE_UNHIDE); } else { /*Close the list*/ const lv_font_t * font = style->text.font; lv_style_t * label_style = lv_obj_get_style(ext->label); @@ -852,6 +853,7 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en) if(anim_en == 0) { lv_obj_set_height(ddlist, new_height); lv_ddlist_pos_current_option(ddlist); + if(ext->opened) lv_page_set_sb_mode(ddlist, LV_SB_MODE_UNHIDE); #if LV_USE_ANIMATION lv_anim_del(ddlist, (lv_anim_fp_t)lv_obj_set_height); /*If an animation is in progress then it will overwrite this changes*/ } else { @@ -859,9 +861,9 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en) a.var = ddlist; a.start = lv_obj_get_height(ddlist); a.end = new_height; - a.fp = (lv_anim_fp_t)lv_obj_set_height; + a.fp = (lv_anim_fp_t)lv_ddlist_adjust_height; a.path = lv_anim_path_linear; - a.end_cb = (lv_anim_cb_t)lv_ddlist_pos_current_option; + a.end_cb = (lv_anim_cb_t)lv_ddlist_anim_cb; a.act_time = 0; a.time = ext->anim_time; a.playback = 0; @@ -869,11 +871,38 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en) a.repeat = 0; a.repeat_pause = 0; + ext->force_sel = 1; /*Keep the list item selected*/ lv_anim_create(&a); #endif } } +/** + * Position the list and remove the selection highlight if it's closed. + * Called at end of list animation. + * @param ddlist pointer to a drop down list + */ +static void lv_ddlist_anim_cb(lv_obj_t * ddlist) { + lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist); + + lv_ddlist_pos_current_option(ddlist); + + ext->force_sel = 0; /*Turn off drawing of selection*/ + + if(ext->opened) lv_page_set_sb_mode(ddlist, LV_SB_MODE_UNHIDE); +} + +/** + * Adjusts the ddlist's height and then positions the option within it's new height. + * This keeps the option visible during animation. + * @param ddlist Drop down list object + * @param height New drop down list height + */ +static void lv_ddlist_adjust_height(lv_obj_t * ddlist, int32_t height) { + lv_obj_set_height(ddlist, height); + lv_ddlist_pos_current_option(ddlist); +} + /** * Set the position of list when it is closed to show the selected item * @param ddlist pointer to a drop down list diff --git a/src/lv_objx/lv_ddlist.h b/src/lv_objx/lv_ddlist.h index 5a516a9329..799df11e54 100644 --- a/src/lv_objx/lv_ddlist.h +++ b/src/lv_objx/lv_ddlist.h @@ -53,6 +53,7 @@ typedef struct uint16_t sel_opt_id_ori; /*Store the original index on focus*/ uint16_t anim_time; /*Open/Close animation time [ms]*/ uint8_t opened :1; /*1: The list is opened (handled by the library)*/ + uint8_t force_sel :1; /*1: Keep the selection highlight even if the list is closed*/ uint8_t draw_arrow :1; /*1: Draw arrow*/ uint8_t stay_open :1; /*1: Don't close the list when a new item is selected*/ lv_coord_t fix_height; /*Height of the ddlist when opened. (0: auto-size)*/ diff --git a/src/lv_objx/lv_page.c b/src/lv_objx/lv_page.c index 2979d59424..4e7feaf80d 100644 --- a/src/lv_objx/lv_page.c +++ b/src/lv_objx/lv_page.c @@ -387,6 +387,33 @@ lv_style_t * lv_page_get_style(const lv_obj_t * page, lv_page_style_t type) * Other functions *====================*/ +/** + * Find whether the page has been scrolled to a certain edge. + * @param page Page object + * @param edge Edge to check + * @return true if the page is on the specified edge + */ +bool lv_page_on_edge(lv_obj_t *page, lv_page_edge_t edge) { + lv_style_t * page_style = lv_obj_get_style(page); + lv_obj_t * scrl = lv_page_get_scrl(page); + lv_area_t page_coords; + lv_area_t scrl_coords; + + lv_obj_get_coords(scrl, &scrl_coords); + lv_obj_get_coords(page, &page_coords); + + if(edge == LV_PAGE_EDGE_TOP && scrl_coords.y1 == page_coords.y1 + page_style->body.padding.top) + return true; + else if(edge == LV_PAGE_EDGE_BOTTOM && scrl_coords.y2 == page_coords.y2 - page_style->body.padding.bottom) + return true; + else if(edge == LV_PAGE_EDGE_LEFT && scrl_coords.x1 == page_coords.x1 + page_style->body.padding.left) + return true; + else if(edge == LV_PAGE_EDGE_RIGHT && scrl_coords.x2 == page_coords.x2 - page_style->body.padding.right) + return true; + + return false; +} + /** * Glue the object to the page. After it the page can be moved (dragged) with this object too. * @param obj pointer to an object on a page @@ -917,7 +944,7 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi } } else if(scrl_coords.x1 > page_coords.x1 + page_style->body.padding.left) { - new_x = hpad; /*Left align*/ + new_x = page_style->body.padding.left; /*Left align*/ refr_x = true; if(page_ext->edge_flash.enabled && page_ext->edge_flash.left_ip == 0 && page_ext->edge_flash.right_ip == 0 && @@ -928,7 +955,7 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi } } - /*scrollable height smaller then page height? -> align to left*/ + /*scrollable height smaller then page height? -> align to top*/ if(lv_area_get_height(&scrl_coords) + vpad <= lv_area_get_height(&page_coords)) { if(scrl_coords.y1 != page_coords.y1 + page_style->body.padding.top) { new_y = page_style->body.padding.top; diff --git a/src/lv_objx/lv_page.h b/src/lv_objx/lv_page.h index 2c9de41f24..ddf68998f1 100644 --- a/src/lv_objx/lv_page.h +++ b/src/lv_objx/lv_page.h @@ -49,6 +49,17 @@ enum }; typedef uint8_t lv_sb_mode_t; +/*Edges: describes the four edges of the page*/ + +enum +{ + LV_PAGE_EDGE_LEFT = 0x0, + LV_PAGE_EDGE_TOP = 0x1, + LV_PAGE_EDGE_RIGHT = 0x2, + LV_PAGE_EDGE_BOTTOM = 0x3 +}; +typedef uint8_t lv_page_edge_t; + /*Data of page*/ typedef struct { @@ -349,6 +360,15 @@ lv_style_t * lv_page_get_style(const lv_obj_t *page, lv_page_style_t type); * Other functions *====================*/ + +/** + * Find whether the page has been scrolled to a certain edge. + * @param page Page object + * @param edge Edge to check + * @return true if the page is on the specified edge + */ +bool lv_page_on_edge(lv_obj_t *page, lv_page_edge_t edge); + /** * Glue the object to the page. After it the page can be moved (dragged) with this object too. * @param obj pointer to an object on a page diff --git a/src/lv_objx/lv_roller.c b/src/lv_objx/lv_roller.c index 1ee06fdf3b..57057539c6 100644 --- a/src/lv_objx/lv_roller.c +++ b/src/lv_objx/lv_roller.c @@ -410,7 +410,9 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par lv_obj_set_height(lv_page_get_scrl(roller), lv_obj_get_height(ext->ddlist.label) + lv_obj_get_height(roller)); lv_obj_align(ext->ddlist.label, NULL, obj_align, 0, 0); + lv_anim_del(lv_page_get_scrl(roller), (lv_anim_fp_t)lv_obj_set_y); lv_ddlist_set_selected(roller, ext->ddlist.sel_opt_id); + refr_position(roller, false); } else if(sign == LV_SIGNAL_CORD_CHG) { @@ -422,6 +424,7 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par lv_obj_get_height(ext->ddlist.label) + lv_obj_get_height(roller)); lv_obj_align(ext->ddlist.label, NULL, obj_align, 0, 0); + lv_anim_del(lv_page_get_scrl(roller), (lv_anim_fp_t)lv_obj_set_y); lv_ddlist_set_selected(roller, ext->ddlist.sel_opt_id); refr_position(roller, false); } @@ -446,7 +449,6 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par } } 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*/ - } #endif } else if(sign == LV_SIGNAL_DEFOCUS) { @@ -461,11 +463,15 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par char c = *((char *)param); if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_DOWN) { if(ext->ddlist.sel_opt_id + 1 < ext->ddlist.option_cnt) { + uint16_t ori_id = ext->ddlist.sel_opt_id_ori; /*lv_roller_set_selceted will overwrite this*/ lv_roller_set_selected(roller, ext->ddlist.sel_opt_id + 1, true); + ext->ddlist.sel_opt_id_ori = ori_id; } } else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_UP) { if(ext->ddlist.sel_opt_id > 0) { + uint16_t ori_id = ext->ddlist.sel_opt_id_ori; /*lv_roller_set_selceted will overwrite this*/ lv_roller_set_selected(roller, ext->ddlist.sel_opt_id - 1, true); + ext->ddlist.sel_opt_id_ori = ori_id; } } } else if(sign == LV_SIGNAL_GET_TYPE) { @@ -518,26 +524,18 @@ static lv_res_t lv_roller_scrl_signal(lv_obj_t * roller_scrl, lv_signal_t sign, ext->ddlist.sel_opt_id = id; ext->ddlist.sel_opt_id_ori = id; - res = lv_event_send(roller, LV_EVENT_VALUE_CHANGED, NULL); + res = lv_event_send(roller, LV_EVENT_VALUE_CHANGED, &id); if(res != LV_RES_OK) return res; - } else if(sign == LV_SIGNAL_RELEASED) { + } + else if(sign == LV_SIGNAL_RELEASED) { /*If picked an option by clicking then set it*/ if(!lv_indev_is_dragging(indev)) { - lv_point_t p; - lv_indev_get_point(indev, &p); - p.y = p.y - ext->ddlist.label->coords.y1; - id = p.y / (font_h + style_label->text.line_space); - if(id < 0) id = 0; - if(id >= ext->ddlist.option_cnt) id = ext->ddlist.option_cnt - 1; - ext->ddlist.sel_opt_id = id; - ext->ddlist.sel_opt_id_ori = id; + id = ext->ddlist.sel_opt_id; #if LV_USE_GROUP 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*/ #endif - res = lv_event_send(roller, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; } } @@ -668,7 +666,6 @@ static void inf_normalize(void * roller_scrl) ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id % real_id_cnt; ext->ddlist.sel_opt_id += (LV_ROLLER_INF_PAGES / 2) * real_id_cnt; /*Select the middle page*/ - ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; /*Move to the new id*/ lv_obj_t * roller_scrl = lv_page_get_scrl(roller); diff --git a/src/lv_objx/lv_tabview.c b/src/lv_objx/lv_tabview.c index 6a0b08fc86..3f4e34c885 100644 --- a/src/lv_objx/lv_tabview.c +++ b/src/lv_objx/lv_tabview.c @@ -82,6 +82,7 @@ lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy) /*Initialize the allocated 'ext' */ ext->drag_hor = 0; ext->draging = 0; + ext->scroll_ver = 0; ext->slide_enable = 1; ext->tab_cur = 0; ext->point_last.x = 0; @@ -733,16 +734,29 @@ static void tabpage_pressing_handler(lv_obj_t * tabview, lv_obj_t * tabpage) lv_coord_t x_diff = point_act.x - ext->point_last.x; lv_coord_t y_diff = point_act.y - ext->point_last.y; - if(ext->draging == 0) { - if(x_diff >= LV_INDEV_DRAG_LIMIT || x_diff <= -LV_INDEV_DRAG_LIMIT) { - ext->drag_hor = 1; - ext->draging = 1; - lv_obj_set_drag(lv_page_get_scrl(tabpage), false); - } else if(y_diff >= LV_INDEV_DRAG_LIMIT || y_diff <= -LV_INDEV_DRAG_LIMIT) { - ext->drag_hor = 0; - ext->draging = 1; - } - } + + if(!ext->scroll_ver && (x_diff >= LV_INDEV_DRAG_LIMIT || x_diff <= -LV_INDEV_DRAG_LIMIT)) { + ext->draging = 1; + /*Check if the page is on the edge */ + if((lv_page_on_edge(tabpage, LV_PAGE_EDGE_LEFT) && x_diff > 0) || + (lv_page_on_edge(tabpage, LV_PAGE_EDGE_RIGHT) && x_diff < 0)) { + if(ext->drag_hor == 0) { + ext->point_last.x = point_act.x; + ext->point_last.y = point_act.y; + } + ext->drag_hor = 1; + lv_obj_set_drag(lv_page_get_scrl(tabpage), false); + + } else if(ext->drag_hor == 0) { + ext->drag_hor = 0; + } + } else if(y_diff >= LV_INDEV_DRAG_LIMIT || y_diff <= -LV_INDEV_DRAG_LIMIT) { + ext->drag_hor = 0; + ext->draging = 1; + ext->scroll_ver = 1; + } else + ext->draging = 0; + if(ext->drag_hor) { lv_obj_set_x(ext->content, lv_obj_get_x(ext->content) + point_act.x - ext->point_last.x); ext->point_last.x = point_act.x; @@ -768,6 +782,7 @@ static void tabpage_press_lost_handler(lv_obj_t * tabview, lv_obj_t * tabpage) lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); ext->drag_hor = 0; ext->draging = 0; + ext->scroll_ver = 0; lv_obj_set_drag(lv_page_get_scrl(tabpage), true); diff --git a/src/lv_objx/lv_tabview.h b/src/lv_objx/lv_tabview.h index 6c451a6a6b..5d0cd8291f 100644 --- a/src/lv_objx/lv_tabview.h +++ b/src/lv_objx/lv_tabview.h @@ -64,6 +64,7 @@ typedef struct uint8_t slide_enable :1; /*1: enable horizontal sliding by touch pad*/ uint8_t draging :1; uint8_t drag_hor :1; + uint8_t scroll_ver :1; uint8_t btns_hide :1; lv_tabview_btns_pos_t btns_pos :1; } lv_tabview_ext_t;