UI: Show library status icons in search menus, rather than letter prefix
authorJulian Eisel <julian@blender.org>
Mon, 29 Jun 2020 15:19:43 +0000 (17:19 +0200)
committerJulian Eisel <julian@blender.org>
Mon, 29 Jun 2020 15:28:37 +0000 (17:28 +0200)
Rather than a `L` (linked), `O` (overridden) or `M` (missing) prefix for the
name, show the existing library status icons. See D7999 for screenshots.

Note that when using preview icons, or if the search menu contains items with
own icons (e.g. brush icons), we still fallback to the prefix solution.

Zero or fake user is still indicated with a prefix.

Differential Revision: https://developer.blender.org/D7999

Reviewed by: Bastien Montagne, William Reynish

source/blender/blenkernel/BKE_lib_id.h
source/blender/blenkernel/intern/lib_id.c
source/blender/editors/include/UI_interface_icons.h
source/blender/editors/interface/interface_icons.c
source/blender/editors/interface/interface_region_search.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_utils.c
source/blender/editors/space_outliner/outliner_draw.c

index e6a711732c92b80ac04aa7712300081743d83cac..bc72afdd08d7f2fbb6a0c8622404dd11569d9c84 100644 (file)
@@ -267,6 +267,7 @@ void BKE_main_id_repair_duplicate_names_listbase(struct ListBase *lb);
 void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const struct ID *id, char separator_str);
 void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI],
                                     const struct ID *id,
+                                    const bool add_lib_hint,
                                     char separator_char);
 
 char *BKE_id_to_unique_string_key(const struct ID *id);
index 0312fa566e86975230cc3f344659d2f2b2b854ba..b983249994b1a9bbd7789d847ab5c03ed72216ef 100644 (file)
@@ -2175,13 +2175,18 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separa
  */
 void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI],
                                     const ID *id,
+                                    const bool add_lib_hint,
                                     char separator_char)
 {
-  name[0] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ID_IS_OVERRIDE_LIBRARY(id) ? 'O' : ' ';
-  name[1] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
-  name[2] = ' ';
+  int i = 0;
+
+  if (add_lib_hint) {
+    name[i++] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ID_IS_OVERRIDE_LIBRARY(id) ? 'O' : ' ';
+  }
+  name[i++] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
+  name[i++] = ' ';
 
-  BKE_id_full_name_get(name + 3, id, separator_char);
+  BKE_id_full_name_get(name + i, id, separator_char);
 }
 
 /**
index a304c76bc9d76137c98e0acb3eea893588257eeb..0529ee08da6670427eee9c3ae52cd4a1a279910e 100644 (file)
@@ -106,6 +106,7 @@ struct PreviewImage *UI_icon_to_preview(int icon_id);
 
 int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
 int UI_idcode_icon_get(const int idcode);
+int UI_library_icon_get(const struct ID *id);
 
 #ifdef __cplusplus
 }
index deea302835456050fd9f66a2aee3e97d2ce10b98..7411639a99fb71ab51fa7226af9c499718fad0d6 100644 (file)
@@ -2192,6 +2192,26 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big)
   return iconid;
 }
 
+int UI_library_icon_get(const ID *id)
+{
+  if (ID_IS_LINKED(id)) {
+    if (id->tag & LIB_TAG_MISSING) {
+      return ICON_LIBRARY_DATA_BROKEN;
+    }
+    else if (id->tag & LIB_TAG_INDIRECT) {
+      return ICON_LIBRARY_DATA_INDIRECT;
+    }
+    else {
+      return ICON_LIBRARY_DATA_DIRECT;
+    }
+  }
+  else if (ID_IS_OVERRIDE_LIBRARY(id)) {
+    return ICON_LIBRARY_DATA_OVERRIDE;
+  }
+
+  return ICON_NONE;
+}
+
 int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big)
 {
   ID *id = NULL;
index 68be08ef4f885d063dd192d464e28202018698ca..c88dd1954c9a60a96879d6ec718631341b9335ef 100644 (file)
@@ -77,6 +77,9 @@ struct uiSearchItems {
   int *icons;
   int *states;
 
+  /** Is there any item with an icon? */
+  bool has_icon;
+
   AutoComplete *autocpl;
   void *active;
 };
@@ -122,6 +125,10 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int
     return true;
   }
 
+  if (iconid) {
+    items->has_icon = true;
+  }
+
   /* hijack for finding active item */
   if (items->active) {
     if (poin == items->active) {
@@ -562,6 +569,10 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region)
         /* widget itself */
         if ((search_sep_len == 0) ||
             !(name_sep_test = strstr(data->items.names[a], data->sep_string))) {
+          if (!icon && data->items.has_icon) {
+            /* If there is any icon item, make sure all items line up. */
+            icon = ICON_BLANK1;
+          }
 
           /* Simple menu item. */
           ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, use_sep_char, NULL);
index d06c1a251f696be3b994d50aabcc83ad6afcdda3..c22eb097761e5745a4a3578c7f9aee0ab82676af 100644 (file)
@@ -361,11 +361,16 @@ static bool id_search_add(const bContext *C,
        * followed by ID_NAME-2 characters from id->name
        */
       char name_ui[MAX_ID_FULL_NAME_UI];
-      BKE_id_full_name_ui_prefix_get(name_ui, id, UI_SEP_CHAR);
-
       int iconid = ui_id_icon_get(C, id, template_ui->preview);
       bool has_sep_char = (id->lib != NULL);
 
+      /* When using previews, the library hint (linked, overriden, missing) is added with a
+       * character prefix, otherwise we can use a icon. */
+      BKE_id_full_name_ui_prefix_get(name_ui, id, template_ui->preview, UI_SEP_CHAR);
+      if (!template_ui->preview) {
+        iconid = UI_library_icon_get(id);
+      }
+
       if (!UI_search_item_add(
               items, name_ui, id, iconid, has_sep_char ? UI_BUT_HAS_SEP_CHAR : 0)) {
         return false;
index 3737b607305fa9385bdfb8ed09536d99fe5919f5..432da3d5dd539750be04ac128937352e24d0e96a 100644 (file)
@@ -45,6 +45,7 @@
 #include "RNA_access.h"
 
 #include "UI_interface.h"
+#include "UI_interface_icons.h"
 #include "UI_resources.h"
 
 #include "WM_api.h"
@@ -384,6 +385,7 @@ typedef struct CollItemSearch {
   char *name;
   int index;
   int iconid;
+  bool is_id;
   uint has_sep_char : 1;
 } CollItemSearch;
 
@@ -418,6 +420,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
   const bool skip_filter = data->search_but && !data->search_but->changed;
   char name_buf[UI_MAX_DRAW_STR];
   char *name;
+  bool has_id_icon = false;
 
   /* build a temporary list of relevant items first */
   RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) {
@@ -437,16 +440,20 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
 
     int iconid = ICON_NONE;
     bool has_sep_char = false;
+    bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type);
 
-    if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
+    if (is_id) {
       iconid = ui_id_icon_get(C, itemptr.data, false);
+      if (!ELEM(iconid, 0, ICON_BLANK1)) {
+        has_id_icon = true;
+      }
 
       if (requires_exact_data_name) {
         name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL);
       }
       else {
         const ID *id = itemptr.data;
-        BKE_id_full_name_ui_prefix_get(name_buf, id, UI_SEP_CHAR);
+        BKE_id_full_name_ui_prefix_get(name_buf, itemptr.data, true, UI_SEP_CHAR);
         BLI_STATIC_ASSERT(sizeof(name_buf) >= MAX_ID_FULL_NAME_UI,
                           "Name string buffer should be big enough to hold full UI ID name");
         name = name_buf;
@@ -464,6 +471,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
         cis->name = BLI_strdup(name);
         cis->index = i;
         cis->iconid = iconid;
+        cis->is_id = is_id;
         cis->has_sep_char = has_sep_char;
         BLI_addtail(items_list, cis);
       }
@@ -480,6 +488,17 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
 
   /* add search items from temporary list */
   for (cis = items_list->first; cis; cis = cis->next) {
+    /* If no item has an own icon to display, libraries can use the library icons rather than the
+     * name prefix for showing the library status. */
+    if (!has_id_icon && cis->is_id) {
+      cis->iconid = UI_library_icon_get(cis->data);
+      /* No need to re-allocate, string should be shorter than before (lib status prefix is
+       * removed). */
+      BKE_id_full_name_ui_prefix_get(name_buf, cis->data, false, UI_SEP_CHAR);
+      BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name));
+      strcpy(cis->name, name_buf);
+    }
+
     if (!UI_search_item_add(items,
                             cis->name,
                             cis->data,
index 7009d416e918195a7f7772ae46ee2ff168051d73..2dd0d9477dea78faaf227b195b865d75f0208d7f 100644 (file)
@@ -3108,33 +3108,13 @@ static void outliner_draw_tree_element(bContext *C,
       offsx += 2 * ufac;
     }
 
-    if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) {
-      if (tselem->id->tag & LIB_TAG_MISSING) {
-        UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
-                           (float)*starty + 2 * ufac,
-                           ICON_LIBRARY_DATA_BROKEN,
-                           alpha_fac);
-      }
-      else if (tselem->id->tag & LIB_TAG_INDIRECT) {
-        UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
-                           (float)*starty + 2 * ufac,
-                           ICON_LIBRARY_DATA_INDIRECT,
-                           alpha_fac);
+    if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
+      const BIFIconID lib_icon = UI_library_icon_get(tselem->id);
+      if (lib_icon != ICON_NONE) {
+        UI_icon_draw_alpha(
+            (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, lib_icon, alpha_fac);
+        offsx += UI_UNIT_X + 4 * ufac;
       }
-      else {
-        UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
-                           (float)*starty + 2 * ufac,
-                           ICON_LIBRARY_DATA_DIRECT,
-                           alpha_fac);
-      }
-      offsx += UI_UNIT_X + 4 * ufac;
-    }
-    else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_OVERRIDE_LIBRARY(tselem->id)) {
-      UI_icon_draw_alpha((float)startx + offsx + 2 * ufac,
-                         (float)*starty + 2 * ufac,
-                         ICON_LIBRARY_DATA_OVERRIDE,
-                         alpha_fac);
-      offsx += UI_UNIT_X + 4 * ufac;
     }
     GPU_blend(false);