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/interface/interface_layout.c')
-rw-r--r--source/blender/editors/interface/interface_layout.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 45085288264..4b767b530f0 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -86,6 +86,13 @@ typedef struct uiLayoutRoot {
int type;
int opcontext;
+ /**
+ * If true, the root will be removed as part of the property search process.
+ * Necessary for cases like searching the contents of closed panels, where the
+ * block-level tag isn't enough because there might be buttons in the header.
+ */
+ bool search_only;
+
int emw, emh;
int padding;
@@ -5097,6 +5104,193 @@ int uiLayoutGetEmboss(uiLayout *layout)
return layout->emboss;
}
+void uiLayoutRootSetSearchOnly(uiLayout *layout, bool search_only)
+{
+ layout->root->search_only = search_only;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Block Layout Search Filtering
+ * \{ */
+
+// #define PROPERTY_SEARCH_USE_TOOLTIPS
+#define PROPERTY_SEARCH_USE_PANEL_LABELS
+
+static void layout_free_and_hide_buttons(uiLayout *layout)
+{
+ LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
+ if (item->type == ITEM_BUTTON) {
+ uiButtonItem *button_item = (uiButtonItem *)item;
+ BLI_assert(button_item->but != NULL);
+ button_item->but->flag |= UI_HIDDEN;
+ MEM_freeN(item);
+ }
+ else {
+ layout_free_and_hide_buttons((uiLayout *)item);
+ }
+ }
+
+ MEM_freeN(layout);
+}
+
+/**
+ * Returns true if a button or the data / operator it represents matches the search filter.
+ *
+ * \note It's important to do the shorter checks first for performance.
+ */
+static bool button_matches_search_filter(uiBut *but, const char *search_filter)
+{
+ if (BLI_strcasestr(but->str, search_filter)) {
+ return true;
+ }
+
+ if (but->optype != NULL) {
+ if (BLI_strcasestr(but->optype->name, search_filter)) {
+ return true;
+ }
+ }
+
+ if (but->rnaprop != NULL) {
+ if (BLI_strcasestr(RNA_property_ui_name(but->rnaprop), search_filter)) {
+ return true;
+ }
+#ifdef PROPERTY_SEARCH_USE_TOOLTIPS
+ if (BLI_strcasestr(RNA_property_description(but->rnaprop), search_filter)) {
+ return true;
+ }
+#endif
+
+ /* Search through labels of enum property items if they are in a dropdown menu.
+ * Unfortunately we have no context here so we cannot search through RNA enums
+ * with dynamic entries (or "itemf" functions) which require context. */
+ if (but->type == UI_BTYPE_MENU) {
+ PointerRNA *ptr = &but->rnapoin;
+ PropertyRNA *enum_prop = but->rnaprop;
+
+ int items_len;
+ const EnumPropertyItem *enum_items = NULL;
+ bool free;
+ RNA_property_enum_items(NULL, ptr, enum_prop, &enum_items, &items_len, &free);
+
+ if (enum_items != NULL) {
+ for (int i = 0; i < items_len; i++) {
+ if (BLI_strcasestr(enum_items[i].name, search_filter)) {
+ return true;
+ }
+ }
+ if (free) {
+ MEM_freeN((void *)enum_items);
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Tag all buttons with whether they matched the search filter or not.
+ */
+static bool block_search_filter_tag_buttons(uiBlock *block)
+{
+ bool has_result = false;
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ /* First match regular buttons. */
+ if (!ELEM(but->type, UI_BTYPE_LABEL) &&
+ button_matches_search_filter(but, block->search_filter)) {
+ has_result = true;
+ but->flag |= UI_SEARCH_FILTER_MATCHES;
+ }
+ /* Then match their labels. */
+ if (but->label_but != NULL &&
+ button_matches_search_filter(but->label_but, block->search_filter)) {
+ has_result = true;
+ but->flag |= UI_SEARCH_FILTER_MATCHES;
+ }
+ }
+
+ /* Remove filter from labels and decorators that correspond to un-filtered buttons. */
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ if (but->flag & UI_SEARCH_FILTER_MATCHES) {
+ if (but->label_but != NULL) {
+ but->label_but->flag |= UI_SEARCH_FILTER_MATCHES;
+ }
+ if (but->decorator_but != NULL) {
+ but->decorator_but->flag |= UI_SEARCH_FILTER_MATCHES;
+ }
+ }
+ }
+
+ return has_result;
+}
+
+static bool block_search(uiBlock *block)
+{
+ /* Only continue if the block has the search filter set. */
+ if (!(block->search_filter && block->search_filter[0])) {
+ return false;
+ }
+
+ /* Also search based on panel labels. */
+ bool panel_label_matches = false;
+#ifdef PROPERTY_SEARCH_USE_PANEL_LABELS
+ if ((block->panel != NULL) && (block->panel->type != NULL)) {
+ if (BLI_strcasestr(block->panel->type->label, block->search_filter)) {
+ panel_label_matches = true;
+ }
+ }
+#endif
+
+ /* Apply search filter. */
+ bool has_result;
+ if (!panel_label_matches) {
+ has_result = block_search_filter_tag_buttons(block);
+ }
+ else {
+ has_result = true;
+ }
+
+ /* Remove search only layout roots before the next step. */
+ LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
+ if (root->search_only) {
+ layout_free_and_hide_buttons(root->layout);
+ BLI_remlink(&block->layouts, root);
+ MEM_freeN(root);
+ }
+ }
+
+ /* Set empty flags. */
+ if (UI_block_is_search_only(block)) {
+ /* Make sure all of the block's buttons are hidden. They might not have
+ * been hidden if a layout wasn't searched. */
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ but->flag |= UI_HIDDEN;
+ }
+ }
+
+ if (block->panel != NULL) {
+ ui_panel_set_search_filter_match(block->panel, has_result);
+ }
+
+ return panel_label_matches;
+}
+
+static void block_search_deactive_buttons(uiBlock *block)
+{
+ /* Only continue if the block has the search filter set. */
+ if (!(block->search_filter && block->search_filter[0])) {
+ return;
+ }
+
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ if (!(but->flag & UI_SEARCH_FILTER_MATCHES)) {
+ but->flag |= UI_BUT_INACTIVE;
+ }
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -5524,6 +5718,8 @@ void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
block->curlayout = NULL;
+ const bool search_disabled = block_search(block);
+
LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) {
ui_layout_add_padding_button(root);
@@ -5532,6 +5728,10 @@ void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
ui_layout_free(root->layout);
}
+ if (!search_disabled) {
+ block_search_deactive_buttons(block);
+ }
+
BLI_freelistN(&block->layouts);
/* XXX silly trick, interface_templates.c doesn't get linked