// SPDX-License-Identifier: GPL-3.0-or-later package ui import ( "github.com/diamondburned/gotk4/pkg/gtk/v4" "krino/gui/internal/model" ) // The colours a configuration is painted in. They are chosen to read on a // light and a dark theme alike, since the window follows whatever GTK theme // is in use (his request, 2026-09-16). var spanColours = map[model.SpanKind]string{ model.SpanComment: "#8b8b8b", model.SpanString: "#2e8b57", model.SpanHead: "#3584e4", model.SpanAction: "#c06014", model.SpanParen: "#9a9a9a", } // highlighter paints a configuration in a TextView. type highlighter struct { buf *gtk.TextBuffer tags map[model.SpanKind]*gtk.TextTag on bool } // newHighlighter registers one tag per kind, once per buffer. func newHighlighter(buf *gtk.TextBuffer) *highlighter { h := &highlighter{buf: buf, tags: map[model.SpanKind]*gtk.TextTag{}, on: true} table := buf.TagTable() names := map[model.SpanKind]string{ model.SpanComment: "krino-comment", model.SpanString: "krino-string", model.SpanHead: "krino-head", model.SpanAction: "krino-action", model.SpanParen: "krino-paren", } for kind, name := range names { t := gtk.NewTextTag(name) t.SetObjectProperty("foreground", spanColours[kind]) if kind == model.SpanComment { t.SetObjectProperty("style", 2) // PANGO_STYLE_ITALIC } table.Add(t) h.tags[kind] = t } return h } // setEnabled turns the colours on or off. func (h *highlighter) setEnabled(on bool) { h.on = on if !on { h.clear() } } // clear takes every colour off the buffer. func (h *highlighter) clear() { start, end := h.buf.Bounds() h.buf.RemoveAllTags(start, end) } // paint colours the text now in the buffer. func (h *highlighter) paint(text string) { h.clear() if !h.on { return } for _, s := range model.Spans(text) { if tag, ok := h.tags[s.Kind]; ok { h.buf.ApplyTag(tag, h.buf.IterAtOffset(s.From), h.buf.IterAtOffset(s.To)) } } }