Fix filename truncation with proper scaling and ellipsis width measurement

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Greg Pomerantz 2026-05-08 20:47:08 -04:00
parent bbd16be9f2
commit 9c1e32c52a
2 changed files with 34 additions and 14 deletions

View File

@ -2,6 +2,7 @@ package ui
import (
"image"
"log"
"gioui.org/layout"
"gioui.org/op"
@ -92,11 +93,13 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
// Truncate filename only if it doesn't fit
displayFilename := sb.Filename
availableWidth := int(reg.W - unit.Dp(8) - unit.Dp(40)) // left margin + right icons in DP
ellipsisWidth := textWidth(gtx, th.Shaper, "...", r.theme.FontSize)
ellipsisWidths := charWidths(gtx, th.Shaper, "...", r.theme.FontSize)
ellipsisWidth := ellipsisWidths[len(ellipsisWidths)-1]
// Measure how wide "..." is, then find how many chars fit in availableWidth - ellipsisWidth
spaceForText := availableWidth - ellipsisWidth
widths := charWidths(gtx, th.Shaper, displayFilename, r.theme.FontSize)
if len(widths) > 0 && widths[len(widths)-1] > availableWidth {
log.Printf("drawStatusBar: filename=%q availableWidth=%d ellipsisWidth=%d spaceForText=%d widths=%v", displayFilename, availableWidth, ellipsisWidth, spaceForText, widths)
if len(widths) > 0 && widths[len(widths)-1] > spaceForText {
// Find the largest index where the width fits
for i, w := range widths {
if w <= spaceForText {
@ -109,6 +112,7 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
}
}
}
log.Printf("drawStatusBar: final filename=%q", displayFilename)
// Position filename at (reg.X + 8, filenameLineY)
call1 := op.Offset(image.Point{X: int(reg.X + unit.Dp(8)), Y: int(filenameLineY)}).Push(gtx.Ops)
@ -210,38 +214,54 @@ func boolToString(b bool) string {
// textWidth measures the total width of a string using the shaper.
func textWidth(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) int {
shp.LayoutString(text.Parameters{PxPerEm: 1024}, str)
var lastX fixed.Int26_6
pixelsPerDp := gtx.Dp(unit.Dp(1))
shp.LayoutString(text.Parameters{PxPerEm: fixed.Int26_6(1024 * pixelsPerDp)}, str)
var minX, maxX fixed.Int26_6
first := true
for {
g, ok := shp.NextGlyph()
if !ok {
break
}
x := g.X + g.Advance
if x > lastX {
lastX = x
if first {
minX = g.X
maxX = g.X + g.Advance
first = false
} else {
if g.X < minX {
minX = g.X
}
if g.X+g.Advance > maxX {
maxX = g.X + g.Advance
}
}
}
return int(lastX)
return int(maxX - minX)
}
// charWidths returns the cumulative width after each rune in str.
func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) []int {
shp.LayoutString(text.Parameters{PxPerEm: 1024}, str)
var widths []int
var cumX fixed.Int26_6
pixelsPerDp := gtx.Dp(unit.Dp(1))
shp.LayoutString(text.Parameters{PxPerEm: fixed.Int26_6(1024 * pixelsPerDp)}, str)
var runeAdvances []fixed.Int26_6
var runeIdx int
for {
g, ok := shp.NextGlyph()
if !ok {
break
}
cumX = g.X + g.Advance
// Each glyph corresponds to one rune in our simple ASCII case
if runeIdx < len(str) {
widths = append(widths, int(cumX))
runeAdvances = append(runeAdvances, g.Advance)
runeIdx++
}
}
// Accumulate advances and convert from Int26_6 to int (divide by 64)
var widths []int
var cumWidth fixed.Int26_6
for _, adv := range runeAdvances {
cumWidth += adv
widths = append(widths, int(cumWidth>>6))
}
log.Printf("charWidths: runeAdvances=%v widths=%v", runeAdvances, widths)
return widths
}

BIN
pad

Binary file not shown.