diff options
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 16 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_region_search.c | 35 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 48 |
3 files changed, 84 insertions, 15 deletions
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 991e8aaf89a..f4e68ca3909 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -991,12 +991,26 @@ extern void ui_draw_but(const struct bContext *C, uiBut *but, rcti *rect); +/** + * Info about what the separator character separates, used to decide between different drawing + * styles. E.g. we never want a shortcut string to be clipped, but other hint strings can be + * clipped. + */ +typedef enum { + UI_MENU_ITEM_SEPARATOR_NONE, + /** Separator is used to indicate shortcut string of this item. Shortcut string will not get + * clipped. */ + UI_MENU_ITEM_SEPARATOR_SHORTCUT, + /** Separator is used to indicate some additional hint to display for this item. Hint string will + * get clipped before the normal text. */ + UI_MENU_ITEM_SEPARATOR_HINT, +} uiMenuItemSeparatorType; void ui_draw_menu_item(const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, - bool use_sep, + uiMenuItemSeparatorType separator_type, int *r_xmax); void ui_draw_preview_item( const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index 7a665909c76..816162e9aa2 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -610,7 +610,15 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) char *name = data->items.names[a]; int icon = data->items.icons[a]; char *name_sep_test = NULL; - const bool use_sep_char = data->use_sep || (state & UI_BUT_HAS_SEP_CHAR); + + uiMenuItemSeparatorType separator_type = UI_MENU_ITEM_SEPARATOR_NONE; + if (data->use_sep) { + separator_type = UI_MENU_ITEM_SEPARATOR_SHORTCUT; + } + /* Only set for displaying additional hint (e.g. library name of a linked data-block). */ + else if (state & UI_BUT_HAS_SEP_CHAR) { + separator_type = UI_MENU_ITEM_SEPARATOR_HINT; + } ui_searchbox_butrect(&rect, data, a); @@ -623,7 +631,7 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) } /* Simple menu item. */ - ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, use_sep_char, NULL); + ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, separator_type, NULL); } else { /* Split menu item, faded text before the separator. */ @@ -637,8 +645,13 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) 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); + ui_draw_menu_item(&data->fstyle, + &rect, + name, + 0, + state | UI_BUT_INACTIVE, + UI_MENU_ITEM_SEPARATOR_NONE, + &name_width); *name_sep = name_sep_prev; rect.xmin += name_width; rect.xmin += UI_UNIT_X / 4; @@ -650,7 +663,7 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) /* The previous menu item draws the active selection. */ ui_draw_menu_item( - &data->fstyle, &rect, name_sep, icon, state & ~UI_ACTIVE, use_sep_char, NULL); + &data->fstyle, &rect, name_sep, icon, state & ~UI_ACTIVE, separator_type, NULL); } } /* indicate more */ @@ -943,10 +956,16 @@ 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, + UI_MENU_ITEM_SEPARATOR_NONE, + NULL); + ui_draw_menu_item(&data->fstyle, + &rect_post, + data->items.names[a], + 0, + state, + data->use_sep ? UI_MENU_ITEM_SEPARATOR_SHORTCUT : + UI_MENU_ITEM_SEPARATOR_NONE, NULL); - ui_draw_menu_item( - &data->fstyle, &rect_post, data->items.names[a], 0, state, data->use_sep, NULL); } } /* indicate more */ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index a99f05730bb..c0c34b0a93d 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -5221,11 +5221,13 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, const char *name, int iconid, int state, - bool use_sep, + uiMenuItemSeparatorType separator_type, int *r_xmax) { uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); const rcti _rect = *rect; + int max_hint_width = INT_MAX; + int padding = 0.25f * UI_UNIT_X; char *cpoin = NULL; wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED); @@ -5234,13 +5236,13 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, UI_fontstyle_set(fstyle); /* text location offset */ - rect->xmin += 0.25f * UI_UNIT_X; + rect->xmin += padding; if (iconid) { rect->xmin += UI_DPI_ICON_SIZE; } /* cut string in 2 parts? */ - if (use_sep) { + if (separator_type != UI_MENU_ITEM_SEPARATOR_NONE) { cpoin = strrchr(name, UI_SEP_CHAR); if (cpoin) { *cpoin = 0; @@ -5253,7 +5255,30 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); } - rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_DPI_ICON_SIZE; + if (separator_type == UI_MENU_ITEM_SEPARATOR_SHORTCUT) { + /* Shrink rect to exclude the shortcut string. */ + rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_DPI_ICON_SIZE; + } + else if (separator_type == UI_MENU_ITEM_SEPARATOR_HINT) { + /* Deterimine max-width for the hint string to leave the name string un-clipped (if there's + * enough space to display it). */ + + const int available_width = BLI_rcti_size_x(rect) - padding; + const int name_width = BLF_width(fstyle->uifont_id, name, INT_MAX); + const int hint_width = BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + padding; + + if ((name_width + hint_width) > available_width) { + /* Clipping width for hint string. */ + max_hint_width = available_width * 0.40f; + /* Clipping xmax for clipping of item name. */ + rect->xmax = (hint_width < max_hint_width) ? + (rect->xmax - hint_width) : + (rect->xmin + (available_width - max_hint_width)); + } + } + else { + BLI_assert(!"Unknwon menu item separator type"); + } if (fstyle->kerning == 1) { BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); @@ -5308,15 +5333,26 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, } /* part text right aligned */ - if (use_sep) { + if (separator_type != UI_MENU_ITEM_SEPARATOR_NONE) { if (cpoin) { /* Set inactive state for grayed out text. */ wt->state(wt, state | UI_BUT_INACTIVE, 0, UI_EMBOSS_UNDEFINED); + char hint_drawstr[UI_MAX_DRAW_STR]; + { + const size_t max_len = sizeof(hint_drawstr); + const float minwidth = (float)(UI_DPI_ICON_SIZE); + + BLI_strncpy(hint_drawstr, cpoin + 1, sizeof(hint_drawstr)); + if (hint_drawstr[0] && (max_hint_width < INT_MAX)) { + UI_text_clip_middle_ex(fstyle, hint_drawstr, max_hint_width, minwidth, max_len, '\0'); + } + } + rect->xmax = _rect.xmax - 5; UI_fontstyle_draw(fstyle, rect, - cpoin + 1, + hint_drawstr, wt->wcol.text, &(struct uiFontStyleDraw_Params){ .align = UI_STYLE_TEXT_RIGHT, |