diff --git a/src/widgets/table/lv_table.c b/src/widgets/table/lv_table.c index e5c6786d17..edfde807b7 100644 --- a/src/widgets/table/lv_table.c +++ b/src/widgets/table/lv_table.c @@ -1091,18 +1091,35 @@ static void get_cell_area(lv_obj_t * obj, uint32_t row, uint32_t col, lv_area_t for(c = 0; c < col; c++) { area->x1 += table->col_w[c]; } + /* Traverse the current row from the first until the penultimate column. + * Increment the offset if the cell has the LV_TABLE_CELL_CTRL_MERGE_RIGHT control, + * exit the traversal when the current cell control is not LV_TABLE_CELL_CTRL_MERGE_RIGHT */ + uint32_t col_merge = 0; + int32_t offset = 0; + for(col_merge = 0; col_merge + col < table->col_cnt - 1; col_merge++) { + lv_table_cell_t * next_cell_data = table->cell_data[row * table->col_cnt + col_merge]; + if(is_cell_empty(next_cell_data)) break; + + lv_table_cell_ctrl_t ctrl = (lv_table_cell_ctrl_t) next_cell_data->ctrl; + if(ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) { + offset += table->col_w[col + col_merge + 1]; + } + else { + break; + } + } bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL; if(rtl) { area->x1 += lv_obj_get_scroll_x(obj); int32_t w = lv_obj_get_width(obj); area->x2 = w - area->x1 - lv_obj_get_style_pad_right(obj, 0); - area->x1 = area->x2 - table->col_w[col]; + area->x1 = area->x2 - (table->col_w[col] + offset); } else { area->x1 -= lv_obj_get_scroll_x(obj); area->x1 += lv_obj_get_style_pad_left(obj, 0); - area->x2 = area->x1 + table->col_w[col] - 1; + area->x2 = area->x1 + (table->col_w[col] + offset) - 1; } uint32_t r; diff --git a/tests/src/test_cases/widgets/test_table.c b/tests/src/test_cases/widgets/test_table.c index 0564ebebe6..4bbfe32791 100644 --- a/tests/src/test_cases/widgets/test_table.c +++ b/tests/src/test_cases/widgets/test_table.c @@ -6,6 +6,10 @@ static lv_obj_t * scr = NULL; static lv_obj_t * table = NULL; +static lv_area_t g_inv_area; +static int32_t g_inv_count; + +static void invalidate_area_event_cb(lv_event_t * e); void setUp(void) { @@ -16,6 +20,7 @@ void setUp(void) void tearDown(void) { lv_obj_clean(lv_screen_active()); + lv_display_remove_event_cb_with_user_data(lv_display_get_default(), invalidate_area_event_cb, NULL); } void test_table_should_set_row_count_to_zero(void) @@ -169,6 +174,13 @@ static void draw_part_event_cb(lv_event_t * e) } } +static void invalidate_area_event_cb(lv_event_t * e) +{ + lv_area_t * inv = lv_event_get_param(e); + lv_area_copy(&g_inv_area, inv); + g_inv_count++; +} + void test_table_rendering(void) { lv_obj_center(table); @@ -203,6 +215,31 @@ void test_table_rendering(void) lv_table_set_cell_value_fmt(table, 4, 3, "crop crop crop crop crop crop crop crop "); TEST_ASSERT_EQUAL_SCREENSHOT("widgets/table_1.png"); + + lv_refr_now(NULL); + lv_area_set(&g_inv_area, 0, 0, 0, 0); + g_inv_count = 0; + lv_display_add_event_cb(lv_display_get_default(), invalidate_area_event_cb, LV_EVENT_INVALIDATE_AREA, NULL); + lv_table_set_cell_value(table, 1, 0, "changed"); + TEST_ASSERT_EQUAL_INT32(1, g_inv_count); + int32_t merged_col_width = lv_table_get_column_width(table, 0) + lv_table_get_column_width(table, 1) + + lv_table_get_column_width(table, 2) + lv_table_get_column_width(table, 3) + + lv_table_get_column_width(table, 4); + +#if LV_DRAW_TRANSFORM_USE_MATRIX + /** + * From `lv_obj_pos`: + * + * When using the global matrix, the vertex coordinates of clip_area lose precision after transformation, + * which can be solved by expanding the redrawing area. + * lv_area_increase(&area_tmp, 5, 5); + * + * This accomodates for this specific calculation. + */ + TEST_ASSERT_EQUAL_INT32(lv_area_get_width(&g_inv_area), merged_col_width + 10); +#else + TEST_ASSERT_EQUAL_INT32(lv_area_get_width(&g_inv_area), merged_col_width); +#endif } /* See #3120 for context */