[Bf-blender-cvs] [58488c08b86] property-search-ui-v2: Property Search: Single tab

Hans Goudey noreply at git.blender.org
Wed Sep 9 21:03:18 CEST 2020


Commit: 58488c08b869a42f81c2acec5b14504a59d5b500
Author: Hans Goudey
Date:   Wed Sep 9 13:00:56 2020 -0500
Branches: property-search-ui-v2
https://developer.blender.org/rB58488c08b869a42f81c2acec5b14504a59d5b500

Property Search: Single tab

This adds a search bar to the properties editor. The full search for every tab
isn't includede in this patch, but the interaction with panels, searching
behavior, internal UI, region level, and DNA changes are included here.

The block-level search works by iterating over the block's buttons and
checking whether they match the search. If they do, they are tagged with
a flag, and the block's panel is tagged too.

For every update (text edit), the panel's expansion is set to whether the
panel has a result or not.

There is some complications to this that you might no initially think of:
1. Closed panel's subpanels have to be searched too. This adds some
   complexity and special cases to the area-level panel layout code.
2. //Maybe more if I think of things to add here//

There might be some methods of simplifying some of the logic, particularly
around choosing whether to highlight panel headers. Also note that automatic
subpanel expansion isn't working right now. I'll look into this, but I want to post
all the patches first.

**Future Improvements**
Here are some improvements possible in the future that won't be part of this patch:
1. Use the new fuzzy search in BLI
2. Reseting panels to their expansion before the search started if you `esc`
   out of the text box
3. Open parent panels if their subpanels have a match but they don't. This
   requires adding a reference to parent panels for subpanels.

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

===================================================================

M	release/scripts/startup/bl_ui/space_properties.py
M	source/blender/editors/include/ED_screen.h
M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_layout.c
M	source/blender/editors/interface/interface_panel.c
M	source/blender/editors/screen/area.c
M	source/blender/editors/space_buttons/space_buttons.c
M	source/blender/makesdna/DNA_screen_types.h
M	source/blender/makesdna/DNA_space_types.h
M	source/blender/makesrna/intern/rna_space.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_properties.py b/release/scripts/startup/bl_ui/space_properties.py
index d4d5843f415..891f73434e0 100644
--- a/release/scripts/startup/bl_ui/space_properties.py
+++ b/release/scripts/startup/bl_ui/space_properties.py
@@ -29,6 +29,10 @@ class PROPERTIES_HT_header(Header):
 
         layout.template_header()
 
+        layout.separator_spacer()
+        layout.prop(view, "search_filter", icon='VIEWZOOM', text="")
+        layout.separator_spacer()
+        
         row = layout.row()
         row.emboss = 'NONE'
         row.operator("buttons.toggle_pin", icon=('PINNED' if view.use_pin_id else 'UNPINNED'), text="")
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index d9c7128c2ee..f4cfb34831d 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -80,6 +80,9 @@ void ED_region_tag_redraw_no_rebuild(struct ARegion *region);
 void ED_region_tag_refresh_ui(struct ARegion *region);
 void ED_region_tag_redraw_editor_overlays(struct ARegion *region);
 
+void ED_region_search_filter_update(const struct bContext *C, struct ARegion *region);
+char *ED_area_search_filter_get(const struct bContext *C);
+
 void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *region);
 void ED_region_panels_ex(const struct bContext *C, struct ARegion *region, const char *contexts[]);
 void ED_region_panels(const struct bContext *C, struct ARegion *region);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 86275ce4d39..58b23d1a4e5 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -157,6 +157,9 @@ enum {
   UI_BLOCK_POPOVER_ONCE = 1 << 22,
   /** Always show keymaps, even for non-menus. */
   UI_BLOCK_SHOW_SHORTCUT_ALWAYS = 1 << 23,
+  /** The block is only used during the search process and will not be drawn.
+   * Currently just for the case of a closed panel's subpanel (and its subpanels). */
+  UI_BLOCK_SEARCH_ONLY = 1 << 25,
 };
 
 /** #uiPopupBlockHandle.menuretval */
@@ -671,6 +674,9 @@ enum {
 void UI_block_theme_style_set(uiBlock *block, char theme_style);
 char UI_block_emboss_get(uiBlock *block);
 void UI_block_emboss_set(uiBlock *block, char emboss);
+bool UI_block_has_search_filter(const uiBlock *block);
+bool UI_block_is_search_only(const uiBlock *block);
+void UI_block_set_search_only(uiBlock *block, bool search_only);
 
 void UI_block_free(const struct bContext *C, uiBlock *block);
 void UI_blocklist_free(const struct bContext *C, struct ListBase *lb);
@@ -1684,6 +1690,8 @@ void UI_panels_scale(struct ARegion *region, float new_width);
 void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y);
 int UI_panel_size_y(const struct Panel *panel);
 bool UI_panel_is_dragging(const struct Panel *panel);
+bool UI_panel_matches_search_filter(const struct Panel *panel);
+void UI_panel_set_expansion_from_seach_filter(const struct bContext *C, struct Panel *panel);
 
 bool UI_panel_category_is_visible(const struct ARegion *region);
 void UI_panel_category_add(struct ARegion *region, const char *name);
@@ -1914,6 +1922,7 @@ float uiLayoutGetUnitsY(uiLayout *layout);
 int uiLayoutGetEmboss(uiLayout *layout);
 bool uiLayoutGetPropSep(uiLayout *layout);
 bool uiLayoutGetPropDecorate(uiLayout *layout);
+void uiLayoutRootSetSearchOnly(uiLayout *layout, bool search_only);
 
 /* layout specifiers */
 uiLayout *uiLayoutRow(uiLayout *layout, bool align);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 0bd4934dd0f..ff05da89993 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1959,8 +1959,12 @@ void UI_block_draw(const bContext *C, uiBlock *block)
         }
       }
     }
-    ui_draw_aligned_panel(
-        &style, block, &rect, UI_panel_category_is_visible(region), show_background);
+    ui_draw_aligned_panel(&style,
+                          block,
+                          &rect,
+                          UI_panel_category_is_visible(region),
+                          show_background,
+                          region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE);
   }
 
   BLF_batch_draw_begin();
@@ -3456,6 +3460,14 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, ch
   block->emboss = emboss;
   block->evil_C = (void *)C; /* XXX */
 
+  /* Set the search filter for the properties editor. */
+  ScrArea *area = CTX_wm_area(C);
+  if ((region && region->regiontype == RGN_TYPE_WINDOW) &&
+      (area && area->spacetype == SPACE_PROPERTIES)) {
+    SpaceProperties *sbuts = CTX_wm_space_properties(C);
+    block->search_filter = sbuts->search_string;
+  }
+
   if (scn) {
     /* store display device name, don't lookup for transformations yet
      * block could be used for non-color displays where looking up for transformation
@@ -3505,6 +3517,21 @@ void UI_block_theme_style_set(uiBlock *block, char theme_style)
   block->theme_style = theme_style;
 }
 
+bool UI_block_has_search_filter(const uiBlock *block)
+{
+  return block->search_filter != NULL && block->search_filter[0] != '\0';
+}
+
+bool UI_block_is_search_only(const uiBlock *block)
+{
+  return block->flag & UI_BLOCK_SEARCH_ONLY;
+}
+
+void UI_block_set_search_only(uiBlock *block, bool search_only)
+{
+  SET_FLAG_FROM_TEST(block->flag, search_only, UI_BLOCK_SEARCH_ONLY);
+}
+
 static void ui_but_build_drawstr_float(uiBut *but, double value)
 {
   size_t slen = 0;
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index fe0d9fda44b..ff8d5d5b55d 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -81,6 +81,8 @@ enum {
   UI_HAS_ICON = (1 << 3),
   UI_HIDDEN = (1 << 4),
   UI_SELECT_DRAW = (1 << 5), /* Display selected, doesn't impact interaction. */
+  /** The button matches the search filter, later used to deactivate it. */
+  UI_SEARCH_FILTER_MATCHES = (1 << 12),
   /* warn: rest of uiBut->flag in UI_interface.h */
 };
 
@@ -525,6 +527,8 @@ struct uiBlock {
    */
   char display_device[64];
 
+  char *search_filter;
+
   struct PieMenuData pie_data;
 };
 
@@ -813,7 +817,9 @@ extern void ui_draw_aligned_panel(const struct uiStyle *style,
                                   const uiBlock *block,
                                   const rcti *rect,
                                   const bool show_pin,
-                                  const bool show_background);
+                                  const bool show_background,
+                                  const bool region_search_filter_active);
+void ui_panel_set_search_filter_match(struct Panel *panel, const bool value);
 
 /* interface_draw.c */
 extern void ui_draw_dropshadow(
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 45085288264..4b767b530f0 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -86,6 +86,13 @@ typedef struct uiLayoutRoot {
   int type;
   int opcontext;
 
+  /**
+   * If true, the root will be removed as part of the property search process.
+   * Necessary for cases like searching the contents of closed panels, where the
+   * block-level tag isn't enough because there might be buttons in the header.
+   */
+  bool search_only;
+
   int emw, emh;
   int padding;
 
@@ -5097,6 +5104,193 @@ int uiLayoutGetEmboss(uiLayout *layout)
   return layout->emboss;
 }
 
+void uiLayoutRootSetSearchOnly(uiLayout *layout, bool search_only)
+{
+  layout->root->search_only = search_only;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Block Layout Search Filtering
+ * \{ */
+
+// #define PROPERTY_SEARCH_USE_TOOLTIPS
+#define PROPERTY_SEARCH_USE_PANEL_LABELS
+
+static void layout_free_and_hide_buttons(uiLayout *layout)
+{
+  LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
+    if (item->type == ITEM_BUTTON) {
+      uiButtonItem *button_item = (uiButtonItem *)item;
+      BLI_assert(button_item->but != NULL);
+      button_item->but->flag |= UI_HIDDEN;
+      MEM_freeN(item);
+    }
+    else {
+      layout_free_and_hide_buttons((uiLayout *)item);
+    }
+  }
+
+  MEM_freeN(layout);
+}
+
+/**
+ * Returns true if a button or the data / operator it represents matches the search filter.
+ *
+ * \note It's important to do the shorter checks first for performance.
+ */
+static bool button_matches_search_filter(uiBut *but, const char *search_filter)
+{
+  if (BLI_strcasestr(but->str, search_filter)) {
+    return true;
+  }
+
+  if (but->optype != NULL) {
+    if (BLI_strcasestr(but->optype->name, search_filter)) {
+      return true;
+    }
+  }
+
+  if (but->rnaprop != NULL) {
+    if (BLI_strcasestr(RNA_property_ui_name(but->rnaprop), search_filter)) {
+      return true;
+    }
+#ifdef PROPERTY_SEARCH_USE_TOOLTIPS
+    if (BLI_strcasestr(RNA_property_description(but->rnaprop), search_filter)) {
+      return true;
+    }
+#endif
+
+    /* Search through labels of enum property items if they are in a dropdown menu.
+     * Unfortunately we have no context here so we cannot search through RNA enums
+     * with dynamic entries (or "itemf" functions) which require context. */
+    if (but->type == UI_BTYPE_MENU) {
+      PointerRNA *ptr = &but->rnapoin;
+      PropertyRNA *enum_prop = but->rnaprop;
+
+      int items_len;
+      const EnumPropertyItem *enum_items = NULL;
+      bool free;
+      RNA_property_enum_items(NULL, ptr, enum_prop, &enum_items, &items_len, &free);
+
+      if (enum_items != NULL) {
+        for (int i = 0; i < items_len; i++) {
+          if (BLI_strcasestr(enum_items[i].name, search_filter)) {
+            return true;
+          }
+        }
+        if (free) {
+          MEM_freeN((void *)enum_items);
+        }
+      }
+    }
+  }
+
+  return false;
+}
+
+/**
+ * Tag all buttons with whether they matched the search filter or

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list