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)
}
}
|