Blender V4.3
interface_template_list.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
9#include <algorithm>
10#include <cstdlib>
11#include <cstring>
12
13#include "BLI_fnmatch.h"
14#include "BLI_function_ref.hh"
15#include "BLI_listbase.h"
16#include "BLI_math_base.h"
17#include "BLI_string.h"
18#include "BLI_string_ref.hh"
19#include "BLI_utildefines.h"
20#include "BLI_vector.hh"
21
22#include "BKE_screen.hh"
23
24#include "BLT_translation.hh"
25
26#include "ED_screen.hh"
27
28#include "MEM_guardedalloc.h"
29
30#include "RNA_access.hh"
31#include "RNA_prototypes.hh"
32
33#include "UI_interface.hh"
34#include "UI_view2d.hh"
35
36#include "WM_api.hh"
37
38#include "interface_intern.hh"
39
40using namespace blender;
41
52
53 /* Index as stored in the input property. I.e. the index before sorting. */
55};
56
65
71 /* Index of the active item following visual order. I.e. unlike
72 * TemplateListInputData.active_item_idx, this is the index after sorting. */
74};
75
84
86 int visual_items; /* Visual number of items (i.e. number of items we have room to display). */
87 int start_idx; /* Index of first item to display. */
88 int end_idx; /* Index of last item to display + 1. */
89};
90
91static void uilist_draw_item_default(uiList *ui_list,
92 const bContext * /*C*/,
93 uiLayout *layout,
94 PointerRNA * /*dataptr*/,
95 PointerRNA *itemptr,
96 int icon,
97 PointerRNA * /*active_dataptr*/,
98 const char * /*active_propname*/,
99 int /*index*/,
100 int /*flt_flag*/)
101{
102 PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
103
104 /* Simplest one! */
105 switch (ui_list->layout_type) {
107 uiItemL(layout, "", icon);
108 break;
111 default:
112 if (nameprop) {
113 uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon);
114 }
115 else {
116 uiItemL(layout, "", icon);
117 }
118 break;
119 }
120}
121
122static void uilist_draw_filter_default(uiList *ui_list, const bContext * /*C*/, uiLayout *layout)
123{
124 PointerRNA listptr = RNA_pointer_create(nullptr, &RNA_UIList, ui_list);
125
126 uiLayout *row = uiLayoutRow(layout, false);
127
128 uiLayout *subrow = uiLayoutRow(row, true);
129 uiItemR(subrow, &listptr, "filter_name", UI_ITEM_NONE, "", ICON_NONE);
130 uiItemR(subrow,
131 &listptr,
132 "use_filter_invert",
134 "",
135 ICON_ARROW_LEFTRIGHT);
136
137 if ((ui_list->filter_sort_flag & UILST_FLT_SORT_LOCK) == 0) {
138 subrow = uiLayoutRow(row, true);
139 uiItemR(subrow,
140 &listptr,
141 "use_filter_sort_alpha",
143 "",
144 ICON_NONE);
145 uiItemR(subrow,
146 &listptr,
147 "use_filter_sort_reverse",
149 "",
150 (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_SORT_DESC : ICON_SORT_ASC);
151 }
152}
153
155{
156 const char *filter_raw = list.filter_byname;
157
158 if (filter_raw[0]) {
159 const size_t slen = strlen(filter_raw);
160
161 /* Implicitly add heading/trailing wildcards if needed. */
162 if (slen + 3 <= sizeof(storage_.filter_buff)) {
163 filter_ = storage_.filter_buff;
164 }
165 else {
166 filter_ = storage_.filter_dyn = static_cast<char *>(
167 MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn"));
168 }
169 BLI_strncpy_ensure_pad(filter_, filter_raw, '*', slen + 3);
170 }
171}
172
174{
175 MEM_SAFE_FREE(storage_.filter_dyn);
176}
177
179 StringRefNull name,
180 int /*index*/)
181{
182 if (!filter_) {
184 }
185
186 /* Use `fnmatch` for shell-style globing.
187 * - Case-insensitive.
188 * - Don't handle escape characters as "special" characters are not expected in names.
189 * Unlike shell input - `\` should be treated like any other character.
190 */
191 const int fn_flag = FNM_CASEFOLD | FNM_NOESCAPE;
192 if (fnmatch(filter_, name.c_str(), fn_flag) == 0) {
194 }
196}
197
198struct StringCmp {
199 char name[MAX_IDPROP_NAME];
201};
202
203static int cmpstringp(const void *p1, const void *p2)
204{
205 /* Case-insensitive comparison. */
206 return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name);
207}
208
210 const bContext * /*C*/,
211 uiListItemFilterFn item_filter_fn,
212 PointerRNA *dataptr,
213 const char *propname,
214 uiListItemGetNameFn get_name_fn)
215{
216 uiListDyn *dyn_data = ui_list->dyn_data;
217 PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
218
219 const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
220 const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) ==
222 const int len = RNA_property_collection_length(dataptr, prop);
223
224 dyn_data->items_shown = dyn_data->items_len = len;
225
226 if (len && (order_by_name || item_filter_fn)) {
227 StringCmp *names = nullptr;
228 int order_idx = 0, i = 0;
229
230 if (order_by_name) {
231 names = static_cast<StringCmp *>(MEM_callocN(sizeof(StringCmp) * len, "StringCmp"));
232 }
233
234 if (item_filter_fn) {
235 dyn_data->items_filter_flags = static_cast<int *>(
236 MEM_callocN(sizeof(int) * len, "items_filter_flags"));
237 dyn_data->items_shown = 0;
238 }
239
240 RNA_PROP_BEGIN (dataptr, itemptr, prop) {
241 bool do_order = false;
242
243 char *namebuf;
244 if (get_name_fn) {
245 namebuf = BLI_strdup(get_name_fn(itemptr, i).c_str());
246 }
247 else {
248 namebuf = RNA_struct_name_get_alloc(&itemptr, nullptr, 0, nullptr);
249 }
250
251 const char *name = namebuf ? namebuf : "";
252
253 if (item_filter_fn) {
254 const eUIListFilterResult filter_result = item_filter_fn(itemptr, name, i);
255
256 if (filter_result == UI_LIST_ITEM_NEVER_SHOW) {
258 }
259 else if (filter_result == UI_LIST_ITEM_FILTER_MATCHES) {
260 dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
261 if (!filter_exclude) {
262 dyn_data->items_shown++;
263 do_order = order_by_name;
264 }
265 // printf("%s: '%s' matches '%s'\n", __func__, name, filter);
266 }
267 else if (filter_exclude) {
268 dyn_data->items_shown++;
269 do_order = order_by_name;
270 }
271 }
272 else {
273 do_order = order_by_name;
274 }
275
276 if (do_order) {
277 names[order_idx].org_idx = order_idx;
278 STRNCPY(names[order_idx++].name, name);
279 }
280
281 /* free name */
282 if (namebuf) {
283 MEM_freeN(namebuf);
284 }
285 i++;
286 }
288
289 if (order_by_name) {
290 int new_idx;
291 /* NOTE: order_idx equals either to ui_list->items_len if no filtering done,
292 * or to ui_list->items_shown if filter is enabled,
293 * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded.
294 * This way, we only sort items we actually intend to draw!
295 */
296 qsort(names, order_idx, sizeof(StringCmp), cmpstringp);
297
298 dyn_data->items_filter_neworder = static_cast<int *>(
299 MEM_mallocN(sizeof(int) * order_idx, "items_filter_neworder"));
300 for (new_idx = 0; new_idx < order_idx; new_idx++) {
301 dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx;
302 }
303 }
304
305 if (names) {
306 MEM_freeN(names);
307 }
308 }
309}
310
311bool UI_list_item_index_is_filtered_visible(const uiList *ui_list, const int item_idx)
312{
313 const uiListDyn *dyn_data = ui_list->dyn_data;
314
315 if (!dyn_data->items_filter_flags) {
316 /* If there are no filter flags to check, always consider all items visible. */
317 return true;
318 }
319
320 if (dyn_data->items_filter_flags[item_idx] & UILST_FLT_ITEM_NEVER_SHOW) {
321 return false;
322 }
323
324 const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
325 return (dyn_data->items_filter_flags[item_idx] & UILST_FLT_ITEM) ^ filter_exclude;
326}
327
332 const bContext *C,
333 PointerRNA *dataptr,
334 const char *propname)
335{
336 if (ui_list->filter_byname[0]) {
337 uiListNameFilter name_filter(*ui_list);
338 UI_list_filter_and_sort_items(ui_list, C, name_filter, dataptr, propname);
339 }
340 /* Optimization: Skip filtering entirely when there is no filter string set. */
341 else {
342 UI_list_filter_and_sort_items(ui_list, C, nullptr, dataptr, propname);
343 }
344}
345
346static void uilist_free_dyn_data(uiList *ui_list)
347{
348 uiListDyn *dyn_data = ui_list->dyn_data;
349 if (!dyn_data) {
350 return;
351 }
352
353 if (dyn_data->custom_activate_opptr) {
356 }
357 if (dyn_data->custom_drag_opptr) {
359 MEM_freeN(dyn_data->custom_drag_opptr);
360 }
361
364 MEM_SAFE_FREE(dyn_data->customdata);
365}
366
373static bool ui_template_list_data_retrieve(const char *listtype_name,
374 const char *list_id,
375 PointerRNA *dataptr,
376 const char *propname,
377 PointerRNA *active_dataptr,
378 const char *active_propname,
379 const char *item_dyntip_propname,
380 TemplateListInputData *r_input_data,
381 uiListType **r_list_type)
382{
383 *r_input_data = {};
384
385 /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
386 if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
387 RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
389 return false;
390 }
391
392 if (!active_dataptr->data) {
393 RNA_warning("No active data");
394 return false;
395 }
396
397 r_input_data->dataptr = *dataptr;
398 if (dataptr->data) {
399 r_input_data->prop = RNA_struct_find_property(dataptr, propname);
400 if (!r_input_data->prop) {
401 RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
402 return false;
403 }
404 }
405
406 r_input_data->active_dataptr = *active_dataptr;
407 r_input_data->activeprop = RNA_struct_find_property(active_dataptr, active_propname);
408 if (!r_input_data->activeprop) {
410 "Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
411 return false;
412 }
413
414 if (r_input_data->prop) {
415 const PropertyType type = RNA_property_type(r_input_data->prop);
416 if (type != PROP_COLLECTION) {
417 RNA_warning("Expected a collection data property");
418 return false;
419 }
420 }
421
422 const PropertyType activetype = RNA_property_type(r_input_data->activeprop);
423 if (activetype != PROP_INT) {
424 RNA_warning("Expected an integer active data property");
425 return false;
426 }
427
428 /* Find the uiList type. */
429 if (!(*r_list_type = WM_uilisttype_find(listtype_name, false))) {
430 RNA_warning("List type %s not found", listtype_name);
431 return false;
432 }
433
434 r_input_data->active_item_idx = RNA_property_int_get(&r_input_data->active_dataptr,
435 r_input_data->activeprop);
436 r_input_data->item_dyntip_propname = item_dyntip_propname;
437
438 return true;
439}
440
442 PropertyRNA *list_prop,
443 const uiList *ui_list,
444 int activei,
445 TemplateListItems *r_items)
446{
447 const uiListDyn *dyn_data = ui_list->dyn_data;
448 const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
449 int i = 0;
450 int reorder_i = 0;
451 bool activei_mapping_pending = true;
452
453 RNA_PROP_BEGIN (list_ptr, itemptr, list_prop) {
455 int new_order_idx;
456 if (dyn_data->items_filter_neworder) {
457 new_order_idx = dyn_data->items_filter_neworder[reorder_i++];
458 new_order_idx = order_reverse ? dyn_data->items_shown - new_order_idx - 1 : new_order_idx;
459 }
460 else {
461 new_order_idx = order_reverse ? dyn_data->items_shown - ++reorder_i : reorder_i++;
462 }
463 // printf("%s: ii: %d\n", __func__, ii);
464 r_items->item_vec[new_order_idx].item = itemptr;
465 r_items->item_vec[new_order_idx].org_idx = i;
466 r_items->item_vec[new_order_idx].flt_flag = dyn_data->items_filter_flags ?
467 dyn_data->items_filter_flags[i] :
468 0;
469
470 if (activei_mapping_pending && activei == i) {
471 activei = new_order_idx;
472 /* So that we do not map again activei! */
473 activei_mapping_pending = false;
474 }
475#if 0 /* For now, do not alter active element, even if it will be hidden... */
476 else if (activei < i) {
477 /* We do not want an active but invisible item!
478 * Only exception is when all items are filtered out...
479 */
480 if (prev_order_idx >= 0) {
481 activei = prev_order_idx;
482 RNA_property_int_set(active_dataptr, activeprop, prev_i);
483 }
484 else {
485 activei = new_order_idx;
486 RNA_property_int_set(active_dataptr, activeprop, i);
487 }
488 }
489 prev_i = i;
490 prev_ii = new_order_idx;
491#endif
492 }
493 i++;
494 }
496
497 /* If mapping is still pending, no active item was found. Mark as invalid (-1) */
498 r_items->active_item_idx = activei_mapping_pending ? -1 : activei;
499}
500
505 uiList *ui_list,
506 TemplateListInputData *input_data,
507 const uiListFilterItemsFunc filter_items_fn,
508 TemplateListItems *r_items)
509{
510 uiListDyn *dyn_data = ui_list->dyn_data;
511
512 /* Filter list items! (not for compact layout, though) */
513 if (input_data->dataptr.data && input_data->prop) {
514 int items_shown;
515#if 0
516 int prev_ii = -1, prev_i;
517#endif
518
519 if (ui_list->layout_type == UILST_LAYOUT_COMPACT) {
521 &input_data->dataptr, input_data->prop);
522 }
523 else {
524 // printf("%s: filtering...\n", __func__);
525 filter_items_fn(ui_list, C, &input_data->dataptr, RNA_property_identifier(input_data->prop));
526 // printf("%s: filtering done.\n", __func__);
527 }
528
529 items_shown = dyn_data->items_shown;
530 if (items_shown >= 0) {
531 r_items->item_vec.resize(items_shown);
532 // printf("%s: items shown: %d.\n", __func__, items_shown);
533
535 &input_data->dataptr, input_data->prop, ui_list, input_data->active_item_idx, r_items);
536 }
537 }
538}
539
540static void uilist_prepare(uiList *ui_list,
541 const TemplateListItems *items,
542 const TemplateListLayoutDrawData *layout_data,
543 TemplateListVisualInfo *r_visual_info)
544{
545 uiListDyn *dyn_data = ui_list->dyn_data;
546 const bool use_auto_size = (ui_list->list_grip <
547 (layout_data->rows - UI_LIST_AUTO_SIZE_THRESHOLD));
548
549 int actual_rows = layout_data->rows;
550 int actual_maxrows = layout_data->maxrows;
551 int columns = layout_data->columns;
552
553 /* default rows */
554 if (actual_rows <= 0) {
555 actual_rows = 5;
556 }
557 dyn_data->visual_height_min = actual_rows;
558 if (actual_maxrows < actual_rows) {
559 actual_maxrows = max_ii(actual_rows, 5);
560 }
561 if (columns <= 0) {
562 columns = 9;
563 }
564
565 int activei_row;
566 if (columns > 1) {
567 dyn_data->height = int(ceil(double(items->item_vec.size()) / double(columns)));
568 activei_row = int(floor(double(items->active_item_idx) / double(columns)));
569 }
570 else {
571 dyn_data->height = items->item_vec.size();
572 activei_row = items->active_item_idx;
573 }
574
575 dyn_data->columns = columns;
576
577 if (!use_auto_size) {
578 /* No auto-size, yet we clamp at min size! */
579 actual_rows = max_ii(ui_list->list_grip, actual_rows);
580 }
581 else if ((actual_rows != actual_maxrows) && (dyn_data->height > actual_rows)) {
582 /* Expand size if needed and possible. */
583 actual_rows = min_ii(dyn_data->height, actual_maxrows);
584 }
585
586 /* If list length changes or list is tagged to check this,
587 * and active is out of view, scroll to it. */
588 if ((ui_list->list_last_len != items->item_vec.size()) ||
590 {
591 if (activei_row < ui_list->list_scroll) {
592 ui_list->list_scroll = activei_row;
593 }
594 else if (activei_row >= ui_list->list_scroll + actual_rows) {
595 ui_list->list_scroll = activei_row - actual_rows + 1;
596 }
597 ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
598 }
599
600 const int max_scroll = max_ii(0, dyn_data->height - actual_rows);
601 CLAMP(ui_list->list_scroll, 0, max_scroll);
602 ui_list->list_last_len = items->item_vec.size();
603 dyn_data->visual_height = actual_rows;
604 r_visual_info->visual_items = actual_rows * columns;
605 r_visual_info->start_idx = ui_list->list_scroll * columns;
606 r_visual_info->end_idx = min_ii(r_visual_info->start_idx + actual_rows * columns,
607 items->item_vec.size());
608}
609
610static void uilist_resize_update(bContext *C, uiList *ui_list)
611{
612 uiListDyn *dyn_data = ui_list->dyn_data;
613
614 /* This way we get diff in number of additional items to show (positive) or hide (negative). */
615 const int diff = round_fl_to_int(float(dyn_data->resize - dyn_data->resize_prev) /
616 float(UI_UNIT_Y));
617
618 if (diff != 0) {
619 ui_list->list_grip += diff;
620 dyn_data->resize_prev += diff * UI_UNIT_Y;
622 }
623
624 /* In case uilist is in popup, we need special refreshing */
626}
627
628static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)
629{
630 if (propname && propname[0] && itemptr && itemptr->data) {
631 PropertyRNA *prop = RNA_struct_find_property(itemptr, propname);
632
633 if (prop && (RNA_property_type(prop) == PROP_STRING)) {
634 return RNA_property_string_get_alloc(itemptr, prop, nullptr, 0, nullptr);
635 }
636 }
637 return nullptr;
638}
639
640static std::string uilist_item_tooltip_func(bContext * /*C*/, void *argN, const char *tip)
641{
642 char *dyn_tooltip = static_cast<char *>(argN);
643 std::string tooltip_string = dyn_tooltip;
644 if (tip && tip[0]) {
645 tooltip_string += '\n';
646 tooltip_string += tip;
647 }
648 return tooltip_string;
649}
650
655 uiListType *ui_list_type,
656 const char *list_id,
657 int layout_type,
658 bool sort_reverse,
659 bool sort_lock)
660{
661 /* Allows to work in popups. */
662 ARegion *region = CTX_wm_region_popup(C);
663 if (region == nullptr) {
664 region = CTX_wm_region(C);
665 }
666
667 /* Find or add the uiList to the current Region. */
668
669 char full_list_id[UI_MAX_NAME_STR];
670 WM_uilisttype_to_full_list_id(ui_list_type, list_id, full_list_id);
671
672 uiList *ui_list = static_cast<uiList *>(
673 BLI_findstring(&region->ui_lists, full_list_id, offsetof(uiList, list_id)));
674
675 if (!ui_list) {
676 ui_list = static_cast<uiList *>(MEM_callocN(sizeof(uiList), "uiList"));
677 STRNCPY(ui_list->list_id, full_list_id);
678 BLI_addtail(&region->ui_lists, ui_list);
679 ui_list->list_grip = -UI_LIST_AUTO_SIZE_THRESHOLD; /* Force auto size by default. */
680 if (sort_reverse) {
682 }
683 if (sort_lock) {
685 }
686 }
687
688 if (!ui_list->dyn_data) {
689 ui_list->dyn_data = static_cast<uiListDyn *>(
690 MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data"));
691 }
692 uiListDyn *dyn_data = ui_list->dyn_data;
693 /* Note that this isn't a `uiListType` callback, it's stored in the runtime list data. Otherwise
694 * the runtime data could leak when the type is unregistered (e.g. on "Reload Scripts"). */
696
697 /* Because we can't actually pass type across save&load... */
698 ui_list->type = ui_list_type;
699 ui_list->layout_type = layout_type;
700
701 /* Reset filtering data. */
704 dyn_data->items_len = dyn_data->items_shown = -1;
705
706 return ui_list;
707}
708
710 uiList *ui_list,
711 uiLayout *layout,
712 TemplateListInputData *input_data,
713 TemplateListItems *items,
714 const TemplateListLayoutDrawData *layout_data,
715 const enum uiTemplateListFlags flags)
716{
717 uiListDyn *dyn_data = ui_list->dyn_data;
718 const char *active_propname = RNA_property_identifier(input_data->activeprop);
719
720 uiLayout *glob = nullptr, *box, *row, *col, *subrow, *sub, *overlap;
721 char numstr[32];
722 int rnaicon = ICON_NONE, icon = ICON_NONE;
723 uiBut *but;
724
725 uiBlock *block = uiLayoutGetBlock(layout);
726
727 /* get icon */
728 if (input_data->dataptr.data && input_data->prop) {
729 StructRNA *ptype = RNA_property_pointer_type(&input_data->dataptr, input_data->prop);
730 rnaicon = RNA_struct_ui_icon(ptype);
731 }
732
733 TemplateListVisualInfo visual_info;
734 switch (ui_list->layout_type) {
736 /* layout */
737 box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
738 glob = uiLayoutColumn(box, true);
739 row = uiLayoutRow(glob, false);
740 col = uiLayoutColumn(row, true);
741
742 TemplateListLayoutDrawData adjusted_layout_data = *layout_data;
743 adjusted_layout_data.columns = 1;
744 /* init numbers */
745 uilist_prepare(ui_list, items, &adjusted_layout_data, &visual_info);
746
747 int i = 0;
748 if (input_data->dataptr.data && input_data->prop) {
749
750 const bool editable = (RNA_property_flag(input_data->prop) & PROP_EDITABLE);
751
752 /* create list items */
753 for (i = visual_info.start_idx; i < visual_info.end_idx; i++) {
754 PointerRNA *itemptr = &items->item_vec[i].item;
755 void *dyntip_data;
756 const int org_i = items->item_vec[i].org_idx;
757 const int flt_flag = items->item_vec[i].flt_flag;
758 uiBlock *subblock = uiLayoutGetBlock(col);
759
760 overlap = uiLayoutOverlap(col);
761
763
764 /* list item behind label & other buttons */
765 uiLayoutRow(overlap, false);
766
767 but = uiDefButR_prop(subblock,
769 0,
770 "",
771 0,
772 0,
773 UI_UNIT_X * 10,
774 UI_UNIT_Y,
775 &input_data->active_dataptr,
776 input_data->activeprop,
777 0,
778 0,
779 org_i,
780 editable ? TIP_("Select List Item "
781 "(Double click to rename)") :
782 TIP_("Select List Item"));
783
784 if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr,
785 input_data->item_dyntip_propname)))
786 {
788 }
789
790 uiLayout *item_row = uiLayoutRow(overlap, true);
791
793
794 sub = uiLayoutRow(item_row, false);
795 icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
796 if (icon == ICON_DOT) {
797 icon = ICON_NONE;
798 }
799 layout_data->draw_item(ui_list,
800 C,
801 sub,
802 &input_data->dataptr,
803 itemptr,
804 icon,
805 &input_data->active_dataptr,
806 active_propname,
807 org_i,
808 flt_flag);
809
810 /* Items should be able to set context pointers for the layout. But the list-row button
811 * swallows events, so it needs the context storage too for handlers to see it. */
813
814 /* If we are "drawing" active item, set all labels as active. */
815 if (i == items->active_item_idx) {
817 }
818
821 }
822 }
823
824 /* add dummy buttons to fill space */
825 for (; i < visual_info.start_idx + visual_info.visual_items; i++) {
826 uiItemL(col, "", ICON_NONE);
827 }
828
829 /* Add scroll-bar. */
830 if (items->item_vec.size() > visual_info.visual_items) {
831 uiLayoutColumn(row, false);
832 but = uiDefButI(block,
834 0,
835 "",
836 0,
837 0,
839 UI_UNIT_Y * dyn_data->visual_height,
840 &ui_list->list_scroll,
841 0,
842 dyn_data->height - dyn_data->visual_height,
843 "");
844 uiButScrollBar *but_scroll = reinterpret_cast<uiButScrollBar *>(but);
845 but_scroll->visual_height = dyn_data->visual_height;
846 }
847 break;
848 }
850 row = uiLayoutRow(layout, true);
851
852 if ((input_data->dataptr.data && input_data->prop) && (dyn_data->items_shown > 0) &&
853 (items->active_item_idx >= 0) && (items->active_item_idx < dyn_data->items_shown))
854 {
855 PointerRNA *itemptr = &items->item_vec[items->active_item_idx].item;
856 const int org_i = items->item_vec[items->active_item_idx].org_idx;
857
858 icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
859 if (icon == ICON_DOT) {
860 icon = ICON_NONE;
861 }
862 layout_data->draw_item(ui_list,
863 C,
864 row,
865 &input_data->dataptr,
866 itemptr,
867 icon,
868 &input_data->active_dataptr,
869 active_propname,
870 org_i,
871 0);
872 }
873 /* if list is empty, add in dummy button */
874 else {
875 uiItemL(row, "", ICON_NONE);
876 }
877
878 /* next/prev button */
879 SNPRINTF(numstr, "%d :", dyn_data->items_shown);
880 but = uiDefIconTextButR_prop(block,
882 0,
883 ICON_NONE,
884 numstr,
885 0,
886 0,
887 UI_UNIT_X * 5,
888 UI_UNIT_Y,
889 &input_data->active_dataptr,
890 input_data->activeprop,
891 0,
892 0,
893 0,
894 "");
895 if (dyn_data->items_shown == 0) {
897 }
898 break;
899 case UILST_LAYOUT_GRID: {
900 box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
901 glob = uiLayoutColumn(box, true);
902 row = uiLayoutRow(glob, false);
903 col = uiLayoutColumn(row, true);
904 subrow = nullptr; /* Quite gcc warning! */
905
906 uilist_prepare(ui_list, items, layout_data, &visual_info);
907
908 int i = 0;
909 if (input_data->dataptr.data && input_data->prop) {
910 /* create list items */
911 for (i = visual_info.start_idx; i < visual_info.end_idx; i++) {
912 PointerRNA *itemptr = &items->item_vec[i].item;
913 const int org_i = items->item_vec[i].org_idx;
914 const int flt_flag = items->item_vec[i].flt_flag;
915
916 /* create button */
917 if (!(i % layout_data->columns)) {
918 subrow = uiLayoutRow(col, false);
919 }
920
921 uiBlock *subblock = uiLayoutGetBlock(subrow);
922 overlap = uiLayoutOverlap(subrow);
923
925
926 /* list item behind label & other buttons */
927 uiLayoutRow(overlap, false);
928
929 but = uiDefButR_prop(subblock,
931 0,
932 "",
933 0,
934 0,
935 UI_UNIT_X * 10,
936 UI_UNIT_Y,
937 &input_data->active_dataptr,
938 input_data->activeprop,
939 0,
940 0,
941 org_i,
942 nullptr);
944
945 sub = uiLayoutRow(overlap, false);
946
947 icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
948 layout_data->draw_item(ui_list,
949 C,
950 sub,
951 &input_data->dataptr,
952 itemptr,
953 icon,
954 &input_data->active_dataptr,
955 active_propname,
956 org_i,
957 flt_flag);
958
959 /* If we are "drawing" active item, set all labels as active. */
960 if (i == items->active_item_idx) {
962 }
963
965 }
966 }
967
968 /* add dummy buttons to fill space */
969 for (; i < visual_info.start_idx + visual_info.visual_items; i++) {
970 if (!(i % layout_data->columns)) {
971 subrow = uiLayoutRow(col, false);
972 }
973 uiItemL(subrow, "", ICON_NONE);
974 }
975
976 /* Add scroll-bar. */
977 if (items->item_vec.size() > visual_info.visual_items) {
978 /* col = */ uiLayoutColumn(row, false);
979 but = uiDefButI(block,
981 0,
982 "",
983 0,
984 0,
986 UI_UNIT_Y * dyn_data->visual_height,
987 &ui_list->list_scroll,
988 0,
989 dyn_data->height - dyn_data->visual_height,
990 "");
991 uiButScrollBar *but_scroll = reinterpret_cast<uiButScrollBar *>(but);
992 but_scroll->visual_height = dyn_data->visual_height;
993 }
994 break;
995 }
997 box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
998 /* For grip button. */
999 glob = uiLayoutColumn(box, true);
1000 /* For scroll-bar. */
1001 row = uiLayoutRow(glob, false);
1002
1003 const bool show_names = (flags & UI_TEMPLATE_LIST_NO_NAMES) == 0;
1004
1005 const int size_x = UI_preview_tile_size_x();
1006 const int size_y = show_names ? UI_preview_tile_size_y() : UI_preview_tile_size_y_no_label();
1007
1008 const int cols_per_row = std::max(int((uiLayoutGetWidth(box) - V2D_SCROLL_WIDTH) / size_x),
1009 1);
1010 uiLayout *grid = uiLayoutGridFlow(row, true, cols_per_row, true, true, true);
1011
1012 TemplateListLayoutDrawData adjusted_layout_data = *layout_data;
1013 adjusted_layout_data.columns = cols_per_row;
1014 uilist_prepare(ui_list, items, &adjusted_layout_data, &visual_info);
1015
1016 if (input_data->dataptr.data && input_data->prop) {
1017 /* create list items */
1018 for (int i = visual_info.start_idx; i < visual_info.end_idx; i++) {
1019 PointerRNA *itemptr = &items->item_vec[i].item;
1020 const int org_i = items->item_vec[i].org_idx;
1021 const int flt_flag = items->item_vec[i].flt_flag;
1022
1023 overlap = uiLayoutOverlap(grid);
1024 col = uiLayoutColumn(overlap, false);
1025
1026 uiBlock *subblock = uiLayoutGetBlock(col);
1028
1029 but = uiDefButR_prop(subblock,
1031 0,
1032 "",
1033 0,
1034 0,
1035 size_x,
1036 size_y,
1037 &input_data->active_dataptr,
1038 input_data->activeprop,
1039 0,
1040 0,
1041 org_i,
1042 nullptr);
1044
1045 col = uiLayoutColumn(overlap, false);
1046
1047 icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
1048 layout_data->draw_item(ui_list,
1049 C,
1050 col,
1051 &input_data->dataptr,
1052 itemptr,
1053 icon,
1054 &input_data->active_dataptr,
1055 active_propname,
1056 org_i,
1057 flt_flag);
1058
1059 /* Items should be able to set context pointers for the layout. But the list-row button
1060 * swallows events, so it needs the context storage too for handlers to see it. */
1062
1063 /* If we are "drawing" active item, set all labels as active. */
1064 if (i == items->active_item_idx) {
1066 }
1067
1069 }
1070 }
1071
1072 if (items->item_vec.size() > visual_info.visual_items) {
1073 /* col = */ uiLayoutColumn(row, false);
1074 but = uiDefButI(block,
1076 0,
1077 "",
1078 0,
1079 0,
1081 size_y * dyn_data->visual_height,
1082 &ui_list->list_scroll,
1083 0,
1084 dyn_data->height - dyn_data->visual_height,
1085 "");
1086 uiButScrollBar *but_scroll = reinterpret_cast<uiButScrollBar *>(but);
1087 but_scroll->visual_height = dyn_data->visual_height;
1088 }
1089 break;
1090 }
1091
1092 const bool add_filters_but = (flags & UI_TEMPLATE_LIST_NO_FILTER_OPTIONS) == 0;
1093 if (glob && add_filters_but) {
1094 const bool add_grip_but = (flags & UI_TEMPLATE_LIST_NO_GRIP) == 0;
1095
1096 /* About #UI_BTYPE_GRIP drag-resize:
1097 * We can't directly use results from a grip button, since we have a
1098 * rather complex behavior here (sizing by discrete steps and, overall, auto-size feature).
1099 * Since we *never* know whether we are grip-resizing or not
1100 * (because there is no callback for when a button enters/leaves its "edit mode"),
1101 * we use the fact that grip-controlled value (dyn_data->resize) is completely handled
1102 * by the grip during the grab resize, so settings its value here has no effect at all.
1103 *
1104 * It is only meaningful when we are not resizing,
1105 * in which case this gives us the correct "init drag" value.
1106 * Note we cannot affect `dyn_data->resize_prev here`,
1107 * since this value is not controlled by the grip!
1108 */
1109 dyn_data->resize = dyn_data->resize_prev +
1110 (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y;
1111
1112 row = uiLayoutRow(glob, true);
1113 uiBlock *subblock = uiLayoutGetBlock(row);
1115
1116 if (ui_list->filter_flag & UILST_FLT_SHOW) {
1117 but = uiDefIconButBitI(subblock,
1120 0,
1121 ICON_DISCLOSURE_TRI_DOWN,
1122 0,
1123 0,
1124 UI_UNIT_X,
1125 UI_UNIT_Y * 0.5f,
1126 &(ui_list->filter_flag),
1127 0,
1128 0,
1129 TIP_("Hide filtering options"));
1130 UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
1131
1132 if (add_grip_but) {
1133 but = uiDefIconButI(subblock,
1135 0,
1136 ICON_GRIP,
1137 0,
1138 0,
1139 UI_UNIT_X * 10.0f,
1140 UI_UNIT_Y * 0.5f,
1141 &dyn_data->resize,
1142 0.0,
1143 0.0,
1144 "");
1145 UI_but_func_set(but, [ui_list](bContext &C) { uilist_resize_update(&C, ui_list); });
1146 }
1147
1148 UI_block_emboss_set(subblock, UI_EMBOSS);
1149
1150 col = uiLayoutColumn(glob, false);
1151 subblock = uiLayoutGetBlock(col);
1152 uiDefBut(subblock,
1154 0,
1155 "",
1156 0,
1157 0,
1158 UI_UNIT_X,
1159 UI_UNIT_Y * 0.05f,
1160 nullptr,
1161 0.0,
1162 0.0,
1163 "");
1164
1165 layout_data->draw_filter(ui_list, C, col);
1166 }
1167 else {
1168 but = uiDefIconButBitI(subblock,
1171 0,
1172 ICON_DISCLOSURE_TRI_RIGHT,
1173 0,
1174 0,
1175 UI_UNIT_X,
1176 UI_UNIT_Y * 0.5f,
1177 &(ui_list->filter_flag),
1178 0,
1179 0,
1180 TIP_("Show filtering options"));
1181 UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
1182
1183 if (add_grip_but) {
1184 but = uiDefIconButI(subblock,
1186 0,
1187 ICON_GRIP,
1188 0,
1189 0,
1190 UI_UNIT_X * 10.0f,
1191 UI_UNIT_Y * 0.5f,
1192 &dyn_data->resize,
1193 0.0,
1194 0.0,
1195 "");
1196 UI_but_func_set(but, [ui_list](bContext &C) { uilist_resize_update(&C, ui_list); });
1197 }
1198
1199 UI_block_emboss_set(subblock, UI_EMBOSS);
1200 }
1201 }
1202}
1203
1205 const bContext *C,
1206 const char *listtype_name,
1207 const char *list_id,
1208 PointerRNA *dataptr,
1209 const char *propname,
1210 PointerRNA *active_dataptr,
1211 const char *active_propname,
1212 const char *item_dyntip_propname,
1213 int rows,
1214 int maxrows,
1215 int layout_type,
1216 int columns,
1217 enum uiTemplateListFlags flags,
1218 void *customdata)
1219{
1220 TemplateListInputData input_data = {};
1221 uiListType *ui_list_type;
1222 if (!ui_template_list_data_retrieve(listtype_name,
1223 list_id,
1224 dataptr,
1225 propname,
1226 active_dataptr,
1227 active_propname,
1228 item_dyntip_propname,
1229 &input_data,
1230 &ui_list_type))
1231 {
1232 return nullptr;
1233 }
1234
1235 uiListDrawItemFunc draw_item = ui_list_type->draw_item ? ui_list_type->draw_item :
1237 uiListDrawFilterFunc draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter :
1239 uiListFilterItemsFunc filter_items = ui_list_type->filter_items ? ui_list_type->filter_items :
1241
1242 uiList *ui_list = ui_list_ensure(C,
1243 ui_list_type,
1244 list_id,
1245 layout_type,
1248 uiListDyn *dyn_data = ui_list->dyn_data;
1249
1250 MEM_SAFE_FREE(dyn_data->customdata);
1251 dyn_data->customdata = customdata;
1252
1253 /* When active item changed since last draw, scroll to it. */
1254 if (input_data.active_item_idx != ui_list->list_last_activei) {
1256 ui_list->list_last_activei = input_data.active_item_idx;
1257 }
1258
1259 TemplateListItems items;
1260 ui_template_list_collect_display_items(C, ui_list, &input_data, filter_items, &items);
1261
1262 TemplateListLayoutDrawData layout_data;
1263 layout_data.draw_item = draw_item;
1264 layout_data.draw_filter = draw_filter;
1265 layout_data.rows = rows;
1266 layout_data.maxrows = maxrows;
1267 layout_data.columns = columns;
1268
1269 ui_template_list_layout_draw(C, ui_list, layout, &input_data, &items, &layout_data, flags);
1270
1271 return ui_list;
1272}
1273
1275 const bContext *C,
1276 const char *listtype_name,
1277 const char *list_id,
1278 PointerRNA *dataptr,
1279 const char *propname,
1280 PointerRNA *active_dataptr,
1281 const char *active_propname,
1282 const char *item_dyntip_propname,
1283 int rows,
1284 int maxrows,
1285 int layout_type,
1286 int columns,
1287 enum uiTemplateListFlags flags)
1288{
1289 uiTemplateList_ex(layout,
1290 C,
1291 listtype_name,
1292 list_id,
1293 dataptr,
1294 propname,
1295 active_dataptr,
1296 active_propname,
1297 item_dyntip_propname,
1298 rows,
1299 maxrows,
1300 layout_type,
1301 columns,
1302 flags,
1303 nullptr);
1304}
1305
1307 const char *opname,
1308 bool create_properties)
1309{
1310 uiListDyn *dyn_data = ui_list->dyn_data;
1311 dyn_data->custom_activate_optype = WM_operatortype_find(opname, false);
1312 if (!dyn_data->custom_activate_optype) {
1313 return nullptr;
1314 }
1315
1316 if (create_properties) {
1317 PointerRNA *opptr = dyn_data->custom_activate_opptr;
1319 &dyn_data->custom_activate_opptr, opptr ? (IDProperty **)&opptr->data : nullptr, opname);
1320 }
1321
1322 return dyn_data->custom_activate_opptr;
1323}
1324
1326 const char *opname,
1327 bool create_properties)
1328{
1329 uiListDyn *dyn_data = ui_list->dyn_data;
1330 dyn_data->custom_drag_optype = WM_operatortype_find(opname, false);
1331 if (!dyn_data->custom_drag_optype) {
1332 return nullptr;
1333 }
1334
1335 if (create_properties) {
1336 PointerRNA *opptr = dyn_data->custom_drag_opptr;
1338 &dyn_data->custom_drag_opptr, opptr ? (IDProperty **)&opptr->data : nullptr, opname);
1339 }
1340
1341 return dyn_data->custom_drag_opptr;
1342}
1343
1344/* -------------------------------------------------------------------- */
1345
1354
ARegion * CTX_wm_region_popup(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
void(*)(uiList *ui_list, const bContext *C, PointerRNA *, const char *propname) uiListFilterItemsFunc
void(*)(uiList *ui_list, const bContext *C, uiLayout *layout) uiListDrawFilterFunc
void(*)(uiList *ui_list, const bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr, int icon, PointerRNA *active_dataptr, const char *active_propname, int index, int flt_flag) uiListDrawItemFunc
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
MINLINE int round_fl_to_int(float a)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
int char char int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char char * BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, char pad, size_t dst_maxncpy) ATTR_NONNULL(1
#define CLAMP(a, b, c)
#define STREQ(a, b)
#define TIP_(msgid)
#define MAX_IDPROP_NAME
Definition DNA_ID.h:185
@ UILST_FLT_ITEM
@ UILST_FLT_ITEM_NEVER_SHOW
@ UILST_SCROLL_TO_ACTIVE_ITEM
@ UILST_LAYOUT_COMPACT
@ UILST_LAYOUT_DEFAULT
@ UILST_LAYOUT_BIG_PREVIEW_GRID
@ UILST_LAYOUT_GRID
@ UILST_FLT_SORT_LOCK
@ UILST_FLT_SORT_ALPHA
@ UILST_FLT_SORT_REVERSE
#define UI_LIST_AUTO_SIZE_THRESHOLD
@ UILST_FLT_EXCLUDE
@ UILST_FLT_SHOW
#define UILST_FLT_SORT_MASK
void ED_region_tag_refresh_ui(ARegion *region)
Definition area.cc:662
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define RNA_PROP_END
#define RNA_PROP_BEGIN(sptr, itemptr, prop)
#define RNA_warning(format,...)
PropertyType
Definition RNA_types.hh:64
@ PROP_INT
Definition RNA_types.hh:66
@ PROP_STRING
Definition RNA_types.hh:68
@ PROP_COLLECTION
Definition RNA_types.hh:71
@ PROP_EDITABLE
Definition RNA_types.hh:207
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
eUIListFilterResult
@ UI_LIST_ITEM_FILTER_MISMATCHES
@ UI_LIST_ITEM_NEVER_SHOW
@ UI_LIST_ITEM_FILTER_MATCHES
void UI_but_flag_disable(uiBut *but, int flag)
#define UI_UNIT_Y
@ UI_EMBOSS_NONE
@ UI_EMBOSS
uiBut * uiDefButI(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, int *poin, float min, float max, const char *tip)
@ UI_BLOCK_LIST_ITEM
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg)
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, const char *tip)
void uiItemL(uiLayout *layout, const char *name, int icon)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
int UI_preview_tile_size_y(const int size_px=96)
void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, const char *name, int icon, const char *placeholder=nullptr)
void UI_block_flag_disable(uiBlock *block, int flag)
void UI_but_drawflag_enable(uiBut *but, int flag)
uiLayout * uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *actptr, PropertyRNA *actprop)
#define UI_ITEM_NONE
#define UI_UL_DEFAULT_CLASS_NAME
void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss)
int uiLayoutGetWidth(uiLayout *layout)
uiLayout * uiLayoutGridFlow(uiLayout *layout, bool row_major, int columns_len, bool even_columns, bool even_rows, bool align)
void uiLayoutListItemAddPadding(uiLayout *layout)
uiBut * uiDefIconButI(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, const char *tip)
uiBut * uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, const char *tip)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
int UI_preview_tile_size_x(const int size_px=96)
uiLayout * uiLayoutOverlap(uiLayout *layout)
uiBut * uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, const char *tip)
uiBut * uiDefIconButBitI(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, const char *tip)
#define UI_UNIT_X
void UI_block_flag_enable(uiBlock *block, int flag)
@ UI_BTYPE_TOGGLE
@ UI_BTYPE_LISTROW
@ UI_BTYPE_SEPR
@ UI_BTYPE_NUM
@ UI_BTYPE_GRIP
@ UI_BTYPE_SCROLL
#define UI_MAX_NAME_STR
int UI_preview_tile_size_y_no_label(const int size_px=96)
bContextStore * uiLayoutGetContextStore(uiLayout *layout)
void UI_but_flag_enable(uiBut *but, int flag)
uiTemplateListFlags
@ UI_TEMPLATE_LIST_SORT_LOCK
@ UI_TEMPLATE_LIST_SORT_REVERSE
@ UI_TEMPLATE_LIST_NO_NAMES
@ UI_TEMPLATE_LIST_NO_FILTER_OPTIONS
@ UI_TEMPLATE_LIST_NO_GRIP
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_BUT_NO_TOOLTIP
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_NO_BG
@ UI_ITEM_R_ICON_ONLY
@ UI_BUT_UNDO
@ UI_BUT_DISABLED
int UI_icon_from_rnaptr(const bContext *C, PointerRNA *ptr, int rnaicon, bool big)
#define V2D_SCROLL_WIDTH
Definition UI_view2d.hh:54
int64_t size() const
void resize(const int64_t new_size)
eUIListFilterResult operator()(const PointerRNA &itemptr, blender::StringRefNull name, int index)
#define offsetof(t, d)
int len
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
uint col
#define RNA_NO_INDEX
uiListType * UI_UL_asset_view()
void ui_layout_list_set_labels_active(uiLayout *layout)
uiListType * UI_UL_cache_file_layers()
PointerRNA * UI_list_custom_drag_operator_set(uiList *ui_list, const char *opname, bool create_properties)
static int cmpstringp(const void *p1, const void *p2)
static uiList * ui_list_ensure(const bContext *C, uiListType *ui_list_type, const char *list_id, int layout_type, bool sort_reverse, bool sort_lock)
static std::string uilist_item_tooltip_func(bContext *, void *argN, const char *tip)
static void uilist_resize_update(bContext *C, uiList *ui_list)
static bool ui_template_list_data_retrieve(const char *listtype_name, const char *list_id, PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, const char *item_dyntip_propname, TemplateListInputData *r_input_data, uiListType **r_list_type)
static void uilist_free_dyn_data(uiList *ui_list)
static void * uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)
void uiTemplateList(uiLayout *layout, const bContext *C, const char *listtype_name, const char *list_id, PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns, enum uiTemplateListFlags flags)
void UI_list_filter_and_sort_items(uiList *ui_list, const bContext *, uiListItemFilterFn item_filter_fn, PointerRNA *dataptr, const char *propname, uiListItemGetNameFn get_name_fn)
uiList * uiTemplateList_ex(uiLayout *layout, const bContext *C, const char *listtype_name, const char *list_id, PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns, enum uiTemplateListFlags flags, void *customdata)
static void ui_template_list_collect_display_items(const bContext *C, uiList *ui_list, TemplateListInputData *input_data, const uiListFilterItemsFunc filter_items_fn, TemplateListItems *r_items)
static void uilist_draw_filter_default(uiList *ui_list, const bContext *, uiLayout *layout)
static void uilist_filter_items_default(uiList *ui_list, const bContext *C, PointerRNA *dataptr, const char *propname)
PointerRNA * UI_list_custom_activate_operator_set(uiList *ui_list, const char *opname, bool create_properties)
static void ui_template_list_collect_items(PointerRNA *list_ptr, PropertyRNA *list_prop, const uiList *ui_list, int activei, TemplateListItems *r_items)
static void ui_template_list_layout_draw(const bContext *C, uiList *ui_list, uiLayout *layout, TemplateListInputData *input_data, TemplateListItems *items, const TemplateListLayoutDrawData *layout_data, const enum uiTemplateListFlags flags)
void ED_uilisttypes_ui()
static void uilist_prepare(uiList *ui_list, const TemplateListItems *items, const TemplateListLayoutDrawData *layout_data, TemplateListVisualInfo *r_visual_info)
bool UI_list_item_index_is_filtered_visible(const uiList *ui_list, const int item_idx)
static void uilist_draw_item_default(uiList *ui_list, const bContext *, uiLayout *layout, PointerRNA *, PointerRNA *itemptr, int icon, PointerRNA *, const char *, int, int)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
char * RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
PropertyType RNA_property_type(PropertyRNA *prop)
char * RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
const char * RNA_struct_identifier(const StructRNA *type)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_flag(PropertyRNA *prop)
int RNA_struct_ui_icon(const StructRNA *type)
PropertyRNA * RNA_struct_name_property(const StructRNA *type)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
const char * RNA_property_identifier(const PropertyRNA *prop)
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
blender::Vector< _uilist_item > item_vec
const bContextStore * context
struct wmOperatorType * custom_activate_optype
struct PointerRNA * custom_drag_opptr
uiListFreeRuntimeDataFunc free_runtime_data_fn
int * items_filter_neworder
struct wmOperatorType * custom_drag_optype
int * items_filter_flags
struct PointerRNA * custom_activate_opptr
uiListFilterItemsFunc filter_items
uiListDrawFilterFunc draw_filter
uiListDrawItemFunc draw_item
char filter_byname[128]
int filter_sort_flag
char list_id[128]
uiListDyn * dyn_data
int list_last_activei
struct uiListType * type
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
void WM_operator_properties_free(PointerRNA *ptr)
uiListType * WM_uilisttype_find(const char *idname, bool quiet)
bool WM_uilisttype_add(uiListType *ult)
void WM_uilisttype_to_full_list_id(const uiListType *ult, const char *list_id, char r_full_list_id[])