handle LV_OBJ_FLAG_SCROLL_ELASTIC/MOMENTUM

This commit is contained in:
Gabor Kiss-Vamosi
2020-09-30 21:17:25 +02:00
parent afc5475196
commit 301859b978
7 changed files with 77 additions and 98 deletions

View File

@@ -12,6 +12,7 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define ELASTIC_SLOWNESS_FACTOR 4 /*Scrolling on elastic parts are slower by this factor*/
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@@ -26,6 +27,7 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo
static void scroll_limit_diff(lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y); static void scroll_limit_diff(lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y);
static lv_coord_t scroll_throw_predict_y(lv_indev_proc_t * proc); static lv_coord_t scroll_throw_predict_y(lv_indev_proc_t * proc);
static lv_coord_t scroll_throw_predict_x(lv_indev_proc_t * proc); static lv_coord_t scroll_throw_predict_x(lv_indev_proc_t * proc);
static lv_coord_t elastic_diff(lv_obj_t * obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@@ -219,16 +221,15 @@ void _lv_scroll_handler(lv_indev_proc_t * proc)
lv_coord_t diff_y = 0; lv_coord_t diff_y = 0;
if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_HOR) { if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_HOR) {
diff_x = proc->types.pointer.vect.x; lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
if(lv_obj_get_scroll_right(scroll_obj) < 0) diff_x = diff_x / 2; lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
if(lv_obj_get_scroll_left(scroll_obj) < 0) diff_x = diff_x / 2; diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr);
} else { } else {
diff_y = proc->types.pointer.vect.y; lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
if(lv_obj_get_scroll_top(scroll_obj) < 0) diff_y = diff_y / 2; lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
if(lv_obj_get_scroll_bottom(scroll_obj) < 0) diff_y = diff_y / 2; diff_y = elastic_diff(scroll_obj, proc->types.pointer.vect.y, st, sb);
} }
if((scroll_obj->scroll_dir & LV_DIR_LEFT) == 0 && diff_x > 0) diff_x = 0; if((scroll_obj->scroll_dir & LV_DIR_LEFT) == 0 && diff_x > 0) diff_x = 0;
if((scroll_obj->scroll_dir & LV_DIR_RIGHT) == 0 && diff_x < 0) diff_x = 0; if((scroll_obj->scroll_dir & LV_DIR_RIGHT) == 0 && diff_x < 0) diff_x = 0;
if((scroll_obj->scroll_dir & LV_DIR_TOP) == 0 && diff_y > 0) diff_y = 0; if((scroll_obj->scroll_dir & LV_DIR_TOP) == 0 && diff_y > 0) diff_y = 0;
@@ -252,27 +253,28 @@ void _lv_scroll_throw_handler(lv_indev_proc_t * proc)
{ {
lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
if(scroll_obj == NULL) return; if(scroll_obj == NULL) return;
if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_NONE) return;
lv_indev_t * indev_act = lv_indev_get_act(); lv_indev_t * indev_act = lv_indev_get_act();
lv_coord_t scroll_throw = indev_act->driver.scroll_throw; lv_coord_t scroll_throw = indev_act->driver.scroll_throw;
if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_NONE) { if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_MOMENTUM) == false) {
return; proc->types.pointer.scroll_throw_vect.y = 0;
proc->types.pointer.scroll_throw_vect.x = 0;
} }
else if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_VER) {
if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_VER) {
proc->types.pointer.scroll_throw_vect.x = 0; proc->types.pointer.scroll_throw_vect.x = 0;
/*If no snapping "throw"*/ /*If no snapping "throw"*/
if(scroll_obj->snap_align_y == LV_SCROLL_SNAP_ALIGN_NONE) { if(scroll_obj->snap_align_y == LV_SCROLL_SNAP_ALIGN_NONE) {
proc->types.pointer.scroll_throw_vect.y = proc->types.pointer.scroll_throw_vect.y =
proc->types.pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100; proc->types.pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100;
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj); lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
/*If scrolled inside reduce faster*/ proc->types.pointer.scroll_throw_vect.y = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.y, st, sb);
if(st < 0 || sb < 0) {
proc->types.pointer.scroll_throw_vect.y = proc->types.pointer.scroll_throw_vect.y >> 1;
}
_lv_obj_scroll_by_raw(scroll_obj, 0, proc->types.pointer.scroll_throw_vect.y); _lv_obj_scroll_by_raw(scroll_obj, 0, proc->types.pointer.scroll_throw_vect.y);
} }
@@ -295,10 +297,7 @@ void _lv_scroll_throw_handler(lv_indev_proc_t * proc)
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj); lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
/*If scrolled inside reduce faster*/ proc->types.pointer.scroll_throw_vect.x = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.x, sl ,sr);
if(sl < 0 || sr < 0) {
proc->types.pointer.scroll_throw_vect.x = proc->types.pointer.scroll_throw_vect.x >> 1;
}
_lv_obj_scroll_by_raw(scroll_obj, proc->types.pointer.scroll_throw_vect.x, 0); _lv_obj_scroll_by_raw(scroll_obj, proc->types.pointer.scroll_throw_vect.x, 0);
} }
@@ -344,12 +343,13 @@ void _lv_scroll_throw_handler(lv_indev_proc_t * proc)
} }
} }
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); lv_signal_send(scroll_obj, LV_SIGNAL_SCROLL_END, indev_act);
if(proc->reset_query) return; if(proc->reset_query) return;
lv_event_send(scroll_obj, LV_EVENT_SCROLL_END, indev_act); lv_event_send(scroll_obj, LV_EVENT_SCROLL_END, indev_act);
if(proc->reset_query) return; if(proc->reset_query) return;
proc->types.pointer.scroll_dir = LV_SCROLL_DIR_NONE;
proc->types.pointer.scroll_obj = NULL;
} }
} }
@@ -531,3 +531,18 @@ static lv_coord_t scroll_throw_predict_x(lv_indev_proc_t * proc)
return move; return move;
} }
static lv_coord_t elastic_diff(lv_obj_t * obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end)
{
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ELASTIC)) {
/*Elastic scroll if scrolled in*/
if(scroll_end < 0) diff = (diff + ELASTIC_SLOWNESS_FACTOR / 2) / ELASTIC_SLOWNESS_FACTOR;
else if(scroll_start < 0) diff = (diff + ELASTIC_SLOWNESS_FACTOR / 2) / ELASTIC_SLOWNESS_FACTOR;
} else {
/*Scroll back to the boundary id required*/
if(scroll_end + diff < 0) diff = - scroll_end;
if(scroll_start - diff < 0) diff = scroll_start;
}
return diff;
}

View File

@@ -289,6 +289,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
new_obj->flags |= LV_OBJ_FLAG_PRESS_LOCK; new_obj->flags |= LV_OBJ_FLAG_PRESS_LOCK;
new_obj->flags |= LV_OBJ_FLAG_CLICK_FOCUSABLE; new_obj->flags |= LV_OBJ_FLAG_CLICK_FOCUSABLE;
new_obj->flags |= LV_OBJ_FLAG_SCROLLABLE; new_obj->flags |= LV_OBJ_FLAG_SCROLLABLE;
new_obj->flags |= LV_OBJ_FLAG_SCROLL_ELASTIC;
new_obj->flags |= LV_OBJ_FLAG_SCROLL_MOMENTUM;
if(parent) new_obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE; if(parent) new_obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE;
new_obj->state = LV_STATE_DEFAULT; new_obj->state = LV_STATE_DEFAULT;
new_obj->scroll.x = 0; new_obj->scroll.x = 0;

View File

@@ -438,6 +438,9 @@ lv_style_int_t _lv_obj_get_style_int(const lv_obj_t * obj, uint8_t part, lv_styl
case LV_STYLE_VALUE_BLEND_MODE: case LV_STYLE_VALUE_BLEND_MODE:
if(list->blend_mode_all_normal) def = true; if(list->blend_mode_all_normal) def = true;
break; break;
case LV_STYLE_TEXT_DECOR:
if(list->text_decor_none) def = true;
break;
} }
if(def) { if(def) {
@@ -1346,6 +1349,7 @@ static bool style_prop_is_cacheable(lv_style_property_t prop)
case LV_STYLE_TEXT_LETTER_SPACE: case LV_STYLE_TEXT_LETTER_SPACE:
case LV_STYLE_TEXT_LINE_SPACE: case LV_STYLE_TEXT_LINE_SPACE:
case LV_STYLE_TEXT_FONT: case LV_STYLE_TEXT_FONT:
case LV_STYLE_TEXT_DECOR:
case LV_STYLE_TRANSFORM_ANGLE: case LV_STYLE_TRANSFORM_ANGLE:
case LV_STYLE_TRANSFORM_WIDTH: case LV_STYLE_TRANSFORM_WIDTH:
case LV_STYLE_TRANSFORM_HEIGHT: case LV_STYLE_TRANSFORM_HEIGHT:

View File

@@ -512,7 +512,7 @@ static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font)
font->line_height = font_header.ascent - font_header.descent; font->line_height = font_header.ascent - font_header.descent;
font->get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt; font->get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt;
font->get_glyph_bitmap = lv_font_get_bitmap_fmt_txt; font->get_glyph_bitmap = lv_font_get_bitmap_fmt_txt;
font->subpx = LV_FONT_SUBPX_NONE; font->subpx = font_header.subpixels_mode;
font_dsc->bpp = font_header.bits_per_pixel; font_dsc->bpp = font_header.bits_per_pixel;
font_dsc->kern_scale = font_header.kerning_scale; font_dsc->kern_scale = font_header.kerning_scale;

View File

@@ -71,7 +71,6 @@ lv_obj_t * lv_line_create(lv_obj_t * par, const lv_obj_t * copy)
ext->point_num = 0; ext->point_num = 0;
ext->point_array = NULL; ext->point_array = NULL;
ext->auto_size = 1;
ext->y_inv = 0; ext->y_inv = 0;
lv_obj_set_design_cb(line, lv_line_design); lv_obj_set_design_cb(line, lv_line_design);
@@ -79,23 +78,19 @@ lv_obj_t * lv_line_create(lv_obj_t * par, const lv_obj_t * copy)
/*Init the new line*/ /*Init the new line*/
if(copy == NULL) { if(copy == NULL) {
lv_obj_set_size(line, LV_DPI, lv_obj_set_size(line, LV_SIZE_AUTO, LV_SIZE_AUTO);
LV_DPI); /*Auto size is enables, but set default size until no points are added*/ lv_obj_clear_flag(line, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_click(line, false);
lv_theme_apply(line, LV_THEME_LINE); lv_theme_apply(line, LV_THEME_LINE);
} }
/*Copy an existing object*/ /*Copy an existing object*/
else { else {
lv_line_ext_t * copy_ext = lv_obj_get_ext_attr(copy); lv_line_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
lv_line_set_auto_size(line, lv_line_get_auto_size(copy));
lv_line_set_y_invert(line, lv_line_get_y_invert(copy)); lv_line_set_y_invert(line, lv_line_get_y_invert(copy));
lv_line_set_auto_size(line, lv_line_get_auto_size(copy));
lv_line_set_points(line, copy_ext->point_array, copy_ext->point_num); lv_line_set_points(line, copy_ext->point_array, copy_ext->point_num);
/*Refresh the style with new signal function*/ /*Refresh the style with new signal function*/
lv_obj_refresh_style(line, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); _lv_obj_refresh_style(line, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
} }
LV_LOG_INFO("line created"); LV_LOG_INFO("line created");
@@ -122,41 +117,11 @@ void lv_line_set_points(lv_obj_t * line, const lv_point_t point_a[], uint16_t po
ext->point_array = point_a; ext->point_array = point_a;
ext->point_num = point_num; ext->point_num = point_num;
if(point_num > 0 && ext->auto_size != 0) { _lv_obj_handle_self_size_chg(line);
uint16_t i;
lv_coord_t xmax = LV_COORD_MIN;
lv_coord_t ymax = LV_COORD_MIN;
for(i = 0; i < point_num; i++) {
xmax = LV_MATH_MAX(point_a[i].x, xmax);
ymax = LV_MATH_MAX(point_a[i].y, ymax);
}
lv_style_int_t line_width = lv_obj_get_style_line_width(line, LV_LINE_PART_MAIN);
lv_obj_set_size(line, xmax + line_width, ymax + line_width);
}
lv_obj_invalidate(line); lv_obj_invalidate(line);
} }
/**
* Enable (or disable) the auto-size option. The size of the object will fit to its points.
* (set width to x max and height to y max)
* @param line pointer to a line object
* @param en true: auto size is enabled, false: auto size is disabled
*/
void lv_line_set_auto_size(lv_obj_t * line, bool en)
{
LV_ASSERT_OBJ(line, LV_OBJX_NAME);
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
if(ext->auto_size == en) return;
ext->auto_size = en == false ? 0 : 1;
/*Refresh the object*/
if(en) lv_line_set_points(line, ext->point_array, ext->point_num);
}
/** /**
* Enable (or disable) the y coordinate inversion. * Enable (or disable) the y coordinate inversion.
* If enabled then y will be subtracted from the height of the object, * If enabled then y will be subtracted from the height of the object,
@@ -180,20 +145,6 @@ void lv_line_set_y_invert(lv_obj_t * line, bool en)
* Getter functions * Getter functions
*====================*/ *====================*/
/**
* Get the auto size attribute
* @param line pointer to a line object
* @return true: auto size is enabled, false: disabled
*/
bool lv_line_get_auto_size(const lv_obj_t * line)
{
LV_ASSERT_OBJ(line, LV_OBJX_NAME);
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
return ext->auto_size == 0 ? false : true;
}
/** /**
* Get the y inversion attribute * Get the y inversion attribute
* @param line pointer to a line object * @param line pointer to a line object
@@ -234,8 +185,8 @@ static lv_design_res_t lv_line_design(lv_obj_t * line, const lv_area_t * clip_ar
lv_area_t area; lv_area_t area;
lv_obj_get_coords(line, &area); lv_obj_get_coords(line, &area);
lv_coord_t x_ofs = area.x1; lv_coord_t x_ofs = area.x1 - lv_obj_get_scroll_top(line);
lv_coord_t y_ofs = area.y1; lv_coord_t y_ofs = area.y1 - lv_obj_get_scroll_left(line);
lv_point_t p1; lv_point_t p1;
lv_point_t p2; lv_point_t p2;
lv_coord_t h = lv_obj_get_height(line); lv_coord_t h = lv_obj_get_height(line);
@@ -280,13 +231,34 @@ static lv_res_t lv_line_signal(lv_obj_t * line, lv_signal_t sign, void * param)
/* Include the ancient signal function */ /* Include the ancient signal function */
res = ancestor_signal(line, sign, param); res = ancestor_signal(line, sign, param);
if(res != LV_RES_OK) return res; if(res != LV_RES_OK) return res;
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); if(sign == LV_SIGNAL_GET_TYPE) {
return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { }
else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
/*The corner of the skew lines is out of the intended area*/ /*The corner of the skew lines is out of the intended area*/
lv_style_int_t line_width = lv_obj_get_style_line_width(line, LV_LINE_PART_MAIN); lv_style_int_t line_width = lv_obj_get_style_line_width(line, LV_LINE_PART_MAIN);
if(line->ext_draw_pad < line_width) line->ext_draw_pad = line_width; if(line->ext_draw_pad < line_width) line->ext_draw_pad = line_width;
} }
else if(sign == LV_SIGNAL_GET_SELF_SIZE) {
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
lv_point_t * p = param;
lv_coord_t w = 0;
lv_coord_t h = 0;
if(ext->point_num > 0) {
uint16_t i;
for(i = 0; i < ext->point_num; i++) {
w = LV_MATH_MAX(ext->point_array[i].x, w);
h = LV_MATH_MAX(ext->point_array[i].y, h);
}
lv_style_int_t line_width = lv_obj_get_style_line_width(line, LV_LINE_PART_MAIN);
w += line_width;
h += line_width;
p->x = w;
p->y = h;
}
}
return res; return res;
} }

View File

@@ -32,7 +32,6 @@ typedef struct {
/*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/ /*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/
const lv_point_t * point_array; /*Pointer to an array with the points of the line*/ const lv_point_t * point_array; /*Pointer to an array with the points of the line*/
uint16_t point_num; /*Number of points in 'point_array' */ uint16_t point_num; /*Number of points in 'point_array' */
uint8_t auto_size : 1; /*1: set obj. width to x max and obj. height to y max */
uint8_t y_inv : 1; /*1: y == 0 will be on the bottom*/ uint8_t y_inv : 1; /*1: y == 0 will be on the bottom*/
} lv_line_ext_t; } lv_line_ext_t;
@@ -66,14 +65,6 @@ lv_obj_t * lv_line_create(lv_obj_t * par, const lv_obj_t * copy);
*/ */
void lv_line_set_points(lv_obj_t * line, const lv_point_t point_a[], uint16_t point_num); void lv_line_set_points(lv_obj_t * line, const lv_point_t point_a[], uint16_t point_num);
/**
* Enable (or disable) the auto-size option. The size of the object will fit to its points.
* (set width to x max and height to y max)
* @param line pointer to a line object
* @param en true: auto size is enabled, false: auto size is disabled
*/
void lv_line_set_auto_size(lv_obj_t * line, bool en);
/** /**
* Enable (or disable) the y coordinate inversion. * Enable (or disable) the y coordinate inversion.
* If enabled then y will be subtracted from the height of the object, * If enabled then y will be subtracted from the height of the object,
@@ -92,13 +83,6 @@ work */
* Getter functions * Getter functions
*====================*/ *====================*/
/**
* Get the auto size attribute
* @param line pointer to a line object
* @return true: auto size is enabled, false: disabled
*/
bool lv_line_get_auto_size(const lv_obj_t * line);
/** /**
* Get the y inversion attribute * Get the y inversion attribute
* @param line pointer to a line object * @param line pointer to a line object

View File

@@ -103,7 +103,8 @@ lv_obj_t * lv_table_create(lv_obj_t * par, const lv_obj_t * copy)
ext->row_h[0] = LV_DPI; /*It will be overwritten when the theme is applied*/ ext->row_h[0] = LV_DPI; /*It will be overwritten when the theme is applied*/
ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char *)); ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char *));
lv_obj_set_size(table, LV_SIZE_AUTO, 80); lv_obj_set_size(table, 80, 80);
// lv_obj_set_size(table, LV_SIZE_AUTO, LV_SIZE_AUTO);
lv_theme_apply(table, LV_THEME_TABLE); lv_theme_apply(table, LV_THEME_TABLE);
} }
@@ -710,6 +711,7 @@ static lv_design_res_t lv_table_design(lv_obj_t * table, const lv_area_t * clip_
uint16_t cell = 0; uint16_t cell = 0;
cell_area.y2 = table->coords.y1 + bg_top - 1 - lv_obj_get_scroll_top(table); cell_area.y2 = table->coords.y1 + bg_top - 1 - lv_obj_get_scroll_top(table);
lv_coord_t scroll_left = lv_obj_get_scroll_left(table);
for(row = 0; row < ext->row_cnt; row++) { for(row = 0; row < ext->row_cnt; row++) {
lv_coord_t h_row = ext->row_h[row]; lv_coord_t h_row = ext->row_h[row];
@@ -718,7 +720,7 @@ static lv_design_res_t lv_table_design(lv_obj_t * table, const lv_area_t * clip_
if(cell_area.y1 > clip_area->y2) return LV_DESIGN_RES_OK; if(cell_area.y1 > clip_area->y2) return LV_DESIGN_RES_OK;
cell_area.x2 = table->coords.x1 + bg_left - 1; cell_area.x2 = table->coords.x1 + bg_left - 1 - scroll_left;
for(col = 0; col < ext->col_cnt; col++) { for(col = 0; col < ext->col_cnt; col++) {