[Bf-blender-cvs] [a33720329bb] property-search-ui: Property Search: New method that reuses existing layouts

Hans Goudey noreply at git.blender.org
Fri Jun 19 13:41:21 CEST 2020


Commit: a33720329bba1204feee6f2e1bee8edb99e4619d
Author: Hans Goudey
Date:   Thu Jun 18 17:00:38 2020 -0400
Branches: property-search-ui
https://developer.blender.org/rBa33720329bba1204feee6f2e1bee8edb99e4619d

Property Search: New method that reuses existing layouts

This method just transforms each layout into a row or a column, without
adding any new layouts at all. There are a few problems with this method
though, the columns have a fixed width for some reason, and it becomes
more difficult to add the label column.

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

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

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

diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 8cf1fb5ce5b..54282664116 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -5072,7 +5072,7 @@ int uiLayoutGetEmboss(uiLayout *layout)
  * \{ */
 
 // #define PROPERTY_SEARCH_USE_TOOLTIPS
-// #define DEBUG_LAYOUT_ROOTS
+#define DEBUG_LAYOUT_ROOTS
 
 static void ui_layout_free(uiLayout *layout);
 
@@ -5149,38 +5149,13 @@ static void debug_print_layout(uiItem *item, int depth)
 #endif /* DEBUG_LAYOUT_ROOTS */
 
 /**
- * Free all layouts except if a child layout has a
+ * Tag all buttons with whether they matched the search filter or not.
  *
- * \return True if the layout was filtered.
+ * \note This doesn't actually remove any buttons, and buttons that were tagged might
+ * not even be removed if they were in a layout with property search turned off.
  */
-// static bool ui_layout_free_filtered(uiLayout *layout)
-// {
-//   bool children_filtered = true;
-//   bool filter_layout = layout->item.flag & UI_ITEM_USE_SEARCH_FILTER;
-//   LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
-//     if (filter_layout && item->type == ITEM_BUTTON) {
-//       MEM_freeN(item);
-//     }
-//     else {
-//       children_filtered &= ui_layout_free_filtered((uiLayout *)item);
-//     }
-//   }
-
-//   filter_layout &= children_filtered;
-
-//   if (filter_layout) {
-//     MEM_freeN(layout);
-//   }
-
-//   return filter_layout;
-// }
-
-/**
- * \return True if all buttons were tagged for removal.
- */
-static bool ui_block_search_filter_tag_buttons(uiBlock *block)
+static void ui_block_search_filter_tag_buttons(uiBlock *block)
 {
-  bool empty = true;
   LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
     /* Flag all buttons with no RNA property. This is probably too strict. */
     if (but->rnaprop == NULL) {
@@ -5204,159 +5179,159 @@ static bool ui_block_search_filter_tag_buttons(uiBlock *block)
     }
 
     but->flag |= UI_FILTERED;
-    empty = false;
   }
-  return empty;
 }
 
-static void move_button_to_search_filter_layout(uiItem *item,
-                                                uiLayout *source_layout,
-                                                uiLayout *labels,
-                                                uiLayout *properties)
+/**
+ * Recursive implementation for #ui_block_search_filter_clean.
+ */
+static bool ui_layout_search_filter_clean_recursive(uiLayout *layout)
 {
-  BLI_assert(item->type == ITEM_BUTTON);
-  uiButtonItem *button_item = (uiButtonItem *)item;
-
-  /* Move the item. */
-  BLI_remlink(&source_layout->items, item);
-  BLI_addtail(&properties->items, item);
-
-  /* Add a label if the text isn't contained in the button. */
-  if (button_item->but->rnaprop) {
-    char name[MAX_NAME];
-    strcpy(name, RNA_property_ui_name(button_item->but->rnaprop));
-    if (ELEM(button_item->but->type,
-             UI_BTYPE_CHECKBOX,
-             UI_BTYPE_TOGGLE_N,
-             UI_BTYPE_ICON_TOGGLE_N,
-             UI_BTYPE_CHECKBOX_N,
-             UI_BTYPE_LABEL)) {
-      /* Toggle buttons with no outside label and have their text changed to the RNA name. */
-      uiItemL(labels, "", ICON_NONE);
-      strcpy(button_item->but->str, name);
-    }
-    else {
-      uiItemL(labels, name, ICON_NONE);
-      /* Add a decorator for animatable properties. */
-      if (/* RNA_property_animateable(...) */ 1) {
-        // uiItemL(decorators, "", ICON_NONE);
+  /* Remove all search filtered button items. */
+  bool layout_emptied = true;
+  if (uiLayoutGetPropSearch(layout)) {
+    LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
+      if (item->type == ITEM_BUTTON) {
+        uiButtonItem *button_item = (uiButtonItem *)item;
+        if (button_item->but->flag & UI_FILTERED) {
+          button_item->but->flag |= UI_HIDDEN;
+          BLI_remlink(&layout->items, item);
+          MEM_freeN(item);
+        }
+        else {
+          layout_emptied = false;
+        }
       }
     }
   }
-  else {
-    uiItemL(labels, "BUTTON NO RNA PROP", ICON_NONE);
+
+  /* Recursively clean sub-layouts. */
+  bool all_children_empty = true;
+  LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
+    if (item->type == ITEM_BUTTON) {
+      BLI_assert(!layout_emptied || !uiLayoutGetPropSearch(layout));
+      continue;
+    }
+
+    bool empty = ui_layout_search_filter_clean_recursive((uiLayout *)item);
+    all_children_empty &= empty;
+
+    if (empty) {
+      BLI_assert(BLI_findindex(&layout->items, item) != -1);
+      BLI_remlink(&layout->items, item);
+      MEM_freeN(item);
+    }
   }
+
+  return layout_emptied && all_children_empty;
 }
 
 /**
- * Check for an expanded / aligned row or column, and move the buttons over to the property search
- * layout if the special case applies. Assumes all filtered buttons have already been removed.
- *
- * \return True if this special case applied and the function did anything.
+ * Remove buttons on layouts with property search set to true,
+ * and remove layouts with no buttons and empty child layouts.
  */
-static bool move_aligned_layout_special_case(uiLayout *labels,
-                                             uiLayout *properties,
-                                             uiLayout *layout)
+static bool ui_block_search_filter_clean(uiBlock *block)
 {
-  /* Check for simple special case conditions. */
-  if (!layout->align || !ELEM(((uiItem *)layout)->type, ITEM_LAYOUT_ROW)) {
-    return false;
-  }
-
-  /* Only apply the special case if there are no sublayouts. */
-  LISTBASE_FOREACH (uiItem *, item, &layout->items) {
-    if (item->type != ITEM_BUTTON) {
-      return false;
+  bool all_roots_empty = true;
+  LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
+    /* Find exceptions to search layout. */
+    if (root->type == UI_LAYOUT_HEADER) {
+      continue;
     }
-  }
-
-  /* Add a label to the label column based on the first button. */
-  uiButtonItem *button_item = (uiButtonItem *)layout->items.first;
-  char name[MAX_NAME];
-  strcpy(name, RNA_property_ui_name(button_item->but->rnaprop));
-  uiItemL(labels, name, ICON_NONE);
 
-  /* Move the buttons to a subrow of the search layout. */
-  uiLayout *aligned_row = uiLayoutRow(properties, true);
-  LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
-    BLI_assert(item->type == ITEM_BUTTON);
+    bool empty = ui_layout_search_filter_clean_recursive(root->layout);
+    all_roots_empty &= empty;
 
-    /* Move the item. */
-    BLI_remlink(&layout->items, item);
-    BLI_addtail(&aligned_row->items, item);
+    /* Empty roots should have all sublayouts freed, but they needs to be freed too. */
+    if (empty) {
+      BLI_assert(BLI_findindex(&block->layouts, root) != -1);
+      BLI_remlink(&block->layouts, root);
+      MEM_freeN(root);
+    }
   }
 
-  return true;
+  return all_roots_empty;
 }
 
-/* HANS-TODO: Use uiLayoutRowWithHeading instead of keeping track of labels
- * and properties separately. */
-
-static bool ui_search_layout_fill(uiLayout *labels, uiLayout *properties, uiLayout *layout)
+static void ui_layout_search_build_recursive(uiLayout *layout,
+                                             int depth,
+                                             bool has_had_horizontal_vertical_switch)
 {
-  BLI_assert(layout->item.type != ITEM_BUTTON);
+  BLI_assert(uiLayoutGetPropSearch(layout) || !BLI_listbase_is_empty(&layout->items));
 
-  /* Don't affect the search layouts. */
-  if (ELEM(layout, labels, properties)) {
-    return true;
-  }
+  uiLayoutSetPropSep(layout, true);
 
-  if (!(layout->item.flag & UI_ITEM_USE_SEARCH_FILTER)) {
-    return false;
-  }
+  bool is_horizontal = uiLayoutGetLocalDir(layout) == UI_LAYOUT_HORIZONTAL &&
+                       (layout->item.type != ITEM_LAYOUT_ROOT);
+  // bool is_horizontal = uiLayoutGetLocalDir(layout) == UI_LAYOUT_HORIZONTAL;
+  bool build_horizontal = is_horizontal && !has_had_horizontal_vertical_switch;
 
-  bool empty = true;
+  layout->item.type = build_horizontal ? ITEM_LAYOUT_ROW : ITEM_LAYOUT_COLUMN;
 
-  /* Remove filtered buttons, checking if the layout will be empty without them. */
   LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
     if (item->type == ITEM_BUTTON) {
       uiButtonItem *button_item = (uiButtonItem *)item;
-      if (button_item->but->flag & UI_FILTERED) {
-        button_item->but->flag |= UI_HIDDEN;
-        BLI_remlink(&layout->items, item);
-        MEM_freeN(item);
+      char name[MAX_NAME];
+      if (button_item->but->rnaprop) {
+        strcpy(name, RNA_property_ui_name(button_item->but->rnaprop));
+
+        /* Toggle buttons have no outside label and so their text is changed to the RNA name. */
+        if (ELEM(button_item->but->type,
+                 UI_BTYPE_CHECKBOX,
+                 UI_BTYPE_TOGGLE_N,
+                 UI_BTYPE_ICON_TOGGLE_N,
+                 UI_BTYPE_CHECKBOX_N,
+                 UI_BTYPE_LABEL)) {
+          strcpy(button_item->but->str, name);
+        }
+        else {
+          // uiLayout *row = uiLayoutRowWithHeading(layout, true, name);
+          // BLI_remlink(&layout->items, item);
+          // BLI_addtail(&row->items, item);
+        }
       }
-      else {
-        empty = false;
+    }
+    else {
+      if (depth > 2) {
+        bool parent_is_horizontal = (layout->parent != NULL) &&
+                                    (uiLayoutGetLocalDir(layout->parent) == UI_LAYOUT_HORIZONTAL);
+        has_had_horizontal_vertical_switch |= (!parent_is_horizontal && is_horizontal);
       }
+      ui_layout_search_build_recursive(
+          (uiLayout *)item, depth + 1, has_had_horizontal_vertical_switch);
     }
   }
+}
 
-  /* Move the remaining filtered items to the property search layout. */
-  if (empty) {
-    /* Pass and move on to the sublayouts. */
-  }
-  else if (move_aligned_layout_special_case(labels, properties, layout)) {
-  }
-  else {
-    /* General case. */
-    LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
-      if (item->type == ITEM_BUTTON) {
-        uiButtonItem *button_item = (uiButtonItem *)it

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list