UI: support searching in menus #110855

Merged
Jacques Lucke merged 38 commits from JacquesLucke/blender:single-menu-search into main 2023-09-06 18:16:52 +02:00
3 changed files with 49 additions and 29 deletions
Showing only changes of commit 12319bd8cd - Show all commits

View File

@ -2409,7 +2409,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C);
void UI_but_func_operator_search(uiBut *but);
void uiTemplateOperatorSearch(uiLayout *layout);
void UI_but_func_menu_search(uiBut *but);
void UI_but_func_menu_search(uiBut *but, const char *single_menu_idname);
void uiTemplateMenuSearch(uiLayout *layout);
/**
JacquesLucke marked this conversation as resolved Outdated

Would make single_menu_idname optional (with a default value).

Would make `single_menu_idname` optional (with a default value).

View File

@ -426,8 +426,12 @@ static void menu_items_from_all_operators(bContext *C, MenuSearch_Data *data)
* - Look up predefined editor-menus.
* - Look up key-map items which call menus.
*/
static MenuSearch_Data *menu_items_from_ui_create(
bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas)
static MenuSearch_Data *menu_items_from_ui_create(bContext *C,
wmWindow *win,
ScrArea *area_init,
ARegion *region_init,
bool include_all_areas,
const char *single_menu_idname)
{
MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
/** Map (#MenuType to #MenuSearch_Parent) */
@ -597,11 +601,18 @@ static MenuSearch_Data *menu_items_from_ui_create(
region = region_init;
}
/* Populate menus from the editors,
* note that we could create a fake header, draw the header and extract the menus
* from the buttons, however this is quite involved and can be avoided as by convention
* each space-type has a single root-menu that headers use. */
{
if (single_menu_idname) {
if (MenuType *mt = WM_menutype_find(single_menu_idname, false)) {
if (BLI_gset_add(menu_tagged, mt)) {
BLI_linklist_prepend(&menu_stack, mt);
}
}
}
else {
/* Populate menus from the editors,
* note that we could create a fake header, draw the header and extract the menus
* from the buttons, however this is quite involved and can be avoided as by convention
* each space-type has a single root-menu that headers use. */
const char *idname_array[2] = {nullptr};
int idname_array_len = 0;
@ -649,6 +660,8 @@ static MenuSearch_Data *menu_items_from_ui_create(
SPACE_MENU_NOP(SPACE_SPREADSHEET);
}
}
#undef SPACE_MENU_MAP
#undef SPACE_MENU_NOP
for (int i = 0; i < idname_array_len; i++) {
MenuType *mt = WM_menutype_find(idname_array[i], false);
if (mt != nullptr) {
@ -659,8 +672,6 @@ static MenuSearch_Data *menu_items_from_ui_create(
}
}
}
#undef SPACE_MENU_MAP
#undef SPACE_MENU_NOP
bool has_keymap_menu_items = false;
@ -792,12 +803,15 @@ static MenuSearch_Data *menu_items_from_ui_create(
}
UI_block_free(nullptr, block);
/* Add key-map items as a second pass,
* so all menus are accessed from the header & top-bar before key shortcuts are expanded. */
if ((menu_stack == nullptr) && (has_keymap_menu_items == false)) {
has_keymap_menu_items = true;
menu_types_add_from_keymap_items(
C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged);
if (single_menu_idname == nullptr) {
/* Add key-map items as a second pass, so all menus are accessed from the header & top-bar
* before key shortcuts are expanded.
*/
if ((menu_stack == nullptr) && (has_keymap_menu_items == false)) {
has_keymap_menu_items = true;
menu_types_add_from_keymap_items(
C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged);
}
}
}
}
@ -904,7 +918,7 @@ static MenuSearch_Data *menu_items_from_ui_create(
* - Many operators need options to be set to give useful results, see: #74157.
* - User who really prefer to list all operators can use #WM_OT_search_operator.
*/
if (U.flag & USER_DEVELOPER_UI) {
if ((U.flag & USER_DEVELOPER_UI) && single_menu_idname == nullptr) {
menu_items_from_all_operators(C, data);
}
@ -1128,15 +1142,17 @@ static ARegion *ui_search_menu_create_tooltip(
/** \name Menu Search Template Public API
* \{ */
void UI_but_func_menu_search(uiBut *but)
void UI_but_func_menu_search(uiBut *but, const char *single_menu_idname)
{
bContext *C = (bContext *)but->block->evil_C;
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
/* When run from top-bar scan all areas in the current window. */
const bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR));
MenuSearch_Data *data = menu_items_from_ui_create(C, win, area, region, include_all_areas);
const bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR)) &&
!single_menu_idname;
MenuSearch_Data *data = menu_items_from_ui_create(
C, win, area, region, include_all_areas, single_menu_idname);
UI_but_func_search_set(but,
/* Generic callback. */
ui_searchbox_create_menu,
@ -1163,7 +1179,7 @@ void uiTemplateMenuSearch(uiLayout *layout)
but = uiDefSearchBut(
block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, "");
UI_but_func_menu_search(but);
UI_but_func_menu_search(but, nullptr);
}
/** \} */

View File

@ -1745,6 +1745,7 @@ enum SearchType {
struct SearchPopupInit_Data {
SearchType search_type;
int size[2];
std::string single_menu_idname;
};
static uiBlock *wm_block_search_menu(bContext *C, ARegion *region, void *userdata)
@ -1773,7 +1774,10 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *region, void *userdat
UI_but_func_operator_search(but);
}
else if (init_data->search_type == SEARCH_TYPE_MENU) {
UI_but_func_menu_search(but);
UI_but_func_menu_search(but, nullptr);
}
else if (init_data->search_type == SEARCH_TYPE_SINGLE_MENU) {
UI_but_func_menu_search(but, init_data->single_menu_idname.c_str());
}
else {
BLI_assert_unreachable();
@ -1836,7 +1840,7 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve
}
}
int search_type;
SearchType search_type;
if (STREQ(op->type->idname, "WM_OT_search_menu")) {
search_type = SEARCH_TYPE_MENU;
}
@ -1847,15 +1851,15 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve
search_type = SEARCH_TYPE_OPERATOR;
}
static SearchPopupInit_Data data{};
if (search_type == SEARCH_TYPE_SINGLE_MENU) {
char buffer[MAX_NAME + 1];
RNA_string_get(op->ptr, "menu_idname", buffer);
std::cout << buffer << "\n";
return OPERATOR_FINISHED;
char *buffer = RNA_string_get_alloc(op->ptr, "menu_idname", nullptr, 0, nullptr);
data.single_menu_idname = buffer;
MEM_freeN(buffer);
}
static SearchPopupInit_Data data{};
data.search_type = SearchType(search_type);
data.search_type = search_type;
data.size[0] = UI_searchbox_size_x() * 2;
data.size[1] = UI_searchbox_size_y();