UI: improve menu search with dimmed menu prefix
- Show dimmed text for the menu entries leading up to the menu item. - Show icons between the menu text and menu item. - Use unicode right pointing triangle instead of arrow.
This commit is contained in:
parent
571646ebc1
commit
e6d9d5dcc1
|
@ -49,6 +49,7 @@ struct PanelType;
|
|||
struct PointerRNA;
|
||||
struct PropertyRNA;
|
||||
struct ReportList;
|
||||
struct ResultBLF;
|
||||
struct ScrArea;
|
||||
struct bContext;
|
||||
struct bContextStore;
|
||||
|
@ -1576,6 +1577,7 @@ void UI_but_func_search_set(uiBut *but,
|
|||
void *arg,
|
||||
uiButSearchArgFreeFunc search_arg_free_func,
|
||||
uiButHandleFunc bfunc,
|
||||
const char *search_sep_string,
|
||||
void *active);
|
||||
/* height in pixels, it's using hardcoded values still */
|
||||
int UI_searchbox_size_y(void);
|
||||
|
@ -2416,7 +2418,8 @@ void UI_fontstyle_draw_ex(const struct uiFontStyle *fs,
|
|||
const struct uiFontStyleDraw_Params *fs_params,
|
||||
size_t len,
|
||||
int *r_xofs,
|
||||
int *r_yofs);
|
||||
int *r_yofs,
|
||||
struct ResultBLF *r_info);
|
||||
void UI_fontstyle_draw(const struct uiFontStyle *fs,
|
||||
const struct rcti *rect,
|
||||
const char *str,
|
||||
|
|
|
@ -6332,7 +6332,9 @@ uiBut *uiDefSearchBut(uiBlock *block,
|
|||
/**
|
||||
* \param search_func, bfunc: both get it as \a arg.
|
||||
* \param arg: user value,
|
||||
* \param active: when set, button opens with this item visible and selected.
|
||||
* \param active: when set, button opens with this item visible and selected.
|
||||
* \param separator_string: when not NULL, this string is used as a separator,
|
||||
* showing the icon and highlighted text after the last instance of this string.
|
||||
*/
|
||||
void UI_but_func_search_set(uiBut *but,
|
||||
uiButSearchCreateFunc search_create_func,
|
||||
|
@ -6340,6 +6342,7 @@ void UI_but_func_search_set(uiBut *but,
|
|||
void *arg,
|
||||
uiButSearchArgFreeFunc search_arg_free_func,
|
||||
uiButHandleFunc bfunc,
|
||||
const char *search_sep_string,
|
||||
void *active)
|
||||
{
|
||||
/* needed since callers don't have access to internal functions
|
||||
|
@ -6358,6 +6361,7 @@ void UI_but_func_search_set(uiBut *but,
|
|||
|
||||
but->search_arg = arg;
|
||||
but->search_arg_free_func = search_arg_free_func;
|
||||
but->search_sep_string = search_sep_string;
|
||||
|
||||
if (bfunc) {
|
||||
#ifdef DEBUG
|
||||
|
@ -6467,6 +6471,7 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
|
|||
but,
|
||||
NULL,
|
||||
operator_enum_call_cb,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
but->optype = ot;
|
||||
|
|
|
@ -205,6 +205,7 @@ struct uiBut {
|
|||
uiButSearchFunc search_func;
|
||||
void *search_arg;
|
||||
uiButSearchArgFreeFunc search_arg_free_func;
|
||||
const char *search_sep_string;
|
||||
|
||||
uiButHandleRenameFunc rename_func;
|
||||
void *rename_arg1;
|
||||
|
@ -851,7 +852,8 @@ void ui_draw_menu_item(const struct uiFontStyle *fstyle,
|
|||
const char *name,
|
||||
int iconid,
|
||||
int state,
|
||||
bool use_sep);
|
||||
bool use_sep,
|
||||
int *r_name_width);
|
||||
void ui_draw_preview_item(
|
||||
const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
|
||||
|
||||
|
|
|
@ -2633,6 +2633,7 @@ void ui_but_add_search(
|
|||
coll_search,
|
||||
ui_rna_collection_search_free_cb,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
else if (but->type == UI_BTYPE_SEARCH_MENU) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
|
@ -89,9 +90,14 @@ typedef struct uiSearchboxData {
|
|||
bool noback;
|
||||
/** draw thumbnail previews, rather than list */
|
||||
bool preview;
|
||||
/** use the UI_SEP_CHAR char for splitting shortcuts (good for operators, bad for data) */
|
||||
/** Use the #UI_SEP_CHAR char for splitting shortcuts (good for operators, bad for data). */
|
||||
bool use_sep;
|
||||
int prv_rows, prv_cols;
|
||||
/**
|
||||
* Show the active icon and text after the last instance of this string.
|
||||
* Used so we can show leading text to menu items less prominently (not related to 'use_sep').
|
||||
*/
|
||||
const char *sep_string;
|
||||
} uiSearchboxData;
|
||||
|
||||
#define SEARCH_ITEMS 10
|
||||
|
@ -465,19 +471,50 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region)
|
|||
}
|
||||
}
|
||||
else {
|
||||
const int search_sep_len = data->sep_string ? strlen(data->sep_string) : 0;
|
||||
/* draw items */
|
||||
for (a = 0; a < data->items.totitem; a++) {
|
||||
const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
|
||||
char *name = data->items.names[a];
|
||||
int icon = data->items.icons[a];
|
||||
char *name_sep_test = NULL;
|
||||
|
||||
ui_searchbox_butrect(&rect, data, a);
|
||||
|
||||
/* widget itself */
|
||||
ui_draw_menu_item(&data->fstyle,
|
||||
&rect,
|
||||
data->items.names[a],
|
||||
data->items.icons[a],
|
||||
state,
|
||||
data->use_sep);
|
||||
if ((search_sep_len == 0) ||
|
||||
!(name_sep_test = strstr(data->items.names[a], data->sep_string))) {
|
||||
|
||||
/* Simple menu item. */
|
||||
ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, data->use_sep, NULL);
|
||||
}
|
||||
else {
|
||||
/* Split menu item, faded text before the separator. */
|
||||
char *name_sep = NULL;
|
||||
do {
|
||||
name_sep = name_sep_test;
|
||||
name_sep_test = strstr(name_sep + search_sep_len, data->sep_string);
|
||||
} while (name_sep_test != NULL);
|
||||
|
||||
name_sep += search_sep_len;
|
||||
const char name_sep_prev = *name_sep;
|
||||
*name_sep = '\0';
|
||||
int name_width = 0;
|
||||
ui_draw_menu_item(
|
||||
&data->fstyle, &rect, name, 0, state | UI_BUT_INACTIVE, false, &name_width);
|
||||
*name_sep = name_sep_prev;
|
||||
rect.xmin += name_width;
|
||||
rect.xmin += UI_UNIT_X / 4;
|
||||
|
||||
if (icon == ICON_BLANK1) {
|
||||
icon = ICON_NONE;
|
||||
rect.xmin -= UI_DPI_ICON_SIZE / 4;
|
||||
}
|
||||
|
||||
/* The previous menu item draws the active selection. */
|
||||
ui_draw_menu_item(
|
||||
&data->fstyle, &rect, name_sep, icon, state & ~UI_ACTIVE, data->use_sep, NULL);
|
||||
}
|
||||
}
|
||||
/* indicate more */
|
||||
if (data->items.more) {
|
||||
|
@ -566,6 +603,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
|
|||
if (but->optype != NULL || (but->drawflag & UI_BUT_HAS_SHORTCUT) != 0) {
|
||||
data->use_sep = true;
|
||||
}
|
||||
data->sep_string = but->search_sep_string;
|
||||
|
||||
/* compute position */
|
||||
if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
|
||||
|
@ -762,9 +800,10 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
|
|||
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, text_pre),
|
||||
data->items.icons[a],
|
||||
state,
|
||||
false);
|
||||
false,
|
||||
NULL);
|
||||
ui_draw_menu_item(
|
||||
&data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep);
|
||||
&data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep, NULL);
|
||||
}
|
||||
}
|
||||
/* indicate more */
|
||||
|
|
|
@ -148,7 +148,8 @@ void UI_fontstyle_draw_ex(const uiFontStyle *fs,
|
|||
const struct uiFontStyleDraw_Params *fs_params,
|
||||
size_t len,
|
||||
int *r_xofs,
|
||||
int *r_yofs)
|
||||
int *r_yofs,
|
||||
struct ResultBLF *r_info)
|
||||
{
|
||||
int xofs = 0, yofs;
|
||||
int font_flag = BLF_CLIPPING;
|
||||
|
@ -196,7 +197,7 @@ void UI_fontstyle_draw_ex(const uiFontStyle *fs,
|
|||
BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
|
||||
BLF_color4ubv(fs->uifont_id, col);
|
||||
|
||||
BLF_draw(fs->uifont_id, str, len);
|
||||
BLF_draw_ex(fs->uifont_id, str, len, r_info);
|
||||
|
||||
BLF_disable(fs->uifont_id, font_flag);
|
||||
|
||||
|
@ -212,7 +213,7 @@ void UI_fontstyle_draw(const uiFontStyle *fs,
|
|||
{
|
||||
int xofs, yofs;
|
||||
|
||||
UI_fontstyle_draw_ex(fs, rect, str, col, fs_params, BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
|
||||
UI_fontstyle_draw_ex(fs, rect, str, col, fs_params, BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs, NULL);
|
||||
}
|
||||
|
||||
/* drawn same as above, but at 90 degree angle */
|
||||
|
|
|
@ -287,8 +287,14 @@ static uiBlock *template_common_search_menu(const bContext *C,
|
|||
0,
|
||||
"");
|
||||
}
|
||||
UI_but_func_search_set(
|
||||
but, ui_searchbox_create_generic, search_func, search_arg, NULL, handle_func, active_item);
|
||||
UI_but_func_search_set(but,
|
||||
ui_searchbox_create_generic,
|
||||
search_func,
|
||||
search_arg,
|
||||
NULL,
|
||||
handle_func,
|
||||
NULL,
|
||||
active_item);
|
||||
|
||||
UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
|
||||
UI_block_direction_set(block, UI_DIR_DOWN);
|
||||
|
@ -6660,8 +6666,14 @@ static void operator_search_cb(const bContext *C,
|
|||
|
||||
void UI_but_func_operator_search(uiBut *but)
|
||||
{
|
||||
UI_but_func_search_set(
|
||||
but, ui_searchbox_create_operator, operator_search_cb, NULL, false, operator_call_cb, NULL);
|
||||
UI_but_func_search_set(but,
|
||||
ui_searchbox_create_operator,
|
||||
operator_search_cb,
|
||||
NULL,
|
||||
false,
|
||||
operator_call_cb,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void uiTemplateOperatorSearch(uiLayout *layout)
|
||||
|
@ -6684,6 +6696,9 @@ void uiTemplateOperatorSearch(uiLayout *layout)
|
|||
/** \name Menu Search Template
|
||||
* \{ */
|
||||
|
||||
/* Unicode arrow. */
|
||||
#define MENU_SEP "\xe2\x96\xb6"
|
||||
|
||||
struct MenuSearch_Parent {
|
||||
struct MenuSearch_Parent *parent;
|
||||
MenuType *parent_mt;
|
||||
|
@ -7127,9 +7142,6 @@ static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C,
|
|||
/* NOTE: currently this builds the full path for each menu item,
|
||||
* that could be moved into the parent menu. */
|
||||
|
||||
/* Unicode arrow. */
|
||||
#define MENU_SEP "\xe2\x86\x92"
|
||||
|
||||
/* Set names as full paths. */
|
||||
LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) {
|
||||
if (item->menu_parent != NULL) {
|
||||
|
@ -7176,7 +7188,6 @@ static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C,
|
|||
BLI_dynstr_clear(dyn_str);
|
||||
}
|
||||
BLI_dynstr_free(dyn_str);
|
||||
#undef MENU_SEP
|
||||
|
||||
/* Finally sort menu items.
|
||||
*
|
||||
|
@ -7309,6 +7320,7 @@ void UI_but_func_menu_search(uiBut *but)
|
|||
data,
|
||||
menu_items_from_ui_destroy,
|
||||
menu_call_fn,
|
||||
MENU_SEP,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
@ -7326,6 +7338,8 @@ void uiTemplateMenuSearch(uiLayout *layout)
|
|||
UI_but_func_menu_search(but);
|
||||
}
|
||||
|
||||
#undef MENU_SEP
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -2315,7 +2315,8 @@ static void widget_draw_text(const uiFontStyle *fstyle,
|
|||
},
|
||||
drawlen,
|
||||
&font_xofs,
|
||||
&font_yofs);
|
||||
&font_yofs,
|
||||
NULL);
|
||||
|
||||
if (but->menu_key != '\0') {
|
||||
char fixedbuf[128];
|
||||
|
@ -5267,8 +5268,13 @@ void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(bl
|
|||
|
||||
/* helper call to draw a menu item without button */
|
||||
/* state: UI_ACTIVE or 0 */
|
||||
void ui_draw_menu_item(
|
||||
const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep)
|
||||
void ui_draw_menu_item(const uiFontStyle *fstyle,
|
||||
rcti *rect,
|
||||
const char *name,
|
||||
int iconid,
|
||||
int state,
|
||||
bool use_sep,
|
||||
int *r_name_width)
|
||||
{
|
||||
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
|
||||
rcti _rect = *rect;
|
||||
|
@ -5318,13 +5324,22 @@ void ui_draw_menu_item(
|
|||
UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
|
||||
}
|
||||
|
||||
UI_fontstyle_draw(fstyle,
|
||||
rect,
|
||||
drawstr,
|
||||
wt->wcol.text,
|
||||
&(struct uiFontStyleDraw_Params){
|
||||
.align = UI_STYLE_TEXT_LEFT,
|
||||
});
|
||||
int xofs = 0, yofs = 0;
|
||||
struct ResultBLF info;
|
||||
UI_fontstyle_draw_ex(fstyle,
|
||||
rect,
|
||||
drawstr,
|
||||
wt->wcol.text,
|
||||
&(struct uiFontStyleDraw_Params){
|
||||
.align = UI_STYLE_TEXT_LEFT,
|
||||
},
|
||||
BLF_DRAW_STR_DUMMY_MAX,
|
||||
&xofs,
|
||||
&yofs,
|
||||
&info);
|
||||
if (r_name_width != NULL) {
|
||||
*r_name_width = xofs + info.width;
|
||||
}
|
||||
}
|
||||
|
||||
/* part text right aligned */
|
||||
|
|
|
@ -1179,7 +1179,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_op)
|
|||
0,
|
||||
0,
|
||||
"");
|
||||
UI_but_func_search_set(but, NULL, node_find_cb, op->type, NULL, node_find_call_cb, NULL);
|
||||
UI_but_func_search_set(but, NULL, node_find_cb, op->type, NULL, node_find_call_cb, NULL, NULL);
|
||||
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
|
||||
|
||||
/* fake button, it holds space for search items */
|
||||
|
|
|
@ -590,7 +590,7 @@ static uiBlock *merged_element_search_menu(bContext *C, ARegion *region, void *d
|
|||
but = uiDefSearchBut(
|
||||
block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, menu_width, UI_UNIT_Y, 0, 0, "");
|
||||
UI_but_func_search_set(
|
||||
but, NULL, merged_element_search_cb, data, NULL, merged_element_search_call_cb, NULL);
|
||||
but, NULL, merged_element_search_cb, data, NULL, merged_element_search_call_cb, NULL, NULL);
|
||||
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
|
||||
|
||||
/* Fake button to hold space for search items */
|
||||
|
|
Loading…
Reference in New Issue