turbo-editors/turbo-corepublic Fork 0
v0.9.0
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 v0.9.0 · k33g · 18h ago
menu_draw.go · 110 lines · 2.9 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
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
package ui

// Where the menu bar puts its panels, and how it paints them.

import (
	"codeberg.org/turbo-editors/turbo-core/theme"
)

// menuX returns the column the title of menu i starts at.
func (b *MenuBar) menuX(i int) int {
	x := b.Bounds().X + 1
	for _, m := range b.menus[:i] {
		x += LabelWidth(m.Label) + 2
	}
	return x
}

// dropdownBounds returns the rectangle the open drop-down occupies.
func (b *MenuBar) dropdownBounds() Rect {
	menu := b.menus[b.openMenu]

	width := 0
	for _, item := range menu.Items {
		width = max(width, item.width())
	}
	width += 4 // one cell of frame and one of padding on each side

	return Rect{
		X: b.menuX(b.openMenu) - 1,
		Y: b.Bounds().Y + 1,
		W: width,
		H: len(menu.Items) + 2,
	}
}

// Draw paints the bar and, if one is open, the drop-down under it.
func (b *MenuBar) Draw(p *Painter, th *theme.Theme) {
	bar := p.Sub(b.Bounds())
	bar.Clear(th.Style(theme.KeyMenuBar))

	for i, menu := range b.menus {
		normal, hot := th.Style(theme.KeyMenuItem), th.Style(theme.KeyMenuShortcut)
		if i == b.openMenu {
			normal = th.Style(theme.KeyMenuSelected)
			hot = normal
		}

		x := b.menuX(i) - b.Bounds().X
		bar.SetCell(x-1, 0, ' ', normal)
		end := DrawLabel(bar, x, 0, menu.Label, normal, hot)
		bar.SetCell(end, 0, ' ', normal)
	}

	if b.Open() {
		b.drawDropdown(p, th)
	}
	if b.submenuOpen() {
		b.drawSubmenu(p, th)
	}
}

// drawDropdown paints the open menu's frame and items.
func (b *MenuBar) drawDropdown(p *Painter, th *theme.Theme) {
	bounds := b.dropdownBounds()
	DrawShadow(p, bounds, th.Style(theme.KeyShadow))

	panel := p.Sub(bounds)
	panel.Clear(th.Style(theme.KeyMenuItem))
	DrawFrame(panel, panel.Size(), FrameSingle, th.Style(theme.KeyMenuItem))

	for i, item := range b.menus[b.openMenu].Items {
		// The item whose submenu is showing stays highlighted, so the eye can
		// see which branch the second panel came from.
		b.drawLine(panel, th, i, item, i == b.highlight || i == b.openItem)
	}
}

// drawLine paints one line of a drop-down.
func (b *MenuBar) drawLine(p *Painter, th *theme.Theme, i int, item *MenuItem, highlighted bool) {
	y := i + 1
	width := p.Size().W

	if item.Separator {
		// The rule joins the frame on both sides, as Turbo Vision drew it.
		style := th.Style(theme.KeyMenuItem)
		p.SetCell(0, y, '├', style)
		p.HLine(1, y, width-2, '─', style)
		p.SetCell(width-1, y, '┤', style)
		return
	}

	normal, hot := th.Style(theme.KeyMenuItem), th.Style(theme.KeyMenuShortcut)
	switch {
	case !item.enabled():
		normal, hot = th.Style(theme.KeyMenuDisabled), th.Style(theme.KeyMenuDisabled)
	case highlighted:
		normal = th.Style(theme.KeyMenuSelected)
		hot = normal
	}

	p.HLine(1, y, width-2, ' ', normal)
	DrawLabel(p, 2, y, item.Label, normal, hot)

	switch {
	case item.Shortcut != "":
		p.Text(width-2-len([]rune(item.Shortcut)), y, item.Shortcut, normal)
	case item.hasSubmenu():
		p.Text(width-2-len([]rune(submenuMarker)), y, submenuMarker, normal)
	}
}