diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2014-01-01 14:18:27 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2014-01-01 14:58:45 +0400 |
commit | 3c6b5b72a497dd5cdb05e3c35c4117a4e8f5daf2 (patch) | |
tree | 186bb193a5be5915a2e1083494ea46c860ee4f93 /source/blender/editors | |
parent | d8f4cb9b690be374ee91fe76f6f880b546aef72a (diff) |
Add a new "shortening process" for UI string drawing, which keeps both right and left parts
of the drawstr and replaces the middle by '...'
Rationnal:
It's usually easier to figure out what a troncated string means if you have both its start and end parts.
Details:
It currently affects all UI items (text fields, buttons, labels...).
Only exceptions are buttons inside menus, text fields & co being edited, and numbuttons/sliders.
Note that some static texts (like panels' titles or items in outliner) do not use usual UI items,
and just draw the whole text, using OpenGL to clip it. Will make another patch to fix this.
Reviewers: campbellbarton, brecht, carter2422, #user_interface
Reviewed by: brecht, carter2422
CC: billrey
Differential Revision: https://developer.blender.org/D114
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 477b7c4e8f3..bffb1b66afa 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -33,6 +33,7 @@ #include <string.h> #include <assert.h> +#include "MEM_guardedalloc.h" #include "DNA_screen_types.h" #include "DNA_userdef_types.h" @@ -968,6 +969,69 @@ static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, const rcti *rect) } /** + * Cut off the middle of the text to fit into the width of \a rect + */ +static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rect) +{ + const int border = UI_TEXT_CLIP_MARGIN + 1; + const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0); + float strwidth; + + /* need to set this first */ + uiStyleFontSet(fstyle); + + if (fstyle->kerning == 1) /* for BLF_width */ + BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + + but->ofs = 0; + strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr)); + + if (strwidth > okwidth) { + const char *sep = "..."; + const int sep_len = strlen(sep); + + const size_t max_len = sizeof(but->drawstr); + size_t l_end; + + const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sizeof(sep)); + const float parts_strwidth = ((float)okwidth - sep_strwidth) / 2.0f; + + if (parts_strwidth < (float)UI_DPI_ICON_SIZE) { + /* If we really have no place, only show start of string. */ + l_end = BLF_width_to_strlen(fstyle->uifont_id, but->drawstr, max_len, okwidth, &strwidth); + but->drawstr[l_end] = '\0'; + } + else { + size_t r_offset, r_len; + + l_end = BLF_width_to_strlen(fstyle->uifont_id, but->drawstr, max_len, parts_strwidth, &strwidth); + r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, but->drawstr, max_len, parts_strwidth, &strwidth); + r_len = strlen(but->drawstr + r_offset) + 1; /* +1 for the trailing '\0'... */ + + if (l_end + sep_len + r_len > max_len) { + /* Corner case, the str already takes all available mem, and the ellipsis chars would actually + * add more chars... + * Better to just trim one or two letters to the right in this case... + */ + l_end = BLF_width_to_strlen(fstyle->uifont_id, but->drawstr, max_len, okwidth, &strwidth); + but->drawstr[l_end] = '\0'; + } + else { + memmove(but->drawstr + l_end + sep_len, but->drawstr + r_offset, r_len); + memcpy(but->drawstr + l_end, sep, sep_len); + strwidth = BLF_width(fstyle->uifont_id, but->drawstr, max_len); + } + } + } + + but->strwidth = strwidth; + + if (fstyle->kerning == 1) { + BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + } +} + +/** * Cut off the text, taking into account the cursor location (text display while editing). */ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, const rcti *rect) @@ -1295,18 +1359,17 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB else if (ELEM(but->type, NUM, NUMSLI)) { ui_text_clip_right_label(fstyle, but, rect); } +#if 0 /* Special hack for non-embossed TEX buttons in uiList (we want them to behave as much as possible as labels). */ else if ((but->type == TEX) && (but->flag & UI_BUT_LIST_ITEM) && (but->dt & UI_EMBOSSN)) { but->ofs = 0; } - else if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) { - ui_text_clip_left(fstyle, but, rect); - } +#endif else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) { ui_text_clip_left(fstyle, but, rect); } else { - but->ofs = 0; + ui_text_clip_middle(fstyle, but, rect); } /* always draw text for textbutton cursor */ |