[Bf-blender-cvs] [a7e3bbabd2e] modifier-panels-ui: Cleanup: Rearrange code
Hans Goudey
noreply at git.blender.org
Wed Apr 22 21:35:40 CEST 2020
Commit: a7e3bbabd2efcd0e1e6b29f36015fa2bad4b1210
Author: Hans Goudey
Date: Wed Apr 22 14:34:59 2020 -0500
Branches: modifier-panels-ui
https://developer.blender.org/rBa7e3bbabd2efcd0e1e6b29f36015fa2bad4b1210
Cleanup: Rearrange code
===================================================================
M source/blender/editors/interface/interface_panel.c
===================================================================
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index f50e63690ef..ef75c7f08bd 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -106,23 +106,21 @@ typedef struct uiHandlePanelData {
/* animation */
wmTimer *animtimer;
double starttime;
- bool is_drag_drop;
/* dragging */
+ bool is_drag_drop;
int startx, starty;
int startofsx, startofsy;
int startsizex, startsizey;
-
- /* Drag Scrolling */
- double starttime_drag_scroll;
- /* Note: There can be multiple drag scroll "sessions" if the mouse leaves the scoll zone, so we
- * need to keep track of the total scroll separately from the scroll for each "session." */
- float scroll_offset, scroll_offset_total;
-
} uiHandlePanelData;
+typedef struct PanelSort {
+ Panel *panel, *orig;
+} PanelSort;
+
static int get_panel_real_size_y(const Panel *panel);
static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state);
+static int compare_panel(const void *a1, const void *a2);
static void panel_title_color_get(bool show_background, uchar color[4])
{
@@ -248,7 +246,250 @@ static bool panels_need_realign(ScrArea *area, ARegion *region, Panel **r_panel_
return false;
}
-/****************************** panels ******************************/
+/***** Functions for recreate list panels. ***********/
+
+/**
+ * Called in situations where panels need to be added dynamically rather than having only one panel
+ * corresponding to each PanelType.
+ */
+Panel *UI_panel_add_list(
+ ScrArea *sa, ARegion *region, ListBase *panels, PanelType *panel_type, int list_index)
+{
+ Panel *panel = MEM_callocN(sizeof(Panel), "list panel");
+ panel->type = panel_type;
+ BLI_strncpy(panel->panelname, panel_type->idname, sizeof(panel->panelname));
+
+ panel->ofsx = 0;
+ panel->ofsy = 0;
+ panel->sizex = 0;
+ panel->sizey = 0;
+ panel->blocksizex = 0;
+ panel->blocksizey = 0;
+
+ panel->runtime.list_index = list_index;
+
+ /* Add the panel's children too. Although they aren't list panels, we can still use this
+ * function to creat them, as UI_panel_begin does other things we don't need to do. */
+ for (LinkData *link = panel_type->children.first; link; link = link->next) {
+ PanelType *child = link->data;
+ UI_panel_add_list(sa, region, &panel->children, child, list_index);
+ }
+
+ /* If we're adding a recreate list panel, make sure it's added to the end of the list. Check the
+ * context string to make sure we add to the right list.
+ *
+ * We can the panel list is also the display order because the list panel list is rebuild
+ * when the order changes. */
+ if (panel_type->flag & PNL_LIST) {
+ Panel *last_list_panel = NULL;
+
+ for (Panel *list_panel = panels->first; list_panel; list_panel = list_panel->next) {
+ if (list_panel->type == NULL) {
+ continue;
+ }
+ if (list_panel->type->flag & (PNL_LIST_START | PNL_LIST)) {
+ last_list_panel = list_panel;
+ }
+ }
+
+ /* There should always be a list panel or a list panel start before this panel. */
+ BLI_assert(last_list_panel);
+
+ panel->sortorder = last_list_panel->sortorder + 1;
+
+ BLI_insertlinkafter(panels, last_list_panel, panel);
+ }
+ else {
+ BLI_addtail(panels, panel);
+ }
+
+ return panel;
+}
+
+void UI_list_panel_unique_str(Panel *panel, char *r_name)
+{
+ snprintf(r_name, LIST_PANEL_UNIQUE_STR_LEN, "%d", panel->runtime.list_index);
+}
+
+static void panel_free_block(ARegion *region, Panel *panel)
+{
+ BLI_assert(panel->type);
+
+ char block_name[BKE_ST_MAXNAME + LIST_PANEL_UNIQUE_STR_LEN];
+ strncpy(block_name, panel->type->idname, BKE_ST_MAXNAME);
+ char unique_panel_str[LIST_PANEL_UNIQUE_STR_LEN];
+ UI_list_panel_unique_str(panel, unique_panel_str);
+ strncat(block_name, unique_panel_str, LIST_PANEL_UNIQUE_STR_LEN);
+
+ LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) {
+ if (STREQ(block->name, block_name)) {
+ BLI_remlink(®ion->uiblocks, block);
+ UI_block_free(NULL, block);
+ break; /* Only delete one block for this panel. */
+ }
+ }
+}
+
+void UI_panel_delete(ARegion *region, ListBase *panels, Panel *panel)
+{
+ /* Recursively delete children. */
+ Panel *child = panel->children.first;
+ while (child != NULL) {
+ Panel *child_next = child->next;
+ UI_panel_delete(region, &panel->children, child);
+ child = child_next;
+ }
+ BLI_freelistN(&panel->children);
+
+ panel_free_block(region, panel);
+
+ BLI_remlink(panels, panel);
+ if (panel->activedata) {
+ MEM_freeN(panel->activedata);
+ }
+ MEM_freeN(panel);
+}
+
+void UI_panels_free_list(bContext *C, ARegion *region)
+{
+ /* Delete panels with the recreate flag. */
+ ListBase *panels = ®ion->panels;
+ Panel *panel = panels->first;
+ Panel *panel_next = NULL;
+ while (panel != NULL) {
+ bool remove = false;
+ if (panel->type != NULL) { /* Some panels don't have a type.. */
+ if (panel->type->flag & PNL_LIST) {
+ remove = true;
+ }
+ }
+
+ panel_next = panel->next;
+ if (remove) {
+ if (panel->activedata != NULL) {
+ panel_activate_state(C, panel, PANEL_STATE_EXIT);
+ }
+ UI_panel_delete(region, panels, panel);
+ }
+ panel = panel_next;
+ }
+}
+
+/**
+ * Check if the list panels in the region's panel list corresponds to the list of data the panels
+ * represent. Returns false if the panels have been reordered or if the types from the list data
+ * don't match in any way.
+ *
+ * \param data: The list of data to check against the list panels.
+ * \param panel_type_func: Each type from the data list should have a corresponding panel type. For
+ * a mix of readabilty and generality, this can happen separately for each type of panel list.
+ */
+bool UI_panel_list_matches_data(ARegion *region,
+ ListBase *data,
+ uiListPanelTypeFromDataFunc panel_type_func)
+{
+ int data_len = BLI_listbase_count(data);
+ int i = 0;
+ Link *data_link = data->first;
+ Panel *panel = region->panels.first;
+ while (panel != NULL) {
+ if (panel->type != NULL && panel->type->flag & PNL_LIST) {
+ /* The panels were reordered by drag and drop. */
+ if (panel->flag & PNL_LIST_ORDER_CHANGED) {
+ return false;
+ }
+
+ /* We reached the last contraint before the last list panel. */
+ if (data_link == NULL) {
+ return false;
+ }
+
+ /* The types of the corresponding panel and constraint don't match. */
+ if (panel_type_func(region, data_link) != panel->type) {
+ return false;
+ }
+
+ data_link = data_link->next;
+ i++;
+ }
+ panel = panel->next;
+ }
+
+ /* If we didn't make it to the last list item, the panel list isn't complete. */
+ if (i != data_len) {
+ return false;
+ }
+
+ return true;
+}
+
+static void reorder_recreate_panel_list(bContext *C, ARegion *region, Panel *panel)
+{
+ /* Only reorder the data for list panels. */
+ if (panel->type == NULL || !(panel->type->flag & PNL_LIST)) {
+ return;
+ }
+ /* Don't reorder if this list panel doesn't support drag and drop reordering. */
+ if (panel->type->reorder == NULL) {
+ return;
+ }
+
+ char *context = panel->type->context;
+
+ /* Find how many list panels with this context string. */
+ int list_panels_len = 0;
+ for (Panel *list_panel = region->panels.first; list_panel; list_panel = list_panel->next) {
+ if (list_panel->type) {
+ if ((strcmp(list_panel->type->context, context) == 0)) {
+ if (list_panel->type->flag & PNL_LIST) {
+ list_panels_len++;
+ }
+ }
+ }
+ }
+
+ /* Sort the matching list panels by their display order. */
+ PanelSort *panel_sort = MEM_callocN(list_panels_len * sizeof(PanelSort), "recreatepanelsort");
+ PanelSort *sort_index = panel_sort;
+ for (Panel *list_panel = region->panels.first; list_panel; list_panel = list_panel->next) {
+ if (list_panel->type) {
+ if ((strcmp(list_panel->type->context, context) == 0)) {
+ if (list_panel->type->flag & PNL_LIST) {
+ sort_index->panel = MEM_dupallocN(list_panel);
+ sort_index->orig = list_panel;
+ sort_index++;
+ }
+ }
+ }
+ }
+ qsort(panel_sort, list_panels_len, sizeof(PanelSort), compare_panel);
+
+ /* Find how many of those panels are above this panel. */
+ int move_to_index = 0;
+ for (; move_to_index < list_panels_len; move_to_index++) {
+ if (panel_sort[move_to_index].orig == panel) {
+ break;
+ }
+ }
+
+ /* Free panel sort array. */
+ int i = 0;
+ for (sort_index = panel_sort; i < list_panels_len; i++, sort_index++) {
+ MEM_freeN(sort_index->panel);
+ }
+ MEM_freeN(panel_sort);
+
+ /* Don't reorder the panel didn't change order after being dropped. */
+ if (move_to_index == panel->runtime.list_index) {
+ return;
+ }
+
+ /* Set the bit to tell the interface to recreate the list. */
+ panel->flag |= PNL_LIST_ORDER_CHANGED;
+
+ /* Finally, move this panel's list item to the new index in its list. */
+ panel->type->reorder(C, panel, move_to_index);
+}
/**
* Recursive implementation for #UI_panel_set_expand_from_list_data.
@@ -332,6 +573,8 @@ static void set_panels_list_data_expand_flag(const bContext *C, ARegion *region)
}
}
+/****************************** panels ******************************/
+
static void panels_collapse_all(const bContext *C,
ScrArea *area,
ARegion *region,
@@ -463,272 +706,95 @@ Panel *UI_panel_begin(ScrArea *area,
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
}
- *r_open = false;
-
- if (panel->flag & PNL_CLOSED) {
- return panel;
- }
-
- *r_open = true;
-
- return panel;
-}
-
-static float panel_region_offset_x_get(const ARegion *region, int align)
-{
- if (UI_panel_category_is_visible(region)) {
- if (align == BUT_VERTICAL &&
- (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) != RGN_ALIGN_RIGHT)) {
- return UI_PANEL_CATEGORY_MARGIN_WIDTH;
- }
-
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list