Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / interface / interface_utils.c
index 1927d7280f3c3e66650c456316261481d29c6d3a..f0317087ddced3c8582c9a563f2d03351403e92b 100644 (file)
@@ -215,8 +215,90 @@ int uiDefAutoButsRNA(
        return tot;
 }
 
-/***************************** ID Utilities *******************************/
+/* *** RNA collection search menu *** */
 
+typedef struct CollItemSearch {
+       struct CollItemSearch *next, *prev;
+       void *data;
+       char *name;
+       int index;
+       int iconid;
+} CollItemSearch;
+
+static int sort_search_items_list(const void *a, const void *b)
+{
+       const CollItemSearch *cis1 = a;
+       const CollItemSearch *cis2 = b;
+
+       if (BLI_strcasecmp(cis1->name, cis2->name) > 0)
+               return 1;
+       else
+               return 0;
+}
+
+void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items)
+{
+       uiRNACollectionSearch *data = arg;
+       char *name;
+       int i = 0, iconid = 0, flag = RNA_property_flag(data->target_prop);
+       ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
+       CollItemSearch *cis;
+       const bool skip_filter = !(data->but_changed && *data->but_changed);
+
+       /* build a temporary list of relevant items first */
+       RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop)
+       {
+
+               if (flag & PROP_ID_SELF_CHECK)
+                       if (itemptr.data == data->target_ptr.id.data)
+                               continue;
+
+               /* use filter */
+               if (RNA_property_type(data->target_prop) == PROP_POINTER) {
+                       if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0)
+                               continue;
+               }
+
+               name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
+               iconid = 0;
+               if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
+                       iconid = ui_id_icon_get(C, itemptr.data, false);
+               }
+
+               if (name) {
+                       if (skip_filter || BLI_strcasestr(name, str)) {
+                               cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
+                               cis->data = itemptr.data;
+                               cis->name = MEM_dupallocN(name);
+                               cis->index = i;
+                               cis->iconid = iconid;
+                               BLI_addtail(items_list, cis);
+                       }
+                       MEM_freeN(name);
+               }
+
+               i++;
+       }
+       RNA_PROP_END;
+
+       BLI_listbase_sort(items_list, sort_search_items_list);
+
+       /* add search items from temporary list */
+       for (cis = items_list->first; cis; cis = cis->next) {
+               if (UI_search_item_add(items, cis->name, cis->data, cis->iconid) == false) {
+                       break;
+               }
+       }
+
+       for (cis = items_list->first; cis; cis = cis->next) {
+               MEM_freeN(cis->name);
+       }
+       BLI_freelistN(items_list);
+       MEM_freeN(items_list);
+}
+
+
+/***************************** ID Utilities *******************************/ 
 int UI_icon_from_id(ID *id)
 {
        Object *ob;