From 4fbc49ff4b9e40ba2326ca77996c281bbb9284dd Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 14 Sep 2020 17:21:42 -0500 Subject: Property Search: Fixes for all tab search V2 --- source/blender/editors/include/UI_interface.h | 2 - source/blender/editors/interface/interface_panel.c | 17 ++------ source/blender/editors/screen/area.c | 41 ++++++++++-------- .../blender/editors/space_buttons/space_buttons.c | 48 +++++++++++++++------- source/blender/makesdna/DNA_space_types.h | 12 ++++-- source/blender/makesrna/intern/rna_space.c | 1 + 6 files changed, 69 insertions(+), 52 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 6655db3395c..48112e70f7c 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1718,8 +1718,6 @@ struct PointerRNA *UI_region_panel_custom_data_under_cursor(const struct bContex const struct wmEvent *event); void UI_panel_custom_data_set(struct Panel *panel, struct PointerRNA *custom_data); -void UI_region_panels_remove_handlers(const struct bContext *C, struct ARegion *region); - /* Polyinstantiated panels for representing a list of data. */ struct Panel *UI_panel_add_instanced(struct ARegion *region, struct ListBase *panels, diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index d4b9e0d849c..fdfb8a6b177 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -2647,13 +2647,6 @@ static void ui_handler_remove_panel(bContext *C, void *userdata) panel_activate_state(C, panel, PANEL_STATE_EXIT); } -void UI_region_panels_remove_handlers(const bContext *C, ARegion *region) -{ - LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { - panel_activate_state(C, panel, PANEL_STATE_EXIT); - } -} - static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state) { uiHandlePanelData *data = panel->activedata; @@ -2681,13 +2674,11 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS } if (state == PANEL_STATE_EXIT) { - if (data != NULL) { - MEM_freeN(data); - panel->activedata = NULL; + MEM_freeN(data); + panel->activedata = NULL; - WM_event_remove_ui_handler( - &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, false); - } + WM_event_remove_ui_handler( + &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, false); } else { if (!data) { diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 0b28dd45ab2..229cd80143c 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2716,7 +2716,6 @@ static void ed_panel_draw(const bContext *C, LISTBASE_FOREACH (LinkData *, link, &pt->children) { PanelType *child_pt = link->data; Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt); - if (child_pt->draw && (!child_pt->poll || child_pt->poll(C, child_pt))) { ed_panel_draw(C, region, @@ -2780,6 +2779,8 @@ static bool panel_add_check(const bContext *C, static bool region_uses_category_tabs(const ScrArea *area, const ARegion *region) { + /* XXX, should use some better check? */ + /* For now also has hardcoded check for clip editor until it supports actual toolbar. */ return ((1 << region->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) || (region->regiontype == RGN_TYPE_TOOLS && area->spacetype == SPACE_CLIP); } @@ -2834,8 +2835,6 @@ void ED_region_panels_layout_ex(const bContext *C, View2D *v2d = ®ion->v2d; int x, y, w, em; - /* XXX, should use some better check? */ - /* For now also has hardcoded check for clip editor until it supports actual toolbar. */ bool use_category_tabs = (category_override == NULL) && region_uses_category_tabs(area, region); /* offset panels for small vertical tab area */ const char *category = NULL; @@ -3085,42 +3084,42 @@ static bool panel_property_search(const bContext *C, panel = UI_panel_begin(region, ®ion->panels, block, panel_type, panel, &open); } - /* Check after each layout to increase the likelyhood of returning early. */ + /* Build the layouts. Because they are only used for search, + * they don't need any of the proper style or layout information. */ if (panel->type->draw_header_preset != NULL) { panel->layout = UI_block_layout( block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style); uiLayoutRootSetSearchOnly(panel->layout, true); panel_type->draw_header_preset(C, panel); - if (UI_block_apply_search_filter(block)) { - return true; - } } - if (panel->type->draw_header != NULL) { panel->layout = UI_block_layout( block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style); uiLayoutRootSetSearchOnly(panel->layout, true); panel_type->draw_header(C, panel); - if (UI_block_apply_search_filter(block)) { - return true; - } } - if (LIKELY(panel->type->draw != NULL)) { panel->layout = UI_block_layout( block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 0, 0, 0, style); uiLayoutRootSetSearchOnly(panel->layout, true); panel_type->draw(C, panel); - if (UI_block_apply_search_filter(block)) { - return true; - } + } + + /* We could check after each layout to increase the likelyhood of returning early, + * but that probably wouldn't make much of a difference anyway. */ + if (UI_block_apply_search_filter(block)) { + return true; } LISTBASE_FOREACH (LinkData *, link, &panel_type->children) { PanelType *panel_type_child = link->data; if (LIKELY(panel->type->draw != NULL)) { if (!panel_type_child->poll || panel_type_child->poll(C, panel_type_child)) { - if (panel_property_search(C, region, style, NULL, panel_type_child, search_filter)) { + /* Search for the existing child panel here because it might be an instanced + * child panel with a custom data field that will be needed to build the layout. */ + Panel *child_panel = UI_panel_find_by_type(&panel->children, panel_type_child); + if (panel_property_search( + C, region, style, child_panel, panel_type_child, search_filter)) { return true; } } @@ -3139,7 +3138,7 @@ bool ED_region_property_search(const bContext *C, ScrArea *area = CTX_wm_area(C); WorkSpace *workspace = CTX_wm_workspace(C); const uiStyle *style = UI_style_get_dpi(); - const char *search_filter = ED_area_search_filter_get(CTX_wm_area(C), region); + const char *search_filter = ED_area_search_filter_get(area, region); LinkNode *panel_types_stack = NULL; LISTBASE_FOREACH_BACKWARD (PanelType *, pt, paneltypes) { @@ -3154,11 +3153,12 @@ bool ED_region_property_search(const bContext *C, category = region_panels_collect_categories(region, panel_types_stack, &use_category_tabs); } + /* Run property search for each panel, stopping if a result is found. */ bool has_result = true; bool has_instanced_panel = false; for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) { PanelType *panel_type = pt_link->link; - + /* Note that these checks are duplicated from #ED_region_panels_layout_ex. */ if (panel_type->flag & PNL_INSTANCED) { has_instanced_panel = true; continue; @@ -3170,14 +3170,18 @@ bool ED_region_property_search(const bContext *C, } } + /* We start property search with an empty panel list, so there's + * no point in trying to find an existing panel with this type. */ has_result = panel_property_search(C, region, style, NULL, panel_type, search_filter); if (has_result) { break; } } + /* Run property search for instanced panels (created in the layout calls of previous panels). */ if (!has_result && has_instanced_panel) { LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + /* Note that these checks are duplicated from #ED_region_panels_layout_ex. */ if (panel->type == NULL || !(panel->type->flag & PNL_INSTANCED)) { continue; } @@ -3194,6 +3198,7 @@ bool ED_region_property_search(const bContext *C, } } + /* Free the panels and blocks, as they are only used for search. */ UI_blocklist_free(C, ®ion->uiblocks); UI_panels_free_instanced(C, region); BKE_area_region_panels_free(®ion->panels); diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index dbdfffb2d56..dd2f1545e47 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -111,8 +111,7 @@ static void buttons_free(SpaceLink *sl) MEM_freeN(ct); } - BLI_assert(sbuts->runtime != NULL); - MEM_freeN(sbuts->runtime); + MEM_SAFE_FREE(sbuts->runtime); } /* spacetype; init callback */ @@ -296,14 +295,15 @@ static void buttons_main_region_layout_properties(const bContext *C, ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, contexts, NULL); } -static bool property_search_for_context(const bContext *C, ARegion *region, const short mainb) +static bool property_search_for_context(const bContext *C, ARegion *region, SpaceProperties *sbuts) { - const char *contexts[2] = {buttons_main_region_context_string(mainb), NULL}; + const char *contexts[2] = {buttons_main_region_context_string(sbuts->mainb), NULL}; - if (mainb == BCONTEXT_TOOL) { + if (sbuts->mainb == BCONTEXT_TOOL) { return false; } else { + buttons_context_compute(C, sbuts); return ED_region_property_search(C, region, ®ion->type->paneltypes, contexts, NULL); } } @@ -322,7 +322,7 @@ static void property_search_move_to_next_tab_with_results(SpaceProperties *sbuts /* Try the tabs after the current tab. */ for (int i = current_tab_index; i < tabs_len; i++) { - if (sbuts->context_search_filter_active & (1 << i)) { + if (sbuts->runtime->context_search_filter_active & (1 << i)) { sbuts->mainbuser = context_tabs_array[i]; return; } @@ -330,7 +330,7 @@ static void property_search_move_to_next_tab_with_results(SpaceProperties *sbuts /* Try the tabs before the current tab. */ for (int i = 0; i < current_tab_index; i++) { - if (sbuts->context_search_filter_active & (1 << i)) { + if (sbuts->runtime->context_search_filter_active & (1 << i)) { sbuts->mainbuser = context_tabs_array[i]; return; } @@ -343,12 +343,12 @@ static void property_search_all_tabs(const bContext *C, const int *context_tabs_array, const int tabs_len) { - sbuts->context_search_filter_active = 0; + sbuts->runtime->context_search_filter_active = 0; /* Duplicate space and region so we don't change any data for this space. */ ScrArea *area_copy = MEM_dupallocN(CTX_wm_area(C)); - ARegion *region_copy = BKE_area_region_copy(CTX_wm_area(C)->type, main_region); - BLI_listbase_clear(®ion_copy->panels); + ARegion *region_copy = BKE_area_region_copy(area_copy->type, main_region); + BKE_area_region_panels_free(®ion_copy->panels); bContext *C_copy = CTX_copy(C); CTX_wm_area_set(C_copy, area_copy); CTX_wm_region_set(C_copy, region_copy); @@ -366,10 +366,10 @@ static void property_search_all_tabs(const bContext *C, continue; } - sbuts_copy->mainb = sbuts->mainbo = sbuts_copy->mainbuser = context_tabs_array[i]; + sbuts_copy->mainb = sbuts_copy->mainbo = sbuts_copy->mainbuser = context_tabs_array[i]; - SET_FLAG_FROM_TEST(sbuts->context_search_filter_active, - property_search_for_context(C_copy, region_copy, sbuts_copy->mainb), + SET_FLAG_FROM_TEST(sbuts->runtime->context_search_filter_active, + property_search_for_context(C_copy, region_copy, sbuts_copy), (1 << i)); } @@ -398,6 +398,7 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region) property_search_all_tabs(C, sbuts, region, context_tabs_array, tabs_len); + /* Check whether the current tab has a search match. */ bool current_tab_has_search_match = false; LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (UI_panel_is_active(panel) && UI_panel_matches_search_filter(panel)) { @@ -405,8 +406,25 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region) } } - if (!current_tab_has_search_match && region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { - property_search_move_to_next_tab_with_results(sbuts, context_tabs_array, tabs_len); + /* Find which index in the list the current tab corresponds to. */ + int current_tab_index = -1; + for (int i = 0; i < tabs_len; i++) { + if (context_tabs_array[i] == sbuts->mainb) { + current_tab_index = i; + } + } + BLI_assert(current_tab_index != -1); + + /* Update the tab search match flag for the current tab. */ + SET_FLAG_FROM_TEST(sbuts->runtime->context_search_filter_active, + current_tab_has_search_match, + (1 << current_tab_index)); + + /* Move to the next tab with a result */ + if (!current_tab_has_search_match) { + if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { + property_search_move_to_next_tab_with_results(sbuts, context_tabs_array, tabs_len); + } } } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 827c233f99e..86218eaaf03 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -132,6 +132,13 @@ typedef enum eSpaceInfo_RptMask { typedef struct SpaceProperties_Runtime { /** For filtering properties displayed in the space. Length defined as UI_MAX_NAME_STR. */ char search_string[128]; + /** + * Bitfield flag (in the same order as the tabs) for whether each tab has properties + * that match the search filter. Only valid when #search_string is set. + */ + int context_search_filter_active; + + char _pad[4]; } SpaceProperties_Runtime; /* Properties Editor */ @@ -152,12 +159,9 @@ typedef struct SpaceProperties { /** Context tabs. */ short mainb, mainbo, mainbuser; - /** Runtime. Bitfield flag (in the same order as the tabs) for whether each tab has properties - * that match the search filter. Only valid when #search_string is set. */ - int context_search_filter_active; /** Preview is signal to refresh. */ short preview; - char _pad[1]; + char _pad[5]; char flag; /** Runtime. */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 74a18f98e25..49538c4e2b9 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -4496,6 +4496,7 @@ static void rna_def_space_properties(BlenderRNA *brna) /* Property search. */ prop = RNA_def_property(srna, "context_search_filter_active", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "runtime->context_search_filter_active"); RNA_def_property_enum_items(prop, buttons_context_items); RNA_def_property_flag(prop, PROP_ENUM_FLAG); RNA_def_property_enum_funcs( -- cgit v1.2.3