summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcitrons <citrons@mondecitronne.com>2025-06-07 15:58:35 -0500
committercitrons <citrons@mondecitronne.com>2025-06-07 16:02:18 -0500
commit4fd84671877754ae3b66acb8a8af8cf0935a53c9 (patch)
tree4d7b6de81bd28e0c1184037f236e1a0e3701b646
parent4067adfc361e87bc4e73e31fdfc4933802f05413 (diff)
context menus
-rw-r--r--client/channel_window.go10
-rw-r--r--tui/context_menu.go75
-rw-r--r--tui/layout.go15
3 files changed, 97 insertions, 3 deletions
diff --git a/client/channel_window.go b/client/channel_window.go
index 3fec792..95f0dbf 100644
--- a/client/channel_window.go
+++ b/client/channel_window.go
@@ -3,6 +3,7 @@ package main
import (
"citrons.xyz/talk/client/buffer"
"citrons.xyz/talk/client/window"
+ "citrons.xyz/talk/client/clipboard"
"citrons.xyz/talk/proto"
"citrons.xyz/talk/tui"
"strconv"
@@ -297,11 +298,16 @@ func (m channelMsg) Show(odd bool) {
m.showName(bg)
tui.Pop()
- tui.Push("", tui.Box {
- Width: tui.TextSize, Height: tui.TextSize,
+ tui.Push(m.Id() + ".content", tui.Box {
+ Width: tui.Fill, Height: tui.TextSize,
Margins: [4]int {1, 0, 0, 0},
})
tui.Text(m.Fields[""], nil)
+ switch {
+ case tui.MenuOption("copy"):
+ clipboard.Get().Copy(m.Fields[""])
+ case tui.MenuOption("reply"):
+ }
tui.Pop()
default:
tui.Push("", tui.Box {Width: tui.Fill, Height: tui.TextSize})
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()
}