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
|
package ui
import "9front/gui/draw"
// An Item is one line of a menu.
type Item struct {
Label string
Do func()
}
// Menu pops up at p and tracks until button 3 comes back up, the way
// page(1) and vdir(1) do it: press 3, drag, release on an item.
//
// It keeps itself on the screen, which is the detail everyone forgets
// until the menu opens near the bottom edge and half of it is missing.
// redraw is called if the menu is dismissed without a choice.
func (u *UI) Menu(items []Item, at draw.Point, mc *draw.Mousectl, redraw func()) {
if len(items) == 0 {
return
}
lh := int32(u.F.Height) + 4
var w int32
for _, it := range items {
if x := u.F.Width(it.Label) + 20; x > w {
w = x
}
}
h := lh*int32(len(items)) + 4
win := u.Win.Rect()
r := draw.Rect(at.X, at.Y, at.X+w, at.Y+h)
if r.Max.X > win.Max.X {
r = r.Add(draw.Point{X: win.Max.X - r.Max.X})
}
if r.Max.Y > win.Max.Y {
r = r.Add(draw.Point{Y: win.Max.Y - r.Max.Y})
}
sel := -1
paint := func() {
u.Fill(r, "tag")
u.Border(r, "border")
for i, it := range items {
ir := draw.Rect(r.Min.X+1, r.Min.Y+2+int32(i)*lh,
r.Max.X-1, r.Min.Y+2+int32(i+1)*lh)
if i == sel {
u.Fill(ir, "today")
}
u.Text(draw.Point{X: ir.Min.X + 8, Y: ir.Min.Y + 2}, "ink", it.Label)
}
u.D.Flush()
}
itemAt := func(p draw.Point) int {
if p.X < r.Min.X || p.X >= r.Max.X {
return -1
}
i := int((p.Y - r.Min.Y - 2) / lh)
if i < 0 || i >= len(items) || p.Y < r.Min.Y+2 {
return -1
}
return i
}
paint()
for m := range mc.C {
if n := itemAt(m.Point); n != sel {
sel = n
paint()
}
if m.Buttons&4 == 0 {
if sel >= 0 {
items[sel].Do()
} else {
redraw()
}
return
}
}
}
|