[Bf-blender-cvs] [75491fe1002] master: Spreadsheet: persistent column storage and data source

Jacques Lucke noreply at git.blender.org
Fri Apr 9 10:21:34 CEST 2021


Commit: 75491fe1002122f19fc9fe8eae941a406b81706a
Author: Jacques Lucke
Date:   Fri Apr 9 10:20:46 2021 +0200
Branches: master
https://developer.blender.org/rB75491fe1002122f19fc9fe8eae941a406b81706a

Spreadsheet: persistent column storage and data source

A `DataSource` provides columns for the spreadsheet to display.
Every column has a SpreadsheetColumnID as identifier. Columns
are not generated eagerly anymore, instead the main spreadsheet
code can request a column from a data source with an column
identifier. The column identifiers can be stored in DNA and allow us
to store persistent data per column.

On the user level the only thing that changes is that columns are
not shown in alphabetical order anymore. Instead, new columns
are always added on the left. The behavior can be changed,
however I'd prefer not to automate this too much currently. I think
we should just add operators to hide/reorder/resize columns soonish.

Differential Revision: https://developer.blender.org/D10901

===================================================================

M	source/blender/blenkernel/intern/screen.c
M	source/blender/editors/space_spreadsheet/CMakeLists.txt
M	source/blender/editors/space_spreadsheet/space_spreadsheet.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
A	source/blender/editors/space_spreadsheet/spreadsheet_column.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_column.hh
D	source/blender/editors/space_spreadsheet/spreadsheet_column_layout.hh
A	source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh
R067	source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.hh	source/blender/editors/space_spreadsheet/spreadsheet_data_source.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_data_source.hh
A	source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh
D	source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
R078	source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc	source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_layout.hh
M	source/blender/makesdna/DNA_space_types.h

===================================================================

diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 9617ef68a7d..d5540a3cfd3 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -1350,6 +1350,13 @@ static void write_area(BlendWriter *writer, ScrArea *area)
     }
     else if (sl->spacetype == SPACE_SPREADSHEET) {
       BLO_write_struct(writer, SpaceSpreadsheet, sl);
+
+      SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
+      LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) {
+        BLO_write_struct(writer, SpreadsheetColumn, column);
+        BLO_write_struct(writer, SpreadsheetColumnID, column->id);
+        BLO_write_string(writer, column->id->name);
+      }
     }
   }
 }
@@ -1702,6 +1709,12 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
       SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
 
       sspreadsheet->runtime = NULL;
+
+      BLO_read_list(reader, &sspreadsheet->columns);
+      LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) {
+        BLO_read_data_address(reader, &column->id);
+        BLO_read_data_address(reader, &column->id->name);
+      }
     }
   }
 
diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt
index 1343ab8d851..5aa708b10c0 100644
--- a/source/blender/editors/space_spreadsheet/CMakeLists.txt
+++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt
@@ -33,15 +33,21 @@ set(INC
 
 set(SRC
   space_spreadsheet.cc
-  spreadsheet_column_layout.cc
+  spreadsheet_column.cc
+  spreadsheet_data_source.cc
+  spreadsheet_data_source_geometry.cc
   spreadsheet_draw.cc
-  spreadsheet_from_geometry.cc
+  spreadsheet_layout.cc
   spreadsheet_ops.cc
 
-  spreadsheet_column_layout.hh
+  spreadsheet_cell_value.hh
+  spreadsheet_column.hh
+  spreadsheet_data_source.hh
+  spreadsheet_data_source_geometry.hh
+  spreadsheet_column_values.hh
   spreadsheet_draw.hh
-  spreadsheet_from_geometry.hh
   spreadsheet_intern.hh
+  spreadsheet_layout.hh
 )
 
 set(LIB
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index 403e6cd6206..d34b625293c 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -17,7 +17,6 @@
 #include <cstring>
 
 #include "BLI_listbase.h"
-#include "BLI_resource_scope.hh"
 
 #include "BKE_screen.h"
 
@@ -41,12 +40,15 @@
 #include "WM_api.h"
 #include "WM_types.h"
 
+#include "BLF_api.h"
+
 #include "spreadsheet_intern.hh"
 
-#include "spreadsheet_column_layout.hh"
-#include "spreadsheet_from_geometry.hh"
+#include "spreadsheet_data_source_geometry.hh"
 #include "spreadsheet_intern.hh"
+#include "spreadsheet_layout.hh"
 
+using namespace blender;
 using namespace blender::ed::spreadsheet;
 
 static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
@@ -85,6 +87,10 @@ static void spreadsheet_free(SpaceLink *sl)
 {
   SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
   MEM_SAFE_FREE(sspreadsheet->runtime);
+
+  LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) {
+    spreadsheet_column_free(column);
+  }
 }
 
 static void spreadsheet_init(wmWindowManager *UNUSED(wm), ScrArea *area)
@@ -94,6 +100,10 @@ static void spreadsheet_init(wmWindowManager *UNUSED(wm), ScrArea *area)
     sspreadsheet->runtime = (SpaceSpreadsheet_Runtime *)MEM_callocN(
         sizeof(SpaceSpreadsheet_Runtime), __func__);
   }
+  LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) {
+    spreadsheet_column_free(column);
+  }
+  BLI_listbase_clear(&sspreadsheet->columns);
 }
 
 static SpaceLink *spreadsheet_duplicate(SpaceLink *sl)
@@ -102,6 +112,12 @@ static SpaceLink *spreadsheet_duplicate(SpaceLink *sl)
   SpaceSpreadsheet *sspreadsheet_new = (SpaceSpreadsheet *)MEM_dupallocN(sspreadsheet_old);
   sspreadsheet_new->runtime = (SpaceSpreadsheet_Runtime *)MEM_dupallocN(sspreadsheet_old->runtime);
 
+  BLI_listbase_clear(&sspreadsheet_new->columns);
+  LISTBASE_FOREACH (SpreadsheetColumn *, src_column, &sspreadsheet_old->columns) {
+    SpreadsheetColumn *new_column = spreadsheet_column_copy(src_column);
+    BLI_addtail(&sspreadsheet_new->columns, new_column);
+  }
+
   return (SpaceLink *)sspreadsheet_new;
 }
 
@@ -133,47 +149,122 @@ static ID *get_used_id(const bContext *C)
   return (ID *)active_object;
 }
 
-class FallbackSpreadsheetDrawer : public SpreadsheetDrawer {
-};
-
-static void gather_spreadsheet_columns(const bContext *C,
-                                       SpreadsheetColumnLayout &column_layout,
-                                       blender::ResourceScope &scope)
+static std::unique_ptr<DataSource> get_data_source(const bContext *C)
 {
   Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
   ID *used_id = get_used_id(C);
   if (used_id == nullptr) {
-    return;
+    return {};
   }
   const ID_Type id_type = GS(used_id->name);
   if (id_type != ID_OB) {
-    return;
+    return {};
   }
   Object *object_orig = (Object *)used_id;
   if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD)) {
-    return;
+    return {};
   }
   Object *object_eval = DEG_get_evaluated_object(depsgraph, object_orig);
   if (object_eval == nullptr) {
-    return;
+    return {};
   }
 
-  return spreadsheet_columns_from_geometry(C, object_eval, column_layout, scope);
+  return data_source_from_geometry(C, object_eval);
+}
+
+static float get_column_width(const ColumnValues &values)
+{
+  if (values.default_width > 0) {
+    return values.default_width * UI_UNIT_X;
+  }
+  const int fontid = UI_style_get()->widget.uifont_id;
+  const int widget_points = UI_style_get_dpi()->widget.points;
+  BLF_size(fontid, widget_points * U.pixelsize, U.dpi);
+  const StringRefNull name = values.name();
+  const float name_width = BLF_width(fontid, name.data(), name.size());
+  return std::max<float>(name_width + UI_UNIT_X, 3 * UI_UNIT_X);
+}
+
+static int get_index_column_width(const int tot_rows)
+{
+  const int fontid = UI_style_get()->widget.uifont_id;
+  BLF_size(fontid, UI_style_get_dpi()->widget.points * U.pixelsize, U.dpi);
+  return std::to_string(std::max(0, tot_rows - 1)).size() * BLF_width(fontid, "0", 1) +
+         UI_UNIT_X * 0.75;
+}
+
+static void update_visible_columns(ListBase &columns, DataSource &data_source)
+{
+  Set<SpreadsheetColumnID> used_ids;
+  LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &columns) {
+    std::unique_ptr<ColumnValues> values = data_source.get_column_values(*column->id);
+    /* Remove columns that don't exist anymore. */
+    if (!values) {
+      BLI_remlink(&columns, column);
+      spreadsheet_column_free(column);
+      continue;
+    }
+
+    used_ids.add(*column->id);
+  }
+
+  data_source.foreach_default_column_ids([&](const SpreadsheetColumnID &column_id) {
+    std::unique_ptr<ColumnValues> values = data_source.get_column_values(column_id);
+    if (values) {
+      if (used_ids.add(column_id)) {
+        SpreadsheetColumnID *new_id = spreadsheet_column_id_copy(&column_id);
+        SpreadsheetColumn *new_column = spreadsheet_column_new(new_id);
+        BLI_addtail(&columns, new_column);
+      }
+    }
+  });
 }
 
 static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
 {
   SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
 
-  blender::ResourceScope scope;
-  SpreadsheetColumnLayout column_layout;
-  gather_spreadsheet_columns(C, column_layout, scope);
+  std::unique_ptr<DataSource> data_source = get_data_source(C);
+  if (!data_source) {
+    data_source = std::make_unique<DataSource>();
+  }
+
+  update_visible_columns(sspreadsheet->columns, *data_source);
+
+  SpreadsheetLayout spreadsheet_layout;
+  ResourceScope scope;
+
+  LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->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);
+    const ColumnValues *values = scope.add(std::move(values_ptr), __func__);
+    const int width = get_column_width(*values);
+    spreadsheet_layout.columns.append({values, width});
+  }
+
+  const int tot_rows = data_source->tot_rows();
+  spreadsheet_layout.index_column_width = get_index_column_width(tot_rows);
+  spreadsheet_layout.row_indices = IndexRange(tot_rows).as_span();
+
+  if (const GeometryDataSource *geometry_data_source = dynamic_cast<const GeometryDataSource *>(
+          data_source.get())) {
+    Object *object_eval = geometry_data_source->object_eval();
+    Object *object_orig = DEG_get_original_object(object_eval);
+    if (object_orig->type == OB_MESH) {
+      if (object_orig->mode == OB_MODE_EDIT) {
+        if (sspreadsheet->filter_flag & SPREADSHEET_FILTER_SELECTED_ONLY) {
+          spreadsheet_layout.row_indices = geometry_data_source->get_selected_element_indices();
+        }
+      }
+    }
+  }
 
-  sspreadsheet->runtime->visible_rows = column_layout.row_indices.size();
-  sspreadsheet->runtime->tot_columns = column_layout.columns.size();
-  sspreadsheet->runtime->tot_rows = column_layout.tot_rows;
+  sspreadsheet->runtime->tot_columns = spreadsheet_layout.columns.size();
+  sspreadsheet->runtime->tot_rows = tot_rows;
+  sspreadsheet->runtime->visible_rows = spreadsheet_layout.row_indices.size();
 
-  std::unique_ptr<SpreadsheetDrawer> drawer = spreadsheet_drawer_from_column_layout(column_layout);
+  std::unique_ptr<SpreadsheetDrawer> drawer = spreadsheet_drawer_from_layout(spreadsheet_layout);
   draw_spreadsheet_in_region(C, region, *drawer);
 
   /* Tag footer for redraw, because the main region updates data for the footer. */
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
new file mode 100644
index 00000000000..0627cff7abc
--- /dev/null
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
@@ -0,0 +1,51 @@
+/*
+ * 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list