diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 3ec8ae962..a415dc1ec 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -1259,7 +1259,7 @@ static void indev_drag(lv_indev_proc_t * proc) /*Go until find the object or parent scrollable in this direction*/ while(proc->types.pointer.drag_obj) { /*Get which object to drad/scroll*/ - lv_drag_dir_t dirs = LV_DRAG_DIR_VER; //scrollable ? lv_obj_get_scroll_dir(target_obj) : lv_obj_get_drag_dir(target_obj); + lv_drag_dir_t dirs = LV_DRAG_DIR_ONE; //scrollable ? lv_obj_get_scroll_dir(target_obj) : lv_obj_get_drag_dir(target_obj); /*Enough move?*/ bool hor_en = false; @@ -1282,16 +1282,32 @@ static void indev_drag(lv_indev_proc_t * proc) lv_coord_t st = lv_obj_get_scroll_top(proc->types.pointer.drag_obj); lv_coord_t sb = lv_obj_get_scroll_bottom(proc->types.pointer.drag_obj); + lv_coord_t sl = lv_obj_get_scroll_left(proc->types.pointer.drag_obj); + lv_coord_t sr = lv_obj_get_scroll_right(proc->types.pointer.drag_obj); - if((up_en && proc->types.pointer.drag_sum.y >= indev_act->driver.drag_limit) || - (down_en && proc->types.pointer.drag_sum.y <= - indev_act->driver.drag_limit)) + bool ver_scrollable = st > 0 || sb > 0 ? true : false; + bool hor_scrollable = sl > 0 || sr > 0 ? true : false; + + if(ver_scrollable && + ((up_en && proc->types.pointer.drag_sum.y >= indev_act->driver.drag_limit) || + (down_en && proc->types.pointer.drag_sum.y <= - indev_act->driver.drag_limit))) { scroll_candidate_obj = proc->types.pointer.drag_obj; dirs_candidate = LV_DRAG_DIR_VER; } + if(hor_scrollable && + ((left_en && proc->types.pointer.drag_sum.x >= indev_act->driver.drag_limit) || + (right_en && proc->types.pointer.drag_sum.x <= - indev_act->driver.drag_limit))) + { + scroll_candidate_obj = proc->types.pointer.drag_obj; + dirs_candidate = LV_DRAG_DIR_HOR; + } + if(st <= 0) up_en = false; if(sb <= 0) down_en = false; + if(sl <= 0) left_en = false; + if(sr <= 0) right_en = false; /*If a move is greater then LV_DRAG_LIMIT then begin the drag*/ @@ -1350,15 +1366,16 @@ static void indev_drag(lv_indev_proc_t * proc) if(scrollable) { lv_area_t child_box; lv_obj_get_children_box(obj, &child_box); - lv_coord_t diff_y = proc->types.pointer.vect.y; - if(obj->scroll.y > 0 && diff_y > 0) { - diff_y = diff_y / 2; + lv_coord_t diff_y = proc->types.pointer.drag_dir == LV_DRAG_DIR_VER ? proc->types.pointer.vect.y : 0; + lv_coord_t diff_x = proc->types.pointer.drag_dir == LV_DRAG_DIR_HOR ? proc->types.pointer.vect.x : 0; + if(obj->scroll.x > 0 && diff_x > 0) { + diff_x = diff_x / 2; } if(child_box.y2 < obj->coords.y2 && diff_y < 0) { diff_y = diff_y / 2; } - lv_obj_scroll_by(obj, 0, diff_y, LV_ANIM_OFF); + lv_obj_scroll_by(obj, diff_x, diff_y, LV_ANIM_OFF); } else { lv_obj_set_pos(obj, act_x, act_y); } @@ -1425,8 +1442,14 @@ static void indev_drag_throw(lv_indev_proc_t * proc) switch(proc->types.pointer.drag_dir) { case LV_DRAG_DIR_HOR: + { proc->types.pointer.drag_throw_vect.y = 0; + lv_coord_t sl = lv_obj_get_scroll_left(target_obj); + lv_coord_t sr = lv_obj_get_scroll_right(target_obj); + /*If scrolled inside reduce faster*/ + if(sl < 0 || sr < 0) proc->types.pointer.drag_throw_vect.x = proc->types.pointer.drag_throw_vect.x >> 1; break; + } case LV_DRAG_DIR_VER: { proc->types.pointer.drag_throw_vect.x = 0; @@ -1438,21 +1461,9 @@ static void indev_drag_throw(lv_indev_proc_t * proc) } } - - if((proc->types.pointer.drag_throw_vect.x != 0 || proc->types.pointer.drag_throw_vect.y != 0)) { /*Get the coordinates and modify them*/ if(scrollable) { -// if(target_obj->scroll.y + proc->types.pointer.drag_throw_vect.y > 0) { -// proc->types.pointer.drag_throw_vect.y = 0; -// lv_obj_scroll_to_y(target_obj, 0, LV_ANIM_OFF); -// } -// -// if(child_box.y2 + proc->types.pointer.drag_throw_vect.y < target_obj->coords.y2) { -// proc->types.pointer.drag_throw_vect.y = 0; -// lv_obj_scroll_by(target_obj, 0, -(child_box.y2 - target_obj->coords.y2), LV_ANIM_OFF); -// } - lv_obj_scroll_by(target_obj, proc->types.pointer.drag_throw_vect.x, proc->types.pointer.drag_throw_vect.y, LV_ANIM_OFF); } else { lv_area_t coords_ori; diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 8ef882f83..876115330 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -104,7 +104,8 @@ static void refresh_event_task_cb(lv_task_t * t); static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find); static void lv_obj_del_async_cb(void * obj); static void obj_del_core(lv_obj_t * obj); -static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv); +static lv_res_t get_ver_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv); +static lv_res_t get_hor_scrollbar_area(lv_obj_t * obj, lv_area_t * sbh); /********************** * STATIC VARIABLES @@ -1099,31 +1100,28 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable lv_anim_init(&a); lv_anim_set_var(&a, obj); + lv_anim_path_t path; + lv_anim_path_init(&path); + lv_anim_path_set_cb(&path, lv_anim_path_ease_out); + if(x) { - lv_anim_set_time(&a, lv_anim_speed_to_time(lv_disp_get_hor_res(d), 0, y)); + lv_anim_set_time(&a, lv_anim_speed_to_time(lv_disp_get_hor_res(d), 0, x)); lv_anim_set_values(&a, obj->scroll.x, obj->scroll.x + x); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_x_cb); + lv_anim_set_path(&a, &path); lv_anim_start(&a); } if(y) { - lv_anim_path_t path; - lv_anim_path_init(&path); - lv_anim_path_set_cb(&path, lv_anim_path_ease_out); lv_anim_set_time(&a, lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 3) >> 2, 0, y)); lv_anim_set_values(&a, obj->scroll.y, obj->scroll.y + y); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_y_cb); lv_anim_set_path(&a, &path); lv_anim_start(&a); } - } else { lv_obj_scroll_by_raw(obj, x, y); } - - - - } /** @@ -1144,7 +1142,7 @@ void lv_obj_scroll_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable */ void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en) { -// refresh_children_position(obj, x, y); + lv_obj_scroll_by(obj, x - obj->scroll.x, 0, anim_en); } /** @@ -1194,6 +1192,42 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj) return y2 - obj->coords.y2; } +/** + * Return the weight of the area on the left the parent. + * That is the number of pixels the object can be scrolled down. + * Normally positive but can be negative when scrolled inside. + * @param obj + * @return + */ +lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj) +{ + return -obj->scroll.x; +} + +/** + * Return the width of the area below the object. + * That is the number of pixels the object can be scrolled left. + * Normally positive but can be negative when scrolled inside. + * @param obj + * @return + */ +lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_coord_t x2 = LV_COORD_MIN; + + lv_obj_t * child = lv_obj_get_child(obj, NULL); + if(child == NULL) return 0; + + while(child) { + x2 = LV_MATH_MAX(x2, child->coords.x2 + lv_obj_get_style_margin_right(child, LV_OBJ_PART_MAIN)); + child = lv_obj_get_child(obj, child); + } + + return x2 - obj->coords.x2; +} + /** * Set the size of an extended clickable area * If TINY mode is used, only the largest of the horizontal and vertical padding @@ -3851,12 +3885,19 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area if(lv_obj_get_screen(obj) == lv_scr_act()) { lv_area_t sb; - if(get_scrollbar_area(obj, &sb)) { + if(get_ver_scrollbar_area(obj, &sb)) { lv_draw_rect_dsc_t sb_rect_dsc; lv_draw_rect_dsc_init(&sb_rect_dsc); sb_rect_dsc.bg_color = LV_COLOR_RED; lv_draw_rect(&sb, clip_area, &sb_rect_dsc); } + + if(get_hor_scrollbar_area(obj, &sb)) { + lv_draw_rect_dsc_t sb_rect_dsc; + lv_draw_rect_dsc_init(&sb_rect_dsc); + sb_rect_dsc.bg_color = LV_COLOR_BLUE; + lv_draw_rect(&sb, clip_area, &sb_rect_dsc); + } } } else if(mode == LV_DESIGN_DRAW_POST) { @@ -3934,13 +3975,30 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) } else if(sign == LV_SIGNAL_SCROLL_END) { - lv_area_t child_box; - lv_obj_get_children_box(obj, &child_box); - if(obj->scroll.y > 0) { - lv_obj_scroll_to_y(obj, 0, LV_ANIM_ON); +// lv_area_t child_box; +// lv_obj_get_children_box(obj, &child_box); + + lv_coord_t st = lv_obj_get_scroll_top(obj); + lv_coord_t sb = lv_obj_get_scroll_bottom(obj); + lv_coord_t sl = lv_obj_get_scroll_left(obj); + lv_coord_t sr = lv_obj_get_scroll_right(obj); + + /*Revert if scrolled in*/ + if(st > 0 || sb > 0) { /*Is vertically scrollable*/ + if(st < 0) { + lv_obj_scroll_by(obj, 0, st, LV_ANIM_ON); + } + else if(sb < 0) { + lv_obj_scroll_by(obj, 0, -sb, LV_ANIM_ON); + } } - else if(child_box.y2 < obj->coords.y2) { - lv_obj_scroll_by(obj, 0, -(child_box.y2 - obj->coords.y2), LV_ANIM_ON); + if(sl > 0 || sr > 0) { /*Is horizontally scrollable*/ + if(sl < 0) { + lv_obj_scroll_by(obj, sl, 0, LV_ANIM_ON); + } + else if(sr < 0) { + lv_obj_scroll_by(obj, -sr, 0, LV_ANIM_ON); + } } } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { @@ -4486,6 +4544,7 @@ static void fade_in_anim_ready(lv_anim_t * a) static void scroll_anim_x_cb(lv_obj_t * obj, lv_anim_value_t v) { + lv_obj_scroll_by_raw(obj, v - obj->scroll.x, 0); } static void scroll_anim_y_cb(lv_obj_t * obj, lv_anim_value_t v) @@ -4524,7 +4583,7 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin return false; } -static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv) +static lv_res_t get_ver_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv) { lv_coord_t obj_h = lv_obj_get_height(obj); @@ -4537,9 +4596,6 @@ static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv) return LV_RES_INV; } lv_coord_t sb_h = (obj_h * obj_h) / content_h; - if(sb_h != 150) { - volatile int x = 0; - } lv_coord_t rem = obj_h - sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ lv_coord_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/ if(scroll_h <= 0) { @@ -4561,4 +4617,37 @@ static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv) return LV_RES_OK; } +static lv_res_t get_hor_scrollbar_area(lv_obj_t * obj, lv_area_t * sbh) +{ + lv_coord_t obj_w = lv_obj_get_width(obj); + + lv_area_t child_box; + lv_res_t res = lv_obj_get_children_box(obj, &child_box); + if(res != LV_RES_OK) return res; + + lv_coord_t content_w = (child_box.x2 - obj->scroll.x) - obj->coords.x1 ; + if(content_w < obj_w) { + return LV_RES_INV; + } + lv_coord_t sb_h = (obj_w * obj_w) / content_w; + lv_coord_t rem = obj_w - sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ + lv_coord_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/ + if(scroll_w <= 0) { + sbh->y2 = obj->coords.y2; + sbh->y1 = sbh->y2 - 10; + sbh->x2 = obj->coords.x2; + sbh->x1 = obj->coords.x1; + return LV_RES_OK; + } + lv_coord_t sb_x = (rem * (child_box.x2 - obj->coords.x2)) / scroll_w; + sb_x = rem - sb_x; + + sbh->x1 = obj->coords.x1 + sb_x; + sbh->x2 = sbh->x1 + sb_h; + sbh->y2 = obj->coords.y2; + sbh->y1 = sbh->y2 - 10; + + return LV_RES_OK; +} + diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index c914616ea..a9acb7bef 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -594,6 +594,24 @@ lv_coord_t lv_obj_get_scroll_top(lv_obj_t * obj); lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj); +/** + * Return the weight of the area on the left the parent. + * That is the number of pixels the object can be scrolled down. + * Normally positive but can be negative when scrolled inside. + * @param obj + * @return + */ +lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj); + +/** + * Return the width of the area below the object. + * That is the number of pixels the object can be scrolled left. + * Normally positive but can be negative when scrolled inside. + * @param obj + * @return + */ +lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj); + /** * Set the size of an extended clickable area * @param obj pointer to an object