summaryrefslogtreecommitdiff
path: root/gui/ui/menu.go
blob: 7fe7ff80a4b6d7b1014fa50ee96ce409f891e763 (plain)
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
		}
	}
}