core.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package ui
  2. import (
  3. "github.com/ayntgl/discordo/config"
  4. "github.com/gdamore/tcell/v2"
  5. "github.com/rivo/tview"
  6. )
  7. type focused int
  8. const (
  9. guildsTree focused = iota
  10. channelsTree
  11. messagesPanel
  12. messageInput
  13. )
  14. // Core is responsible for the following:
  15. // - Initialization of the application, UI elements, configuration, and state.
  16. // - Configuration of the application and state when Run is called.
  17. // - Management of the application and state.
  18. type Core struct {
  19. Application *tview.Application
  20. MainFlex *tview.Flex
  21. GuildsTree *GuildsTree
  22. ChannelsTree *ChannelsTree
  23. MessagesPanel *MessagesPanel
  24. MessageInput *MessageInput
  25. Config *config.Config
  26. State *State
  27. focused focused
  28. }
  29. func NewCore(cfg *config.Config) *Core {
  30. c := &Core{
  31. Application: tview.NewApplication(),
  32. MainFlex: tview.NewFlex(),
  33. Config: cfg,
  34. }
  35. tview.Styles.PrimitiveBackgroundColor = tcell.GetColor(cfg.Theme.Background)
  36. tview.Styles.BorderColor = tcell.GetColor(cfg.Theme.Border)
  37. tview.Styles.TitleColor = tcell.GetColor(cfg.Theme.Title)
  38. c.Application.EnableMouse(c.Config.Mouse)
  39. c.Application.SetInputCapture(c.onInputCapture)
  40. c.Application.SetBeforeDrawFunc(c.beforeDraw)
  41. c.GuildsTree = NewGuildsTree(c)
  42. c.ChannelsTree = NewChannelsTree(c)
  43. c.MessagesPanel = NewMessagesPanel(c)
  44. c.MessageInput = NewMessageInput(c)
  45. return c
  46. }
  47. func (c *Core) Run(token string) error {
  48. c.State = NewState(token, c)
  49. return c.State.Run()
  50. }
  51. func (c *Core) DrawMainFlex() {
  52. leftFlex := tview.NewFlex().
  53. SetDirection(tview.FlexRow).
  54. AddItem(c.GuildsTree, 10, 1, false).
  55. AddItem(c.ChannelsTree, 0, 1, false)
  56. rightFlex := tview.NewFlex().
  57. SetDirection(tview.FlexRow).
  58. AddItem(c.MessagesPanel, 0, 1, false).
  59. AddItem(c.MessageInput, 3, 1, false)
  60. c.MainFlex.
  61. AddItem(leftFlex, 0, 1, false).
  62. AddItem(rightFlex, 0, 4, false)
  63. }
  64. func (c *Core) beforeDraw(screen tcell.Screen) bool {
  65. if c.Config.Theme.Background == "default" {
  66. screen.Clear()
  67. }
  68. return false
  69. }
  70. func (c *Core) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
  71. // If the main flex is nil, that is, it is not initialized yet, then the login form is currently focused.
  72. if c.MainFlex == nil {
  73. return event
  74. }
  75. switch event.Key() {
  76. case tcell.KeyEsc:
  77. c.focused = 0
  78. case tcell.KeyBacktab:
  79. // If the currently focused widget is the guilds tree widget (first), then focus the message input widget (last)
  80. if c.focused == 0 {
  81. c.focused = messageInput
  82. } else {
  83. c.focused--
  84. }
  85. c.setFocus()
  86. case tcell.KeyTab:
  87. // If the currently focused widget is the message input widget (last), then focus the guilds tree widget (first)
  88. if c.focused == messageInput {
  89. c.focused = guildsTree
  90. } else {
  91. c.focused++
  92. }
  93. c.setFocus()
  94. }
  95. return event
  96. }
  97. func (c *Core) setFocus() {
  98. var p tview.Primitive
  99. switch c.focused {
  100. case guildsTree:
  101. p = c.GuildsTree
  102. case channelsTree:
  103. p = c.ChannelsTree
  104. case messagesPanel:
  105. p = c.MessagesPanel
  106. case messageInput:
  107. p = c.MessageInput
  108. }
  109. c.Application.SetFocus(p)
  110. }