Always initialize context menu List

Resolves #12
This commit is contained in:
Trevor Slocum 2020-05-09 10:19:23 -07:00
parent cfce21cc90
commit ce60530a57
3 changed files with 64 additions and 39 deletions

View File

@ -3,6 +3,7 @@ v1.4.6 (WIP)
- Add Vim-style keybindings to List
- Fix List not updating selected item before calling selected handlers
- Do not handle right click on List when there is no context menu
- Always initialize context menu List
v1.4.5 (2020-04-25)
- Add multithreading support

View File

@ -18,9 +18,28 @@ type ContextMenu struct {
// NewContextMenu returns a new context menu.
func NewContextMenu(parent Primitive) *ContextMenu {
c := &ContextMenu{parent: parent}
return &ContextMenu{
parent: parent,
}
}
return c
func (c *ContextMenu) initializeList() {
if c.list != nil {
return
}
c.list = NewList().
ShowSecondaryText(false).
SetHover(true).
SetWrapAround(true)
c.list.
SetBorder(true).
SetBorderPadding(
Styles.ContextMenuPaddingTop,
Styles.ContextMenuPaddingBottom,
Styles.ContextMenuPaddingLeft,
Styles.ContextMenuPaddingRight)
c.list.showFocus = false
}
// ContextMenuList returns the underlying List of the context menu.
@ -28,6 +47,8 @@ func (c *ContextMenu) ContextMenuList() *List {
c.l.Lock()
defer c.l.Unlock()
c.initializeList()
return c.list
}
@ -37,20 +58,7 @@ func (c *ContextMenu) AddContextItem(text string, shortcut rune, selected func(i
c.l.Lock()
defer c.l.Unlock()
if c.list == nil {
c.list = NewList().
ShowSecondaryText(false).
SetHover(true).
SetWrapAround(true)
c.list.
SetBorder(true).
SetBorderPadding(
Styles.ContextMenuPaddingTop,
Styles.ContextMenuPaddingBottom,
Styles.ContextMenuPaddingLeft,
Styles.ContextMenuPaddingRight)
c.list.showFocus = false
}
c.initializeList()
c.list.AddItem(text, "", shortcut, c.wrap(selected))
if text == "" && shortcut == 0 {
@ -74,9 +82,9 @@ func (c *ContextMenu) ClearContextMenu() *ContextMenu {
c.l.Lock()
defer c.l.Unlock()
if c.list != nil {
c.list.Clear()
}
c.initializeList()
c.list.Clear()
return c
}
@ -101,8 +109,26 @@ func (c *ContextMenu) ShowContextMenu(item int, x int, y int, setFocus func(Prim
c.show(item, x, y, setFocus)
}
// HideContextMenu hides the context menu.
func (c *ContextMenu) HideContextMenu(setFocus func(Primitive)) {
c.l.Lock()
defer c.l.Unlock()
c.hide(setFocus)
}
// ContextMenuVisible returns whether or not the context menu is visible.
func (c *ContextMenu) ContextMenuVisible() bool {
c.l.Lock()
defer c.l.Unlock()
return c.open
}
func (c *ContextMenu) show(item int, x int, y int, setFocus func(Primitive)) {
if c.list == nil || len(c.list.items) == 0 {
c.initializeList()
if len(c.list.items) == 0 {
return
}
@ -139,11 +165,9 @@ func (c *ContextMenu) show(item int, x int, y int, setFocus func(Primitive)) {
}
func (c *ContextMenu) hide(setFocus func(Primitive)) {
c.open = false
c.initializeList()
if c.list == nil {
return
}
c.open = false
if c.list.HasFocus() {
setFocus(c.parent)

30
list.go
View File

@ -577,12 +577,12 @@ func (l *List) Focus(delegate func(p Primitive)) {
// HasFocus returns whether or not this primitive has focus.
func (l *List) HasFocus() bool {
l.RLock()
defer l.RUnlock()
if l.ContextMenu.open {
return l.ContextMenu.list.HasFocus()
}
l.RLock()
defer l.RUnlock()
return l.hasFocus
}
@ -791,13 +791,13 @@ func (l *List) Draw(screen tcell.Screen) {
// Draw context menu.
if hasFocus && l.ContextMenu.open {
list := l.ContextMenu.list
ctx := l.ContextMenuList()
x, y, width, height = l.GetInnerRect()
// What's the longest option text?
maxWidth := 0
for _, option := range list.items {
for _, option := range ctx.items {
strWidth := TaggedStringWidth(option.MainText)
if option.Shortcut != 0 {
strWidth += 4
@ -807,15 +807,15 @@ func (l *List) Draw(screen tcell.Screen) {
}
}
lheight := len(list.items)
lheight := len(ctx.items)
lwidth := maxWidth
// Add space for borders
lwidth += 2
lheight += 2
lwidth += l.list.paddingLeft + l.list.paddingRight
lheight += l.list.paddingTop + l.list.paddingBottom
lwidth += ctx.paddingLeft + ctx.paddingRight
lheight += ctx.paddingTop + ctx.paddingBottom
cx, cy := l.ContextMenu.x, l.ContextMenu.y
if cx < 0 || cy < 0 {
@ -834,12 +834,12 @@ func (l *List) Draw(screen tcell.Screen) {
lheight = sheight - cy
}
if list.scrollBarVisibility == ScrollBarAlways || (list.scrollBarVisibility == ScrollBarAuto && len(list.items) > lheight) {
if ctx.scrollBarVisibility == ScrollBarAlways || (ctx.scrollBarVisibility == ScrollBarAuto && len(ctx.items) > lheight) {
lwidth++ // Add space for scroll bar
}
list.SetRect(cx, cy, lwidth, lheight)
list.Draw(screen)
ctx.SetRect(cx, cy, lwidth, lheight)
ctx.Draw(screen)
}
}
@ -1016,8 +1016,8 @@ func (l *List) MouseHandler() func(action MouseAction, event *tcell.EventMouse,
l.Lock()
// Pass events to context menu.
if l.ContextMenu.open && l.ContextMenu.list != nil && l.ContextMenu.list.InRect(event.Position()) {
defer l.ContextMenu.list.MouseHandler()(action, event, setFocus)
if l.ContextMenuVisible() && l.ContextMenuList().InRect(event.Position()) {
defer l.ContextMenuList().MouseHandler()(action, event, setFocus)
consumed = true
l.Unlock()
return
@ -1031,7 +1031,7 @@ func (l *List) MouseHandler() func(action MouseAction, event *tcell.EventMouse,
// Process mouse event.
switch action {
case MouseLeftClick:
if l.ContextMenu.open {
if l.ContextMenuVisible() {
defer l.ContextMenu.hide(setFocus)
consumed = true
l.Unlock()
@ -1073,7 +1073,7 @@ func (l *List) MouseHandler() func(action MouseAction, event *tcell.EventMouse,
return
}
case MouseRightDown:
if l.ContextMenu.list == nil || len(l.ContextMenu.list.items) == 0 {
if len(l.ContextMenuList().items) == 0 {
l.Unlock()
return
}