1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-21 06:53:01 +08:00

scroll: wip

This commit is contained in:
Gabor Kiss-Vamosi 2020-07-08 14:59:19 +02:00
parent 9cfd399fb3
commit 0cea8b2c08
4 changed files with 214 additions and 45 deletions

View File

@ -1095,6 +1095,7 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev)
if(indev->proc.reset_query) { if(indev->proc.reset_query) {
indev->proc.types.pointer.act_obj = NULL; indev->proc.types.pointer.act_obj = NULL;
indev->proc.types.pointer.last_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_limit_out = 0;
indev->proc.types.pointer.drag_in_prog = 0; indev->proc.types.pointer.drag_in_prog = 0;
indev->proc.long_pr_sent = 0; indev->proc.long_pr_sent = 0;
@ -1251,25 +1252,26 @@ static void indev_click_focus(lv_indev_proc_t * proc)
*/ */
static void indev_drag(lv_indev_proc_t * proc) static void indev_drag(lv_indev_proc_t * proc)
{ {
bool scrollable = true; bool scrollable = true;
/*Get which object to drad/scroll*/ /*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 dirs = LV_DRAG_DIR_VER; //scrollable ? lv_obj_get_scroll_dir(target_obj) : lv_obj_get_drag_dir(target_obj);
bool just_started = false; bool just_started = false;
/*Get the coordinates of the object and modify them*/ lv_coord_t act_x = 0;
lv_coord_t act_x = lv_obj_get_x(target_obj); lv_coord_t act_y = 0;
lv_coord_t act_y = lv_obj_get_y(target_obj);
/*Count the movement by drag*/ /*Count the movement by drag*/
if(proc->types.pointer.drag_limit_out == 0) { if(proc->types.pointer.drag_limit_out == 0) {
proc->types.pointer.drag_sum.x += proc->types.pointer.vect.x; proc->types.pointer.drag_sum.x += proc->types.pointer.vect.x;
proc->types.pointer.drag_sum.y += proc->types.pointer.vect.y; proc->types.pointer.drag_sum.y += proc->types.pointer.vect.y;
proc->types.pointer.drag_obj = proc->types.pointer.act_obj;
/*Go until find the object or parent scrollable in this direction*/
while(proc->types.pointer.drag_obj) {
dirs = LV_DRAG_DIR_VER;
/*Enough move?*/ /*Enough move?*/
bool hor_en = false; bool hor_en = false;
bool ver_en = false; bool ver_en = false;
@ -1290,9 +1292,16 @@ static void indev_drag(lv_indev_proc_t * proc)
} }
} }
bool up_en = ver_en;
bool down_en = ver_en;
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 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) || 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)) { (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; proc->types.pointer.drag_limit_out = 1;
just_started = true; just_started = true;
if(dirs == LV_DRAG_DIR_ONE) { if(dirs == LV_DRAG_DIR_ONE) {
@ -1305,18 +1314,69 @@ static void indev_drag(lv_indev_proc_t * proc)
if(!hor_en) proc->types.pointer.drag_sum.x = 0; if(!hor_en) proc->types.pointer.drag_sum.x = 0;
if(!ver_en) proc->types.pointer.drag_sum.y = 0; if(!ver_en) proc->types.pointer.drag_sum.y = 0;
act_x += proc->types.pointer.drag_sum.x; act_x = lv_obj_get_x(proc->types.pointer.drag_obj) + proc->types.pointer.drag_sum.x;
act_y += proc->types.pointer.drag_sum.y; 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 the drag limit is exceeded handle the dragging*/
if(proc->types.pointer.drag_limit_out != 0) { if(proc->types.pointer.drag_limit_out != 0) {
/*Set new position or scroll 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) { 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_x = obj->coords.x1;
lv_coord_t prev_y = target_obj->coords.y1; lv_coord_t prev_y = obj->coords.y1;
/*Move the object. `drag_sum` is zerod out for *disabled direction*/ /*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.x) act_x += proc->types.pointer.vect.x;
@ -1327,18 +1387,18 @@ static void indev_drag(lv_indev_proc_t * proc)
if(scrollable) { if(scrollable) {
lv_area_t child_box; 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; 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; 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; 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 { } 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; proc->types.pointer.drag_in_prog = 1;
@ -1397,9 +1457,9 @@ static void indev_drag_throw(lv_indev_proc_t * proc)
/*Reduce the vectors*/ /*Reduce the vectors*/
proc->types.pointer.drag_throw_vect.x = 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 =
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) { switch(proc->types.pointer.drag_dir) {
case LV_DRAG_DIR_HOR: 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, 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);
lv_obj_scroll_by(target_obj, proc->types.pointer.drag_throw_vect.x, proc->types.pointer.drag_throw_vect.y);
} else { } else {
lv_area_t coords_ori; lv_area_t coords_ori;
lv_obj_get_coords(target_obj, &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*/ signal*/
else { else {
proc->types.pointer.drag_in_prog = 0; 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); target_obj->signal_cb(target_obj, scrollable ? LV_SIGNAL_SCROLL_END : LV_SIGNAL_DRAG_END, indev_act);
if(indev_reset_check(proc)) return; if(indev_reset_check(proc)) return;
lv_event_send(target_obj, LV_EVENT_DRAG_END, NULL); 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) static lv_obj_t * get_dragged_obj(lv_obj_t * obj)
{ {
return 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; if(obj == NULL) return NULL;
lv_obj_t * drag_obj = obj; lv_obj_t * drag_obj = obj;
while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) { while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) {

View File

@ -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); 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 * Set the size of an extended clickable area
* If TINY mode is used, only the largest of the horizontal and vertical padding * If TINY mode is used, only the largest of the horizontal and vertical padding

View File

@ -534,6 +534,66 @@ void lv_obj_realign(lv_obj_t * obj);
*/ */
void lv_obj_set_auto_realign(lv_obj_t * obj, bool en); 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 * Set the size of an extended clickable area
* @param obj pointer to an object * @param obj pointer to an object

View File

@ -139,6 +139,7 @@ typedef struct _lv_indev_proc_t {
struct _lv_obj_t * act_obj; /*The object being pressed*/ 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 struct _lv_obj_t * last_obj; /*The last object which was pressed (used by drag_throw and
other post-release event)*/ other post-release event)*/
struct _lv_obj_t * drag_obj; /*The object being pressed*/
struct _lv_obj_t * last_pressed; /*The lastly pressed object*/ struct _lv_obj_t * last_pressed; /*The lastly pressed object*/
lv_gesture_dir_t gesture_dir; lv_gesture_dir_t gesture_dir;