aboutsummaryrefslogtreecommitdiff
path: root/gui/internal/ui/highlight.go
blob: 88c701ba4e8c08beb734a7918e0d15e05a69f853 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// SPDX-License-Identifier: GPL-3.0-or-later

package ui

import (
	"github.com/diamondburned/gotk4/pkg/gtk/v4"

	"git.labunix.xyz/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.
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))
		}
	}
}