Commit: 9887b38692e3bcf7ba613ca947fd76e299c58cbd
Author: Severin
Date:   Mon Jul 2 14:19:49 2018 +0200
Branches: temp-tab_drag_drop
https://developer.blender.org/rB9887b38692e3bcf7ba613ca947fd76e299c58cbd

Cleanup: Refactor button-group code

* Split generic button-group code from specific application
* Move button-group API to interface.c.
* Avoid struct abuse by using wrapper structs
* Naming, comments, etc.

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

M       source/blender/blenkernel/BKE_screen.h
M       source/blender/editors/include/UI_interface.h
M       source/blender/editors/interface/interface.c
M       source/blender/editors/interface/interface_templates.c
M       source/blender/makesdna/DNA_screen_types.h

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

diff --git a/source/blender/blenkernel/BKE_screen.h 
b/source/blender/blenkernel/BKE_screen.h
index b1777cb77d7..3f3eca7d34b 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -259,7 +259,7 @@ typedef struct uiListType {
 } uiListType;
 
 typedef bool (*uiButtonGroupIdentifyFunc)(struct uiButtonGroup *, void *);
-typedef void (*uiButtonGroupItemsFunc)(struct uiButtonGroup *, void *, 
ListBase *);
+typedef void (*uiButtonGroupItemsFunc)(void *, ListBase *);
 typedef void (*uiButtonGroupItemDrawFunc)(struct uiBlock *, void *, struct 
uiButtonGroupItemInfo *);
 
 typedef struct uiButtonGroupType {
diff --git a/source/blender/editors/include/UI_interface.h 
b/source/blender/editors/include/UI_interface.h
index 7fef72b7484..946c1822da3 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -810,6 +810,9 @@ void UI_but_focus_on_enter_event(struct wmWindow *win, 
uiBut *but);
 
 void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
 
+struct uiButtonGroup *UI_button_group_ensure(struct ARegion *region, const 
char *name, void *custom_data);
+void UI_button_group_add_sorted_items(struct uiButtonGroup *group, uiBlock 
*block, void *custom_data);
+void UI_button_group_item_add(void *data, ListBase *items);
 void UI_block_button_group_begin(uiBlock *block, struct uiButtonGroup *group);
 void UI_block_button_group_end(uiBlock *block);
 
diff --git a/source/blender/editors/interface/interface.c 
b/source/blender/editors/interface/interface.c
index 3eb8f3d6bb5..5673bc2535c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -4756,6 +4756,157 @@ void UI_but_string_info_get(bContext *C, uiBut *but, 
...)
        }
 }
 
+
+/* -------------------------------------------------------------------- */
+/**
+ * \name Button Group
+ * \brief Generate buttons with custom, storable order.
+ *
+ * Button groups have the following key characteristics:
+ * * Sortable: Contained buttons can be sorted.
+ * * Generates: They in fact do not contain buttons, but manage info on how to
+ *   create and sort buttons on runtime.
+ * * Storable: The mapping for custom sorting is written into files, alongside
+ *   an identifier for this specific group. That way the group can be
+ *   identified and the custom sorting re-applied after reading files.
+ *
+ * Maybe button group is a bit of a misleading term, since it doesn't actually
+ * store the buttons itself.
+ * Via a callback a button-group gathers information from which another
+ * callback can create the buttons then. In-between those two callbacks the
+ * items are sorted in a customizable way.
+ *
+ * \{ */
+
+uiButtonGroup *UI_button_group_ensure(ARegion *region, const char *name, void 
*custom_data)
+{
+       uiButtonGroup *group;
+
+       for (group = region->button_groups.first; group; group = group->next) {
+               if (STREQ(group->type->idname, name) && 
group->type->identify(group, custom_data)) {
+                       return group;
+               }
+       }
+
+       group = MEM_callocN(sizeof(*group), __func__);
+       group->type = WM_uibuttongrouptype_find(name, false);
+       BLI_addtail(&region->button_groups, group);
+
+       return group;
+}
+
+typedef struct SortedButtonGroupItemInfo {
+       struct SortedButtonGroupItemInfo *next, *prev;
+
+       uiButtonGroupItemInfo *item;
+       int new_position_index;
+} SortedButtonGroupItemInfo;
+
+static int ui_button_group_items_cmp(const void *a, const void *b)
+{
+       const SortedButtonGroupItemInfo *item_a = a, *item_b = b;
+       return item_a->new_position_index > item_b->new_position_index ? 1 : 0;
+}
+
+static void ui_button_group_sort(
+        const uiButtonGroup *group, const ListBase *items,
+        ListBase *r_sorted_items)
+{
+       int i = 0;
+       for (uiButtonGroupItemInfo *item = items->first; item; item = 
item->next, i++) {
+               SortedButtonGroupItemInfo *sort_item = 
MEM_callocN(sizeof(*sort_item), __func__);
+
+               sort_item->item = item;
+               sort_item->new_position_index = group->reordered_indices[i];
+               BLI_addtail(r_sorted_items, sort_item);
+       }
+       BLI_listbase_sort(r_sorted_items, ui_button_group_items_cmp);
+}
+
+static void ui_button_group_find_added_items(
+        const uiButtonGroup *group, const ListBase *items,
+        const int prev_tot_items,
+        ListBase *r_added_items)
+{
+       const int difference = group->tot_items - prev_tot_items;
+
+       if (difference == 0) {
+               return;
+       }
+
+       if (difference > 0) {
+               for (uiButtonGroupItemInfo *item = items->first; item; item = 
item->next) {
+                       const bool has_item = BLI_findptr(&group->items, 
item->data,
+                                                         
offsetof(uiButtonGroupItemInfo, data)) != NULL;
+                       if (!has_item) {
+                               uiButtonGroupItemInfo *item_new = 
MEM_dupallocN(item);
+                               BLI_addtail(r_added_items, item_new);
+                       }
+               }
+       }
+}
+
+static void ui_button_group_handle_added_or_removed_items(
+        uiButtonGroup *group, const ListBase *new_items,
+        int old_tot_items)
+{
+       ListBase added_items = {NULL, NULL};
+
+       group->reordered_indices = MEM_recallocN(
+                                      group->reordered_indices, 
sizeof(*group->reordered_indices) * group->tot_items);
+       ui_button_group_find_added_items(group, new_items, old_tot_items, 
&added_items);
+
+       /* Add new items at the end of the list. */
+       const int tot_new_items = group->tot_items - old_tot_items;
+
+       BLI_assert(BLI_listbase_count(&added_items) == tot_new_items);
+       int i = 0;
+       for (uiButtonGroupItemInfo *new_item = added_items.first; new_item; 
new_item = new_item->next, i++) {
+               for (int j = group->tot_items - tot_new_items + i; j > 
new_item->position_index; j--) {
+                       group->reordered_indices[j] = 
group->reordered_indices[j - 1];
+               }
+               group->reordered_indices[new_item->position_index] = 
group->tot_items - tot_new_items + i;
+       }
+       BLI_freelistN(&added_items);
+
+       /* TODO support removing items */
+}
+
+void UI_button_group_add_sorted_items(uiButtonGroup *group, uiBlock *block, 
void *custom_data)
+{
+       const int old_tot_items = group->tot_items;
+       ListBase new_items = {NULL, NULL};
+       ListBase sorted_items = {NULL, NULL};
+
+       group->type->items(custom_data, &new_items);
+       group->tot_items = BLI_listbase_count(&new_items);
+
+       if (!group->reordered_indices || (group->tot_items != old_tot_items)) {
+               ui_button_group_handle_added_or_removed_items(group, 
&new_items, old_tot_items);
+       }
+
+       ui_button_group_sort(group, &new_items, &sorted_items);
+
+       UI_block_button_group_begin(block, group);
+       for (SortedButtonGroupItemInfo *sorted_item = sorted_items.first; 
sorted_item; sorted_item = sorted_item->next) {
+               group->type->item_draw(block, custom_data, sorted_item->item);
+       }
+       UI_block_button_group_end(block);
+
+       BLI_freelistN(&sorted_items);
+       BLI_freelistN(&group->items);
+       group->items = new_items;
+}
+
+void UI_button_group_item_add(void *data, ListBase *items)
+{
+       uiButtonGroupItemInfo *item = MEM_callocN(sizeof(*item), __func__);
+
+       BLI_addtail(items, item);
+       item->data = data;
+       item->position_index = item->prev ? ((uiButtonGroupItemInfo 
*)item->prev)->position_index + 1 : 0;
+}
+
 void UI_block_button_group_begin(uiBlock *block, uiButtonGroup *group)
 {
        BLI_assert(block->current_group == NULL);
diff --git a/source/blender/editors/interface/interface_templates.c 
b/source/blender/editors/interface/interface_templates.c
index b890e8b38b0..b70468dd508 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -103,14 +103,10 @@ void UI_template_fix_linking(void)
 {
 }
 
-
 typedef struct TemplateID {
        PointerRNA ptr;
        PropertyRNA *prop;
 
-       wmOperatorType *unlink_ot; // XXX tmp!
-       PointerRNA active_ptr;
-
        ListBase *idlb;
        short idcode;
        short filter;
@@ -118,123 +114,13 @@ typedef struct TemplateID {
        bool preview;
 } TemplateID;
 
-static uiButtonGroup *ui_button_group_ensure(ARegion *region, const char 
*name, void *custom_data)
-{
-       uiButtonGroup *group;
-
-       for (group = region->button_groups.first; group; group = group->next) {
-               if (STREQ(group->type->idname, name) && 
group->type->identify(group, custom_data)) {
-                       return group;
-               }
-       }
-
-       group = MEM_callocN(sizeof(uiButtonGroup), __func__);
-       group->type = WM_uibuttongrouptype_find(name, false);
-       BLI_addtail(&region->button_groups, group);
-
-       return group;
-}
-
-static int ui_button_group_items_cmp(const void *a, const void *b)
-{
-       const uiButtonGroupItemInfo *item_a = a, *item_b = b;
-       return item_a->position_index > item_b->position_index ? 1 : 0;
-}
-
-static void ui_button_group_sort(
-        const uiButtonGroup *group, const ListBase *items,
-        ListBase *r_sorted_items)
-{
-       int i = 0;
-       for (uiButtonGroupItemInfo *item = items->first; item; item = 
item->next, i++) {
-               uiButtonGroupItemInfo *sort_item = MEM_dupallocN(item);
-
-               sort_item->position_index = group->reordered_indices[i];
-               BLI_addtail(r_sorted_items, sort_item);
-       }
-       BLI_listbase_sort(r_sorted_items, ui_button_group_items_cmp);
-}
-
-static void ui_button_group_find_new_items(
-        const uiButtonGroup *group, const ListBase *current_items, const int 
prev_tot_items,
-        ListBase *r_new_items)
-{
-       const int difference = group->tot_items - prev_tot_items;
-
-       if (difference == 0) {
-               return;
-       }
-
-       if (difference > 0) {
-               for (uiButtonGroupItemInfo *item = current_items->first; item; 
item = item->next) {
-                       const bool has_item = BLI_findptr(&group->items, 
item->data,
-                                                         
offsetof(uiButtonGroupItemInfo, data)) != NULL;
-                       if (!has_item) {
-                               uiButtonGroupItemInfo *item_new = 
MEM_dupallocN(item);
-                               BLI_addtail(r_new_items, item_new);
-                       }
-               }
-       }
-}
-
+typedef struct SortableIDTabsData {
+       TemplateID *template_id;
 
-/* XXX split this up into generic and sortable_id_tabs functions */
-static void ui_template_sortable_id_tabs(
-        ARegion *region, uiBlock *block, TemplateID *template_ui, 
wmOperatorType *unlink_ot)
-{
-       uiButtonGroup *group = ui_button_group_ensure(region, 
"UI_BGT_sortable_id_tabs", template_ui);
-       const int old_tot_items = group->tot_items;
-       ListBase items = {NULL, NULL};
-
-       template_ui->unlink_ot = unlink_ot;
-       template_ui->active_ptr = RNA_property_pointer_get(&temp

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to