diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-05-07 16:16:22 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-05-07 16:38:44 +0300 |
commit | 82704ac3edf0e37d9eea2860bc565bcf521ae593 (patch) | |
tree | f5a1f73cca5b0399f92247fac030163213cbd79a /source/blender/editors/interface/interface_template_search_menu.c | |
parent | daf10d17f46c933341be12bc9a9baf359d3280f7 (diff) |
UI: support context menu in menu search popup
Diffstat (limited to 'source/blender/editors/interface/interface_template_search_menu.c')
-rw-r--r-- | source/blender/editors/interface/interface_template_search_menu.c | 104 |
1 files changed, 103 insertions, 1 deletions
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 1e8d32abf67..8bd61ccd038 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -137,6 +137,12 @@ struct MenuSearch_Data { ListBase items; /** Use for all small allocations. */ MemArena *memarena; + + /** Use for context menu, to fake a button to create a context menu. */ + struct { + uiBut but; + uiBlock block; + } context_menu_data; }; static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v) @@ -208,7 +214,8 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d /* Handle shared settings. */ item->drawstr = strdup_memarena(memarena, but->drawstr); item->icon = ui_but_icon(but); - item->state = (but->flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT)); + item->state = (but->flag & + (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)); item->mt = mt; item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : NULL; @@ -222,6 +229,51 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d } /** + * Populate a fake button from a menu item (use for context menu). + */ +static bool menu_items_to_ui_button(struct MenuSearch_Item *item, uiBut *but) +{ + bool changed = false; + switch (item->type) { + case MENU_SEARCH_TYPE_OP: { + but->optype = item->op.type; + but->opcontext = item->op.opcontext; + but->context = item->op.context; + but->opptr = item->op.opptr; + changed = true; + break; + } + case MENU_SEARCH_TYPE_RNA: { + const int prop_type = RNA_property_type(item->rna.prop); + + but->rnapoin = item->rna.ptr; + but->rnaprop = item->rna.prop; + but->rnaindex = item->rna.index; + + if (prop_type == PROP_ENUM) { + but->hardmax = item->rna.enum_value; + } + changed = true; + break; + } + } + + if (changed) { + STRNCPY(but->drawstr, item->drawstr); + char *drawstr_sep = (item->state & UI_BUT_HAS_SEP_CHAR) ? strrchr(but->drawstr, UI_SEP_CHAR) : + NULL; + if (drawstr_sep) { + *drawstr_sep = '\0'; + } + + but->icon = item->icon; + but->str = but->strdata; + } + + return changed; +} + +/** * Populate \a menu_stack with menus from inspecting active key-maps for this context. */ static void menu_types_add_from_keymap_items(bContext *C, @@ -318,6 +370,7 @@ static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *d SNPRINTF(uiname, "%s " MENU_SEP "%s", idname_as_py, ot_ui_name); item->drawwstr_full = strdup_memarena(memarena, uiname); + item->drawstr = ot_ui_name; item->wm_context = NULL; @@ -896,6 +949,53 @@ static void menu_search_cb(const bContext *UNUSED(C), /** \} */ /* -------------------------------------------------------------------- */ +/** \name Context Menu + * + * This uses a fake button to create a context menu, + * if this ever causes hard to solve bugs we may need to create + * a separate context menu just for the search, however this is fairly involved. + * \{ */ + +static bool menu_search_context_menu_fn(struct bContext *C, + void *arg, + void *active, + const struct wmEvent *UNUSED(event)) +{ + struct MenuSearch_Data *data = arg; + struct MenuSearch_Item *item = active; + bool has_menu = false; + + memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data)); + uiBut *but = &data->context_menu_data.but; + uiBlock *block = &data->context_menu_data.block; + + but->block = block; + + if (menu_items_to_ui_button(item, but)) { + ScrArea *area_prev = CTX_wm_area(C); + ARegion *region_prev = CTX_wm_region(C); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, item->wm_context->area); + CTX_wm_region_set(C, item->wm_context->region); + } + + if (ui_popup_context_menu_for_button(C, but)) { + has_menu = true; + } + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, region_prev); + } + } + + return has_menu; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Menu Search Template Public API * \{ */ @@ -916,6 +1016,8 @@ void UI_but_func_menu_search(uiBut *but) menu_items_from_ui_destroy, menu_call_fn, NULL); + + UI_but_func_search_set_context_menu(but, menu_search_context_menu_fn); UI_but_func_search_set_sep_string(but, MENU_SEP); } |