Add drawTruncatedText for single-pass layout, measure, and render
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
16719afb95
commit
fcd2fea870
|
|
@ -95,23 +95,27 @@ 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
|
||||||
ellipsisWidths := charWidths(gtx, th.Shaper, "...", r.theme.FontSize)
|
|
||||||
|
// Layout ellipsis once and get its width
|
||||||
|
th.Shaper.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(r.theme.FontSize))}, "...")
|
||||||
|
var ellipsisWidths []int
|
||||||
|
for {
|
||||||
|
g, ok := th.Shaper.NextGlyph()
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if len(ellipsisWidths) == 0 {
|
||||||
|
ellipsisWidths = append(ellipsisWidths, int(g.Advance>>6))
|
||||||
|
} else {
|
||||||
|
ellipsisWidths = append(ellipsisWidths, ellipsisWidths[len(ellipsisWidths)-1]+int(g.Advance>>6))
|
||||||
|
}
|
||||||
|
}
|
||||||
ellipsisWidth := ellipsisWidths[len(ellipsisWidths)-1]
|
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)
|
|
||||||
if len(widths) > 0 && widths[len(widths)-1] > availableWidth {
|
|
||||||
// Find the largest index where the width fits
|
|
||||||
for i := len(widths)-1; i >= 0; i-- {
|
|
||||||
if widths[i] <= spaceForText {
|
|
||||||
displayFilename = displayFilename[:i] + "..."
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position filename at (reg.X + 8, filenameLineY) - draw using shaper to avoid double-shaping
|
// Layout filename, measure widths, and draw in a single pass
|
||||||
r.drawText(gtx, th.Shaper, displayFilename, r.theme.FontSize, reg.X+unit.Dp(8), filenameLineY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
r.drawTruncatedText(gtx, th.Shaper, displayFilename, r.theme.FontSize, reg.X+unit.Dp(8), filenameLineY, availableWidth, spaceForText, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||||
|
|
||||||
// Line 2: Icons
|
// Line 2: Icons
|
||||||
iconsLineY := filenameLineY + filenameLineH
|
iconsLineY := filenameLineY + filenameLineH
|
||||||
|
|
@ -196,6 +200,41 @@ func boolToString(b bool) string {
|
||||||
return "Off"
|
return "Off"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
// Layout text
|
||||||
|
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, str)
|
||||||
|
|
||||||
|
// Measure widths and find truncation point
|
||||||
|
var widths []int
|
||||||
|
var cumWidth fixed.Int26_6
|
||||||
|
fullStr := str
|
||||||
|
for {
|
||||||
|
g, ok := shp.NextGlyph()
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cumWidth += g.Advance
|
||||||
|
w := int(cumWidth >> 6)
|
||||||
|
widths = append(widths, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate if needed
|
||||||
|
if len(widths) > 0 && widths[len(widths)-1] > availableWidth {
|
||||||
|
// Find truncation point (from longest to shortest)
|
||||||
|
for i := len(widths)-1; i >= 0; i-- {
|
||||||
|
if widths[i] <= spaceForText {
|
||||||
|
fullStr = str[:i] + "..."
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-layout truncated text and draw
|
||||||
|
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, fullStr)
|
||||||
|
r.drawText(gtx, shp, fullStr, size, 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) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user