Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/screen/area.c')
-rw-r--r--source/blender/editors/screen/area.c146
1 files changed, 145 insertions, 1 deletions
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 6fa9d203bba..fd94eea337f 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -48,6 +48,7 @@
#include "WM_toolsystem.h"
#include "WM_types.h"
+#include "ED_buttons.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
@@ -765,7 +766,7 @@ const char *ED_area_region_search_filter_get(const ScrArea *area, const ARegion
if (area->spacetype == SPACE_PROPERTIES) {
SpaceProperties *sbuts = area->spacedata.first;
if (region->regiontype == RGN_TYPE_WINDOW) {
- return sbuts->runtime->search_string;
+ return ED_buttons_search_string_get(sbuts);
}
}
@@ -3074,6 +3075,149 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
WM_event_add_keymap_handler(&region->handlers, keymap);
}
+/**
+ * Check whether any of the buttons generated by the \a panel_type's
+ * layout callbacks match the \a search_filter.
+ *
+ * \param panel: If non-NULL, use this instead of adding a new panel for the \a panel_type.
+ */
+static bool panel_property_search(const bContext *C,
+ ARegion *region,
+ const uiStyle *style,
+ Panel *panel,
+ PanelType *panel_type,
+ const char *search_filter)
+{
+ uiBlock *block = UI_block_begin(C, region, panel_type->idname, UI_EMBOSS);
+ UI_block_set_search_only(block, true);
+
+ if (panel == NULL) {
+ bool open; /* Dummy variable. */
+ panel = UI_panel_begin(region, &region->panels, block, panel_type, panel, &open);
+ }
+
+ /* 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);
+ panel_type->draw_header_preset(C, panel);
+ }
+ if (panel->type->draw_header != NULL) {
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style);
+ panel_type->draw_header(C, panel);
+ }
+ if (LIKELY(panel->type->draw != NULL)) {
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 0, 0, 0, style);
+ panel_type->draw(C, panel);
+ }
+
+ UI_block_layout_free(block);
+
+ /* 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, search_filter)) {
+ return true;
+ }
+
+ LISTBASE_FOREACH (LinkData *, link, &panel_type->children) {
+ PanelType *panel_type_child = link->data;
+ if (!panel_type_child->poll || panel_type_child->poll(C, panel_type_child)) {
+ /* 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;
+ }
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Build the same panel list as #ED_region_panels_layout_ex and checks whether any
+ * of the panels contain a search result based on the area / region's search filter.
+ */
+bool ED_region_property_search(const bContext *C,
+ ARegion *region,
+ ListBase *paneltypes,
+ const char *contexts[],
+ const char *category_override)
+{
+ 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_region_search_filter_get(area, region);
+
+ LinkNode *panel_types_stack = NULL;
+ LISTBASE_FOREACH_BACKWARD (PanelType *, pt, paneltypes) {
+ if (panel_add_check(C, workspace, contexts, category_override, pt)) {
+ BLI_linklist_prepend_alloca(&panel_types_stack, pt);
+ }
+ }
+
+ const char *category = NULL;
+ bool use_category_tabs = (category_override == NULL) && region_uses_category_tabs(area, region);
+ if (use_category_tabs) {
+ 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;
+ }
+
+ if (use_category_tabs) {
+ if (panel_type->category[0] && !STREQ(category, panel_type->category)) {
+ continue;
+ }
+ }
+
+ /* 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, &region->panels) {
+ /* Note that these checks are duplicated from #ED_region_panels_layout_ex. */
+ if (panel->type == NULL || !(panel->type->flag & PNL_INSTANCED)) {
+ continue;
+ }
+ if (use_category_tabs) {
+ if (panel->type->category[0] && !STREQ(category, panel->type->category)) {
+ continue;
+ }
+ }
+
+ has_result = panel_property_search(C, region, style, panel, panel->type, search_filter);
+ if (has_result) {
+ break;
+ }
+ }
+ }
+
+ /* Free the panels and blocks, as they are only used for search. */
+ UI_blocklist_free(C, &region->uiblocks);
+ UI_panels_free_instanced(C, region);
+ BKE_area_region_panels_free(&region->panels);
+
+ return has_result;
+}
+
void ED_region_header_layout(const bContext *C, ARegion *region)
{
const uiStyle *style = UI_style_get_dpi();