[Bf-blender-cvs] [dc9df6540c0] temp-ui-button-type-refactor: Add own derived struct for search buttons

Julian Eisel noreply at git.blender.org
Fri Jun 5 14:22:47 CEST 2020


Commit: dc9df6540c08b1195f65530be0b1a0374d636c16
Author: Julian Eisel
Date:   Sat May 2 02:06:16 2020 +0200
Branches: temp-ui-button-type-refactor
https://developer.blender.org/rBdc9df6540c08b1195f65530be0b1a0374d636c16

Add own derived struct for search buttons

A complication was that we sometimes change the button type after it's created.
So I had to add logic to reallocate the button if needed, so the derived data
can be used.

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_context_menu.c
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_layout.c
M	source/blender/editors/interface/interface_ops.c
M	source/blender/editors/interface/interface_region_search.c
M	source/blender/editors/interface/interface_templates.c

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index f4dd2da06fc..1222aedbb72 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -58,6 +58,7 @@ struct bNodeSocket;
 struct bNodeTree;
 struct bScreen;
 struct rcti;
+struct uiButSearch;
 struct uiFontStyle;
 struct uiList;
 struct uiStyle;
@@ -504,7 +505,7 @@ typedef void (*uiButHandleHoldFunc)(struct bContext *C, struct ARegion *butregio
 typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
 typedef struct ARegion *(*uiButSearchCreateFunc)(struct bContext *C,
                                                  struct ARegion *butregion,
-                                                 uiBut *but);
+                                                 struct uiButSearch *search_but);
 typedef void (*uiButSearchFunc)(const struct bContext *C,
                                 void *arg,
                                 const char *str,
@@ -1894,8 +1895,6 @@ uiLayout *uiLayoutGridFlow(uiLayout *layout,
 uiLayout *uiLayoutBox(uiLayout *layout);
 uiLayout *uiLayoutListBox(uiLayout *layout,
                           struct uiList *ui_list,
-                          struct PointerRNA *ptr,
-                          struct PropertyRNA *prop,
                           struct PointerRNA *actptr,
                           struct PropertyRNA *actprop);
 uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 8ff3dc11dc7..48c3e25a5ad 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -807,8 +807,14 @@ static bool ui_but_update_from_old_block(const bContext *C,
 
     SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons);
 
-    SWAP(uiButSearchArgFreeFunc, oldbut->search_arg_free_func, but->search_arg_free_func);
-    SWAP(void *, oldbut->search_arg, but->search_arg);
+    if (oldbut->type == UI_BTYPE_SEARCH_MENU) {
+      uiButSearch *search_oldbut = (uiButSearch *)oldbut, *search_but = (uiButSearch *)but;
+
+      SWAP(uiButSearchArgFreeFunc,
+           search_oldbut->item_collect_arg_free_func,
+           search_but->item_collect_arg_free_func);
+      SWAP(void *, search_oldbut->item_collect_arg, search_but->item_collect_arg);
+    }
 
     /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
      * when scrolling without moving mouse (see [#28432]) */
@@ -2941,10 +2947,10 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
           return true;
         }
         else {
+          uiButSearch *search_but = (but->type == UI_BTYPE_SEARCH_MENU) ? (uiButSearch *)but :
+                                                                          NULL;
           /* RNA pointer */
           PointerRNA rptr;
-          PointerRNA ptr = but->rnasearchpoin;
-          PropertyRNA *prop = but->rnasearchprop;
 
           /* This is kind of hackish, in theory think we could only ever use the second member of
            * this if/else, since ui_searchbox_apply() is supposed to always set that pointer when
@@ -2952,7 +2958,9 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
            * to try to break as little as possible existing code. All this is band-aids anyway.
            * Fact remains, using editstr as main 'reference' over whole search button thingy
            * is utterly weak and should be redesigned imho, but that's not a simple task. */
-          if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
+          if (search_but && search_but->rnasearchprop &&
+              RNA_property_collection_lookup_string(
+                  &search_but->rnasearchpoin, search_but->rnasearchprop, str, &rptr)) {
             RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL);
           }
           else if (but->func_arg2 != NULL) {
@@ -3207,6 +3215,27 @@ static void ui_set_but_soft_range(uiBut *but)
 
 /* ******************* Free ********************/
 
+/**
+ * Free data specific to a certain button type.
+ * For now just do in a switch-case, we could instead have a callback stored in #uiBut and set that
+ * in #ui_but_alloc().
+ */
+static void ui_but_free_type_specific(uiBut *but)
+{
+  switch (but->type) {
+    case UI_BTYPE_SEARCH_MENU: {
+      uiButSearch *search_but = (uiButSearch *)but;
+      if (search_but->item_collect_arg_free_func) {
+        search_but->item_collect_arg_free_func(search_but->item_collect_arg);
+        search_but->item_collect_arg = NULL;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+}
+
 /* can be called with C==NULL */
 static void ui_but_free(const bContext *C, uiBut *but)
 {
@@ -3227,10 +3256,7 @@ static void ui_but_free(const bContext *C, uiBut *but)
     MEM_freeN(but->hold_argN);
   }
 
-  if (but->search_arg_free_func) {
-    but->search_arg_free_func(but->search_arg);
-    but->search_arg = NULL;
-  }
+  ui_but_free_type_specific(but);
 
   if (but->active) {
     /* XXX solve later, buttons should be free-able without context ideally,
@@ -3709,16 +3735,95 @@ void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3])
   IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
 }
 
-static uiBut *ui_but_alloc(const eButType type)
+static void ui_but_alloc_info(const eButType type,
+                              size_t *r_alloc_size,
+                              const char **r_alloc_str,
+                              bool *r_has_custom_type)
 {
+  size_t alloc_size;
+  const char *alloc_str;
+  bool has_custom_type = true;
+
   switch (type) {
     case UI_BTYPE_TAB:
-      return MEM_callocN(sizeof(uiButTab), "uiButTab");
+      alloc_size = sizeof(uiButTab);
+      alloc_str = "uiButTab";
+      break;
+    case UI_BTYPE_SEARCH_MENU:
+      alloc_size = sizeof(uiButSearch);
+      alloc_str = "uiButSearch";
+      break;
     default:
-      return MEM_callocN(sizeof(uiBut), "uiBut");
+      alloc_size = sizeof(uiBut);
+      alloc_str = "uiBut";
+      has_custom_type = false;
+      break;
+  }
+
+  if (r_alloc_size) {
+    *r_alloc_size = alloc_size;
+  }
+  if (r_alloc_str) {
+    *r_alloc_str = alloc_str;
+  }
+  if (r_has_custom_type) {
+    *r_has_custom_type = has_custom_type;
   }
 }
 
+static uiBut *ui_but_alloc(const eButType type)
+{
+  size_t alloc_size;
+  const char *alloc_str;
+
+  ui_but_alloc_info(type, &alloc_size, &alloc_str, NULL);
+
+  return MEM_callocN(alloc_size, alloc_str);
+}
+
+/**
+ * Reallocate the button (new address is returned) for a new button type.
+ * This should generally be avoided and instead the correct type be created right away.
+ *
+ * \note Only the #uiBut data can be kept. If the old button used a derived type (e.g. #uiButTab),
+ *       the data that is not inside #uiBut will be lost.
+ */
+uiBut *ui_but_change_type(uiBut *but, eButType new_type)
+{
+  if (but->type != new_type) {
+    size_t alloc_size;
+    const char *alloc_str;
+    uiBut *insert_after_but = but->prev;
+    bool new_has_custom_type, old_has_custom_type;
+
+    /* Remove old button address */
+    BLI_remlink(&but->block->buttons, but);
+
+    ui_but_alloc_info(but->type, NULL, NULL, &old_has_custom_type);
+    ui_but_alloc_info(new_type, &alloc_size, &alloc_str, &new_has_custom_type);
+
+    if (new_has_custom_type || old_has_custom_type) {
+      const void *old_but_ptr = but;
+      /* Button may have pointer to a member within itself, this will have to be updated. */
+      const bool has_str_ptr_to_self = but->str == but->strdata;
+
+      but = MEM_recallocN_id(but, alloc_size, alloc_str);
+      but->type = new_type;
+      if (has_str_ptr_to_self) {
+        but->str = but->strdata;
+      }
+
+      BLI_insertlinkafter(&but->block->buttons, insert_after_but, but);
+
+      const bool found_layout = ui_layout_replace_but_ptr(but->layout, old_but_ptr, but);
+      BLI_assert(found_layout);
+      UNUSED_VARS_NDEBUG(found_layout);
+    }
+  }
+
+  return but;
+}
+
 /**
  * \brief ui_def_but is the function that draws many button types
  *
@@ -6356,7 +6461,7 @@ uiBut *uiDefSearchBut(uiBlock *block,
  * showing the icon and highlighted text after the last instance of this string.
  */
 void UI_but_func_search_set(uiBut *but,
-                            uiButSearchCreateFunc search_create_func,
+                            uiButSearchCreateFunc popup_create_func,
                             uiButSearchFunc search_func,
                             void *arg,
                             uiButSearchArgFreeFunc search_arg_free_func,
@@ -6364,27 +6469,31 @@ void UI_but_func_search_set(uiBut *but,
                             const char *search_sep_string,
                             void *active)
 {
+  uiButSearch *but_search = (uiButSearch *)but;
+
+  BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
+
   /* needed since callers don't have access to internal functions
    * (as an alternative we could expose it) */
-  if (search_create_func == NULL) {
-    search_create_func = ui_searchbox_create_generic;
+  if (popup_create_func == NULL) {
+    popup_create_func = ui_searchbox_create_generic;
   }
 
-  if (but->search_arg_free_func != NULL) {
-    but->search_arg_free_func(but->search_arg);
-    but->search_arg = NULL;
+  if (but_search->item_collect_arg_free_func != NULL) {
+    but_search->item_collect_arg_free_func(but_search->item_collect_arg);
+    but_search->item_collect_arg = NULL;
   }
 
-  but->search_create_func = search_create_func;
-  but->search_func = search_func;
+  but_search->popup_create_func = popup_create_func;
+  but_search->item_collect_func = search_func;
 
-  but->search_arg = arg;
-  but->search_arg_free_func = search_arg_free_func;
-  but->search_sep_string = search_sep_string;
+  but_search->item_collect_arg = arg;
+  but_search->item_collect_arg_free_func = search_arg_free_func;
+  but_search->item_sep_string = search_sep_string;
 
   if (bfunc) {
 #ifdef DEBUG
-    if (but->func) {
+    if (but_search->but.func) {
       /* watch this, can be cause of much confusion, 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list