Spreadsheet: support restoring temporarily unavailable data columns

Previously, columns were removed from a table in the spreadsheet if they are not
available anymore. This also meant that their position and width was lost. When
the same column became available again, it was inserted at the end.

This patch makes it so that each table also remembers the columns that are not
available currently (and flags them accordingly). This way, the position and
width can be restored once the data becomes available again.

Pull Request: https://projects.blender.org/blender/blender/pulls/139440
This commit is contained in:
Jacques Lucke
2025-05-26 19:16:20 +02:00
parent 68ddf4125c
commit 66a5469bcf
4 changed files with 47 additions and 13 deletions

View File

@@ -384,15 +384,11 @@ static void update_visible_columns(SpreadsheetTable &table, DataSource &data_sou
Set<std::reference_wrapper<const SpreadsheetColumnID>> handled_columns;
Vector<SpreadsheetColumn *, 32> new_columns;
for (SpreadsheetColumn *column : Span{table.columns, table.num_columns}) {
const bool still_exists = data_source.get_column_values(*column->id) != nullptr;
if (still_exists) {
if (handled_columns.add(*column->id)) {
new_columns.append(column);
continue;
}
if (handled_columns.add(*column->id)) {
const bool has_data = data_source.get_column_values(*column->id) != nullptr;
SET_FLAG_FROM_TEST(column->flag, !has_data, SPREADSHEET_COLUMN_FLAG_UNAVAILABLE);
new_columns.append(column);
}
/* Free columns that don't exist anymore or are duplicates for some reason. */
spreadsheet_column_free(column);
}
data_source.foreach_default_column_ids(
@@ -468,8 +464,9 @@ static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
for (SpreadsheetColumn *column : Span{table->columns, table->num_columns}) {
std::unique_ptr<ColumnValues> values_ptr = data_source->get_column_values(*column->id);
/* Should have been removed before if it does not exist anymore. */
BLI_assert(values_ptr);
if (!values_ptr) {
continue;
}
const ColumnValues *values = scope.add(std::move(values_ptr));
if (column->width <= 0.0f) {

View File

@@ -196,6 +196,9 @@ SpreadsheetColumn *find_hovered_column_edge(SpaceSpreadsheet &sspreadsheet,
}
const float cursor_x_view = UI_view2d_region_to_view_x(&region.v2d, cursor_re.x);
for (SpreadsheetColumn *column : Span{table->columns, table->num_columns}) {
if (column->flag & SPREADSHEET_COLUMN_FLAG_UNAVAILABLE) {
continue;
}
if (std::abs(cursor_x_view - column->runtime->right_x) < SPREADSHEET_EDGE_ACTION_ZONE) {
return column;
}
@@ -213,6 +216,9 @@ SpreadsheetColumn *find_hovered_column(SpaceSpreadsheet &sspreadsheet,
}
const float cursor_x_view = UI_view2d_region_to_view_x(&region.v2d, cursor_re.x);
for (SpreadsheetColumn *column : Span{table->columns, table->num_columns}) {
if (column->flag & SPREADSHEET_COLUMN_FLAG_UNAVAILABLE) {
continue;
}
if (cursor_x_view > column->runtime->left_x && cursor_x_view <= column->runtime->right_x) {
return column;
}
@@ -321,6 +327,26 @@ struct ReorderColumnData {
View2DEdgePanData pan_data{};
};
static std::optional<int> find_first_available_column_index(const SpreadsheetTable &table)
{
for (int i = 0; i < table.num_columns; i++) {
if (!(table.columns[i]->flag & SPREADSHEET_COLUMN_FLAG_UNAVAILABLE)) {
return i;
}
}
return std::nullopt;
}
static std::optional<int> find_last_available_column_index(const SpreadsheetTable &table)
{
for (int i = table.num_columns - 1; i >= 0; i--) {
if (!(table.columns[i]->flag & SPREADSHEET_COLUMN_FLAG_UNAVAILABLE)) {
return i;
}
}
return std::nullopt;
}
static wmOperatorStatus reorder_columns_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceSpreadsheet &sspreadsheet = *CTX_wm_space_spreadsheet(C);
@@ -384,10 +410,10 @@ static wmOperatorStatus reorder_columns_modal(bContext *C, wmOperator *op, const
}
else {
if (cursor_re.x > sspreadsheet.runtime->left_column_width) {
new_index = columns.size() - 1;
new_index = *find_last_available_column_index(table);
}
else {
new_index = 0;
new_index = *find_first_available_column_index(table);
}
}

View File

@@ -1019,6 +1019,15 @@ typedef enum eSpreadsheetColumnValueType {
SPREADSHEET_VALUE_TYPE_FLOAT4X4 = 12,
} eSpreadsheetColumnValueType;
typedef enum eSpreadsheetColumnFlag {
/**
* There is no data for this column currently, so it's not displayed. However, it is still kept
* around so that the column remembers its position and width when the data becomes available
* again.
*/
SPREADSHEET_COLUMN_FLAG_UNAVAILABLE = (1 << 0),
} eSpreadsheetColumnFlag;
typedef enum eSpreadsheetTableIDType {
/** This table uses the #SpreadsheetTableIDGeometry key. */
SPREADSHEET_TABLE_ID_TYPE_GEOMETRY = 0,

View File

@@ -1091,7 +1091,9 @@ typedef struct SpreadsheetColumn {
* #eSpreadsheetColumnValueType.
*/
uint8_t data_type;
char _pad0[3];
char _pad0[1];
/** #eSpreadsheetColumnFlag. */
uint16_t flag;
/** Width in SPREADSHEET_WIDTH_UNIT. */
float width;