[Bf-blender-cvs] [67e630609bb] master: Property Search: Build button groups for Search

Hans Goudey noreply at git.blender.org
Tue Sep 15 16:38:47 CEST 2020


Commit: 67e630609bb408e366398cb7ea9fdc09f31190e7
Author: Hans Goudey
Date:   Tue Sep 15 09:38:19 2020 -0500
Branches: master
https://developer.blender.org/rB67e630609bb408e366398cb7ea9fdc09f31190e7

Property Search: Build button groups for Search

This is needed for property search (upcoming patch D8856) where a
buttons labels are often separate buttons, but we need to highlight
the label to show that a property is a search result. This is
especially important in "property split" layouts where the label is
almost always another button in a separate column.

The button groups here are basically a flattened view of the buttons
in the layout tree. Every function that adds a new set of buttons
creates a new button group, and the new buttons are automatically
added to the most recent group. Then, each group is searched
separately in the property search phase. It's important that every
function adding a new button set calls layout_root_new_button_group.

Note that this won't be disabled when property search isn't active.
It may be useful for other things in the future, and trying to pass
that information to layout functions didn't feel worth it to me.

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

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

M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_layout.c

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

diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 8e7fc807835..b9a001a9571 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -3943,6 +3943,7 @@ uiBut *ui_but_change_type(uiBut *but, eButType new_type)
         const bool found_layout = ui_layout_replace_but_ptr(but->layout, old_but_ptr, but);
         BLI_assert(found_layout);
         UNUSED_VARS_NDEBUG(found_layout);
+        ui_button_group_replace_but_ptr(but->layout, old_but_ptr, but);
       }
     }
   }
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 4661d0816ae..edaadd880d7 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -994,6 +994,7 @@ void ui_resources_free(void);
 /* interface_layout.c */
 void ui_layout_add_but(uiLayout *layout, uiBut *but);
 bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but);
+void ui_button_group_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but);
 uiBut *ui_but_add_search(uiBut *but,
                          PointerRNA *ptr,
                          PropertyRNA *prop,
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index f73e4bb0540..c3bcaff0d0c 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -80,12 +80,25 @@
 
 /* uiLayoutRoot */
 
+/**
+ * A group of button references, used by property search to keep track of sets of buttons that
+ * should be searched together. For example, in property split layouts number buttons and their
+ * labels (and even their decorators) are separate buttons, but they must be searched and
+ * highlighted together.
+ */
+typedef struct uiButtonGroup {
+  void *next, *prev;
+  ListBase buttons; /* #LinkData with #uiBut data field. */
+} uiButtonGroup;
+
 typedef struct uiLayoutRoot {
   struct uiLayoutRoot *next, *prev;
 
   int type;
   int opcontext;
 
+  ListBase button_groups; /* #uiButtonGroup. */
+
   int emw, emh;
   int padding;
 
@@ -414,6 +427,58 @@ static void ui_item_move(uiItem *item, int delta_xmin, int delta_xmax)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Button Groups
+ * \{ */
+
+/**
+ * Every function that adds a set of buttons must create another group,
+ * then #ui_def_but adds buttons to the current group (the last).
+ */
+static void layout_root_new_button_group(uiLayoutRoot *root)
+{
+  uiButtonGroup *new_group = MEM_mallocN(sizeof(uiButtonGroup), __func__);
+  BLI_listbase_clear(&new_group->buttons);
+  BLI_addtail(&root->button_groups, new_group);
+}
+
+static void button_group_add_but(uiLayoutRoot *root, uiBut *but)
+{
+  BLI_assert(root != NULL);
+
+  uiButtonGroup *current_button_group = root->button_groups.last;
+  BLI_assert(current_button_group != NULL);
+
+  /* We can't use the button directly because adding it to
+   * this list would mess with its prev and next pointers. */
+  LinkData *button_link = BLI_genericNodeN(but);
+  BLI_addtail(&current_button_group->buttons, button_link);
+}
+
+static void button_group_free(uiButtonGroup *button_group)
+{
+  BLI_freelistN(&button_group->buttons);
+  MEM_freeN(button_group);
+}
+
+/* This function should be removed whenever #ui_layout_replace_but_ptr is removed. */
+void ui_button_group_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but)
+{
+  LISTBASE_FOREACH (uiButtonGroup *, button_group, &layout->root->button_groups) {
+    LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) {
+      if (link->data == old_but_ptr) {
+        link->data = new_but;
+        return;
+      }
+    }
+  }
+
+  /* The button should be in a group. */
+  BLI_assert(false);
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Special RNA Items
  * \{ */
@@ -2019,6 +2084,7 @@ void uiItemFullR(uiLayout *layout,
 #endif /* UI_PROP_DECORATE */
 
   UI_block_layout_set_current(block, layout);
+  layout_root_new_button_group(layout->root);
 
   /* retrieve info */
   const PropertyType type = RNA_property_type(prop);
@@ -2769,6 +2835,8 @@ void uiItemPointerR_prop(uiLayout *layout,
   char namestr[UI_MAX_NAME_STR];
   const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
 
+  layout_root_new_button_group(layout->root);
+
   type = RNA_property_type(prop);
   if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
     RNA_warning("Property %s.%s must be a pointer, string or enum",
@@ -2874,6 +2942,7 @@ static uiBut *ui_item_menu(uiLayout *layout,
   int w, h;
 
   UI_block_layout_set_current(block, layout);
+  layout_root_new_button_group(layout->root);
 
   if (!name) {
     name = "";
@@ -3141,6 +3210,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
   int w;
 
   UI_block_layout_set_current(block, layout);
+  layout_root_new_button_group(layout->root);
 
   if (!name) {
     name = "";
@@ -5306,6 +5376,16 @@ static void ui_layout_free(uiLayout *layout)
   MEM_freeN(layout);
 }
 
+static void layout_root_free(uiLayoutRoot *root)
+{
+  ui_layout_free(root->layout);
+
+  LISTBASE_FOREACH_MUTABLE (uiButtonGroup *, button_group, &root->button_groups) {
+    button_group_free(button_group);
+  }
+  MEM_freeN(root);
+}
+
 static void ui_layout_add_padding_button(uiLayoutRoot *root)
 {
   if (root->padding) {
@@ -5340,6 +5420,9 @@ uiLayout *UI_block_layout(uiBlock *block,
   root->padding = padding;
   root->opcontext = WM_OP_INVOKE_REGION_WIN;
 
+  BLI_listbase_clear(&root->button_groups);
+  layout_root_new_button_group(root);
+
   layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
   layout->item.type = (type == UI_LAYOUT_VERT_BAR) ? ITEM_LAYOUT_COLUMN : ITEM_LAYOUT_ROOT;
 
@@ -5424,6 +5507,8 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
   if (layout->emboss != UI_EMBOSS_UNDEFINED) {
     but->emboss = layout->emboss;
   }
+
+  button_group_add_but(layout->root, but);
 }
 
 bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but)
@@ -5489,15 +5574,15 @@ void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
 
   block->curlayout = NULL;
 
-  LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) {
+  LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
     ui_layout_add_padding_button(root);
 
     /* NULL in advance so we don't interfere when adding button */
     ui_layout_end(block, root->layout, r_x, r_y);
-    ui_layout_free(root->layout);
+    layout_root_free(root);
   }
 
-  BLI_freelistN(&block->layouts);
+  BLI_listbase_clear(&block->layouts);
 
   /* XXX silly trick, interface_templates.c doesn't get linked
    * because it's not used by other files in this module? */



More information about the Bf-blender-cvs mailing list