discordo/ui/core.go

132 lines
2.9 KiB
Go

package ui
import (
"github.com/ayntgl/discordo/config"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
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.
// - Management of the application and state.
type Core struct {
Application *tview.Application
MainFlex *tview.Flex
GuildsTree *GuildsTree
ChannelsTree *ChannelsTree
MessagesPanel *MessagesPanel
MessageInput *MessageInput
Config *config.Config
State *State
focused focused
}
func NewCore(cfg *config.Config) *Core {
c := &Core{
Application: tview.NewApplication(),
MainFlex: tview.NewFlex(),
Config: cfg,
}
tview.Styles.PrimitiveBackgroundColor = tcell.GetColor(cfg.Theme.Background)
tview.Styles.BorderColor = tcell.GetColor(cfg.Theme.Border)
tview.Styles.TitleColor = tcell.GetColor(cfg.Theme.Title)
c.Application.EnableMouse(c.Config.Mouse)
c.Application.SetInputCapture(c.onInputCapture)
c.Application.SetBeforeDrawFunc(c.beforeDraw)
c.GuildsTree = NewGuildsTree(c)
c.ChannelsTree = NewChannelsTree(c)
c.MessagesPanel = NewMessagesPanel(c)
c.MessageInput = NewMessageInput(c)
return c
}
func (c *Core) Run(token string) error {
c.State = NewState(token, c)
return c.State.Run()
}
func (c *Core) DrawMainFlex() {
leftFlex := tview.NewFlex().
SetDirection(tview.FlexRow).
AddItem(c.GuildsTree, 10, 1, false).
AddItem(c.ChannelsTree, 0, 1, false)
rightFlex := tview.NewFlex().
SetDirection(tview.FlexRow).
AddItem(c.MessagesPanel, 0, 1, false).
AddItem(c.MessageInput, 3, 1, false)
c.MainFlex.
AddItem(leftFlex, 0, 1, false).
AddItem(rightFlex, 0, 4, false)
}
func (c *Core) beforeDraw(screen tcell.Screen) bool {
if c.Config.Theme.Background == "default" {
screen.Clear()
}
return false
}
func (c *Core) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
// 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 event
}
switch event.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 event
}
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)
}