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 ( import (
"image" "image"
"log"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
@ -92,11 +93,13 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
// Truncate filename only if it doesn't fit // Truncate filename only if it doesn't fit
displayFilename := sb.Filename displayFilename := sb.Filename
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
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 // Measure how wide "..." is, then find how many chars fit in availableWidth - ellipsisWidth
spaceForText := availableWidth - ellipsisWidth spaceForText := availableWidth - ellipsisWidth
widths := charWidths(gtx, th.Shaper, displayFilename, r.theme.FontSize) 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 // Find the largest index where the width fits
for i, w := range widths { for i, w := range widths {
if w <= spaceForText { 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) // 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) 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. // 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 { func textWidth(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) int {
shp.LayoutString(text.Parameters{PxPerEm: 1024}, str) pixelsPerDp := gtx.Dp(unit.Dp(1))
var lastX fixed.Int26_6 shp.LayoutString(text.Parameters{PxPerEm: fixed.Int26_6(1024 * pixelsPerDp)}, str)
var minX, maxX fixed.Int26_6
first := true
for { for {
g, ok := shp.NextGlyph() g, ok := shp.NextGlyph()
if !ok { if !ok {
break break
} }
x := g.X + g.Advance if first {
if x > lastX { minX = g.X
lastX = 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. // 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 {
shp.LayoutString(text.Parameters{PxPerEm: 1024}, str) pixelsPerDp := gtx.Dp(unit.Dp(1))
var widths []int shp.LayoutString(text.Parameters{PxPerEm: fixed.Int26_6(1024 * pixelsPerDp)}, str)
var cumX fixed.Int26_6 var runeAdvances []fixed.Int26_6
var runeIdx int var runeIdx int
for { for {
g, ok := shp.NextGlyph() g, ok := shp.NextGlyph()
if !ok { if !ok {
break break
} }
cumX = g.X + g.Advance
// Each glyph corresponds to one rune in our simple ASCII case
if runeIdx < len(str) { if runeIdx < len(str) {
widths = append(widths, int(cumX)) runeAdvances = append(runeAdvances, g.Advance)
runeIdx++ 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 return widths
} }

BIN
pad

Binary file not shown.