Fix text wrapping: add MinWidth/MaxWidth/MaxLines to all LayoutString calls

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Greg Pomerantz 2026-05-09 14:01:02 -04:00
parent ddd44baefd
commit ca34a570a9

View File

@ -97,7 +97,12 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
availableWidth := int(reg.W - unit.Dp(8) - unit.Dp(40)) // left margin + right icons in DP availableWidth := int(reg.W - unit.Dp(8) - unit.Dp(40)) // left margin + right icons in DP
// Layout ellipsis once and get its width // Layout ellipsis once and get its width
th.Shaper.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(r.theme.FontSize))}, "...") th.Shaper.LayoutString(text.Parameters{
PxPerEm: fixed.I(gtx.Sp(r.theme.FontSize)),
MinWidth: 0,
MaxWidth: 1000,
MaxLines: 1,
}, "...")
var ellipsisWidth int var ellipsisWidth int
for { for {
g, ok := th.Shaper.NextGlyph() g, ok := th.Shaper.NextGlyph()
@ -197,8 +202,13 @@ func boolToString(b bool) string {
// drawTruncatedText layouts text, measures widths, truncates if needed, and draws in a single pass. // drawTruncatedText layouts text, measures widths, truncates if needed, and draws in a single pass.
func (r *Renderer) drawTruncatedText(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp, x, y unit.Dp, availableWidth, spaceForText int, col color.NRGBA) { func (r *Renderer) drawTruncatedText(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp, x, y unit.Dp, availableWidth, spaceForText int, col color.NRGBA) {
// Layout text // Layout text with width constraints so the shaper doesn't wrap every character.
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, str) shp.LayoutString(text.Parameters{
PxPerEm: fixed.I(gtx.Sp(size)),
MinWidth: 0,
MaxWidth: availableWidth,
MaxLines: 1,
}, str)
// Measure widths and find truncation point // Measure widths and find truncation point
var widths []int var widths []int
@ -226,15 +236,25 @@ func (r *Renderer) drawTruncatedText(gtx layout.Context, shp *text.Shaper, str s
} }
// Re-layout truncated text and draw glyphs directly // Re-layout truncated text and draw glyphs directly
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, fullStr) shp.LayoutString(text.Parameters{
PxPerEm: fixed.I(gtx.Sp(size)),
MinWidth: 0,
MaxWidth: availableWidth,
MaxLines: 1,
}, fullStr)
r.drawLineText(gtx, shp, x, y, col) r.drawLineText(gtx, shp, x, y, col)
} }
// drawText draws text using the same approach as Gio's textView: // drawText draws text using the same approach as Gio's textView:
// layout text, iterate glyphs, buffer into lines, and draw using shaper.Shape(). // layout text, iterate glyphs, buffer into lines, and draw using shaper.Shape().
func (r *Renderer) drawText(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp, x, y unit.Dp, col color.NRGBA) { func (r *Renderer) drawText(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp, x, y unit.Dp, col color.NRGBA) {
// Layout text // Layout text with width constraints so the shaper doesn't wrap every character.
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, str) shp.LayoutString(text.Parameters{
PxPerEm: fixed.I(gtx.Sp(size)),
MinWidth: 0,
MaxWidth: 1000,
MaxLines: 1,
}, str)
r.drawLineText(gtx, shp, x, y, col) r.drawLineText(gtx, shp, x, y, col)
} }
@ -292,7 +312,13 @@ func (r *Renderer) drawLine(gtx layout.Context, shp *text.Shaper, line []text.Gl
// charWidths returns the cumulative width after each rune in str. // charWidths returns the cumulative width after each rune in str.
func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) []int { func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) []int {
// Match Gio's textView: PxPerEm = font size in device pixels // Match Gio's textView: PxPerEm = font size in device pixels
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, str) // Must set MinWidth/MaxWidth/MaxLines or shaper wraps every character.
shp.LayoutString(text.Parameters{
PxPerEm: fixed.I(gtx.Sp(size)),
MinWidth: 0,
MaxWidth: 1000,
MaxLines: 1,
}, str)
var widths []int var widths []int
var cumWidth fixed.Int26_6 = 0 var cumWidth fixed.Int26_6 = 0
for { for {