69 lines
1.5 KiB
Go
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]]
|
|
}
|