[Bf-blender-cvs] [5ad4713cd8e] master: Spreadsheet: improve separation of drawing and data generation

Jacques Lucke noreply at git.blender.org
Mon Mar 15 12:25:57 CET 2021


Commit: 5ad4713cd8ed2943d96a020ba63ed4d611d14007
Author: Jacques Lucke
Date:   Mon Mar 15 12:19:48 2021 +0100
Branches: master
https://developer.blender.org/rB5ad4713cd8ed2943d96a020ba63ed4d611d14007

Spreadsheet: improve separation of drawing and data generation

This is a refactor and no functional changes are expected.

The goal is to make it simpler to add other data sources without having
to repeat the drawing code everywhere. Also, having the `CellValue` class
allows us to implement filtering and sorting in a more generic way.

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

M	source/blender/editors/space_spreadsheet/CMakeLists.txt
M	source/blender/editors/space_spreadsheet/space_spreadsheet.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_column_layout.hh
M	source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
M	source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.hh

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

diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt
index e270ce9676c..a77e74ffd93 100644
--- a/source/blender/editors/space_spreadsheet/CMakeLists.txt
+++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt
@@ -33,11 +33,13 @@ set(INC
 
 set(SRC
   space_spreadsheet.cc
+  spreadsheet_column_layout.cc
   spreadsheet_draw.cc
   spreadsheet_from_geometry.cc
   spreadsheet_ops.cc
 
   spreadsheet_draw.hh
+  spreadsheet_column_layout.hh
   spreadsheet_from_geometry.hh
   spreadsheet_intern.hh
 )
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index e3ab87583ce..e4bb19d67bf 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -17,6 +17,7 @@
 #include <cstring>
 
 #include "BLI_listbase.h"
+#include "BLI_resource_collector.hh"
 
 #include "BKE_screen.h"
 
@@ -42,6 +43,7 @@
 
 #include "spreadsheet_intern.hh"
 
+#include "spreadsheet_column_layout.hh"
 #include "spreadsheet_from_geometry.hh"
 #include "spreadsheet_intern.hh"
 
@@ -134,39 +136,44 @@ static ID *get_used_id(const bContext *C)
 class FallbackSpreadsheetDrawer : public SpreadsheetDrawer {
 };
 
-static std::unique_ptr<SpreadsheetDrawer> generate_spreadsheet_drawer(const bContext *C)
+static void gather_spreadsheet_columns(const bContext *C,
+                                       SpreadsheetColumnLayout &column_layout,
+                                       blender::ResourceCollector &resources)
 {
   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_drawer_from_geometry_attributes(C, object_eval);
+  return spreadsheet_columns_from_geometry(C, object_eval, column_layout, resources);
 }
 
 static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
 {
   SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
-  std::unique_ptr<SpreadsheetDrawer> drawer = generate_spreadsheet_drawer(C);
-  if (!drawer) {
-    sspreadsheet->runtime->visible_rows = 0;
-    sspreadsheet->runtime->tot_columns = 0;
-    sspreadsheet->runtime->tot_rows = 0;
-    drawer = std::make_unique<FallbackSpreadsheetDrawer>();
-  }
+
+  blender::ResourceCollector resources;
+  SpreadsheetColumnLayout column_layout;
+  gather_spreadsheet_columns(C, column_layout, resources);
+
+  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;
+
+  std::unique_ptr<SpreadsheetDrawer> drawer = spreadsheet_drawer_from_column_layout(column_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_column_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc
new file mode 100644
index 00000000000..c90cf1a2955
--- /dev/null
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc
@@ -0,0 +1,189 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <iomanip>
+#include <sstream>
+
+#include "spreadsheet_column_layout.hh"
+
+#include "DNA_userdef_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "BLF_api.h"
+
+namespace blender::ed::spreadsheet {
+
+class ColumnLayoutDrawer : public SpreadsheetDrawer {
+ private:
+  const SpreadsheetColumnLayout &column_layout_;
+  Vector<int> column_widths_;
+
+ public:
+  ColumnLayoutDrawer(const SpreadsheetColumnLayout &column_layout) : column_layout_(column_layout)
+  {
+    tot_columns = column_layout.columns.size();
+    tot_rows = column_layout.row_indices.size();
+
+    const int fontid = UI_style_get()->widget.uifont_id;
+    /* Use a consistent font size for the width calculation. */
+    BLF_size(fontid, 11 * U.pixelsize, U.dpi);
+
+    /* The width of the index column depends on the maximum row index. */
+    left_column_width = std::to_string(std::max(0, column_layout_.tot_rows - 1)).size() *
+                            BLF_width(fontid, "0", 1) +
+                        UI_UNIT_X * 0.75;
+
+    /* The column widths depend on the column name widths. */
+    const int minimum_column_width = 3 * UI_UNIT_X;
+    const int header_name_padding = UI_UNIT_X;
+    for (const SpreadsheetColumn *column : column_layout_.columns) {
+      StringRefNull name = column->name();
+      const int name_width = BLF_width(fontid, name.data(), name.size());
+      const int width = std::max(name_width + header_name_padding, minimum_column_width);
+      column_widths_.append(width);
+    }
+  }
+
+  void draw_top_row_cell(int column_index, const CellDrawParams &params) const final
+  {
+    const StringRefNull name = column_layout_.columns[column_index]->name();
+    uiBut *but = uiDefIconTextBut(params.block,
+                                  UI_BTYPE_LABEL,
+                                  0,
+                                  ICON_NONE,
+                                  name.c_str(),
+                                  params.xmin,
+                                  params.ymin,
+                                  params.width,
+                                  params.height,
+                                  nullptr,
+                                  0,
+                                  0,
+                                  0,
+                                  0,
+                                  nullptr);
+    /* Center-align column headers. */
+    UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
+    UI_but_drawflag_disable(but, UI_BUT_TEXT_RIGHT);
+  }
+
+  void draw_left_column_cell(int row_index, const CellDrawParams &params) const final
+  {
+    const int real_index = column_layout_.row_indices[row_index];
+    std::string index_str = std::to_string(real_index);
+    uiBut *but = uiDefIconTextBut(params.block,
+                                  UI_BTYPE_LABEL,
+                                  0,
+                                  ICON_NONE,
+                                  index_str.c_str(),
+                                  params.xmin,
+                                  params.ymin,
+                                  params.width,
+                                  params.height,
+                                  nullptr,
+                                  0,
+                                  0,
+                                  0,
+                                  0,
+                                  nullptr);
+    /* Right-align indices. */
+    UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
+    UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
+  }
+
+  void draw_content_cell(int row_index, int column_index, const CellDrawParams &params) const final
+  {
+    const int real_index = column_layout_.row_indices[row_index];
+    const SpreadsheetColumn &column = *column_layout_.columns[column_index];
+    CellValue cell_value;
+    column.get_value(real_index, cell_value);
+
+    if (std::holds_alternative<int>(cell_value.value)) {
+      const int value = std::get<int>(cell_value.value);
+      const std::string value_str = std::to_string(value);
+      uiDefIconTextBut(params.block,
+                       UI_BTYPE_LABEL,
+                       0,
+                       ICON_NONE,
+                       value_str.c_str(),
+                       params.xmin,
+                       params.ymin,
+                       params.width,
+                       params.height,
+                       nullptr,
+                       0,
+                       0,
+                       0,
+                       0,
+                       nullptr);
+    }
+    else if (std::holds_alternative<float>(cell_value.value)) {
+      const float value = std::get<float>(cell_value.value);
+      std::stringstream ss;
+      ss << std::fixed << std::setprecision(3) << value;
+      const std::string value_str = ss.str();
+      uiDefIconTextBut(params.block,
+                       UI_BTYPE_LABEL,
+                       0,
+                       ICON_NONE,
+                       value_str.c_str(),
+                       params.xmin,
+                       params.ymin,
+                       params.width,
+                       params.height,
+                       nullptr,
+                       0,
+                       0,
+                       0,
+                       0,
+                       nullptr);
+    }
+    else if (std::holds_alternative<bool>(cell_value.value)) {
+      const bool value = std::get<bool>(cell_value.value);
+      const int icon = value ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+      uiDefIconTextBut(params.block,
+                       UI_BTYPE_LABEL,
+                       0,
+                       icon,
+                       "",
+                       params.xmin,
+                       params.ymin,
+   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list