turbo-editors/turbo-corepublic Fork 0
28d59854361aeda8541d853093e732126f3d7bff
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

🛟 Updated. 28d5985 · on 28d59854361aeda8541d853093e732126f3d7bff · k33g · 14h ago
view_draw.go · 95 lines · 2.5 KBGo Blame HistoryRaw
 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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package filetree

import (
	"strings"

	"github.com/gdamore/tcell/v2"

	"codeberg.org/turbo-editors/turbo-core/theme"
	"codeberg.org/turbo-editors/turbo-core/ui"
)

// Draw paints the visible rows and the scroll bar beside them.
func (v *View) Draw(p *ui.Painter, th *theme.Theme) {
	area := p.Sub(v.Bounds())
	area.Clear(th.Style(theme.KeyTreeText))

	rows := v.tree.Rows()
	v.scrollToSelection(len(rows), area.Size().H)
	width := max(area.Size().W-1, 0)

	for line := range area.Size().H {
		index := v.top + line
		if index >= len(rows) {
			break
		}
		v.drawRow(area, line, width, rows[index], index == v.selected, th)
	}

	ui.DrawVScrollBar(area, area.Size().W-1, 0, area.Size().H,
		v.top, area.Size().H, len(rows),
		th.Style(theme.KeyScrollBar), th.Style(theme.KeyScrollBarThumb))
}

// drawRow paints one entry: its indentation, its marker and its name.
func (v *View) drawRow(p *ui.Painter, line, width int, row Row, selected bool, th *theme.Theme) {
	style := v.styleFor(row.Node, selected, th)
	if selected {
		p.HLine(0, line, width, ' ', style)
	}
	p.TextLimited(0, line, width, label(row), style)
}

// label renders one row as the text to draw.
//
// A file is indented by a marker's width as well, so that names line up in a
// column whatever their neighbours are.
func label(row Row) string {
	return strings.Repeat(indent, row.Depth) + marker(row.Node) + row.Node.Name()
}

// marker returns the glyph that says whether a directory is open, closed, or
// not a directory at all.
func marker(node *Node) string {
	switch {
	case !node.IsDir():
		return fileMarker
	case node.Expanded():
		return openMarker
	default:
		return closedMarker
	}
}

// styleFor picks the colour of one row.
//
// The highlight is dimmed when the tree does not have the focus, the same way
// a list box dims its own, so that a screenful of windows still says where the
// keyboard is.
func (v *View) styleFor(node *Node, selected bool, th *theme.Theme) tcell.Style {
	switch {
	case selected && v.Focused():
		return th.Style(theme.KeyTreeSelected)
	case selected:
		return th.Style(theme.KeyTreeUnfocused)
	case node.IsDir():
		return th.Style(theme.KeyTreeDirectory)
	default:
		return th.Style(theme.KeyTreeText)
	}
}

// scrollToSelection moves the window of visible rows just enough to keep the
// highlight on screen.
func (v *View) scrollToSelection(total, height int) {
	if height <= 0 {
		return
	}
	if v.selected < v.top {
		v.top = v.selected
	}
	if v.selected >= v.top+height {
		v.top = v.selected - height + 1
	}
	v.top = min(max(v.top, 0), max(total-height, 0))
}