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:
Diffstat (limited to 'source/blender/editors/interface/interface_templates.c')
-rw-r--r--source/blender/editors/interface/interface_templates.c571
1 files changed, 467 insertions, 104 deletions
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 61cc021800e..6b6b7114c84 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1,4 +1,5 @@
/*
+
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -43,6 +44,7 @@
#include "BLI_rect.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_fnmatch.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -1017,6 +1019,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
Scene *scene = CTX_data_scene(C);
Object *ob;
ModifierData *md, *vmd;
+ VirtualModifierData virtualModifierData;
int i, lastCageIndex, cageIndex;
/* verify we have valid data */
@@ -1039,7 +1042,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
/* XXX virtual modifiers are not accesible for python */
- vmd = modifiers_getVirtualModifierList(ob);
+ vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
for (i = 0; vmd; i++, vmd = vmd->next) {
if (md == vmd)
@@ -1145,9 +1148,10 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
uiBlockSetEmboss(block, UI_EMBOSSN);
uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
uiBlockSetEmboss(block, UI_EMBOSS);
-
+
/* name */
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco + 0.5f*UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f*UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr,
+ xco + 0.5f * UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f * UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "");
if (con->flag & CONSTRAINT_DISABLE)
uiLayoutSetRedAlert(row, TRUE);
@@ -2468,7 +2472,7 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
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(index), int UNUSED(flt_flag))
{
char *namebuf;
const char *name;
@@ -2494,30 +2498,245 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN
}
}
+static void uilist_draw_filter_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout)
+{
+ PointerRNA listptr;
+ uiLayout *row, *subrow;
+
+ RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr);
+
+ row = uiLayoutRow(layout, FALSE);
+
+ 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, "",
+ (ui_list->filter_flag & UILST_FLT_EXCLUDE) ? ICON_ZOOM_OUT : ICON_ZOOM_IN);
+
+ 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_TRIA_UP : ICON_TRIA_DOWN);
+}
+
+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;
+ bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
+ bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_ALPHA) != 0;
+ 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, AT);
+ }
+ if (filter_raw[0]) {
+ size_t idx = 0, slen = strlen(filter_raw);
+
+ dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, AT);
+ dyn_data->items_shown = 0;
+
+ /* Implicitly add heading/trailing wildcards if needed. */
+ if (len + 3 <= 32) {
+ filter = filter_buff;
+ }
+ else {
+ filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), AT);
+ }
+ if (filter_raw[idx] != '*') {
+ filter[idx++] = '*';
+ }
+ memcpy(filter + idx, filter_raw, slen);
+ idx += slen;
+ if (filter[idx - 1] != '*') {
+ filter[idx++] = '*';
+ }
+ filter[idx] = '\0';
+ }
+
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ char *namebuf;
+ const char *name;
+ bool do_order = false;
+
+ namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
+ 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, AT);
+ 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);
+ }
+ }
+}
+
+typedef struct {
+ PointerRNA item;
+ int org_idx;
+ int flt_flag;
+} _uilist_item;
+
+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. */
+} uiListLayoutdata;
+
+static void prepare_list(uiList *ui_list, int len, int activei, int rows, int maxrows, int columns,
+ uiListLayoutdata *layoutdata)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ int activei_row, max_scroll;
+
+ /* default rows */
+ if (rows == 0)
+ rows = 5;
+ dyn_data->visual_height_min = rows;
+ if (maxrows == 0)
+ maxrows = 5;
+ if (columns == 0)
+ columns = 9;
+
+ if (ui_list->list_grip >= rows) {
+ maxrows = rows = ui_list->list_grip;
+ }
+ else {
+ ui_list->list_grip = 0; /* Reset to auto-size mode. */
+ /* Prevent auto-size mode to take effect while grab-resizing! */
+ if (ui_list->flag & UILST_RESIZING) {
+ maxrows = rows;
+ }
+ }
+
+ if (columns > 1) {
+ dyn_data->height = (int)ceil((double)len / (double)columns);
+ activei_row = (int)floor((double)activei / (double)columns);
+ }
+ else {
+ dyn_data->height = len;
+ activei_row = activei;
+ }
+
+ /* Expand size if needed and possible. */
+ if ((ui_list->list_grip == 0) && (rows != maxrows) && (dyn_data->height > rows)) {
+ rows = min_ii(dyn_data->height, 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 != len || 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 + rows) {
+ ui_list->list_scroll = activei_row - rows + 1;
+ }
+ ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
+ }
+
+ max_scroll = max_ii(0, dyn_data->height - rows);
+ CLAMP(ui_list->list_scroll, 0, max_scroll);
+ ui_list->list_last_len = len;
+ dyn_data->visual_height = rows;
+ layoutdata->visual_items = rows * columns;
+ layoutdata->start_idx = ui_list->list_scroll * columns;
+ layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
+}
+
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, int rows, int maxrows, int layout_type)
+ const char *active_propname, int rows, int maxrows, int layout_type, int columns)
{
uiListType *ui_list_type;
uiList *ui_list = NULL;
+ uiListDyn *dyn_data;
ARegion *ar;
uiListDrawItemFunc draw_item;
+ uiListDrawFilterFunc draw_filter;
+ uiListFilterItemsFunc filter_items;
PropertyRNA *prop = NULL, *activeprop;
PropertyType type, activetype;
+ _uilist_item *items_ptr = NULL;
StructRNA *ptype;
- uiLayout *box, *row, *col, *sub, *overlap;
+ uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap;
uiBlock *block, *subblock;
uiBut *but;
+ uiListLayoutdata layoutdata;
char ui_list_id[UI_MAX_NAME_STR];
char numstr[32];
int rnaicon = ICON_NONE, icon = ICON_NONE;
int i = 0, activei = 0;
int len = 0;
- int items;
- int found;
- int min, max;
/* validate arguments */
/* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
@@ -2580,6 +2799,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
}
draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default;
+ draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter : uilist_draw_filter_default;
+ filter_items = ui_list_type->filter_items ? ui_list_type->filter_items : uilist_filter_items_default;
/* Find or add the uiList to the current Region. */
/* We tag the list id with the list type... */
@@ -2589,146 +2810,211 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id));
if (!ui_list) {
- ui_list = MEM_callocN(sizeof(uiList), __func__);
+ ui_list = MEM_callocN(sizeof(uiList), AT);
BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id));
BLI_addtail(&ar->ui_lists, ui_list);
}
+ if (!ui_list->dyn_data) {
+ ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), AT);
+ }
+ dyn_data = ui_list->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. */
+ if (dyn_data->items_filter_flags) {
+ MEM_freeN(dyn_data->items_filter_flags);
+ dyn_data->items_filter_flags = NULL;
+ }
+ if (dyn_data->items_filter_neworder) {
+ MEM_freeN(dyn_data->items_filter_neworder);
+ dyn_data->items_filter_neworder = NULL;
+ }
+ dyn_data->items_len = dyn_data->items_shown = -1;
+
+ /* Filter list items! (not for compact layout, though) */
+ if (dataptr->data && prop) {
+ int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+ bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
+ int items_shown, idx = 0;
+#if 0
+ int prev_ii = -1, prev_i;
+#endif
+
+ if (layout_type == UILST_LAYOUT_COMPACT) {
+ dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(dataptr, prop);
+ }
+ else {
+ //printf("%s: filtering...\n", __func__);
+ filter_items(ui_list, C, dataptr, propname);
+ //printf("%s: filtering done.\n", __func__);
+ }
+
+ items_shown = dyn_data->items_shown;
+ if (items_shown >= 0) {
+ items_ptr = MEM_mallocN(sizeof(_uilist_item) * items_shown, AT);
+ //printf("%s: items shown: %d.\n", __func__, items_shown);
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ if (!dyn_data->items_filter_flags ||
+ ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude))
+ {
+ int ii;
+ if (dyn_data->items_filter_neworder) {
+ ii = dyn_data->items_filter_neworder[idx++];
+ ii = order_reverse ? items_shown - ii - 1 : ii;
+ }
+ else {
+ ii = order_reverse ? items_shown - ++idx : idx++;
+ }
+ //printf("%s: ii: %d\n", __func__, ii);
+ items_ptr[ii].item = itemptr;
+ items_ptr[ii].org_idx = i;
+ items_ptr[ii].flt_flag = dyn_data->items_filter_flags ? dyn_data->items_filter_flags[i] : 0;
+
+ if (activei == i) {
+ activei = ii;
+ }
+# 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_ii >= 0) {
+ activei = prev_ii;
+ RNA_property_int_set(active_dataptr, activeprop, prev_i);
+ }
+ else {
+ activei = ii;
+ RNA_property_int_set(active_dataptr, activeprop, i);
+ }
+ }
+ prev_i = i;
+ prev_ii = ii;
+#endif
+ }
+ i++;
+ }
+ RNA_PROP_END;
+ }
+ if (dyn_data->items_shown >= 0) {
+ len = dyn_data->items_shown;
+ }
+ else {
+ len = dyn_data->items_len;
+ }
+ }
+
switch (layout_type) {
case UILST_LAYOUT_DEFAULT:
- /* default rows */
- if (rows == 0)
- rows = 5;
- if (maxrows == 0)
- maxrows = 5;
- if (ui_list->list_grip_size != 0)
- rows = ui_list->list_grip_size;
-
/* layout */
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
- row = uiLayoutRow(box, FALSE);
+ glob = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(glob, FALSE);
col = uiLayoutColumn(row, TRUE);
/* init numbers */
- RNA_property_int_range(active_dataptr, activeprop, &min, &max);
-
- if (prop)
- len = RNA_property_collection_length(dataptr, prop);
- items = CLAMPIS(len, rows, MAX2(rows, maxrows));
-
- /* if list length changes and active is out of view, scroll to it */
- if ((ui_list->list_last_len != len) &&
- (activei < ui_list->list_scroll || activei >= ui_list->list_scroll + items))
- {
- ui_list->list_scroll = activei;
- }
-
- ui_list->list_scroll = min_ii(ui_list->list_scroll, len - items);
- ui_list->list_scroll = max_ii(ui_list->list_scroll, 0);
- ui_list->list_size = items;
- ui_list->list_last_len = len;
+ prepare_list(ui_list, len, activei, rows, maxrows, 1, &layoutdata);
if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
- if (i >= ui_list->list_scroll && i < ui_list->list_scroll + items) {
- subblock = uiLayoutGetBlock(col);
- overlap = uiLayoutOverlap(col);
+ for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
+ PointerRNA *itemptr = &items_ptr[i].item;
+ int org_i = items_ptr[i].org_idx;
+ int flt_flag = items_ptr[i].flt_flag;
+ subblock = uiLayoutGetBlock(col);
- uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
+ overlap = uiLayoutOverlap(col);
+
+ uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, FALSE);
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, FALSE);
- but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, i, 0, 0, NULL);
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+ but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
- sub = uiLayoutRow(overlap, FALSE);
+ sub = uiLayoutRow(overlap, FALSE);
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- if (icon == ICON_DOT)
- icon = ICON_NONE;
- draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
+ org_i, flt_flag);
- /* If we are "drawing" active item, set all labels as active. */
- if (i == activei) {
- ui_layout_list_set_labels_active(sub);
- }
- uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
+ /* If we are "drawing" active item, set all labels as active. */
+ if (i == activei) {
+ ui_layout_list_set_labels_active(sub);
}
- i++;
+
+ uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
}
- RNA_PROP_END;
}
/* add dummy buttons to fill space */
- while (i < ui_list->list_scroll + items) {
- if (i >= ui_list->list_scroll)
- uiItemL(col, "", ICON_NONE);
- i++;
+ for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
+ uiItemL(col, "", ICON_NONE);
}
/* add scrollbar */
- if (len > items) {
+ if (len > layoutdata.visual_items) {
col = uiLayoutColumn(row, FALSE);
- uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &ui_list->list_scroll,
- 0, len - items, items, 0, "");
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, 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 (dataptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
- found = (activei == i);
-
- if (found) {
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- if (icon == ICON_DOT)
- icon = ICON_NONE;
- draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
- }
+ if (dataptr->data && prop && dyn_data->items_shown > 0) {
+ PointerRNA *itemptr = &items_ptr[activei].item;
+ int org_i = items_ptr[activei].org_idx;
- i++;
- }
- RNA_PROP_END;
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, row, dataptr, itemptr, icon, active_dataptr, active_propname, org_i, 0);
}
-
/* if list is empty, add in dummy button */
- if (i == 0)
+ else {
uiItemL(row, "", ICON_NONE);
+ }
/* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
+ BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
- if (i == 0)
+ if (dyn_data->items_shown == 0)
uiButSetFlag(but, UI_BUT_DISABLED);
break;
case UILST_LAYOUT_GRID:
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
- col = uiLayoutColumn(box, TRUE);
- row = uiLayoutRow(col, FALSE);
+ glob = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(glob, FALSE);
+ col = uiLayoutColumn(row, TRUE);
+ subrow = NULL; /* Quite gcc warning! */
+
+ prepare_list(ui_list, len, activei, rows, maxrows, columns, &layoutdata);
if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
+ for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
+ PointerRNA *itemptr = &items_ptr[i].item;
+ int org_i = items_ptr[i].org_idx;
+ int flt_flag = items_ptr[i].flt_flag;
+
/* create button */
- if (!(i % 9))
- row = uiLayoutRow(col, FALSE);
+ if (!(i % columns))
+ subrow = uiLayoutRow(col, FALSE);
- subblock = uiLayoutGetBlock(row);
- overlap = uiLayoutOverlap(row);
+ subblock = uiLayoutGetBlock(subrow);
+ overlap = uiLayoutOverlap(subrow);
uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
@@ -2736,13 +3022,14 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
sub = uiLayoutRow(overlap, FALSE);
but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, i, 0, 0, NULL);
+ active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
sub = uiLayoutRow(overlap, FALSE);
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
+ org_i, flt_flag);
/* If we are "drawing" active item, set all labels as active. */
if (i == activei) {
@@ -2750,13 +3037,67 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
}
uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
+ }
+ }
- i++;
+ /* add dummy buttons to fill space */
+ for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
+ if (!(i % columns)) {
+ subrow = uiLayoutRow(col, FALSE);
}
- RNA_PROP_END;
+ uiItemL(subrow, "", ICON_NONE);
+ }
+
+ /* add scrollbar */
+ if (len > layoutdata.visual_items) {
+ col = uiLayoutColumn(row, FALSE);
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, 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;
}
+
+ if (glob) {
+ row = uiLayoutRow(glob, TRUE);
+ subblock = uiLayoutGetBlock(row);
+ uiBlockSetEmboss(subblock, UI_EMBOSSN);
+
+ if (ui_list->filter_flag & UILST_FLT_SHOW) {
+ but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_DOWN, 0, 0,
+ UI_UNIT_X, UI_UNIT_Y * 0.6f, &(ui_list->filter_flag), 0, 0, 0, 0,
+ TIP_("Hide filtering options"));
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.6f, ui_list,
+ 0.0, 0.0, 0, -1, "");
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ uiBlockSetEmboss(subblock, UI_EMBOSS);
+
+ col = uiLayoutColumn(glob, FALSE);
+ subblock = uiLayoutGetBlock(col);
+ uiDefBut(subblock, SEPR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y * 0.05f, NULL, 0.0, 0.0, 0, 0, "");
+
+ draw_filter(ui_list, C, col);
+ }
+ else {
+ but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_RIGHT, 0, 0,
+ UI_UNIT_X, UI_UNIT_Y * 0.6f, &(ui_list->filter_flag), 0, 0, 0, 0,
+ TIP_("Show filtering options"));
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.6f, ui_list,
+ 0.0, 0.0, 0, -1, "");
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ uiBlockSetEmboss(subblock, UI_EMBOSS);
+ }
+ }
+
+ if (items_ptr) {
+ MEM_freeN(items_ptr);
+ }
}
/************************* Operator Search Template **************************/
@@ -2792,7 +3133,7 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char
if (WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, true,
&name[len + 1], sizeof(name) - len - 1))
{
- name[len] = '|';
+ name[len] = UI_SEP_CHAR;
}
}
@@ -3003,7 +3344,7 @@ static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(
static void template_keymap_item_properties(uiLayout *layout, const char *title, PointerRNA *ptr)
{
- uiLayout *flow;
+ uiLayout *flow, *box, *row;
uiItemS(layout);
@@ -3015,6 +3356,8 @@ static void template_keymap_item_properties(uiLayout *layout, const char *title,
RNA_STRUCT_BEGIN (ptr, prop)
{
int flag = RNA_property_flag(prop);
+ bool is_set = RNA_property_is_set(ptr, prop);
+ uiBut *but;
if (flag & PROP_HIDDEN)
continue;
@@ -3030,8 +3373,22 @@ static void template_keymap_item_properties(uiLayout *layout, const char *title,
}
}
- /* add property */
- uiItemFullR(flow, ptr, prop, -1, 0, 0, NULL, ICON_NONE);
+ box = uiLayoutBox(flow);
+ uiLayoutSetActive(box, is_set);
+ row = uiLayoutRow(box, false);
+
+ /* property value */
+ uiItemFullR(row, ptr, prop, -1, 0, 0, NULL, ICON_NONE);
+
+ if (is_set) {
+ /* unset operator */
+ uiBlock *block = uiLayoutGetBlock(row);
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ but = uiDefIconButO(block, BUT, "UI_OT_unset_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ but->rnapoin = *ptr;
+ but->rnaprop = prop;
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
}
RNA_STRUCT_END;
}
@@ -3047,8 +3404,12 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
/* attach callbacks to compensate for missing properties update,
* we don't know which keymap (item) is being modified there */
- for (; but; but = but->next)
- uiButSetFunc(but, keymap_item_modified, ptr->data, NULL);
+ for (; but; but = but->next) {
+ /* operator buttons may store props for use (file selector, [#36492]) */
+ if (but->rnaprop) {
+ uiButSetFunc(but, keymap_item_modified, ptr->data, NULL);
+ }
+ }
}
}
@@ -3100,6 +3461,8 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P
uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE);
uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE);
+ uiItemR(col, &view_transform_ptr, "look", 0, IFACE_("Look"), ICON_NONE);
+
col = uiLayoutColumn(layout, FALSE);
uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, NULL, ICON_NONE);
if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)