Blender V4.3
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
7#include "BLI_listbase.h"
8#include "BLI_string.h"
9
10#include "BKE_screen.hh"
11
12#include "ED_screen.hh"
13#include "ED_space_api.hh"
14#include "ED_spreadsheet.hh"
15#include "ED_viewer_path.hh"
16
17#include "DNA_scene_types.h"
18#include "DNA_screen_types.h"
19#include "DNA_space_types.h"
20
21#include "MEM_guardedalloc.h"
22
23#include "UI_interface.hh"
24#include "UI_resources.hh"
25#include "UI_view2d.hh"
26
27#include "BLO_read_write.hh"
28
30
31#include "WM_api.hh"
32#include "WM_types.hh"
33
34#include "BLT_translation.hh"
35
36#include "BLF_api.hh"
37
39#include "spreadsheet_intern.hh"
40#include "spreadsheet_layout.hh"
43
44#include <sstream>
45
47
48static SpaceLink *spreadsheet_create(const ScrArea * /*area*/, const Scene * /*scene*/)
49{
50 SpaceSpreadsheet *spreadsheet_space = MEM_cnew<SpaceSpreadsheet>("spreadsheet space");
51 spreadsheet_space->spacetype = SPACE_SPREADSHEET;
52
53 spreadsheet_space->filter_flag = SPREADSHEET_FILTER_ENABLE;
54
55 {
56 /* Header. */
57 ARegion *region = MEM_cnew<ARegion>("spreadsheet header");
58 BLI_addtail(&spreadsheet_space->regionbase, region);
59 region->regiontype = RGN_TYPE_HEADER;
60 region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
61 }
62
63 {
64 /* Footer. */
65 ARegion *region = MEM_cnew<ARegion>("spreadsheet footer region");
66 BLI_addtail(&spreadsheet_space->regionbase, region);
67 region->regiontype = RGN_TYPE_FOOTER;
68 region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM;
69 }
70
71 {
72 /* Dataset Region */
73 ARegion *region = MEM_cnew<ARegion>("spreadsheet dataset region");
74 BLI_addtail(&spreadsheet_space->regionbase, region);
75 region->regiontype = RGN_TYPE_TOOLS;
76 region->alignment = RGN_ALIGN_LEFT;
77 }
78
79 {
80 /* Properties region. */
81 ARegion *region = MEM_cnew<ARegion>("spreadsheet right region");
82 BLI_addtail(&spreadsheet_space->regionbase, region);
83 region->regiontype = RGN_TYPE_UI;
84 region->alignment = RGN_ALIGN_RIGHT;
85 region->flag = RGN_FLAG_HIDDEN;
86 }
87
88 {
89 /* Main window. */
90 ARegion *region = MEM_cnew<ARegion>("spreadsheet main region");
91 BLI_addtail(&spreadsheet_space->regionbase, region);
92 region->regiontype = RGN_TYPE_WINDOW;
93 }
94
95 return (SpaceLink *)spreadsheet_space;
96}
97
99{
100 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
101
102 MEM_delete(sspreadsheet->runtime);
103
104 LISTBASE_FOREACH_MUTABLE (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
105 spreadsheet_row_filter_free(row_filter);
106 }
107 LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) {
109 }
110 MEM_SAFE_FREE(sspreadsheet->instance_ids);
111 BKE_viewer_path_clear(&sspreadsheet->viewer_path);
112}
113
114static void spreadsheet_init(wmWindowManager * /*wm*/, ScrArea *area)
115{
116 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)area->spacedata.first;
117 if (sspreadsheet->runtime == nullptr) {
118 sspreadsheet->runtime = MEM_new<SpaceSpreadsheet_Runtime>(__func__);
119 }
120}
121
123{
124 const SpaceSpreadsheet *sspreadsheet_old = (SpaceSpreadsheet *)sl;
125 SpaceSpreadsheet *sspreadsheet_new = (SpaceSpreadsheet *)MEM_dupallocN(sspreadsheet_old);
126 if (sspreadsheet_old->runtime) {
127 sspreadsheet_new->runtime = MEM_new<SpaceSpreadsheet_Runtime>(__func__,
128 *sspreadsheet_old->runtime);
129 }
130 else {
131 sspreadsheet_new->runtime = MEM_new<SpaceSpreadsheet_Runtime>(__func__);
132 }
133
134 BLI_listbase_clear(&sspreadsheet_new->row_filters);
135 LISTBASE_FOREACH (const SpreadsheetRowFilter *, src_filter, &sspreadsheet_old->row_filters) {
136 SpreadsheetRowFilter *new_filter = spreadsheet_row_filter_copy(src_filter);
137 BLI_addtail(&sspreadsheet_new->row_filters, new_filter);
138 }
139 BLI_listbase_clear(&sspreadsheet_new->columns);
140 LISTBASE_FOREACH (SpreadsheetColumn *, src_column, &sspreadsheet_old->columns) {
141 SpreadsheetColumn *new_column = spreadsheet_column_copy(src_column);
142 BLI_addtail(&sspreadsheet_new->columns, new_column);
143 }
144
145 sspreadsheet_new->instance_ids = static_cast<SpreadsheetInstanceID *>(
146 MEM_dupallocN(sspreadsheet_old->instance_ids));
147 BKE_viewer_path_copy(&sspreadsheet_new->viewer_path, &sspreadsheet_old->viewer_path);
148
149 return (SpaceLink *)sspreadsheet_new;
150}
151
152static void spreadsheet_keymap(wmKeyConfig *keyconf)
153{
154 /* Entire editor only. */
155 WM_keymap_ensure(keyconf, "Spreadsheet Generic", SPACE_SPREADSHEET, RGN_TYPE_WINDOW);
156}
157
158static void spreadsheet_id_remap(ScrArea * /*area*/,
159 SpaceLink *slink,
160 const blender::bke::id::IDRemapper &mappings)
161{
162 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)slink;
163 BKE_viewer_path_id_remap(&sspreadsheet->viewer_path, mappings);
164}
165
167{
168 SpaceSpreadsheet *sspreadsheet = reinterpret_cast<SpaceSpreadsheet *>(space_link);
169 BKE_viewer_path_foreach_id(data, &sspreadsheet->viewer_path);
170}
171
173{
176 region->v2d.align = V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y;
177 region->v2d.keepzoom = V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT;
178 region->v2d.keeptot = V2D_KEEPTOT_STRICT;
179 region->v2d.minzoom = region->v2d.maxzoom = 1.0f;
180
181 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
182
183 {
184 wmKeyMap *keymap = WM_keymap_ensure(
185 wm->defaultconf, "View2D Buttons List", SPACE_EMPTY, RGN_TYPE_WINDOW);
186 WM_event_add_keymap_handler(&region->handlers, keymap);
187 }
188 {
189 wmKeyMap *keymap = WM_keymap_ensure(
190 wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, RGN_TYPE_WINDOW);
191 WM_event_add_keymap_handler(&region->handlers, keymap);
192 }
193}
194
195ID *get_current_id(const SpaceSpreadsheet *sspreadsheet)
196{
197 if (BLI_listbase_is_empty(&sspreadsheet->viewer_path.path)) {
198 return nullptr;
199 }
200 ViewerPathElem *root_context = static_cast<ViewerPathElem *>(
201 sspreadsheet->viewer_path.path.first);
202 if (root_context->type != VIEWER_PATH_ELEM_TYPE_ID) {
203 return nullptr;
204 }
205 IDViewerPathElem *id_elem = reinterpret_cast<IDViewerPathElem *>(root_context);
206 return id_elem->id;
207}
208
209static void view_active_object(const bContext *C, SpaceSpreadsheet *sspreadsheet)
210{
211 BKE_viewer_path_clear(&sspreadsheet->viewer_path);
213 if (ob == nullptr) {
214 return;
215 }
217 id_elem->id = &ob->id;
218 BLI_addtail(&sspreadsheet->viewer_path.path, id_elem);
220}
221
223{
225
227 Object *active_object = CTX_data_active_object(C);
228 Object *context_object = blender::ed::viewer_path::parse_object_only(sspreadsheet->viewer_path);
232 if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) {
233 if (context_object == nullptr) {
234 /* Object is not available anymore, so clear the pinning. */
235 sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED;
236 }
237 else {
238 /* The object is still pinned, do nothing. */
239 break;
240 }
241 }
242 else {
243 if (active_object != context_object) {
244 /* The active object has changed, so view the new active object. */
245 view_active_object(C, sspreadsheet);
246 }
247 else {
248 /* Nothing changed. */
249 break;
250 }
251 }
252 break;
253 }
255 WorkSpace *workspace = CTX_wm_workspace(C);
256 if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) {
257 const std::optional<ViewerPathForGeometryNodesViewer> parsed_path =
259 if (parsed_path.has_value()) {
261 /* The pinned path is still valid, do nothing. */
262 break;
263 }
264 /* The pinned path does not exist anymore, clear pinning. */
265 sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED;
266 }
267 else {
268 /* Unknown pinned path, clear pinning. */
269 sspreadsheet->flag &= ~SPREADSHEET_FLAG_PINNED;
270 }
271 }
272 /* Now try to update the viewer path from the workspace. */
273 const std::optional<ViewerPathForGeometryNodesViewer> workspace_parsed_path =
275 if (workspace_parsed_path.has_value()) {
276 if (BKE_viewer_path_equal(&sspreadsheet->viewer_path, &workspace->viewer_path)) {
277 /* Nothing changed. */
278 break;
279 }
280 /* Update the viewer path from the workspace. */
281 BKE_viewer_path_clear(&sspreadsheet->viewer_path);
282 BKE_viewer_path_copy(&sspreadsheet->viewer_path, &workspace->viewer_path);
283 }
284 else {
285 /* No active viewer node, change back to showing evaluated active object. */
287 view_active_object(C, sspreadsheet);
288 }
289
290 break;
291 }
292 }
293}
294
296 const Depsgraph *depsgraph)
297{
298 ID *used_id = get_current_id(sspreadsheet);
299 if (used_id == nullptr) {
300 return nullptr;
301 }
302 const ID_Type id_type = GS(used_id->name);
303 if (id_type != ID_OB) {
304 return nullptr;
305 }
306 Object *object_orig = (Object *)used_id;
307 if (!ELEM(object_orig->type,
308 OB_MESH,
310 OB_VOLUME,
312 OB_FONT,
313 OB_CURVES,
315 {
316 return nullptr;
317 }
318
319 Object *object_eval = DEG_get_evaluated_object(depsgraph, object_orig);
320 if (object_eval == nullptr) {
321 return nullptr;
322 }
323
324 return object_eval;
325}
326
327static std::unique_ptr<DataSource> get_data_source(const bContext *C)
328{
331
332 Object *object_eval = spreadsheet_get_object_eval(sspreadsheet, depsgraph);
333 if (object_eval) {
334 return data_source_from_geometry(C, object_eval);
335 }
336 return {};
337}
338
339static float get_default_column_width(const ColumnValues &values)
340{
341 if (values.default_width > 0.0f) {
342 return values.default_width;
343 }
344 static const float float_width = 3;
345 switch (values.type()) {
348 return 2.0f;
351 return float_width;
353 return float_width;
356 return 2.0f * float_width;
358 return 3.0f * float_width;
362 return 4.0f * float_width;
364 return 8.0f;
366 return 5.0f;
368 return 2.0f;
369 }
370 return float_width;
371}
372
373static float get_column_width(const ColumnValues &values)
374{
375 float data_width = get_default_column_width(values);
376 const int fontid = UI_style_get()->widget.uifont_id;
378 const StringRefNull name = values.name();
379 const float name_width = BLF_width(fontid, name.data(), name.size());
380 return std::max<float>(name_width / UI_UNIT_X + 1.0f, data_width);
381}
382
383static float get_column_width_in_pixels(const ColumnValues &values)
384{
386}
387
388static int get_index_column_width(const int tot_rows)
389{
390 const int fontid = UI_style_get()->widget.uifont_id;
391 BLF_size(fontid, UI_style_get_dpi()->widget.points * UI_SCALE_FAC);
392 return std::to_string(std::max(0, tot_rows - 1)).size() * BLF_width(fontid, "0", 1) +
393 UI_UNIT_X * 0.75;
394}
395
396static void update_visible_columns(ListBase &columns, DataSource &data_source)
397{
399 LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &columns) {
400 std::unique_ptr<ColumnValues> values = data_source.get_column_values(*column->id);
401 /* Remove columns that don't exist anymore. */
402 if (!values) {
403 BLI_remlink(&columns, column);
405 continue;
406 }
407
408 if (!used_ids.add(*column->id)) {
409 /* Remove duplicate columns for now. */
410 BLI_remlink(&columns, column);
412 continue;
413 }
414 }
415
416 data_source.foreach_default_column_ids(
417 [&](const SpreadsheetColumnID &column_id, const bool is_extra) {
418 std::unique_ptr<ColumnValues> values = data_source.get_column_values(column_id);
419 if (values) {
420 if (used_ids.add(column_id)) {
421 SpreadsheetColumnID *new_id = spreadsheet_column_id_copy(&column_id);
422 SpreadsheetColumn *new_column = spreadsheet_column_new(new_id);
423 if (is_extra) {
424 BLI_addhead(&columns, new_column);
425 }
426 else {
427 BLI_addtail(&columns, new_column);
428 }
429 }
430 }
431 });
432}
433
434static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
435{
437 sspreadsheet->runtime->cache.set_all_unused();
439
440 std::unique_ptr<DataSource> data_source = get_data_source(C);
441 if (!data_source) {
442 data_source = std::make_unique<DataSource>();
443 }
444
445 update_visible_columns(sspreadsheet->columns, *data_source);
446
447 SpreadsheetLayout spreadsheet_layout;
448 ResourceScope scope;
449
450 LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) {
451 std::unique_ptr<ColumnValues> values_ptr = data_source->get_column_values(*column->id);
452 /* Should have been removed before if it does not exist anymore. */
453 BLI_assert(values_ptr);
454 const ColumnValues *values = scope.add(std::move(values_ptr));
455 const int width = get_column_width_in_pixels(*values);
456 spreadsheet_layout.columns.append({values, width});
457
458 spreadsheet_column_assign_runtime_data(column, values->type(), values->name());
459 }
460
461 const int tot_rows = data_source->tot_rows();
462 spreadsheet_layout.index_column_width = get_index_column_width(tot_rows);
463 spreadsheet_layout.row_indices = spreadsheet_filter_rows(
464 *sspreadsheet, spreadsheet_layout, *data_source, scope);
465
466 sspreadsheet->runtime->tot_columns = spreadsheet_layout.columns.size();
467 sspreadsheet->runtime->tot_rows = tot_rows;
468 sspreadsheet->runtime->visible_rows = spreadsheet_layout.row_indices.size();
469
470 std::unique_ptr<SpreadsheetDrawer> drawer = spreadsheet_drawer_from_layout(spreadsheet_layout);
471 draw_spreadsheet_in_region(C, region, *drawer);
472
473 /* Tag other regions for redraw, because the main region updates data for them. */
475 ED_region_tag_redraw(footer);
477 ED_region_tag_redraw(sidebar);
478
479 /* Free all cache items that have not been used. */
480 sspreadsheet->runtime->cache.remove_all_unused();
481}
482
484{
485 ARegion *region = params->region;
486 const wmNotifier *wmn = params->notifier;
487 SpaceSpreadsheet *sspreadsheet = static_cast<SpaceSpreadsheet *>(params->area->spacedata.first);
488
489 switch (wmn->category) {
490 case NC_SCENE: {
491 switch (wmn->data) {
492 case ND_MODE:
493 case ND_FRAME:
494 case ND_OB_ACTIVE: {
495 ED_region_tag_redraw(region);
496 break;
497 }
498 }
499 break;
500 }
501 case NC_OBJECT: {
502 ED_region_tag_redraw(region);
503 break;
504 }
505 case NC_SPACE: {
506 if (wmn->data == ND_SPACE_SPREADSHEET) {
507 ED_region_tag_redraw(region);
508 }
509 break;
510 }
511 case NC_TEXTURE:
512 case NC_GEOM: {
513 ED_region_tag_redraw(region);
514 break;
515 }
516 case NC_GPENCIL: {
517 ED_region_tag_redraw(region);
518 break;
519 }
520 case NC_VIEWER_PATH: {
522 ED_region_tag_redraw(region);
523 }
524 break;
525 }
526 }
527}
528
530{
531 ED_region_header_init(region);
532}
533
534static void spreadsheet_header_region_draw(const bContext *C, ARegion *region)
535{
537 ED_region_header(C, region);
538}
539
540static void spreadsheet_header_region_free(ARegion * /*region*/) {}
541
543{
544 ARegion *region = params->region;
545 const wmNotifier *wmn = params->notifier;
546 SpaceSpreadsheet *sspreadsheet = static_cast<SpaceSpreadsheet *>(params->area->spacedata.first);
547
548 switch (wmn->category) {
549 case NC_SCENE: {
550 switch (wmn->data) {
551 case ND_MODE:
552 case ND_OB_ACTIVE: {
553 ED_region_tag_redraw(region);
554 break;
555 }
556 }
557 break;
558 }
559 case NC_OBJECT: {
560 ED_region_tag_redraw(region);
561 break;
562 }
563 case NC_SPACE: {
564 if (wmn->data == ND_SPACE_SPREADSHEET) {
565 ED_region_tag_redraw(region);
566 }
567 break;
568 }
569 case NC_GEOM: {
570 ED_region_tag_redraw(region);
571 break;
572 }
573 case NC_GPENCIL: {
574 ED_region_tag_redraw(region);
575 break;
576 }
577 case NC_VIEWER_PATH: {
579 ED_region_tag_redraw(region);
580 }
581 break;
582 }
583 }
584}
585
587{
588 ED_region_header_init(region);
589}
590
591static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region)
592{
594 SpaceSpreadsheet_Runtime *runtime = sspreadsheet->runtime;
595 std::stringstream ss;
596 ss << IFACE_("Rows:") << " ";
597 if (runtime->visible_rows != runtime->tot_rows) {
598 char visible_rows_str[BLI_STR_FORMAT_INT32_GROUPED_SIZE];
599 BLI_str_format_int_grouped(visible_rows_str, runtime->visible_rows);
600 ss << visible_rows_str << " / ";
601 }
602 char tot_rows_str[BLI_STR_FORMAT_INT32_GROUPED_SIZE];
603 BLI_str_format_int_grouped(tot_rows_str, runtime->tot_rows);
604 ss << tot_rows_str << " | " << IFACE_("Columns:") << " " << runtime->tot_columns;
605 std::string stats_str = ss.str();
606
608
609 uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
610 const uiStyle *style = UI_style_get_dpi();
611 uiLayout *layout = UI_block_layout(block,
615 region->winy - (region->winy - UI_UNIT_Y) / 2.0f,
616 region->winx,
617 1,
618 0,
619 style);
620 uiItemSpacer(layout);
622 uiItemL(layout, stats_str.c_str(), ICON_NONE);
623 UI_block_layout_resolve(block, nullptr, nullptr);
624 UI_block_align_end(block);
625 UI_block_end(C, block);
626 UI_block_draw(C, block);
627}
628
629static void spreadsheet_footer_region_free(ARegion * /*region*/) {}
630
632
634{
635 ARegion *region = params->region;
636 const wmNotifier *wmn = params->notifier;
637
638 switch (wmn->category) {
639 case NC_SCENE: {
640 switch (wmn->data) {
641 case ND_FRAME:
642 ED_region_tag_redraw(region);
643 break;
644 }
645 break;
646 }
647 case NC_TEXTURE:
648 ED_region_tag_redraw(region);
649 break;
650 }
651
653}
654
656{
658 ED_region_panels(C, region);
659}
660
662{
663 UI_panel_category_active_set_default(region, "Filters");
664 ED_region_panels_init(wm, region);
665
666 wmKeyMap *keymap = WM_keymap_ensure(
667 wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, RGN_TYPE_WINDOW);
668 WM_event_add_keymap_handler(&region->handlers, keymap);
669}
670
671static void spreadsheet_right_region_free(ARegion * /*region*/) {}
672
674
676{
677 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
678
679 sspreadsheet->runtime = nullptr;
681 LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
682 BLO_read_string(reader, &row_filter->value_string);
683 }
684 BLO_read_struct_list(reader, SpreadsheetColumn, &sspreadsheet->columns);
685 LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) {
686 BLO_read_struct(reader, SpreadsheetColumnID, &column->id);
687 BLO_read_string(reader, &column->id->name);
688 /* While the display name is technically runtime data, it is loaded here, otherwise the row
689 * filters might not now their type if their region draws before the main region.
690 * This would ideally be cleared here. */
691 BLO_read_string(reader, &column->display_name);
692 }
693
695 reader, SpreadsheetInstanceID, sspreadsheet->instance_ids_num, &sspreadsheet->instance_ids);
696
697 BKE_viewer_path_blend_read_data(reader, &sspreadsheet->viewer_path);
698}
699
701{
703 SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
704
705 LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
706 BLO_write_struct(writer, SpreadsheetRowFilter, row_filter);
707 BLO_write_string(writer, row_filter->value_string);
708 }
709
710 LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) {
711 BLO_write_struct(writer, SpreadsheetColumn, column);
712 BLO_write_struct(writer, SpreadsheetColumnID, column->id);
713 BLO_write_string(writer, column->id->name);
714 /* While the display name is technically runtime data, we write it here, otherwise the row
715 * filters might not now their type if their region draws before the main region.
716 * This would ideally be cleared here. */
717 BLO_write_string(writer, column->display_name);
718 }
719
721 writer, SpreadsheetInstanceID, sspreadsheet->instance_ids_num, sspreadsheet->instance_ids);
722 BKE_viewer_path_blend_write(writer, &sspreadsheet->viewer_path);
723}
724
726{
727 std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
728 ARegionType *art;
729
730 st->spaceid = SPACE_SPREADSHEET;
731 STRNCPY(st->name, "Spreadsheet");
732
733 st->create = spreadsheet_create;
734 st->free = spreadsheet_free;
735 st->init = spreadsheet_init;
736 st->duplicate = spreadsheet_duplicate;
737 st->operatortypes = spreadsheet_operatortypes;
738 st->keymap = spreadsheet_keymap;
739 st->id_remap = spreadsheet_id_remap;
740 st->foreach_id = spreadsheet_foreach_id;
741 st->blend_read_data = spreadsheet_blend_read_data;
742 st->blend_read_after_liblink = nullptr;
743 st->blend_write = spreadsheet_blend_write;
744
745 /* regions: main window */
746 art = MEM_cnew<ARegionType>("spacetype spreadsheet region");
749 art->lock = 1;
750
754 BLI_addhead(&st->regiontypes, art);
755
756 /* regions: header */
757 art = MEM_cnew<ARegionType>("spacetype spreadsheet header region");
759 art->prefsizey = HEADERY;
760 art->keymapflag = 0;
762 art->lock = 1;
763
768 BLI_addhead(&st->regiontypes, art);
769
770 /* regions: footer */
771 art = MEM_cnew<ARegionType>("spacetype spreadsheet footer region");
773 art->prefsizey = HEADERY;
774 art->keymapflag = 0;
776 art->lock = 1;
777
782 BLI_addhead(&st->regiontypes, art);
783
784 /* regions: right panel buttons */
785 art = MEM_cnew<ARegionType>("spacetype spreadsheet right region");
786 art->regionid = RGN_TYPE_UI;
789 art->lock = 1;
790
796 BLI_addhead(&st->regiontypes, art);
797
799
800 /* regions: channels */
801 art = MEM_cnew<ARegionType>("spreadsheet dataset region");
803 art->prefsizex = 150 + V2D_SCROLL_WIDTH;
805 art->lock = 1;
810 BLI_addhead(&st->regiontypes, art);
811
812 BKE_spacetype_register(std::move(st));
813}
814
815} // 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:268
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:815
void BKE_viewer_path_copy(ViewerPath *dst, const ViewerPath *src)
void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const blender::bke::id::IDRemapper &mappings)
void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_path)
void BKE_viewer_path_clear(ViewerPath *viewer_path)
IDViewerPathElem * BKE_viewer_path_elem_new_id()
void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer_path)
bool BKE_viewer_path_equal(const ViewerPath *a, const ViewerPath *b, ViewerPathEqualFlag flag=ViewerPathEqualFlag(0))
void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_path)
void BLF_size(int fontid, float size)
Definition blf.cc:426
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:791
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
size_t BLI_str_format_int_grouped(char dst[BLI_STR_FORMAT_INT32_GROUPED_SIZE], int num) ATTR_NONNULL(1)
Definition string.c:1168
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define BLI_STR_FORMAT_INT32_GROUPED_SIZE
Definition BLI_string.h:25
#define ELEM(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
Definition readfile.cc:4992
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define IFACE_(msgid)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
ID_Type
@ ID_OB
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
#define HEADERY
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
@ RGN_TYPE_UI
@ RGN_TYPE_WINDOW
@ RGN_TYPE_FOOTER
@ RGN_TYPE_HEADER
@ RGN_TYPE_TOOLS
@ RGN_FLAG_HIDDEN
@ SPACE_SPREADSHEET
@ SPACE_EMPTY
@ SPREADSHEET_FILTER_ENABLE
eSpaceSpreadsheet_ObjectEvalState
@ SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE
@ SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED
@ SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL
@ SPREADSHEET_VALUE_TYPE_INT8
@ SPREADSHEET_VALUE_TYPE_FLOAT
@ SPREADSHEET_VALUE_TYPE_INT32_2D
@ SPREADSHEET_VALUE_TYPE_BYTE_COLOR
@ SPREADSHEET_VALUE_TYPE_UNKNOWN
@ SPREADSHEET_VALUE_TYPE_FLOAT3
@ SPREADSHEET_VALUE_TYPE_BOOL
@ SPREADSHEET_VALUE_TYPE_STRING
@ SPREADSHEET_VALUE_TYPE_QUATERNION
@ SPREADSHEET_VALUE_TYPE_FLOAT4X4
@ SPREADSHEET_VALUE_TYPE_INT32
@ SPREADSHEET_VALUE_TYPE_FLOAT2
@ SPREADSHEET_VALUE_TYPE_COLOR
@ SPREADSHEET_VALUE_TYPE_INSTANCES
#define SPREADSHEET_WIDTH_UNIT
@ SPREADSHEET_FLAG_PINNED
@ USER_HEADER_BOTTOM
#define UI_SCALE_FAC
@ V2D_ALIGN_NO_NEG_X
@ V2D_ALIGN_NO_POS_Y
@ V2D_SCROLL_HORIZONTAL_HIDE
@ V2D_SCROLL_VERTICAL_HIDE
@ V2D_SCROLL_RIGHT
@ V2D_SCROLL_BOTTOM
@ V2D_KEEPTOT_STRICT
@ V2D_LIMITZOOM
@ V2D_LOCKZOOM_X
@ V2D_KEEPASPECT
@ V2D_LOCKZOOM_Y
@ VIEWER_PATH_ELEM_TYPE_ID
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:708
void ED_region_panels(const bContext *C, ARegion *region)
Definition area.cc:3336
void ED_region_header(const bContext *C, ARegion *region)
Definition area.cc:3646
void ED_region_header_init(ARegion *region)
Definition area.cc:3661
void ED_region_panels_layout(const bContext *C, ARegion *region)
Definition area.cc:3271
void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
Definition area.cc:3343
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
@ ED_KEYMAP_UI
Definition ED_screen.hh:725
@ ED_KEYMAP_HEADER
Definition ED_screen.hh:731
@ ED_KEYMAP_VIEW2D
Definition ED_screen.hh:728
@ ED_KEYMAP_FRAMES
Definition ED_screen.hh:730
void ED_region_panels_draw(const bContext *C, ARegion *region)
Definition area.cc:3277
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define UI_UNIT_Y
#define UI_SIDEBAR_PANEL_WIDTH
@ UI_EMBOSS
@ UI_LAYOUT_ALIGN_RIGHT
void uiItemL(uiLayout *layout, const char *name, int icon)
uiLayout * UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, const uiStyle *style)
const uiStyle * UI_style_get_dpi()
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss)
#define UI_HEADER_OFFSET
const uiStyle * UI_style_get()
void uiItemSpacer(uiLayout *layout)
void UI_block_draw(const bContext *C, uiBlock *block)
@ UI_LAYOUT_HORIZONTAL
@ UI_LAYOUT_HEADER
void UI_panel_category_active_set_default(ARegion *region, const char *idname)
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
#define UI_DEFAULT_TEXT_POINTS
#define UI_UNIT_X
void UI_block_end(const bContext *C, uiBlock *block)
void UI_block_align_end(uiBlock *block)
@ 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:212
@ V2D_COMMONVIEW_LIST
Definition UI_view2d.hh:35
#define NC_GEOM
Definition WM_types.hh:360
#define ND_OB_ACTIVE
Definition WM_types.hh:407
#define NC_VIEWER_PATH
Definition WM_types.hh:373
#define ND_MODE
Definition WM_types.hh:412
#define NC_SCENE
Definition WM_types.hh:345
#define ND_FRAME
Definition WM_types.hh:401
#define NC_GPENCIL
Definition WM_types.hh:366
#define NC_TEXTURE
Definition WM_types.hh:348
#define ND_SPACE_SPREADSHEET
Definition WM_types.hh:507
#define NC_OBJECT
Definition WM_types.hh:346
#define NC_SPACE
Definition WM_types.hh:359
unsigned int U
Definition btGjkEpa3.h:78
T * add(std::unique_ptr< T > resource)
bool add(const Key &key)
Definition BLI_set.hh:248
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
const Depsgraph * depsgraph
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define GS(x)
Definition iris.cc:202
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
static void spreadsheet_header_region_free(ARegion *)
static void spreadsheet_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
static void spreadsheet_free(SpaceLink *sl)
static void spreadsheet_header_region_init(wmWindowManager *, ARegion *region)
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)
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 float get_column_width(const ColumnValues &values)
static void spreadsheet_init(wmWindowManager *, ScrArea *area)
static std::unique_ptr< DataSource > get_data_source(const bContext *C)
std::unique_ptr< DataSource > data_source_from_geometry(const bContext *C, Object *object_eval)
static SpaceLink * spreadsheet_duplicate(SpaceLink *sl)
static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region)
static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region)
static float get_default_column_width(const ColumnValues &values)
Object * spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet, const Depsgraph *depsgraph)
ID * get_current_id(const SpaceSpreadsheet *sspreadsheet)
void spreadsheet_column_free(SpreadsheetColumn *column)
static void spreadsheet_footer_region_init(wmWindowManager *, ARegion *region)
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)
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 update_visible_columns(ListBase &columns, DataSource &data_source)
static void spreadsheet_update_context(const bContext *C)
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)
static float get_column_width_in_pixels(const ColumnValues &values)
static void spreadsheet_header_region_listener(const wmRegionListenerParams *params)
static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region)
void register_row_filter_panels(ARegionType &region_type)
SpreadsheetColumn * spreadsheet_column_copy(const SpreadsheetColumn *src_column)
static void spreadsheet_id_remap(ScrArea *, SpaceLink *slink, const blender::bke::id::IDRemapper &mappings)
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)
void(* free)(ARegion *)
void(* listener)(const wmRegionListenerParams *params)
void(* draw)(const bContext *C, ARegion *region)
void(* layout)(const bContext *C, ARegion *region)
void(* init)(wmWindowManager *wm, ARegion *region)
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
void * first
SpreadsheetInstanceID * instance_ids
SpaceSpreadsheet_Runtime * runtime
ViewerPath viewer_path
uiFontStyle widget
unsigned int data
Definition WM_types.hh:325
unsigned int category
Definition WM_types.hh:325
struct wmKeyConfig * defaultconf
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:897