UI: word-wrap support for tooltips
Tooltips will automatically wrap when exceeding UI_TIP_MAXWIDTH.
This commit is contained in:
@@ -155,13 +155,14 @@ static void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar)
|
|||||||
|
|
||||||
#define UI_TIP_PAD_FAC 1.3f
|
#define UI_TIP_PAD_FAC 1.3f
|
||||||
#define UI_TIP_PADDING (int)(UI_TIP_PAD_FAC * UI_UNIT_Y)
|
#define UI_TIP_PADDING (int)(UI_TIP_PAD_FAC * UI_UNIT_Y)
|
||||||
|
#define UI_TIP_MAXWIDTH 600
|
||||||
|
|
||||||
#define MAX_TOOLTIP_LINES 8
|
#define MAX_TOOLTIP_LINES 8
|
||||||
typedef struct uiTooltipData {
|
typedef struct uiTooltipData {
|
||||||
rcti bbox;
|
rcti bbox;
|
||||||
uiFontStyle fstyle;
|
uiFontStyle fstyle;
|
||||||
char lines[MAX_TOOLTIP_LINES][512];
|
char lines[MAX_TOOLTIP_LINES][2048];
|
||||||
char header[512], active_info[512];
|
char header[2048], active_info[2048];
|
||||||
struct {
|
struct {
|
||||||
enum {
|
enum {
|
||||||
UI_TIP_STYLE_NORMAL = 0,
|
UI_TIP_STYLE_NORMAL = 0,
|
||||||
@@ -178,6 +179,14 @@ typedef struct uiTooltipData {
|
|||||||
} color_id : 4;
|
} color_id : 4;
|
||||||
int is_pad : 1;
|
int is_pad : 1;
|
||||||
} format[MAX_TOOLTIP_LINES];
|
} format[MAX_TOOLTIP_LINES];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int lines;
|
||||||
|
} line_geom[MAX_TOOLTIP_LINES];
|
||||||
|
|
||||||
|
int wrap_width;
|
||||||
|
|
||||||
int totline;
|
int totline;
|
||||||
int toth, lineh;
|
int toth, lineh;
|
||||||
} uiTooltipData;
|
} uiTooltipData;
|
||||||
@@ -257,12 +266,14 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
|
|||||||
rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */
|
rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */
|
||||||
|
|
||||||
/* draw text */
|
/* draw text */
|
||||||
|
BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
|
||||||
|
BLF_wordwrap(blf_mono_font, data->wrap_width);
|
||||||
|
|
||||||
bbox.xmin += 0.5f * pad_px; /* add padding to the text */
|
bbox.xmin += 0.5f * pad_px; /* add padding to the text */
|
||||||
bbox.ymax -= 0.5f * (BLI_rcti_size_y(&bbox) - data->toth);
|
bbox.ymax -= 0.25f * pad_px;
|
||||||
bbox.ymin = bbox.ymax - data->lineh;
|
|
||||||
|
|
||||||
for (i = 0; i < data->totline; i++) {
|
for (i = 0; i < data->totline; i++) {
|
||||||
|
bbox.ymin = bbox.ymax - (data->lineh * data->line_geom[i].lines);
|
||||||
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
|
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
|
||||||
/* draw header and active data (is done here to be able to change color) */
|
/* draw header and active data (is done here to be able to change color) */
|
||||||
uiFontStyle fstyle_header = data->fstyle;
|
uiFontStyle fstyle_header = data->fstyle;
|
||||||
@@ -273,12 +284,13 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
|
|||||||
fstyle_header.shadowcolor = rgb_to_grayscale(tip_colors[UI_TIP_LC_MAIN]);
|
fstyle_header.shadowcolor = rgb_to_grayscale(tip_colors[UI_TIP_LC_MAIN]);
|
||||||
fstyle_header.shadx = fstyle_header.shady = 0;
|
fstyle_header.shadx = fstyle_header.shady = 0;
|
||||||
fstyle_header.shadowalpha = 1.0f;
|
fstyle_header.shadowalpha = 1.0f;
|
||||||
|
fstyle_header.word_wrap = true;
|
||||||
|
|
||||||
UI_fontstyle_set(&fstyle_header);
|
UI_fontstyle_set(&fstyle_header);
|
||||||
glColor3fv(tip_colors[UI_TIP_LC_MAIN]);
|
glColor3fv(tip_colors[UI_TIP_LC_MAIN]);
|
||||||
UI_fontstyle_draw(&fstyle_header, &bbox, data->header);
|
UI_fontstyle_draw(&fstyle_header, &bbox, data->header);
|
||||||
|
|
||||||
xofs = BLF_width(fstyle_header.uifont_id, data->header, sizeof(data->header));
|
xofs = data->line_geom[i].width;
|
||||||
bbox.xmin += xofs;
|
bbox.xmin += xofs;
|
||||||
|
|
||||||
glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]);
|
glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]);
|
||||||
@@ -289,6 +301,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
|
|||||||
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
|
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
|
||||||
uiFontStyle fstyle_mono = data->fstyle;
|
uiFontStyle fstyle_mono = data->fstyle;
|
||||||
fstyle_mono.uifont_id = blf_mono_font;
|
fstyle_mono.uifont_id = blf_mono_font;
|
||||||
|
fstyle_mono.word_wrap = true;
|
||||||
|
|
||||||
UI_fontstyle_set(&fstyle_mono);
|
UI_fontstyle_set(&fstyle_mono);
|
||||||
/* XXX, needed because we dont have mono in 'U.uifonts' */
|
/* XXX, needed because we dont have mono in 'U.uifonts' */
|
||||||
@@ -297,22 +310,26 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
|
|||||||
UI_fontstyle_draw(&fstyle_mono, &bbox, data->lines[i]);
|
UI_fontstyle_draw(&fstyle_mono, &bbox, data->lines[i]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
uiFontStyle fstyle_normal = data->fstyle;
|
||||||
BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
|
BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
|
||||||
|
fstyle_normal.word_wrap = true;
|
||||||
|
|
||||||
/* draw remaining data */
|
/* draw remaining data */
|
||||||
UI_fontstyle_set(&data->fstyle);
|
UI_fontstyle_set(&fstyle_normal);
|
||||||
glColor3fv(tip_colors[data->format[i].color_id]);
|
glColor3fv(tip_colors[data->format[i].color_id]);
|
||||||
UI_fontstyle_draw(&data->fstyle, &bbox, data->lines[i]);
|
UI_fontstyle_draw(&data->fstyle, &bbox, data->lines[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bbox.ymax -= data->lineh * data->line_geom[i].lines;
|
||||||
|
|
||||||
if ((i + 1 != data->totline) && data->format[i + 1].is_pad) {
|
if ((i + 1 != data->totline) && data->format[i + 1].is_pad) {
|
||||||
bbox.ymax -= data->lineh * UI_TIP_PAD_FAC;
|
bbox.ymax -= data->lineh * (UI_TIP_PAD_FAC - 1);
|
||||||
bbox.ymin -= data->lineh * UI_TIP_PAD_FAC;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bbox.ymax -= data->lineh;
|
|
||||||
bbox.ymin -= data->lineh;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
|
||||||
|
BLF_disable(blf_mono_font, BLF_WORD_WRAP);
|
||||||
|
|
||||||
if (multisample_enabled)
|
if (multisample_enabled)
|
||||||
glEnable(GL_MULTISAMPLE_ARB);
|
glEnable(GL_MULTISAMPLE_ARB);
|
||||||
}
|
}
|
||||||
@@ -338,10 +355,11 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
|
|||||||
char buf[512];
|
char buf[512];
|
||||||
/* aspect values that shrink text are likely unreadable */
|
/* aspect values that shrink text are likely unreadable */
|
||||||
const float aspect = min_ff(1.0f, but->block->aspect);
|
const float aspect = min_ff(1.0f, but->block->aspect);
|
||||||
float fonth, fontw;
|
int fonth, fontw;
|
||||||
int winx, ofsx, ofsy, w = 0, h, i;
|
int winx, ofsx, ofsy, h, i;
|
||||||
rctf rect_fl;
|
rctf rect_fl;
|
||||||
rcti rect_i;
|
rcti rect_i;
|
||||||
|
int font_flag = 0;
|
||||||
|
|
||||||
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
|
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
|
||||||
uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
|
uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
|
||||||
@@ -578,6 +596,17 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
|
|||||||
|
|
||||||
UI_fontstyle_set(&data->fstyle);
|
UI_fontstyle_set(&data->fstyle);
|
||||||
|
|
||||||
|
data->wrap_width = min_ii(UI_TIP_MAXWIDTH * U.pixelsize / aspect, WM_window_pixels_x(win) - (UI_TIP_PADDING * 2));
|
||||||
|
|
||||||
|
font_flag |= BLF_WORD_WRAP;
|
||||||
|
if (data->fstyle.kerning == 1) {
|
||||||
|
font_flag |= BLF_KERNING_DEFAULT;
|
||||||
|
}
|
||||||
|
BLF_enable(data->fstyle.uifont_id, font_flag);
|
||||||
|
BLF_enable(blf_mono_font, font_flag);
|
||||||
|
BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
|
||||||
|
BLF_wordwrap(blf_mono_font, data->wrap_width);
|
||||||
|
|
||||||
/* these defines tweaked depending on font */
|
/* these defines tweaked depending on font */
|
||||||
#define TIP_BORDER_X (16.0f / aspect)
|
#define TIP_BORDER_X (16.0f / aspect)
|
||||||
#define TIP_BORDER_Y (6.0f / aspect)
|
#define TIP_BORDER_Y (6.0f / aspect)
|
||||||
@@ -585,33 +614,41 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
|
|||||||
h = BLF_height_max(data->fstyle.uifont_id);
|
h = BLF_height_max(data->fstyle.uifont_id);
|
||||||
|
|
||||||
for (i = 0, fontw = 0, fonth = 0; i < data->totline; i++) {
|
for (i = 0, fontw = 0, fonth = 0; i < data->totline; i++) {
|
||||||
|
struct ResultBLF info;
|
||||||
|
int w, w_other = 0;
|
||||||
|
|
||||||
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
|
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
|
||||||
w = BLF_width(data->fstyle.uifont_id, data->header, sizeof(data->header));
|
w = BLF_width_ex(data->fstyle.uifont_id, data->header, sizeof(data->header), &info);
|
||||||
if (enum_label.strinfo)
|
if (enum_label.strinfo)
|
||||||
w += BLF_width(data->fstyle.uifont_id, data->active_info, sizeof(data->active_info));
|
w_other = BLF_width(data->fstyle.uifont_id, data->active_info, sizeof(data->active_info));
|
||||||
}
|
}
|
||||||
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
|
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
|
||||||
BLF_size(blf_mono_font, data->fstyle.points * U.pixelsize, U.dpi);
|
BLF_size(blf_mono_font, data->fstyle.points * U.pixelsize, U.dpi);
|
||||||
|
|
||||||
w = BLF_width(blf_mono_font, data->lines[i], sizeof(data->lines[i]));
|
w = BLF_width_ex(blf_mono_font, data->lines[i], sizeof(data->lines[i]), &info);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
|
BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
|
||||||
w = BLF_width(data->fstyle.uifont_id, data->lines[i], sizeof(data->lines[i]));
|
|
||||||
|
w = BLF_width_ex(data->fstyle.uifont_id, data->lines[i], sizeof(data->lines[i]), &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
fontw = max_ff(fontw, (float)w);
|
fontw = max_ii(fontw, w + w_other);
|
||||||
|
|
||||||
|
fonth += h * info.lines;
|
||||||
if ((i + 1 != data->totline) && data->format[i + 1].is_pad) {
|
if ((i + 1 != data->totline) && data->format[i + 1].is_pad) {
|
||||||
fonth += h * UI_TIP_PAD_FAC;
|
fonth += h * (UI_TIP_PAD_FAC - 1);
|
||||||
}
|
|
||||||
else {
|
|
||||||
fonth += h;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->line_geom[i].lines = info.lines;
|
||||||
|
data->line_geom[i].width = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
//fontw *= aspect;
|
//fontw *= aspect;
|
||||||
|
|
||||||
|
BLF_disable(data->fstyle.uifont_id, font_flag);
|
||||||
|
BLF_disable(blf_mono_font, font_flag);
|
||||||
|
|
||||||
ar->regiondata = data;
|
ar->regiondata = data;
|
||||||
|
|
||||||
data->toth = fonth;
|
data->toth = fonth;
|
||||||
|
|||||||
@@ -152,7 +152,6 @@ void UI_fontstyle_draw_ex(
|
|||||||
const uiFontStyle *fs, const rcti *rect, const char *str,
|
const uiFontStyle *fs, const rcti *rect, const char *str,
|
||||||
size_t len, float *r_xofs, float *r_yofs)
|
size_t len, float *r_xofs, float *r_yofs)
|
||||||
{
|
{
|
||||||
float height;
|
|
||||||
int xofs = 0, yofs;
|
int xofs = 0, yofs;
|
||||||
int font_flag = BLF_CLIPPING;
|
int font_flag = BLF_CLIPPING;
|
||||||
|
|
||||||
@@ -167,11 +166,13 @@ void UI_fontstyle_draw_ex(
|
|||||||
if (fs->kerning == 1) {
|
if (fs->kerning == 1) {
|
||||||
font_flag |= BLF_KERNING_DEFAULT;
|
font_flag |= BLF_KERNING_DEFAULT;
|
||||||
}
|
}
|
||||||
|
if (fs->word_wrap == 1) {
|
||||||
|
font_flag |= BLF_WORD_WRAP;
|
||||||
|
}
|
||||||
|
|
||||||
BLF_enable(fs->uifont_id, font_flag);
|
BLF_enable(fs->uifont_id, font_flag);
|
||||||
|
|
||||||
height = BLF_ascender(fs->uifont_id);
|
yofs = BLI_rcti_size_y(rect) - BLF_height_max(fs->uifont_id);
|
||||||
yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
|
|
||||||
|
|
||||||
if (fs->align == UI_STYLE_TEXT_CENTER) {
|
if (fs->align == UI_STYLE_TEXT_CENTER) {
|
||||||
xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
|
xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
|
||||||
|
|||||||
@@ -74,7 +74,8 @@ typedef struct uiFontStyle {
|
|||||||
short uifont_id; /* saved in file, 0 is default */
|
short uifont_id; /* saved in file, 0 is default */
|
||||||
short points; /* actual size depends on 'global' dpi */
|
short points; /* actual size depends on 'global' dpi */
|
||||||
short kerning; /* unfitted or default kerning value. */
|
short kerning; /* unfitted or default kerning value. */
|
||||||
char pad[6];
|
char word_wrap; /* enable word-wrap when drawing */
|
||||||
|
char pad[5];
|
||||||
short italic, bold; /* style hint */
|
short italic, bold; /* style hint */
|
||||||
short shadow; /* value is amount of pixels blur */
|
short shadow; /* value is amount of pixels blur */
|
||||||
short shadx, shady; /* shadow offset in pixels */
|
short shadx, shady; /* shadow offset in pixels */
|
||||||
|
|||||||
Reference in New Issue
Block a user