Elements are now pass-scoped value handles: tests that read bounds after a frame bind a ui.Handle. pixel tells frames apart by the build pass's root, since the Tester clock no longer moves on its own. Fix the regressions the upgrade brought: - Clipboard reads in input handlers go through c.Services(). - MyGo notes an overlay's opener after building it, so AutoFocus inside lost it; pixel.AutoFocus focuses through a Handle, and archtest bans the raw call. Dialogs hand the focus back again. - Elements around a press stay hovered: Tooltip tells a press-given focus by focus arriving under the pointer. - The web host moves the Tester clock with real time, at most 500 ms a call, and gives components the real clock. The gallery's source index also accepts CRLF checkouts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
55 lines
1.1 KiB
Go
55 lines
1.1 KiB
Go
package text
|
|
|
|
import (
|
|
"unicode"
|
|
|
|
"github.com/egoist/mygo/ui"
|
|
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
|
)
|
|
|
|
type HighlightOptions struct {
|
|
Slot pixel.Slot
|
|
// Mark is the marker slot; zero means Warn.
|
|
Mark pixel.Slot
|
|
}
|
|
|
|
// Highlight marks each match of query in s, ignoring case.
|
|
func Highlight(c *ui.Context, s, query string, o HighlightOptions) ui.Element {
|
|
k := pixel.K(c)
|
|
mark := slotOr(o.Mark, pixel.Warn)
|
|
rs := []rune(s)
|
|
spans := matches(rs, []rune(query))
|
|
return block(c, k, s, pixel.Measure(s), pixel.LineHeight, func(g pixel.Canvas) {
|
|
for _, sp := range spans {
|
|
x0, x1 := pixel.Measure(string(rs[:sp[0]])), pixel.Measure(string(rs[:sp[1]]))
|
|
g.Veil(x0, 2, x1-x0, pixel.LineHeight-4, mark, 10)
|
|
}
|
|
g.Text(0, 0, s, o.Slot, 1)
|
|
})
|
|
}
|
|
|
|
// matches are the rune spans of q in s.
|
|
func matches(s, q []rune) [][2]int {
|
|
var out [][2]int
|
|
if len(q) == 0 {
|
|
return nil
|
|
}
|
|
for i := 0; i+len(q) <= len(s); {
|
|
same := true
|
|
for j := range q {
|
|
if unicode.ToLower(s[i+j]) != unicode.ToLower(q[j]) {
|
|
same = false
|
|
break
|
|
}
|
|
}
|
|
if same {
|
|
out = append(out, [2]int{i, i + len(q)})
|
|
i += len(q)
|
|
} else {
|
|
i++
|
|
}
|
|
}
|
|
return out
|
|
}
|