summaryrefslogtreecommitdiff
path: root/gui/ui/menu.go
diff options
context:
space:
mode:
Diffstat (limited to 'gui/ui/menu.go')
-rw-r--r--gui/ui/menu.go79
1 files changed, 79 insertions, 0 deletions
diff --git a/gui/ui/menu.go b/gui/ui/menu.go
new file mode 100644
index 0000000..7fe7ff8
--- /dev/null
+++ b/gui/ui/menu.go
@@ -0,0 +1,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
+ }
+ }
+}