diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2014-08-17 00:21:10 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2014-08-17 00:36:23 +0400 |
commit | 1ad9987af14e4f5c8fbe168df2fbe39c058732e5 (patch) | |
tree | d1f686fb5c0251f330f64b2831782a30a5860806 /source/blender/editors/interface/interface_widgets.c | |
parent | c47a01da11b42df849ba0881c577d020c8eb0b44 (diff) |
Fix filenames in splashscreen.
For some reason, labels of buttons in popups/menus were clipped left.
Removed that function (was the only place were it was used), clipping text
by its left is really bad for its understanding!
Instead, extended clip_middle code so that it optionnally preserves a right piece of
the given string (like the shortcut part of a menu label). Think that's what makes
more sense here (note that most menus adapt themselves to their longest item,
we do not have much fixed-width ones, anyway).
Also tweaked a bit clip_middle logic, so that left part always have at least ten chars
(in addition to already existing 'min width' checks).
Diffstat (limited to 'source/blender/editors/interface/interface_widgets.c')
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 138 |
1 files changed, 83 insertions, 55 deletions
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index db4ddeae659..ff46925edaa 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -922,45 +922,12 @@ static void ui_text_clip_give_next_off(uiBut *but, const char *str) but->ofs += bytes; } -/** - * Cut off the start of the text to fit into the width of \a rect - * - * \note Sets but->ofs to make sure text is correctly visible. - * \note Clips right in some cases, this function could be cleaned up. - */ -static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, const rcti *rect) -{ - /* We are not supposed to use labels with that clipping, so we can always apply margins. */ - const int border = (int)(UI_TEXT_CLIP_MARGIN + 0.5f); - const int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0); - - /* 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; - but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr)); - - if ((okwidth > 0.0f) && (but->strwidth > okwidth)) { - float strwidth; - but->ofs = BLF_width_to_rstrlen(fstyle->uifont_id, but->drawstr, - sizeof(but->drawstr), okwidth, &strwidth); - but->strwidth = strwidth; - } - - if (fstyle->kerning == 1) { - BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); - } -} - /* Helper. * This func assumes things like kerning handling have already been handled! * Return the length of modified (right-clipped + ellipsis) string. */ static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth, - const char *sep, const int sep_len, const float sep_strwidth) + const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len) { float tmp; int l_end; @@ -973,19 +940,27 @@ static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t m if (sep_strwidth / okwidth > 0.2f) { l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp); str[l_end] = '\0'; + if (r_final_len) { + *r_final_len = (size_t)l_end; + } } else { l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, &tmp); memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */ + if (r_final_len) { + *r_final_len = (size_t)(l_end + sep_len); + } } } /** * Cut off the middle of the text to fit into the given width. * Note in case this middle clipping would just remove a few chars, it rather clips right, which is more readable. + * If rpart_sep is not Null, the part of str starting to first occurrence of rpart_sep is preserved at all cost (useful + * for strings with shortcuts, like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O'). */ -static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, const float okwidth, const float minwidth, - const size_t max_len) +static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidth, const float minwidth, + const size_t max_len, const char *rpart_sep) { float strwidth; @@ -1004,37 +979,76 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, const float /* utf8 ellipsis '...', some compilers complain */ const char sep[] = {0xe2, 0x80, 0xa6, 0x0}; const int sep_len = sizeof(sep) - 1; + const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1); + float parts_strwidth; size_t l_end; - const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1); - const float parts_strwidth = ((float)okwidth - sep_strwidth) / 2.0f; + char *rpart = NULL, rpart_buf[UI_MAX_DRAW_STR]; + float rpart_width = 0.0f; + size_t rpart_len = 0; + size_t final_lpart_len; + + if (rpart_sep) { + rpart = strstr(str, rpart_sep); + + if (rpart) { + rpart_len = strlen(rpart); + rpart_width = BLF_width(fstyle->uifont_id, rpart, rpart_len); + okwidth -= rpart_width; + strwidth -= rpart_width; + + if (okwidth < 0.0f) { + /* Not enough place for actual label, just display protected right part. + * Here just for safety, should never happen in real life! */ + memmove(str, rpart, rpart_len + 1); + rpart = NULL; + okwidth += rpart_width; + strwidth = rpart_width; + } + } + } + + parts_strwidth = (okwidth - sep_strwidth) / 2.0f; + + if (rpart) { + strcpy(rpart_buf, rpart); + *rpart = '\0'; + rpart = rpart_buf; + } - if (min_ff(parts_strwidth, strwidth - okwidth) < minwidth) { + l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, &rpart_width); + if (l_end < 10 || min_ff(parts_strwidth, strwidth - okwidth) < minwidth) { /* If we really have no place, or we would clip a very small piece of string in the middle, * only show start of string. */ - ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth); + ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len); } else { size_t r_offset, r_len; - l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, parts_strwidth, &strwidth); - r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, &strwidth); - r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'... */ + r_offset = BLF_width_to_rstrlen(fstyle->uifont_id, str, max_len, parts_strwidth, &rpart_width); + r_len = strlen(str + r_offset) + 1; /* +1 for the trailing '\0'. */ - if (l_end + sep_len + r_len > max_len) { + if (l_end + sep_len + r_len + rpart_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... * Note: with a single-char ellipsis, this should never happen! But better be safe here... */ - ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth); + ui_text_clip_right_ex(fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len); } else { memmove(str + l_end + sep_len, str + r_offset, r_len); memcpy(str + l_end, sep, sep_len); + final_lpart_len = (size_t)(l_end + sep_len + r_len - 1); /* -1 to remove trailing '\0'! */ } } + + if (rpart) { + /* Add back preserved right part to our shorten str. */ + memcpy(str + final_lpart_len, rpart, rpart_len + 1); /* +1 for trailing '\0'. */ + } + strwidth = BLF_width(fstyle->uifont_id, str, max_len); } @@ -1045,6 +1059,9 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, const float return strwidth; } +/** + * Wrapper around ui_text_clip_middle_ex. + */ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rect) { /* No margin for labels! */ @@ -1054,7 +1071,23 @@ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rec const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f; but->ofs = 0; - but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len); + but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, NULL); +} + +/** + * Like ui_text_clip_middle(), but protect/preserve at all cost the right part of the string after sep. + * Useful for strings with shortcuts (like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O'). + */ +static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char *rsep) +{ + /* No margin for labels! */ + const int border = ELEM(but->type, LABEL, MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f); + const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0); + const size_t max_len = sizeof(but->drawstr); + const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f; + + but->ofs = 0; + but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep); } /** @@ -1431,14 +1464,9 @@ 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; - } -#endif else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) { - ui_text_clip_left(fstyle, but, rect); + /* Clip middle, but protect in all case right part containing the shortcut, if any. */ + ui_text_clip_middle_protect_right(fstyle, but, rect, "|"); } else { ui_text_clip_middle(fstyle, but, rect); @@ -3921,7 +3949,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic const float minwidth = (float)(UI_DPI_ICON_SIZE); BLI_strncpy(drawstr, name, sizeof(drawstr)); - ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len); + ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL); glColor4ubv((unsigned char *)wt->wcol.text); uiStyleFontDraw(fstyle, rect, drawstr); @@ -3996,7 +4024,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int const float minwidth = (float)(UI_DPI_ICON_SIZE); BLI_strncpy(drawstr, name, sizeof(drawstr)); - ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len); + ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL); glColor4ubv((unsigned char *)wt->wcol.text); uiStyleFontDraw(fstyle, &trect, drawstr); |