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

flex, scroll: support RTL base dir

This commit is contained in:
Gabor Kiss-Vamosi 2020-11-02 15:52:26 +01:00
parent a2cc8c3127
commit 66dc6250b5
9 changed files with 215 additions and 56 deletions

View File

@ -36,20 +36,45 @@ static void place_content(lv_coord_t place, lv_coord_t max_size, lv_coord_t trac
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
void lv_obj_set_flex_cont(lv_obj_t * obj, lv_flex_dir_t flex_dir, lv_flex_place_t flex_place) void lv_obj_set_flex_dir(lv_obj_t * obj, lv_flex_dir_t flex_dir)
{ {
if(obj->spec_attr == NULL) lv_obj_allocate_rare_attr(obj); lv_obj_allocate_rare_attr(obj);
if(obj->spec_attr->flex_cont.dir == flex_dir && obj->spec_attr->flex_cont.place == flex_place) return; if(obj->spec_attr->flex_cont.dir == flex_dir) return;
obj->spec_attr->flex_cont.dir = flex_dir & 0x3; obj->spec_attr->flex_cont.dir = flex_dir & 0x3;
obj->spec_attr->flex_cont.wrap = flex_dir & LV_FLEX_WRAP ? 1 : 0; obj->spec_attr->flex_cont.wrap = flex_dir & LV_FLEX_WRAP ? 1 : 0;
obj->spec_attr->flex_cont.rev = flex_dir & LV_FLEX_REVERSE ? 1 : 0; obj->spec_attr->flex_cont.rev = flex_dir & LV_FLEX_REVERSE ? 1 : 0;
obj->spec_attr->flex_cont.place = flex_place;
_lv_flex_refresh(obj); _lv_flex_refresh(obj);
} }
/**
* Set how to place the tracks below/next to each other.
* For ROW direction it means how to place the rows vertically.
* For COLUMN direction it means how to place the column horizontally.
* @param obj point to a flex container
* @param place the placement type. Can be any element of `lv_flex_place_t`.
* @note if the base direction is RTL and the direction is ROW, LV_FLEX_START means the right side
*/
void lv_obj_set_flex_track_place(lv_obj_t * obj, lv_flex_place_t place)
{
lv_obj_allocate_rare_attr(obj);
if(obj->spec_attr->flex_cont.place == place) return;
obj->spec_attr->flex_cont.place = place;
_lv_flex_refresh(obj);
}
/**
* Set a gap in the main direction.
* For ROW direction it means adding gap horizontally between the items.
* For COLUMN direction it means adding gap vertically between the items.
* @param obj pointer to an object (flex container)
* @param gap the gap in pixels
* @note By default the objects are packed tightly after each other
*/
void lv_obj_set_flex_gap(lv_obj_t * obj, lv_coord_t gap) void lv_obj_set_flex_gap(lv_obj_t * obj, lv_coord_t gap)
{ {
if(obj->spec_attr == NULL) lv_obj_allocate_rare_attr(obj); if(obj->spec_attr == NULL) lv_obj_allocate_rare_attr(obj);
@ -61,7 +86,32 @@ void lv_obj_set_flex_gap(lv_obj_t * obj, lv_coord_t gap)
_lv_flex_refresh(obj); _lv_flex_refresh(obj);
} }
void lv_obj_set_flex_item(lv_obj_t * obj, lv_flex_place_t place) /**
* Make an object flex item, i.e. allow setting it's coordinate according to the parent's flex settings.
* @param obj pointer to an object
*/
void lv_obj_set_flex_item(lv_obj_t * obj, bool en)
{
if(en) {
lv_coord_t f = _LV_COORD_FELX(LV_FLEX_START);
lv_obj_set_pos(obj, f, f);
} else {
lv_obj_set_pos(obj, lv_obj_get_x(obj), lv_obj_get_y(obj));
}
}
/**
* Set how the place the item in it's track in the cross direction.
* It has a visible effect only if the objects in the same track has different size in the cross direction.
* For ROW direction it means how to place the objects vertically in their row.
* For COLUMN direction it means how to place the objects horizontally in their column.
* @param obj pointer to a flex item
* @param place:
* - `LV_FLEX_START` top/left (in case of RTL base direction right)
* - `LV_FLEX_CENTER` center
* - `LV_FLEX_END` bottom/right (in case of RTL base direction left)
*/
void lv_obj_set_flex_item_place(lv_obj_t * obj, lv_flex_place_t place)
{ {
lv_coord_t f = _LV_COORD_FELX(place); lv_coord_t f = _LV_COORD_FELX(place);
lv_obj_set_pos(obj, f, f); lv_obj_set_pos(obj, f, f);
@ -103,11 +153,12 @@ void _lv_flex_refresh(lv_obj_t * cont)
if(dir == LV_FLEX_DIR_NONE) return; if(dir == LV_FLEX_DIR_NONE) return;
bool rtl = lv_obj_get_base_dir(cont) == LV_BIDI_DIR_RTL ? true : false;
bool row = dir == LV_FLEX_DIR_ROW ? true : false; bool row = dir == LV_FLEX_DIR_ROW ? true : false;
/*Count the grow units and free space*/ /*Count the grow units and free space*/
lv_coord_t max_main_size = (row ? lv_obj_get_width_fit(cont) : lv_obj_get_height_fit(cont)); lv_coord_t max_main_size = (row ? lv_obj_get_width_fit(cont) : lv_obj_get_height_fit(cont));
lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont, LV_OBJ_PART_MAIN) - lv_obj_get_scroll_left(cont); lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont, LV_OBJ_PART_MAIN) - lv_obj_get_scroll_y(cont);
lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont, LV_OBJ_PART_MAIN) - lv_obj_get_scroll_top(cont); lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont, LV_OBJ_PART_MAIN) - lv_obj_get_scroll_x(cont);
lv_coord_t place = lv_obj_get_flex_place(cont); lv_coord_t place = lv_obj_get_flex_place(cont);
lv_ll_t * ll = _lv_obj_get_child_ll(cont); lv_ll_t * ll = _lv_obj_get_child_ll(cont);
@ -119,6 +170,11 @@ void _lv_flex_refresh(lv_obj_t * cont)
place = LV_FLEX_START; place = LV_FLEX_START;
} }
if(rtl && !row) {
if(place == LV_FLEX_START) place = LV_FLEX_END;
else if(place == LV_FLEX_END) place = LV_FLEX_START;
}
lv_coord_t all_track_size = 0; lv_coord_t all_track_size = 0;
lv_coord_t gap = 0; lv_coord_t gap = 0;
uint32_t row_cnt = 0; uint32_t row_cnt = 0;
@ -144,14 +200,26 @@ void _lv_flex_refresh(lv_obj_t * cont)
} }
track_first_item = rev ? _lv_ll_get_head(ll) : _lv_ll_get_tail(ll); track_first_item = rev ? _lv_ll_get_head(ll) : _lv_ll_get_tail(ll);
if(rtl && !row) {
*cross_pos += all_track_size;
}
while(track_first_item) { while(track_first_item) {
/*Search the first item of the next row */ /*Search the first item of the next row */
next_track_first_item = find_track_end(cont, track_first_item, max_main_size, &grow_unit, &track_size); next_track_first_item = find_track_end(cont, track_first_item, max_main_size, &grow_unit, &track_size);
if(rtl && !row) {
*cross_pos -= track_size;
}
children_repos(cont, track_first_item, next_track_first_item, abs_x, abs_y, track_size, grow_unit); children_repos(cont, track_first_item, next_track_first_item, abs_x, abs_y, track_size, grow_unit);
track_first_item = next_track_first_item; track_first_item = next_track_first_item;
*cross_pos += track_size + gap;
if(rtl && !row) {
*cross_pos -= gap;
} else {
*cross_pos += track_size + gap;
}
} }
LV_ASSERT_MEM_INTEGRITY(); LV_ASSERT_MEM_INTEGRITY();
@ -236,6 +304,10 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it
lv_style_int_t (*get_margin_end)(const lv_obj_t *, uint8_t part) = (row ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom); lv_style_int_t (*get_margin_end)(const lv_obj_t *, uint8_t part) = (row ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom);
void * (*ll_iter)(const lv_ll_t * , const void *) = rev ? _lv_ll_get_next : _lv_ll_get_prev; void * (*ll_iter)(const lv_ll_t * , const void *) = rev ? _lv_ll_get_next : _lv_ll_get_prev;
bool rtl = lv_obj_get_base_dir(cont) == LV_BIDI_DIR_RTL ? true : false;
if(row && rtl) abs_x += lv_obj_get_width_fit(cont);
lv_ll_t * ll = _lv_obj_get_child_ll(cont); lv_ll_t * ll = _lv_obj_get_child_ll(cont);
lv_coord_t main_pos = 0; lv_coord_t main_pos = 0;
/*Reposition the children*/ /*Reposition the children*/
@ -274,20 +346,15 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it
break; break;
} }
lv_coord_t diff_x; if(row && rtl) {
lv_coord_t diff_y; main_pos -= obj_get_main_size(item) + gap;
if(row) {
cross_pos += lv_obj_get_style_margin_top(item, LV_OBJ_PART_MAIN);
main_pos += lv_obj_get_style_margin_left(item, LV_OBJ_PART_MAIN);
diff_x = abs_x + main_pos - item->coords.x1;
diff_y = abs_y + cross_pos - item->coords.y1;
} else {
main_pos += lv_obj_get_style_margin_top(item, LV_OBJ_PART_MAIN);
cross_pos += lv_obj_get_style_margin_left(item, LV_OBJ_PART_MAIN);
diff_x = abs_x + cross_pos - item->coords.x1;
diff_y = abs_y + main_pos - item->coords.y1;
} }
lv_coord_t diff_x = abs_x - item->coords.x1 + lv_obj_get_style_margin_left(item, LV_OBJ_PART_MAIN);
lv_coord_t diff_y = abs_y - item->coords.y1 + lv_obj_get_style_margin_top(item, LV_OBJ_PART_MAIN);
diff_x += row ? main_pos : cross_pos;
diff_y += row ? cross_pos : main_pos;
if(diff_x || diff_y) { if(diff_x || diff_y) {
item->coords.x1 += diff_x; item->coords.x1 += diff_x;
item->coords.x2 += diff_x; item->coords.x2 += diff_x;
@ -295,7 +362,10 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it
item->coords.y2 += diff_y; item->coords.y2 += diff_y;
_lv_obj_move_children_by(item, diff_x, diff_y); _lv_obj_move_children_by(item, diff_x, diff_y);
} }
main_pos += obj_get_main_size(item) + gap;
if(!(row && rtl)) {
main_pos += obj_get_main_size(item) + gap;
}
item = ll_iter(ll, item); item = ll_iter(ll, item);
} }
} }

View File

@ -58,9 +58,46 @@ typedef struct {
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
void lv_obj_set_flex_cont(lv_obj_t * obj, lv_flex_dir_t flex_dir, lv_flex_place_t flex_place); void lv_obj_set_flex_dir(lv_obj_t * obj, lv_flex_dir_t flex_dir);
/**
* Set how to place the tracks below/next to each other.
* For ROW direction it means how to place the rows vertically.
* For COLUMN direction it means how to place the column horizontally.
* @param obj point to a flex container
* @param place the placement type. Can be any element of `lv_flex_place_t`.
* @note if the base direction is RTL and the direction is ROW, LV_FLEX_START means the right side
*/
void lv_obj_set_flex_track_place(lv_obj_t * obj, lv_flex_place_t place);
/**
* Set a gap in the main direction.
* For ROW direction it means adding gap horizontally between the items.
* For COLUMN direction it means adding gap vertically between the items.
* @param obj pointer to an object (flex container)
* @param gap the gap in pixels
* @note By default the objects are packed tightly after each other
*/
void lv_obj_set_flex_gap(lv_obj_t * obj, lv_coord_t gap); void lv_obj_set_flex_gap(lv_obj_t * obj, lv_coord_t gap);
void lv_obj_set_flex_item(lv_obj_t * obj, lv_flex_place_t place);
/**
* Make an object flex item, i.e. allow setting it's coordinate according to the parent's flex settings.
* @param obj pointer to an object
*/
void lv_obj_set_flex_item(lv_obj_t * obj, bool en);
/**
* Set how the place the item in it's track in the cross direction.
* It has a visible effect only if the objects in the same track has different size in the cross direction.
* For ROW direction it means how to place the objects vertically in their row.
* For COLUMN direction it means how to place the objects horizontally in their column.
* @param obj pointer to a flex item
* @param place:
* - `LV_FLEX_START` top/left (in case of RTL base direction right)
* - `LV_FLEX_CENTER` center
* - `LV_FLEX_END` bottom/right (in case of RTL base direction left)
*/
void lv_obj_set_flex_item_place(lv_obj_t * obj, lv_flex_place_t place);
lv_flex_dir_t lv_obj_get_flex_dir(const lv_obj_t * obj); lv_flex_dir_t lv_obj_get_flex_dir(const lv_obj_t * obj);
lv_flex_place_t lv_obj_get_flex_place(const lv_obj_t * obj); lv_flex_place_t lv_obj_get_flex_place(const lv_obj_t * obj);

View File

@ -192,8 +192,8 @@ void _lv_grid_full_refresh(lv_obj_t * cont)
* It will be used as helper during item repositioning to avoid calculating this value for every children*/ * It will be used as helper during item repositioning to avoid calculating this value for every children*/
lv_coord_t pad_left = lv_obj_get_style_pad_left(cont, LV_OBJ_PART_MAIN); 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); lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_OBJ_PART_MAIN);
hint.grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_left(cont); hint.grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_x(cont);
hint.grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_top(cont); hint.grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_y(cont);
lv_obj_t * item = lv_obj_get_child_back(cont, NULL); lv_obj_t * item = lv_obj_get_child_back(cont, NULL);
while(item) { while(item) {

View File

@ -1824,8 +1824,8 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area
lv_point_t grid_abs; 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_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); 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.x = pad_left + obj->coords.x1 - lv_obj_get_scroll_x(obj);
grid_abs.y = pad_top + obj->coords.y1 - lv_obj_get_scroll_top(obj); grid_abs.y = pad_top + obj->coords.y1 - lv_obj_get_scroll_y(obj);
uint32_t row; uint32_t row;
uint32_t col; uint32_t col;

View File

@ -419,7 +419,7 @@ lv_coord_t lv_obj_get_x(const lv_obj_t * obj)
lv_obj_t * parent = lv_obj_get_parent(obj); lv_obj_t * parent = lv_obj_get_parent(obj);
if(parent) { 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_scroll_x(parent);
rel_x -= lv_obj_get_style_pad_left(parent, LV_OBJ_PART_MAIN); rel_x -= lv_obj_get_style_pad_left(parent, LV_OBJ_PART_MAIN);
} }
else { else {
@ -444,7 +444,7 @@ lv_coord_t lv_obj_get_y(const lv_obj_t * obj)
lv_obj_t * parent = lv_obj_get_parent(obj); lv_obj_t * parent = lv_obj_get_parent(obj);
if(parent) { 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_scroll_y(parent);
rel_y -= lv_obj_get_style_pad_top(parent, LV_OBJ_PART_MAIN); rel_y -= lv_obj_get_style_pad_top(parent, LV_OBJ_PART_MAIN);
} }
else { else {
@ -638,8 +638,8 @@ void _lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, bool notify_par
lv_coord_t pad_left = lv_obj_get_style_pad_left(parent, LV_OBJ_PART_MAIN); 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); lv_coord_t pad_top = lv_obj_get_style_pad_top(parent, LV_OBJ_PART_MAIN);
x += pad_left + parent->coords.x1 - lv_obj_get_scroll_left(parent); x += pad_left + parent->coords.x1 - lv_obj_get_scroll_x(parent);
y += pad_top + parent->coords.y1 - lv_obj_get_scroll_top(parent); y += pad_top + parent->coords.y1 - lv_obj_get_scroll_y(parent);
} else { } else {
/*If no parent then it's screen but screen can't be on a grid*/ /*If no parent then it's screen but screen can't be on a grid*/
if(LV_COORD_IS_GRID(obj->x_set) || LV_COORD_IS_GRID(obj->x_set)) { if(LV_COORD_IS_GRID(obj->x_set) || LV_COORD_IS_GRID(obj->x_set)) {

View File

@ -102,8 +102,8 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN; if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX; if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
lv_anim_set_time(&a, t); lv_anim_set_time(&a, t);
lv_coord_t sl = lv_obj_get_scroll_left(obj); lv_coord_t sx = lv_obj_get_scroll_x(obj);
lv_anim_set_values(&a, -sl, -sl + x); lv_anim_set_values(&a, -sx, -sx + x);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_x_cb); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_x_cb);
lv_anim_set_path(&a, &path); lv_anim_set_path(&a, &path);
lv_anim_start(&a); lv_anim_start(&a);
@ -114,8 +114,8 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN; if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX; if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
lv_anim_set_time(&a, t); lv_anim_set_time(&a, t);
lv_coord_t st = lv_obj_get_scroll_top(obj); lv_coord_t sy = lv_obj_get_scroll_y(obj);
lv_anim_set_values(&a, -st, -st + y); lv_anim_set_values(&a, -sy, -sy + y);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_y_cb); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_y_cb);
lv_anim_set_path(&a, &path); lv_anim_set_path(&a, &path);
lv_anim_start(&a); lv_anim_start(&a);
@ -144,7 +144,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) 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 + lv_obj_get_scroll_left(obj), 0, anim_en); lv_obj_scroll_by(obj, -x + lv_obj_get_scroll_x(obj), 0, anim_en);
} }
/** /**
@ -154,9 +154,20 @@ 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) 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 + lv_obj_get_scroll_top(obj), anim_en); lv_obj_scroll_by(obj, 0, -y + lv_obj_get_scroll_y(obj), anim_en);
} }
lv_coord_t lv_obj_get_scroll_x(const lv_obj_t * obj)
{
if(obj->spec_attr == NULL) return 0;
return -obj->spec_attr->scroll.x;
}
lv_coord_t lv_obj_get_scroll_y(const lv_obj_t * obj)
{
if(obj->spec_attr == NULL) return 0;
return -obj->spec_attr->scroll.y;
}
/** /**
* Return the height of the area above the parent. * Return the height of the area above the parent.
@ -203,7 +214,7 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
lv_coord_t self_h = _lv_obj_get_self_height(obj); lv_coord_t self_h = _lv_obj_get_self_height(obj);
self_h = self_h - (lv_obj_get_height(obj) - pad_top - pad_bottom); self_h = self_h - (lv_obj_get_height(obj) - pad_top - pad_bottom);
self_h -= lv_obj_get_scroll_top(obj); self_h -= lv_obj_get_scroll_y(obj);
return LV_MATH_MAX(child_res, self_h); return LV_MATH_MAX(child_res, self_h);
} }
@ -216,8 +227,38 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
*/ */
lv_coord_t lv_obj_get_scroll_left(const lv_obj_t * obj) lv_coord_t lv_obj_get_scroll_left(const lv_obj_t * obj)
{ {
if(obj->spec_attr == NULL) return 0; LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
return -obj->spec_attr->scroll.x;
/* Normally can't scroll the object out on the left.
* So simply use the current scroll position as "left size"*/
if(lv_obj_get_base_dir(obj) != LV_BIDI_DIR_RTL) {
if(obj->spec_attr == NULL) return 0;
return -obj->spec_attr->scroll.x;
}
/*With RTL base direction scrolling the left is normal so find the left most coordinate*/
else {
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN);
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN);
lv_coord_t child_res = 0;
lv_obj_t * child = lv_obj_get_child(obj, NULL);
if(child) {
lv_coord_t x1 = LV_COORD_MAX;
while(child) {
x1 = LV_MATH_MIN(x1, child->coords.x1 - lv_obj_get_style_margin_left(child, LV_OBJ_PART_MAIN));
child = lv_obj_get_child(obj, child);
}
child_res = x1;
child_res = (obj->coords.x1 + pad_left) - child_res;
}
lv_coord_t self_w = _lv_obj_get_self_width(obj);
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left);
self_w -= lv_obj_get_scroll_x(obj);
return LV_MATH_MAX(child_res, self_w);
}
} }
/** /**
@ -231,6 +272,8 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj)
{ {
LV_ASSERT_OBJ(obj, LV_OBJX_NAME); LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
/* Unlike `scroll_left`, `scroll_right` should be calculated regardless to the base direction.
* It's because `scroll_x` is always measured from the left side of the object hence there is no information about right side. */
lv_coord_t child_res = LV_COORD_MIN; lv_coord_t child_res = LV_COORD_MIN;
lv_obj_t * child = lv_obj_get_child(obj, NULL); lv_obj_t * child = lv_obj_get_child(obj, NULL);
if(child) { if(child) {
@ -248,10 +291,15 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj)
child_res -= (obj->coords.x2 - pad_right); child_res -= (obj->coords.x2 - pad_right);
lv_coord_t self_w = _lv_obj_get_self_width(obj); lv_coord_t self_w;
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left); /*With RTL base dir self_width is handled in `scroll_right`*/
self_w -= lv_obj_get_scroll_left(obj); if(lv_obj_get_base_dir(obj) != LV_BIDI_DIR_RTL) {
self_w = _lv_obj_get_self_width(obj);
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left);
self_w -= lv_obj_get_scroll_x(obj);
} else {
self_w = LV_COORD_MIN;
}
return LV_MATH_MAX(child_res, self_w); return LV_MATH_MAX(child_res, self_w);
} }
@ -265,10 +313,10 @@ void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end)
{ {
lv_anim_t * a; lv_anim_t * a;
a = lv_anim_get(obj, (lv_anim_exec_xcb_t)scroll_anim_x_cb); a = lv_anim_get(obj, (lv_anim_exec_xcb_t)scroll_anim_x_cb);
end->x = a ? -a->end : lv_obj_get_scroll_left(obj); end->x = a ? -a->end : lv_obj_get_scroll_x(obj);
a = lv_anim_get(obj, (lv_anim_exec_xcb_t)scroll_anim_y_cb); a = lv_anim_get(obj, (lv_anim_exec_xcb_t)scroll_anim_y_cb);
end->y = a ? -a->end : lv_obj_get_scroll_top(obj); end->y = a ? -a->end : lv_obj_get_scroll_y(obj);
} }
lv_dir_t lv_obj_get_scroll_dir(const struct _lv_obj_t * obj) lv_dir_t lv_obj_get_scroll_dir(const struct _lv_obj_t * obj)
@ -323,10 +371,10 @@ void lv_obj_set_snap_align_y(struct _lv_obj_t * obj, lv_scroll_snap_align_t alig
static void scroll_anim_x_cb(lv_obj_t * obj, lv_anim_value_t v) static void scroll_anim_x_cb(lv_obj_t * obj, lv_anim_value_t v)
{ {
_lv_obj_scroll_by_raw(obj, v + lv_obj_get_scroll_left(obj), 0); _lv_obj_scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0);
} }
static void scroll_anim_y_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 + lv_obj_get_scroll_top(obj)); _lv_obj_scroll_by_raw(obj, 0, v + lv_obj_get_scroll_y(obj));
} }

View File

@ -97,7 +97,11 @@ void lv_obj_scroll_to_x(struct _lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t a
void lv_obj_scroll_to_y(struct _lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en); void lv_obj_scroll_to_y(struct _lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en);
lv_coord_t lv_obj_get_scroll_x(const struct _lv_obj_t * obj);
lv_coord_t lv_obj_get_scroll_y(const struct _lv_obj_t * obj);
/** /**
*
* Return the height of the area above the parent. * Return the height of the area above the parent.
* That is the number of pixels the object can be scrolled down. * That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside. * Normally positive but can be negative when scrolled inside.

View File

@ -185,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_obj_get_scroll_top(line); lv_coord_t x_ofs = area.x1 - lv_obj_get_scroll_x(line);
lv_coord_t y_ofs = area.y1 - lv_obj_get_scroll_left(line); lv_coord_t y_ofs = area.y1 - lv_obj_get_scroll_y(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);

View File

@ -817,8 +817,8 @@ static lv_design_res_t lv_table_design(lv_obj_t * table, const lv_area_t * clip_
uint16_t row; uint16_t row;
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_y(table);
lv_coord_t scroll_left = lv_obj_get_scroll_left(table); lv_coord_t scroll_x = lv_obj_get_scroll_x(table);
bool rtl = lv_obj_get_base_dir(table) == LV_BIDI_DIR_RTL ? true : false; bool rtl = lv_obj_get_base_dir(table) == LV_BIDI_DIR_RTL ? true : false;
for(row = 0; row < ext->row_cnt; row++) { for(row = 0; row < ext->row_cnt; row++) {
@ -829,8 +829,8 @@ 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;
if(rtl) cell_area.x1 = table->coords.x2 - bg_right - 1 - scroll_left; if(rtl) cell_area.x1 = table->coords.x2 - bg_right - 1 - scroll_x;
else cell_area.x2 = table->coords.x1 + bg_left - 1 - scroll_left; else cell_area.x2 = table->coords.x1 + bg_left - 1 - scroll_x;
for(col = 0; col < ext->col_cnt; col++) { for(col = 0; col < ext->col_cnt; col++) {