...
1 package cview
2
3 import "sync"
4
5
6
7 type ContextMenu struct {
8 parent Primitive
9 item int
10 open bool
11 drag bool
12 list *List
13 x, y int
14 selected func(int, string, rune)
15
16 l sync.RWMutex
17 }
18
19
20 func NewContextMenu(parent Primitive) *ContextMenu {
21 return &ContextMenu{
22 parent: parent,
23 }
24 }
25
26 func (c *ContextMenu) initializeList() {
27 if c.list != nil {
28 return
29 }
30
31 c.list = NewList()
32 c.list.ShowSecondaryText(false)
33 c.list.SetHover(true)
34 c.list.SetWrapAround(true)
35 c.list.ShowFocus(false)
36 c.list.SetBorder(true)
37 c.list.SetPadding(
38 Styles.ContextMenuPaddingTop,
39 Styles.ContextMenuPaddingBottom,
40 Styles.ContextMenuPaddingLeft,
41 Styles.ContextMenuPaddingRight)
42 }
43
44
45 func (c *ContextMenu) ContextMenuList() *List {
46 c.l.Lock()
47 defer c.l.Unlock()
48
49 c.initializeList()
50
51 return c.list
52 }
53
54
55
56 func (c *ContextMenu) AddContextItem(text string, shortcut rune, selected func(index int)) {
57 c.l.Lock()
58 defer c.l.Unlock()
59
60 c.initializeList()
61
62 item := NewListItem(text)
63 item.SetShortcut(shortcut)
64 item.SetSelectedFunc(c.wrap(selected))
65
66 c.list.AddItem(item)
67 if text == "" && shortcut == 0 {
68 c.list.Lock()
69 index := len(c.list.items) - 1
70 c.list.items[index].disabled = true
71 c.list.Unlock()
72 }
73 }
74
75 func (c *ContextMenu) wrap(f func(index int)) func() {
76 return func() {
77 f(c.item)
78 }
79 }
80
81
82 func (c *ContextMenu) ClearContextMenu() {
83 c.l.Lock()
84 defer c.l.Unlock()
85
86 c.initializeList()
87
88 c.list.Clear()
89 }
90
91
92
93
94
95 func (c *ContextMenu) SetContextSelectedFunc(handler func(index int, text string, shortcut rune)) {
96 c.l.Lock()
97 defer c.l.Unlock()
98
99 c.selected = handler
100 }
101
102
103
104 func (c *ContextMenu) ShowContextMenu(item int, x int, y int, setFocus func(Primitive)) {
105 c.l.Lock()
106 defer c.l.Unlock()
107
108 c.show(item, x, y, setFocus)
109 }
110
111
112 func (c *ContextMenu) HideContextMenu(setFocus func(Primitive)) {
113 c.l.Lock()
114 defer c.l.Unlock()
115
116 c.hide(setFocus)
117 }
118
119
120 func (c *ContextMenu) ContextMenuVisible() bool {
121 c.l.Lock()
122 defer c.l.Unlock()
123
124 return c.open
125 }
126
127 func (c *ContextMenu) show(item int, x int, y int, setFocus func(Primitive)) {
128 c.initializeList()
129
130 if len(c.list.items) == 0 {
131 return
132 }
133
134 c.open = true
135 c.item = item
136 c.x, c.y = x, y
137
138 c.list.Lock()
139 for i, item := range c.list.items {
140 if !item.disabled {
141 c.list.currentItem = i
142 break
143 }
144 }
145 c.list.Unlock()
146
147 c.list.SetSelectedFunc(func(index int, item *ListItem) {
148 c.l.Lock()
149
150
151 c.hide(setFocus)
152
153 if c.selected != nil {
154 c.l.Unlock()
155 c.selected(index, string(item.mainText), item.shortcut)
156 } else {
157 c.l.Unlock()
158 }
159 })
160 c.list.SetDoneFunc(func() {
161 c.l.Lock()
162 defer c.l.Unlock()
163
164 c.hide(setFocus)
165 })
166
167 setFocus(c.list)
168 }
169
170 func (c *ContextMenu) hide(setFocus func(Primitive)) {
171 c.initializeList()
172
173 c.open = false
174
175 if c.list.HasFocus() {
176 setFocus(c.parent)
177 }
178 }
179
View as plain text