feat(ui): support tab to focus next widget & back tab (Shift + Tab) to focus previous widget (#196)

This commit is contained in:
ayntgl 2022-08-29 15:27:21 +05:30 • committed by GitHub
parent 41ed0bc604
commit c6393e2a1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 47 deletions

View file

@ -38,36 +38,16 @@ identifyProperties = {
-- Keybindings
keys = {
application = {
key(
"Rune[g]",
"Focus the guilds tree widget.",
function(core, event)
core.Application:SetFocus(core.GuildsTree)
end
),
key(
"Rune[c]",
"Focus the channels tree widget.",
function(core, event)
core.Application:SetFocus(core.ChannelsTree)
end
),
key(
"Rune[m]",
"Focus the messages panel widget.",
function(core, event)
core.Application:SetFocus(core.MessagesPanel)
end
),
key(
"Rune[i]",
"Focus the message input widget.",
function(core, event)
core.Application:SetFocus(core.MessageInput)
end
)
},
-- application = {
-- key(
-- "Ctrl+R",
-- "Refresh the screen.",
-- function(core, event)
-- core.Application:Sync()
-- return nil
-- end
-- )
-- },
messagesPanel = {
key(
"Rune[a]",

View file

@ -15,6 +15,15 @@ import (
luar "layeh.com/gopher-luar"
)
type focused int
const (
guildsTree focused = iota
channelsTree
messagesPanel
messageInput
)
// Core is responsible for the following:
// - Initialization of the application, UI elements, configuration, and state.
// - Configuration of the application and state when Run is called.
@ -29,6 +38,8 @@ type Core struct {
Config *config.Config
State *state.State
focused focused
}
func NewCore(path string) *Core {
@ -122,9 +133,6 @@ func (c *Core) DrawMainFlex() {
}
func (c *Core) onInputCapture(e *tcell.EventKey) *tcell.EventKey {
if c.MessageInput.HasFocus() {
return e
}
// If the main flex is nil, that is, it is not initialized yet, then the login form is currently focused.
if c.MainFlex == nil {
return e
@ -148,20 +156,67 @@ func (c *Core) onInputCapture(e *tcell.EventKey) *tcell.EventKey {
}
})
c.Config.State.CallByParam(lua.P{
Fn: fn,
NRet: 1,
Protect: true,
}, luar.New(c.Config.State, c), luar.New(c.Config.State, e))
// Returned value
ret, ok := c.Config.State.Get(-1).(*lua.LUserData)
if !ok {
return e
if fn != nil {
c.Config.State.CallByParam(lua.P{
Fn: fn,
NRet: 1,
Protect: true,
}, luar.New(c.Config.State, c), luar.New(c.Config.State, e))
// Returned value
ret, ok := c.Config.State.Get(-1).(*lua.LUserData)
if !ok {
return e
}
// Remove returned value
c.Config.State.Pop(1)
ev, ok := ret.Value.(*tcell.EventKey)
if ok {
return ev
}
}
// Remove returned value
c.Config.State.Pop(1)
return ret.Value.(*tcell.EventKey)
// Default
switch e.Key() {
case tcell.KeyEsc:
c.focused = 0
case tcell.KeyBacktab:
// If the currently focused widget is the guilds tree widget (first), then focus the message input widget (last)
if c.focused == 0 {
c.focused = messageInput
} else {
c.focused--
}
c.setFocus()
case tcell.KeyTab:
// If the currently focused widget is the message input widget (last), then focus the guilds tree widget (first)
if c.focused == messageInput {
c.focused = guildsTree
} else {
c.focused++
}
c.setFocus()
}
return e
}
func (c *Core) setFocus() {
var p tview.Primitive
switch c.focused {
case guildsTree:
p = c.GuildsTree
case channelsTree:
p = c.ChannelsTree
case messagesPanel:
p = c.MessagesPanel
case messageInput:
p = c.MessageInput
}
c.Application.SetFocus(p)
}
func (c *Core) onStateReady(r *gateway.ReadyEvent) {

View file

@ -87,8 +87,6 @@ func (mi *MessageInput) onInputCapture(e *tcell.EventKey) *tcell.EventKey {
mi.
SetText("").
SetTitle("")
mi.core.Application.SetFocus(mi.core.MainFlex)
mi.core.MessagesPanel.SelectedMessage = -1
mi.core.MessagesPanel.Highlight()
return nil