zntg/ui/text.go
Sander Schobers de8ce3e7bc Added text overflow to label.
Generalised text fitting (to width) and implemented binary search.
2021-07-19 17:55:10 +02:00

69 lines
1.5 KiB
Go

package ui
import "strings"
// findOptimalFit tries to find the optimal (largest) fit for the interval [0..n] by doing a binary search.
func findOptimalFit(n int, fits func(i int) bool) int {
if n < 0 || fits(n) {
return n
}
min, max := 0, n
for {
if min == max {
if min == 0 && !fits(min) {
return -1
}
return min
}
middle := (max + min + 1) / 2
if fits(middle) {
min = middle
} else {
max = middle - 1
}
}
}
// findSpaces creates a slice with indices where spaces can be found in string s
func findSpaces(s string) []int {
var spaces []int
offset := 0
for {
space := strings.Index(s[offset:], " ")
if space == -1 {
return spaces
}
offset += space
spaces = append(spaces, offset)
offset++
}
}
func fitTextEllipsis(font Font, text string, availableWidth float32) string {
if font.WidthOf(text) <= availableWidth {
return text
}
ellipsis := "..."
availableWidth -= font.WidthOf(ellipsis)
cut := findOptimalFit(len(text), func(i int) bool { return font.WidthOf(text[:i]) <= availableWidth })
if cut == -1 {
return ""
}
return text[:cut] + ellipsis
}
// fitTextWord tries to fit as much of string s in width space.
func fitTextWord(font Font, s string, availableWidth float32) string {
if font.WidthOf(s) < availableWidth {
return s
}
spaces := findSpaces(s)
split := findOptimalFit(len(spaces)-1, func(i int) bool {
return font.WidthOf(s[:spaces[i]]) <= availableWidth
})
if split == -1 {
return s
}
return s[:spaces[split]]
}