Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2021-07-15 17:56:18 +0300
committerJulian Eisel <julian@blender.org>2021-07-15 20:09:49 +0300
commit9d9c879f4bdf05c92826023131e7eb2a57c06102 (patch)
tree6ab101d1c71bd7e78bb4d2a1364e5282e1debaae /source/blender/editors/interface/interface_templates.c
parent0cc2a72f94b71d5594a0aca088007ecbb3221b60 (diff)
Cleanup: Move UI list template code to own file (C++)
This move was already prepared with 788d38046032 and 26b098c04fbe. The template is quite big already, better to give it its own file. Plus it could use some C++ features like RAII and maybe some more object oriented code. I plan further refactoring there.
Diffstat (limited to 'source/blender/editors/interface/interface_templates.c')
-rw-r--r--source/blender/editors/interface/interface_templates.c1255
1 files changed, 0 insertions, 1255 deletions
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 548852b407e..766840909cc 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -5645,1261 +5645,6 @@ void uiTemplateLayers(uiLayout *layout,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name List Template
- * \{ */
-
-static void uilist_draw_item_default(struct uiList *ui_list,
- struct bContext *UNUSED(C),
- struct uiLayout *layout,
- struct PointerRNA *UNUSED(dataptr),
- struct PointerRNA *itemptr,
- int icon,
- struct PointerRNA *UNUSED(active_dataptr),
- const char *UNUSED(active_propname),
- int UNUSED(index),
- int UNUSED(flt_flag))
-{
- PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
-
- /* Simplest one! */
- switch (ui_list->layout_type) {
- case UILST_LAYOUT_GRID:
- uiItemL(layout, "", icon);
- break;
- case UILST_LAYOUT_DEFAULT:
- case UILST_LAYOUT_COMPACT:
- default:
- if (nameprop) {
- uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon);
- }
- else {
- uiItemL(layout, "", icon);
- }
- break;
- }
-}
-
-static void uilist_draw_filter_default(struct uiList *ui_list,
- struct bContext *UNUSED(C),
- struct uiLayout *layout)
-{
- PointerRNA listptr;
- RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr);
-
- uiLayout *row = uiLayoutRow(layout, false);
-
- uiLayout *subrow = uiLayoutRow(row, true);
- uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE);
- uiItemR(subrow,
- &listptr,
- "use_filter_invert",
- UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
- "",
- ICON_ARROW_LEFTRIGHT);
-
- if ((ui_list->filter_sort_flag & UILST_FLT_SORT_LOCK) == 0) {
- subrow = uiLayoutRow(row, true);
- uiItemR(subrow,
- &listptr,
- "use_filter_sort_alpha",
- UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
- "",
- ICON_NONE);
- uiItemR(subrow,
- &listptr,
- "use_filter_sort_reverse",
- UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
- "",
- (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_SORT_DESC : ICON_SORT_ASC);
- }
-}
-
-typedef struct {
- char name[MAX_IDPROP_NAME];
- int org_idx;
-} StringCmp;
-
-static int cmpstringp(const void *p1, const void *p2)
-{
- /* Case-insensitive comparison. */
- return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name);
-}
-
-static void uilist_filter_items_default(struct uiList *ui_list,
- struct bContext *UNUSED(C),
- struct PointerRNA *dataptr,
- const char *propname)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
-
- const char *filter_raw = ui_list->filter_byname;
- char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL;
- const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
- const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) ==
- UILST_FLT_SORT_ALPHA;
- const int len = RNA_property_collection_length(dataptr, prop);
-
- dyn_data->items_shown = dyn_data->items_len = len;
-
- if (len && (order_by_name || filter_raw[0])) {
- StringCmp *names = NULL;
- int order_idx = 0, i = 0;
-
- if (order_by_name) {
- names = MEM_callocN(sizeof(StringCmp) * len, "StringCmp");
- }
- if (filter_raw[0]) {
- const size_t slen = strlen(filter_raw);
-
- dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, "items_filter_flags");
- dyn_data->items_shown = 0;
-
- /* Implicitly add heading/trailing wildcards if needed. */
- if (slen + 3 <= sizeof(filter_buff)) {
- filter = filter_buff;
- }
- else {
- filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn");
- }
- BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3);
- }
-
- RNA_PROP_BEGIN (dataptr, itemptr, prop) {
- bool do_order = false;
-
- char *namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
- const char *name = namebuf ? namebuf : "";
-
- if (filter[0]) {
- /* Case-insensitive! */
- if (fnmatch(filter, name, FNM_CASEFOLD) == 0) {
- dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
- if (!filter_exclude) {
- dyn_data->items_shown++;
- do_order = order_by_name;
- }
- // printf("%s: '%s' matches '%s'\n", __func__, name, filter);
- }
- else if (filter_exclude) {
- dyn_data->items_shown++;
- do_order = order_by_name;
- }
- }
- else {
- do_order = order_by_name;
- }
-
- if (do_order) {
- names[order_idx].org_idx = order_idx;
- BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME);
- }
-
- /* free name */
- if (namebuf) {
- MEM_freeN(namebuf);
- }
- i++;
- }
- RNA_PROP_END;
-
- if (order_by_name) {
- int new_idx;
- /* NOTE: order_idx equals either to ui_list->items_len if no filtering done,
- * or to ui_list->items_shown if filter is enabled,
- * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded.
- * This way, we only sort items we actually intend to draw!
- */
- qsort(names, order_idx, sizeof(StringCmp), cmpstringp);
-
- dyn_data->items_filter_neworder = MEM_mallocN(sizeof(int) * order_idx,
- "items_filter_neworder");
- for (new_idx = 0; new_idx < order_idx; new_idx++) {
- dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx;
- }
- }
-
- if (filter_dyn) {
- MEM_freeN(filter_dyn);
- }
- if (names) {
- MEM_freeN(names);
- }
- }
-}
-
-static void uilist_free_dyn_data(uiList *ui_list)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- if (!dyn_data) {
- return;
- }
-
- if (dyn_data->custom_activate_opptr) {
- WM_operator_properties_free(dyn_data->custom_activate_opptr);
- MEM_freeN(dyn_data->custom_activate_opptr);
- }
- if (dyn_data->custom_drag_opptr) {
- WM_operator_properties_free(dyn_data->custom_drag_opptr);
- MEM_freeN(dyn_data->custom_drag_opptr);
- }
-
- MEM_SAFE_FREE(dyn_data->items_filter_flags);
- MEM_SAFE_FREE(dyn_data->items_filter_neworder);
- MEM_SAFE_FREE(dyn_data->customdata);
-}
-
-/**
- * The validated data that was passed to #uiTemplateList (typically through Python).
- * Populated through #ui_template_list_data_retrieve().
- */
-typedef struct {
- PointerRNA dataptr;
- PropertyRNA *prop;
- PointerRNA active_dataptr;
- PropertyRNA *activeprop;
- const char *item_dyntip_propname;
-
- /* Index as stored in the input property. I.e. the index before sorting. */
- int active_item_idx;
-} TemplateListInputData;
-
-/**
- * Internal wrapper for a single item in the list (well, actually stored as a vector).
- */
-typedef struct {
- PointerRNA item;
- int org_idx;
- int flt_flag;
-} _uilist_item;
-
-/**
- * Container for the item vector and additional info.
- */
-typedef struct {
- _uilist_item *item_vec;
- /* Index of the active item following visual order. I.e. unlike
- * TemplateListInputData.active_item_idx, this is the index after sorting. */
- int active_item_idx;
- int tot_items;
-} TemplateListItems;
-
-typedef struct {
- uiListDrawItemFunc draw_item;
- uiListDrawFilterFunc draw_filter;
-
- int rows;
- int maxrows;
- int columns;
-} TemplateListLayoutDrawData;
-
-typedef struct {
- int visual_items; /* Visual number of items (i.e. number of items we have room to display). */
- int start_idx; /* Index of first item to display. */
- int end_idx; /* Index of last item to display + 1. */
-} TemplateListVisualInfo;
-
-/**
- * Validate input parameters and initialize \a r_data from that. Plus find the list-type and return
- * it in \a r_list_type.
- *
- * \return false if the input data isn't valid. Will also raise an RNA warning in that case.
- */
-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)
-{
- memset(r_input_data, 0, sizeof(*r_input_data));
-
- /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
- if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
- RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
- UI_UL_DEFAULT_CLASS_NAME);
- return false;
- }
-
- if (!active_dataptr->data) {
- RNA_warning("No active data");
- return false;
- }
-
- r_input_data->dataptr = *dataptr;
- if (dataptr->data) {
- r_input_data->prop = RNA_struct_find_property(dataptr, propname);
- if (!r_input_data->prop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
- return false;
- }
- }
-
- r_input_data->active_dataptr = *active_dataptr;
- r_input_data->activeprop = RNA_struct_find_property(active_dataptr, active_propname);
- if (!r_input_data->activeprop) {
- RNA_warning(
- "Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
- return false;
- }
-
- if (r_input_data->prop) {
- const PropertyType type = RNA_property_type(r_input_data->prop);
- if (type != PROP_COLLECTION) {
- RNA_warning("Expected a collection data property");
- return false;
- }
- }
-
- const PropertyType activetype = RNA_property_type(r_input_data->activeprop);
- if (activetype != PROP_INT) {
- RNA_warning("Expected an integer active data property");
- return false;
- }
-
- /* Find the uiList type. */
- if (!(*r_list_type = WM_uilisttype_find(listtype_name, false))) {
- RNA_warning("List type %s not found", listtype_name);
- return false;
- }
-
- r_input_data->active_item_idx = RNA_property_int_get(&r_input_data->active_dataptr,
- r_input_data->activeprop);
- r_input_data->item_dyntip_propname = item_dyntip_propname;
-
- return true;
-}
-
-static void ui_template_list_collect_items(PointerRNA *list_ptr,
- PropertyRNA *list_prop,
- uiListDyn *dyn_data,
- int filter_exclude,
- bool order_reverse,
- int activei,
- TemplateListItems *r_items)
-{
- int i = 0;
- int reorder_i = 0;
- bool activei_mapping_pending = true;
-
- RNA_PROP_BEGIN (list_ptr, itemptr, list_prop) {
- if (!dyn_data->items_filter_flags ||
- ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) {
- int new_order_idx;
- if (dyn_data->items_filter_neworder) {
- new_order_idx = dyn_data->items_filter_neworder[reorder_i++];
- new_order_idx = order_reverse ? dyn_data->items_shown - new_order_idx - 1 : new_order_idx;
- }
- else {
- new_order_idx = order_reverse ? dyn_data->items_shown - ++reorder_i : reorder_i++;
- }
- // printf("%s: ii: %d\n", __func__, ii);
- r_items->item_vec[new_order_idx].item = itemptr;
- r_items->item_vec[new_order_idx].org_idx = i;
- r_items->item_vec[new_order_idx].flt_flag = dyn_data->items_filter_flags ?
- dyn_data->items_filter_flags[i] :
- 0;
-
- if (activei_mapping_pending && activei == i) {
- activei = new_order_idx;
- /* So that we do not map again activei! */
- activei_mapping_pending = false;
- }
-#if 0 /* For now, do not alter active element, even if it will be hidden... */
- else if (activei < i) {
- /* We do not want an active but invisible item!
- * Only exception is when all items are filtered out...
- */
- if (prev_order_idx >= 0) {
- activei = prev_order_idx;
- RNA_property_int_set(active_dataptr, activeprop, prev_i);
- }
- else {
- activei = new_order_idx;
- RNA_property_int_set(active_dataptr, activeprop, i);
- }
- }
- prev_i = i;
- prev_ii = new_order_idx;
-#endif
- }
- i++;
- }
- RNA_PROP_END;
-
- /* If mapping is still pending, no active item was found. Mark as invalid (-1) */
- r_items->active_item_idx = activei_mapping_pending ? -1 : activei;
-}
-
-/**
- * Create the UI-list representation of the list items, sorted and filtered if needed.
- */
-static void ui_template_list_collect_display_items(bContext *C,
- uiList *ui_list,
- TemplateListInputData *input_data,
- const uiListFilterItemsFunc filter_items_fn,
- TemplateListItems *r_items)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- memset(r_items, 0, sizeof(*r_items));
-
- /* Filter list items! (not for compact layout, though) */
- if (input_data->dataptr.data && input_data->prop) {
- const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
- const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
- int items_shown;
-#if 0
- int prev_ii = -1, prev_i;
-#endif
-
- if (ui_list->layout_type == UILST_LAYOUT_COMPACT) {
- dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(
- &input_data->dataptr, input_data->prop);
- }
- else {
- // printf("%s: filtering...\n", __func__);
- filter_items_fn(ui_list, C, &input_data->dataptr, RNA_property_identifier(input_data->prop));
- // printf("%s: filtering done.\n", __func__);
- }
-
- items_shown = dyn_data->items_shown;
- if (items_shown >= 0) {
- r_items->item_vec = MEM_mallocN(sizeof(*r_items->item_vec) * items_shown, __func__);
- // printf("%s: items shown: %d.\n", __func__, items_shown);
-
- ui_template_list_collect_items(&input_data->dataptr,
- input_data->prop,
- dyn_data,
- filter_exclude,
- order_reverse,
- input_data->active_item_idx,
- r_items);
- }
- if (dyn_data->items_shown >= 0) {
- r_items->tot_items = dyn_data->items_shown;
- }
- else {
- r_items->tot_items = dyn_data->items_len;
- }
- }
-}
-
-static void ui_template_list_free_items(TemplateListItems *items)
-{
- if (items->item_vec) {
- MEM_freeN(items->item_vec);
- }
-}
-
-static void uilist_prepare(uiList *ui_list,
- const TemplateListItems *items,
- const TemplateListLayoutDrawData *layout_data,
- TemplateListVisualInfo *r_visual_info)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- const bool use_auto_size = (ui_list->list_grip <
- (layout_data->rows - UI_LIST_AUTO_SIZE_THRESHOLD));
-
- int actual_rows = layout_data->rows;
- int actual_maxrows = layout_data->maxrows;
- int columns = layout_data->columns;
-
- /* default rows */
- if (actual_rows <= 0) {
- actual_rows = 5;
- }
- dyn_data->visual_height_min = actual_rows;
- if (actual_maxrows < actual_rows) {
- actual_maxrows = max_ii(actual_rows, 5);
- }
- if (columns <= 0) {
- columns = 9;
- }
-
- int activei_row;
- if (columns > 1) {
- dyn_data->height = (int)ceil((double)items->tot_items / (double)columns);
- activei_row = (int)floor((double)items->active_item_idx / (double)columns);
- }
- else {
- dyn_data->height = items->tot_items;
- activei_row = items->active_item_idx;
- }
-
- dyn_data->columns = columns;
-
- if (!use_auto_size) {
- /* No auto-size, yet we clamp at min size! */
- actual_rows = max_ii(ui_list->list_grip, actual_rows);
- }
- else if ((actual_rows != actual_maxrows) && (dyn_data->height > actual_rows)) {
- /* Expand size if needed and possible. */
- actual_rows = min_ii(dyn_data->height, actual_maxrows);
- }
-
- /* If list length changes or list is tagged to check this,
- * and active is out of view, scroll to it. */
- if ((ui_list->list_last_len != items->tot_items) ||
- (ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM)) {
- if (activei_row < ui_list->list_scroll) {
- ui_list->list_scroll = activei_row;
- }
- else if (activei_row >= ui_list->list_scroll + actual_rows) {
- ui_list->list_scroll = activei_row - actual_rows + 1;
- }
- ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
- }
-
- const int max_scroll = max_ii(0, dyn_data->height - actual_rows);
- CLAMP(ui_list->list_scroll, 0, max_scroll);
- ui_list->list_last_len = items->tot_items;
- dyn_data->visual_height = actual_rows;
- r_visual_info->visual_items = actual_rows * columns;
- r_visual_info->start_idx = ui_list->list_scroll * columns;
- r_visual_info->end_idx = min_ii(r_visual_info->start_idx + actual_rows * columns,
- items->tot_items);
-}
-
-static void uilist_resize_update_cb(bContext *C, void *arg1, void *UNUSED(arg2))
-{
- uiList *ui_list = arg1;
- uiListDyn *dyn_data = ui_list->dyn_data;
-
- /* This way we get diff in number of additional items to show (positive) or hide (negative). */
- const int diff = round_fl_to_int((float)(dyn_data->resize - dyn_data->resize_prev) /
- (float)UI_UNIT_Y);
-
- if (diff != 0) {
- ui_list->list_grip += diff;
- dyn_data->resize_prev += diff * UI_UNIT_Y;
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- }
-
- /* In case uilist is in popup, we need special refreshing */
- ED_region_tag_refresh_ui(CTX_wm_menu(C));
-}
-
-static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)
-{
- if (propname && propname[0] && itemptr && itemptr->data) {
- PropertyRNA *prop = RNA_struct_find_property(itemptr, propname);
-
- if (prop && (RNA_property_type(prop) == PROP_STRING)) {
- return RNA_property_string_get_alloc(itemptr, prop, NULL, 0, NULL);
- }
- }
- return NULL;
-}
-
-static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const char *tip)
-{
- char *dyn_tooltip = argN;
- return BLI_sprintfN("%s - %s", tip, dyn_tooltip);
-}
-
-/**
- * \note Note that \a layout_type may be NULL.
- */
-static uiList *ui_list_ensure(bContext *C,
- uiListType *ui_list_type,
- const char *list_id,
- int layout_type,
- bool sort_reverse,
- bool sort_lock)
-{
- /* Allows to work in popups. */
- ARegion *region = CTX_wm_menu(C);
- if (region == NULL) {
- region = CTX_wm_region(C);
- }
-
- /* Find or add the uiList to the current Region. */
-
- char full_list_id[UI_MAX_NAME_STR];
- WM_uilisttype_to_full_list_id(ui_list_type, list_id, full_list_id);
-
- uiList *ui_list = BLI_findstring(&region->ui_lists, full_list_id, offsetof(uiList, list_id));
-
- if (!ui_list) {
- ui_list = MEM_callocN(sizeof(uiList), "uiList");
- BLI_strncpy(ui_list->list_id, full_list_id, sizeof(ui_list->list_id));
- BLI_addtail(&region->ui_lists, ui_list);
- ui_list->list_grip = -UI_LIST_AUTO_SIZE_THRESHOLD; /* Force auto size by default. */
- if (sort_reverse) {
- ui_list->filter_sort_flag |= UILST_FLT_SORT_REVERSE;
- }
- if (sort_lock) {
- ui_list->filter_sort_flag |= UILST_FLT_SORT_LOCK;
- }
- }
-
- if (!ui_list->dyn_data) {
- ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data");
- }
- uiListDyn *dyn_data = ui_list->dyn_data;
- /* Note that this isn't a `uiListType` callback, it's stored in the runtime list data. Otherwise
- * the runtime data could leak when the type is unregistered (e.g. on "Reload Scripts"). */
- dyn_data->free_runtime_data_fn = uilist_free_dyn_data;
-
- /* Because we can't actually pass type across save&load... */
- ui_list->type = ui_list_type;
- ui_list->layout_type = layout_type;
-
- /* Reset filtering data. */
- MEM_SAFE_FREE(dyn_data->items_filter_flags);
- MEM_SAFE_FREE(dyn_data->items_filter_neworder);
- dyn_data->items_len = dyn_data->items_shown = -1;
-
- return ui_list;
-}
-
-static void ui_template_list_layout_draw(bContext *C,
- uiList *ui_list,
- uiLayout *layout,
- TemplateListInputData *input_data,
- TemplateListItems *items,
- const TemplateListLayoutDrawData *layout_data,
- const enum uiTemplateListFlags flags)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- const char *active_propname = RNA_property_identifier(input_data->activeprop);
-
- uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap;
- char numstr[32];
- int rnaicon = ICON_NONE, icon = ICON_NONE;
- uiBut *but;
-
- uiBlock *block = uiLayoutGetBlock(layout);
-
- /* get icon */
- if (input_data->dataptr.data && input_data->prop) {
- StructRNA *ptype = RNA_property_pointer_type(&input_data->dataptr, input_data->prop);
- rnaicon = RNA_struct_ui_icon(ptype);
- }
-
- TemplateListVisualInfo visual_info;
- switch (ui_list->layout_type) {
- case UILST_LAYOUT_DEFAULT: {
- /* layout */
- box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
- glob = uiLayoutColumn(box, true);
- row = uiLayoutRow(glob, false);
- col = uiLayoutColumn(row, true);
-
- TemplateListLayoutDrawData adjusted_layout_data = *layout_data;
- adjusted_layout_data.columns = 1;
- /* init numbers */
- uilist_prepare(ui_list, items, &adjusted_layout_data, &visual_info);
-
- int i = 0;
- if (input_data->dataptr.data && input_data->prop) {
- /* create list items */
- for (i = visual_info.start_idx; i < visual_info.end_idx; i++) {
- PointerRNA *itemptr = &items->item_vec[i].item;
- void *dyntip_data;
- const int org_i = items->item_vec[i].org_idx;
- const int flt_flag = items->item_vec[i].flt_flag;
- uiBlock *subblock = uiLayoutGetBlock(col);
-
- overlap = uiLayoutOverlap(col);
-
- UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
-
- /* list item behind label & other buttons */
- uiLayoutRow(overlap, false);
-
- but = uiDefButR_prop(subblock,
- UI_BTYPE_LISTROW,
- 0,
- "",
- 0,
- 0,
- UI_UNIT_X * 10,
- UI_UNIT_Y,
- &input_data->active_dataptr,
- input_data->activeprop,
- 0,
- 0,
- org_i,
- 0,
- 0,
- TIP_("Double click to rename"));
- if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr,
- input_data->item_dyntip_propname))) {
- UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data, MEM_freeN);
- }
-
- sub = uiLayoutRow(overlap, false);
-
- icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
- if (icon == ICON_DOT) {
- icon = ICON_NONE;
- }
- layout_data->draw_item(ui_list,
- C,
- sub,
- &input_data->dataptr,
- itemptr,
- icon,
- &input_data->active_dataptr,
- active_propname,
- org_i,
- flt_flag);
-
- /* Items should be able to set context pointers for the layout. But the list-row button
- * swallows events, so it needs the context storage too for handlers to see it. */
- but->context = uiLayoutGetContextStore(sub);
-
- /* If we are "drawing" active item, set all labels as active. */
- if (i == items->active_item_idx) {
- ui_layout_list_set_labels_active(sub);
- }
-
- UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
- }
- }
-
- /* add dummy buttons to fill space */
- for (; i < visual_info.start_idx + visual_info.visual_items; i++) {
- uiItemL(col, "", ICON_NONE);
- }
-
- /* add scrollbar */
- if (items->tot_items > visual_info.visual_items) {
- uiLayoutColumn(row, false);
- uiDefButI(block,
- UI_BTYPE_SCROLL,
- 0,
- "",
- 0,
- 0,
- V2D_SCROLL_WIDTH,
- UI_UNIT_Y * dyn_data->visual_height,
- &ui_list->list_scroll,
- 0,
- dyn_data->height - dyn_data->visual_height,
- dyn_data->visual_height,
- 0,
- "");
- }
- } break;
- case UILST_LAYOUT_COMPACT:
- row = uiLayoutRow(layout, true);
-
- if ((input_data->dataptr.data && input_data->prop) && (dyn_data->items_shown > 0) &&
- (items->active_item_idx >= 0) && (items->active_item_idx < dyn_data->items_shown)) {
- PointerRNA *itemptr = &items->item_vec[items->active_item_idx].item;
- const int org_i = items->item_vec[items->active_item_idx].org_idx;
-
- icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
- if (icon == ICON_DOT) {
- icon = ICON_NONE;
- }
- layout_data->draw_item(ui_list,
- C,
- row,
- &input_data->dataptr,
- itemptr,
- icon,
- &input_data->active_dataptr,
- active_propname,
- org_i,
- 0);
- }
- /* if list is empty, add in dummy button */
- else {
- uiItemL(row, "", ICON_NONE);
- }
-
- /* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
- but = uiDefIconTextButR_prop(block,
- UI_BTYPE_NUM,
- 0,
- 0,
- numstr,
- 0,
- 0,
- UI_UNIT_X * 5,
- UI_UNIT_Y,
- &input_data->active_dataptr,
- input_data->activeprop,
- 0,
- 0,
- 0,
- 0,
- 0,
- "");
- if (dyn_data->items_shown == 0) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- break;
- case UILST_LAYOUT_GRID: {
- box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
- glob = uiLayoutColumn(box, true);
- row = uiLayoutRow(glob, false);
- col = uiLayoutColumn(row, true);
- subrow = NULL; /* Quite gcc warning! */
-
- uilist_prepare(ui_list, items, layout_data, &visual_info);
-
- int i = 0;
- if (input_data->dataptr.data && input_data->prop) {
- /* create list items */
- for (i = visual_info.start_idx; i < visual_info.end_idx; i++) {
- PointerRNA *itemptr = &items->item_vec[i].item;
- const int org_i = items->item_vec[i].org_idx;
- const int flt_flag = items->item_vec[i].flt_flag;
-
- /* create button */
- if (!(i % layout_data->columns)) {
- subrow = uiLayoutRow(col, false);
- }
-
- uiBlock *subblock = uiLayoutGetBlock(subrow);
- overlap = uiLayoutOverlap(subrow);
-
- UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
-
- /* list item behind label & other buttons */
- uiLayoutRow(overlap, false);
-
- but = uiDefButR_prop(subblock,
- UI_BTYPE_LISTROW,
- 0,
- "",
- 0,
- 0,
- UI_UNIT_X * 10,
- UI_UNIT_Y,
- &input_data->active_dataptr,
- input_data->activeprop,
- 0,
- 0,
- org_i,
- 0,
- 0,
- NULL);
- UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP);
-
- sub = uiLayoutRow(overlap, false);
-
- icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
- layout_data->draw_item(ui_list,
- C,
- sub,
- &input_data->dataptr,
- itemptr,
- icon,
- &input_data->active_dataptr,
- active_propname,
- org_i,
- flt_flag);
-
- /* If we are "drawing" active item, set all labels as active. */
- if (i == items->active_item_idx) {
- ui_layout_list_set_labels_active(sub);
- }
-
- UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
- }
- }
-
- /* add dummy buttons to fill space */
- for (; i < visual_info.start_idx + visual_info.visual_items; i++) {
- if (!(i % layout_data->columns)) {
- subrow = uiLayoutRow(col, false);
- }
- uiItemL(subrow, "", ICON_NONE);
- }
-
- /* add scrollbar */
- if (items->tot_items > visual_info.visual_items) {
- /* col = */ uiLayoutColumn(row, false);
- uiDefButI(block,
- UI_BTYPE_SCROLL,
- 0,
- "",
- 0,
- 0,
- V2D_SCROLL_WIDTH,
- UI_UNIT_Y * dyn_data->visual_height,
- &ui_list->list_scroll,
- 0,
- dyn_data->height - dyn_data->visual_height,
- dyn_data->visual_height,
- 0,
- "");
- }
- break;
- }
- case UILST_LAYOUT_BIG_PREVIEW_GRID:
- box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
- /* For grip button. */
- glob = uiLayoutColumn(box, true);
- /* For scrollbar. */
- row = uiLayoutRow(glob, false);
-
- /* TODO ED_fileselect_init_layout(). Share somehow? */
- float size_x = (96.0f / 20.0f) * UI_UNIT_X;
- float size_y = (96.0f / 20.0f) * UI_UNIT_Y;
-
- const int cols_per_row = MAX2((uiLayoutGetWidth(box) - V2D_SCROLL_WIDTH) / size_x, 1);
- uiLayout *grid = uiLayoutGridFlow(row, true, cols_per_row, true, true, true);
-
- TemplateListLayoutDrawData adjusted_layout_data = *layout_data;
- adjusted_layout_data.columns = cols_per_row;
- uilist_prepare(ui_list, items, &adjusted_layout_data, &visual_info);
-
- if (input_data->dataptr.data && input_data->prop) {
- /* create list items */
- for (int i = visual_info.start_idx; i < visual_info.end_idx; i++) {
- PointerRNA *itemptr = &items->item_vec[i].item;
- const int org_i = items->item_vec[i].org_idx;
- const int flt_flag = items->item_vec[i].flt_flag;
-
- overlap = uiLayoutOverlap(grid);
- col = uiLayoutColumn(overlap, false);
-
- uiBlock *subblock = uiLayoutGetBlock(col);
- UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
-
- but = uiDefButR_prop(subblock,
- UI_BTYPE_LISTROW,
- 0,
- "",
- 0,
- 0,
- size_x,
- size_y,
- &input_data->active_dataptr,
- input_data->activeprop,
- 0,
- 0,
- org_i,
- 0,
- 0,
- NULL);
- UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP);
-
- col = uiLayoutColumn(overlap, false);
-
- icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
- layout_data->draw_item(ui_list,
- C,
- col,
- &input_data->dataptr,
- itemptr,
- icon,
- &input_data->active_dataptr,
- active_propname,
- org_i,
- flt_flag);
-
- /* Items should be able to set context pointers for the layout. But the list-row button
- * swallows events, so it needs the context storage too for handlers to see it. */
- but->context = uiLayoutGetContextStore(col);
-
- /* If we are "drawing" active item, set all labels as active. */
- if (i == items->active_item_idx) {
- ui_layout_list_set_labels_active(col);
- }
-
- UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
- }
- }
-
- if (items->tot_items > visual_info.visual_items) {
- /* col = */ uiLayoutColumn(row, false);
- uiDefButI(block,
- UI_BTYPE_SCROLL,
- 0,
- "",
- 0,
- 0,
- V2D_SCROLL_WIDTH,
- size_y * dyn_data->visual_height,
- &ui_list->list_scroll,
- 0,
- dyn_data->height - dyn_data->visual_height,
- dyn_data->visual_height,
- 0,
- "");
- }
- break;
- }
-
- if (glob) {
- const bool add_grip_but = (flags & UI_TEMPLATE_LIST_NO_GRIP) == 0;
-
- /* About #UI_BTYPE_GRIP drag-resize:
- * We can't directly use results from a grip button, since we have a
- * rather complex behavior here (sizing by discrete steps and, overall, auto-size feature).
- * Since we *never* know whether we are grip-resizing or not
- * (because there is no callback for when a button enters/leaves its "edit mode"),
- * we use the fact that grip-controlled value (dyn_data->resize) is completely handled
- * by the grip during the grab resize, so settings its value here has no effect at all.
- *
- * It is only meaningful when we are not resizing,
- * in which case this gives us the correct "init drag" value.
- * Note we cannot affect `dyn_data->resize_prev here`,
- * since this value is not controlled by the grip!
- */
- dyn_data->resize = dyn_data->resize_prev +
- (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y;
-
- row = uiLayoutRow(glob, true);
- uiBlock *subblock = uiLayoutGetBlock(row);
- UI_block_emboss_set(subblock, UI_EMBOSS_NONE);
-
- if (ui_list->filter_flag & UILST_FLT_SHOW) {
- but = uiDefIconButBitI(subblock,
- UI_BTYPE_TOGGLE,
- UILST_FLT_SHOW,
- 0,
- ICON_DISCLOSURE_TRI_DOWN,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y * 0.5f,
- &(ui_list->filter_flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Hide filtering options"));
- UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
-
- if (add_grip_but) {
- but = uiDefIconButI(subblock,
- UI_BTYPE_GRIP,
- 0,
- ICON_GRIP,
- 0,
- 0,
- UI_UNIT_X * 10.0f,
- UI_UNIT_Y * 0.5f,
- &dyn_data->resize,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
- }
-
- UI_block_emboss_set(subblock, UI_EMBOSS);
-
- col = uiLayoutColumn(glob, false);
- subblock = uiLayoutGetBlock(col);
- uiDefBut(subblock,
- UI_BTYPE_SEPR,
- 0,
- "",
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y * 0.05f,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
-
- layout_data->draw_filter(ui_list, C, col);
- }
- else {
- but = uiDefIconButBitI(subblock,
- UI_BTYPE_TOGGLE,
- UILST_FLT_SHOW,
- 0,
- ICON_DISCLOSURE_TRI_RIGHT,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y * 0.5f,
- &(ui_list->filter_flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Show filtering options"));
- UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
-
- if (add_grip_but) {
- but = uiDefIconButI(subblock,
- UI_BTYPE_GRIP,
- 0,
- ICON_GRIP,
- 0,
- 0,
- UI_UNIT_X * 10.0f,
- UI_UNIT_Y * 0.5f,
- &dyn_data->resize,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
- }
-
- UI_block_emboss_set(subblock, UI_EMBOSS);
- }
- }
-}
-
-uiList *uiTemplateList_ex(uiLayout *layout,
- 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)
-{
- TemplateListInputData input_data = {0};
- uiListType *ui_list_type;
- if (!ui_template_list_data_retrieve(listtype_name,
- list_id,
- dataptr,
- propname,
- active_dataptr,
- active_propname,
- item_dyntip_propname,
- &input_data,
- &ui_list_type)) {
- return NULL;
- }
-
- uiListDrawItemFunc draw_item = ui_list_type->draw_item ? ui_list_type->draw_item :
- uilist_draw_item_default;
- uiListDrawFilterFunc draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter :
- uilist_draw_filter_default;
- uiListFilterItemsFunc filter_items = ui_list_type->filter_items ? ui_list_type->filter_items :
- uilist_filter_items_default;
-
- uiList *ui_list = ui_list_ensure(C,
- ui_list_type,
- list_id,
- layout_type,
- flags & UI_TEMPLATE_LIST_SORT_REVERSE,
- flags & UI_TEMPLATE_LIST_SORT_LOCK);
- uiListDyn *dyn_data = ui_list->dyn_data;
-
- MEM_SAFE_FREE(dyn_data->customdata);
- dyn_data->customdata = customdata;
-
- /* When active item changed since last draw, scroll to it. */
- if (input_data.active_item_idx != ui_list->list_last_activei) {
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- ui_list->list_last_activei = input_data.active_item_idx;
- }
-
- TemplateListItems items;
- ui_template_list_collect_display_items(C, ui_list, &input_data, filter_items, &items);
-
- TemplateListLayoutDrawData layout_data = {
- .draw_item = draw_item,
- .draw_filter = draw_filter,
- .rows = rows,
- .maxrows = maxrows,
- .columns = columns,
- };
-
- ui_template_list_layout_draw(C, ui_list, layout, &input_data, &items, &layout_data, flags);
-
- ui_template_list_free_items(&items);
-
- return ui_list;
-}
-
-void uiTemplateList(uiLayout *layout,
- 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)
-{
- uiTemplateList_ex(layout,
- C,
- listtype_name,
- list_id,
- dataptr,
- propname,
- active_dataptr,
- active_propname,
- item_dyntip_propname,
- rows,
- maxrows,
- layout_type,
- columns,
- flags,
- NULL);
-}
-
-/**
- * \return: A RNA pointer for the operator properties.
- */
-PointerRNA *UI_list_custom_activate_operator_set(uiList *ui_list,
- const char *opname,
- bool create_properties)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- dyn_data->custom_activate_optype = WM_operatortype_find(opname, false);
- if (!dyn_data->custom_activate_optype) {
- return NULL;
- }
-
- if (create_properties) {
- WM_operator_properties_alloc(&dyn_data->custom_activate_opptr, NULL, opname);
- }
-
- return dyn_data->custom_activate_opptr;
-}
-
-/**
- * \return: A RNA pointer for the operator properties.
- */
-PointerRNA *UI_list_custom_drag_operator_set(uiList *ui_list,
- const char *opname,
- bool create_properties)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- dyn_data->custom_drag_optype = WM_operatortype_find(opname, false);
- if (!dyn_data->custom_drag_optype) {
- return NULL;
- }
-
- if (create_properties) {
- WM_operator_properties_alloc(&dyn_data->custom_drag_opptr, NULL, opname);
- }
-
- return dyn_data->custom_drag_opptr;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Running Jobs Template
* \{ */