diff options
| author | citrons <citrons@mondecitronne.com> | 2025-06-07 15:58:35 -0500 |
|---|---|---|
| committer | citrons <citrons@mondecitronne.com> | 2025-06-07 16:02:18 -0500 |
| commit | 4fd84671877754ae3b66acb8a8af8cf0935a53c9 (patch) | |
| tree | 4d7b6de81bd28e0c1184037f236e1a0e3701b646 /tui | |
| parent | 4067adfc361e87bc4e73e31fdfc4933802f05413 (diff) | |
context menus
Diffstat (limited to 'tui')
| -rw-r--r-- | tui/context_menu.go | 75 | ||||
| -rw-r--r-- | tui/layout.go | 15 |
2 files changed, 89 insertions, 1 deletions
diff --git a/tui/context_menu.go b/tui/context_menu.go new file mode 100644 index 0000000..e6d5bb9 --- /dev/null +++ b/tui/context_menu.go @@ -0,0 +1,75 @@ +package tui + +import ( + "github.com/rivo/uniseg" + "strings" +) + +var menuStyle = Style {Fg: Black, Bg: Yellow} + +var menuState struct { + open bool + x, y int + width, height int + boxId string + menu []string + selected string +} + +func MenuOption(name string) bool { + b := top() + b.contextMenu = append(b.contextMenu, name) + if menuState.boxId == top().id && menuState.selected == name { + menuState.selected = "" + return true + } + return false +} + +func openContextMenu(x int, y int, b *Box) { + menuState.open = true + menuState.boxId = b.id + menuState.menu = b.contextMenu + + menuState.height = len(menuState.menu) + for _, option := range menuState.menu { + menuState.width = max(menuState.width, uniseg.StringWidth(option)) + } + size := Size() + if x + menuState.width < size.Width { + menuState.x = x + 1 + } else { + menuState.x = x - menuState.width - 1 + } + if y + menuState.height < size.Height { + menuState.y = y + } else { + menuState.y = y - menuState.height + } +} + + +func processContextMenu(ev MouseEvent) { + for i, option := range menuState.menu { + x, y := menuState.x, menuState.y + i + if ev.Button <= 2 && (ev.Pressed || ev.Released) && + ev.X >= x && ev.X < x + menuState.width && ev.Y == y { + menuState.selected = option + menuState.open = false + } + } + if ev.Button <= 2 && ev.Pressed { + menuState.open = false + } +} + +func drawContextMenu() { + if !menuState.open { + return + } + for i, option := range menuState.menu { + x, y := menuState.x, menuState.y + i + WriteAt(x, y, strings.Repeat(" ", menuState.width), menuStyle) + WriteAt(x, y, option, menuStyle) + } +} diff --git a/tui/layout.go b/tui/layout.go index ede0fa6..039ce52 100644 --- a/tui/layout.go +++ b/tui/layout.go @@ -24,6 +24,7 @@ type Box struct { computedRect rect isOverflow bool mouseEvent MouseEvent + contextMenu []string } type BoxSize int @@ -439,6 +440,9 @@ func (b *Box) mouseEvents(ev MouseEvent) { bev.Pressed = ev.Pressed bev.Released = ev.Released bev.Scroll = ev.Scroll + if ev.Pressed && ev.Button == 2 && len(b.contextMenu) > 0 { + openContextMenu(ev.X, ev.Y, b) + } } b.mouseEvent = bev for _, c := range b.children { @@ -470,5 +474,14 @@ func DrawLayout() { b.drawComputed(parentRect, DefaultStyle) ev := getLastEvent() - b.mouseEvents(ev.Mouse) + if menuState.open { + processContextMenu(ev.Mouse) + var releaseEvent MouseEvent + releaseEvent.Button = ev.Mouse.Button + releaseEvent.ReleasedAnywhere = ev.Mouse.ReleasedAnywhere + b.mouseEvents(releaseEvent) + } else { + b.mouseEvents(ev.Mouse) + } + drawContextMenu() } |
