Blender V4.5
space_spreadsheet.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cstring>
6#include <fmt/format.h>
7
8#include "BLI_listbase.h"
9#include "BLI_string.h"
10
11#include "BKE_screen.hh"
12#include "BKE_viewer_path.hh"
13
14#include "ED_screen.hh"
15#include "ED_space_api.hh"
16#include "ED_spreadsheet.hh"
17#include "ED_viewer_path.hh"
18
19#include "DNA_scene_types.h"
20#include "DNA_screen_types.h"
21#include "DNA_space_types.h"
22
23#include "MEM_guardedalloc.h"
24
25#include "UI_interface.hh"
26#include "UI_resources.hh"
27#include "UI_view2d.hh"
28
29#include "BLO_read_write.hh"
30
32
33#include "WM_api.hh"
34#include "WM_types.hh"
35
36#include "BLT_translation.hh"
37
38#include "BLF_api.hh"
39
40#include "spreadsheet_column.hh"
42#include "spreadsheet_intern.hh"
43#include "spreadsheet_layout.hh"
46#include "spreadsheet_table.hh"
47
48#include <sstream>
49
51
52static SpaceLink *spreadsheet_create(const ScrArea * /*area*/, const Scene * /*scene*/)
53{
54 SpaceSpreadsheet *spreadsheet_space = MEM_callocN<SpaceSpreadsheet>("spreadsheet space");
55 spreadsheet_space->spacetype = SPACE_SPREADSHEET;
56
58 spreadsheet_space->filter_flag = SPREADSHEET_FILTER_ENABLE;
59
60 {
61 /* Header. */
62 ARegion *region = BKE_area_region_new();
63 BLI_addtail(&spreadsheet_space->regionbase, region);
66 }
67
68 {
69 /* Footer. */
70 ARegion *region = BKE_area_region_new();
71 BLI_addtail(&spreadsheet_space->regionbase, region);
74 }
75
76 {
77 /* Dataset Region */
78 ARegion *region = BKE_area_region_new();
79 BLI_addtail(&spreadsheet_space->regionbase, region);
80 region->regiontype = RGN_TYPE_TOOLS;
81 region->alignment = RGN_ALIGN_LEFT;
82 }
83
84 {
85 /* Properties region. */
86 ARegion *region = BKE_area_region_new();
87 BLI_addtail(&spreadsheet_space->regionbase, region);
88 region->regiontype = RGN_TYPE_UI;
89 region->alignment = RGN_ALIGN_RIGHT;
90 region->flag = RGN_FLAG_HIDDEN;
91 }
92
93 {
94 /* Main window. */
95 ARegion *region = BKE_area_region_new();
96 BLI_addtail(&spreadsheet_space->regionbase, region);
98 }
99
100 return (SpaceLink *)spreadsheet_space;
101}
102
104{
105 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
106
107 MEM_delete(sspreadsheet->runtime);
108
109 LISTBASE_FOREACH_MUTABLE (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
110 spreadsheet_row_filter_free(row_filter);
111 }
112 for (const int i : IndexRange(sspreadsheet->num_tables)) {
113 spreadsheet_table_free(sspreadsheet->tables[i]);
114 }
115 MEM_SAFE_FREE(sspreadsheet->tables);
117}
118
119static void spreadsheet_init(wmWindowManager * /*wm*/, ScrArea *area)
120{
121 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)area->spacedata.first;
122 if (sspreadsheet->runtime == nullptr) {
123 sspreadsheet->runtime = MEM_new<SpaceSpreadsheet_Runtime>(__func__);
124 }
125}
126
128{
129 const SpaceSpreadsheet *sspreadsheet_old = (SpaceSpreadsheet *)sl;
130 SpaceSpreadsheet *sspreadsheet_new = (SpaceSpreadsheet *)MEM_dupallocN(sspreadsheet_old);
131 if (sspreadsheet_old->runtime) {
132 sspreadsheet_new->runtime = MEM_new<SpaceSpreadsheet_Runtime>(__func__,
133 *sspreadsheet_old->runtime);
134 }
135 else {
136 sspreadsheet_new->runtime = MEM_new<SpaceSpreadsheet_Runtime>(__func__);
137 }
138
139 BLI_listbase_clear(&sspreadsheet_new->row_filters);
140 LISTBASE_FOREACH (const SpreadsheetRowFilter *, src_filter, &sspreadsheet_old->row_filters) {
141 SpreadsheetRowFilter *new_filter = spreadsheet_row_filter_copy(src_filter);
142 BLI_addtail(&sspreadsheet_new->row_filters, new_filter);
143 }
144 sspreadsheet_new->num_tables = sspreadsheet_old->num_tables;
145 sspreadsheet_new->tables = MEM_calloc_arrayN<SpreadsheetTable *>(sspreadsheet_old->num_tables,
146 __func__);
147 for (const int i : IndexRange(sspreadsheet_old->num_tables)) {
148 sspreadsheet_new->tables[i] = spreadsheet_table_copy(*sspreadsheet_old->tables[i]);
149 }
150
152 sspreadsheet_old->geometry_id);
153 return (SpaceLink *)sspreadsheet_new;
154}
155
156static void spreadsheet_keymap(wmKeyConfig *keyconf)
157{
158 /* Entire editor only. */
159 WM_keymap_ensure(keyconf, "Spreadsheet Generic", SPACE_SPREADSHEET, RGN_TYPE_WINDOW);
160}
161
162static void spreadsheet_id_remap(ScrArea * /*area*/,
163 SpaceLink *slink,
164 const blender::bke::id::IDRemapper &mappings)
165{
166 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)slink;
167 spreadsheet_table_id_remap_id(sspreadsheet->geometry_id.base, mappings);
168 for (const int i : IndexRange(sspreadsheet->num_tables)) {
169 spreadsheet_table_remap_id(*sspreadsheet->tables[i], mappings);
170 }
171}
172
174{
175 SpaceSpreadsheet *sspreadsheet = reinterpret_cast<SpaceSpreadsheet *>(space_link);
177 for (const int i : IndexRange(sspreadsheet->num_tables)) {
178 spreadsheet_table_foreach_id(*sspreadsheet->tables[i], data);
179 }
180}
181
183{
189 region->v2d.minzoom = region->v2d.maxzoom = 1.0f;
190
191 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
192
193 {
194 wmKeyMap *keymap = WM_keymap_ensure(
195 wm->defaultconf, "View2D Buttons List", SPACE_EMPTY, RGN_TYPE_WINDOW);
196 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
197 }
198 {
199 wmKeyMap *keymap = WM_keymap_ensure(
200 wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, RGN_TYPE_WINDOW);
201 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
202 }
203}
204
205ID *get_current_id(const SpaceSpreadsheet *sspreadsheet)
206{
208 return nullptr;
209 }
210 ViewerPathElem *root_context = static_cast<ViewerPathElem *>(
211 sspreadsheet->geometry_id.viewer_path.path.first);
212 if (root_context->type != VIEWER_PATH_ELEM_TYPE_ID) {
213 return nullptr;
214 }
215 IDViewerPathElem *id_elem = reinterpret_cast<IDViewerPathElem *>(root_context);
216 return id_elem->id;
217}
218
219static void view_active_object(const bContext *C, SpaceSpreadsheet *sspreadsheet)
220{
223 if (ob == nullptr) {
224 return;
225 }
227 id_elem->id = &ob->id;
228 BLI_addtail(&sspreadsheet->geometry_id.viewer_path.path, id_elem);
230}
231
233{
235
237 Object *active_object = CTX_data_active_object(C);
239 sspreadsheet->geometry_id.viewer_path);
243 if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) {
244 if (context_object == nullptr) {
245 /* Object is not available anymore, so clear the pinning. */
246 sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED;
247 }
248 else {
249 /* The object is still pinned, do nothing. */
250 break;
251 }
252 }
253 else {
254 if (active_object != context_object) {
255 /* The active object has changed, so view the new active object. */
256 view_active_object(C, sspreadsheet);
257 }
258 else {
259 /* Nothing changed. */
260 break;
261 }
262 }
263 break;
264 }
266 WorkSpace *workspace = CTX_wm_workspace(C);
267 if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) {
268 const std::optional<ViewerPathForGeometryNodesViewer> parsed_path =
270 sspreadsheet->geometry_id.viewer_path);
271 if (parsed_path.has_value()) {
273 /* The pinned path is still valid, do nothing. */
274 break;
275 }
276 /* The pinned path does not exist anymore, clear pinning. */
277 sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED;
278 }
279 else {
280 /* Unknown pinned path, clear pinning. */
281 sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED;
282 }
283 }
284 /* Now try to update the viewer path from the workspace. */
285 const std::optional<ViewerPathForGeometryNodesViewer> workspace_parsed_path =
287 if (workspace_parsed_path.has_value()) {
289 &workspace->viewer_path,
291 {
292 /* Nothing changed. */
293 break;
294 }
295 /* Update the viewer path from the workspace. */
297 BKE_viewer_path_copy(&sspreadsheet->geometry_id.viewer_path, &workspace->viewer_path);
298 }
299 else {
300 /* No active viewer node, change back to showing evaluated active object. */
302 view_active_object(C, sspreadsheet);
303 }
304
305 break;
306 }
307 }
308}
309
311 const Depsgraph *depsgraph)
312{
313 ID *used_id = get_current_id(sspreadsheet);
314 if (used_id == nullptr) {
315 return nullptr;
316 }
317 const ID_Type id_type = GS(used_id->name);
318 if (id_type != ID_OB) {
319 return nullptr;
320 }
321 Object *object_orig = (Object *)used_id;
322 if (!ELEM(object_orig->type,
323 OB_MESH,
325 OB_VOLUME,
327 OB_FONT,
328 OB_CURVES,
330 {
331 return nullptr;
332 }
333
334 Object *object_eval = DEG_get_evaluated(depsgraph, object_orig);
335 if (object_eval == nullptr) {
336 return nullptr;
337 }
338
339 return object_eval;
340}
341
342std::unique_ptr<DataSource> get_data_source(const bContext &C)
343{
346
347 Object *object_eval = spreadsheet_get_object_eval(sspreadsheet, depsgraph);
348 if (object_eval) {
349 return data_source_from_geometry(&C, object_eval);
350 }
351 return {};
352}
353
355{
356 return &sspreadsheet.geometry_id.base;
357}
358
360{
361 return const_cast<SpreadsheetTable *>(
362 get_active_table(const_cast<const SpaceSpreadsheet &>(sspreadsheet)));
363}
364
366{
367 const SpreadsheetTableID *active_table_id = get_active_table_id(sspreadsheet);
368 if (!active_table_id) {
369 return nullptr;
370 }
371 return spreadsheet_table_find(sspreadsheet, *active_table_id);
372}
373
374static int get_index_column_width(const int tot_rows)
375{
376 const int fontid = BLF_default();
377 BLF_size(fontid, UI_style_get_dpi()->widget.points * UI_SCALE_FAC);
378 return std::to_string(std::max(0, tot_rows - 1)).size() * BLF_width(fontid, "0", 1) +
379 UI_UNIT_X * 0.75;
380}
381
382static void update_visible_columns(SpreadsheetTable &table, DataSource &data_source)
383{
386 for (SpreadsheetColumn *column : Span{table.columns, table.num_columns}) {
387 if (handled_columns.add(*column->id)) {
388 const bool has_data = data_source.get_column_values(*column->id) != nullptr;
390 new_columns.append(column);
391 }
392 }
393
394 data_source.foreach_default_column_ids(
395 [&](const SpreadsheetColumnID &column_id, const bool is_extra) {
396 if (handled_columns.contains(column_id)) {
397 return;
398 }
399 std::unique_ptr<ColumnValues> values = data_source.get_column_values(column_id);
400 if (!values) {
401 return;
402 }
403 table.column_use_clock++;
405 if (is_extra) {
406 new_columns.insert(0, column);
407 }
408 else {
409 new_columns.append(column);
410 }
411 handled_columns.add(*column->id);
412 });
413
414 if (Span(table.columns, table.num_columns) == new_columns.as_span()) {
415 /* Nothing changed. */
416 return;
417 }
418
419 /* Update last used times of the columns to support garbage collection. */
420 for (SpreadsheetColumn *column : new_columns) {
421 const bool clock_was_reset = table.column_use_clock < column->last_used;
422 if (clock_was_reset || column->is_available()) {
423 column->last_used = table.column_use_clock;
424 }
425 }
426
427 /* Update the stored column pointers. */
428 MEM_SAFE_FREE(table.columns);
429 table.columns = MEM_calloc_arrayN<SpreadsheetColumn *>(new_columns.size(), __func__);
430 table.num_columns = new_columns.size();
431 std::copy_n(new_columns.begin(), new_columns.size(), table.columns);
432
433 /* Remove columns that have not been used for a while when there are too many. */
435}
436
437static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
438{
441
442 std::unique_ptr<DataSource> data_source = get_data_source(*C);
443 if (!data_source) {
444 data_source = std::make_unique<DataSource>();
445 }
446
447 const SpreadsheetTableID *active_table_id = get_active_table_id(*sspreadsheet);
448 SpreadsheetTable *table = spreadsheet_table_find(*sspreadsheet, *active_table_id);
449 if (!table) {
450 spreadsheet_table_remove_unused(*sspreadsheet);
451 table = spreadsheet_table_new(spreadsheet_table_id_copy(*active_table_id));
452 spreadsheet_table_add(*sspreadsheet, table);
453 }
454 if (table) {
455 /* Move to the front of the tables list to make it cheaper to find the table in future. */
456 spreadsheet_table_move_to_front(*sspreadsheet, *table);
457 }
458
459 /* Update the last used time on the table. */
460 if (table->last_used < sspreadsheet->table_use_clock || sspreadsheet->table_use_clock == 0) {
461 sspreadsheet->table_use_clock++;
462 /* Handle clock overflow by just resetting all clocks. */
463 if (sspreadsheet->table_use_clock == 0) {
464 for (SpreadsheetTable *table : Span(sspreadsheet->tables, sspreadsheet->num_tables)) {
465 table->last_used = sspreadsheet->table_use_clock;
466 }
467 }
468 table->last_used = sspreadsheet->table_use_clock;
469 }
470
471 update_visible_columns(*table, *data_source);
472
473 SpreadsheetLayout spreadsheet_layout;
474 ResourceScope scope;
475
476 const int tot_rows = data_source->tot_rows();
477 spreadsheet_layout.index_column_width = get_index_column_width(tot_rows);
478
479 int x = spreadsheet_layout.index_column_width;
480
481 for (SpreadsheetColumn *column : Span{table->columns, table->num_columns}) {
482 std::unique_ptr<ColumnValues> values_ptr = data_source->get_column_values(*column->id);
483 if (!values_ptr) {
484 continue;
485 }
486 const ColumnValues *values = scope.add(std::move(values_ptr));
487 const eSpreadsheetColumnValueType column_type = values->type();
488
489 if (column->width <= 0.0f || column_type != column->data_type) {
490 column->width = values->fit_column_width_px(100) / SPREADSHEET_WIDTH_UNIT;
491 }
492 const int width_in_pixels = column->width * SPREADSHEET_WIDTH_UNIT;
493 spreadsheet_layout.columns.append({values, width_in_pixels});
494
495 column->runtime->left_x = x;
496 x += width_in_pixels;
497 column->runtime->right_x = x;
498
499 spreadsheet_column_assign_runtime_data(column, column_type, values->name());
500 }
501
502 spreadsheet_layout.row_indices = spreadsheet_filter_rows(
503 *sspreadsheet, spreadsheet_layout, *data_source, scope);
504
505 sspreadsheet->runtime->tot_columns = spreadsheet_layout.columns.size();
506 sspreadsheet->runtime->tot_rows = tot_rows;
507 sspreadsheet->runtime->visible_rows = spreadsheet_layout.row_indices.size();
508
509 std::unique_ptr<SpreadsheetDrawer> drawer = spreadsheet_drawer_from_layout(spreadsheet_layout);
510 draw_spreadsheet_in_region(C, region, *drawer);
511
512 sspreadsheet->runtime->top_row_height = drawer->top_row_height;
513 sspreadsheet->runtime->left_column_width = drawer->left_column_width;
514
515 /* Tag other regions for redraw, because the main region updates data for them. */
517 ED_region_tag_redraw(footer);
519 ED_region_tag_redraw(sidebar);
520}
521
523{
524 ARegion *region = params->region;
525 const wmNotifier *wmn = params->notifier;
526 SpaceSpreadsheet *sspreadsheet = static_cast<SpaceSpreadsheet *>(params->area->spacedata.first);
527
528 switch (wmn->category) {
529 case NC_SCENE: {
530 switch (wmn->data) {
531 case ND_MODE:
532 case ND_FRAME:
533 case ND_OB_ACTIVE: {
534 ED_region_tag_redraw(region);
535 break;
536 }
537 }
538 break;
539 }
540 case NC_OBJECT: {
541 ED_region_tag_redraw(region);
542 break;
543 }
544 case NC_SPACE: {
545 if (wmn->data == ND_SPACE_SPREADSHEET) {
546 ED_region_tag_redraw(region);
547 }
548 break;
549 }
550 case NC_TEXTURE:
551 case NC_GEOM: {
552 ED_region_tag_redraw(region);
553 break;
554 }
555 case NC_GPENCIL: {
556 ED_region_tag_redraw(region);
557 break;
558 }
559 case NC_VIEWER_PATH: {
561 {
562 ED_region_tag_redraw(region);
563 }
564 break;
565 }
566 }
567}
568
570{
571 ED_region_header_init(region);
572}
573
575{
577 ED_region_header(C, region);
578}
579
580static void spreadsheet_header_region_free(ARegion * /*region*/) {}
581
583{
584 ARegion *region = params->region;
585 const wmNotifier *wmn = params->notifier;
586 SpaceSpreadsheet *sspreadsheet = static_cast<SpaceSpreadsheet *>(params->area->spacedata.first);
587
588 switch (wmn->category) {
589 case NC_SCENE: {
590 switch (wmn->data) {
591 case ND_MODE:
592 case ND_OB_ACTIVE: {
593 ED_region_tag_redraw(region);
594 break;
595 }
596 }
597 break;
598 }
599 case NC_OBJECT: {
600 ED_region_tag_redraw(region);
601 break;
602 }
603 case NC_SPACE: {
604 if (wmn->data == ND_SPACE_SPREADSHEET) {
605 ED_region_tag_redraw(region);
606 }
607 break;
608 }
609 case NC_GEOM: {
610 ED_region_tag_redraw(region);
611 break;
612 }
613 case NC_GPENCIL: {
614 ED_region_tag_redraw(region);
615 break;
616 }
617 case NC_VIEWER_PATH: {
619 {
620 ED_region_tag_redraw(region);
621 }
622 break;
623 }
624 }
625}
626
628{
629 ED_region_header_init(region);
630}
631
633{
635 SpaceSpreadsheet_Runtime *runtime = sspreadsheet->runtime;
636 std::stringstream ss;
637 ss << IFACE_("Rows:") << " ";
638 if (runtime->visible_rows != runtime->tot_rows) {
639 char visible_rows_str[BLI_STR_FORMAT_INT32_GROUPED_SIZE];
640 BLI_str_format_int_grouped(visible_rows_str, runtime->visible_rows);
641 ss << visible_rows_str << " / ";
642 }
643 char tot_rows_str[BLI_STR_FORMAT_INT32_GROUPED_SIZE];
644 BLI_str_format_int_grouped(tot_rows_str, runtime->tot_rows);
645 ss << tot_rows_str << " | " << IFACE_("Columns:") << " " << runtime->tot_columns;
646 std::string stats_str = ss.str();
647
649
650 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
651 const uiStyle *style = UI_style_get_dpi();
652 uiLayout *layout = UI_block_layout(block,
656 region->winy - (region->winy - UI_UNIT_Y) / 2.0f,
657 region->winx,
658 1,
659 0,
660 style);
661 uiItemSpacer(layout);
663 layout->label(stats_str, ICON_NONE);
664 UI_block_layout_resolve(block, nullptr, nullptr);
665 UI_block_align_end(block);
666 UI_block_end(C, block);
667 UI_block_draw(C, block);
668}
669
670static void spreadsheet_footer_region_free(ARegion * /*region*/) {}
671
673
675{
676 ARegion *region = params->region;
677 const wmNotifier *wmn = params->notifier;
678
679 switch (wmn->category) {
680 case NC_SCENE: {
681 switch (wmn->data) {
682 case ND_FRAME:
683 ED_region_tag_redraw(region);
684 break;
685 }
686 break;
687 }
688 case NC_TEXTURE:
689 ED_region_tag_redraw(region);
690 break;
691 }
692
694}
695
697{
699 ED_region_panels(C, region);
700}
701
703{
704 UI_panel_category_active_set_default(region, "Filters");
705 ED_region_panels_init(wm, region);
706
707 wmKeyMap *keymap = WM_keymap_ensure(
708 wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, RGN_TYPE_WINDOW);
709 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
710}
711
712static void spreadsheet_right_region_free(ARegion * /*region*/) {}
713
715
717{
718 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
719
720 sspreadsheet->runtime = nullptr;
722 LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
723 BLO_read_string(reader, &row_filter->value_string);
724 }
725
727 reader, sspreadsheet->num_tables, reinterpret_cast<void **>(&sspreadsheet->tables));
728 for (const int i : IndexRange(sspreadsheet->num_tables)) {
729 BLO_read_struct(reader, SpreadsheetTable, &sspreadsheet->tables[i]);
730 spreadsheet_table_blend_read(reader, sspreadsheet->tables[i]);
731 }
732
733 spreadsheet_table_id_blend_read(reader, &sspreadsheet->geometry_id.base);
734}
735
737{
739 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
740
741 LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
742 BLO_write_struct(writer, SpreadsheetRowFilter, row_filter);
743 BLO_write_string(writer, row_filter->value_string);
744 }
745
746 BLO_write_pointer_array(writer, sspreadsheet->num_tables, sspreadsheet->tables);
747 for (const int i : IndexRange(sspreadsheet->num_tables)) {
748 spreadsheet_table_blend_write(writer, sspreadsheet->tables[i]);
749 }
750
752}
753
754static void spreadsheet_cursor(wmWindow *win, ScrArea *area, ARegion *region)
755{
756 SpaceSpreadsheet &sspreadsheet = *static_cast<SpaceSpreadsheet *>(area->spacedata.first);
757
758 const int2 cursor_re{win->eventstate->xy[0] - region->winrct.xmin,
759 win->eventstate->xy[1] - region->winrct.ymin};
760 if (find_hovered_column_header_edge(sspreadsheet, *region, cursor_re)) {
762 return;
763 }
764 if (find_hovered_column_header(sspreadsheet, *region, cursor_re)) {
766 return;
767 }
769}
770
772{
773 std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
774 ARegionType *art;
775
776 st->spaceid = SPACE_SPREADSHEET;
777 STRNCPY(st->name, "Spreadsheet");
778
779 st->create = spreadsheet_create;
780 st->free = spreadsheet_free;
781 st->init = spreadsheet_init;
782 st->duplicate = spreadsheet_duplicate;
783 st->operatortypes = spreadsheet_operatortypes;
784 st->keymap = spreadsheet_keymap;
785 st->id_remap = spreadsheet_id_remap;
786 st->foreach_id = spreadsheet_foreach_id;
787 st->blend_read_data = spreadsheet_blend_read_data;
788 st->blend_read_after_liblink = nullptr;
789 st->blend_write = spreadsheet_blend_write;
790
791 /* regions: main window */
792 art = MEM_callocN<ARegionType>("spacetype spreadsheet region");
796
801 art->event_cursor = true;
802 BLI_addhead(&st->regiontypes, art);
803
804 /* regions: header */
805 art = MEM_callocN<ARegionType>("spacetype spreadsheet header region");
807 art->prefsizey = HEADERY;
808 art->keymapflag = 0;
811
816 BLI_addhead(&st->regiontypes, art);
817
818 /* regions: footer */
819 art = MEM_callocN<ARegionType>("spacetype spreadsheet footer region");
821 art->prefsizey = HEADERY;
822 art->keymapflag = 0;
825
830 BLI_addhead(&st->regiontypes, art);
831
832 /* regions: right panel buttons */
833 art = MEM_callocN<ARegionType>("spacetype spreadsheet right region");
834 art->regionid = RGN_TYPE_UI;
838
844 BLI_addhead(&st->regiontypes, art);
845
847
848 /* regions: channels */
849 art = MEM_callocN<ARegionType>("spreadsheet dataset region");
851 art->prefsizex = 150 + V2D_SCROLL_WIDTH;
858 BLI_addhead(&st->regiontypes, art);
859
860 BKE_spacetype_register(std::move(st));
861}
862
863} // namespace blender::ed::spreadsheet
WorkSpace * CTX_wm_workspace(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
SpaceSpreadsheet * CTX_wm_space_spreadsheet(const bContext *C)
void BKE_spacetype_register(std::unique_ptr< SpaceType > st)
Definition screen.cc:276
ARegion * BKE_area_region_new()
Definition screen.cc:381
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:840
@ REGION_DRAW_LOCK_ALL
void BKE_viewer_path_copy(ViewerPath *dst, const ViewerPath *src)
@ VIEWER_PATH_EQUAL_FLAG_CONSIDER_UI_NAME
void BKE_viewer_path_clear(ViewerPath *viewer_path)
IDViewerPathElem * BKE_viewer_path_elem_new_id()
bool BKE_viewer_path_equal(const ViewerPath *a, const ViewerPath *b, ViewerPathEqualFlag flag=ViewerPathEqualFlag(0))
void BLF_size(int fontid, float size)
Definition blf.cc:440
int BLF_default()
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:805
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
size_t BLI_str_format_int_grouped(char dst[BLI_STR_FORMAT_INT32_GROUPED_SIZE], int num) ATTR_NONNULL(1)
Definition string.cc:1181
#define BLI_STR_FORMAT_INT32_GROUPED_SIZE
Definition BLI_string.h:25
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
Definition readfile.cc:5351
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct(reader, struct_name, ptr_p)
void BLO_write_pointer_array(BlendWriter *writer, int64_t num, const void *data_ptr)
void BLO_read_pointer_array(BlendDataReader *reader, int64_t array_size, void **ptr_p)
Definition readfile.cc:5402
#define IFACE_(msgid)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
ID_Type
@ ID_OB
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
#define HEADERY
@ RGN_TYPE_UI
@ RGN_TYPE_WINDOW
@ RGN_TYPE_FOOTER
@ RGN_TYPE_HEADER
@ RGN_TYPE_TOOLS
@ RGN_FLAG_HIDDEN
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
@ SPREADSHEET_TABLE_ID_TYPE_GEOMETRY
@ SPACE_SPREADSHEET
@ SPACE_EMPTY
@ SPREADSHEET_COLUMN_FLAG_UNAVAILABLE
@ SPREADSHEET_FILTER_ENABLE
eSpaceSpreadsheet_ObjectEvalState
@ SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE
@ SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED
@ SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL
eSpreadsheetColumnValueType
#define SPREADSHEET_WIDTH_UNIT
@ SPREADSHEET_FLAG_PINNED
#define UI_SCALE_FAC
@ USER_HEADER_BOTTOM
@ V2D_SCROLL_HORIZONTAL_HIDE
@ V2D_SCROLL_VERTICAL_HIDE
@ V2D_SCROLL_RIGHT
@ V2D_SCROLL_BOTTOM
@ V2D_ALIGN_NO_NEG_X
@ V2D_ALIGN_NO_POS_Y
@ V2D_LIMITZOOM
@ V2D_LOCKZOOM_X
@ V2D_KEEPASPECT
@ V2D_LOCKZOOM_Y
@ V2D_KEEPTOT_STRICT
@ VIEWER_PATH_ELEM_TYPE_ID
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:714
@ ED_KEYMAP_UI
Definition ED_screen.hh:740
@ ED_KEYMAP_HEADER
Definition ED_screen.hh:746
@ ED_KEYMAP_VIEW2D
Definition ED_screen.hh:743
@ ED_KEYMAP_FRAMES
Definition ED_screen.hh:745
void ED_region_panels(const bContext *C, ARegion *region)
Definition area.cc:3466
void ED_region_header(const bContext *C, ARegion *region)
Definition area.cc:3754
void ED_region_header_init(ARegion *region)
Definition area.cc:3769
void ED_region_panels_layout(const bContext *C, ARegion *region)
Definition area.cc:3403
void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
Definition area.cc:3473
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:639
void ED_region_panels_draw(const bContext *C, ARegion *region)
Definition area.cc:3409
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define UI_UNIT_Y
#define UI_SIDEBAR_PANEL_WIDTH
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType emboss)
const uiStyle * UI_style_get_dpi()
#define UI_HEADER_OFFSET
void UI_block_draw(const bContext *C, uiBlock *block)
void UI_panel_category_active_set_default(ARegion *region, const char *idname)
#define UI_UNIT_X
void UI_block_end(const bContext *C, uiBlock *block)
void UI_block_align_end(uiBlock *block)
@ UI_LAYOUT_HORIZONTAL
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const uiStyle *style)
@ UI_LAYOUT_ALIGN_RIGHT
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
@ UI_LAYOUT_HEADER
void uiItemSpacer(uiLayout *layout)
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
@ TH_BACK
void UI_ThemeClearColor(int colorid)
#define V2D_SCROLL_WIDTH
Definition UI_view2d.hh:54
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
Definition view2d.cc:221
@ V2D_COMMONVIEW_LIST
Definition UI_view2d.hh:35
#define NC_GEOM
Definition WM_types.hh:390
#define ND_OB_ACTIVE
Definition WM_types.hh:437
#define NC_VIEWER_PATH
Definition WM_types.hh:403
#define ND_MODE
Definition WM_types.hh:442
#define NC_SCENE
Definition WM_types.hh:375
#define ND_FRAME
Definition WM_types.hh:431
#define NC_GPENCIL
Definition WM_types.hh:396
#define NC_TEXTURE
Definition WM_types.hh:378
#define ND_SPACE_SPREADSHEET
Definition WM_types.hh:538
#define NC_OBJECT
Definition WM_types.hh:376
#define NC_SPACE
Definition WM_types.hh:389
#define U
BMesh const char void * data
BPy_StructRNA * depsgraph
T * add(std::unique_ptr< T > resource)
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
int64_t size() const
void append(const T &value)
void insert(const int64_t insert_index, const T &value)
Span< T > as_span() const
eSpreadsheetColumnValueType type() const
float fit_column_width_px(const std::optional< int64_t > &max_sample_size=std::nullopt) const
virtual void foreach_default_column_ids(FunctionRef< void(const SpreadsheetColumnID &, bool is_extra)>) const
virtual std::unique_ptr< ColumnValues > get_column_values(const SpreadsheetColumnID &) const
#define MEM_SAFE_FREE(v)
#define GS(a)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
SpreadsheetColumn * spreadsheet_column_new(SpreadsheetColumnID *column_id)
static void spreadsheet_header_region_free(ARegion *)
static void spreadsheet_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
static void spreadsheet_free(SpaceLink *sl)
const SpreadsheetTableID * get_active_table_id(const SpaceSpreadsheet &sspreadsheet)
void spreadsheet_table_move_to_front(SpaceSpreadsheet &sspreadsheet, SpreadsheetTable &table)
static void spreadsheet_header_region_init(wmWindowManager *, ARegion *region)
void spreadsheet_table_blend_write(BlendWriter *writer, const SpreadsheetTable *table)
IndexMask spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet, const SpreadsheetLayout &spreadsheet_layout, const DataSource &data_source, ResourceScope &scope)
void draw_spreadsheet_in_region(const bContext *C, ARegion *region, const SpreadsheetDrawer &drawer)
void spreadsheet_table_blend_read(BlendDataReader *reader, SpreadsheetTable *table)
SpreadsheetRowFilter * spreadsheet_row_filter_copy(const SpreadsheetRowFilter *src_row_filter)
static void spreadsheet_footer_region_free(ARegion *)
static void spreadsheet_right_region_free(ARegion *)
static SpaceLink * spreadsheet_create(const ScrArea *, const Scene *)
static void spreadsheet_sidebar_init(wmWindowManager *wm, ARegion *region)
static void spreadsheet_keymap(wmKeyConfig *keyconf)
static void update_visible_columns(SpreadsheetTable &table, DataSource &data_source)
static void spreadsheet_init(wmWindowManager *, ScrArea *area)
void spreadsheet_table_remove_unused(SpaceSpreadsheet &sspreadsheet)
void spreadsheet_table_id_free_content(SpreadsheetTableID *table_id)
std::unique_ptr< DataSource > data_source_from_geometry(const bContext *C, Object *object_eval)
static SpaceLink * spreadsheet_duplicate(SpaceLink *sl)
SpreadsheetTableID * spreadsheet_table_id_copy(const SpreadsheetTableID &src_table_id)
void spreadsheet_table_id_copy_content_geometry(SpreadsheetTableIDGeometry &dst, const SpreadsheetTableIDGeometry &src)
static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
void spreadsheet_table_id_blend_write_content_geometry(BlendWriter *writer, const SpreadsheetTableIDGeometry *table_id)
std::unique_ptr< DataSource > get_data_source(const bContext &C)
static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region)
void spreadsheet_table_id_blend_read(BlendDataReader *reader, SpreadsheetTableID *table_id)
void spreadsheet_table_remove_unused_columns(SpreadsheetTable &table)
void spreadsheet_table_id_foreach_id(SpreadsheetTableID &table_id, LibraryForeachIDData *data)
static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region)
Object * spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet, const Depsgraph *depsgraph)
SpreadsheetTable * spreadsheet_table_new(SpreadsheetTableID *table_id)
ID * get_current_id(const SpaceSpreadsheet *sspreadsheet)
static void spreadsheet_footer_region_init(wmWindowManager *, ARegion *region)
SpreadsheetColumn * find_hovered_column_header(SpaceSpreadsheet &sspreadsheet, ARegion &region, const int2 &cursor_re)
static void spreadsheet_footer_region_listener(const wmRegionListenerParams *)
std::unique_ptr< SpreadsheetDrawer > spreadsheet_drawer_from_layout(const SpreadsheetLayout &spreadsheet_layout)
static void view_active_object(const bContext *C, SpaceSpreadsheet *sspreadsheet)
static void spreadsheet_dataset_region_listener(const wmRegionListenerParams *params)
void spreadsheet_table_free(SpreadsheetTable *table)
static void spreadsheet_blend_read_data(BlendDataReader *reader, SpaceLink *sl)
static void spreadsheet_header_region_draw(const bContext *C, ARegion *region)
static int get_index_column_width(const int tot_rows)
void spreadsheet_row_filter_free(SpreadsheetRowFilter *row_filter)
static void spreadsheet_blend_write(BlendWriter *writer, SpaceLink *sl)
static void spreadsheet_update_context(const bContext *C)
void spreadsheet_table_foreach_id(SpreadsheetTable &table, LibraryForeachIDData *data)
SpreadsheetColumn * find_hovered_column_header_edge(SpaceSpreadsheet &sspreadsheet, ARegion &region, const int2 &cursor_re)
void spreadsheet_column_assign_runtime_data(SpreadsheetColumn *column, const eSpreadsheetColumnValueType data_type, const StringRefNull display_name)
void spreadsheet_data_set_region_panels_register(ARegionType &region_type)
SpreadsheetTable * get_active_table(SpaceSpreadsheet &sspreadsheet)
static void spreadsheet_header_region_listener(const wmRegionListenerParams *params)
static void spreadsheet_cursor(wmWindow *win, ScrArea *area, ARegion *region)
SpreadsheetColumnID * spreadsheet_column_id_copy(const SpreadsheetColumnID *src_column_id)
SpreadsheetTable * spreadsheet_table_copy(const SpreadsheetTable &src_table)
void spreadsheet_table_remap_id(SpreadsheetTable &table, const bke::id::IDRemapper &mappings)
static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region)
void register_row_filter_panels(ARegionType &region_type)
void spreadsheet_table_id_remap_id(SpreadsheetTableID &table_id, const bke::id::IDRemapper &mappings)
SpreadsheetTable * spreadsheet_table_find(SpaceSpreadsheet &sspreadsheet, const SpreadsheetTableID &table_id)
static void spreadsheet_id_remap(ScrArea *, SpaceLink *slink, const blender::bke::id::IDRemapper &mappings)
void spreadsheet_table_add(SpaceSpreadsheet &sspreadsheet, SpreadsheetTable *table)
static void spreadsheet_main_region_listener(const wmRegionListenerParams *params)
static void spreadsheet_right_region_listener(const wmRegionListenerParams *)
Object * parse_object_only(const ViewerPath &viewer_path)
std::optional< ViewerPathForGeometryNodesViewer > parse_geometry_nodes_viewer(const ViewerPath &viewer_path)
bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed_viewer_path)
VecBase< int32_t, 2 > int2
void(* free)(ARegion *)
void(* cursor)(wmWindow *win, ScrArea *area, ARegion *region)
void(* listener)(const wmRegionListenerParams *params)
void(* draw)(const bContext *C, ARegion *region)
void(* layout)(const bContext *C, ARegion *region)
short event_cursor
void(* init)(wmWindowManager *wm, ARegion *region)
ARegionRuntimeHandle * runtime
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
void * first
ListBase spacedata
SpreadsheetTableIDGeometry geometry_id
SpreadsheetTable ** tables
SpaceSpreadsheet_Runtime * runtime
SpreadsheetColumnID * id
SpreadsheetColumn ** columns
float minzoom
short keeptot
short keepzoom
float maxzoom
ViewerPath viewer_path
int ymin
int xmin
void label(blender::StringRef name, int icon)
int xy[2]
Definition WM_types.hh:758
unsigned int data
Definition WM_types.hh:355
unsigned int category
Definition WM_types.hh:355
struct wmEvent * eventstate
i
Definition text_draw.cc:230
void WM_cursor_set(wmWindow *win, int curs)
@ WM_CURSOR_HAND
Definition wm_cursors.hh:22
@ WM_CURSOR_DEFAULT
Definition wm_cursors.hh:15
@ WM_CURSOR_X_MOVE
Definition wm_cursors.hh:39
wmEventHandler_Keymap * WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:893