From e55500af5dd4c7b7d4fcf0bcf16086c69ce6ff8a Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 28 Jun 2020 13:19:28 +0200 Subject: [PATCH 01/84] scroll: add basic api --- src/lv_core/lv_obj.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ src/lv_core/lv_obj.h | 1 + 2 files changed, 60 insertions(+) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 91e2f9636..8f454d2c5 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -1061,6 +1061,65 @@ void lv_obj_set_auto_realign(lv_obj_t * obj, bool en) #endif } +/** + * Moves all children with horizontally or vertically. + * It doesn't take into account any limits so any values are possible + * @param obj pointer to an object whose children should be moved + * @param x pixel to move horizontally + * @param y pixels to move vertically + */ +void lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +{ + obj->scroll.x += x; + obj->scroll.y += y; + + refresh_children_position(obj, x, y); +} +/** + * Moves all children with horizontally or vertically. + * Limits the scroll to the bounding box of the children. + * @param obj pointer to an object whose children should be moved + * @param x pixel to move horizontally + * @param y pixels to move vertically + */ +void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en) +{ + obj->scroll.x += x; + obj->scroll.y += y; + + refresh_children_position(obj, x, y); +} + +/** + * Scroll the a given x coordinate to the left side of obj. + * @param obj pointer to an object which should be scrolled + * @param x the x coordinate to scroll to + * @param y the y coordinate to scroll to + */ +void lv_obj_scroll_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en) +{ + +} + +/** + * Scroll the a given x coordinate to the left side of obj. + * @param obj pointer to an object which should be scrolled + * @param x the x coordinate to scroll to + */ +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); +} + +/** + * Scroll the a given y coordinate to the top side of obj. + * @param obj pointer to an object which should be scrolled + * @param y the y coordinate to scroll to + */ +void lv_obj_scroll_to_y(lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en) +{ +// refresh_children_position(obj, x, y); +} /** * Set the size of an extended clickable area diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index ad438c399..112959fe1 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -198,6 +198,7 @@ typedef struct _lv_obj_t { lv_ll_t child_ll; /**< Linked list to store the children objects*/ lv_area_t coords; /**< Coordinates of the object (x1, y1, x2, y2)*/ + lv_point_t scroll; /**< The current X/Y scroll offset*/ lv_event_cb_t event_cb; /**< Event callback function */ lv_signal_cb_t signal_cb; /**< Object type specific signal function*/ From b091b676fe96f35d87ec3c9089e4a151a61b76fc Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 2 Jul 2020 13:04:44 +0200 Subject: [PATCH 02/84] scroll: add animation and elastic scroll --- src/lv_core/lv_indev.c | 162 +++++++++++++++++++---------------------- src/lv_core/lv_obj.c | 101 ++++++++++++++++++++++++- src/lv_core/lv_obj.h | 10 ++- 3 files changed, 179 insertions(+), 94 deletions(-) diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index a491c0996..4e78de2ca 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -1245,15 +1245,20 @@ static void indev_click_focus(lv_indev_proc_t * proc) */ static void indev_drag(lv_indev_proc_t * proc) { - lv_obj_t * drag_obj = get_dragged_obj(proc->types.pointer.act_obj); - bool drag_just_started = false; - if(drag_obj == NULL) return; + bool scrollable = true; - if(lv_obj_get_drag(drag_obj) == false) return; + /*Get which object to drad/scroll*/ + lv_obj_t * target_obj = get_dragged_obj(proc->types.pointer.act_obj); + if(target_obj == NULL) return; + 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 allowed_dirs = lv_obj_get_drag_dir(drag_obj); + bool just_started = false; + + /*Get the coordinates of the object and modify them*/ + lv_coord_t act_x = lv_obj_get_x(target_obj); + lv_coord_t act_y = lv_obj_get_y(target_obj); /*Count the movement by drag*/ if(proc->types.pointer.drag_limit_out == 0) { @@ -1263,15 +1268,15 @@ static void indev_drag(lv_indev_proc_t * proc) /*Enough move?*/ bool hor_en = false; bool ver_en = false; - if(allowed_dirs == LV_DRAG_DIR_HOR || allowed_dirs == LV_DRAG_DIR_BOTH) { + if(dirs == LV_DRAG_DIR_HOR || dirs == LV_DRAG_DIR_BOTH) { hor_en = true; } - if(allowed_dirs == LV_DRAG_DIR_VER || allowed_dirs == LV_DRAG_DIR_BOTH) { + if(dirs == LV_DRAG_DIR_VER || dirs == LV_DRAG_DIR_BOTH) { ver_en = true; } - if(allowed_dirs == LV_DRAG_DIR_ONE) { + if(dirs == LV_DRAG_DIR_ONE) { if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { hor_en = true; } @@ -1284,102 +1289,77 @@ static void indev_drag(lv_indev_proc_t * proc) if((hor_en && LV_MATH_ABS(proc->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) || (ver_en && LV_MATH_ABS(proc->types.pointer.drag_sum.y) >= indev_act->driver.drag_limit)) { proc->types.pointer.drag_limit_out = 1; - drag_just_started = true; + just_started = true; + if(dirs == LV_DRAG_DIR_ONE) { + proc->types.pointer.drag_dir = hor_en ? LV_DRAG_DIR_HOR : LV_DRAG_DIR_VER; + } else { + proc->types.pointer.drag_dir = dirs; + } + + /*The was no move due to drag limit. Compensate it now.*/ + if(!hor_en) proc->types.pointer.drag_sum.x = 0; + if(!ver_en) proc->types.pointer.drag_sum.y = 0; + + act_x += proc->types.pointer.drag_sum.x; + act_y += proc->types.pointer.drag_sum.y; } } /*If the drag limit is exceeded handle the dragging*/ if(proc->types.pointer.drag_limit_out != 0) { - /*Set new position if the vector is not zero*/ + /*Set new position or scroll if the vector is not zero*/ if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) { - lv_coord_t prev_x = drag_obj->coords.x1; - lv_coord_t prev_y = drag_obj->coords.y1; - lv_coord_t prev_par_w = lv_obj_get_width(lv_obj_get_parent(drag_obj)); - lv_coord_t prev_par_h = lv_obj_get_height(lv_obj_get_parent(drag_obj)); + lv_coord_t prev_x = target_obj->coords.x1; + lv_coord_t prev_y = target_obj->coords.y1; - /*Get the coordinates of the object and modify them*/ - lv_coord_t act_x = lv_obj_get_x(drag_obj); - lv_coord_t act_y = lv_obj_get_y(drag_obj); - - if(allowed_dirs == LV_DRAG_DIR_BOTH) { - if(drag_just_started) { - proc->types.pointer.drag_dir = LV_DRAG_DIR_BOTH; - act_x += proc->types.pointer.drag_sum.x; - act_y += proc->types.pointer.drag_sum.y; - } - } - else if(allowed_dirs == LV_DRAG_DIR_HOR) { - if(drag_just_started) { - proc->types.pointer.drag_dir = LV_DRAG_DIR_HOR; - proc->types.pointer.drag_sum.y = 0; - act_x += proc->types.pointer.drag_sum.x; - } - } - else if(allowed_dirs == LV_DRAG_DIR_VER) { - if(drag_just_started) { - proc->types.pointer.drag_dir = LV_DRAG_DIR_VER; - proc->types.pointer.drag_sum.x = 0; - act_y += proc->types.pointer.drag_sum.y; - } - } - else if(allowed_dirs == LV_DRAG_DIR_ONE) { - if(drag_just_started) { - if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { - proc->types.pointer.drag_dir = LV_DRAG_DIR_HOR; - proc->types.pointer.drag_sum.y = 0; - act_x += proc->types.pointer.drag_sum.x; - } - else { - proc->types.pointer.drag_dir = LV_DRAG_DIR_VER; - proc->types.pointer.drag_sum.x = 0; - act_y += proc->types.pointer.drag_sum.y; - } - } - } - - /*Move the object*/ - if(allowed_dirs == LV_DRAG_DIR_HOR || - allowed_dirs == LV_DRAG_DIR_BOTH || - (allowed_dirs == LV_DRAG_DIR_ONE && - LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y))) { - act_x += proc->types.pointer.vect.x; - } - if(allowed_dirs == LV_DRAG_DIR_VER || - allowed_dirs == LV_DRAG_DIR_BOTH || - (allowed_dirs == LV_DRAG_DIR_ONE && - LV_MATH_ABS(proc->types.pointer.drag_sum.x) < LV_MATH_ABS(proc->types.pointer.drag_sum.y))) { - act_y += proc->types.pointer.vect.y; - } + /*Move the object. `drag_sum` is zerod out for *disabled direction*/ + if(proc->types.pointer.drag_sum.x) act_x += proc->types.pointer.vect.x; + if(proc->types.pointer.drag_sum.y) act_y += proc->types.pointer.vect.y; uint16_t inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp); /*Get the number of currently invalidated areas*/ - lv_obj_set_pos(drag_obj, act_x, act_y); - proc->types.pointer.drag_in_prog = 1; - - /*If the object didn't moved then clear the invalidated areas*/ - if(drag_obj->coords.x1 == prev_x && drag_obj->coords.y1 == prev_y) { - /*In a special case if the object is moved on a page and - * the scrollable has fit == true and the object is dragged of the page then - * while its coordinate is not changing only the parent's size is reduced */ - lv_coord_t act_par_w = lv_obj_get_width(lv_obj_get_parent(drag_obj)); - lv_coord_t act_par_h = lv_obj_get_height(lv_obj_get_parent(drag_obj)); - if(act_par_w == prev_par_w && act_par_h == prev_par_h) { - uint16_t new_inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp); - _lv_disp_pop_from_inv_buf(indev_act->driver.disp, new_inv_buf_size - inv_buf_size); + if(scrollable) { + lv_area_t child_box; + lv_obj_get_children_box(target_obj, &child_box); + lv_coord_t diff_y = proc->types.pointer.vect.y; + if(target_obj->scroll.y > 0 && diff_y > 0) { + diff_y = diff_y / 2; } + if(child_box.y2 < target_obj->coords.y2 && diff_y < 0) { + diff_y = diff_y / 2; + } + + lv_obj_scroll_by(target_obj, 0, diff_y, LV_ANIM_OFF); + } else { + lv_obj_set_pos(target_obj, act_x, act_y); } - /*Set the drag in progress flag*/ - /*Send the drag begin signal on first move*/ - if(drag_just_started) { - drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_BEGIN, indev_act); - if(indev_reset_check(proc)) return; - - lv_event_send(drag_obj, LV_EVENT_DRAG_BEGIN, NULL); - if(indev_reset_check(proc)) return; - } + proc->types.pointer.drag_in_prog = 1; +// +// /*If the object didn't moved then clear the invalidated areas*/ +// if(target_obj->coords.x1 == prev_x && target_obj->coords.y1 == prev_y) { +// /*In a special case if the object is moved on a page and +// * the scrollable has fit == true and the object is dragged of the page then +// * while its coordinate is not changing only the parent's size is reduced */ +// lv_coord_t act_par_w = lv_obj_get_width(lv_obj_get_parent(target_obj)); +// lv_coord_t act_par_h = lv_obj_get_height(lv_obj_get_parent(target_obj)); +// if(act_par_w == prev_par_w && act_par_h == prev_par_h) { +// uint16_t new_inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp); +// _lv_disp_pop_from_inv_buf(indev_act->driver.disp, new_inv_buf_size - inv_buf_size); +// } +// } +// +// /*Set the drag in progress flag*/ +// /*Send the drag begin signal on first move*/ +// if(just_started) { +// target_obj->signal_cb(target_obj, LV_SIGNAL_DRAG_BEGIN, indev_act); +// if(indev_reset_check(proc)) return; +// +// lv_event_send(target_obj, LV_EVENT_DRAG_BEGIN, NULL); +// if(indev_reset_check(proc)) return; +// } } } @@ -1466,12 +1446,16 @@ static void indev_drag_throw(lv_indev_proc_t * proc) */ static lv_obj_t * get_dragged_obj(lv_obj_t * obj) { + + return obj; + if(obj == NULL) return NULL; lv_obj_t * drag_obj = obj; while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) { drag_obj = lv_obj_get_parent(drag_obj); } + if(lv_obj_get_drag(drag_obj) == false) return NULL; return drag_obj; } diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 8f454d2c5..c39ddc647 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -96,6 +96,8 @@ static void trans_anim_start_cb(lv_anim_t * a); static void trans_anim_ready_cb(lv_anim_t * a); static void opa_scale_anim(lv_obj_t * obj, lv_anim_value_t v); 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); +static void scroll_anim_y_cb(lv_obj_t * obj, lv_anim_value_t v); #endif static void lv_event_mark_deleted(lv_obj_t * obj); static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find); @@ -1074,6 +1076,7 @@ void lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) obj->scroll.y += y; refresh_children_position(obj, x, y); + lv_obj_invalidate(obj); } /** * Moves all children with horizontally or vertically. @@ -1084,10 +1087,37 @@ void lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) */ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en) { - obj->scroll.x += x; - obj->scroll.y += y; - refresh_children_position(obj, x, y); + if(x == 0 && y == 0) return; + + if(anim_en == LV_ANIM_ON) { + lv_disp_t * d = lv_obj_get_disp(obj); + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, obj); + + if(x) { + lv_anim_set_time(&a, lv_anim_speed_to_time(lv_disp_get_hor_res(d), 0, y)); + 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_start(&a); + } + + + if(y) { + lv_anim_set_time(&a, lv_anim_speed_to_time(lv_disp_get_ver_res(d), 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_start(&a); + } + + } else { + lv_obj_scroll_by_raw(obj, x, y); + } + + + + } /** @@ -1118,7 +1148,7 @@ void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en) */ void lv_obj_scroll_to_y(lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en) { -// refresh_children_position(obj, x, y); + lv_obj_scroll_by(obj, 0, y - obj->scroll.y, anim_en); } /** @@ -2125,6 +2155,37 @@ void lv_obj_get_coords(const lv_obj_t * obj, lv_area_t * cords_p) lv_area_copy(cords_p, &obj->coords); } +/** + * Get a bounding which includes all the the children. + * `margin` of the children also taken into account and makes the box larger (if positive) + * @param obj pointer to an object + * @param coords pointer to an area to store the coordinates + * @return LV_RES_INV: `obj` has no children and `coords` can't be set; `LV_RES_OK`: success + */ +lv_res_t lv_obj_get_children_box(const lv_obj_t * obj, lv_area_t * coords) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + coords->x1 = LV_COORD_MAX; + coords->y1 = LV_COORD_MAX; + coords->x2 = LV_COORD_MIN; + coords->y2 = LV_COORD_MIN; + + lv_obj_t * child = lv_obj_get_child(obj, NULL); + if(child == NULL) return LV_RES_INV; + + while(child) { + coords->x1 = LV_MATH_MIN(coords->x1, child->coords.x1 - lv_obj_get_style_margin_left(child, LV_OBJ_PART_MAIN)); + coords->y1 = LV_MATH_MIN(coords->y1, child->coords.y1 - lv_obj_get_style_margin_top(child, LV_OBJ_PART_MAIN)); + coords->x2 = LV_MATH_MAX(coords->x2, child->coords.x2 + lv_obj_get_style_margin_right(child, LV_OBJ_PART_MAIN)); + coords->y2 = LV_MATH_MAX(coords->y2, child->coords.y2 + lv_obj_get_style_margin_bottom(child, LV_OBJ_PART_MAIN)); + + child = lv_obj_get_child(obj, child); + } + + return LV_RES_OK; +} + /** * Reduce area retried by `lv_obj_get_coords()` the get graphically usable area of an object. * (Without the size of the border or other extra graphical elements) @@ -2761,6 +2822,18 @@ lv_drag_dir_t lv_obj_get_drag_dir(const lv_obj_t * obj) return obj->drag_dir; } +/** + * Get the directions an object can be scrolled + * @param obj pointer to an object + * @return bitwise OR of allowed directions an object can be dragged in + */ +lv_drag_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + return obj->scroll_dir; +} + /** * Get the drag throw enable attribute of an object * @param obj pointer to an object @@ -3738,6 +3811,17 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) /*Return 'invalid' if the child change signal is not enabled*/ if(lv_obj_is_protected(obj, LV_PROTECT_CHILD_CHG) != false) res = LV_RES_INV; } + else if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED) { + + 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); + } + else if(child_box.y2 < obj->coords.y2) { + lv_obj_scroll_by(obj, 0, -(child_box.y2 - obj->coords.y2), LV_ANIM_ON); + } + } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { lv_coord_t d = lv_obj_get_draw_rect_ext_pad_size(obj, LV_OBJ_PART_MAIN); obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d); @@ -4278,6 +4362,15 @@ static void fade_in_anim_ready(lv_anim_t * a) lv_style_remove_prop(lv_obj_get_local_style(a->var, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE); } + +static void scroll_anim_x_cb(lv_obj_t * obj, lv_anim_value_t v) +{ +} + +static void scroll_anim_y_cb(lv_obj_t * obj, lv_anim_value_t v) +{ + lv_obj_scroll_by_raw(obj, 0, v - obj->scroll.y); +} #endif static void lv_event_mark_deleted(lv_obj_t * obj) diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 112959fe1..b26543ca1 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -228,7 +228,8 @@ typedef struct _lv_obj_t { uint8_t gesture_parent : 1; /**< 1: Parent will be gesture instead*/ uint8_t focus_parent : 1; /**< 1: Parent will be focused instead*/ - lv_drag_dir_t drag_dir : 3; /**< Which directions the object can be dragged in */ + lv_drag_dir_t drag_dir : 3; /**< In which directions the object can be dragged */ + lv_drag_dir_t scroll_dir : 3; /**< In which directions the object can be scrolled */ lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */ #if LV_USE_GROUP != 0 @@ -1223,6 +1224,13 @@ bool lv_obj_get_drag(const lv_obj_t * obj); */ lv_drag_dir_t lv_obj_get_drag_dir(const lv_obj_t * obj); +/** + * Get the directions an object can be scrolled + * @param obj pointer to an object + * @return bitwise OR of allowed directions an object can be dragged in + */ +lv_drag_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj); + /** * Get the drag throw enable attribute of an object * @param obj pointer to an object From bb68dde55d4385146075d2d5610f514bad5496b0 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 7 Jul 2020 09:02:41 +0200 Subject: [PATCH 03/84] scroll: start scrollbar --- src/lv_core/lv_obj.c | 58 +++++++++++++++++++++++++++++++++++++++++-- src/lv_core/lv_obj.h | 1 + src/lv_core/lv_refr.c | 2 +- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index c39ddc647..98c09b9bf 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -103,6 +103,7 @@ static void lv_event_mark_deleted(lv_obj_t * obj); 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 VARIABLES @@ -1076,6 +1077,7 @@ void lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) obj->scroll.y += y; refresh_children_position(obj, x, y); + lv_signal_send(obj, LV_SIGNAL_SCROLLED, NULL); lv_obj_invalidate(obj); } /** @@ -1103,11 +1105,14 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable lv_anim_start(&a); } - if(y) { - lv_anim_set_time(&a, lv_anim_speed_to_time(lv_disp_get_ver_res(d), 0, 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); } @@ -3740,6 +3745,14 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ lv_draw_mask_add(mp, obj + 8); } + + lv_area_t sb; + if(get_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); + } } else if(mode == LV_DESIGN_DRAW_POST) { if(lv_obj_get_style_clip_corner(obj, LV_OBJ_PART_MAIN)) { @@ -3810,6 +3823,9 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) if(sign == LV_SIGNAL_CHILD_CHG) { /*Return 'invalid' if the child change signal is not enabled*/ if(lv_obj_is_protected(obj, LV_PROTECT_CHILD_CHG) != false) res = LV_RES_INV; + } + else if(sign == LV_SIGNAL_SCROLLED) { + } else if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED) { @@ -4397,3 +4413,41 @@ 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) +{ + lv_coord_t obj_h = lv_obj_get_height(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_h = (child_box.y2 - obj->scroll.y) - obj->coords.y1 ; + if(content_h < obj_h) { + 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) { + sbv->y1 = obj->coords.y1; + sbv->y2 = obj->coords.y2; + sbv->x2 = obj->coords.x2; + sbv->x1 = sbv->x2 - 10; + return LV_RES_OK; + } + lv_coord_t sb_y = (rem * (child_box.y2 - obj->coords.y2)) / scroll_h; + printf("overflow: sb_h: %d, y: %d\n", sb_h, sb_y); + + sbv->y1 = obj->coords.y1 + sb_y; + sbv->y2 = sbv->y1 + sb_h; + sbv->x2 = obj->coords.x2; + sbv->x1 = sbv->x2 - 10; + + return LV_RES_OK; +} + + diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index b26543ca1..88150db05 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -122,6 +122,7 @@ enum { /*General signals*/ LV_SIGNAL_CLEANUP, /**< Object is being deleted */ LV_SIGNAL_CHILD_CHG, /**< Child was removed/added */ + LV_SIGNAL_SCROLLED, /**< Object coordinates/size have changed */ LV_SIGNAL_COORD_CHG, /**< Object coordinates/size have changed */ LV_SIGNAL_PARENT_SIZE_CHG, /**< Parent's size has changed */ LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */ diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index 9644a0459..834b59050 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -31,7 +31,7 @@ * DEFINES *********************/ /* Draw translucent random colored areas on the invalidated (redrawn) areas*/ -#define MASK_AREA_DEBUG 0 +#define MASK_AREA_DEBUG 1 /********************** * TYPEDEFS From 9cfd399fb305b7066cadeee3c0ebc50161ab9047 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 8 Jul 2020 12:29:47 +0200 Subject: [PATCH 04/84] scroll: add scroll throw --- src/lv_core/lv_indev.c | 114 +++++++++++++++++++++++++---------------- src/lv_core/lv_obj.c | 7 ++- src/lv_core/lv_obj.h | 4 +- src/lv_core/lv_refr.c | 2 +- 4 files changed, 77 insertions(+), 50 deletions(-) diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 88d6e58a4..37124a3bc 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -1259,7 +1259,6 @@ static void indev_drag(lv_indev_proc_t * proc) if(target_obj == NULL) return; lv_drag_dir_t dirs = LV_DRAG_DIR_VER; //scrollable ? lv_obj_get_scroll_dir(target_obj) : lv_obj_get_drag_dir(target_obj); - bool just_started = false; /*Get the coordinates of the object and modify them*/ @@ -1379,67 +1378,94 @@ static void indev_drag_throw(lv_indev_proc_t * proc) { if(proc->types.pointer.drag_in_prog == 0) return; - lv_obj_t * drag_obj = get_dragged_obj(proc->types.pointer.last_obj); - if(drag_obj == NULL) return; + bool scrollable = true; + + /*Get which object to drad/scroll*/ + lv_obj_t * target_obj = get_dragged_obj(proc->types.pointer.last_obj); + if(target_obj == NULL) return; /*Return if the drag throw is not enabled*/ - if(lv_obj_get_drag_throw(drag_obj) == false) { - proc->types.pointer.drag_in_prog = 0; - drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, indev_act); - if(indev_reset_check(proc)) return; - - lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL); - return; - } - - lv_drag_dir_t allowed_dirs = lv_obj_get_drag_dir(drag_obj); +// if(lv_obj_get_drag_throw(target_obj) == false) { +// proc->types.pointer.drag_in_prog = 0; +// target_obj->signal_cb(target_obj, scrollable ? LV_SIGNAL_SCROLL_END : LV_SIGNAL_DRAG_END, indev_act); +// if(indev_reset_check(proc)) return; +// +// lv_event_send(target_obj, LV_EVENT_DRAG_END, NULL); +// return; +// } /*Reduce the vectors*/ proc->types.pointer.drag_throw_vect.x = - proc->types.pointer.drag_throw_vect.x * (100 - indev_act->driver.drag_throw) / 100; + proc->types.pointer.drag_throw_vect.x * (100 - indev_act->driver.drag_throw) / 30; proc->types.pointer.drag_throw_vect.y = - proc->types.pointer.drag_throw_vect.y * (100 - indev_act->driver.drag_throw) / 100; + proc->types.pointer.drag_throw_vect.y * (100 - indev_act->driver.drag_throw) / 30; - if(proc->types.pointer.drag_throw_vect.x != 0 || proc->types.pointer.drag_throw_vect.y != 0) { + switch(proc->types.pointer.drag_dir) { + case LV_DRAG_DIR_HOR: + proc->types.pointer.drag_throw_vect.y = 0; + break; + case LV_DRAG_DIR_VER: + proc->types.pointer.drag_throw_vect.x = 0; + break; + } + + lv_area_t child_box; + lv_obj_get_children_box(target_obj, &child_box); + + + if((target_obj->scroll.y < 0 && child_box.y2 > target_obj->coords.y2) && + (proc->types.pointer.drag_throw_vect.x != 0 || proc->types.pointer.drag_throw_vect.y != 0)) { /*Get the coordinates and modify them*/ - lv_area_t coords_ori; - lv_obj_get_coords(drag_obj, &coords_ori); - lv_coord_t act_x = lv_obj_get_x(drag_obj) + proc->types.pointer.drag_throw_vect.x; - lv_coord_t act_y = lv_obj_get_y(drag_obj) + proc->types.pointer.drag_throw_vect.y; + 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); + } else { + lv_area_t coords_ori; + lv_obj_get_coords(target_obj, &coords_ori); + + lv_coord_t act_x = lv_obj_get_x(target_obj) + proc->types.pointer.drag_throw_vect.x; + lv_coord_t act_y = lv_obj_get_y(target_obj) + proc->types.pointer.drag_throw_vect.y; + lv_obj_set_pos(target_obj, act_x, act_y); + + lv_area_t coords_new; + lv_obj_get_coords(target_obj, &coords_new); + + /*If non of the coordinates are changed then do not continue throwing*/ + if((coords_ori.x1 == coords_new.x1 || proc->types.pointer.drag_throw_vect.x == 0) && + (coords_ori.y1 == coords_new.y1 || proc->types.pointer.drag_throw_vect.y == 0)) { + proc->types.pointer.drag_in_prog = 0; + proc->types.pointer.vect.x = 0; + proc->types.pointer.vect.y = 0; + proc->types.pointer.drag_throw_vect.x = 0; + proc->types.pointer.drag_throw_vect.y = 0; + target_obj->signal_cb(target_obj, LV_SIGNAL_DRAG_END, indev_act); + if(indev_reset_check(proc)) return; + + lv_event_send(target_obj, LV_EVENT_DRAG_END, NULL); + if(indev_reset_check(proc)) return; + } - if(allowed_dirs == LV_DRAG_DIR_BOTH) lv_obj_set_pos(drag_obj, act_x, act_y); - else if(allowed_dirs == LV_DRAG_DIR_HOR) lv_obj_set_x(drag_obj, act_x); - else if(allowed_dirs == LV_DRAG_DIR_VER) lv_obj_set_y(drag_obj, act_y); - else if(allowed_dirs == LV_DRAG_DIR_ONE) { - if(proc->types.pointer.drag_sum.x) lv_obj_set_x(drag_obj, act_x); - else lv_obj_set_y(drag_obj, act_y); } - lv_area_t coord_new; - lv_obj_get_coords(drag_obj, &coord_new); - /*If non of the coordinates are changed then do not continue throwing*/ - if((coords_ori.x1 == coord_new.x1 || proc->types.pointer.drag_throw_vect.x == 0) && - (coords_ori.y1 == coord_new.y1 || proc->types.pointer.drag_throw_vect.y == 0)) { - proc->types.pointer.drag_in_prog = 0; - proc->types.pointer.vect.x = 0; - proc->types.pointer.vect.y = 0; - proc->types.pointer.drag_throw_vect.x = 0; - proc->types.pointer.drag_throw_vect.y = 0; - drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, indev_act); - if(indev_reset_check(proc)) return; - - lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL); - if(indev_reset_check(proc)) return; - } } /*If the types.pointer.vectors become 0 -> types.pointer.drag_in_prog = 0 and send a drag end signal*/ else { proc->types.pointer.drag_in_prog = 0; - drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, indev_act); + target_obj->signal_cb(target_obj, scrollable ? LV_SIGNAL_SCROLL_END : LV_SIGNAL_DRAG_END, indev_act); if(indev_reset_check(proc)) return; - lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL); + lv_event_send(target_obj, LV_EVENT_DRAG_END, NULL); if(indev_reset_check(proc)) return; } } diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 3e137a904..49cfe7521 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -1078,7 +1078,7 @@ void lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) obj->scroll.y += y; refresh_children_position(obj, x, y); - lv_signal_send(obj, LV_SIGNAL_SCROLLED, NULL); + lv_signal_send(obj, LV_SIGNAL_SCROLL, NULL); lv_obj_invalidate(obj); } /** @@ -3890,10 +3890,10 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) /*Return 'invalid' if the child change signal is not enabled*/ if(lv_obj_is_protected(obj, LV_PROTECT_CHILD_CHG) != false) res = LV_RES_INV; } - else if(sign == LV_SIGNAL_SCROLLED) { + else if(sign == LV_SIGNAL_SCROLL) { } - else if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED) { + else if(sign == LV_SIGNAL_SCROLL_END) { lv_area_t child_box; lv_obj_get_children_box(obj, &child_box); @@ -4511,7 +4511,6 @@ static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv) return LV_RES_OK; } lv_coord_t sb_y = (rem * (child_box.y2 - obj->coords.y2)) / scroll_h; - printf("overflow: sb_h: %d, y: %d\n", sb_h, sb_y); sbv->y1 = obj->coords.y1 + sb_y; sbv->y2 = sbv->y1 + sb_h; diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 7a4c40c6d..7533b4c3a 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -122,7 +122,6 @@ enum { /*General signals*/ LV_SIGNAL_CLEANUP, /**< Object is being deleted */ LV_SIGNAL_CHILD_CHG, /**< Child was removed/added */ - LV_SIGNAL_SCROLLED, /**< Object coordinates/size have changed */ LV_SIGNAL_COORD_CHG, /**< Object coordinates/size have changed */ LV_SIGNAL_PARENT_SIZE_CHG, /**< Parent's size has changed */ LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */ @@ -140,6 +139,9 @@ enum { LV_SIGNAL_RELEASED, /**< User pressed object for a short period of time, then released it. Not called if dragged. */ LV_SIGNAL_LONG_PRESS, /**< Object has been pressed for at least `LV_INDEV_LONG_PRESS_TIME`. Not called if dragged.*/ LV_SIGNAL_LONG_PRESS_REP, /**< Called after `LV_INDEV_LONG_PRESS_TIME` in every `LV_INDEV_LONG_PRESS_REP_TIME` ms. Not called if dragged.*/ + LV_SIGNAL_SCROLL_BEGIN, /**< The scrolling has just begun */ + LV_SIGNAL_SCROLL, /**< The object has been scrolled */ + LV_SIGNAL_SCROLL_END, /**< The scrolling has ended */ LV_SIGNAL_DRAG_BEGIN, LV_SIGNAL_DRAG_THROW_BEGIN, LV_SIGNAL_DRAG_END, diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index 834b59050..9644a0459 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -31,7 +31,7 @@ * DEFINES *********************/ /* Draw translucent random colored areas on the invalidated (redrawn) areas*/ -#define MASK_AREA_DEBUG 1 +#define MASK_AREA_DEBUG 0 /********************** * TYPEDEFS From 0cea8b2c0866ff4c1301b1343b1669951a0b3be9 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 8 Jul 2020 14:59:19 +0200 Subject: [PATCH 05/84] scroll: wip --- src/lv_core/lv_indev.c | 161 +++++++++++++++++++++++++++----------- src/lv_core/lv_obj.c | 37 +++++++++ src/lv_core/lv_obj.h | 60 ++++++++++++++ src/lv_hal/lv_hal_indev.h | 1 + 4 files changed, 214 insertions(+), 45 deletions(-) diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 37124a3bc..775c484f3 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -1095,6 +1095,7 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev) if(indev->proc.reset_query) { indev->proc.types.pointer.act_obj = NULL; indev->proc.types.pointer.last_obj = NULL; + indev->proc.types.pointer.drag_obj = NULL; indev->proc.types.pointer.drag_limit_out = 0; indev->proc.types.pointer.drag_in_prog = 0; indev->proc.long_pr_sent = 0; @@ -1251,72 +1252,131 @@ static void indev_click_focus(lv_indev_proc_t * proc) */ static void indev_drag(lv_indev_proc_t * proc) { - bool scrollable = true; /*Get which object to drad/scroll*/ - lv_obj_t * target_obj = get_dragged_obj(proc->types.pointer.act_obj); - if(target_obj == NULL) return; - lv_drag_dir_t dirs = LV_DRAG_DIR_VER; //scrollable ? lv_obj_get_scroll_dir(target_obj) : lv_obj_get_drag_dir(target_obj); bool just_started = false; - /*Get the coordinates of the object and modify them*/ - lv_coord_t act_x = lv_obj_get_x(target_obj); - lv_coord_t act_y = lv_obj_get_y(target_obj); + lv_coord_t act_x = 0; + lv_coord_t act_y = 0; /*Count the movement by drag*/ if(proc->types.pointer.drag_limit_out == 0) { proc->types.pointer.drag_sum.x += proc->types.pointer.vect.x; proc->types.pointer.drag_sum.y += proc->types.pointer.vect.y; - /*Enough move?*/ - bool hor_en = false; - bool ver_en = false; - if(dirs == LV_DRAG_DIR_HOR || dirs == LV_DRAG_DIR_BOTH) { - hor_en = true; - } + proc->types.pointer.drag_obj = proc->types.pointer.act_obj; - if(dirs == LV_DRAG_DIR_VER || dirs == LV_DRAG_DIR_BOTH) { - ver_en = true; - } + /*Go until find the object or parent scrollable in this direction*/ + while(proc->types.pointer.drag_obj) { + dirs = LV_DRAG_DIR_VER; - if(dirs == LV_DRAG_DIR_ONE) { - if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { + /*Enough move?*/ + bool hor_en = false; + bool ver_en = false; + if(dirs == LV_DRAG_DIR_HOR || dirs == LV_DRAG_DIR_BOTH) { hor_en = true; } - else { + + if(dirs == LV_DRAG_DIR_VER || dirs == LV_DRAG_DIR_BOTH) { ver_en = true; } - } - /*If a move is greater then LV_DRAG_LIMIT then begin the drag*/ - if((hor_en && LV_MATH_ABS(proc->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) || - (ver_en && LV_MATH_ABS(proc->types.pointer.drag_sum.y) >= indev_act->driver.drag_limit)) { - proc->types.pointer.drag_limit_out = 1; - just_started = true; if(dirs == LV_DRAG_DIR_ONE) { - proc->types.pointer.drag_dir = hor_en ? LV_DRAG_DIR_HOR : LV_DRAG_DIR_VER; - } else { - proc->types.pointer.drag_dir = dirs; + if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { + hor_en = true; + } + else { + ver_en = true; + } } - /*The was no move due to drag limit. Compensate it now.*/ - if(!hor_en) proc->types.pointer.drag_sum.x = 0; - if(!ver_en) proc->types.pointer.drag_sum.y = 0; + bool up_en = ver_en; + bool down_en = ver_en; - act_x += proc->types.pointer.drag_sum.x; - act_y += proc->types.pointer.drag_sum.y; + if(lv_obj_get_scroll_top(proc->types.pointer.drag_obj) <= 0) up_en = false; + if(lv_obj_get_scroll_bottom(proc->types.pointer.drag_obj) <= 0) down_en = false; + + /*If a move is greater then LV_DRAG_LIMIT then begin the drag*/ + if((hor_en && LV_MATH_ABS(proc->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) || + (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)) { + proc->types.pointer.drag_limit_out = 1; + just_started = true; + if(dirs == LV_DRAG_DIR_ONE) { + proc->types.pointer.drag_dir = hor_en ? LV_DRAG_DIR_HOR : LV_DRAG_DIR_VER; + } else { + proc->types.pointer.drag_dir = dirs; + } + + /*The was no move due to drag limit. Compensate it now.*/ + if(!hor_en) proc->types.pointer.drag_sum.x = 0; + if(!ver_en) proc->types.pointer.drag_sum.y = 0; + + act_x = lv_obj_get_x(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.x; + act_y = lv_obj_get_y(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.y; + break; + } + proc->types.pointer.drag_obj = lv_obj_get_parent(proc->types.pointer.drag_obj); } } + /*If the drag/scroll can't be propagated to any parent show an elastic scroll in the original object*/ + if(proc->types.pointer.drag_obj == NULL) { + proc->types.pointer.drag_obj = proc->types.pointer.act_obj; +// +// dirs = LV_DRAG_DIR_VER; +// +// /*Enough move?*/ +// bool hor_en = false; +// bool ver_en = false; +// if(dirs == LV_DRAG_DIR_HOR || dirs == LV_DRAG_DIR_BOTH) { +// hor_en = true; +// } +// +// if(dirs == LV_DRAG_DIR_VER || dirs == LV_DRAG_DIR_BOTH) { +// ver_en = true; +// } +// +// if(dirs == LV_DRAG_DIR_ONE) { +// if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { +// hor_en = true; +// } +// else { +// ver_en = true; +// } +// } +// +// /*If a move is greater then LV_DRAG_LIMIT then begin the drag*/ +// if((hor_en && LV_MATH_ABS(proc->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) || +// (ver_en && LV_MATH_ABS(proc->types.pointer.drag_sum.y) >= indev_act->driver.drag_limit)) { +// proc->types.pointer.drag_limit_out = 1; +// just_started = true; +// if(dirs == LV_DRAG_DIR_ONE) { +// proc->types.pointer.drag_dir = hor_en ? LV_DRAG_DIR_HOR : LV_DRAG_DIR_VER; +// } else { +// proc->types.pointer.drag_dir = dirs; +// } +// +// /*The was no move due to drag limit. Compensate it now.*/ +// if(!hor_en) proc->types.pointer.drag_sum.x = 0; +// if(!ver_en) proc->types.pointer.drag_sum.y = 0; +// +// act_x = lv_obj_get_x(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.x; +// act_y = lv_obj_get_y(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.y; +// } + + } + lv_obj_t * obj = proc->types.pointer.drag_obj; + /*If the drag limit is exceeded handle the dragging*/ if(proc->types.pointer.drag_limit_out != 0) { /*Set new position or scroll if the vector is not zero*/ if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) { - lv_coord_t prev_x = target_obj->coords.x1; - lv_coord_t prev_y = target_obj->coords.y1; + lv_coord_t prev_x = obj->coords.x1; + lv_coord_t prev_y = obj->coords.y1; /*Move the object. `drag_sum` is zerod out for *disabled direction*/ if(proc->types.pointer.drag_sum.x) act_x += proc->types.pointer.vect.x; @@ -1327,18 +1387,18 @@ static void indev_drag(lv_indev_proc_t * proc) if(scrollable) { lv_area_t child_box; - lv_obj_get_children_box(target_obj, &child_box); + lv_obj_get_children_box(obj, &child_box); lv_coord_t diff_y = proc->types.pointer.vect.y; - if(target_obj->scroll.y > 0 && diff_y > 0) { + if(obj->scroll.y > 0 && diff_y > 0) { diff_y = diff_y / 2; } - if(child_box.y2 < target_obj->coords.y2 && diff_y < 0) { + if(child_box.y2 < obj->coords.y2 && diff_y < 0) { diff_y = diff_y / 2; } - lv_obj_scroll_by(target_obj, 0, diff_y, LV_ANIM_OFF); + lv_obj_scroll_by(obj, 0, diff_y, LV_ANIM_OFF); } else { - lv_obj_set_pos(target_obj, act_x, act_y); + lv_obj_set_pos(obj, act_x, act_y); } proc->types.pointer.drag_in_prog = 1; @@ -1397,9 +1457,9 @@ static void indev_drag_throw(lv_indev_proc_t * proc) /*Reduce the vectors*/ proc->types.pointer.drag_throw_vect.x = - proc->types.pointer.drag_throw_vect.x * (100 - indev_act->driver.drag_throw) / 30; + proc->types.pointer.drag_throw_vect.x * (100 - indev_act->driver.drag_throw) / 100; proc->types.pointer.drag_throw_vect.y = - proc->types.pointer.drag_throw_vect.y * (100 - indev_act->driver.drag_throw) / 30; + proc->types.pointer.drag_throw_vect.y * (100 - indev_act->driver.drag_throw) / 100; switch(proc->types.pointer.drag_dir) { case LV_DRAG_DIR_HOR: @@ -1428,8 +1488,7 @@ static void indev_drag_throw(lv_indev_proc_t * proc) 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_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; lv_obj_get_coords(target_obj, &coords_ori); @@ -1463,6 +1522,7 @@ static void indev_drag_throw(lv_indev_proc_t * proc) signal*/ else { proc->types.pointer.drag_in_prog = 0; + proc->types.pointer.drag_obj = NULL; target_obj->signal_cb(target_obj, scrollable ? LV_SIGNAL_SCROLL_END : LV_SIGNAL_DRAG_END, indev_act); if(indev_reset_check(proc)) return; lv_event_send(target_obj, LV_EVENT_DRAG_END, NULL); @@ -1478,9 +1538,20 @@ static void indev_drag_throw(lv_indev_proc_t * proc) */ static lv_obj_t * get_dragged_obj(lv_obj_t * obj) { - return obj; + if(indev_act->proc.types.pointer.drag_obj) { + return indev_act->proc.types.pointer.drag_obj; + } else { + lv_area_t child_box; + lv_obj_get_children_box(obj, &child_box); + if(child_box.y2 == obj->coords.y2) indev_act->proc.types.pointer.drag_obj = lv_obj_get_parent(obj); + else indev_act->proc.types.pointer.drag_obj = obj; + } + + return indev_act->proc.types.pointer.drag_obj; + + if(obj == NULL) return NULL; lv_obj_t * drag_obj = obj; while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) { diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 49cfe7521..0bd559ba5 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -1157,6 +1157,43 @@ void lv_obj_scroll_to_y(lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en) lv_obj_scroll_by(obj, 0, y - obj->scroll.y, anim_en); } + +/** + * Return the height of the area above 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_top(lv_obj_t * obj) +{ + return -obj->scroll.y; +} + +/** + * Return the height of the area below the parent. + * That is the number of pixels the object can be scrolled up. + * Normally positive but can be negative when scrolled inside. + * @param obj + * @return + */ +lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_coord_t y2 = LV_COORD_MIN; + + lv_obj_t * child = lv_obj_get_child(obj, NULL); + if(child == NULL) return 0; + + while(child) { + y2 = LV_MATH_MAX(y2, child->coords.y2 + lv_obj_get_style_margin_bottom(child, LV_OBJ_PART_MAIN)); + child = lv_obj_get_child(obj, child); + } + + return y2 - obj->coords.y2; +} + /** * Set the size of an extended clickable area * If TINY mode is used, only the largest of the horizontal and vertical padding diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 7533b4c3a..c914616ea 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -534,6 +534,66 @@ void lv_obj_realign(lv_obj_t * obj); */ void lv_obj_set_auto_realign(lv_obj_t * obj, bool en); +/** + * Moves all children with horizontally or vertically. + * It doesn't take into account any limits so any values are possible + * @param obj pointer to an object whose children should be moved + * @param x pixel to move horizontally + * @param y pixels to move vertically + */ +void lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y); + +/** + * Moves all children with horizontally or vertically. + * Limits the scroll to the bounding box of the children. + * @param obj pointer to an object whose children should be moved + * @param x pixel to move horizontally + * @param y pixels to move vertically + */ +void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en); + +/** + * Scroll the a given x coordinate to the left side of obj. + * @param obj pointer to an object which should be scrolled + * @param x the x coordinate to scroll to + * @param y the y coordinate to scroll to + */ +void lv_obj_scroll_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en); + +/** + * Scroll the a given x coordinate to the left side of obj. + * @param obj pointer to an object which should be scrolled + * @param x the x coordinate to scroll to + */ +void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en); + +/** + * Scroll the a given y coordinate to the top side of obj. + * @param obj pointer to an object which should be scrolled + * @param y the y coordinate to scroll to + */ +void lv_obj_scroll_to_y(lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en); + + +/** + * Return the height of the area above 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_top(lv_obj_t * obj); + +/** + * Return the height of the area below the parent. + * That is the number of pixels the object can be scrolled up. + * Normally positive but can be negative when scrolled inside. + * @param obj + * @return + */ +lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj); + + /** * Set the size of an extended clickable area * @param obj pointer to an object diff --git a/src/lv_hal/lv_hal_indev.h b/src/lv_hal/lv_hal_indev.h index 1d4f77e7a..6f77ccef2 100644 --- a/src/lv_hal/lv_hal_indev.h +++ b/src/lv_hal/lv_hal_indev.h @@ -139,6 +139,7 @@ typedef struct _lv_indev_proc_t { struct _lv_obj_t * act_obj; /*The object being pressed*/ struct _lv_obj_t * last_obj; /*The last object which was pressed (used by drag_throw and other post-release event)*/ + struct _lv_obj_t * drag_obj; /*The object being pressed*/ struct _lv_obj_t * last_pressed; /*The lastly pressed object*/ lv_gesture_dir_t gesture_dir; From ce0fb2da4d7d078a2965f39bec700b711350a20a Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 8 Jul 2020 20:07:10 +0200 Subject: [PATCH 06/84] scroll: add scroll chain --- src/lv_core/lv_indev.c | 153 +++++++++++++++----------------------- src/lv_core/lv_obj.c | 4 + src/lv_hal/lv_hal_indev.h | 1 + 3 files changed, 64 insertions(+), 94 deletions(-) diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 775c484f3..3ec8ae962 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -940,18 +940,8 @@ static void indev_proc_press(lv_indev_proc_t * proc) proc->types.pointer.vect.x = proc->types.pointer.act_point.x - proc->types.pointer.last_point.x; proc->types.pointer.vect.y = proc->types.pointer.act_point.y - proc->types.pointer.last_point.y; - proc->types.pointer.drag_throw_vect.x = (proc->types.pointer.drag_throw_vect.x * 5) >> 3; - proc->types.pointer.drag_throw_vect.y = (proc->types.pointer.drag_throw_vect.y * 5) >> 3; - - if(proc->types.pointer.drag_throw_vect.x < 0) - proc->types.pointer.drag_throw_vect.x++; - else if(proc->types.pointer.drag_throw_vect.x > 0) - proc->types.pointer.drag_throw_vect.x--; - - if(proc->types.pointer.drag_throw_vect.y < 0) - proc->types.pointer.drag_throw_vect.y++; - else if(proc->types.pointer.drag_throw_vect.y > 0) - proc->types.pointer.drag_throw_vect.y--; + proc->types.pointer.drag_throw_vect.x = (proc->types.pointer.drag_throw_vect.x * 4) >> 3; + proc->types.pointer.drag_throw_vect.y = (proc->types.pointer.drag_throw_vect.y * 4) >> 3; proc->types.pointer.drag_throw_vect.x += (proc->types.pointer.vect.x * 4) >> 3; proc->types.pointer.drag_throw_vect.y += (proc->types.pointer.vect.y * 4) >> 3; @@ -1254,12 +1244,10 @@ static void indev_drag(lv_indev_proc_t * proc) { bool scrollable = true; - /*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); - bool just_started = false; - lv_coord_t act_x = 0; lv_coord_t act_y = 0; + lv_obj_t * scroll_candidate_obj = NULL; + lv_drag_dir_t dirs_candidate = LV_DRAG_DIR_NONE; /*Count the movement by drag*/ if(proc->types.pointer.drag_limit_out == 0) { @@ -1270,19 +1258,14 @@ 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) { - dirs = LV_DRAG_DIR_VER; + /*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); /*Enough move?*/ bool hor_en = false; bool ver_en = false; - if(dirs == LV_DRAG_DIR_HOR || dirs == LV_DRAG_DIR_BOTH) { - hor_en = true; - } - - if(dirs == LV_DRAG_DIR_VER || dirs == LV_DRAG_DIR_BOTH) { - ver_en = true; - } - + if(dirs == LV_DRAG_DIR_HOR || dirs == LV_DRAG_DIR_BOTH) hor_en = true; + if(dirs == LV_DRAG_DIR_VER || dirs == LV_DRAG_DIR_BOTH) ver_en = true; if(dirs == LV_DRAG_DIR_ONE) { if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { hor_en = true; @@ -1294,16 +1277,30 @@ static void indev_drag(lv_indev_proc_t * proc) bool up_en = ver_en; bool down_en = ver_en; + bool left_en = hor_en; + bool right_en = hor_en; + + 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); + + 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)) + { + scroll_candidate_obj = proc->types.pointer.drag_obj; + dirs_candidate = LV_DRAG_DIR_VER; + } + + if(st <= 0) up_en = false; + if(sb <= 0) down_en = false; - if(lv_obj_get_scroll_top(proc->types.pointer.drag_obj) <= 0) up_en = false; - if(lv_obj_get_scroll_bottom(proc->types.pointer.drag_obj) <= 0) down_en = false; /*If a move is greater then LV_DRAG_LIMIT then begin the drag*/ - if((hor_en && LV_MATH_ABS(proc->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) || - (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)) { + if((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) || + (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)) + { proc->types.pointer.drag_limit_out = 1; - just_started = true; if(dirs == LV_DRAG_DIR_ONE) { proc->types.pointer.drag_dir = hor_en ? LV_DRAG_DIR_HOR : LV_DRAG_DIR_VER; } else { @@ -1324,50 +1321,15 @@ static void indev_drag(lv_indev_proc_t * proc) /*If the drag/scroll can't be propagated to any parent show an elastic scroll in the original object*/ if(proc->types.pointer.drag_obj == NULL) { - proc->types.pointer.drag_obj = proc->types.pointer.act_obj; -// -// dirs = LV_DRAG_DIR_VER; -// -// /*Enough move?*/ -// bool hor_en = false; -// bool ver_en = false; -// if(dirs == LV_DRAG_DIR_HOR || dirs == LV_DRAG_DIR_BOTH) { -// hor_en = true; -// } -// -// if(dirs == LV_DRAG_DIR_VER || dirs == LV_DRAG_DIR_BOTH) { -// ver_en = true; -// } -// -// if(dirs == LV_DRAG_DIR_ONE) { -// if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { -// hor_en = true; -// } -// else { -// ver_en = true; -// } -// } -// -// /*If a move is greater then LV_DRAG_LIMIT then begin the drag*/ -// if((hor_en && LV_MATH_ABS(proc->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) || -// (ver_en && LV_MATH_ABS(proc->types.pointer.drag_sum.y) >= indev_act->driver.drag_limit)) { -// proc->types.pointer.drag_limit_out = 1; -// just_started = true; -// if(dirs == LV_DRAG_DIR_ONE) { -// proc->types.pointer.drag_dir = hor_en ? LV_DRAG_DIR_HOR : LV_DRAG_DIR_VER; -// } else { -// proc->types.pointer.drag_dir = dirs; -// } -// -// /*The was no move due to drag limit. Compensate it now.*/ -// if(!hor_en) proc->types.pointer.drag_sum.x = 0; -// if(!ver_en) proc->types.pointer.drag_sum.y = 0; -// -// act_x = lv_obj_get_x(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.x; -// act_y = lv_obj_get_y(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.y; -// } - + if(scroll_candidate_obj) { + proc->types.pointer.drag_limit_out = 1; + proc->types.pointer.drag_dir = dirs_candidate; + proc->types.pointer.drag_obj = scroll_candidate_obj; + } else { + return; + } } + lv_obj_t * obj = proc->types.pointer.drag_obj; /*If the drag limit is exceeded handle the dragging*/ @@ -1442,7 +1404,7 @@ static void indev_drag_throw(lv_indev_proc_t * proc) bool scrollable = true; /*Get which object to drad/scroll*/ - lv_obj_t * target_obj = get_dragged_obj(proc->types.pointer.last_obj); + lv_obj_t * target_obj = proc->types.pointer.drag_obj; if(target_obj == NULL) return; /*Return if the drag throw is not enabled*/ @@ -1462,31 +1424,34 @@ static void indev_drag_throw(lv_indev_proc_t * proc) proc->types.pointer.drag_throw_vect.y * (100 - indev_act->driver.drag_throw) / 100; switch(proc->types.pointer.drag_dir) { - case LV_DRAG_DIR_HOR: - proc->types.pointer.drag_throw_vect.y = 0; - break; - case LV_DRAG_DIR_VER: - proc->types.pointer.drag_throw_vect.x = 0; - break; + case LV_DRAG_DIR_HOR: + proc->types.pointer.drag_throw_vect.y = 0; + break; + case LV_DRAG_DIR_VER: + { + proc->types.pointer.drag_throw_vect.x = 0; + lv_coord_t st = lv_obj_get_scroll_top(target_obj); + lv_coord_t sb = lv_obj_get_scroll_bottom(target_obj); + /*If scrolled inside reduce faster*/ + if(st < 0 || sb < 0) proc->types.pointer.drag_throw_vect.y = proc->types.pointer.drag_throw_vect.y >> 1; + break; + } } - lv_area_t child_box; - lv_obj_get_children_box(target_obj, &child_box); - if((target_obj->scroll.y < 0 && child_box.y2 > target_obj->coords.y2) && - (proc->types.pointer.drag_throw_vect.x != 0 || proc->types.pointer.drag_throw_vect.y != 0)) { + 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); - } +// 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 { diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 0bd559ba5..8ef882f83 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -3849,6 +3849,7 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area lv_draw_mask_add(mp, obj + 8); } + if(lv_obj_get_screen(obj) == lv_scr_act()) { lv_area_t sb; if(get_scrollbar_area(obj, &sb)) { lv_draw_rect_dsc_t sb_rect_dsc; @@ -3856,6 +3857,7 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area sb_rect_dsc.bg_color = LV_COLOR_RED; lv_draw_rect(&sb, clip_area, &sb_rect_dsc); } + } } else if(mode == LV_DESIGN_DRAW_POST) { if(lv_obj_get_style_clip_corner(obj, LV_OBJ_PART_MAIN)) { @@ -4548,6 +4550,8 @@ static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv) return LV_RES_OK; } lv_coord_t sb_y = (rem * (child_box.y2 - obj->coords.y2)) / scroll_h; + sb_y = rem - sb_y; + sbv->y1 = obj->coords.y1 + sb_y; sbv->y2 = sbv->y1 + sb_h; diff --git a/src/lv_hal/lv_hal_indev.h b/src/lv_hal/lv_hal_indev.h index 6f77ccef2..a4af05936 100644 --- a/src/lv_hal/lv_hal_indev.h +++ b/src/lv_hal/lv_hal_indev.h @@ -52,6 +52,7 @@ typedef uint8_t lv_indev_state_t; enum { + LV_DRAG_DIR_NONE = 0x0, /**< Object can't be dragged to any directions. */ LV_DRAG_DIR_HOR = 0x1, /**< Object can be dragged horizontally. */ LV_DRAG_DIR_VER = 0x2, /**< Object can be dragged vertically. */ LV_DRAG_DIR_BOTH = 0x3, /**< Object can be dragged in all directions. */ From f3a1028064c3c6e3600345e0c3bac89c4dc962ff Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 14 Jul 2020 15:23:20 +0200 Subject: [PATCH 07/84] scroll: handle horizontayl scrolling --- src/lv_core/lv_indev.c | 49 +++++++++------ src/lv_core/lv_obj.c | 133 ++++++++++++++++++++++++++++++++++------- src/lv_core/lv_obj.h | 18 ++++++ 3 files changed, 159 insertions(+), 41 deletions(-) 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 From a86e03371f60a642a973efaed9bbdebe21715ec8 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 14 Jul 2020 20:07:49 +0200 Subject: [PATCH 08/84] scroll: handle styles --- src/lv_core/lv_obj.c | 195 +++++++++++++++++++++------------ src/lv_core/lv_obj.h | 1 + src/lv_core/lv_obj_style_dec.h | 10 ++ src/lv_core/lv_style.h | 10 ++ 4 files changed, 145 insertions(+), 71 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 876115330..e47033428 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -48,6 +48,7 @@ #define LV_OBJX_NAME "lv_obj" #define LV_OBJ_DEF_WIDTH (LV_DPX(100)) #define LV_OBJ_DEF_HEIGHT (LV_DPX(50)) +#define SCROLLBAR_MIN_SIZE (LV_DPX(10)) /********************** * TYPEDEFS @@ -104,8 +105,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_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 lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc); +static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, const lv_area_t * clip_area); /********************** * STATIC VARIABLES @@ -3882,25 +3883,22 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ lv_draw_mask_add(mp, obj + 8); } - - if(lv_obj_get_screen(obj) == lv_scr_act()) { - lv_area_t 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) { + + if(lv_obj_get_screen(obj) == lv_scr_act()) { + lv_draw_rect_dsc_t sb_rect_dsc; + lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &sb_rect_dsc); + if(sb_res == LV_RES_OK) { + lv_area_t hor_area; + lv_area_t ver_area; + scrollbar_get_area(obj, &hor_area, &ver_area, clip_area); + + lv_draw_rect(&hor_area, clip_area, &sb_rect_dsc); + lv_draw_rect(&ver_area, clip_area, &sb_rect_dsc); + } + } + if(lv_obj_get_style_clip_corner(obj, LV_OBJ_PART_MAIN)) { lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8); _lv_mem_buf_release(param); @@ -4583,71 +4581,126 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin return false; } -static lv_res_t get_ver_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv) +static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc) { - lv_coord_t obj_h = lv_obj_get_height(obj); + lv_draw_rect_dsc_init(dsc); + dsc->bg_opa = 100;//lv_obj_get_style_scrollbar_bg_opa(obj, LV_OBJ_PART_MAIN); + if(dsc->bg_opa > LV_OPA_MIN) { + dsc->bg_color = lv_obj_get_style_scrollbar_bg_color(obj, LV_OBJ_PART_MAIN); + } - lv_area_t child_box; - lv_res_t res = lv_obj_get_children_box(obj, &child_box); - if(res != LV_RES_OK) return res; + dsc->border_opa = lv_obj_get_style_scrollbar_border_opa(obj, LV_OBJ_PART_MAIN); + if(dsc->border_opa > LV_OPA_MIN) { + dsc->border_width = lv_obj_get_style_scrollbar_border_opa(obj, LV_OBJ_PART_MAIN); + if(dsc->border_width > 0) { + dsc->border_color = lv_obj_get_style_scrollbar_border_color(obj, LV_OBJ_PART_MAIN); + } else { + dsc->border_opa = LV_OPA_TRANSP; + } + } - lv_coord_t content_h = (child_box.y2 - obj->scroll.y) - obj->coords.y1 ; - if(content_h < obj_h) { + if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP) { + dsc->radius = 20;//lv_obj_get_style_scrollbar_radius(obj, LV_OBJ_PART_MAIN); + return LV_RES_OK; + } else { return LV_RES_INV; } - lv_coord_t sb_h = (obj_h * obj_h) / content_h; - 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) { - sbv->y1 = obj->coords.y1; - sbv->y2 = obj->coords.y2; - sbv->x2 = obj->coords.x2; - sbv->x1 = sbv->x2 - 10; - return LV_RES_OK; - } - lv_coord_t sb_y = (rem * (child_box.y2 - obj->coords.y2)) / scroll_h; - sb_y = rem - sb_y; - - - sbv->y1 = obj->coords.y1 + sb_y; - sbv->y2 = sbv->y1 + sb_h; - sbv->x2 = obj->coords.x2; - sbv->x1 = sbv->x2 - 10; - - return LV_RES_OK; } -static lv_res_t get_hor_scrollbar_area(lv_obj_t * obj, lv_area_t * sbh) +static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, const lv_area_t * clip_area) { + lv_coord_t end_space = lv_obj_get_style_scrollbar_space_end(obj, LV_OBJ_PART_MAIN); + lv_coord_t side_space = lv_obj_get_style_scrollbar_space_side(obj, LV_OBJ_PART_MAIN); + lv_coord_t tickness = 10;//lv_obj_get_style_scrollbar_width(obj, LV_OBJ_PART_MAIN); + + lv_coord_t obj_h = lv_obj_get_height(obj); 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 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); - 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 ver_reg_space = tickness + side_space; + lv_coord_t hor_req_space = tickness + side_space; + lv_coord_t rem; + + ver->y1 = obj->coords.y1; + ver->y2 = obj->coords.y2; + ver->x2 = obj->coords.x2; + ver->x1 = ver->x2 - tickness; + + if(_lv_area_is_on(ver, clip_area)) { + printf("v\n"); + lv_coord_t content_h = obj_h + st + sb; + lv_coord_t sb_h = ((obj_h - end_space * 2 - hor_req_space) * obj_h) / content_h; + sb_h = LV_MATH_MAX(sb_h, SCROLLBAR_MIN_SIZE); + rem = (obj_h - end_space * 2 - hor_req_space) - 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) { + ver->y1 = obj->coords.y1 + end_space; + ver->y2 = obj->coords.y2 - end_space - hor_req_space; + ver->x2 = obj->coords.x2; + ver->x1 = ver->x2 - tickness; + } else { + lv_coord_t sb_y = (rem * sb) / scroll_h; + sb_y = rem - sb_y; + + ver->y1 = obj->coords.y1 + sb_y + end_space; + ver->y2 = ver->y1 + sb_h; + ver->x2 = obj->coords.x2; + ver->x1 = ver->x2 - tickness; + if(ver->y1 < obj->coords.y1) { + ver->y1 = obj->coords.y1; + if(ver->y1 + SCROLLBAR_MIN_SIZE > ver->y2) ver->y2 = ver->y1 + SCROLLBAR_MIN_SIZE; + } + if(ver->y2 > obj->coords.y2) { + ver->y2 = obj->coords.y2; + if(ver->y2 - SCROLLBAR_MIN_SIZE < ver->y1) ver->y1 = ver->y2 - SCROLLBAR_MIN_SIZE; + } + } + } else { + /*Set an invalid area if not in the clip area*/ + lv_area_set(ver, -1, -1, -2, -2); } - 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; + + hor->y2 = obj->coords.y2; + hor->y1 = hor->y2 - tickness; + hor->x1 = obj->coords.x1; + hor->x2 = obj->coords.x2; + if(_lv_area_is_on(hor, clip_area)) { + printf("h\n"); + lv_coord_t content_w = obj_w + sl + sr; + lv_coord_t sb_w = ((obj_w - end_space * 2 - ver_reg_space) * obj_w) / content_w; + sb_w = LV_MATH_MAX(sb_w, SCROLLBAR_MIN_SIZE); + rem = (obj_w - end_space * 2 - ver_reg_space) - sb_w; /*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) { + hor->y2 = obj->coords.y2; + hor->y1 = hor->y2 - tickness; + hor->x1 = obj->coords.x1 + end_space; + hor->x2 = obj->coords.x2 - end_space - ver_reg_space; + } else { + lv_coord_t sb_x = (rem * sr) / scroll_w; + sb_x = rem - sb_x; + + hor->x1 = obj->coords.x1 + sb_x + end_space; + hor->x2 = hor->x1 + sb_w; + hor->y2 = obj->coords.y2; + hor->y1 = hor->y2 - tickness; + if(hor->x1 < obj->coords.x1) { + hor->x1 = obj->coords.x1; + if(hor->x1 + SCROLLBAR_MIN_SIZE > hor->x2) hor->x2 = hor->x1 + SCROLLBAR_MIN_SIZE; + } + if(hor->x2 > obj->coords.x2) { + hor->x2 = obj->coords.x2; + if(hor->x2 - SCROLLBAR_MIN_SIZE < hor->x1) hor->x1 = hor->x2 - SCROLLBAR_MIN_SIZE; + } + } + } else { + /*Set an invalid area if not in the clip area*/ + lv_area_set(hor, -1, -1, -2, -2); } - 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 a9acb7bef..f2e01a33f 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -230,6 +230,7 @@ typedef struct _lv_obj_t { uint8_t adv_hittest : 1; /**< 1: Use advanced hit-testing (slower) */ uint8_t gesture_parent : 1; /**< 1: Parent will be gesture instead*/ uint8_t focus_parent : 1; /**< 1: Parent will be focused instead*/ + lv_drag_dir_t scroll_elastic : 3; /**< In which directions the object can be scrolled */ lv_drag_dir_t drag_dir : 3; /**< In which directions the object can be dragged */ lv_drag_dir_t scroll_dir : 3; /**< In which directions the object can be scrolled */ diff --git a/src/lv_core/lv_obj_style_dec.h b/src/lv_core/lv_obj_style_dec.h index 47751597e..839005fc9 100644 --- a/src/lv_core/lv_obj_style_dec.h +++ b/src/lv_core/lv_obj_style_dec.h @@ -197,6 +197,16 @@ _LV_OBJ_STYLE_SET_GET_DECLARE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_sty _LV_OBJ_STYLE_SET_GET_DECLARE(SCALE_GRAD_COLOR, scale_grad_color, lv_color_t, _color, nonscalar) _LV_OBJ_STYLE_SET_GET_DECLARE(SCALE_END_COLOR, scale_end_color, lv_color_t, _color, nonscalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_WIDTH, scrollbar_width, lv_style_int_t, _int, scalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_SPACE_SIDE, scrollbar_space_side, lv_style_int_t, _int, scalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_SPACE_END, scrollbar_space_end, lv_style_int_t, _int, scalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_RADIUS, scrollbar_radius, lv_style_int_t, _int, scalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_BORDER_WIDTH, scrollbar_border_width, lv_style_int_t, _int, scalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_BG_COLOR, scrollbar_bg_color, lv_color_t, _color, nonscalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_BORDER_COLOR, scrollbar_border_color, lv_color_t, _color, nonscalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_BG_OPA, scrollbar_bg_opa, lv_opa_t, _opa, scalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_BORDER_OPA, scrollbar_border_opa, lv_opa_t, _opa, scalar) + #undef _LV_OBJ_STYLE_SET_GET_DECLARE diff --git a/src/lv_core/lv_style.h b/src/lv_core/lv_style.h index 5909299b6..a5602675d 100644 --- a/src/lv_core/lv_style.h +++ b/src/lv_core/lv_style.h @@ -197,6 +197,16 @@ enum { LV_STYLE_PROP_INIT(LV_STYLE_SCALE_END_LINE_WIDTH, 0xC, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SCALE_GRAD_COLOR, 0xC, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SCALE_END_COLOR, 0xC, LV_STYLE_ID_COLOR + 1, LV_STYLE_ATTR_NONE), + + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_WIDTH, 0xD, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_SPACE_SIDE, 0xD, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_SPACE_END, 0xD, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_RADIUS, 0xD, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_BORDER_WIDTH, 0xD, LV_STYLE_ID_VALUE + 4, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_BG_COLOR, 0xD, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_BORDER_COLOR, 0xD, LV_STYLE_ID_COLOR + 1, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_BG_OPA, 0xD, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_BORDER_OPA, 0xD, LV_STYLE_ID_OPA + 1, LV_STYLE_ATTR_NONE), }; typedef uint16_t lv_style_property_t; From 01a78485aaeaa6589295232cefe5c619c40ffef1 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 16 Jul 2020 13:06:32 +0200 Subject: [PATCH 09/84] scroll: set default style values --- src/lv_core/lv_obj.c | 28 ++++++++++++++-------------- src/lv_core/lv_obj_style_dec.h | 2 +- src/lv_core/lv_style.h | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index e47033428..5b1c9c068 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -1190,7 +1190,7 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj) child = lv_obj_get_child(obj, child); } - return y2 - obj->coords.y2; + return y2 - obj->coords.y2 + lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN); } /** @@ -1226,7 +1226,7 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj) child = lv_obj_get_child(obj, child); } - return x2 - obj->coords.x2; + return x2 - obj->coords.x2 + lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN); } /** @@ -2697,6 +2697,8 @@ lv_style_int_t _lv_obj_get_style_int(const lv_obj_t * obj, uint8_t part, lv_styl return 255; case LV_STYLE_TRANSFORM_ZOOM: return LV_IMG_ZOOM_NONE; + case LV_STYLE_SCROLLBAR_TICKNESS: + return LV_DPX(10); } return 0; @@ -4584,14 +4586,14 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc) { lv_draw_rect_dsc_init(dsc); - dsc->bg_opa = 100;//lv_obj_get_style_scrollbar_bg_opa(obj, LV_OBJ_PART_MAIN); + dsc->bg_opa = lv_obj_get_style_scrollbar_bg_opa(obj, LV_OBJ_PART_MAIN); if(dsc->bg_opa > LV_OPA_MIN) { dsc->bg_color = lv_obj_get_style_scrollbar_bg_color(obj, LV_OBJ_PART_MAIN); } dsc->border_opa = lv_obj_get_style_scrollbar_border_opa(obj, LV_OBJ_PART_MAIN); if(dsc->border_opa > LV_OPA_MIN) { - dsc->border_width = lv_obj_get_style_scrollbar_border_opa(obj, LV_OBJ_PART_MAIN); + dsc->border_width = lv_obj_get_style_scrollbar_border_width(obj, LV_OBJ_PART_MAIN); if(dsc->border_width > 0) { dsc->border_color = lv_obj_get_style_scrollbar_border_color(obj, LV_OBJ_PART_MAIN); } else { @@ -4600,7 +4602,7 @@ static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc } if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP) { - dsc->radius = 20;//lv_obj_get_style_scrollbar_radius(obj, LV_OBJ_PART_MAIN); + dsc->radius = lv_obj_get_style_scrollbar_radius(obj, LV_OBJ_PART_MAIN); return LV_RES_OK; } else { return LV_RES_INV; @@ -4611,7 +4613,7 @@ static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, { lv_coord_t end_space = lv_obj_get_style_scrollbar_space_end(obj, LV_OBJ_PART_MAIN); lv_coord_t side_space = lv_obj_get_style_scrollbar_space_side(obj, LV_OBJ_PART_MAIN); - lv_coord_t tickness = 10;//lv_obj_get_style_scrollbar_width(obj, LV_OBJ_PART_MAIN); + lv_coord_t tickness = lv_obj_get_style_scrollbar_tickness(obj, LV_OBJ_PART_MAIN); lv_coord_t obj_h = lv_obj_get_height(obj); lv_coord_t obj_w = lv_obj_get_width(obj); @@ -4631,7 +4633,6 @@ static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, ver->x1 = ver->x2 - tickness; if(_lv_area_is_on(ver, clip_area)) { - printf("v\n"); lv_coord_t content_h = obj_h + st + sb; lv_coord_t sb_h = ((obj_h - end_space * 2 - hor_req_space) * obj_h) / content_h; sb_h = LV_MATH_MAX(sb_h, SCROLLBAR_MIN_SIZE); @@ -4639,15 +4640,15 @@ static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, lv_coord_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/ if(scroll_h <= 0) { ver->y1 = obj->coords.y1 + end_space; - ver->y2 = obj->coords.y2 - end_space - hor_req_space; + ver->y2 = obj->coords.y2 - end_space - hor_req_space - 1; ver->x2 = obj->coords.x2; - ver->x1 = ver->x2 - tickness; + ver->x1 = ver->x2 - tickness + 1; } else { lv_coord_t sb_y = (rem * sb) / scroll_h; sb_y = rem - sb_y; ver->y1 = obj->coords.y1 + sb_y + end_space; - ver->y2 = ver->y1 + sb_h; + ver->y2 = ver->y1 + sb_h - 1; ver->x2 = obj->coords.x2; ver->x1 = ver->x2 - tickness; if(ver->y1 < obj->coords.y1) { @@ -4669,7 +4670,6 @@ static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, hor->x1 = obj->coords.x1; hor->x2 = obj->coords.x2; if(_lv_area_is_on(hor, clip_area)) { - printf("h\n"); lv_coord_t content_w = obj_w + sl + sr; lv_coord_t sb_w = ((obj_w - end_space * 2 - ver_reg_space) * obj_w) / content_w; sb_w = LV_MATH_MAX(sb_w, SCROLLBAR_MIN_SIZE); @@ -4677,15 +4677,15 @@ static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, lv_coord_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/ if(scroll_w <= 0) { hor->y2 = obj->coords.y2; - hor->y1 = hor->y2 - tickness; + hor->y1 = hor->y2 - tickness + 1; hor->x1 = obj->coords.x1 + end_space; - hor->x2 = obj->coords.x2 - end_space - ver_reg_space; + hor->x2 = obj->coords.x2 - end_space - ver_reg_space - 1; } else { lv_coord_t sb_x = (rem * sr) / scroll_w; sb_x = rem - sb_x; hor->x1 = obj->coords.x1 + sb_x + end_space; - hor->x2 = hor->x1 + sb_w; + hor->x2 = hor->x1 + sb_w - 1; hor->y2 = obj->coords.y2; hor->y1 = hor->y2 - tickness; if(hor->x1 < obj->coords.x1) { diff --git a/src/lv_core/lv_obj_style_dec.h b/src/lv_core/lv_obj_style_dec.h index 839005fc9..8876412c3 100644 --- a/src/lv_core/lv_obj_style_dec.h +++ b/src/lv_core/lv_obj_style_dec.h @@ -197,7 +197,7 @@ _LV_OBJ_STYLE_SET_GET_DECLARE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_sty _LV_OBJ_STYLE_SET_GET_DECLARE(SCALE_GRAD_COLOR, scale_grad_color, lv_color_t, _color, nonscalar) _LV_OBJ_STYLE_SET_GET_DECLARE(SCALE_END_COLOR, scale_end_color, lv_color_t, _color, nonscalar) -_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_WIDTH, scrollbar_width, lv_style_int_t, _int, scalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_TICKNESS, scrollbar_tickness, lv_style_int_t, _int, scalar) _LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_SPACE_SIDE, scrollbar_space_side, lv_style_int_t, _int, scalar) _LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_SPACE_END, scrollbar_space_end, lv_style_int_t, _int, scalar) _LV_OBJ_STYLE_SET_GET_DECLARE(SCROLLBAR_RADIUS, scrollbar_radius, lv_style_int_t, _int, scalar) diff --git a/src/lv_core/lv_style.h b/src/lv_core/lv_style.h index a5602675d..5af62ec3f 100644 --- a/src/lv_core/lv_style.h +++ b/src/lv_core/lv_style.h @@ -198,7 +198,7 @@ enum { LV_STYLE_PROP_INIT(LV_STYLE_SCALE_GRAD_COLOR, 0xC, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SCALE_END_COLOR, 0xC, LV_STYLE_ID_COLOR + 1, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_WIDTH, 0xD, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_TICKNESS, 0xD, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_SPACE_SIDE, 0xD, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_SPACE_END, 0xD, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SCROLLBAR_RADIUS, 0xD, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_NONE), From 5cce6daa4a2fb38fbe04ea7ea6198a271220963b Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 21 Jul 2020 21:09:33 +0200 Subject: [PATCH 10/84] scroll: remove drag --- src/lv_core/lv_indev.c | 493 +++++++++++------------------------ src/lv_core/lv_indev.h | 20 +- src/lv_core/lv_obj.c | 120 ++------- src/lv_core/lv_obj.h | 119 +++------ src/lv_hal/lv_hal_indev.c | 4 +- src/lv_hal/lv_hal_indev.h | 24 +- src/lv_widgets/lv_btn.c | 2 +- src/lv_widgets/lv_cpicker.c | 4 +- src/lv_widgets/lv_dropdown.c | 6 +- src/lv_widgets/lv_list.c | 4 +- src/lv_widgets/lv_page.c | 2 +- src/lv_widgets/lv_roller.c | 2 +- src/lv_widgets/lv_tileview.c | 4 +- 13 files changed, 222 insertions(+), 582 deletions(-) diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index a415dc1ec..2be5474d9 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -40,9 +40,8 @@ static void indev_proc_press(lv_indev_proc_t * proc); static void indev_proc_release(lv_indev_proc_t * proc); static void indev_proc_reset_query_handler(lv_indev_t * indev); static void indev_click_focus(lv_indev_proc_t * proc); -static void indev_drag(lv_indev_proc_t * proc); -static void indev_drag_throw(lv_indev_proc_t * proc); -static lv_obj_t * get_dragged_obj(lv_obj_t * obj); +static void indev_scroll_handler(lv_indev_proc_t * proc); +static void indev_scroll_throw_handler(lv_indev_proc_t * proc); static void indev_gesture(lv_indev_proc_t * proc); static bool indev_reset_check(lv_indev_proc_t * proc); @@ -288,20 +287,21 @@ uint32_t lv_indev_get_key(const lv_indev_t * indev) } /** - * Check if there is dragging with an input device or not (for LV_INDEV_TYPE_POINTER and + * Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and * LV_INDEV_TYPE_BUTTON) * @param indev pointer to an input device - * @return true: drag is in progress + * @return LV_SCROLL_DIR_NONE: no scrolling now + * LV_SCROLL_DIR_HOR/VER */ -bool lv_indev_is_dragging(const lv_indev_t * indev) +lv_scroll_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev) { if(indev == NULL) return false; if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) return false; - return indev->proc.types.pointer.drag_in_prog == 0 ? false : true; + return indev->proc.types.pointer.scroll_dir; } /** - * Get the types.pointer.vector of dragging of an input device (for LV_INDEV_TYPE_POINTER and + * Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and * LV_INDEV_TYPE_BUTTON) * @param indev pointer to an input device * @param point pointer to a point to store the types.pointer.vector @@ -324,36 +324,6 @@ void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point) } } -/** - * Manually finish dragging. - * `LV_SIGNAL_DRAG_END` and `LV_EVENT_DRAG_END` will be sent. - * @param indev pointer to an input device - * @return `LV_RES_INV` if the object being dragged was deleted. Else `LV_RES_OK`. - */ -lv_res_t lv_indev_finish_drag(lv_indev_t * indev) -{ - if(indev == NULL) return LV_RES_OK; - if(indev->driver.type != LV_INDEV_TYPE_POINTER) return LV_RES_OK; - if(indev->proc.types.pointer.drag_in_prog == 0) return LV_RES_OK; - - indev->proc.types.pointer.drag_in_prog = 0; - indev->proc.types.pointer.drag_throw_vect.x = 0; - indev->proc.types.pointer.drag_throw_vect.y = 0; - - lv_obj_t * drag_obj; - drag_obj = get_dragged_obj(indev->proc.types.pointer.act_obj); - if(drag_obj == NULL) return LV_RES_OK; - - lv_res_t res; - res = drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, NULL); - if(res != LV_RES_OK) return res; - - res = lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL); - if(res != LV_RES_OK) return res; - - return res; -} - /** * Do nothing until the next release * @param indev pointer to an input device @@ -846,8 +816,8 @@ static void indev_proc_press(lv_indev_proc_t * proc) &proc->types.pointer.act_point); new_obj_searched = true; } - /*If there is last object but it is not dragged and not protected also search*/ - else if(proc->types.pointer.drag_in_prog == 0 && + /*If there is last object but it is not scrolled and not protected also search*/ + else if(proc->types.pointer.scroll_obj == NULL && lv_obj_is_protected(indev_obj_act, LV_PROTECT_PRESS_LOST) == false) { indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), @@ -856,15 +826,12 @@ static void indev_proc_press(lv_indev_proc_t * proc) &proc->types.pointer.act_point); new_obj_searched = true; } - /*If a draggable or a protected object was the last then keep it*/ - else { - } - /*The last object might have drag throw. Stop it manually*/ + /*The last object might have scroll throw. Stop it manually*/ if(new_obj_searched && proc->types.pointer.last_obj) { - proc->types.pointer.drag_throw_vect.x = 0; - proc->types.pointer.drag_throw_vect.y = 0; - indev_drag_throw(proc); + proc->types.pointer.scroll_throw_vect.x = 0; + proc->types.pointer.scroll_throw_vect.y = 0; + indev_scroll_throw_handler(proc); } /*Do not use disabled objects*/ @@ -882,11 +849,10 @@ static void indev_proc_press(lv_indev_proc_t * proc) /*Save the obj because in special cases `act_obj` can change in the signal function*/ lv_obj_t * last_obj = proc->types.pointer.act_obj; - last_obj->signal_cb(last_obj, LV_SIGNAL_PRESS_LOST, indev_act); + lv_signal_send(last_obj, LV_SIGNAL_PRESS_LOST, indev_act); if(indev_reset_check(proc)) return; lv_event_send(last_obj, LV_EVENT_PRESS_LOST, NULL); if(indev_reset_check(proc)) return; - } proc->types.pointer.act_obj = indev_obj_act; /*Save the pressed object*/ @@ -896,11 +862,9 @@ static void indev_proc_press(lv_indev_proc_t * proc) /* Save the time when the obj pressed to count long press time.*/ proc->pr_timestamp = lv_tick_get(); proc->long_pr_sent = 0; - proc->types.pointer.drag_limit_out = 0; - proc->types.pointer.drag_in_prog = 0; - proc->types.pointer.drag_sum.x = 0; - proc->types.pointer.drag_sum.y = 0; - proc->types.pointer.drag_dir = LV_DRAG_DIR_BOTH; + proc->types.pointer.scroll_sum.x = 0; + proc->types.pointer.scroll_sum.y = 0; + proc->types.pointer.scroll_dir = LV_SCROLL_DIR_NONE; proc->types.pointer.gesture_sent = 0; proc->types.pointer.gesture_sum.x = 0; proc->types.pointer.gesture_sum.y = 0; @@ -921,7 +885,7 @@ static void indev_proc_press(lv_indev_proc_t * proc) } /*Send a signal about the press*/ - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSED, indev_act); + lv_signal_send(indev_obj_act, LV_SIGNAL_PRESSED, indev_act); if(indev_reset_check(proc)) return; lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL); @@ -936,33 +900,33 @@ static void indev_proc_press(lv_indev_proc_t * proc) } } - /*Calculate the types.pointer.vector*/ + /*Calculate the vector and apply a low pass filter: new value = 0.5 * old_value + 0.5 * new_value*/ proc->types.pointer.vect.x = proc->types.pointer.act_point.x - proc->types.pointer.last_point.x; proc->types.pointer.vect.y = proc->types.pointer.act_point.y - proc->types.pointer.last_point.y; - proc->types.pointer.drag_throw_vect.x = (proc->types.pointer.drag_throw_vect.x * 4) >> 3; - proc->types.pointer.drag_throw_vect.y = (proc->types.pointer.drag_throw_vect.y * 4) >> 3; + proc->types.pointer.scroll_throw_vect.x = (proc->types.pointer.scroll_throw_vect.x * 4) >> 3; + proc->types.pointer.scroll_throw_vect.y = (proc->types.pointer.scroll_throw_vect.y * 4) >> 3; - proc->types.pointer.drag_throw_vect.x += (proc->types.pointer.vect.x * 4) >> 3; - proc->types.pointer.drag_throw_vect.y += (proc->types.pointer.vect.y * 4) >> 3; + proc->types.pointer.scroll_throw_vect.x += (proc->types.pointer.vect.x * 4) >> 3; + proc->types.pointer.scroll_throw_vect.y += (proc->types.pointer.vect.y * 4) >> 3; - /*If there is active object and it can be dragged run the drag*/ - if(indev_obj_act != NULL) { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSING, indev_act); + if(indev_obj_act) { + lv_signal_send(indev_obj_act, LV_SIGNAL_PRESSING, indev_act); if(indev_reset_check(proc)) return; lv_event_send(indev_obj_act, LV_EVENT_PRESSING, NULL); if(indev_reset_check(proc)) return; + if(indev_act->proc.wait_until_release) return; - indev_drag(proc); + indev_scroll_handler(proc); indev_gesture(proc); if(indev_reset_check(proc)) return; - /*If there is no drag then check for long press time*/ - if(proc->types.pointer.drag_in_prog == 0 && proc->long_pr_sent == 0) { + /*If there is no scrolling then check for long press time*/ + if(proc->types.pointer.scroll_obj == NULL && proc->long_pr_sent == 0) { /*Send a signal about the long press if enough time elapsed*/ if(lv_tick_elaps(proc->pr_timestamp) > indev_act->driver.long_press_time) { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS, indev_act); + lv_signal_send(indev_obj_act, LV_SIGNAL_LONG_PRESS, indev_act); if(indev_reset_check(proc)) return; lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, NULL); if(indev_reset_check(proc)) return; @@ -974,11 +938,12 @@ static void indev_proc_press(lv_indev_proc_t * proc) proc->longpr_rep_timestamp = lv_tick_get(); } } + /*Send long press repeated signal*/ - if(proc->types.pointer.drag_in_prog == 0 && proc->long_pr_sent == 1) { + if(proc->types.pointer.scroll_obj == NULL && proc->long_pr_sent == 1) { /*Send a signal about the long press repeat if enough time elapsed*/ if(lv_tick_elaps(proc->longpr_rep_timestamp) > indev_act->driver.long_press_rep_time) { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS_REP, indev_act); + lv_signal_send(indev_obj_act, LV_SIGNAL_LONG_PRESS_REP, indev_act); if(indev_reset_check(proc)) return; lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, NULL); if(indev_reset_check(proc)) return; @@ -1002,73 +967,49 @@ static void indev_proc_release(lv_indev_proc_t * proc) proc->wait_until_release = 0; } indev_obj_act = proc->types.pointer.act_obj; + lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; /*Forget the act obj and send a released signal */ if(indev_obj_act) { - /* If the object was protected against press lost then it possible that - * the object is already not pressed but still it is the `act_obj`. - * In this case send the `LV_SIGNAL_RELEASED/CLICKED` instead of `LV_SIGNAL_PRESS_LOST` if - * the indev is ON the `types.pointer.act_obj` */ - if(lv_obj_is_protected(indev_obj_act, LV_PROTECT_PRESS_LOST)) { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, indev_act); - if(indev_reset_check(proc)) return; - - if(proc->types.pointer.drag_in_prog == 0) { - if(proc->long_pr_sent == 0) { - lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL); - if(indev_reset_check(proc)) return; - } - - lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL); - if(indev_reset_check(proc)) return; - } - - lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL); - if(indev_reset_check(proc)) return; - } - /* The simple case: `act_obj` was not protected against press lost. - * If it is already not pressed then `indev_proc_press` would set `indev_obj_act = NULL`*/ - else { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, indev_act); - if(indev_reset_check(proc)) return; - - if(proc->long_pr_sent == 0 && proc->types.pointer.drag_in_prog == 0) { + /*Send CLICK if no scrolling*/ + if(scroll_obj == NULL) { + if(proc->long_pr_sent == 0) { lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL); if(indev_reset_check(proc)) return; } - if(proc->types.pointer.drag_in_prog == 0) { - lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL); - if(indev_reset_check(proc)) return; - } - - lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL); + lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL); if(indev_reset_check(proc)) return; } - /*Send LV_EVENT_DRAG_THROW_BEGIN if required */ - /*If drag parent is active check recursively the drag_parent attribute*/ - lv_obj_t * drag_obj = get_dragged_obj(indev_obj_act); - if(drag_obj) { - if(lv_obj_get_drag_throw(drag_obj) && proc->types.pointer.drag_in_prog) { - if(drag_obj->signal_cb) drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_THROW_BEGIN, NULL); - if(indev_reset_check(proc)) return; + /*Send RELEASE signal and event*/ + lv_signal_send(indev_obj_act, LV_SIGNAL_RELEASED, indev_act); + if(indev_reset_check(proc)) return; - lv_event_send(drag_obj, LV_EVENT_DRAG_THROW_BEGIN, NULL); - if(indev_reset_check(proc)) return; - } + lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL); + if(indev_reset_check(proc)) return; + + + /*Send SCROLL_THROW_BEGIN signal and event*/ + if(scroll_obj) { + lv_signal_send(scroll_obj, LV_SIGNAL_SCROLL_THROW_BEGIN, indev_act); + if(indev_reset_check(proc)) return; + + lv_event_send(indev_obj_act, LV_EVENT_SCROLL_THROW_BEGIN, indev_act); + if(indev_reset_check(proc)) return; } proc->types.pointer.act_obj = NULL; proc->pr_timestamp = 0; proc->longpr_rep_timestamp = 0; + } /*The reset can be set in the signal function. * In case of reset query ignore the remaining parts.*/ - if(proc->types.pointer.last_obj != NULL && proc->reset_query == 0) { - indev_drag_throw(proc); + if(scroll_obj) { + indev_scroll_throw_handler(proc); if(indev_reset_check(proc)) return; } } @@ -1085,17 +1026,15 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev) if(indev->proc.reset_query) { indev->proc.types.pointer.act_obj = NULL; indev->proc.types.pointer.last_obj = NULL; - indev->proc.types.pointer.drag_obj = NULL; - indev->proc.types.pointer.drag_limit_out = 0; - indev->proc.types.pointer.drag_in_prog = 0; + indev->proc.types.pointer.scroll_obj = NULL; indev->proc.long_pr_sent = 0; indev->proc.pr_timestamp = 0; indev->proc.longpr_rep_timestamp = 0; - indev->proc.types.pointer.drag_sum.x = 0; - indev->proc.types.pointer.drag_sum.y = 0; - indev->proc.types.pointer.drag_dir = LV_DRAG_DIR_BOTH; - indev->proc.types.pointer.drag_throw_vect.x = 0; - indev->proc.types.pointer.drag_throw_vect.y = 0; + indev->proc.types.pointer.scroll_sum.x = 0; + indev->proc.types.pointer.scroll_sum.y = 0; + indev->proc.types.pointer.scroll_dir = LV_SCROLL_DIR_NONE; + indev->proc.types.pointer.scroll_throw_vect.x = 0; + indev->proc.types.pointer.scroll_throw_vect.y = 0; indev->proc.types.pointer.gesture_sum.x = 0; indev->proc.types.pointer.gesture_sum.y = 0; indev->proc.reset_query = 0; @@ -1237,42 +1176,30 @@ static void indev_click_focus(lv_indev_proc_t * proc) } /** - * Handle the dragging of indev_proc_p->types.pointer.act_obj + * Handle the scrolling * @param indev pointer to a input device state */ -static void indev_drag(lv_indev_proc_t * proc) +static void indev_scroll_handler(lv_indev_proc_t * proc) { - bool scrollable = true; - - lv_coord_t act_x = 0; - lv_coord_t act_y = 0; lv_obj_t * scroll_candidate_obj = NULL; - lv_drag_dir_t dirs_candidate = LV_DRAG_DIR_NONE; + lv_scroll_dir_t dirs_candidate = LV_SCROLL_DIR_NONE; - /*Count the movement by drag*/ - if(proc->types.pointer.drag_limit_out == 0) { - proc->types.pointer.drag_sum.x += proc->types.pointer.vect.x; - proc->types.pointer.drag_sum.y += proc->types.pointer.vect.y; + /*If there is no scroll object yet try to find one*/ + if(proc->types.pointer.scroll_obj == NULL) { + proc->types.pointer.scroll_sum.x += proc->types.pointer.vect.x; + proc->types.pointer.scroll_sum.y += proc->types.pointer.vect.y; - proc->types.pointer.drag_obj = proc->types.pointer.act_obj; + proc->types.pointer.scroll_obj = proc->types.pointer.act_obj; - /*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_ONE; //scrollable ? lv_obj_get_scroll_dir(target_obj) : lv_obj_get_drag_dir(target_obj); - - /*Enough move?*/ + /*Go until find an scrollable object in the current direction*/ + while(proc->types.pointer.scroll_obj) { bool hor_en = false; bool ver_en = false; - if(dirs == LV_DRAG_DIR_HOR || dirs == LV_DRAG_DIR_BOTH) hor_en = true; - if(dirs == LV_DRAG_DIR_VER || dirs == LV_DRAG_DIR_BOTH) ver_en = true; - if(dirs == LV_DRAG_DIR_ONE) { - if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { - hor_en = true; - } - else { - ver_en = true; - } + if(LV_MATH_ABS(proc->types.pointer.scroll_sum.x) > LV_MATH_ABS(proc->types.pointer.scroll_sum.y)) { + hor_en = true; + } + else { + ver_en = true; } bool up_en = ver_en; @@ -1280,28 +1207,28 @@ static void indev_drag(lv_indev_proc_t * proc) bool left_en = hor_en; bool right_en = hor_en; - 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); + lv_coord_t st = lv_obj_get_scroll_top(proc->types.pointer.scroll_obj); + lv_coord_t sb = lv_obj_get_scroll_bottom(proc->types.pointer.scroll_obj); + lv_coord_t sl = lv_obj_get_scroll_left(proc->types.pointer.scroll_obj); + lv_coord_t sr = lv_obj_get_scroll_right(proc->types.pointer.scroll_obj); 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))) + ((up_en && proc->types.pointer.scroll_sum.y >= indev_act->driver.scroll_limit) || + (down_en && proc->types.pointer.scroll_sum.y <= - indev_act->driver.scroll_limit))) { - scroll_candidate_obj = proc->types.pointer.drag_obj; - dirs_candidate = LV_DRAG_DIR_VER; + scroll_candidate_obj = proc->types.pointer.scroll_obj; + dirs_candidate = LV_SCROLL_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))) + ((left_en && proc->types.pointer.scroll_sum.x >= indev_act->driver.scroll_limit) || + (right_en && proc->types.pointer.scroll_sum.x <= - indev_act->driver.scroll_limit))) { - scroll_candidate_obj = proc->types.pointer.drag_obj; - dirs_candidate = LV_DRAG_DIR_HOR; + scroll_candidate_obj = proc->types.pointer.scroll_obj; + dirs_candidate = LV_SCROLL_DIR_HOR; } if(st <= 0) up_en = false; @@ -1309,236 +1236,106 @@ static void indev_drag(lv_indev_proc_t * proc) 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*/ - if((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) || - (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)) + if((left_en && proc->types.pointer.scroll_sum.x >= indev_act->driver.scroll_limit) || + (right_en && proc->types.pointer.scroll_sum.x <= - indev_act->driver.scroll_limit) || + (up_en && proc->types.pointer.scroll_sum.y >= indev_act->driver.scroll_limit) || + (down_en && proc->types.pointer.scroll_sum.y <= - indev_act->driver.scroll_limit)) { - proc->types.pointer.drag_limit_out = 1; - if(dirs == LV_DRAG_DIR_ONE) { - proc->types.pointer.drag_dir = hor_en ? LV_DRAG_DIR_HOR : LV_DRAG_DIR_VER; - } else { - proc->types.pointer.drag_dir = dirs; - } + proc->types.pointer.scroll_dir = hor_en ? LV_SCROLL_DIR_HOR : LV_SCROLL_DIR_VER; - /*The was no move due to drag limit. Compensate it now.*/ - if(!hor_en) proc->types.pointer.drag_sum.x = 0; - if(!ver_en) proc->types.pointer.drag_sum.y = 0; + if(!hor_en) proc->types.pointer.scroll_sum.x = 0; + if(!ver_en) proc->types.pointer.scroll_sum.y = 0; - act_x = lv_obj_get_x(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.x; - act_y = lv_obj_get_y(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.y; - break; + break; /*It"s good scrollable object, use it*/ } - proc->types.pointer.drag_obj = lv_obj_get_parent(proc->types.pointer.drag_obj); + proc->types.pointer.scroll_obj = lv_obj_get_parent(proc->types.pointer.scroll_obj); } } - /*If the drag/scroll can't be propagated to any parent show an elastic scroll in the original object*/ - if(proc->types.pointer.drag_obj == NULL) { + if(proc->types.pointer.scroll_obj == NULL) { if(scroll_candidate_obj) { - proc->types.pointer.drag_limit_out = 1; - proc->types.pointer.drag_dir = dirs_candidate; - proc->types.pointer.drag_obj = scroll_candidate_obj; + proc->types.pointer.scroll_dir = dirs_candidate; + proc->types.pointer.scroll_obj = scroll_candidate_obj; } else { return; } } - lv_obj_t * obj = proc->types.pointer.drag_obj; + /*If there is no scroll object there is nothing to do*/ + lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; + if(scroll_obj == NULL) return; - /*If the drag limit is exceeded handle the dragging*/ - if(proc->types.pointer.drag_limit_out != 0) { - /*Set new position or scroll if the vector is not zero*/ - if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) { - - lv_coord_t prev_x = obj->coords.x1; - lv_coord_t prev_y = obj->coords.y1; - - /*Move the object. `drag_sum` is zerod out for *disabled direction*/ - if(proc->types.pointer.drag_sum.x) act_x += proc->types.pointer.vect.x; - if(proc->types.pointer.drag_sum.y) act_y += proc->types.pointer.vect.y; - - uint16_t inv_buf_size = - lv_disp_get_inv_buf_size(indev_act->driver.disp); /*Get the number of currently invalidated areas*/ - - if(scrollable) { - lv_area_t child_box; - lv_obj_get_children_box(obj, &child_box); - 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, diff_x, diff_y, LV_ANIM_OFF); - } else { - lv_obj_set_pos(obj, act_x, act_y); - } - - proc->types.pointer.drag_in_prog = 1; -// -// /*If the object didn't moved then clear the invalidated areas*/ -// if(target_obj->coords.x1 == prev_x && target_obj->coords.y1 == prev_y) { -// /*In a special case if the object is moved on a page and -// * the scrollable has fit == true and the object is dragged of the page then -// * while its coordinate is not changing only the parent's size is reduced */ -// lv_coord_t act_par_w = lv_obj_get_width(lv_obj_get_parent(target_obj)); -// lv_coord_t act_par_h = lv_obj_get_height(lv_obj_get_parent(target_obj)); -// if(act_par_w == prev_par_w && act_par_h == prev_par_h) { -// uint16_t new_inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp); -// _lv_disp_pop_from_inv_buf(indev_act->driver.disp, new_inv_buf_size - inv_buf_size); -// } -// } -// -// /*Set the drag in progress flag*/ -// /*Send the drag begin signal on first move*/ -// if(just_started) { -// target_obj->signal_cb(target_obj, LV_SIGNAL_DRAG_BEGIN, indev_act); -// if(indev_reset_check(proc)) return; -// -// lv_event_send(target_obj, LV_EVENT_DRAG_BEGIN, NULL); -// if(indev_reset_check(proc)) return; -// } + /*Set new position or scroll if the vector is not zero*/ + if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) { + lv_coord_t diff_x = 0; + lv_coord_t diff_y = 0; + if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_HOR) { + diff_x = proc->types.pointer.vect.x; + if(lv_obj_get_scroll_right(scroll_obj) < 0) diff_x = diff_x / 2; + if(lv_obj_get_scroll_left(scroll_obj) < 0) diff_x = diff_x / 2; + } else { + diff_y = proc->types.pointer.vect.y; + if(lv_obj_get_scroll_top(scroll_obj) < 0) diff_y = diff_y / 2; + if(lv_obj_get_scroll_bottom(scroll_obj) < 0) diff_y = diff_y / 2; } + lv_obj_scroll_by(scroll_obj, diff_x, diff_y, LV_ANIM_OFF); } } /** - * Handle throwing by drag if the drag is ended + * Handle throwing by after scrolling * @param indev pointer to an input device state */ -static void indev_drag_throw(lv_indev_proc_t * proc) +static void indev_scroll_throw_handler(lv_indev_proc_t * proc) { - if(proc->types.pointer.drag_in_prog == 0) return; + lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; - - bool scrollable = true; - - /*Get which object to drad/scroll*/ - lv_obj_t * target_obj = proc->types.pointer.drag_obj; - if(target_obj == NULL) return; - - /*Return if the drag throw is not enabled*/ -// if(lv_obj_get_drag_throw(target_obj) == false) { -// proc->types.pointer.drag_in_prog = 0; -// target_obj->signal_cb(target_obj, scrollable ? LV_SIGNAL_SCROLL_END : LV_SIGNAL_DRAG_END, indev_act); -// if(indev_reset_check(proc)) return; -// -// lv_event_send(target_obj, LV_EVENT_DRAG_END, NULL); -// return; -// } + if(scroll_obj == NULL) return; + if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_NONE) return; /*Reduce the vectors*/ - proc->types.pointer.drag_throw_vect.x = - proc->types.pointer.drag_throw_vect.x * (100 - indev_act->driver.drag_throw) / 100; - proc->types.pointer.drag_throw_vect.y = - proc->types.pointer.drag_throw_vect.y * (100 - indev_act->driver.drag_throw) / 100; + proc->types.pointer.scroll_throw_vect.x = + proc->types.pointer.scroll_throw_vect.x * (100 - indev_act->driver.scroll_throw) / 100; + proc->types.pointer.scroll_throw_vect.y = + proc->types.pointer.scroll_throw_vect.y * (100 - indev_act->driver.scroll_throw) / 100; - switch(proc->types.pointer.drag_dir) { - case LV_DRAG_DIR_HOR: + switch(proc->types.pointer.scroll_dir) { + case LV_SCROLL_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); + proc->types.pointer.scroll_throw_vect.y = 0; + lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); + lv_coord_t sr = lv_obj_get_scroll_right(scroll_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; + if(sl < 0 || sr < 0) proc->types.pointer.scroll_throw_vect.x = proc->types.pointer.scroll_throw_vect.x >> 1; break; } - case LV_DRAG_DIR_VER: + case LV_SCROLL_DIR_VER: { - proc->types.pointer.drag_throw_vect.x = 0; - lv_coord_t st = lv_obj_get_scroll_top(target_obj); - lv_coord_t sb = lv_obj_get_scroll_bottom(target_obj); + proc->types.pointer.scroll_throw_vect.x = 0; + lv_coord_t st = lv_obj_get_scroll_top(scroll_obj); + lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj); /*If scrolled inside reduce faster*/ - if(st < 0 || sb < 0) proc->types.pointer.drag_throw_vect.y = proc->types.pointer.drag_throw_vect.y >> 1; + if(st < 0 || sb < 0) proc->types.pointer.scroll_throw_vect.y = proc->types.pointer.scroll_throw_vect.y >> 1; break; } } - 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) { - 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; - lv_obj_get_coords(target_obj, &coords_ori); - - lv_coord_t act_x = lv_obj_get_x(target_obj) + proc->types.pointer.drag_throw_vect.x; - lv_coord_t act_y = lv_obj_get_y(target_obj) + proc->types.pointer.drag_throw_vect.y; - lv_obj_set_pos(target_obj, act_x, act_y); - - lv_area_t coords_new; - lv_obj_get_coords(target_obj, &coords_new); - - /*If non of the coordinates are changed then do not continue throwing*/ - if((coords_ori.x1 == coords_new.x1 || proc->types.pointer.drag_throw_vect.x == 0) && - (coords_ori.y1 == coords_new.y1 || proc->types.pointer.drag_throw_vect.y == 0)) { - proc->types.pointer.drag_in_prog = 0; - proc->types.pointer.vect.x = 0; - proc->types.pointer.vect.y = 0; - proc->types.pointer.drag_throw_vect.x = 0; - proc->types.pointer.drag_throw_vect.y = 0; - target_obj->signal_cb(target_obj, LV_SIGNAL_DRAG_END, indev_act); - if(indev_reset_check(proc)) return; - - lv_event_send(target_obj, LV_EVENT_DRAG_END, NULL); - if(indev_reset_check(proc)) return; - } - - } - + if((proc->types.pointer.scroll_throw_vect.x != 0 || proc->types.pointer.scroll_throw_vect.y != 0)) { + lv_obj_scroll_by(scroll_obj, proc->types.pointer.scroll_throw_vect.x, proc->types.pointer.scroll_throw_vect.y, LV_ANIM_OFF); } - /*If the types.pointer.vectors become 0 -> types.pointer.drag_in_prog = 0 and send a drag end + /*If the vectors become 0 then finish scrolling signal*/ else { - proc->types.pointer.drag_in_prog = 0; - proc->types.pointer.drag_obj = NULL; - target_obj->signal_cb(target_obj, scrollable ? LV_SIGNAL_SCROLL_END : LV_SIGNAL_DRAG_END, indev_act); + proc->types.pointer.scroll_dir = LV_SCROLL_DIR_NONE; + proc->types.pointer.scroll_obj = NULL; + lv_signal_send(scroll_obj, LV_SIGNAL_SCROLL_END, indev_act); if(indev_reset_check(proc)) return; - lv_event_send(target_obj, LV_EVENT_DRAG_END, NULL); + lv_event_send(scroll_obj, LV_EVENT_SCROLL_END, indev_act); if(indev_reset_check(proc)) return; } } - -/** - * Get the really dragged object by taking `drag_parent` into account. - * @param obj the start object - * @return the object to really drag - */ -static lv_obj_t * get_dragged_obj(lv_obj_t * obj) -{ - return obj; - - if(indev_act->proc.types.pointer.drag_obj) { - return indev_act->proc.types.pointer.drag_obj; - } else { - lv_area_t child_box; - lv_obj_get_children_box(obj, &child_box); - if(child_box.y2 == obj->coords.y2) indev_act->proc.types.pointer.drag_obj = lv_obj_get_parent(obj); - else indev_act->proc.types.pointer.drag_obj = obj; - } - - return indev_act->proc.types.pointer.drag_obj; - - - if(obj == NULL) return NULL; - lv_obj_t * drag_obj = obj; - while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) { - drag_obj = lv_obj_get_parent(drag_obj); - } - - if(lv_obj_get_drag(drag_obj) == false) return NULL; - return drag_obj; -} - - /** * Handle the gesture of indev_proc_p->types.pointer.act_obj * @param indev pointer to a input device state @@ -1546,7 +1343,7 @@ static lv_obj_t * get_dragged_obj(lv_obj_t * obj) static void indev_gesture(lv_indev_proc_t * proc) { - if(proc->types.pointer.drag_in_prog) return; + if(proc->types.pointer.scroll_obj) return; if(proc->types.pointer.gesture_sent) return; lv_obj_t * gesture_obj = proc->types.pointer.act_obj; diff --git a/src/lv_core/lv_indev.h b/src/lv_core/lv_indev.h index 403081f22..ebaf519c0 100644 --- a/src/lv_core/lv_indev.h +++ b/src/lv_core/lv_indev.h @@ -120,36 +120,28 @@ lv_gesture_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev); uint32_t lv_indev_get_key(const lv_indev_t * indev); /** - * Check if there is dragging with an input device or not (for LV_INDEV_TYPE_POINTER and + * Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and * LV_INDEV_TYPE_BUTTON) * @param indev pointer to an input device - * @return true: drag is in progress + * @return LV_SCROLL_DIR_NONE: no scrolling now + * LV_SCROLL_DIR_HOR/VER */ -bool lv_indev_is_dragging(const lv_indev_t * indev); +lv_scroll_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev); /** - * Get the vector of dragging of an input device (for LV_INDEV_TYPE_POINTER and + * Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and * LV_INDEV_TYPE_BUTTON) * @param indev pointer to an input device - * @param point pointer to a point to store the vector + * @param point pointer to a point to store the types.pointer.vector */ void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point); -/** - * Manually finish dragging. - * `LV_SIGNAL_DRAG_END` and `LV_EVENT_DRAG_END` will be sent. - * @param indev pointer to an input device - * @return `LV_RES_INV` if the object being dragged was deleted. Else `LV_RES_OK`. - */ -lv_res_t lv_indev_finish_drag(lv_indev_t * indev); - /** * Do nothing until the next release * @param indev pointer to an input device */ void lv_indev_wait_release(lv_indev_t * indev); - /** * Gets a pointer to the currently active object in indev proc functions. * NULL if no object is currently being handled or if groups aren't used. diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 5b1c9c068..053775ca9 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -329,10 +329,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) /*Set attributes*/ new_obj->adv_hittest = 0; new_obj->click = 1; - new_obj->drag = 0; - new_obj->drag_throw = 0; - new_obj->drag_parent = 0; - new_obj->drag_dir = LV_DRAG_DIR_BOTH; + new_obj->scroll_mode = LV_SCROLL_MODE_AUTO; new_obj->hidden = 0; new_obj->top = 0; new_obj->protect = LV_PROTECT_NONE; @@ -340,6 +337,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->gesture_parent = parent ? 1 : 0; new_obj->focus_parent = 0; new_obj->state = LV_STATE_DEFAULT; + new_obj->scroll.x = 0; + new_obj->scroll.y = 0; new_obj->ext_attr = NULL; @@ -384,10 +383,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) /*Copy attributes*/ new_obj->adv_hittest = copy->adv_hittest; new_obj->click = copy->click; - new_obj->drag = copy->drag; - new_obj->drag_dir = copy->drag_dir; - new_obj->drag_throw = copy->drag_throw; - new_obj->drag_parent = copy->drag_parent; + new_obj->scroll_mode = copy->scroll_mode; new_obj->hidden = copy->hidden; new_obj->top = copy->top; new_obj->parent_event = copy->parent_event; @@ -1613,55 +1609,17 @@ void lv_obj_set_top(lv_obj_t * obj, bool en) } /** - * Enable the dragging of an object + * Set how the scrollbars should behave. * @param obj pointer to an object - * @param en true: make the object draggable + * @param mode: LV_SCROLL_MODE_ON/OFF/AUTO/ACTIVE */ -void lv_obj_set_drag(lv_obj_t * obj, bool en) +void lv_obj_set_scroll_mode(lv_obj_t * obj, lv_scroll_mode_t mode) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - if(en == true) lv_obj_set_click(obj, true); /*Drag is useless without enabled clicking*/ - obj->drag = (en == true ? 1 : 0); -} - -/** - * Set the directions an object can be dragged in - * @param obj pointer to an object - * @param drag_dir bitwise OR of allowed directions an object can be dragged in - */ -void lv_obj_set_drag_dir(lv_obj_t * obj, lv_drag_dir_t drag_dir) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->drag_dir = drag_dir; - - if(obj->drag_dir != 0) lv_obj_set_drag(obj, true); /*Drag direction requires drag*/ -} - -/** - * Enable the throwing of an object after is is dragged - * @param obj pointer to an object - * @param en true: enable the drag throw - */ -void lv_obj_set_drag_throw(lv_obj_t * obj, bool en) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->drag_throw = (en == true ? 1 : 0); -} - -/** - * Enable to use parent for drag related operations. - * If trying to drag the object the parent will be moved instead - * @param obj pointer to an object - * @param en true: enable the 'drag parent' for the object - */ -void lv_obj_set_drag_parent(lv_obj_t * obj, bool en) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->drag_parent = (en == true ? 1 : 0); + if(obj->scroll_mode == mode) return; + obj->scroll_mode = mode; + lv_obj_invalidate(obj); } /** @@ -2944,61 +2902,15 @@ bool lv_obj_get_top(const lv_obj_t * obj) } /** - * Get the drag enable attribute of an object + * Get how the scrollbars should behave. * @param obj pointer to an object - * @return true: the object is draggable + * @return mode: LV_SCROLL_MODE_ON/OFF/AUTO/ACTIVE */ -bool lv_obj_get_drag(const lv_obj_t * obj) +lv_scroll_mode_t lv_obj_get_scroll_mode(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - return obj->drag == 0 ? false : true; -} - -/** - * Get the directions an object can be dragged - * @param obj pointer to an object - * @return bitwise OR of allowed directions an object can be dragged in - */ -lv_drag_dir_t lv_obj_get_drag_dir(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->drag_dir; -} - -/** - * Get the directions an object can be scrolled - * @param obj pointer to an object - * @return bitwise OR of allowed directions an object can be dragged in - */ -lv_drag_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->scroll_dir; -} - -/** - * Get the drag throw enable attribute of an object - * @param obj pointer to an object - * @return true: drag throw is enabled - */ -bool lv_obj_get_drag_throw(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->drag_throw == 0 ? false : true; -} - -/** - * Get the drag parent attribute of an object - * @param obj pointer to an object - * @return true: drag parent is enabled - */ -bool lv_obj_get_drag_parent(const lv_obj_t * obj) -{ - return obj->drag_parent == 0 ? false : true; + return obj->scroll_mode; } /** @@ -3022,9 +2934,9 @@ bool lv_obj_get_focus_parent(const lv_obj_t * obj) } /** - * Get the drag parent attribute of an object + * Get the parent event attribute of an object * @param obj pointer to an object - * @return true: drag parent is enabled + * @return true: parent event is enabled */ bool lv_obj_get_parent_event(const lv_obj_t * obj) { diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index f2e01a33f..87286ec6a 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -85,15 +85,16 @@ enum { LV_EVENT_PRESSED, /**< The object has been pressed*/ LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ LV_EVENT_PRESS_LOST, /**< User is still pressing but slid cursor/finger off of the object */ - LV_EVENT_SHORT_CLICKED, /**< User pressed object for a short period of time, then released it. Not called if dragged. */ - LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `LV_INDEV_LONG_PRESS_TIME`. Not called if dragged.*/ + LV_EVENT_SHORT_CLICKED, /**< User pressed object for a short period of time, then released it. Not called if scrolled. */ + LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `LV_INDEV_LONG_PRESS_TIME`. Not called if scrolled.*/ LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `LV_INDEV_LONG_PRESS_TIME` in every - `LV_INDEV_LONG_PRESS_REP_TIME` ms. Not called if dragged.*/ - LV_EVENT_CLICKED, /**< Called on release if not dragged (regardless to long press)*/ + `LV_INDEV_LONG_PRESS_REP_TIME` ms. Not called if scrolled.*/ + LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/ LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ - LV_EVENT_DRAG_BEGIN, - LV_EVENT_DRAG_END, - LV_EVENT_DRAG_THROW_BEGIN, + LV_EVENT_SCROLL_BEGIN, + LV_EVENT_SCROLL_THROW_BEGIN, + LV_EVENT_SCROLL_END, + LV_EVENT_SCROLL, LV_EVENT_GESTURE, /**< The object has been gesture*/ LV_EVENT_KEY, LV_EVENT_FOCUSED, @@ -136,15 +137,13 @@ enum { LV_SIGNAL_PRESSED, /**< The object has been pressed*/ LV_SIGNAL_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ LV_SIGNAL_PRESS_LOST, /**< User is still pressing but slid cursor/finger off of the object */ - LV_SIGNAL_RELEASED, /**< User pressed object for a short period of time, then released it. Not called if dragged. */ - LV_SIGNAL_LONG_PRESS, /**< Object has been pressed for at least `LV_INDEV_LONG_PRESS_TIME`. Not called if dragged.*/ - LV_SIGNAL_LONG_PRESS_REP, /**< Called after `LV_INDEV_LONG_PRESS_TIME` in every `LV_INDEV_LONG_PRESS_REP_TIME` ms. Not called if dragged.*/ + LV_SIGNAL_RELEASED, /**< User pressed object for a short period of time, then released it. Not called if scrolled. */ + LV_SIGNAL_LONG_PRESS, /**< Object has been pressed for at least `LV_INDEV_LONG_PRESS_TIME`. Not called if scrolled.*/ + LV_SIGNAL_LONG_PRESS_REP, /**< Called after `LV_INDEV_LONG_PRESS_TIME` in every `LV_INDEV_LONG_PRESS_REP_TIME` ms. Not called if scrolled.*/ LV_SIGNAL_SCROLL_BEGIN, /**< The scrolling has just begun */ LV_SIGNAL_SCROLL, /**< The object has been scrolled */ LV_SIGNAL_SCROLL_END, /**< The scrolling has ended */ - LV_SIGNAL_DRAG_BEGIN, - LV_SIGNAL_DRAG_THROW_BEGIN, - LV_SIGNAL_DRAG_END, + LV_SIGNAL_SCROLL_THROW_BEGIN,/**< Scroll throw started*/ LV_SIGNAL_GESTURE, /**< The object has been gesture*/ LV_SIGNAL_LEAVE, /**< Another object is clicked or chosen via an input device */ @@ -196,6 +195,15 @@ enum { typedef uint8_t lv_state_t; +/** Scrollbar modes: shows when should the scrollbars be visible*/ +enum { + LV_SCROLL_MODE_OFF = 0x0, /**< Never show scroll bars*/ + LV_SCROLL_MODE_ON = 0x1, /**< Always show scroll bars*/ + LV_SCROLL_MODE_ACTIVE = 0x2, /**< Show scroll bars when object is being scrolled*/ + LV_SCROLL_MODE_AUTO = 0x3, /**< Show scroll bars when the content is large enough to be scrolled*/ +}; +typedef uint8_t lv_scroll_mode_t; + typedef struct _lv_obj_t { struct _lv_obj_t * parent; /**< Pointer to the parent object*/ lv_ll_t child_ll; /**< Linked list to store the children objects*/ @@ -221,19 +229,13 @@ typedef struct _lv_obj_t { /*Attributes and states*/ uint8_t click : 1; /**< 1: Can be pressed by an input device*/ - uint8_t drag : 1; /**< 1: Enable the dragging*/ - uint8_t drag_throw : 1; /**< 1: Enable throwing with drag*/ - uint8_t drag_parent : 1; /**< 1: Parent will be dragged instead*/ uint8_t hidden : 1; /**< 1: Object is hidden*/ uint8_t top : 1; /**< 1: If the object or its children is clicked it goes to the foreground*/ uint8_t parent_event : 1; /**< 1: Send the object's events to the parent too. */ uint8_t adv_hittest : 1; /**< 1: Use advanced hit-testing (slower) */ uint8_t gesture_parent : 1; /**< 1: Parent will be gesture instead*/ uint8_t focus_parent : 1; /**< 1: Parent will be focused instead*/ - lv_drag_dir_t scroll_elastic : 3; /**< In which directions the object can be scrolled */ - - lv_drag_dir_t drag_dir : 3; /**< In which directions the object can be dragged */ - lv_drag_dir_t scroll_dir : 3; /**< In which directions the object can be scrolled */ + lv_scroll_mode_t scroll_mode :2; /**< How to display scrollbars*/ lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */ #if LV_USE_GROUP != 0 @@ -781,35 +783,6 @@ void lv_obj_set_click(lv_obj_t * obj, bool en); */ void lv_obj_set_top(lv_obj_t * obj, bool en); -/** - * Enable the dragging of an object - * @param obj pointer to an object - * @param en true: make the object draggable - */ -void lv_obj_set_drag(lv_obj_t * obj, bool en); - -/** - * Set the directions an object can be dragged in - * @param obj pointer to an object - * @param drag_dir bitwise OR of allowed drag directions - */ -void lv_obj_set_drag_dir(lv_obj_t * obj, lv_drag_dir_t drag_dir); - -/** - * Enable the throwing of an object after is is dragged - * @param obj pointer to an object - * @param en true: enable the drag throw - */ -void lv_obj_set_drag_throw(lv_obj_t * obj, bool en); - -/** - * Enable to use parent for drag related operations. - * If trying to drag the object the parent will be moved instead - * @param obj pointer to an object - * @param en true: enable the 'drag parent' for the object - */ -void lv_obj_set_drag_parent(lv_obj_t * obj, bool en); - /** * Enable to use parent for focus state. * When object is focused the parent will get the state instead (visual only) @@ -818,6 +791,13 @@ void lv_obj_set_drag_parent(lv_obj_t * obj, bool en); */ void lv_obj_set_focus_parent(lv_obj_t * obj, bool en); +/** + * Set how the scrollbars should behave. + * @param obj pointer to an object + * @param mode: LV_SCROLL_MODE_ON/OFF/AUTO/ACTIVE + */ +void lv_obj_set_scroll_mode(lv_obj_t * obj, lv_scroll_mode_t mode); + /** * Enable to use parent for gesture related operations. * If trying to gesture the object the parent will be moved instead @@ -1314,42 +1294,6 @@ bool lv_obj_get_click(const lv_obj_t * obj); */ bool lv_obj_get_top(const lv_obj_t * obj); -/** - * Get the drag enable attribute of an object - * @param obj pointer to an object - * @return true: the object is draggable - */ -bool lv_obj_get_drag(const lv_obj_t * obj); - -/** - * Get the directions an object can be dragged - * @param obj pointer to an object - * @return bitwise OR of allowed directions an object can be dragged in - */ -lv_drag_dir_t lv_obj_get_drag_dir(const lv_obj_t * obj); - -/** - * Get the directions an object can be scrolled - * @param obj pointer to an object - * @return bitwise OR of allowed directions an object can be dragged in - */ -lv_drag_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj); - -/** - * Get the drag throw enable attribute of an object - * @param obj pointer to an object - * @return true: drag throw is enabled - */ -bool lv_obj_get_drag_throw(const lv_obj_t * obj); - -/** - * Get the drag parent attribute of an object - * @param obj pointer to an object - * @return true: drag parent is enabled - */ -bool lv_obj_get_drag_parent(const lv_obj_t * obj); - - /** * Get the focus parent attribute of an object * @param obj pointer to an object @@ -1357,11 +1301,10 @@ bool lv_obj_get_drag_parent(const lv_obj_t * obj); */ bool lv_obj_get_focus_parent(const lv_obj_t * obj); - /** - * Get the drag parent attribute of an object + * Get the parent event attribute of an object * @param obj pointer to an object - * @return true: drag parent is enabled + * @return true: parent event is enabled */ bool lv_obj_get_parent_event(const lv_obj_t * obj); diff --git a/src/lv_hal/lv_hal_indev.c b/src/lv_hal/lv_hal_indev.c index ca4404816..c0f2f4835 100644 --- a/src/lv_hal/lv_hal_indev.c +++ b/src/lv_hal/lv_hal_indev.c @@ -54,8 +54,8 @@ void lv_indev_drv_init(lv_indev_drv_t * driver) _lv_memset_00(driver, sizeof(lv_indev_drv_t)); driver->type = LV_INDEV_TYPE_NONE; - driver->drag_limit = LV_INDEV_DEF_DRAG_LIMIT; - driver->drag_throw = LV_INDEV_DEF_DRAG_THROW; + driver->scroll_limit = LV_INDEV_DEF_DRAG_LIMIT; + driver->scroll_throw = LV_INDEV_DEF_DRAG_THROW; driver->long_press_time = LV_INDEV_DEF_LONG_PRESS_TIME; driver->long_press_rep_time = LV_INDEV_DEF_LONG_PRESS_REP_TIME; driver->gesture_limit = LV_INDEV_DEF_GESTURE_LIMIT; diff --git a/src/lv_hal/lv_hal_indev.h b/src/lv_hal/lv_hal_indev.h index a4af05936..b49080db3 100644 --- a/src/lv_hal/lv_hal_indev.h +++ b/src/lv_hal/lv_hal_indev.h @@ -52,14 +52,12 @@ typedef uint8_t lv_indev_state_t; enum { - LV_DRAG_DIR_NONE = 0x0, /**< Object can't be dragged to any directions. */ - LV_DRAG_DIR_HOR = 0x1, /**< Object can be dragged horizontally. */ - LV_DRAG_DIR_VER = 0x2, /**< Object can be dragged vertically. */ - LV_DRAG_DIR_BOTH = 0x3, /**< Object can be dragged in all directions. */ - LV_DRAG_DIR_ONE = 0x4, /**< Object can be dragged only one direction (the first move). */ + LV_SCROLL_DIR_NONE = 0x0, /**< Object can't be dragged to any directions. */ + LV_SCROLL_DIR_HOR = 0x1, /**< Object can be dragged horizontally. */ + LV_SCROLL_DIR_VER = 0x2, /**< Object can be dragged vertically. */ }; -typedef uint8_t lv_drag_dir_t; +typedef uint8_t lv_scroll_dir_t; enum { LV_GESTURE_DIR_TOP, /**< Gesture dir up. */ @@ -106,10 +104,10 @@ typedef struct _lv_indev_drv_t { lv_task_t * read_task; /**< Number of pixels to slide before actually drag the object*/ - uint8_t drag_limit; + uint8_t scroll_limit; /**< Drag throw slow-down in [%]. Greater value means faster slow-down */ - uint8_t drag_throw; + uint8_t scroll_throw; /**< At least this difference should between two points to evaluate as gesture */ uint8_t gesture_min_velocity; @@ -135,20 +133,18 @@ typedef struct _lv_indev_proc_t { lv_point_t act_point; /**< Current point of input device. */ lv_point_t last_point; /**< Last point of input device. */ lv_point_t vect; /**< Difference between `act_point` and `last_point`. */ - lv_point_t drag_sum; /*Count the dragged pixels to check LV_INDEV_DEF_DRAG_LIMIT*/ - lv_point_t drag_throw_vect; + lv_point_t scroll_sum; /*Count the dragged pixels to check LV_INDEV_DEF_DRAG_LIMIT*/ + lv_point_t scroll_throw_vect; struct _lv_obj_t * act_obj; /*The object being pressed*/ struct _lv_obj_t * last_obj; /*The last object which was pressed (used by drag_throw and other post-release event)*/ - struct _lv_obj_t * drag_obj; /*The object being pressed*/ + struct _lv_obj_t * scroll_obj; /*The object being scrolled*/ struct _lv_obj_t * last_pressed; /*The lastly pressed object*/ lv_gesture_dir_t gesture_dir; lv_point_t gesture_sum; /*Count the gesture pixels to check LV_INDEV_DEF_GESTURE_LIMIT*/ /*Flags*/ - uint8_t drag_limit_out : 1; - uint8_t drag_in_prog : 1; - lv_drag_dir_t drag_dir : 3; + lv_scroll_dir_t scroll_dir : 2; uint8_t gesture_sent : 1; } pointer; struct { diff --git a/src/lv_widgets/lv_btn.c b/src/lv_widgets/lv_btn.c index fa327bd6e..e3d7d9325 100644 --- a/src/lv_widgets/lv_btn.c +++ b/src/lv_widgets/lv_btn.c @@ -273,7 +273,7 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param) if(sign == LV_SIGNAL_RELEASED) { /*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) { + if(lv_indev_get_scroll_dir(param) == LV_SCROLL_DIR_NONE && tgl) { uint32_t toggled = 0; if(lv_obj_get_state(btn, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) { lv_btn_set_state(btn, LV_BTN_STATE_RELEASED); diff --git a/src/lv_widgets/lv_cpicker.c b/src/lv_widgets/lv_cpicker.c index d80c9a56c..21d1c09c2 100644 --- a/src/lv_widgets/lv_cpicker.c +++ b/src/lv_widgets/lv_cpicker.c @@ -768,8 +768,8 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p 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)) { + if((LV_MATH_ABS(p.x - ext->last_press_point.x) > indev->driver.scroll_limit / 2) || + (LV_MATH_ABS(p.y - ext->last_press_point.y) > indev->driver.scroll_limit / 2)) { ext->last_change_time = lv_tick_get(); ext->last_press_point.x = p.x; ext->last_press_point.y = p.y; diff --git a/src/lv_widgets/lv_dropdown.c b/src/lv_widgets/lv_dropdown.c index c7bbd8746..e6b05eba8 100644 --- a/src/lv_widgets/lv_dropdown.c +++ b/src/lv_widgets/lv_dropdown.c @@ -930,7 +930,7 @@ static lv_res_t lv_dropdown_signal(lv_obj_t * ddlist, lv_signal_t sign, void * p } else if(sign == LV_SIGNAL_RELEASED) { lv_indev_t * indev = lv_indev_get_act(); - if(lv_indev_is_dragging(indev) == false) { + if(lv_indev_is_scrolling(indev) == false) { if(ext->page) { lv_dropdown_close(ddlist); if(ext->sel_opt_id_orig != ext->sel_opt_id) { @@ -1034,7 +1034,7 @@ static lv_res_t lv_dropdown_page_signal(lv_obj_t * page, lv_signal_t sign, void scrl->ext_draw_pad = LV_MATH_MAX3(scrl->ext_draw_pad, left, right); } else if(sign == LV_SIGNAL_RELEASED) { - if(lv_indev_is_dragging(lv_indev_get_act()) == false) { + if(lv_indev_is_scrolling(lv_indev_get_act()) == false) { page_release_handler(page); } } @@ -1071,7 +1071,7 @@ static lv_res_t lv_dropdown_page_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, lv_dropdown_ext_t * ext = lv_obj_get_ext_attr(ddlist); if(sign == LV_SIGNAL_RELEASED) { - if(lv_indev_is_dragging(lv_indev_get_act()) == false) { + if(lv_indev_is_scrolling(lv_indev_get_act()) == false) { page_release_handler(page); } } diff --git a/src/lv_widgets/lv_list.c b/src/lv_widgets/lv_list.c index 76ba666ff..d1d370a87 100644 --- a/src/lv_widgets/lv_list.c +++ b/src/lv_widgets/lv_list.c @@ -688,7 +688,7 @@ static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param) res = lv_event_send(ext->act_sel_btn, LV_EVENT_SHORT_CLICKED, NULL); if(res != LV_RES_OK) return res; } - if(lv_indev_is_dragging(indev) == false) { + if(lv_indev_is_scrolling(indev) == false) { res = lv_event_send(ext->act_sel_btn, LV_EVENT_CLICKED, NULL); if(res != LV_RES_OK) return res; } @@ -806,7 +806,7 @@ static lv_res_t lv_list_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * para } } else if(sign == LV_SIGNAL_RELEASED) { - if(lv_indev_is_dragging(lv_indev_get_act()) == false) { + if(lv_indev_is_scrolling(lv_indev_get_act()) == false) { lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn)); lv_list_focus_btn(list, btn); #if LV_USE_GROUP diff --git a/src/lv_widgets/lv_page.c b/src/lv_widgets/lv_page.c index 89c6c0f0e..f7e1a8e34 100644 --- a/src/lv_widgets/lv_page.c +++ b/src/lv_widgets/lv_page.c @@ -932,7 +932,7 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi if(parent_ext->scroll_prop_obj == NULL) { /*If the dragging just started or scroll is already propagated to this object * enable the scroll propagation if the conditions are met*/ - if((lv_indev_is_dragging(indev) == false || page_ext->scroll_prop_obj) && (drag_sum->y || drag_sum->x)) { + if((lv_indev_is_scrolling(indev) == false || page_ext->scroll_prop_obj) && (drag_sum->y || drag_sum->x)) { /*Propagate vertically?*/ if((drag_sum->y > 0 && lv_page_on_edge(page, LV_PAGE_EDGE_TOP)) || (drag_sum->y < 0 && lv_page_on_edge(page, LV_PAGE_EDGE_BOTTOM))) { diff --git a/src/lv_widgets/lv_roller.c b/src/lv_widgets/lv_roller.c index 46f81221a..9b1672ceb 100644 --- a/src/lv_widgets/lv_roller.c +++ b/src/lv_widgets/lv_roller.c @@ -885,7 +885,7 @@ static lv_res_t release_handler(lv_obj_t * roller) { /*If there was dragging `DRAG_END` signal will refresh the position and update the selected option*/ - if(lv_indev_is_dragging(lv_indev_get_act())) return LV_RES_OK; + if(lv_indev_is_scrolling(lv_indev_get_act())) return LV_RES_OK; lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller); diff --git a/src/lv_widgets/lv_tileview.c b/src/lv_widgets/lv_tileview.c index 0ea0f8133..f5dae125c 100644 --- a/src/lv_widgets/lv_tileview.c +++ b/src/lv_widgets/lv_tileview.c @@ -380,7 +380,7 @@ static lv_res_t lv_tileview_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void } /*Apply the drag constraints*/ - lv_drag_dir_t drag_dir = indev->proc.types.pointer.drag_dir; + lv_scroll_dir_t drag_dir = indev->proc.types.pointer.drag_dir; if(drag_dir == LV_DRAG_DIR_HOR) lv_obj_set_y(scrl, -ext->act_id.y * lv_obj_get_height(tileview) + top); else if(drag_dir == LV_DRAG_DIR_VER) @@ -406,7 +406,7 @@ static void drag_end_handler(lv_obj_t * tileview) p.x = -(lv_obj_get_x(scrl) - lv_obj_get_width(tileview) / 2); p.y = -(lv_obj_get_y(scrl) - lv_obj_get_height(tileview) / 2); - lv_drag_dir_t drag_dir = indev->proc.types.pointer.drag_dir; + lv_scroll_dir_t drag_dir = indev->proc.types.pointer.drag_dir; /*From the drag vector (drag throw) predict the end position*/ if(drag_dir & LV_DRAG_DIR_HOR) { lv_point_t vect; From 7a1d9e77538a8d3253143fe0fbbcdf5bc7b15a44 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 21 Jul 2020 21:47:31 +0200 Subject: [PATCH 11/84] scroll: handle scroll modes --- src/lv_core/lv_indev.c | 12 +++ src/lv_core/lv_indev.h | 8 ++ src/lv_core/lv_obj.c | 160 +++++++++++++++++++++++---------------- src/lv_hal/lv_hal_disp.c | 3 + 4 files changed, 117 insertions(+), 66 deletions(-) diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 2be5474d9..4159326fd 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -299,6 +299,18 @@ lv_scroll_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev) if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) return false; return indev->proc.types.pointer.scroll_dir; } +/** + * Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @return pointer to the currently scrolled object or NULL if no scrolling by this indev + */ +lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev) +{ + if(indev == NULL) return NULL; + if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) return NULL; + return indev->proc.types.pointer.scroll_obj; +} /** * Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and diff --git a/src/lv_core/lv_indev.h b/src/lv_core/lv_indev.h index ebaf519c0..2b6c69161 100644 --- a/src/lv_core/lv_indev.h +++ b/src/lv_core/lv_indev.h @@ -128,6 +128,14 @@ uint32_t lv_indev_get_key(const lv_indev_t * indev); */ lv_scroll_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev); +/** + * Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @return pointer to the currently scrolled object or NULL if no scrolling by this indev + */ +lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev); + /** * Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and * LV_INDEV_TYPE_BUTTON) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 053775ca9..3f23fbd96 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -106,7 +106,7 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin static void lv_obj_del_async_cb(void * obj); static void obj_del_core(lv_obj_t * obj); static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc); -static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, const lv_area_t * clip_area); +static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area); /********************** * STATIC VARIABLES @@ -3800,18 +3800,8 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area } else if(mode == LV_DESIGN_DRAW_POST) { - if(lv_obj_get_screen(obj) == lv_scr_act()) { - lv_draw_rect_dsc_t sb_rect_dsc; - lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &sb_rect_dsc); - if(sb_res == LV_RES_OK) { - lv_area_t hor_area; - lv_area_t ver_area; - scrollbar_get_area(obj, &hor_area, &ver_area, clip_area); - lv_draw_rect(&hor_area, clip_area, &sb_rect_dsc); - lv_draw_rect(&ver_area, clip_area, &sb_rect_dsc); - } - } + scrollbar_draw(obj, clip_area); if(lv_obj_get_style_clip_corner(obj, LV_OBJ_PART_MAIN)) { lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8); @@ -3887,9 +3877,6 @@ 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); - 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); @@ -3912,6 +3899,11 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) lv_obj_scroll_by(obj, -sr, 0, LV_ANIM_ON); } } + + if(lv_obj_get_scroll_mode(obj) == LV_SCROLL_MODE_ACTIVE) { + lv_obj_invalidate(obj); + } + } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { lv_coord_t d = lv_obj_get_draw_rect_ext_pad_size(obj, LV_OBJ_PART_MAIN); @@ -4521,8 +4513,39 @@ static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc } } -static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, const lv_area_t * clip_area) +static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area) { + lv_scroll_dir_t sm = lv_obj_get_scroll_mode(obj); + if(sm == LV_SCROLL_MODE_OFF) { + return; + } + + 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); + + /*Return if too small content to scroll*/ + if(sm == LV_SCROLL_MODE_AUTO && st <= 0 && sb <= 0 && sl <= 0 && sl <= 0) { + return; + } + + /*If there is no indev scrolling this object but the moe is active return*/ + lv_indev_t * indev = lv_indev_get_next(NULL); + if(sm == LV_SCROLL_MODE_ACTIVE) { + bool found = false; + while(indev) { + if(lv_indev_get_scroll_obj(indev) == obj) { + found = true; + break; + } + indev = lv_indev_get_next(indev); + } + if(!found) { + return; + } + } + lv_coord_t end_space = lv_obj_get_style_scrollbar_space_end(obj, LV_OBJ_PART_MAIN); lv_coord_t side_space = lv_obj_get_style_scrollbar_space_side(obj, LV_OBJ_PART_MAIN); lv_coord_t tickness = lv_obj_get_style_scrollbar_tickness(obj, LV_OBJ_PART_MAIN); @@ -4530,88 +4553,93 @@ static void scrollbar_get_area(lv_obj_t * obj, lv_area_t * ver, lv_area_t * hor, lv_coord_t obj_h = lv_obj_get_height(obj); lv_coord_t obj_w = lv_obj_get_width(obj); - 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); - lv_coord_t ver_reg_space = tickness + side_space; lv_coord_t hor_req_space = tickness + side_space; lv_coord_t rem; - ver->y1 = obj->coords.y1; - ver->y2 = obj->coords.y2; - ver->x2 = obj->coords.x2; - ver->x1 = ver->x2 - tickness; + lv_draw_rect_dsc_t draw_dsc; + lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc); + if(sb_res != LV_RES_OK) return; - if(_lv_area_is_on(ver, clip_area)) { + lv_area_t area; + area.y1 = obj->coords.y1; + area.y2 = obj->coords.y2; + area.x2 = obj->coords.x2; + area.x1 = area.x2 - tickness; + + /*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/ + if(_lv_area_is_on(&area, clip_area) && + ((sm == LV_SCROLL_MODE_ON) || + (sm == LV_SCROLL_MODE_AUTO && (st > 0 || sb > 0)) || + (sm == LV_SCROLL_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_SCROLL_DIR_VER))) { lv_coord_t content_h = obj_h + st + sb; lv_coord_t sb_h = ((obj_h - end_space * 2 - hor_req_space) * obj_h) / content_h; sb_h = LV_MATH_MAX(sb_h, SCROLLBAR_MIN_SIZE); rem = (obj_h - end_space * 2 - hor_req_space) - 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) { - ver->y1 = obj->coords.y1 + end_space; - ver->y2 = obj->coords.y2 - end_space - hor_req_space - 1; - ver->x2 = obj->coords.x2; - ver->x1 = ver->x2 - tickness + 1; + area.y1 = obj->coords.y1 + end_space; + area.y2 = obj->coords.y2 - end_space - hor_req_space - 1; + area.x2 = obj->coords.x2; + area.x1 = area.x2 - tickness + 1; } else { lv_coord_t sb_y = (rem * sb) / scroll_h; sb_y = rem - sb_y; - ver->y1 = obj->coords.y1 + sb_y + end_space; - ver->y2 = ver->y1 + sb_h - 1; - ver->x2 = obj->coords.x2; - ver->x1 = ver->x2 - tickness; - if(ver->y1 < obj->coords.y1) { - ver->y1 = obj->coords.y1; - if(ver->y1 + SCROLLBAR_MIN_SIZE > ver->y2) ver->y2 = ver->y1 + SCROLLBAR_MIN_SIZE; + area.y1 = obj->coords.y1 + sb_y + end_space; + area.y2 = area.y1 + sb_h - 1; + area.x2 = obj->coords.x2; + area.x1 = area.x2 - tickness; + if(area.y1 < obj->coords.y1) { + area.y1 = obj->coords.y1; + if(area.y1 + SCROLLBAR_MIN_SIZE > area.y2) area.y2 = area.y1 + SCROLLBAR_MIN_SIZE; } - if(ver->y2 > obj->coords.y2) { - ver->y2 = obj->coords.y2; - if(ver->y2 - SCROLLBAR_MIN_SIZE < ver->y1) ver->y1 = ver->y2 - SCROLLBAR_MIN_SIZE; + if(area.y2 > obj->coords.y2) { + area.y2 = obj->coords.y2; + if(area.y2 - SCROLLBAR_MIN_SIZE < area.y1) area.y1 = area.y2 - SCROLLBAR_MIN_SIZE; } } - } else { - /*Set an invalid area if not in the clip area*/ - lv_area_set(ver, -1, -1, -2, -2); + lv_draw_rect(&area, clip_area, &draw_dsc); + } - hor->y2 = obj->coords.y2; - hor->y1 = hor->y2 - tickness; - hor->x1 = obj->coords.x1; - hor->x2 = obj->coords.x2; - if(_lv_area_is_on(hor, clip_area)) { - lv_coord_t content_w = obj_w + sl + sr; + area.y2 = obj->coords.y2; + area.y1 =area.y2 - tickness; + area.x1 = obj->coords.x1; + area.x2 = obj->coords.x2; + /*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/ + if(_lv_area_is_on(&area, clip_area) && + ((sm == LV_SCROLL_MODE_ON) || + (sm == LV_SCROLL_MODE_AUTO && (sl > 0 || sr > 0)) || + (sm == LV_SCROLL_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_SCROLL_DIR_HOR))) { + lv_coord_t content_w = obj_w + sl + sr; lv_coord_t sb_w = ((obj_w - end_space * 2 - ver_reg_space) * obj_w) / content_w; sb_w = LV_MATH_MAX(sb_w, SCROLLBAR_MIN_SIZE); rem = (obj_w - end_space * 2 - ver_reg_space) - sb_w; /*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) { - hor->y2 = obj->coords.y2; - hor->y1 = hor->y2 - tickness + 1; - hor->x1 = obj->coords.x1 + end_space; - hor->x2 = obj->coords.x2 - end_space - ver_reg_space - 1; + area.y2 = obj->coords.y2; + area.y1 = area.y2 - tickness + 1; + area.x1 = obj->coords.x1 + end_space; + area.x2 = obj->coords.x2 - end_space - ver_reg_space - 1; } else { lv_coord_t sb_x = (rem * sr) / scroll_w; sb_x = rem - sb_x; - hor->x1 = obj->coords.x1 + sb_x + end_space; - hor->x2 = hor->x1 + sb_w - 1; - hor->y2 = obj->coords.y2; - hor->y1 = hor->y2 - tickness; - if(hor->x1 < obj->coords.x1) { - hor->x1 = obj->coords.x1; - if(hor->x1 + SCROLLBAR_MIN_SIZE > hor->x2) hor->x2 = hor->x1 + SCROLLBAR_MIN_SIZE; + area.x1 = obj->coords.x1 + sb_x + end_space; + area.x2 = area.x1 + sb_w - 1; + area.y2 = obj->coords.y2; + area.y1 = area.y2 - tickness; + if(area.x1 < obj->coords.x1) { + area.x1 = obj->coords.x1; + if(area.x1 + SCROLLBAR_MIN_SIZE > area.x2) area.x2 = area.x1 + SCROLLBAR_MIN_SIZE; } - if(hor->x2 > obj->coords.x2) { - hor->x2 = obj->coords.x2; - if(hor->x2 - SCROLLBAR_MIN_SIZE < hor->x1) hor->x1 = hor->x2 - SCROLLBAR_MIN_SIZE; + if(area.x2 > obj->coords.x2) { + area.x2 = obj->coords.x2; + if(area.x2 - SCROLLBAR_MIN_SIZE < area.x1) area.x1 = area.x2 - SCROLLBAR_MIN_SIZE; } } - } else { - /*Set an invalid area if not in the clip area*/ - lv_area_set(hor, -1, -1, -2, -2); + lv_draw_rect(&area, clip_area, &draw_dsc); } } diff --git a/src/lv_hal/lv_hal_disp.c b/src/lv_hal/lv_hal_disp.c index d87afb55f..ed5fbc90c 100644 --- a/src/lv_hal/lv_hal_disp.c +++ b/src/lv_hal/lv_hal_disp.c @@ -161,6 +161,9 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) lv_obj_set_click(disp->top_layer, false); lv_obj_set_click(disp->sys_layer, false); + lv_obj_set_scroll_mode(disp->top_layer, LV_SCROLL_MODE_OFF); + lv_obj_set_scroll_mode(disp->sys_layer, LV_SCROLL_MODE_OFF); + lv_obj_invalidate(disp->act_scr); disp_def = disp_def_tmp; /*Revert the default display*/ From 0b78cbf937853246371f93416bedd5704d232a61 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 21 Jul 2020 22:12:04 +0200 Subject: [PATCH 12/84] scroll: minor fixes --- src/lv_core/lv_obj.c | 59 +++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 3f23fbd96..59c151e58 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -4553,8 +4553,22 @@ static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area) lv_coord_t obj_h = lv_obj_get_height(obj); lv_coord_t obj_w = lv_obj_get_width(obj); - lv_coord_t ver_reg_space = tickness + side_space; - lv_coord_t hor_req_space = tickness + side_space; + bool ver_draw = false; + if((sm == LV_SCROLL_MODE_ON) || + (sm == LV_SCROLL_MODE_AUTO && (st > 0 || sb > 0)) || + (sm == LV_SCROLL_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_SCROLL_DIR_VER)) { + ver_draw = true; + } + + bool hor_draw = false; + if((sm == LV_SCROLL_MODE_ON) || + (sm == LV_SCROLL_MODE_AUTO && (sl > 0 || sr > 0)) || + (sm == LV_SCROLL_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_SCROLL_DIR_HOR)) { + hor_draw = true; + } + + lv_coord_t ver_reg_space = ver_draw ? tickness + side_space : 0; + lv_coord_t hor_req_space = hor_draw ? tickness + side_space : 0; lv_coord_t rem; lv_draw_rect_dsc_t draw_dsc; @@ -4564,14 +4578,11 @@ static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area) lv_area_t area; area.y1 = obj->coords.y1; area.y2 = obj->coords.y2; - area.x2 = obj->coords.x2; + area.x2 = obj->coords.x2 - side_space; area.x1 = area.x2 - tickness; /*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/ - if(_lv_area_is_on(&area, clip_area) && - ((sm == LV_SCROLL_MODE_ON) || - (sm == LV_SCROLL_MODE_AUTO && (st > 0 || sb > 0)) || - (sm == LV_SCROLL_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_SCROLL_DIR_VER))) { + if(ver_draw && _lv_area_is_on(&area, clip_area)) { lv_coord_t content_h = obj_h + st + sb; lv_coord_t sb_h = ((obj_h - end_space * 2 - hor_req_space) * obj_h) / content_h; sb_h = LV_MATH_MAX(sb_h, SCROLLBAR_MIN_SIZE); @@ -4580,7 +4591,7 @@ static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area) if(scroll_h <= 0) { area.y1 = obj->coords.y1 + end_space; area.y2 = obj->coords.y2 - end_space - hor_req_space - 1; - area.x2 = obj->coords.x2; + area.x2 = obj->coords.x2 - side_space; area.x1 = area.x2 - tickness + 1; } else { lv_coord_t sb_y = (rem * sb) / scroll_h; @@ -4588,37 +4599,33 @@ static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area) area.y1 = obj->coords.y1 + sb_y + end_space; area.y2 = area.y1 + sb_h - 1; - area.x2 = obj->coords.x2; + area.x2 = obj->coords.x2 - side_space; area.x1 = area.x2 - tickness; - if(area.y1 < obj->coords.y1) { - area.y1 = obj->coords.y1; + if(area.y1 < obj->coords.y1 + end_space) { + area.y1 = obj->coords.y1 + end_space; if(area.y1 + SCROLLBAR_MIN_SIZE > area.y2) area.y2 = area.y1 + SCROLLBAR_MIN_SIZE; } - if(area.y2 > obj->coords.y2) { - area.y2 = obj->coords.y2; + if(area.y2 > obj->coords.y2 - hor_req_space - end_space) { + area.y2 = obj->coords.y2 - hor_req_space - end_space; if(area.y2 - SCROLLBAR_MIN_SIZE < area.y1) area.y1 = area.y2 - SCROLLBAR_MIN_SIZE; } } lv_draw_rect(&area, clip_area, &draw_dsc); - } - area.y2 = obj->coords.y2; + area.y2 = obj->coords.y2 - side_space; area.y1 =area.y2 - tickness; area.x1 = obj->coords.x1; area.x2 = obj->coords.x2; /*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/ - if(_lv_area_is_on(&area, clip_area) && - ((sm == LV_SCROLL_MODE_ON) || - (sm == LV_SCROLL_MODE_AUTO && (sl > 0 || sr > 0)) || - (sm == LV_SCROLL_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_SCROLL_DIR_HOR))) { - lv_coord_t content_w = obj_w + sl + sr; + if(hor_draw && _lv_area_is_on(&area, clip_area)) { + lv_coord_t content_w = obj_w + sl + sr; lv_coord_t sb_w = ((obj_w - end_space * 2 - ver_reg_space) * obj_w) / content_w; sb_w = LV_MATH_MAX(sb_w, SCROLLBAR_MIN_SIZE); rem = (obj_w - end_space * 2 - ver_reg_space) - sb_w; /*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) { - area.y2 = obj->coords.y2; + area.y2 = obj->coords.y2 - side_space; area.y1 = area.y2 - tickness + 1; area.x1 = obj->coords.x1 + end_space; area.x2 = obj->coords.x2 - end_space - ver_reg_space - 1; @@ -4628,14 +4635,14 @@ static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area) area.x1 = obj->coords.x1 + sb_x + end_space; area.x2 = area.x1 + sb_w - 1; - area.y2 = obj->coords.y2; + area.y2 = obj->coords.y2 - side_space; area.y1 = area.y2 - tickness; - if(area.x1 < obj->coords.x1) { - area.x1 = obj->coords.x1; + if(area.x1 < obj->coords.x1 + end_space) { + area.x1 = obj->coords.x1 + end_space; if(area.x1 + SCROLLBAR_MIN_SIZE > area.x2) area.x2 = area.x1 + SCROLLBAR_MIN_SIZE; } - if(area.x2 > obj->coords.x2) { - area.x2 = obj->coords.x2; + if(area.x2 > obj->coords.x2 - ver_reg_space - end_space) { + area.x2 = obj->coords.x2 - ver_reg_space - end_space; if(area.x2 - SCROLLBAR_MIN_SIZE < area.x1) area.x1 = area.x2 - SCROLLBAR_MIN_SIZE; } } From 2278fb36104f45f2103fe3f7f5b4c0fb2ee9bd44 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 21 Jul 2020 22:12:13 +0200 Subject: [PATCH 13/84] add styling to material theme --- src/lv_themes/lv_theme_material.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index 1aa9fe580..01e79bf8b 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -221,6 +221,14 @@ static void basic_init(void) lv_style_set_image_recolor(&styles->bg, LV_STATE_DEFAULT, COLOR_BG_TEXT); lv_style_set_line_color(&styles->bg, LV_STATE_DEFAULT, COLOR_BG_TEXT); lv_style_set_line_width(&styles->bg, LV_STATE_DEFAULT, 1); + + lv_style_set_scrollbar_bg_opa(&styles->bg, LV_STATE_DEFAULT, LV_OPA_COVER); + lv_style_set_scrollbar_bg_color(&styles->bg, LV_STATE_DEFAULT, (IS_LIGHT ? lv_color_hex(0xcccfd1) : lv_color_hex(0x777f85))); + lv_style_set_scrollbar_radius(&styles->bg, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_style_set_scrollbar_tickness(&styles->bg, LV_STATE_DEFAULT, LV_DPX(7)); + lv_style_set_scrollbar_space_side(&styles->bg, LV_STATE_DEFAULT, LV_DPX(7)); + lv_style_set_scrollbar_space_end(&styles->bg, LV_STATE_DEFAULT, LV_DPX(7)); + lv_style_set_pad_left(&styles->bg, LV_STATE_DEFAULT, PAD_DEF + BORDER_WIDTH); lv_style_set_pad_right(&styles->bg, LV_STATE_DEFAULT, PAD_DEF + BORDER_WIDTH); lv_style_set_pad_top(&styles->bg, LV_STATE_DEFAULT, PAD_DEF + BORDER_WIDTH); From f739506dddf4d96a6f96c86e4448ea353eecac49 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 5 Aug 2020 11:06:48 +0200 Subject: [PATCH 14/84] add linemeter's mirror feature again the drawing part was somehow removed --- CHANGELOG.md | 1 + src/lv_widgets/lv_linemeter.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0748227c..62fc6fec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Bugfixes - Fix drawing value string twice - Rename `lv_chart_clear_serie` to `lv_chart_clear_series` and `lv_obj_align_origo` to `lv_obj_align_mid` +- Add linemeter's mirror feature again ## v7.3.0 (04.08.2020) diff --git a/src/lv_widgets/lv_linemeter.c b/src/lv_widgets/lv_linemeter.c index c8e7ae724..d8043f876 100644 --- a/src/lv_widgets/lv_linemeter.c +++ b/src/lv_widgets/lv_linemeter.c @@ -392,15 +392,15 @@ void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uin lv_coord_t x_ofs = lmeter->coords.x1 + r_out + left; lv_coord_t y_ofs = lmeter->coords.y1 + r_out + top; int16_t angle_ofs = ext->angle_ofs + 90 + (360 - ext->scale_angle) / 2; - int16_t level = - (int32_t)((int32_t)(ext->cur_value - ext->min_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value); + int16_t level = ext->mirrored ? + (int32_t)((int32_t)(ext->max_value - ext->cur_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value) : + (int32_t)((int32_t)(ext->cur_value - ext->min_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value); uint8_t i; lv_color_t main_color = lv_obj_get_style_line_color(lmeter, part); lv_color_t grad_color = lv_obj_get_style_scale_grad_color(lmeter, part); lv_color_t end_color = lv_obj_get_style_scale_end_color(lmeter, part); - lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_init(&line_dsc); lv_obj_init_draw_line_dsc(lmeter, part, &line_dsc); @@ -520,11 +520,11 @@ void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uin p1.y = y_out_extra; /* Set the color of the lines */ - if(i > level) { + uint16_t index = ext->mirrored ? ext->line_cnt - i : i; + if((!ext->mirrored && i >= level) || (ext->mirrored && i <= level)) { line_dsc.color = end_color; line_dsc.width = end_line_width; - } - else { + } else { line_dsc.color = lv_color_mix(grad_color, main_color, (255 * i) / ext->line_cnt); } From 756522a64c3efc2be4e344512afbec1965bc8db9 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 19 Aug 2020 20:16:20 +0200 Subject: [PATCH 15/84] add auto size --- src/lv_api_map.h | 15 --- src/lv_core/lv_indev.c | 4 +- src/lv_core/lv_obj.c | 300 ++++++++++------------------------------- src/lv_core/lv_obj.h | 88 +----------- src/lv_misc/lv_area.h | 7 + 5 files changed, 84 insertions(+), 330 deletions(-) diff --git a/src/lv_api_map.h b/src/lv_api_map.h index d8e904e8a..578fabe6b 100644 --- a/src/lv_api_map.h +++ b/src/lv_api_map.h @@ -209,21 +209,6 @@ static inline void lv_chart_clear_serie(lv_obj_t * chart, lv_chart_series_t * se #endif -static inline void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) -{ - lv_obj_align_mid(obj, base, align, x_ofs, y_ofs); -} - -static inline void lv_obj_align_origo_x(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs) -{ - lv_obj_align_mid_y(obj, base, align, x_ofs); -} - -static inline void lv_obj_align_origo_y(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t y_ofs) -{ - lv_obj_align_mid_y(obj, base, align, y_ofs); -} - #endif /*LV_USE_API_EXTENSION_V6*/ /********************** * MACROS diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index af756f4b5..e820fe127 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -1292,7 +1292,7 @@ static void indev_scroll_handler(lv_indev_proc_t * proc) if(lv_obj_get_scroll_top(scroll_obj) < 0) diff_y = diff_y / 2; if(lv_obj_get_scroll_bottom(scroll_obj) < 0) diff_y = diff_y / 2; } - lv_obj_scroll_by(scroll_obj, diff_x, diff_y, LV_ANIM_OFF); + lv_obj_scroll_by_raw(scroll_obj, diff_x, diff_y); } } @@ -1335,7 +1335,7 @@ static void indev_scroll_throw_handler(lv_indev_proc_t * proc) } if((proc->types.pointer.scroll_throw_vect.x != 0 || proc->types.pointer.scroll_throw_vect.y != 0)) { - lv_obj_scroll_by(scroll_obj, proc->types.pointer.scroll_throw_vect.x, proc->types.pointer.scroll_throw_vect.y, LV_ANIM_OFF); + lv_obj_scroll_by_raw(scroll_obj, proc->types.pointer.scroll_throw_vect.x, proc->types.pointer.scroll_throw_vect.y); } /*If the vectors become 0 then finish scrolling signal*/ diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 0436c8cb3..f5b818d7a 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -307,15 +307,6 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->ext_click_pad_ver = 0; #endif - /*Init realign*/ -#if LV_USE_OBJ_REALIGN - new_obj->realign.align = LV_ALIGN_CENTER; - new_obj->realign.xofs = 0; - new_obj->realign.yofs = 0; - new_obj->realign.base = NULL; - new_obj->realign.auto_realign = 0; -#endif - /*Init. user date*/ #if LV_USE_USER_DATA _lv_memset_00(&new_obj->user_data, sizeof(lv_obj_user_data_t)); @@ -368,15 +359,6 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) _lv_memcpy(&new_obj->user_data, ©->user_data, sizeof(lv_obj_user_data_t)); #endif - /*Copy realign*/ -#if LV_USE_OBJ_REALIGN - new_obj->realign.align = copy->realign.align; - new_obj->realign.xofs = copy->realign.xofs; - new_obj->realign.yofs = copy->realign.yofs; - new_obj->realign.base = copy->realign.base; - new_obj->realign.auto_realign = copy->realign.auto_realign; -#endif - /*Only copy the `event_cb`. `signal_cb` and `design_cb` will be copied in the derived * object type (e.g. `lv_btn`)*/ new_obj->event_cb = copy->event_cb; @@ -678,24 +660,20 @@ void lv_obj_move_background(lv_obj_t * obj) * Coordinate set * ------------------*/ -/** - * Set relative the position of an object (relative to the parent) - * @param obj pointer to an object - * @param x new distance from the left side of the parent - * @param y new distance from the top of the parent - */ -void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +static void refr_pos(lv_obj_t * obj) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - /*Convert x and y to absolute coordinates*/ lv_obj_t * par = obj->parent; + lv_coord_t x = obj->x_set; + lv_coord_t y = obj->y_set; if(par) { - x = x + par->coords.x1; - y = y + par->coords.y1; - } + lv_coord_t pad_left = lv_obj_get_style_pad_left(par, LV_OBJ_PART_MAIN); + lv_coord_t pad_top = lv_obj_get_style_pad_top(par, LV_OBJ_PART_MAIN); + x += pad_left + par->coords.x1 - lv_obj_get_scroll_left(par); + y += pad_top + par->coords.y1 - lv_obj_get_scroll_top(par); + } /*Calculate and set the movement*/ lv_point_t diff; @@ -731,6 +709,23 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) lv_obj_invalidate(obj); } +/** + * Set relative the position of an object (relative to the parent) + * @param obj pointer to an object + * @param x new distance from the left side of the parent + * @param y new distance from the top of the parent + */ +void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + obj->x_set = x; + obj->y_set = y; + + refr_pos(obj); + +} + /** * Set the x coordinate of a object * @param obj pointer to an object @@ -755,15 +750,27 @@ void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y) lv_obj_set_pos(obj, lv_obj_get_x(obj), y); } -/** - * Set the size of an object - * @param obj pointer to an object - * @param w new width - * @param h new height - */ -void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) +static void refr_size(lv_obj_t * obj) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_coord_t w = 0; + lv_coord_t h = 0; + + + if(LV_COORD_IS_AUTO(obj->w_set)) { + lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF); + lv_coord_t scroll_right = lv_obj_get_scroll_right(obj); + w = lv_obj_get_width(obj) + scroll_right; + } else { + w = obj->w_set; + } + + if(LV_COORD_IS_AUTO(obj->h_set)) { + lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); + lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj); + h = lv_obj_get_height(obj) + scroll_bottom; + } else { + h = obj->h_set; + } /* Do nothing if the size is not changed */ /* It is very important else recursive resizing can @@ -803,11 +810,22 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) /*Invalidate the new area*/ lv_obj_invalidate(obj); +} - /*Automatically realign the object if required*/ -#if LV_USE_OBJ_REALIGN - if(obj->realign.auto_realign) lv_obj_realign(obj); -#endif +/** + * Set the size of an object + * @param obj pointer to an object + * @param w new width + * @param h new height + */ +void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + obj->w_set = w; + obj->h_set = h; + + refr_size(obj); } /** @@ -905,163 +923,6 @@ void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_co LV_ASSERT_OBJ(base, LV_OBJX_NAME); obj_align_core(obj, base, align, true, true, x_ofs, y_ofs); - -#if LV_USE_OBJ_REALIGN - /*Save the last align parameters to use them in `lv_obj_realign`*/ - obj->realign.align = align; - obj->realign.xofs = x_ofs; - obj->realign.yofs = y_ofs; - obj->realign.base = base; - obj->realign.mid_align = 0; -#endif -} - -/** - * Align an object to an other object horizontally. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param x_ofs x coordinate offset after alignment - */ -void lv_obj_align_x(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - if(base == NULL) base = lv_obj_get_parent(obj); - - LV_ASSERT_OBJ(base, LV_OBJX_NAME); - - obj_align_core(obj, base, align, true, false, x_ofs, 0); -} - -/** - * Align an object to an other object vertically. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param y_ofs y coordinate offset after alignment - */ -void lv_obj_align_y(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t y_ofs) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - if(base == NULL) base = lv_obj_get_parent(obj); - - LV_ASSERT_OBJ(base, LV_OBJX_NAME); - - obj_align_core(obj, base, align, true, false, 0, y_ofs); -} - -/** - * Align an object's middle point to an other object. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param x_ofs x coordinate offset after alignment - * @param y_ofs y coordinate offset after alignment - */ -void lv_obj_align_mid(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - if(base == NULL) { - base = lv_obj_get_parent(obj); - } - - LV_ASSERT_OBJ(base, LV_OBJX_NAME); - - - obj_align_mid_core(obj, base, align, true, true, x_ofs, y_ofs); - -#if LV_USE_OBJ_REALIGN - /*Save the last align parameters to use them in `lv_obj_realign`*/ - obj->realign.align = align; - obj->realign.xofs = x_ofs; - obj->realign.yofs = y_ofs; - obj->realign.base = base; - obj->realign.mid_align = 1; -#endif -} - -/** - * Align an object's middle point to an other object horizontally. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param x_ofs x coordinate offset after alignment - */ -void lv_obj_align_mid_x(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - if(base == NULL) { - base = lv_obj_get_parent(obj); - } - - LV_ASSERT_OBJ(base, LV_OBJX_NAME); - - - obj_align_mid_core(obj, base, align, true, false, x_ofs, 0); -} - - -/** - * Align an object's middle point to an other object vertically. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param y_ofs y coordinate offset after alignment - */ -void lv_obj_align_mid_y(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t y_ofs) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - if(base == NULL) { - base = lv_obj_get_parent(obj); - } - - LV_ASSERT_OBJ(base, LV_OBJX_NAME); - - - obj_align_mid_core(obj, base, align, true, false, 0, y_ofs); -} - -/** - * Realign the object based on the last `lv_obj_align` parameters. - * @param obj pointer to an object - */ -void lv_obj_realign(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - -#if LV_USE_OBJ_REALIGN - if(obj->realign.mid_align) - lv_obj_align_mid(obj, obj->realign.base, obj->realign.align, obj->realign.xofs, obj->realign.yofs); - else - lv_obj_align(obj, obj->realign.base, obj->realign.align, obj->realign.xofs, obj->realign.yofs); -#else - (void)obj; - LV_LOG_WARN("lv_obj_realign: no effect because LV_USE_OBJ_REALIGN = 0"); -#endif -} - -/** - * Enable the automatic realign of the object when its size has changed based on the last - * `lv_obj_align` parameters. - * @param obj pointer to an object - * @param en true: enable auto realign; false: disable auto realign - */ -void lv_obj_set_auto_realign(lv_obj_t * obj, bool en) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - -#if LV_USE_OBJ_REALIGN - obj->realign.auto_realign = en ? 1 : 0; -#else - (void)obj; - (void)en; - LV_LOG_WARN("lv_obj_set_auto_realign: no effect because LV_USE_OBJ_REALIGN = 0"); -#endif } /** @@ -1103,7 +964,7 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable 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, x)); + lv_anim_set_time(&a, lv_anim_speed_to_time((lv_disp_get_hor_res(d) * 3) >> 2, 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); @@ -1140,7 +1001,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) { - lv_obj_scroll_by(obj, x - obj->scroll.x, 0, anim_en); + lv_obj_scroll_by(obj, -x - obj->scroll.x, 0, anim_en); } /** @@ -1150,7 +1011,7 @@ void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en) */ void lv_obj_scroll_to_y(lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en) { - lv_obj_scroll_by(obj, 0, y - obj->scroll.y, anim_en); + lv_obj_scroll_by(obj, 0, -y - obj->scroll.y, anim_en); } @@ -2302,7 +2163,9 @@ lv_coord_t lv_obj_get_x(const lv_obj_t * obj) lv_coord_t rel_x; lv_obj_t * parent = lv_obj_get_parent(obj); if(parent) { - rel_x = obj->coords.x1 - parent->coords.x1; + rel_x = obj->coords.x1 - parent->coords.x1; + rel_x += lv_obj_get_scroll_left(parent); + rel_x -= lv_obj_get_style_pad_left(parent, LV_OBJ_PART_MAIN); } else { rel_x = obj->coords.x1; @@ -2322,7 +2185,9 @@ lv_coord_t lv_obj_get_y(const lv_obj_t * obj) lv_coord_t rel_y; lv_obj_t * parent = lv_obj_get_parent(obj); if(parent) { - rel_y = obj->coords.y1 - parent->coords.y1; + rel_y = obj->coords.y1 - parent->coords.y1; + rel_y += lv_obj_get_scroll_top(parent); + rel_y -= lv_obj_get_style_pad_top(parent, LV_OBJ_PART_MAIN); } else { rel_y = obj->coords.y1; @@ -2454,23 +2319,6 @@ lv_coord_t lv_obj_get_height_grid(lv_obj_t * obj, uint8_t div, uint8_t span) return r; } -/** - * Get the automatic realign property of the object. - * @param obj pointer to an object - * @return true: auto realign is enabled; false: auto realign is disabled - */ -bool lv_obj_get_auto_realign(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - -#if LV_USE_OBJ_REALIGN - return obj->realign.auto_realign ? true : false; -#else - (void)obj; - return false; -#endif -} - /** * Get the left padding of extended clickable area * @param obj pointer to an object @@ -3898,13 +3746,6 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) lv_coord_t d = lv_obj_get_draw_rect_ext_pad_size(obj, LV_OBJ_PART_MAIN); obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d); } -#if LV_USE_OBJ_REALIGN - else if(sign == LV_SIGNAL_PARENT_SIZE_CHG) { - if(obj->realign.auto_realign) { - lv_obj_realign(obj); - } - } -#endif else if(sign == LV_SIGNAL_STYLE_CHG) { lv_obj_refresh_ext_draw_pad(obj); } @@ -4000,6 +3841,7 @@ static void report_style_mod_core(void * style, lv_obj_t * obj) } + /** * Recursively refresh the style of the children. Go deeper until a not NULL style is found * because the NULL styles are inherited from the parent @@ -4512,7 +4354,7 @@ static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area) lv_coord_t sr = lv_obj_get_scroll_right(obj); /*Return if too small content to scroll*/ - if(sm == LV_SCROLL_MODE_AUTO && st <= 0 && sb <= 0 && sl <= 0 && sl <= 0) { + if(sm == LV_SCROLL_MODE_AUTO && st <= 0 && sb <= 0 && sl <= 0 && sr <= 0) { return; } diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index ff8e36aa3..22d9339af 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -157,18 +157,6 @@ typedef uint8_t lv_signal_t; typedef lv_res_t (*lv_signal_cb_t)(struct _lv_obj_t * obj, lv_signal_t sign, void * param); -#if LV_USE_OBJ_REALIGN -typedef struct { - const struct _lv_obj_t * base; - lv_coord_t xofs; - lv_coord_t yofs; - lv_align_t align; - uint8_t auto_realign : 1; - uint8_t mid_align : 1; /**< 1: the origo (center of the object) was aligned with - `lv_obj_align_origo`*/ -} lv_realign_t; -#endif - /*Protect some attributes (max. 8 bit)*/ enum { LV_PROTECT_NONE = 0x00, @@ -237,6 +225,10 @@ typedef struct _lv_obj_t { uint8_t focus_parent : 1; /**< 1: Parent will be focused instead*/ lv_scroll_mode_t scroll_mode :2; /**< How to display scrollbars*/ lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */ + lv_coord_t x_set; + lv_coord_t y_set; + lv_coord_t w_set; + lv_coord_t h_set; #if LV_USE_GROUP != 0 void * group_p; @@ -246,10 +238,6 @@ typedef struct _lv_obj_t { 'OR'ed values from `lv_protect_t`*/ lv_state_t state; -#if LV_USE_OBJ_REALIGN - lv_realign_t realign; /**< Information about the last call to ::lv_obj_align. */ -#endif - #if LV_USE_USER_DATA lv_obj_user_data_t user_data; /**< Custom user data for object. */ #endif @@ -476,67 +464,6 @@ void lv_obj_set_height_margin(lv_obj_t * obj, lv_coord_t h); */ void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs); -/** - * Align an object to an other object horizontally. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param x_ofs x coordinate offset after alignment - */ -void lv_obj_align_x(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs); - -/** - * Align an object to an other object vertically. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param y_ofs y coordinate offset after alignment - */ -void lv_obj_align_y(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t y_ofs); - -/** - * Align an object to an other object. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param x_ofs x coordinate offset after alignment - * @param y_ofs y coordinate offset after alignment - */ -void lv_obj_align_mid(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs); - - -/** - * Align an object's middle point to an other object horizontally. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param x_ofs x coordinate offset after alignment - */ -void lv_obj_align_mid_x(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs); - -/** - * Align an object's middle point to an other object vertically. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param y_ofs y coordinate offset after alignment - */ -void lv_obj_align_mid_y(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t y_ofs); - -/** - * Realign the object based on the last `lv_obj_align` parameters. - * @param obj pointer to an object - */ -void lv_obj_realign(lv_obj_t * obj); - -/** - * Enable the automatic realign of the object when its size has changed based on the last - * `lv_obj_align` parameters. - * @param obj pointer to an object - * @param en true: enable auto realign; false: disable auto realign - */ -void lv_obj_set_auto_realign(lv_obj_t * obj, bool en); - /** * Moves all children with horizontally or vertically. * It doesn't take into account any limits so any values are possible @@ -1123,13 +1050,6 @@ lv_coord_t lv_obj_get_width_grid(lv_obj_t * obj, uint8_t div, uint8_t span); */ lv_coord_t lv_obj_get_height_grid(lv_obj_t * obj, uint8_t div, uint8_t span); -/** - * Get the automatic realign property of the object. - * @param obj pointer to an object - * @return true: auto realign is enabled; false: auto realign is disabled - */ -bool lv_obj_get_auto_realign(const lv_obj_t * obj); - /** * Get the left padding of extended clickable area * @param obj pointer to an object diff --git a/src/lv_misc/lv_area.h b/src/lv_misc/lv_area.h index 879a9c03a..6bbb3afb2 100644 --- a/src/lv_misc/lv_area.h +++ b/src/lv_misc/lv_area.h @@ -208,6 +208,13 @@ void _lv_area_align(const lv_area_t * base, const lv_area_t * to_align, lv_align * MACROS **********************/ +#define LV_COORD_PX(x) (x) +#define LV_COORD_AUTO (LV_COORD_MAX - 100) + +#define LV_COORD_IS_PX(x) (((x) < LV_COORD_MAX - 1000) ? true : false) +#define LV_COORD_IS_AUTO(x) (((x) == LV_COORD_MAX - 100) ? true : false) + + #ifdef __cplusplus } /* extern "C" */ #endif From 43b706f2d420f2d6dd1bd0dc74a4e7d19b7ded9d Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 26 Aug 2020 15:25:35 +0200 Subject: [PATCH 16/84] add layout files --- src/lv_core/lv_layout.c | 0 src/lv_core/lv_layout.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/lv_core/lv_layout.c create mode 100644 src/lv_core/lv_layout.h diff --git a/src/lv_core/lv_layout.c b/src/lv_core/lv_layout.c new file mode 100644 index 000000000..e69de29bb diff --git a/src/lv_core/lv_layout.h b/src/lv_core/lv_layout.h new file mode 100644 index 000000000..e69de29bb From 5d345c1d562d7d26fd6398bad05ecb753855e8d6 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 27 Aug 2020 09:39:27 +0200 Subject: [PATCH 17/84] start grid --- src/lv_core/lv_align.c | 36 +++++++++++++++++++++++++++ src/lv_core/lv_align.h | 54 +++++++++++++++++++++++++++++++++++++++++ src/lv_core/lv_layout.c | 0 src/lv_core/lv_layout.h | 0 src/lv_core/lv_obj.c | 11 +++------ 5 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 src/lv_core/lv_align.c create mode 100644 src/lv_core/lv_align.h delete mode 100644 src/lv_core/lv_layout.c delete mode 100644 src/lv_core/lv_layout.h diff --git a/src/lv_core/lv_align.c b/src/lv_core/lv_align.c new file mode 100644 index 000000000..580c08a5c --- /dev/null +++ b/src/lv_core/lv_align.c @@ -0,0 +1,36 @@ +/** + * @file lv_align.c + * + */ + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/src/lv_core/lv_align.h b/src/lv_core/lv_align.h new file mode 100644 index 000000000..74f0af775 --- /dev/null +++ b/src/lv_core/lv_align.h @@ -0,0 +1,54 @@ +/** + * @file lv_templ.h + * + */ + +#ifndef LV_ALIGN_H +#define LV_ALIGN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + const lv_coord_t * col_dsc; + const lv_coord_t * row_dsc; + lv_coord_t gap_col; + lv_coord_t gap_row; + uint8_t flow; + uint8_t place_content; + uint8_t place_items; +}lv_grid_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_grid_init(lv_grid_t * grid); + +void lv_grid_set_template(lv_grid_t * grid, const lv_coord_t * col_dsc, const lv_coord_t * row_dsc); + +void lv_grid_set_place_content(lv_grid_t * grid, uint8_t col_mode, uint8_t row_mode); + +void lv_grid_set_place_items(lv_grid_t * grid, uint8_t col_mode, uint8_t row_mode); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_ALIGN_H*/ diff --git a/src/lv_core/lv_layout.c b/src/lv_core/lv_layout.c deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/lv_core/lv_layout.h b/src/lv_core/lv_layout.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 021357ae4..b04278d01 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -106,15 +106,12 @@ static void lv_event_mark_deleted(lv_obj_t * obj); 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); -<<<<<<< HEAD static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc); static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area); - -======= static void update_style_cache(lv_obj_t * obj, uint8_t part, uint16_t prop); static void update_style_cache_children(lv_obj_t * obj); static void invalidate_style_cache(lv_obj_t * obj, uint8_t part, lv_style_property_t prop); ->>>>>>> master + /********************** * STATIC VARIABLES **********************/ @@ -4484,7 +4481,7 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin return false; } -<<<<<<< HEAD + static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc) { lv_draw_rect_dsc_init(dsc); @@ -4648,7 +4645,7 @@ static void scrollbar_draw(lv_obj_t * obj, const lv_area_t * clip_area) } } -======= + static bool style_prop_is_cacheble(lv_style_property_t prop) { @@ -4846,5 +4843,3 @@ static void invalidate_style_cache(lv_obj_t * obj, uint8_t part, lv_style_proper child = lv_obj_get_child(obj, child); } } ->>>>>>> master - From c801a2cfa2449792f380d72f2136cdbe35216fbb Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 28 Aug 2020 18:48:52 +0200 Subject: [PATCH 18/84] basic grid working --- src/lv_core/lv_align.c | 50 +++++++++ src/lv_core/lv_align.h | 90 ++++++++++++++-- src/lv_core/lv_obj.c | 240 +++++++++++++++++++++++++++++------------ src/lv_core/lv_obj.h | 3 + src/lv_misc/lv_area.h | 11 +- 5 files changed, 316 insertions(+), 78 deletions(-) diff --git a/src/lv_core/lv_align.c b/src/lv_core/lv_align.c index 580c08a5c..a9ed4cf83 100644 --- a/src/lv_core/lv_align.c +++ b/src/lv_core/lv_align.c @@ -6,6 +6,7 @@ /********************* * INCLUDES *********************/ +#include "lv_align.h" /********************* * DEFINES @@ -31,6 +32,55 @@ * GLOBAL FUNCTIONS **********************/ +void grid_calc(lv_grid_t * grid, _lv_grid_calc_t * calc) +{ + calc->col_dsc_len = grid->col_dsc_len + 1; + calc->col_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->col_dsc_len); + calc->row_dsc_len = grid->row_dsc_len + 1; + calc->row_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->row_dsc_len); + + calc->col_dsc[0] = 0; + calc->row_dsc[0] = 0; + + uint8_t i; + for(i = 0; i < grid->col_dsc_len; i++) { + calc->col_dsc[i + 1] = calc->col_dsc[i] + grid->col_dsc[i]; + } + for(i = 0; i < grid->row_dsc_len; i++) { + calc->row_dsc[i + 1] = calc->row_dsc[i] + grid->row_dsc[i]; + } +} + +void grid_calc_free(_lv_grid_calc_t * calc) +{ + _lv_mem_buf_release(calc->col_dsc); + _lv_mem_buf_release(calc->row_dsc); +} + +uint8_t _lv_grid_get_col_type(lv_grid_t * grid, uint32_t col) +{ + lv_coord_t x; + /*If explicitly defined get the column size else use the first column*/ + if(col < grid->col_dsc_len) x = grid->col_dsc[col]; + else x = grid->col_dsc[0]; + + if(_GRID_IS_FR(x)) return _GRID_CELL_SIZE_FR; + else if(_GRID_IS_AUTO(x)) return _GRID_CELL_SIZE_AUTO; + else return _GRID_CELL_SIZE_PX; +} + +uint8_t _lv_grid_get_row_type(lv_grid_t * grid, uint32_t row) +{ + lv_coord_t x; + /*If explicitly defined get the row size else use the first row*/ + if(row < grid->row_dsc_len) x = grid->row_dsc[row]; + else x = grid->row_dsc[0]; + + if(_GRID_IS_FR(x)) return _GRID_CELL_SIZE_FR; + else if(_GRID_IS_AUTO(x)) return _GRID_CELL_SIZE_AUTO; + else return _GRID_CELL_SIZE_PX; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/lv_core/lv_align.h b/src/lv_core/lv_align.h index 74f0af775..c32e422a6 100644 --- a/src/lv_core/lv_align.h +++ b/src/lv_core/lv_align.h @@ -1,5 +1,5 @@ /** - * @file lv_templ.h + * @file lv_grid.h * */ @@ -13,24 +13,94 @@ extern "C" { /********************* * INCLUDES *********************/ +#include "../lv_misc/lv_area.h" /********************* * DEFINES *********************/ +#define LV_GRID_CENTER 0 +#define LV_GRID_START 1 +#define LV_GRID_END 2 +#define LV_GRID_STRETCH 3 +#define LV_GRID_SPACE_EVENLY 4 +#define LV_GRID_SPACE_AROUND 5 +#define LV_GRID_SPACE_BETWEEN 6 + +/** + * Some helper defines + * */ +#define _GRID_IS_CELL(c) ((c) > LV_COORD_MAX ? true : false) +#define _GRID_CELL_SHIFT 5 +#define _GRID_CELL_MAX ((1 << _GRID_CELL_SHIFT) - 1) +#define _GRID_CELL_POS_MASK ((1 << _GRID_CELL_SHIFT) - 1) +#define _GRID_CELL_SPAN_MASK (_GRID_CELL_POS_MASK << _GRID_CELL_SHIFT) +#define _GRID_CELL_FLAG_MASK (_GRID_CELL_POS_MASK << (2 * _GRID_CELL_SHIFT)) +#define _GRID_CELL_FLAG(b) ((b) << (_GRID_CELL_SHIFT * 2)) +#define _GRID_CELL_AUTO _GRID_CELL_MAX +#define _GRID_GET_CELL_POS(c) ((c) & _GRID_CELL_POS_MASK) +#define _GRID_GET_CELL_SPAN(c) (((c) & _GRID_CELL_SPAN_MASK) >> _GRID_CELL_SHIFT) +#define _GRID_GET_CELL_FLAG(c) ((c) >> (_GRID_CELL_SHIFT * 2) & 0x3) + +#define _GRID_CELL_SIZE_PX 0 /* The cell size is set in pixels*/ +#define _GRID_CELL_SIZE_FR 1 /* The cell size is set in free units*/ +#define _GRID_CELL_SIZE_AUTO 2 /* The cell size is automatically set to content*/ + +#define LV_GRID_FR(x) (LV_COORD_MAX + (x)) +#define LV_GRID_AUTO LV_COORD_AUTO + +#define _GRID_IS_PX(x) ((_GRID_IS_FR(x) == false) && (_GRID_IS_AUTO(x) == false) ? true : false) +#define _GRID_IS_FR(x) (x > LV_COORD_MAX ? true : false) +#define _GRID_IS_AUTO(x) (x == LV_GRID_AUTO ? true : false) + + +/** + * Define a grid cell with position and span. + * Can be used like `lv_obj_set_pos(btn, LV_GRID_CELL(3,2), LV_GRID_CELL(2,1))` + */ +#define LV_GRID_CELL_START(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_START)) +#define LV_GRID_CELL_END(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_END)) +#define LV_GRID_CELL_CENTER(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_CENTER)) +#define LV_GRID_CELL_STRETCH(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_STRETCH)) + +/** + * Special LV_GRID_CELL position to flow the object automatically. + * Both X (column) and Y (row) value needs to be AUTO or explicitly specified*/ +#define LV_GRID_AUTO_START LV_GRID_CELL_START(_GRID_CELL_AUTO, 0) +#define LV_GRID_AUTO_END LV_GRID_CELL_END(_GRID_CELL_AUTO, 0) +#define LV_GRID_AUTO_CENTER LV_GRID_CELL_CENTER(_GRID_CELL_AUTO, 0) +#define LV_GRID_AUTO_STRETCH LV_GRID_CELL_STRETCH(_GRID_CELL_AUTO, 0) + /********************** * TYPEDEFS **********************/ + +/** + * Describe how to flow LV_GRID_POS_AUTO elements + */ +typedef enum { + LV_GRID_FLOW_COLUMN, /**Fill each column and add now columns if required*/ + LV_GRID_FLOW_ROW, /**Fill each row and add now rows if required*/ +}lv_grid_flow_t; + typedef struct { const lv_coord_t * col_dsc; const lv_coord_t * row_dsc; - lv_coord_t gap_col; - lv_coord_t gap_row; - uint8_t flow; + uint8_t col_dsc_len; + uint8_t row_dsc_len; + lv_coord_t col_gap; + lv_coord_t row_gap; + lv_grid_flow_t flow; uint8_t place_content; - uint8_t place_items; }lv_grid_t; +typedef struct { + lv_coord_t * col_dsc; + lv_coord_t * row_dsc; + uint8_t col_dsc_len; + uint8_t row_dsc_len; +}_lv_grid_calc_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -39,9 +109,15 @@ void lv_grid_init(lv_grid_t * grid); void lv_grid_set_template(lv_grid_t * grid, const lv_coord_t * col_dsc, const lv_coord_t * row_dsc); -void lv_grid_set_place_content(lv_grid_t * grid, uint8_t col_mode, uint8_t row_mode); +void lv_grid_set_place_content(lv_grid_t * grid, uint8_t col_place, uint8_t row_place); -void lv_grid_set_place_items(lv_grid_t * grid, uint8_t col_mode, uint8_t row_mode); +void grid_calc(lv_grid_t * grid, _lv_grid_calc_t * calc); + +void grid_calc_free(_lv_grid_calc_t * calc); + +uint8_t _lv_grid_get_col_type(lv_grid_t * grid, uint32_t row); + +uint8_t _lv_grid_get_row_type(lv_grid_t * grid, uint32_t col); /********************** * MACROS diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index b04278d01..7f19e3865 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -699,19 +699,25 @@ void lv_obj_move_background(lv_obj_t * obj) * Coordinate set * ------------------*/ -static void refr_pos(lv_obj_t * obj) +static void refr_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) { /*Convert x and y to absolute coordinates*/ lv_obj_t * par = obj->parent; - lv_coord_t x = obj->x_set; - lv_coord_t y = obj->y_set; if(par) { lv_coord_t pad_left = lv_obj_get_style_pad_left(par, LV_OBJ_PART_MAIN); lv_coord_t pad_top = lv_obj_get_style_pad_top(par, LV_OBJ_PART_MAIN); x += pad_left + par->coords.x1 - lv_obj_get_scroll_left(par); y += pad_top + par->coords.y1 - lv_obj_get_scroll_top(par); + } else { + /*If no parent then it's screen but screen can't be on a grid*/ + if(_GRID_IS_CELL(obj->x_set) || _GRID_IS_CELL(obj->x_set)) { + obj->x_set = 0; + obj->y_set = 0; + x = 0; + y = 0; + } } /*Calculate and set the movement*/ @@ -748,76 +754,18 @@ static void refr_pos(lv_obj_t * obj) lv_obj_invalidate(obj); } -/** - * Set relative the position of an object (relative to the parent) - * @param obj pointer to an object - * @param x new distance from the left side of the parent - * @param y new distance from the top of the parent - */ -void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) + +static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->x_set = x; - obj->y_set = y; - - refr_pos(obj); - -} - -/** - * Set the x coordinate of a object - * @param obj pointer to an object - * @param x new distance from the left side from the parent - */ -void lv_obj_set_x(lv_obj_t * obj, lv_coord_t x) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_obj_set_pos(obj, x, lv_obj_get_y(obj)); -} - -/** - * Set the y coordinate of a object - * @param obj pointer to an object - * @param y new distance from the top of the parent - */ -void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_obj_set_pos(obj, lv_obj_get_x(obj), y); -} - -static void refr_size(lv_obj_t * obj) -{ - lv_coord_t w = 0; - lv_coord_t h = 0; - - - if(LV_COORD_IS_AUTO(obj->w_set)) { - lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF); - lv_coord_t scroll_right = lv_obj_get_scroll_right(obj); - w = lv_obj_get_width(obj) + scroll_right; - } else { - w = obj->w_set; - } - - if(LV_COORD_IS_AUTO(obj->h_set)) { - lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); - lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj); - h = lv_obj_get_height(obj) + scroll_bottom; - } else { - h = obj->h_set; - } /* Do nothing if the size is not changed */ /* It is very important else recursive resizing can * occur without size change*/ if(lv_obj_get_width(obj) == w && lv_obj_get_height(obj) == h) { - return; + return false; } + /*Invalidate the original area*/ lv_obj_invalidate(obj); @@ -849,6 +797,121 @@ static void refr_size(lv_obj_t * obj) /*Invalidate the new area*/ lv_obj_invalidate(obj); + + return true; +} + + + +static void lv_grid_refresh_item_pos(lv_obj_t * obj) +{ + /*Calculate the grid*/ + lv_obj_t * parent = lv_obj_get_parent(obj); + lv_coord_t * col_dsc; + lv_coord_t * row_dsc; + uint8_t col_num; + uint8_t row_num; + _lv_grid_calc_t calc; + grid_calc(parent->grid, &calc); + + uint8_t col_pos = _GRID_GET_CELL_POS(obj->x_set); + uint8_t col_span = _GRID_GET_CELL_SPAN(obj->x_set); + uint8_t row_pos = _GRID_GET_CELL_POS(obj->y_set); + uint8_t row_span = _GRID_GET_CELL_SPAN(obj->y_set); + + lv_coord_t col_w = calc.col_dsc[col_pos + col_span] - calc.col_dsc[col_pos]; + lv_coord_t row_h = calc.row_dsc[row_pos + row_span] - calc.row_dsc[row_pos]; + + uint8_t x_flag = _GRID_GET_CELL_FLAG(obj->x_set); + uint8_t y_flag = _GRID_GET_CELL_FLAG(obj->y_set); + + lv_coord_t x; + lv_coord_t y; + lv_coord_t w = lv_obj_get_width(obj); + lv_coord_t h = lv_obj_get_height(obj); + + switch(x_flag) { + case LV_GRID_START: + x = calc.col_dsc[col_pos]; + break; + case LV_GRID_STRETCH: + x = calc.col_dsc[col_pos]; + w = col_w; + break; + case LV_GRID_CENTER: + x = calc.col_dsc[col_pos] + (col_w - w) / 2; + break; + case LV_GRID_END: + x = calc.col_dsc[col_pos + 1] - lv_obj_get_width(obj); + break; + } + + switch(y_flag) { + case LV_GRID_START: + y = calc.row_dsc[row_pos]; + break; + case LV_GRID_STRETCH: + y = calc.row_dsc[row_pos]; + h = row_h; + break; + case LV_GRID_CENTER: + y = calc.row_dsc[row_pos] + (row_h - h) / 2; + break; + case LV_GRID_END: + y = calc.row_dsc[row_pos + 1] - lv_obj_get_height(obj); + break; + } + + refr_pos(obj, x, y); + refr_size(obj, w, h); + + grid_calc_free(&calc); +} + + +/** + * Set relative the position of an object (relative to the parent) + * @param obj pointer to an object + * @param x new distance from the left side of the parent + * @param y new distance from the top of the parent + */ +void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + obj->x_set = x; + obj->y_set = y; + + /*If the object is on a grid item let grid to position it. */ + if(_GRID_IS_CELL(obj->x_set) && _GRID_IS_CELL(obj->x_set)) { + lv_grid_refresh_item_pos(obj); + } else { + refr_pos(obj, x, y); + } +} + +/** + * Set the x coordinate of a object + * @param obj pointer to an object + * @param x new distance from the left side from the parent + */ +void lv_obj_set_x(lv_obj_t * obj, lv_coord_t x) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_obj_set_pos(obj, x, lv_obj_get_y(obj)); +} + +/** + * Set the y coordinate of a object + * @param obj pointer to an object + * @param y new distance from the top of the parent + */ +void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_obj_set_pos(obj, lv_obj_get_x(obj), y); } /** @@ -864,7 +927,52 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) obj->w_set = w; obj->h_set = h; - refr_size(obj); + /*If the object is a grid element and stretched, prevent settings its size */ + bool x_stretch = false; + bool y_stretch = false; + x_stretch = _GRID_GET_CELL_FLAG(obj->x_set) == LV_GRID_STRETCH ? true : false; + y_stretch = _GRID_GET_CELL_FLAG(obj->y_set) == LV_GRID_STRETCH ? true : false; + + if(x_stretch && y_stretch) return; + + lv_coord_t grid_w = 0; + lv_coord_t grid_h = 0; + if(((LV_COORD_IS_AUTO(obj->w_set) && !x_stretch) || + (LV_COORD_IS_AUTO(obj->h_set) && !y_stretch))) { + _lv_grid_calc_t calc; + grid_calc(obj->grid, &calc); + grid_w = calc.col_dsc[calc.col_dsc_len - 1]; + grid_h = calc.row_dsc[calc.row_dsc_len - 1]; + grid_calc_free(&calc); + } + + + if(x_stretch) w = lv_obj_get_width(obj); + else { + if(LV_COORD_IS_AUTO(obj->w_set)) { + lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF); + lv_coord_t scroll_right = lv_obj_get_scroll_right(obj); + w = lv_obj_get_width(obj) + scroll_right; + w = LV_MATH_MAX(w, grid_w); + } + } + + if(y_stretch) h = lv_obj_get_height(obj); + else { + if(LV_COORD_IS_AUTO(obj->h_set) && !x_stretch) { + lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); + lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj); + h = lv_obj_get_height(obj) + scroll_bottom; + h = LV_MATH_MAX(h, grid_h); + } + } + + bool chg = refr_size(obj, w, h); + + /*Refresh the position in the grid item if required*/ + if(chg && (_GRID_IS_CELL(obj->x_set) || _GRID_IS_CELL(obj->y_set))) { + lv_grid_refresh_item_pos(obj); + } } /** diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index e0188a0b5..9c0ee22fc 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -18,6 +18,7 @@ extern "C" { #include #include #include "lv_style.h" +#include "lv_align.h" #include "../lv_misc/lv_types.h" #include "../lv_misc/lv_area.h" #include "../lv_misc/lv_color.h" @@ -243,6 +244,8 @@ typedef struct _lv_obj_t { lv_obj_user_data_t user_data; /**< Custom user data for object. */ #endif + lv_grid_t * grid; + } lv_obj_t; enum { diff --git a/src/lv_misc/lv_area.h b/src/lv_misc/lv_area.h index 6bbb3afb2..86ee4a186 100644 --- a/src/lv_misc/lv_area.h +++ b/src/lv_misc/lv_area.h @@ -22,8 +22,9 @@ extern "C" { /********************* * DEFINES *********************/ -/*To avoid overflow don't let the max ranges (reduce with 1000) */ -#define LV_COORD_MAX ((lv_coord_t)((uint32_t)((uint32_t)1 << (8 * sizeof(lv_coord_t) - 1)) - 1000)) +#define _LV_COORD_MAX_REDUCE 8192 +/*To allow some special values in the end reduce the max value */ +#define LV_COORD_MAX ((lv_coord_t)((uint32_t)((uint32_t)1 << (8 * sizeof(lv_coord_t) - 1)) - _LV_COORD_MAX_REDUCE)) #define LV_COORD_MIN (-LV_COORD_MAX) LV_EXPORT_CONST_INT(LV_COORD_MAX); @@ -209,10 +210,10 @@ void _lv_area_align(const lv_area_t * base, const lv_area_t * to_align, lv_align **********************/ #define LV_COORD_PX(x) (x) -#define LV_COORD_AUTO (LV_COORD_MAX - 100) +#define LV_COORD_AUTO (LV_COORD_MAX - 1) -#define LV_COORD_IS_PX(x) (((x) < LV_COORD_MAX - 1000) ? true : false) -#define LV_COORD_IS_AUTO(x) (((x) == LV_COORD_MAX - 100) ? true : false) +#define LV_COORD_IS_PX(x) (((x) < LV_COORD_MAX) ? true : false) +#define LV_COORD_IS_AUTO(x) (((x) == LV_COORD_AUTO) ? true : false) #ifdef __cplusplus From 03fa6b492c4c8aa9ef336bdfeffbd151fc7bd2d8 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 30 Aug 2020 20:05:50 +0200 Subject: [PATCH 19/84] grid fuly works --- src/lv_api_map.h | 6 +- src/lv_core/lv_align.c | 215 +++++++++++++++++++++---- src/lv_core/lv_align.h | 17 +- src/lv_core/lv_obj.c | 353 ++++++++++++++++++++++++++++++----------- src/lv_core/lv_obj.h | 3 + src/lv_misc/lv_area.h | 7 +- 6 files changed, 466 insertions(+), 135 deletions(-) diff --git a/src/lv_api_map.h b/src/lv_api_map.h index 6006216cb..23f7b8894 100644 --- a/src/lv_api_map.h +++ b/src/lv_api_map.h @@ -212,17 +212,17 @@ static inline void lv_chart_clear_serie(lv_obj_t * chart, lv_chart_series_t * se static inline void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) { - lv_obj_align_mid(obj, base, align, x_ofs, y_ofs); +// lv_obj_align_mid(obj, base, align, x_ofs, y_ofs); } static inline void lv_obj_align_origo_x(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs) { - lv_obj_align_mid_y(obj, base, align, x_ofs); +// lv_obj_align_mid_y(obj, base, align, x_ofs); } static inline void lv_obj_align_origo_y(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t y_ofs) { - lv_obj_align_mid_y(obj, base, align, y_ofs); +// lv_obj_align_mid_y(obj, base, align, y_ofs); } #endif /*LV_USE_API_EXTENSION_V6*/ diff --git a/src/lv_core/lv_align.c b/src/lv_core/lv_align.c index a9ed4cf83..2a7d35ca7 100644 --- a/src/lv_core/lv_align.c +++ b/src/lv_core/lv_align.c @@ -7,6 +7,7 @@ * INCLUDES *********************/ #include "lv_align.h" +#include "lv_obj.h" /********************* * DEFINES @@ -19,6 +20,12 @@ /********************** * STATIC PROTOTYPES **********************/ +static void calc_explicit(lv_obj_t * obj, _lv_grid_calc_t * calc); +static void calc_flow_row(lv_obj_t * obj, _lv_grid_calc_t * calc); + +static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc); +static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc); +static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc); /********************** * STATIC VARIABLES @@ -32,23 +39,17 @@ * GLOBAL FUNCTIONS **********************/ -void grid_calc(lv_grid_t * grid, _lv_grid_calc_t * calc) +void grid_calc(struct _lv_obj_t * obj, _lv_grid_calc_t * calc) { - calc->col_dsc_len = grid->col_dsc_len + 1; - calc->col_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->col_dsc_len); - calc->row_dsc_len = grid->row_dsc_len + 1; - calc->row_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->row_dsc_len); + static uint32_t cnt = 0; + cnt++; + if(obj->grid == NULL) return; - calc->col_dsc[0] = 0; - calc->row_dsc[0] = 0; + printf("calc: %d (size: %d)\n", cnt, obj->grid->col_dsc_len); + + if(obj->grid->col_dsc && obj->grid->row_dsc) calc_explicit(obj, calc); + else if(obj->grid->col_dsc && !obj->grid->row_dsc) calc_flow_row(obj, calc); - uint8_t i; - for(i = 0; i < grid->col_dsc_len; i++) { - calc->col_dsc[i + 1] = calc->col_dsc[i] + grid->col_dsc[i]; - } - for(i = 0; i < grid->row_dsc_len; i++) { - calc->row_dsc[i + 1] = calc->row_dsc[i] + grid->row_dsc[i]; - } } void grid_calc_free(_lv_grid_calc_t * calc) @@ -57,30 +58,182 @@ void grid_calc_free(_lv_grid_calc_t * calc) _lv_mem_buf_release(calc->row_dsc); } -uint8_t _lv_grid_get_col_type(lv_grid_t * grid, uint32_t col) -{ - lv_coord_t x; - /*If explicitly defined get the column size else use the first column*/ - if(col < grid->col_dsc_len) x = grid->col_dsc[col]; - else x = grid->col_dsc[0]; - if(_GRID_IS_FR(x)) return _GRID_CELL_SIZE_FR; - else if(_GRID_IS_AUTO(x)) return _GRID_CELL_SIZE_AUTO; - else return _GRID_CELL_SIZE_PX; +bool _lv_grid_has_fr_col(struct _lv_obj_t * obj) +{ + if(obj->grid == NULL) return false; + if(obj->grid->col_dsc == NULL) return false; + + uint32_t i; + for(i = 0; i < obj->grid->col_dsc_len; i++) { + if(_GRID_IS_FR(obj->grid->col_dsc[i])) return true; + } + + return false; } -uint8_t _lv_grid_get_row_type(lv_grid_t * grid, uint32_t row) +bool _lv_grid_has_fr_row(struct _lv_obj_t * obj) { - lv_coord_t x; - /*If explicitly defined get the row size else use the first row*/ - if(row < grid->row_dsc_len) x = grid->row_dsc[row]; - else x = grid->row_dsc[0]; + if(obj->grid == NULL) return false; + if(obj->grid->row_dsc == NULL) return false; - if(_GRID_IS_FR(x)) return _GRID_CELL_SIZE_FR; - else if(_GRID_IS_AUTO(x)) return _GRID_CELL_SIZE_AUTO; - else return _GRID_CELL_SIZE_PX; + uint32_t i; + for(i = 0; i < obj->grid->row_dsc_len; i++) { + if(_GRID_IS_FR(obj->grid->row_dsc[i])) return true; + } + + return false; } /********************** * STATIC FUNCTIONS **********************/ + +static void calc_explicit(lv_obj_t * obj, _lv_grid_calc_t * calc) +{ + calc_explicit_rows(obj, calc); + calc_explicit_cols(obj, calc); + +} + + +static void calc_flow_row(lv_obj_t * obj, _lv_grid_calc_t * calc) +{ + calc_explicit_cols(obj, calc); + calc_implicit_rows(obj, calc); +} + + +static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc) +{ + lv_grid_t * grid = cont->grid; + uint32_t i; + + lv_coord_t * cols_w = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->col_dsc_len); + uint32_t col_fr_cnt = 0; + lv_coord_t grid_w = 0; + bool auto_w = cont->w_set == LV_SIZE_AUTO ? true : false; + + for(i = 0; i < grid->col_dsc_len; i++) { + lv_coord_t x = grid->col_dsc[i]; + if(_GRID_IS_FR(x)) col_fr_cnt += _GRID_GET_FR(x); + else { + cols_w[i] = x; + grid_w += x; + } + } + + lv_coord_t free_w = lv_obj_get_width_fit(cont) - grid_w; + + + for(i = 0; i < grid->col_dsc_len; i++) { + lv_coord_t x = grid->col_dsc[i]; + if(_GRID_IS_FR(x)) { + if(auto_w) cols_w[i] = 0; /*Fr is considered zero if the cont has auto width*/ + else { + lv_coord_t f = _GRID_GET_FR(x); + cols_w[i] = (free_w * f) / col_fr_cnt; + } + } + } + + calc->col_dsc_len = grid->col_dsc_len + 1; + calc->col_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->col_dsc_len); + + calc->col_dsc[0] = 0; + for(i = 0; i < grid->col_dsc_len; i++) { + calc->col_dsc[i + 1] = calc->col_dsc[i] + cols_w[i]; + } + _lv_mem_buf_release(cols_w); +} + +static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc) +{ + lv_grid_t * grid = cont->grid; + uint32_t i; + calc_explicit_cols(cont, calc); + + lv_coord_t * rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->row_dsc_len); + uint32_t row_fr_cnt = 0; + lv_coord_t grid_h = 0; + + bool auto_h = cont->h_set == LV_SIZE_AUTO ? true : false; + + + for(i = 0; i < grid->row_dsc_len; i++) { + lv_coord_t x = grid->row_dsc[i]; + if(_GRID_IS_FR(x)) row_fr_cnt += _GRID_GET_FR(x); + else { + rows_h[i] = x; + grid_h += x; + } + } + + lv_coord_t free_h = lv_obj_get_height_fit(cont) - grid_h; + + for(i = 0; i < grid->row_dsc_len; i++) { + lv_coord_t x = grid->row_dsc[i]; + if(_GRID_IS_FR(x)) { + if(auto_h) rows_h[i] = 0; /*Fr is considered zero if the obj has auto height*/ + else { + lv_coord_t f = _GRID_GET_FR(x); + rows_h[i] = (free_h * f) / row_fr_cnt; + } + } + } + + calc->row_dsc_len = grid->row_dsc_len + 1; + calc->row_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->row_dsc_len); + + calc->row_dsc[0] = 0; + + + for(i = 0; i < grid->row_dsc_len; i++) { + calc->row_dsc[i + 1] = calc->row_dsc[i] + rows_h[i]; + } + + _lv_mem_buf_release(rows_h); +} + + +static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc) +{ + + lv_grid_t * grid = cont->grid; + + uint32_t child_cnt = lv_obj_count_children(cont); + + uint32_t row_cnt = (child_cnt / grid->col_dsc_len) + 1; + /*At worst case all children is gird item prepare place for all of them*/ + lv_coord_t * rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * row_cnt); + _lv_memset_00(rows_h, sizeof(lv_coord_t) * row_cnt); + + uint32_t i; + + lv_obj_t * child = lv_obj_get_child_back(cont, NULL); + uint32_t col_i = 0; + uint32_t row_i = 0; + while(child) { + if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) { + rows_h[row_i] = LV_MATH_MAX(rows_h[row_i], lv_obj_get_height(child)); + col_i++; + if(col_i == grid->col_dsc_len) { + col_i = 0; + row_i++; + } + } + child = lv_obj_get_child_back(cont, child); + } + + + calc->row_dsc_len = row_cnt + 1; + calc->row_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->row_dsc_len); + + calc->row_dsc[0] = 0; + + for(i = 0; i < row_cnt; i++) { + calc->row_dsc[i + 1] = calc->row_dsc[i] + rows_h[i]; + } + + _lv_mem_buf_release(rows_h); +} diff --git a/src/lv_core/lv_align.h b/src/lv_core/lv_align.h index c32e422a6..ceb91b597 100644 --- a/src/lv_core/lv_align.h +++ b/src/lv_core/lv_align.h @@ -44,14 +44,13 @@ extern "C" { #define _GRID_CELL_SIZE_PX 0 /* The cell size is set in pixels*/ #define _GRID_CELL_SIZE_FR 1 /* The cell size is set in free units*/ -#define _GRID_CELL_SIZE_AUTO 2 /* The cell size is automatically set to content*/ #define LV_GRID_FR(x) (LV_COORD_MAX + (x)) -#define LV_GRID_AUTO LV_COORD_AUTO #define _GRID_IS_PX(x) ((_GRID_IS_FR(x) == false) && (_GRID_IS_AUTO(x) == false) ? true : false) #define _GRID_IS_FR(x) (x > LV_COORD_MAX ? true : false) #define _GRID_IS_AUTO(x) (x == LV_GRID_AUTO ? true : false) +#define _GRID_GET_FR(x) ((x) - LV_COORD_MAX) /** @@ -62,7 +61,6 @@ extern "C" { #define LV_GRID_CELL_END(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_END)) #define LV_GRID_CELL_CENTER(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_CENTER)) #define LV_GRID_CELL_STRETCH(pos, span) ((LV_COORD_MAX + (pos) + (span << _GRID_CELL_SHIFT)) | _GRID_CELL_FLAG(LV_GRID_STRETCH)) - /** * Special LV_GRID_CELL position to flow the object automatically. * Both X (column) and Y (row) value needs to be AUTO or explicitly specified*/ @@ -75,6 +73,9 @@ extern "C" { * TYPEDEFS **********************/ +/* Can't include lv_obj.h because it includes this header file */ +struct _lv_obj_t; + /** * Describe how to flow LV_GRID_POS_AUTO elements */ @@ -97,8 +98,8 @@ typedef struct { typedef struct { lv_coord_t * col_dsc; lv_coord_t * row_dsc; - uint8_t col_dsc_len; - uint8_t row_dsc_len; + uint32_t col_dsc_len; + uint32_t row_dsc_len; }_lv_grid_calc_t; /********************** @@ -111,13 +112,13 @@ void lv_grid_set_template(lv_grid_t * grid, const lv_coord_t * col_dsc, const lv void lv_grid_set_place_content(lv_grid_t * grid, uint8_t col_place, uint8_t row_place); -void grid_calc(lv_grid_t * grid, _lv_grid_calc_t * calc); +void grid_calc(struct _lv_obj_t * obj, _lv_grid_calc_t * calc); void grid_calc_free(_lv_grid_calc_t * calc); -uint8_t _lv_grid_get_col_type(lv_grid_t * grid, uint32_t row); +bool _lv_grid_has_fr_col(struct _lv_obj_t * obj); -uint8_t _lv_grid_get_row_type(lv_grid_t * grid, uint32_t col); +bool _lv_grid_has_fr_row(struct _lv_obj_t * obj); /********************** * MACROS diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 7f19e3865..7f450224b 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -295,6 +295,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->coords.x1 = parent->coords.x1; new_obj->coords.x2 = parent->coords.x1 + LV_OBJ_DEF_WIDTH; } + new_obj->w_set = lv_area_get_width(&new_obj->coords); + new_obj->h_set = lv_area_get_height(&new_obj->coords); } @@ -390,6 +392,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) } } + lv_obj_set_pos(new_obj, 0, 0); + /*Send a signal to the parent to notify it about the new child*/ if(parent != NULL) { parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, new_obj); @@ -641,7 +645,7 @@ void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) } /*Notify the original parent because one of its children is lost*/ - old_par->signal_cb(old_par, LV_SIGNAL_CHILD_CHG, NULL); + old_par->signal_cb(old_par, LV_SIGNAL_CHILD_CHG, obj); /*Notify the new parent about the child*/ parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, obj); @@ -699,17 +703,17 @@ void lv_obj_move_background(lv_obj_t * obj) * Coordinate set * ------------------*/ -static void refr_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +static void move_obj_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, bool notify_parent) { /*Convert x and y to absolute coordinates*/ - lv_obj_t * par = obj->parent; + lv_obj_t * parent = obj->parent; - if(par) { - lv_coord_t pad_left = lv_obj_get_style_pad_left(par, LV_OBJ_PART_MAIN); - lv_coord_t pad_top = lv_obj_get_style_pad_top(par, LV_OBJ_PART_MAIN); + if(parent) { + lv_coord_t pad_left = lv_obj_get_style_pad_left(parent, LV_OBJ_PART_MAIN); + lv_coord_t pad_top = lv_obj_get_style_pad_top(parent, LV_OBJ_PART_MAIN); - x += pad_left + par->coords.x1 - lv_obj_get_scroll_left(par); - y += pad_top + par->coords.y1 - lv_obj_get_scroll_top(par); + x += pad_left + parent->coords.x1 - lv_obj_get_scroll_left(parent); + y += pad_top + parent->coords.y1 - lv_obj_get_scroll_top(parent); } else { /*If no parent then it's screen but screen can't be on a grid*/ if(_GRID_IS_CELL(obj->x_set) || _GRID_IS_CELL(obj->x_set)) { @@ -748,7 +752,7 @@ static void refr_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) obj->signal_cb(obj, LV_SIGNAL_COORD_CHG, &ori); /*Send a signal to the parent too*/ - if(par) par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); + if(parent && notify_parent) parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, obj); /*Invalidate the new area*/ lv_obj_invalidate(obj); @@ -757,15 +761,12 @@ static void refr_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) { - /* Do nothing if the size is not changed */ /* It is very important else recursive resizing can * occur without size change*/ if(lv_obj_get_width(obj) == w && lv_obj_get_height(obj) == h) { return false; } - - /*Invalidate the original area*/ lv_obj_invalidate(obj); @@ -797,77 +798,165 @@ static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) /*Invalidate the new area*/ lv_obj_invalidate(obj); - return true; } +bool lv_obj_is_grid_item(lv_obj_t * obj); +static void lv_grid_full_refr(lv_obj_t * cont); - -static void lv_grid_refresh_item_pos(lv_obj_t * obj) +static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc) { - /*Calculate the grid*/ - lv_obj_t * parent = lv_obj_get_parent(obj); - lv_coord_t * col_dsc; - lv_coord_t * row_dsc; - uint8_t col_num; - uint8_t row_num; - _lv_grid_calc_t calc; - grid_calc(parent->grid, &calc); + if(lv_obj_is_grid_item(item) == false) return; - uint8_t col_pos = _GRID_GET_CELL_POS(obj->x_set); - uint8_t col_span = _GRID_GET_CELL_SPAN(obj->x_set); - uint8_t row_pos = _GRID_GET_CELL_POS(obj->y_set); - uint8_t row_span = _GRID_GET_CELL_SPAN(obj->y_set); + uint8_t col_pos; + uint8_t col_span; + uint8_t row_pos; + uint8_t row_span; - lv_coord_t col_w = calc.col_dsc[col_pos + col_span] - calc.col_dsc[col_pos]; - lv_coord_t row_h = calc.row_dsc[row_pos + row_span] - calc.row_dsc[row_pos]; + if(cont->grid->row_dsc && cont->grid->col_dsc) { + col_pos = _GRID_GET_CELL_POS(item->x_set); + col_span = _GRID_GET_CELL_SPAN(item->x_set); + row_pos = _GRID_GET_CELL_POS(item->y_set); + row_span = _GRID_GET_CELL_SPAN(item->y_set); + } else { + col_span = 1; + row_span = 1; - uint8_t x_flag = _GRID_GET_CELL_FLAG(obj->x_set); - uint8_t y_flag = _GRID_GET_CELL_FLAG(obj->y_set); + uint32_t child_id = 0; + lv_obj_t * child = lv_obj_get_child_back(cont, NULL); + + while(child) { + if(child == item) break; + if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) { + child_id++; + } + child = lv_obj_get_child_back(cont, child); + } + + col_pos = child_id % cont->grid->col_dsc_len; + row_pos = child_id / cont->grid->col_dsc_len; + } + + lv_coord_t col_w = calc->col_dsc[col_pos + col_span] - calc->col_dsc[col_pos]; + lv_coord_t row_h = calc->row_dsc[row_pos + row_span] - calc->row_dsc[row_pos]; + + uint8_t x_flag = _GRID_GET_CELL_FLAG(item->x_set); + uint8_t y_flag = _GRID_GET_CELL_FLAG(item->y_set); lv_coord_t x; lv_coord_t y; - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); + lv_coord_t w = lv_obj_get_width(item); + lv_coord_t h = lv_obj_get_height(item); switch(x_flag) { case LV_GRID_START: - x = calc.col_dsc[col_pos]; + x = calc->col_dsc[col_pos]; break; case LV_GRID_STRETCH: - x = calc.col_dsc[col_pos]; + x = calc->col_dsc[col_pos]; w = col_w; + item->w_set = LV_SIZE_STRETCH; break; case LV_GRID_CENTER: - x = calc.col_dsc[col_pos] + (col_w - w) / 2; + x = calc->col_dsc[col_pos] + (col_w - w) / 2; break; case LV_GRID_END: - x = calc.col_dsc[col_pos + 1] - lv_obj_get_width(obj); + x = calc->col_dsc[col_pos + 1] - lv_obj_get_width(item); break; } switch(y_flag) { case LV_GRID_START: - y = calc.row_dsc[row_pos]; + y = calc->row_dsc[row_pos]; break; case LV_GRID_STRETCH: - y = calc.row_dsc[row_pos]; + y = calc->row_dsc[row_pos]; + item->h_set = LV_SIZE_STRETCH; h = row_h; break; case LV_GRID_CENTER: - y = calc.row_dsc[row_pos] + (row_h - h) / 2; + y = calc->row_dsc[row_pos] + (row_h - h) / 2; break; case LV_GRID_END: - y = calc.row_dsc[row_pos + 1] - lv_obj_get_height(obj); + y = calc->row_dsc[row_pos + 1] - lv_obj_get_height(item); break; } - refr_pos(obj, x, y); - refr_size(obj, w, h); + /*Set a new size if required*/ + if(lv_obj_get_width(item) != w || lv_obj_get_height(item) != h) { + lv_area_t old_coords; + lv_area_copy(&old_coords, &item->coords); + lv_obj_invalidate(item); + lv_area_set_width(&item->coords, w); + lv_area_set_height(&item->coords, h); + lv_obj_invalidate(item); + item->signal_cb(item, LV_SIGNAL_COORD_CHG, &old_coords); + + /* If a children is a grid container and has an FR field it also needs to be updated + * because the FR cell size will change with child size change. */ + lv_obj_t * child = lv_obj_get_child(item, NULL); + while(child) { + if(_lv_grid_has_fr_col(child) || _lv_grid_has_fr_row(child)) { + lv_grid_full_refr(child); + } + child = lv_obj_get_child(item, child); + } + } + + move_obj_to(item, x, y, false); +} + +bool lv_obj_is_content_sensitive(lv_obj_t * item) +{ + if(lv_obj_is_grid_item(item) == false) return false; + lv_obj_t * cont = lv_obj_get_parent(item); + + if(cont->grid->col_dsc == NULL && _GRID_GET_CELL_FLAG(item->x_set) == LV_GRID_STRETCH) return true; + if(cont->grid->row_dsc == NULL && _GRID_GET_CELL_FLAG(item->y_set) == LV_GRID_STRETCH) return true; + + return false; +} + +static void lv_grid_full_refr(lv_obj_t * cont) +{ + /*Calculate the grid*/ + if(cont->grid == NULL) return; + _lv_grid_calc_t calc; + grid_calc(cont, &calc); + + lv_obj_t * item = lv_obj_get_child_back(cont, NULL); + while(item) { + _grid_item_repos(cont, item, &calc); + item = lv_obj_get_child_back(cont, item); + } + grid_calc_free(&calc); + + if(cont->w_set == LV_SIZE_AUTO || cont->h_set == LV_SIZE_AUTO) { + lv_obj_set_size(cont, cont->w_set, cont->h_set); + } +} + +static void lv_grid_item_refr_pos(lv_obj_t * item) +{ + /*Calculate the grid*/ + lv_obj_t * cont = lv_obj_get_parent(item); + if(cont->grid == NULL) return; + _lv_grid_calc_t calc; + grid_calc(cont, &calc); + + _grid_item_repos(cont, item, &calc); grid_calc_free(&calc); } +bool lv_obj_is_grid_item(lv_obj_t * obj) +{ + lv_obj_t * cont = lv_obj_get_parent(obj); + if(cont == NULL) return false; + if(cont->grid == NULL) return false; + if(_GRID_IS_CELL(obj->x_set) && _GRID_IS_CELL(obj->y_set)) return true; + return false; +} /** * Set relative the position of an object (relative to the parent) @@ -882,11 +971,34 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) obj->x_set = x; obj->y_set = y; - /*If the object is on a grid item let grid to position it. */ - if(_GRID_IS_CELL(obj->x_set) && _GRID_IS_CELL(obj->x_set)) { - lv_grid_refresh_item_pos(obj); + bool gi = lv_obj_is_grid_item(obj); + + /*For consistency set the size to stretched if the objects is stretched on the grid*/ + if(gi) { + if(_GRID_GET_CELL_FLAG(obj->x_set) == LV_GRID_STRETCH) obj->w_set = LV_SIZE_STRETCH; + if(_GRID_GET_CELL_FLAG(obj->y_set) == LV_GRID_STRETCH) obj->h_set = LV_SIZE_STRETCH; + } + + /*If not grid item but has grid position set the position to 0*/ + if(!gi) { + if(_GRID_IS_CELL(x)) { + obj->x_set = 0; + x = 0; + } + if(_GRID_IS_CELL(y)) { + obj->y_set = 0; + y = 0; + } + } + + /*If the object is on a grid item let the grid to position it. */ + if(gi) { + lv_obj_t * cont = lv_obj_get_parent(obj); + /*If added to a grid with auto flow refresh the whole grid else just this item*/ + if(cont->grid->col_dsc == NULL || cont->grid->row_dsc == NULL) lv_grid_full_refr(cont); + else lv_grid_item_refr_pos(obj); } else { - refr_pos(obj, x, y); + move_obj_to(obj, x, y, true); } } @@ -914,6 +1026,52 @@ void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y) lv_obj_set_pos(obj, lv_obj_get_x(obj), y); } +void _lv_obj_calc_auto_size(lv_obj_t * obj, lv_coord_t * w, lv_coord_t * h) +{ + if(!w && !h) return; + + static uint32_t cnt = 0; + printf("auto_size: %d\n", cnt); + cnt++; + /*If no other effect the auto-size of zero by default*/ + if(w) *w = 0; + if(h) *h = 0; + + /*Get the grid size of the object has a defined grid*/ + lv_coord_t grid_w = 0; + lv_coord_t grid_h = 0; + if(obj->grid) { + _lv_grid_calc_t calc; + grid_calc(obj, &calc); + grid_w = calc.col_dsc[calc.col_dsc_len - 1]; + grid_h = calc.row_dsc[calc.row_dsc_len - 1]; + grid_calc_free(&calc); + } + + /*Get the children's most right and bottom position*/ + lv_coord_t children_w = 0; + lv_coord_t children_h = 0; + if(w) { + lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF); + lv_coord_t scroll_right = lv_obj_get_scroll_right(obj); + children_w = lv_obj_get_width(obj) + scroll_right; + } + + if(h) { + static uint32_t cnt = 0; +// printf("auto_size_scrl: %d\n", cnt); + cnt++; + lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); + lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj); + children_h = lv_obj_get_height(obj) + scroll_bottom; + } + + + /*auto_size = max(gird_size, children_size)*/ + if(w) *w = LV_MATH_MAX(children_w, grid_w); + if(h) *h = LV_MATH_MAX(children_h, grid_h); +} + /** * Set the size of an object * @param obj pointer to an object @@ -924,55 +1082,47 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + bool gi = lv_obj_is_grid_item(obj); + bool x_stretch = false; + bool y_stretch = false; + + if(gi) { + x_stretch = _GRID_GET_CELL_FLAG(obj->x_set) == LV_GRID_STRETCH ? true : false; + y_stretch = _GRID_GET_CELL_FLAG(obj->y_set) == LV_GRID_STRETCH ? true : false; + if(x_stretch) w = LV_SIZE_STRETCH; + if(y_stretch) h = LV_SIZE_STRETCH; + } + obj->w_set = w; obj->h_set = h; - /*If the object is a grid element and stretched, prevent settings its size */ - bool x_stretch = false; - bool y_stretch = false; - x_stretch = _GRID_GET_CELL_FLAG(obj->x_set) == LV_GRID_STRETCH ? true : false; - y_stretch = _GRID_GET_CELL_FLAG(obj->y_set) == LV_GRID_STRETCH ? true : false; - + /*If both streched it was alraedy managed by the grid*/ if(x_stretch && y_stretch) return; - lv_coord_t grid_w = 0; - lv_coord_t grid_h = 0; - if(((LV_COORD_IS_AUTO(obj->w_set) && !x_stretch) || - (LV_COORD_IS_AUTO(obj->h_set) && !y_stretch))) { - _lv_grid_calc_t calc; - grid_calc(obj->grid, &calc); - grid_w = calc.col_dsc[calc.col_dsc_len - 1]; - grid_h = calc.row_dsc[calc.row_dsc_len - 1]; - grid_calc_free(&calc); - } - - if(x_stretch) w = lv_obj_get_width(obj); - else { - if(LV_COORD_IS_AUTO(obj->w_set)) { - lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF); - lv_coord_t scroll_right = lv_obj_get_scroll_right(obj); - w = lv_obj_get_width(obj) + scroll_right; - w = LV_MATH_MAX(w, grid_w); - } - } - if(y_stretch) h = lv_obj_get_height(obj); - else { - if(LV_COORD_IS_AUTO(obj->h_set) && !x_stretch) { - lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); - lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj); - h = lv_obj_get_height(obj) + scroll_bottom; - h = LV_MATH_MAX(h, grid_h); - } + + /*Calculate the required auto sizes*/ + bool x_auto = obj->w_set == LV_SIZE_AUTO ? true : false; + bool y_auto = obj->h_set == LV_SIZE_AUTO ? true : false; + + lv_coord_t auto_w; + lv_coord_t auto_h; + if(x_auto && y_auto) { + _lv_obj_calc_auto_size(obj, &auto_w, &auto_h); + w = auto_w; + h = auto_h; + } + else if(x_auto) { + _lv_obj_calc_auto_size(obj, &auto_w, NULL); + w = auto_w; + } + else if(y_auto) { + _lv_obj_calc_auto_size(obj, NULL, &auto_h); + h = auto_h; } bool chg = refr_size(obj, w, h); - - /*Refresh the position in the grid item if required*/ - if(chg && (_GRID_IS_CELL(obj->x_set) || _GRID_IS_CELL(obj->y_set))) { - lv_grid_refresh_item_pos(obj); - } } /** @@ -1528,7 +1678,7 @@ void lv_obj_refresh_style(lv_obj_t * obj, uint8_t part, lv_style_property_t prop case LV_STYLE_MARGIN_BOTTOM: case LV_STYLE_MARGIN_LEFT: case LV_STYLE_MARGIN_RIGHT: - if(obj->parent) obj->parent->signal_cb(obj->parent, LV_SIGNAL_CHILD_CHG, NULL); + if(obj->parent) obj->parent->signal_cb(obj->parent, LV_SIGNAL_CHILD_CHG, obj); break; } @@ -3909,8 +4059,6 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area } } else if(mode == LV_DESIGN_DRAW_POST) { - - scrollbar_draw(obj, clip_area); if(lv_obj_get_style_clip_corner(obj, LV_OBJ_PART_MAIN)) { @@ -3979,9 +4127,34 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) lv_res_t res = LV_RES_OK; - if(sign == LV_SIGNAL_CHILD_CHG) { + if(sign == LV_SIGNAL_COORD_CHG) { + if((lv_area_get_width(param) != lv_obj_get_width(obj) && _lv_grid_has_fr_col(obj)) || + (lv_area_get_height(param) != lv_obj_get_height(obj) && _lv_grid_has_fr_row(obj))) + { + lv_grid_full_refr(obj); + } + } + else if(sign == LV_SIGNAL_CHILD_CHG) { /*Return 'invalid' if the child change signal is not enabled*/ if(lv_obj_is_protected(obj, LV_PROTECT_CHILD_CHG) != false) res = LV_RES_INV; + + if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) { + lv_obj_set_size(obj, obj->w_set, obj->h_set); + } + + if(obj->grid) { + lv_obj_t * child = param; + if(child) { + if(lv_obj_is_grid_item(child)) lv_grid_full_refr(obj); + } else { + lv_grid_full_refr(obj); + } + } + +// else if(lv_obj_is_content_sensitive(obj)) { +// lv_grid_full_refr(lv_obj_get_parent(obj)); +// } + } else if(sign == LV_SIGNAL_SCROLL) { diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 9c0ee22fc..ffbfbbcff 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -422,6 +422,9 @@ void lv_obj_set_x(lv_obj_t * obj, lv_coord_t x); */ void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y); + +void _lv_obj_calc_auto_size(lv_obj_t * obj, lv_coord_t * w, lv_coord_t * h); + /** * Set the size of an object * @param obj pointer to an object diff --git a/src/lv_misc/lv_area.h b/src/lv_misc/lv_area.h index 86ee4a186..49fd59c1c 100644 --- a/src/lv_misc/lv_area.h +++ b/src/lv_misc/lv_area.h @@ -210,10 +210,11 @@ void _lv_area_align(const lv_area_t * base, const lv_area_t * to_align, lv_align **********************/ #define LV_COORD_PX(x) (x) -#define LV_COORD_AUTO (LV_COORD_MAX - 1) +#define LV_SIZE_AUTO (LV_COORD_MAX - 1) +#define LV_SIZE_STRETCH (LV_COORD_MAX - 2) -#define LV_COORD_IS_PX(x) (((x) < LV_COORD_MAX) ? true : false) -#define LV_COORD_IS_AUTO(x) (((x) == LV_COORD_AUTO) ? true : false) +#define LV_COORD_IS_PX(x) (((x) < LV_COORD_MAX - 2) ? true : false) +#define LV_COORD_IS_AUTO(x) (((x) == LV_SIZE_AUTO) ? true : false) #ifdef __cplusplus From 67d268b3ee114817fb5d6902dc3c52ff01540ace Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 31 Aug 2020 09:33:44 +0200 Subject: [PATCH 20/84] gird optimization --- src/lv_core/lv_core.mk | 1 + src/lv_core/{lv_align.c => lv_grid.c} | 152 ++++++++++++++----- src/lv_core/{lv_align.h => lv_grid.h} | 6 +- src/lv_core/lv_obj.c | 203 ++++++++++++++++++-------- src/lv_core/lv_obj.h | 2 +- src/lv_core/lv_refr.c | 2 +- src/lv_core/lv_style.c | 7 + src/lv_core/lv_style.h | 3 +- src/lv_misc/lv_anim.c | 4 +- src/lv_misc/lv_ll.c | 35 ----- src/lv_misc/lv_ll.h | 10 +- src/lv_misc/lv_mem.c | 51 +++---- 12 files changed, 308 insertions(+), 168 deletions(-) rename src/lv_core/{lv_align.c => lv_grid.c} (54%) rename src/lv_core/{lv_align.h => lv_grid.h} (98%) diff --git a/src/lv_core/lv_core.mk b/src/lv_core/lv_core.mk index b46c01625..9f15199bd 100644 --- a/src/lv_core/lv_core.mk +++ b/src/lv_core/lv_core.mk @@ -1,3 +1,4 @@ +CSRCS += lv_grid.c CSRCS += lv_group.c CSRCS += lv_indev.c CSRCS += lv_disp.c diff --git a/src/lv_core/lv_align.c b/src/lv_core/lv_grid.c similarity index 54% rename from src/lv_core/lv_align.c rename to src/lv_core/lv_grid.c index 2a7d35ca7..6d4b3665b 100644 --- a/src/lv_core/lv_align.c +++ b/src/lv_core/lv_grid.c @@ -6,12 +6,13 @@ /********************* * INCLUDES *********************/ -#include "lv_align.h" +#include "lv_grid.h" #include "lv_obj.h" /********************* * DEFINES *********************/ +#define CALC_DSC_BUF_SIZE 8 /********************** * TYPEDEFS @@ -20,16 +21,18 @@ /********************** * STATIC PROTOTYPES **********************/ -static void calc_explicit(lv_obj_t * obj, _lv_grid_calc_t * calc); -static void calc_flow_row(lv_obj_t * obj, _lv_grid_calc_t * calc); - static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc); static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc); +static void calc_implicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc); static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc); /********************** * STATIC VARIABLES **********************/ +static lv_coord_t col_dsc_calc_buf[CALC_DSC_BUF_SIZE]; +static lv_coord_t row_dsc_calc_buf[CALC_DSC_BUF_SIZE]; +static bool col_dsc_buf_used; +static bool row_dsc_buf_used; /********************** * MACROS @@ -41,14 +44,24 @@ static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc); void grid_calc(struct _lv_obj_t * obj, _lv_grid_calc_t * calc) { - static uint32_t cnt = 0; - cnt++; if(obj->grid == NULL) return; - printf("calc: %d (size: %d)\n", cnt, obj->grid->col_dsc_len); +// static uint32_t cnt = 0; +// cnt++; +// printf("calc: %d (size: %d)\n", cnt, obj->grid->col_dsc_len); - if(obj->grid->col_dsc && obj->grid->row_dsc) calc_explicit(obj, calc); - else if(obj->grid->col_dsc && !obj->grid->row_dsc) calc_flow_row(obj, calc); + if(obj->grid->col_dsc && obj->grid->row_dsc) { + calc_explicit_rows(obj, calc); + calc_explicit_cols(obj, calc); + } + else if(obj->grid->col_dsc && !obj->grid->row_dsc) { + calc_explicit_cols(obj, calc); + calc_implicit_rows(obj, calc); + } + else if(!obj->grid->col_dsc && obj->grid->row_dsc) { + calc_implicit_cols(obj, calc); + calc_explicit_rows(obj, calc); + } } @@ -89,27 +102,19 @@ bool _lv_grid_has_fr_row(struct _lv_obj_t * obj) * STATIC FUNCTIONS **********************/ -static void calc_explicit(lv_obj_t * obj, _lv_grid_calc_t * calc) -{ - calc_explicit_rows(obj, calc); - calc_explicit_cols(obj, calc); - -} - - -static void calc_flow_row(lv_obj_t * obj, _lv_grid_calc_t * calc) -{ - calc_explicit_cols(obj, calc); - calc_implicit_rows(obj, calc); -} - - static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc) { lv_grid_t * grid = cont->grid; uint32_t i; - lv_coord_t * cols_w = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->col_dsc_len); + lv_coord_t * cols_w; + if(!col_dsc_buf_used && grid->col_dsc_len <= CALC_DSC_BUF_SIZE) { + cols_w = col_dsc_calc_buf; + col_dsc_buf_used = true; + } else { + cols_w = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->col_dsc_len); + } + uint32_t col_fr_cnt = 0; lv_coord_t grid_w = 0; bool auto_w = cont->w_set == LV_SIZE_AUTO ? true : false; @@ -144,16 +149,24 @@ static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc) for(i = 0; i < grid->col_dsc_len; i++) { calc->col_dsc[i + 1] = calc->col_dsc[i] + cols_w[i]; } - _lv_mem_buf_release(cols_w); + + if(col_dsc_buf_used) col_dsc_buf_used = false ; + else _lv_mem_buf_release(cols_w); } static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc) { lv_grid_t * grid = cont->grid; uint32_t i; - calc_explicit_cols(cont, calc); - lv_coord_t * rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->row_dsc_len); + lv_coord_t * rows_h; + if(!row_dsc_buf_used && grid->row_dsc_len <= CALC_DSC_BUF_SIZE) { + rows_h = row_dsc_calc_buf; + row_dsc_buf_used = true; + } else { + rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->row_dsc_len); + } + uint32_t row_fr_cnt = 0; lv_coord_t grid_h = 0; @@ -192,7 +205,65 @@ static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc) calc->row_dsc[i + 1] = calc->row_dsc[i] + rows_h[i]; } - _lv_mem_buf_release(rows_h); + if(row_dsc_buf_used) row_dsc_buf_used = false; + else _lv_mem_buf_release(rows_h); +} + + +static void calc_implicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc) +{ + lv_grid_t * grid = cont->grid; + + uint32_t child_cnt = lv_obj_count_children(cont); + + uint32_t col_cnt = (child_cnt / grid->row_dsc_len) + 1; + /* If `col_dsc_buf_used`, nested a call of this func. will release `col_dsc_buf_used` because it think it taken it. + * So mark that if the buffer was taken in this call*/ + bool col_dsc_buf_mine = false; + /*At worst case all children is gird item prepare place for all of them*/ + lv_coord_t * cols_w; + if(!col_dsc_buf_used && col_cnt <= CALC_DSC_BUF_SIZE) { + cols_w = col_dsc_calc_buf; + col_dsc_buf_used = true; + col_dsc_buf_mine = true; + } else { + cols_w = _lv_mem_buf_get(sizeof(lv_coord_t) * col_cnt); + } + + uint32_t i; + + lv_obj_t * child = lv_obj_get_child_back(cont, NULL); + uint32_t row_i = 0; + uint32_t col_i = 0; + cols_w[0] = 0; + while(child) { + if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) { + lv_coord_t w; + if(_GRID_GET_CELL_FLAG(child->x_set) == LV_GRID_STRETCH) _lv_obj_calc_auto_size(child, &w, NULL); + else w = lv_obj_get_width(child); + cols_w[col_i] = LV_MATH_MAX(cols_w[col_i], w); + row_i++; + if(row_i == grid->row_dsc_len) { + row_i = 0; + col_i++; + cols_w[col_i] = 0; + } + } + child = lv_obj_get_child_back(cont, child); + } + + + calc->col_dsc_len = col_cnt + 1; + calc->col_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->col_dsc_len); + + calc->col_dsc[0] = 0; + + for(i = 0; i < col_cnt; i++) { + calc->col_dsc[i + 1] = calc->col_dsc[i] + cols_w[i]; + } + + if(col_dsc_buf_used && col_dsc_buf_mine) col_dsc_buf_used = false; + else _lv_mem_buf_release(cols_w); } @@ -200,26 +271,36 @@ static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc) { lv_grid_t * grid = cont->grid; - uint32_t child_cnt = lv_obj_count_children(cont); - uint32_t row_cnt = (child_cnt / grid->col_dsc_len) + 1; + bool row_dsc_buf_mine = false; /*At worst case all children is gird item prepare place for all of them*/ - lv_coord_t * rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * row_cnt); - _lv_memset_00(rows_h, sizeof(lv_coord_t) * row_cnt); + lv_coord_t * rows_h; + if(!row_dsc_buf_used && row_cnt <= CALC_DSC_BUF_SIZE) { + rows_h = row_dsc_calc_buf; + row_dsc_buf_used = true; + row_dsc_buf_mine = true; + } else { + rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * row_cnt); + } uint32_t i; lv_obj_t * child = lv_obj_get_child_back(cont, NULL); uint32_t col_i = 0; uint32_t row_i = 0; + rows_h[0] = 0; while(child) { if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) { - rows_h[row_i] = LV_MATH_MAX(rows_h[row_i], lv_obj_get_height(child)); + lv_coord_t h; + if(_GRID_GET_CELL_FLAG(child->y_set) == LV_GRID_STRETCH) _lv_obj_calc_auto_size(child, NULL, &h); + else h = lv_obj_get_height(child); + rows_h[row_i] = LV_MATH_MAX(rows_h[row_i], h); col_i++; if(col_i == grid->col_dsc_len) { col_i = 0; row_i++; + rows_h[row_i] = 0; } } child = lv_obj_get_child_back(cont, child); @@ -235,5 +316,6 @@ static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc) calc->row_dsc[i + 1] = calc->row_dsc[i] + rows_h[i]; } - _lv_mem_buf_release(rows_h); + if(row_dsc_buf_used && row_dsc_buf_mine) row_dsc_buf_used = false; + else _lv_mem_buf_release(rows_h); } diff --git a/src/lv_core/lv_align.h b/src/lv_core/lv_grid.h similarity index 98% rename from src/lv_core/lv_align.h rename to src/lv_core/lv_grid.h index ceb91b597..b64576072 100644 --- a/src/lv_core/lv_align.h +++ b/src/lv_core/lv_grid.h @@ -3,8 +3,8 @@ * */ -#ifndef LV_ALIGN_H -#define LV_ALIGN_H +#ifndef LV_GRID_H +#define LV_GRID_H #ifdef __cplusplus extern "C" { @@ -128,4 +128,4 @@ bool _lv_grid_has_fr_row(struct _lv_obj_t * obj); } /* extern "C" */ #endif -#endif /*LV_ALIGN_H*/ +#endif /*LV_GRID_H*/ diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 7f450224b..193d977dd 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -49,6 +49,10 @@ #define LV_OBJ_DEF_WIDTH (LV_DPX(100)) #define LV_OBJ_DEF_HEIGHT (LV_DPX(50)) #define SCROLLBAR_MIN_SIZE (LV_DPX(10)) +#define SCROLL_ANIM_TIME_MIN 100 /*ms*/ +#define SCROLL_ANIM_TIME_MAX 300 /*ms*/ + +#define GRID_DEBUG 1 /*Draw rectangles on grid cells*/ /********************** * TYPEDEFS @@ -804,14 +808,14 @@ static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) bool lv_obj_is_grid_item(lv_obj_t * obj); static void lv_grid_full_refr(lv_obj_t * cont); -static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc) +static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc, uint32_t * child_id_ext, lv_point_t * grid_abs) { if(lv_obj_is_grid_item(item) == false) return; - uint8_t col_pos; - uint8_t col_span; - uint8_t row_pos; - uint8_t row_span; + uint32_t col_pos; + uint32_t col_span; + uint32_t row_pos; + uint32_t row_span; if(cont->grid->row_dsc && cont->grid->col_dsc) { col_pos = _GRID_GET_CELL_POS(item->x_set); @@ -823,18 +827,26 @@ static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * row_span = 1; uint32_t child_id = 0; - lv_obj_t * child = lv_obj_get_child_back(cont, NULL); + if(child_id_ext) child_id = *child_id_ext; + else { + lv_obj_t * child = lv_obj_get_child_back(cont, NULL); - while(child) { - if(child == item) break; - if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) { - child_id++; + while(child) { + if(child == item) break; + if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) { + child_id++; + } + child = lv_obj_get_child_back(cont, child); } - child = lv_obj_get_child_back(cont, child); } - col_pos = child_id % cont->grid->col_dsc_len; - row_pos = child_id / cont->grid->col_dsc_len; + if(cont->grid->row_dsc == NULL) { + col_pos = child_id % cont->grid->col_dsc_len; + row_pos = child_id / cont->grid->col_dsc_len; + } else { + col_pos = child_id / cont->grid->row_dsc_len; + row_pos = child_id % cont->grid->row_dsc_len; + } } lv_coord_t col_w = calc->col_dsc[col_pos + col_span] - calc->col_dsc[col_pos]; @@ -902,19 +914,12 @@ static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * child = lv_obj_get_child(item, child); } } + bool moved = true; + if(grid_abs) { + if(grid_abs->x + x == item->coords.x1 && grid_abs->y + y == item->coords.y1) moved = false; + } - move_obj_to(item, x, y, false); -} - -bool lv_obj_is_content_sensitive(lv_obj_t * item) -{ - if(lv_obj_is_grid_item(item) == false) return false; - lv_obj_t * cont = lv_obj_get_parent(item); - - if(cont->grid->col_dsc == NULL && _GRID_GET_CELL_FLAG(item->x_set) == LV_GRID_STRETCH) return true; - if(cont->grid->row_dsc == NULL && _GRID_GET_CELL_FLAG(item->y_set) == LV_GRID_STRETCH) return true; - - return false; + if(moved) move_obj_to(item, x, y, false); } static void lv_grid_full_refr(lv_obj_t * cont) @@ -924,9 +929,21 @@ static void lv_grid_full_refr(lv_obj_t * cont) _lv_grid_calc_t calc; grid_calc(cont, &calc); + /* Calculate the grids absolute x and y coordinates. + * It will be used as helper during item repositioning to avoid calculating this value for every children*/ + lv_point_t grid_abs; + lv_coord_t pad_left = lv_obj_get_style_pad_left(cont, LV_OBJ_PART_MAIN); + lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_OBJ_PART_MAIN); + grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_left(cont); + grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_top(cont); + + uint32_t child_id = 0; lv_obj_t * item = lv_obj_get_child_back(cont, NULL); while(item) { - _grid_item_repos(cont, item, &calc); + if(_GRID_IS_CELL(item->x_set) && _GRID_IS_CELL(item->y_set)) { + _grid_item_repos(cont, item, &calc, &child_id, &grid_abs); + child_id++; + } item = lv_obj_get_child_back(cont, item); } grid_calc_free(&calc); @@ -944,7 +961,7 @@ static void lv_grid_item_refr_pos(lv_obj_t * item) _lv_grid_calc_t calc; grid_calc(cont, &calc); - _grid_item_repos(cont, item, &calc); + _grid_item_repos(cont, item, &calc, NULL, NULL); grid_calc_free(&calc); } @@ -993,10 +1010,18 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) /*If the object is on a grid item let the grid to position it. */ if(gi) { + lv_area_t old_area; + lv_area_copy(&old_area, &obj->coords); + lv_grid_item_refr_pos(obj); + lv_obj_t * cont = lv_obj_get_parent(obj); - /*If added to a grid with auto flow refresh the whole grid else just this item*/ - if(cont->grid->col_dsc == NULL || cont->grid->row_dsc == NULL) lv_grid_full_refr(cont); - else lv_grid_item_refr_pos(obj); + + /*If the item was moved and grid is implicit in the changed direction refresh the whole grid.*/ + if((cont->grid->col_dsc == NULL && (old_area.x1 != obj->coords.x1 || old_area.x2 != obj->coords.x2)) || + (cont->grid->row_dsc == NULL && (old_area.y1 != obj->coords.y1 || old_area.y2 != obj->coords.y2))) + { + lv_grid_full_refr(cont); + } } else { move_obj_to(obj, x, y, true); } @@ -1030,9 +1055,10 @@ void _lv_obj_calc_auto_size(lv_obj_t * obj, lv_coord_t * w, lv_coord_t * h) { if(!w && !h) return; - static uint32_t cnt = 0; - printf("auto_size: %d\n", cnt); - cnt++; +// static uint32_t cnt = 0; +// printf("auto_size: %d\n", cnt); +// cnt++; + /*If no other effect the auto-size of zero by default*/ if(w) *w = 0; if(h) *h = 0; @@ -1043,8 +1069,8 @@ void _lv_obj_calc_auto_size(lv_obj_t * obj, lv_coord_t * w, lv_coord_t * h) if(obj->grid) { _lv_grid_calc_t calc; grid_calc(obj, &calc); - grid_w = calc.col_dsc[calc.col_dsc_len - 1]; - grid_h = calc.row_dsc[calc.row_dsc_len - 1]; + grid_w = calc.col_dsc[calc.col_dsc_len - 1] + lv_obj_get_style_pad_top(obj, LV_OBJ_PART_MAIN) + + lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN); + grid_h = calc.row_dsc[calc.row_dsc_len - 1] + lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN) + lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN);; grid_calc_free(&calc); } @@ -1058,9 +1084,6 @@ void _lv_obj_calc_auto_size(lv_obj_t * obj, lv_coord_t * w, lv_coord_t * h) } if(h) { - static uint32_t cnt = 0; -// printf("auto_size_scrl: %d\n", cnt); - cnt++; lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj); children_h = lv_obj_get_height(obj) + scroll_bottom; @@ -1122,7 +1145,7 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) h = auto_h; } - bool chg = refr_size(obj, w, h); + refr_size(obj, w, h); } /** @@ -1261,7 +1284,10 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable 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) * 3) >> 2, 0, x)); + uint32_t t = lv_anim_speed_to_time((lv_disp_get_hor_res(d) * 3) >> 2, 0, x); + if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN; + if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX; + lv_anim_set_time(&a, t); 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); @@ -1269,7 +1295,10 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable } if(y) { - lv_anim_set_time(&a, lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 3) >> 2, 0, y)); + uint32_t t = lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 3) >> 2, 0, y); + if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN; + if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX; + lv_anim_set_time(&a, t); 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); @@ -2332,16 +2361,7 @@ lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, const lv_obj_t * child) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_obj_t * result = NULL; - - if(child == NULL) { - result = _lv_ll_get_head(&obj->child_ll); - } - else { - result = _lv_ll_get_next(&obj->child_ll, child); - } - - return result; + return child ? _lv_ll_get_next(&obj->child_ll, child) : _lv_ll_get_head(&obj->child_ll); } /** @@ -2355,16 +2375,7 @@ lv_obj_t * lv_obj_get_child_back(const lv_obj_t * obj, const lv_obj_t * child) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_obj_t * result = NULL; - - if(child == NULL) { - result = _lv_ll_get_tail(&obj->child_ll); - } - else { - result = _lv_ll_get_prev(&obj->child_ll, child); - } - - return result; + return child ? _lv_ll_get_prev(&obj->child_ll, child) : _lv_ll_get_tail(&obj->child_ll); } /** @@ -2818,6 +2829,12 @@ lv_style_int_t _lv_obj_get_style_int(const lv_obj_t * obj, uint8_t part, lv_styl case LV_STYLE_PAD_RIGHT: if(list->pad_all_zero) def = true; break; + case LV_STYLE_MARGIN_TOP: + case LV_STYLE_MARGIN_BOTTOM: + case LV_STYLE_MARGIN_LEFT: + case LV_STYLE_MARGIN_RIGHT: + if(list->margin_all_zero) def = true; + break; case LV_STYLE_BG_BLEND_MODE: case LV_STYLE_BORDER_BLEND_MODE: case LV_STYLE_IMAGE_BLEND_MODE: @@ -4086,6 +4103,47 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area coords.y2 += h; lv_draw_rect(&coords, clip_area, &draw_dsc); } + +#if GRID_DEBUG + /*Draw the grid cells*/ + if(obj->grid) { + _lv_grid_calc_t calc; + grid_calc(obj, &calc); + + /*Create a color unique to this object. */ + lv_color_t c = lv_color_hex(((lv_uintptr_t) obj) & 0xFFFFFF); + + lv_draw_rect_dsc_t grid_rect_dsc; + lv_draw_rect_dsc_init(&grid_rect_dsc); + grid_rect_dsc.bg_color = c; + grid_rect_dsc.bg_opa = LV_OPA_20; + grid_rect_dsc.border_width = 2; + grid_rect_dsc.border_color = c; + grid_rect_dsc.border_opa = LV_OPA_70; + + lv_point_t grid_abs; + lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN); + lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_OBJ_PART_MAIN); + grid_abs.x = pad_left + obj->coords.x1 - lv_obj_get_scroll_left(obj); + grid_abs.y = pad_top + obj->coords.y1 - lv_obj_get_scroll_top(obj); + + uint32_t row; + uint32_t col; + for(row = 0; row < calc.row_dsc_len - 1; row ++) { + for(col = 0; col < calc.col_dsc_len - 1; col ++) { + lv_area_t a; + a.x1 = grid_abs.x + calc.col_dsc[col]; + a.x2 = grid_abs.x + calc.col_dsc[col + 1]; + a.y1 = grid_abs.y + calc.row_dsc[row]; + a.y2 = grid_abs.y + calc.row_dsc[row + 1]; + lv_draw_rect(&a, clip_area, &grid_rect_dsc); + } + } + + + grid_calc_free(&calc); + } +#endif } return LV_DESIGN_RES_OK; @@ -4194,6 +4252,17 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d); } else if(sign == LV_SIGNAL_STYLE_CHG) { + lv_obj_t * child = lv_obj_get_child(obj, NULL); + while(child) { + lv_obj_set_pos(child, child->x_set, child->y_set); + child = lv_obj_get_child(obj, child); + } + + + if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) { + lv_obj_set_size(obj, obj->w_set, obj->h_set); + } +// if(lv_obj_is_grid_item(obj)) lv_grid_full_refr(lv_obj_get_parent(obj)); lv_obj_refresh_ext_draw_pad(obj); } else if(sign == LV_SIGNAL_PRESSED) { @@ -4956,6 +5025,10 @@ static bool style_prop_is_cacheble(lv_style_property_t prop) case LV_STYLE_PAD_BOTTOM: case LV_STYLE_PAD_LEFT: case LV_STYLE_PAD_RIGHT: + case LV_STYLE_MARGIN_TOP: + case LV_STYLE_MARGIN_BOTTOM: + case LV_STYLE_MARGIN_LEFT: + case LV_STYLE_MARGIN_RIGHT: case LV_STYLE_BG_BLEND_MODE: case LV_STYLE_BORDER_BLEND_MODE: case LV_STYLE_IMAGE_BLEND_MODE: @@ -5035,6 +5108,14 @@ static void update_style_cache(lv_obj_t * obj, uint8_t part, uint16_t prop) list->pad_all_zero = 0; } + list->margin_all_zero = 1; + if(lv_obj_get_style_margin_top(obj, part) != 0 || + lv_obj_get_style_margin_bottom(obj, part) != 0 || + lv_obj_get_style_margin_left(obj, part) != 0 || + lv_obj_get_style_margin_right(obj, part) != 0) { + list->margin_all_zero = 0; + } + list->blend_mode_all_normal = 1; #if LV_USE_BLEND_MODES if(lv_obj_get_style_bg_blend_mode(obj, part) != LV_BLEND_MODE_NORMAL || diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index ffbfbbcff..cbfd9aef3 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -18,7 +18,7 @@ extern "C" { #include #include #include "lv_style.h" -#include "lv_align.h" +#include "lv_grid.h" #include "../lv_misc/lv_types.h" #include "../lv_misc/lv_area.h" #include "../lv_misc/lv_color.h" diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index 0765fba27..cde758fa2 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -678,7 +678,7 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) draw_dsc.bg_color.full = debug_color.full; draw_dsc.bg_opa = LV_OPA_20; draw_dsc.border_width = 2; - draw_dsc.border_opa = LV_OPA_50; + draw_dsc.border_opa = LV_OPA_70; draw_dsc.border_color.full = (debug_color.full + 0x13) * 9; lv_draw_rect(&obj_ext_mask, &obj_ext_mask, &draw_dsc); diff --git a/src/lv_core/lv_style.c b/src/lv_core/lv_style.c index 3a2ad6d80..5fc116932 100644 --- a/src/lv_core/lv_style.c +++ b/src/lv_core/lv_style.c @@ -1044,6 +1044,7 @@ bool lv_debug_check_style_list(const lv_style_list_t * list) * STATIC FUNCTIONS **********************/ +static uint32_t stat[256]; /** * Get a property's index (byte index in `style->map`) from a style. * Return best matching property's index considering the state of `prop` @@ -1067,6 +1068,12 @@ LV_ATTRIBUTE_FAST_MEM static inline int32_t get_property_index(const lv_style_t size_t i = 0; + stat[prop & 0xFF]++; +// +// if((prop & 0xFF) == LV_STYLE_PAD_TOP) { +// printf("pad top\n"); +// } + uint8_t prop_id; while((prop_id = get_style_prop_id(style, i)) != _LV_STYLE_CLOSEING_PROP) { if(prop_id == id_to_find) { diff --git a/src/lv_core/lv_style.h b/src/lv_core/lv_style.h index 420576dc5..c992388c0 100644 --- a/src/lv_core/lv_style.h +++ b/src/lv_core/lv_style.h @@ -231,7 +231,7 @@ typedef struct { #if LV_USE_ASSERT_STYLE uint32_t sentinel; #endif - uint32_t style_cnt : 6; + uint32_t style_cnt : 5; uint32_t has_local : 1; uint32_t has_trans : 1; uint32_t skip_trans : 1; /*1: Temporally skip the transition style if any*/ @@ -244,6 +244,7 @@ typedef struct { uint32_t clip_corner_off : 1; uint32_t transform_all_zero : 1; uint32_t pad_all_zero : 1; + uint32_t margin_all_zero : 1; uint32_t blend_mode_all_normal : 1; uint32_t bg_opa_transp : 1; uint32_t bg_opa_cover : 1; diff --git a/src/lv_misc/lv_anim.c b/src/lv_misc/lv_anim.c index ed3fd7929..3794593d5 100644 --- a/src/lv_misc/lv_anim.c +++ b/src/lv_misc/lv_anim.c @@ -260,7 +260,7 @@ lv_anim_value_t lv_anim_path_ease_in(const lv_anim_path_t * path, const lv_anim_ else t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; - int32_t step = _lv_bezier3(t, 0, 1, 1, 1024); + int32_t step = _lv_bezier3(t, 0, 100, 200, 1024); int32_t new_value; new_value = (int32_t)step * (a->end - a->start); @@ -287,7 +287,7 @@ lv_anim_value_t lv_anim_path_ease_out(const lv_anim_path_t * path, const lv_anim else t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; - int32_t step = _lv_bezier3(t, 0, 1023, 1023, 1024); + int32_t step = _lv_bezier3(t, 0, 800, 900, 1024); int32_t new_value; new_value = (int32_t)step * (a->end - a->start); diff --git a/src/lv_misc/lv_ll.c b/src/lv_misc/lv_ll.c index 9f25b8f7f..4d3e4dabc 100644 --- a/src/lv_misc/lv_ll.c +++ b/src/lv_misc/lv_ll.c @@ -249,37 +249,6 @@ void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool h } } -/** - * Return with head node of the linked list - * @param ll_p pointer to linked list - * @return pointer to the head of 'll_p' - */ -void * _lv_ll_get_head(const lv_ll_t * ll_p) -{ - void * head = NULL; - - if(ll_p != NULL) { - head = ll_p->head; - } - - return head; -} - -/** - * Return with tail node of the linked list - * @param ll_p pointer to linked list - * @return pointer to the head of 'll_p' - */ -void * _lv_ll_get_tail(const lv_ll_t * ll_p) -{ - void * tail = NULL; - - if(ll_p != NULL) { - tail = ll_p->tail; - } - - return tail; -} /** * Return with the pointer of the next node after 'n_act' @@ -289,8 +258,6 @@ void * _lv_ll_get_tail(const lv_ll_t * ll_p) */ void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act) { - if(ll_p == NULL) return NULL; - /* Pointer to the next node is stored in the end of this node. * Go there and return the address found there */ const lv_ll_node_t * n_act_d = n_act; @@ -306,8 +273,6 @@ void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act) */ void * _lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act) { - if(ll_p == NULL) return NULL; - /* Pointer to the prev. node is stored in the end of this node. * Go there and return the address found there */ const lv_ll_node_t * n_act_d = n_act; diff --git a/src/lv_misc/lv_ll.h b/src/lv_misc/lv_ll.h index 906414d16..0fac6a713 100644 --- a/src/lv_misc/lv_ll.h +++ b/src/lv_misc/lv_ll.h @@ -98,14 +98,20 @@ void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool h * @param ll_p pointer to linked list * @return pointer to the head of 'll_p' */ -void * _lv_ll_get_head(const lv_ll_t * ll_p); +static inline void * _lv_ll_get_head(const lv_ll_t * ll_p) +{ + return ll_p->head; +} /** * Return with tail node of the linked list * @param ll_p pointer to linked list * @return pointer to the head of 'll_p' */ -void * _lv_ll_get_tail(const lv_ll_t * ll_p); +static inline void * _lv_ll_get_tail(const lv_ll_t * ll_p) +{ + return ll_p->tail; +} /** * Return with the pointer of the next node after 'n_act' diff --git a/src/lv_misc/lv_mem.c b/src/lv_misc/lv_mem.c index 7fa3146f8..3ef1bd9ae 100644 --- a/src/lv_misc/lv_mem.c +++ b/src/lv_misc/lv_mem.c @@ -73,7 +73,7 @@ typedef struct { **********************/ #if LV_MEM_CUSTOM == 0 static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e); - static void * ent_alloc(lv_mem_ent_t * e, size_t size); + static inline void * ent_alloc(lv_mem_ent_t * e, size_t size); static void ent_trunc(lv_mem_ent_t * e, size_t size); #endif @@ -84,9 +84,9 @@ typedef struct { static uint8_t * work_mem; #endif -static uint32_t zero_mem; /*Give the address of this variable if 0 byte should be allocated*/ - +static uint32_t zero_mem; /*Give the address of this variable if 0 byte should be allocated*/ #if LV_MEM_CUSTOM == 0 + static uint8_t * last_mem; /*Address of the last valid byte*/ static uint32_t mem_max_size; /*Tracks the maximum total size of memory ever used from the internal heap*/ #endif @@ -125,7 +125,7 @@ void _lv_mem_init(void) #else work_mem = (uint8_t *)LV_MEM_ADR; #endif - + last_mem = &work_mem[LV_MEM_SIZE - 1]; lv_mem_ent_t * full = (lv_mem_ent_t *)work_mem; full->header.s.used = 0; /*The total mem size id reduced by the first header and the close patterns */ @@ -176,13 +176,11 @@ void * lv_mem_alloc(size_t size) do { /* Get the next entry*/ e = ent_get_next(e); - + if( e == NULL) break; /*If there is next entry then try to allocate there*/ - if(e != NULL) { - alloc = ent_alloc(e, size); - } - /* End if there is not next entry OR the alloc. is successful*/ - } while(e != NULL && alloc == NULL); + if(!e->header.s.used && e->header.s.d_size >= size) alloc = ent_alloc(e, size); + /* End if the alloc. is successful*/ + } while(alloc == NULL); #else /*Use custom, user defined malloc function*/ @@ -817,19 +815,15 @@ LV_ATTRIBUTE_FAST_MEM void _lv_memset_ff(void * dst, size_t len) */ static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e) { - lv_mem_ent_t * next_e = NULL; - - if(act_e == NULL) { /*NULL means: get the first entry*/ - next_e = (lv_mem_ent_t *)work_mem; - } - else { /*Get the next entry */ + /*NULL means: get the first entry; else get the next after `act_e`*/ + if(act_e == NULL) return (lv_mem_ent_t *)work_mem; + else { uint8_t * data = &act_e->first_data; - next_e = (lv_mem_ent_t *)&data[act_e->header.s.d_size]; + lv_mem_ent_t * next_e = (lv_mem_ent_t *)&data[act_e->header.s.d_size]; - if(&next_e->first_data >= &work_mem[LV_MEM_SIZE]) next_e = NULL; + if(&next_e->first_data > last_mem) return NULL; + else return next_e; } - - return next_e; } /** @@ -838,20 +832,23 @@ static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e) * @param size size of the new memory in bytes * @return pointer to the allocated memory or NULL if not enough memory in the entry */ -static void * ent_alloc(lv_mem_ent_t * e, size_t size) +static inline void * ent_alloc(lv_mem_ent_t * e, size_t size) { - void * alloc = NULL; - /*If the memory is free and big enough then use it */ - if(e->header.s.used == 0 && e->header.s.d_size >= size) { +// static uint32_t cnt = 0; +// +//// if((cnt & 0xFFFF) == 0) +// printf("alloc: %d\n", cnt); +// cnt++; +// + + /*Truncate the entry to the desired size */ ent_trunc(e, size); e->header.s.used = 1; /*Save the allocated data*/ - alloc = &e->first_data; - } + return &e->first_data; - return alloc; } /** From 075fe54537e4b5623999670dfab54acd0008c54f Mon Sep 17 00:00:00 2001 From: rockindy Date: Mon, 31 Aug 2020 16:15:42 +0800 Subject: [PATCH 21/84] Fix lv_page_glue_obj() interface for lv_binding_micropython. (#1759) --- src/lv_widgets/lv_list.c | 2 +- src/lv_widgets/lv_page.c | 3 ++- src/lv_widgets/lv_page.h | 3 ++- src/lv_widgets/lv_tileview.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lv_widgets/lv_list.c b/src/lv_widgets/lv_list.c index 5a1cfb144..fd8d5a41a 100644 --- a/src/lv_widgets/lv_list.c +++ b/src/lv_widgets/lv_list.c @@ -170,7 +170,7 @@ lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * t /*Set the default styles*/ lv_theme_apply(btn, LV_THEME_LIST_BTN); - lv_page_glue_obj(btn, true); + lv_page_glue_obj(list, btn, true); lv_btn_set_layout(btn, LV_LAYOUT_ROW_MID); lv_layout_t list_layout = lv_list_get_layout(list); diff --git a/src/lv_widgets/lv_page.c b/src/lv_widgets/lv_page.c index f2330de78..0c81100a0 100644 --- a/src/lv_widgets/lv_page.c +++ b/src/lv_widgets/lv_page.c @@ -457,10 +457,11 @@ 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 page pointer to a page object * @param obj pointer to an object on a page * @param glue true: enable glue, false: disable glue */ -void lv_page_glue_obj(lv_obj_t * obj, bool glue) +void lv_page_glue_obj(lv_obj_t * page, lv_obj_t * obj, bool glue) { lv_obj_set_drag_parent(obj, glue); lv_obj_set_drag(obj, glue); diff --git a/src/lv_widgets/lv_page.h b/src/lv_widgets/lv_page.h index 051dce509..387afc6e7 100644 --- a/src/lv_widgets/lv_page.h +++ b/src/lv_widgets/lv_page.h @@ -378,10 +378,11 @@ 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 page pointer to a page object * @param obj pointer to an object on a page * @param glue true: enable glue, false: disable glue */ -void lv_page_glue_obj(lv_obj_t * obj, bool glue); +void lv_page_glue_obj(lv_obj_t * page, lv_obj_t * obj, bool glue); /** * Focus on an object. It ensures that the object will be visible on the page. diff --git a/src/lv_widgets/lv_tileview.c b/src/lv_widgets/lv_tileview.c index 0b471b83f..73014a7f5 100644 --- a/src/lv_widgets/lv_tileview.c +++ b/src/lv_widgets/lv_tileview.c @@ -156,7 +156,7 @@ void lv_tileview_add_element(lv_obj_t * tileview, lv_obj_t * element) LV_ASSERT_OBJ(tileview, LV_OBJX_NAME); LV_ASSERT_NULL(tileview); - lv_page_glue_obj(element, true); + lv_page_glue_obj(tileview, element, true); } /*===================== From f09d871e4c8798fe42b79feb52b32f25bf2a2a88 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 2 Sep 2020 11:56:51 +0200 Subject: [PATCH 22/84] add lv_obj_has/set/clear_flag() instead unique function for click, hidden etc --- src/lv_core/lv_grid.c | 4 +- src/lv_core/lv_group.c | 24 +--- src/lv_core/lv_indev.c | 25 +--- src/lv_core/lv_obj.c | 257 ++++---------------------------------- src/lv_core/lv_obj.h | 179 ++++++-------------------- src/lv_core/lv_refr.c | 4 +- src/lv_hal/lv_hal_disp.c | 4 +- src/lv_hal/lv_hal_indev.h | 7 +- src/lv_widgets/lv_label.c | 2 +- 9 files changed, 83 insertions(+), 423 deletions(-) diff --git a/src/lv_core/lv_grid.c b/src/lv_core/lv_grid.c index 6d4b3665b..a7a08a588 100644 --- a/src/lv_core/lv_grid.c +++ b/src/lv_core/lv_grid.c @@ -216,7 +216,7 @@ static void calc_implicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc) uint32_t child_cnt = lv_obj_count_children(cont); - uint32_t col_cnt = (child_cnt / grid->row_dsc_len) + 1; + uint32_t col_cnt = ((child_cnt + grid->row_dsc_len - 1) / grid->row_dsc_len) + 1; /*+ grid->row_dsc_len - 1 to round up*/ /* If `col_dsc_buf_used`, nested a call of this func. will release `col_dsc_buf_used` because it think it taken it. * So mark that if the buffer was taken in this call*/ bool col_dsc_buf_mine = false; @@ -272,7 +272,7 @@ static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc) lv_grid_t * grid = cont->grid; uint32_t child_cnt = lv_obj_count_children(cont); - uint32_t row_cnt = (child_cnt / grid->col_dsc_len) + 1; + uint32_t row_cnt = ((child_cnt + grid->col_dsc_len - 1) / grid->col_dsc_len) + 1; /*+ grid->col_dsc_len - 1 to round up*/ bool row_dsc_buf_mine = false; /*At worst case all children is gird item prepare place for all of them*/ lv_coord_t * rows_h; diff --git a/src/lv_core/lv_group.c b/src/lv_core/lv_group.c index a926a5a0c..d5567b1ab 100644 --- a/src/lv_core/lv_group.c +++ b/src/lv_core/lv_group.c @@ -31,7 +31,6 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *), void * (*move)(const lv_ll_t *, const void *)); static void lv_group_refocus(lv_group_t * g); -static void obj_to_foreground(lv_obj_t * obj); /********************** * STATIC VARIABLES @@ -241,9 +240,6 @@ void lv_group_focus_obj(lv_obj_t * obj) lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_FOCUSED, NULL); if(res != LV_RES_OK) return; lv_obj_invalidate(*g->obj_focus); - - /*If the object or its parent has `top == true` bring it to the foreground*/ - obj_to_foreground(*g->obj_focus); } break; } @@ -490,7 +486,7 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) if(obj_next == NULL) continue; /*Hidden objects don't receive focus*/ - if(!lv_obj_get_hidden(*obj_next)) break; + if(lv_obj_has_flag(*obj_next, LV_OBJ_FLAG_HIDDEN) == false) break; } if(obj_next == group->obj_focus) return; /*There's only one visible object and it's already focused*/ @@ -508,28 +504,10 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, NULL); if(res != LV_RES_OK) return; - /*If the object or its parent has `top == true` bring it to the foreground*/ - obj_to_foreground(*group->obj_focus); - lv_obj_invalidate(*group->obj_focus); if(group->focus_cb) group->focus_cb(group); } -static void obj_to_foreground(lv_obj_t * obj) -{ - /*Search for 'top' attribute*/ - lv_obj_t * i = obj; - lv_obj_t * last_top = NULL; - while(i != NULL) { - if(i->top != 0) last_top = i; - i = lv_obj_get_parent(i); - } - - if(last_top != NULL) { - /*Move the last_top object to the foreground*/ - lv_obj_move_foreground(last_top); - } -} #endif /*LV_USE_GROUP != 0*/ diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index e820fe127..3a258729d 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -212,7 +212,7 @@ void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj) indev->cursor = cur_obj; lv_obj_set_parent(indev->cursor, lv_disp_get_layer_sys(indev->driver.disp)); lv_obj_set_pos(indev->cursor, indev->proc.types.pointer.act_point.x, indev->proc.types.pointer.act_point.y); - lv_obj_set_click(indev->cursor, false); + lv_obj_add_flag(indev->cursor, LV_OBJ_FLAG_CLICKABLE); } #if LV_USE_GROUP @@ -831,7 +831,7 @@ static void indev_proc_press(lv_indev_proc_t * proc) } /*If there is last object but it is not scrolled and not protected also search*/ else if(proc->types.pointer.scroll_obj == NULL && - lv_obj_is_protected(indev_obj_act, LV_PROTECT_PRESS_LOST) == false) { + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) { indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), &proc->types.pointer.act_point); @@ -884,19 +884,6 @@ static void indev_proc_press(lv_indev_proc_t * proc) proc->types.pointer.vect.x = 0; proc->types.pointer.vect.y = 0; - /*Search for 'top' attribute*/ - lv_obj_t * i = indev_obj_act; - lv_obj_t * last_top = NULL; - while(i != NULL) { - if(i->top) last_top = i; - i = lv_obj_get_parent(i); - } - - if(last_top != NULL) { - /*Move the last_top object to the foreground*/ - lv_obj_move_foreground(last_top); - } - /*Send a signal about the press*/ lv_signal_send(indev_obj_act, LV_SIGNAL_PRESSED, indev_act); if(indev_reset_check(proc)) return; @@ -1079,10 +1066,10 @@ lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) /*If then the children was not ok, and this obj is clickable * and it or its parent is not hidden then save this object*/ - if(found_p == NULL && lv_obj_get_click(obj) != false) { + if(found_p == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CLICKABLE)) { lv_obj_t * hidden_i = obj; while(hidden_i != NULL) { - if(lv_obj_get_hidden(hidden_i) == true) break; + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN) == true) break; hidden_i = lv_obj_get_parent(hidden_i); } /*No parent found with hidden == true*/ @@ -1101,7 +1088,7 @@ static void indev_click_focus(lv_indev_proc_t * proc) { /*Handle click focus*/ lv_obj_t * obj_to_focus = lv_obj_get_focused_obj(indev_obj_act); - if(lv_obj_is_protected(indev_obj_act, LV_PROTECT_CLICK_FOCUS) == false && + if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false && proc->types.pointer.last_pressed != obj_to_focus) { #if LV_USE_GROUP lv_group_t * g_act = lv_obj_get_group(indev_obj_act); @@ -1362,7 +1349,7 @@ static void indev_gesture(lv_indev_proc_t * proc) lv_obj_t * gesture_obj = proc->types.pointer.act_obj; /*If gesture parent is active check recursively the gesture attribute*/ - while(gesture_obj && lv_obj_get_gesture_parent(gesture_obj)) { + while(gesture_obj && lv_obj_has_flag(gesture_obj, LV_OBJ_FLAG_GESTURE_BUBBLE)) { gesture_obj = lv_obj_get_parent(gesture_obj); } diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 193d977dd..f314a9c9e 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -329,14 +329,9 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) /*Set attributes*/ new_obj->adv_hittest = 0; - new_obj->click = 1; new_obj->scroll_mode = LV_SCROLL_MODE_AUTO; - new_obj->hidden = 0; - new_obj->top = 0; - new_obj->protect = LV_PROTECT_NONE; - new_obj->parent_event = 0; - new_obj->gesture_parent = parent ? 1 : 0; - new_obj->focus_parent = 0; + new_obj->flags = LV_OBJ_FLAG_CLICKABLE; + if(parent) new_obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE; new_obj->state = LV_STATE_DEFAULT; new_obj->scroll.x = 0; new_obj->scroll.y = 0; @@ -374,14 +369,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) /*Copy attributes*/ new_obj->adv_hittest = copy->adv_hittest; - new_obj->click = copy->click; + new_obj->flags = copy->flags; new_obj->scroll_mode = copy->scroll_mode; - new_obj->hidden = copy->hidden; - new_obj->top = copy->top; - new_obj->parent_event = copy->parent_event; - - new_obj->protect = copy->protect; - new_obj->gesture_parent = copy->gesture_parent; #if LV_USE_GROUP /*Add to the same group*/ @@ -533,7 +522,7 @@ void lv_obj_invalidate(const lv_obj_t * obj) */ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) { - if(lv_obj_get_hidden(obj)) return false; + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return false; /*Invalidate the object only if it belongs to the curent or previous'*/ lv_obj_t * obj_scr = lv_obj_get_screen(obj); @@ -562,7 +551,7 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) while(par != NULL) { is_common = _lv_area_intersect(area, area, &par->coords); if(is_common == false) return false; /*If no common parts with parent break;*/ - if(lv_obj_get_hidden(par)) return false; /*If the parent is hidden then the child is hidden and won't be drawn*/ + if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return false; /*If the parent is hidden then the child is hidden and won't be drawn*/ par = lv_obj_get_parent(par); } @@ -794,12 +783,6 @@ static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) lv_obj_t * par = lv_obj_get_parent(obj); if(par != NULL) par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); - /*Tell the children the parent's size has changed*/ - lv_obj_t * i; - _LV_LL_READ(obj->child_ll, i) { - i->signal_cb(i, LV_SIGNAL_PARENT_SIZE_CHG, &ori); - } - /*Invalidate the new area*/ lv_obj_invalidate(obj); return true; @@ -1763,25 +1746,6 @@ void _lv_obj_disable_style_caching(lv_obj_t * obj, bool dis) * Attribute set *----------------*/ -/** - * Hide an object. It won't be visible and clickable. - * @param obj pointer to an object - * @param en true: hide the object - */ -void lv_obj_set_hidden(lv_obj_t * obj, bool en) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - if(!obj->hidden) lv_obj_invalidate(obj); /*Invalidate when not hidden (hidden objects are ignored) */ - - obj->hidden = en == false ? 0 : 1; - - if(!obj->hidden) lv_obj_invalidate(obj); /*Invalidate when not hidden (hidden objects are ignored) */ - - lv_obj_t * par = lv_obj_get_parent(obj); - if(par) par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); -} - /** * Set whether advanced hit-testing is enabled on an object * @param obj pointer to an object @@ -1794,31 +1758,6 @@ void lv_obj_set_adv_hittest(lv_obj_t * obj, bool en) obj->adv_hittest = en == false ? 0 : 1; } -/** - * Enable or disable the clicking of an object - * @param obj pointer to an object - * @param en true: make the object clickable - */ -void lv_obj_set_click(lv_obj_t * obj, bool en) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->click = (en == true ? 1 : 0); -} - -/** - * Enable to bring this object to the foreground if it - * or any of its children is clicked - * @param obj pointer to an object - * @param en true: enable the auto top feature - */ -void lv_obj_set_top(lv_obj_t * obj, bool en) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->top = (en == true ? 1 : 0); -} - /** * Set how the scrollbars should behave. * @param obj pointer to an object @@ -1833,54 +1772,6 @@ void lv_obj_set_scroll_mode(lv_obj_t * obj, lv_scroll_mode_t mode) lv_obj_invalidate(obj); } -/** -* Enable to use parent for gesture related operations. -* If trying to gesture the object the parent will be moved instead -* @param obj pointer to an object -* @param en true: enable the 'gesture parent' for the object -*/ -void lv_obj_set_gesture_parent(lv_obj_t * obj, bool en) -{ - obj->gesture_parent = (en == true ? 1 : 0); -} - -/** -* Enable to use parent for focus state. -* When object is focused the parent will get the state instead (visual only) -* @param obj pointer to an object -* @param en true: enable the 'focus parent' for the object -*/ -void lv_obj_set_focus_parent(lv_obj_t * obj, bool en) -{ - if(lv_obj_is_focused(obj)) { - if(en) { - obj->focus_parent = 1; - lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED); - lv_obj_set_state(lv_obj_get_focused_obj(obj), LV_STATE_FOCUSED); - } - else { - lv_obj_clear_state(lv_obj_get_focused_obj(obj), LV_STATE_FOCUSED | LV_STATE_EDITED); - lv_obj_set_state(obj, LV_STATE_FOCUSED); - obj->focus_parent = 0; - } - } - else { - obj->focus_parent = (en == true ? 1 : 0); - } -} - -/** - * Propagate the events to the parent too - * @param obj pointer to an object - * @param en true: enable the event propagation - */ -void lv_obj_set_parent_event(lv_obj_t * obj, bool en) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->parent_event = (en == true ? 1 : 0); -} - /** * Set the base direction of the object * @param obj pointer to an object @@ -1903,31 +1794,24 @@ void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir) base_dir_refr_children(obj); } -/** - * Set a bit or bits in the protect filed - * @param obj pointer to an object - * @param prot 'OR'-ed values from `lv_protect_t` - */ -void lv_obj_add_protect(lv_obj_t * obj, uint8_t prot) + +void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - obj->protect |= prot; + obj->flags |= f; } -/** - * Clear a bit or bits in the protect filed - * @param obj pointer to an object - * @param prot 'OR'-ed values from `lv_protect_t` - */ -void lv_obj_clear_protect(lv_obj_t * obj, uint8_t prot) + + +void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - prot = (~prot) & 0xFF; - obj->protect &= prot; + obj->flags &= (~f); } + /** * Set the state (fully overwrite) of an object. * If specified in the styles a transition animation will be started @@ -2001,6 +1885,7 @@ void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) } + /** * Add a given state or states to the object. The other state bits will remain unchanged. * If specified in the styles a transition animation will be started @@ -2185,7 +2070,7 @@ lv_res_t lv_event_send_func(lv_event_cb_t event_xcb, lv_obj_t * obj, lv_event_t } if(obj) { - if(obj->parent_event && obj->parent) { + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE) && obj->parent) { lv_res_t res = lv_event_send(obj->parent, event, data); if(res != LV_RES_OK) { return LV_RES_INV; @@ -3124,16 +3009,11 @@ lv_style_t * lv_obj_get_local_style(lv_obj_t * obj, uint8_t part) * Attribute get *----------------*/ -/** - * Get the hidden attribute of an object - * @param obj pointer to an object - * @return true: the object is hidden - */ -bool lv_obj_get_hidden(const lv_obj_t * obj) +bool lv_obj_has_flag(lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - return obj->hidden == 0 ? false : true; + return obj->flags & f ? true : false; } /** @@ -3148,29 +3028,6 @@ bool lv_obj_get_adv_hittest(const lv_obj_t * obj) return obj->adv_hittest == 0 ? false : true; } -/** - * Get the click enable attribute of an object - * @param obj pointer to an object - * @return true: the object is clickable - */ -bool lv_obj_get_click(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->click == 0 ? false : true; -} - -/** - * Get the top enable attribute of an object - * @param obj pointer to an object - * @return true: the auto top feature is enabled - */ -bool lv_obj_get_top(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->top == 0 ? false : true; -} /** * Get how the scrollbars should behave. @@ -3184,39 +3041,6 @@ lv_scroll_mode_t lv_obj_get_scroll_mode(lv_obj_t * obj) return obj->scroll_mode; } -/** -* Get the gesture parent attribute of an object -* @param obj pointer to an object -* @return true: gesture parent is enabled -*/ -bool lv_obj_get_gesture_parent(const lv_obj_t * obj) -{ - return obj->gesture_parent == 0 ? false : true; -} - -/** -* Get the focus parent attribute of an object -* @param obj pointer to an object -* @return true: focus parent is enabled -*/ -bool lv_obj_get_focus_parent(const lv_obj_t * obj) -{ - return obj->focus_parent == 0 ? false : true; -} - -/** - * Get the parent event attribute of an object - * @param obj pointer to an object - * @return true: parent event is enabled - */ -bool lv_obj_get_parent_event(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->parent_event == 0 ? false : true; -} - - lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -3237,31 +3061,6 @@ lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj) #endif } -/** - * Get the protect field of an object - * @param obj pointer to an object - * @return protect field ('OR'ed values of `lv_protect_t`) - */ -uint8_t lv_obj_get_protect(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->protect; -} - -/** - * Check at least one bit of a given protect bitfield is set - * @param obj pointer to an object - * @param prot protect bits to test ('OR'ed values of `lv_protect_t`) - * @return false: none of the given bits are set, true: at least one bit is set - */ -bool lv_obj_is_protected(const lv_obj_t * obj, uint8_t prot) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return (obj->protect & prot) == 0 ? false : true; -} - lv_state_t lv_obj_get_state(const lv_obj_t * obj, uint8_t part) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -4159,7 +3958,7 @@ lv_obj_t * lv_obj_get_focused_obj(const lv_obj_t * obj) { if(obj == NULL) return NULL; const lv_obj_t * focus_obj = obj; - while(lv_obj_get_focus_parent(focus_obj) != false && focus_obj != NULL) { + while(lv_obj_has_flag(focus_obj, LV_OBJ_FLAG_FOCUS_BUBBLE) != false && focus_obj != NULL) { focus_obj = lv_obj_get_parent(focus_obj); } @@ -4193,9 +3992,6 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) } } else if(sign == LV_SIGNAL_CHILD_CHG) { - /*Return 'invalid' if the child change signal is not enabled*/ - if(lv_obj_is_protected(obj, LV_PROTECT_CHILD_CHG) != false) res = LV_RES_INV; - if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) { lv_obj_set_size(obj, obj->w_set, obj->h_set); } @@ -4208,11 +4004,6 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) lv_grid_full_refr(obj); } } - -// else if(lv_obj_is_content_sensitive(obj)) { -// lv_grid_full_refr(lv_obj_get_parent(obj)); -// } - } else if(sign == LV_SIGNAL_SCROLL) { @@ -4252,11 +4043,13 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d); } else if(sign == LV_SIGNAL_STYLE_CHG) { - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child) { - lv_obj_set_pos(child, child->x_set, child->y_set); - child = lv_obj_get_child(obj, child); - } + if(lv_obj_is_grid_item(obj)) lv_grid_full_refr(obj); + +// lv_obj_t * child = lv_obj_get_child(obj, NULL); +// while(child) { +// lv_obj_set_pos(child, child->x_set, child->y_set); +// child = lv_obj_get_child(obj, child); +// } if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) { diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index cbfd9aef3..0ad5e0593 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -126,7 +126,6 @@ enum { LV_SIGNAL_CLEANUP, /**< Object is being deleted */ LV_SIGNAL_CHILD_CHG, /**< Child was removed/added */ LV_SIGNAL_COORD_CHG, /**< Object coordinates/size have changed */ - LV_SIGNAL_PARENT_SIZE_CHG, /**< Parent's size has changed */ LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */ LV_SIGNAL_BASE_DIR_CHG, /**