[Bf-blender-cvs] [d435b0d] master: UI: word-wrap support for tooltips

Campbell Barton noreply at git.blender.org
Fri Sep 18 12:49:28 CEST 2015


Commit: d435b0d24d389143e766dc7d776760b10315206c
Author: Campbell Barton
Date:   Fri Sep 18 20:21:25 2015 +1000
Branches: master
https://developer.blender.org/rBd435b0d24d389143e766dc7d776760b10315206c

UI: word-wrap support for tooltips

Tooltips will automatically wrap when exceeding UI_TIP_MAXWIDTH.

===================================================================

M	source/blender/editors/interface/interface_regions.c
M	source/blender/editors/interface/interface_style.c
M	source/blender/makesdna/DNA_userdef_types.h

===================================================================

diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index b9bacb8..7c3da92 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -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_PADDING      (int)(UI_TIP_PAD_FAC * UI_UNIT_Y)
+#define UI_TIP_MAXWIDTH     600
 
 #define MAX_TOOLTIP_LINES 8
 typedef struct uiTooltipData {
 	rcti bbox;
 	uiFontStyle fstyle;
-	char lines[MAX_TOOLTIP_LINES][512];
-	char header[512], active_info[512];
+	char lines[MAX_TOOLTIP_LINES][2048];
+	char header[2048], active_info[2048];
 	struct {
 		enum {
 			UI_TIP_STYLE_NORMAL = 0,
@@ -178,6 +179,14 @@ typedef struct uiTooltipData {
 		} color_id : 4;
 		int is_pad : 1;
 	} format[MAX_TOOLTIP_LINES];
+
+	struct {
+		unsigned int width;
+		unsigned int lines;
+	} line_geom[MAX_TOOLTIP_LINES];
+
+	int wrap_width;
+
 	int totline;
 	int toth, lineh;
 } 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        */
 
 	/* 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.ymax -= 0.5f * (BLI_rcti_size_y(&bbox) - data->toth);
-	bbox.ymin = bbox.ymax - data->lineh;
+	bbox.ymax -= 0.25f * pad_px;
 
 	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) {
 			/* draw header and active data (is done here to be able to change color) */
 			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.shadx = fstyle_header.shady = 0;
 			fstyle_header.shadowalpha = 1.0f;
+			fstyle_header.word_wrap = true;
 
 			UI_fontstyle_set(&fstyle_header);
 			glColor3fv(tip_colors[UI_TIP_LC_MAIN]);
 			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;
 
 			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) {
 			uiFontStyle fstyle_mono = data->fstyle;
 			fstyle_mono.uifont_id = blf_mono_font;
+			fstyle_mono.word_wrap = true;
 
 			UI_fontstyle_set(&fstyle_mono);
 			/* 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]);
 		}
 		else {
+			uiFontStyle fstyle_normal = data->fstyle;
 			BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
+			fstyle_normal.word_wrap = true;
+
 			/* draw remaining data */
-			UI_fontstyle_set(&data->fstyle);
+			UI_fontstyle_set(&fstyle_normal);
 			glColor3fv(tip_colors[data->format[i].color_id]);
 			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) {
-			bbox.ymax -= data->lineh * UI_TIP_PAD_FAC;
-			bbox.ymin -= data->lineh * UI_TIP_PAD_FAC;
-		}
-		else {
-			bbox.ymax -= data->lineh;
-			bbox.ymin -= data->lineh;
+			bbox.ymax -= data->lineh * (UI_TIP_PAD_FAC - 1);
 		}
 	}
 
+	BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
+	BLF_disable(blf_mono_font, BLF_WORD_WRAP);
+
 	if (multisample_enabled)
 		glEnable(GL_MULTISAMPLE_ARB);
 }
@@ -338,10 +355,11 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
 	char buf[512];
 	/* aspect values that shrink text are likely unreadable */
 	const float aspect = min_ff(1.0f, but->block->aspect);
-	float fonth, fontw;
-	int winx, ofsx, ofsy, w = 0, h, i;
+	int fonth, fontw;
+	int winx, ofsx, ofsy, h, i;
 	rctf rect_fl;
 	rcti rect_i;
+	int font_flag = 0;
 
 	uiStringInfo but_tip = {BUT_GET_TIP, 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);
 
+	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 */
 #define TIP_BORDER_X (16.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);
 
 	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) {
-			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)
-				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) {
 			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 {
 			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) {
-			fonth += h * UI_TIP_PAD_FAC;
-		}
-		else {
-			fonth += h;
+			fonth += h * (UI_TIP_PAD_FAC - 1);
 		}
+
+		data->line_geom[i].lines = info.lines;
+		data->line_geom[i].width = w;
 	}
 
 	//fontw *= aspect;
 
+	BLF_disable(data->fstyle.uifont_id, font_flag);
+	BLF_disable(blf_mono_font, font_flag);
+
 	ar->regiondata = data;
 
 	data->toth = fonth;
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index e158b70..5d0d82e 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -152,7 +152,6 @@ void UI_fontstyle_draw_ex(
         const uiFontStyle *fs, const rcti *rect, const char *str,
         size_t len, float *r_xofs, float *r_yofs)
 {
-	float height;
 	int xofs = 0, yofs;
 	int font_flag = BLF_CLIPPING;
 	
@@ -167,11 +166,13 @@ void UI_fontstyle_draw_ex(
 	if (fs->kerning == 1) {
 		font_flag |= BLF_KERNING_DEFAULT;
 	}
+	if (fs->word_wrap == 1) {
+		font_flag |= BLF_WORD_WRAP;
+	}
 
 	BLF_enable(fs->uifont_id, font_flag);
 
-	height = BLF_ascender(fs->uifont_id);
-	yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
+	yofs = BLI_rcti_size_y(rect) - BLF_height_max(fs->uifont_id);
 
 	if (fs->align == UI_STYLE_TEXT_CENTER) {
 		xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index bc2c746..00dc1c1 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -74,7 +74,8 @@ typedef struct uiFontStyle {
 	short uifont_id;		/* saved in file, 0 is default */
 	short points;			/* actual size depends on 'global' dpi */
 	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 shadow;			/* value is amount of pixels blur */
 	short shadx, shady;		/* shadow offset in pixels */




More information about the Bf-blender-cvs mailing list