My mirror of the Barnard terminal client for Mumble.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

162 lines
3.0 KiB

  1. package uiterm
  2. import (
  3. "errors"
  4. "github.com/nsf/termbox-go"
  5. )
  6. type KeyListener func(ui *Ui, key Key)
  7. type UiManager interface {
  8. OnUiInitialize(ui *Ui)
  9. OnUiResize(ui *Ui, width, height int)
  10. }
  11. type Ui struct {
  12. Fg Attribute
  13. Bg Attribute
  14. close chan bool
  15. manager UiManager
  16. elements map[string]*uiElement
  17. activeElement *uiElement
  18. keyListeners map[Key][]KeyListener
  19. }
  20. type uiElement struct {
  21. Name string
  22. X0, Y0, X1, Y1 int
  23. View View
  24. }
  25. func New(manager UiManager) *Ui {
  26. ui := &Ui{
  27. close: make(chan bool, 10),
  28. elements: make(map[string]*uiElement),
  29. manager: manager,
  30. keyListeners: make(map[Key][]KeyListener),
  31. }
  32. return ui
  33. }
  34. func (ui *Ui) Close() {
  35. if termbox.IsInit {
  36. ui.close <- true
  37. }
  38. }
  39. func (ui *Ui) Refresh() {
  40. if termbox.IsInit {
  41. termbox.Clear(termbox.Attribute(ui.Fg), termbox.Attribute(ui.Bg))
  42. termbox.HideCursor()
  43. for _, element := range ui.elements {
  44. element.View.uiDraw()
  45. }
  46. termbox.Flush()
  47. }
  48. }
  49. func (ui *Ui) Active() string {
  50. return ui.activeElement.Name
  51. }
  52. func (ui *Ui) SetActive(name string) {
  53. element, _ := ui.elements[name]
  54. if ui.activeElement != nil {
  55. ui.activeElement.View.uiSetActive(false)
  56. }
  57. ui.activeElement = element
  58. if element != nil {
  59. element.View.uiSetActive(true)
  60. }
  61. ui.Refresh()
  62. }
  63. func (ui *Ui) Run() error {
  64. if termbox.IsInit {
  65. return nil
  66. }
  67. if err := termbox.Init(); err != nil {
  68. return nil
  69. }
  70. defer termbox.Close()
  71. termbox.SetInputMode(termbox.InputAlt)
  72. events := make(chan termbox.Event)
  73. go func() {
  74. for {
  75. events <- termbox.PollEvent()
  76. }
  77. }()
  78. ui.manager.OnUiInitialize(ui)
  79. width, height := termbox.Size()
  80. ui.manager.OnUiResize(ui, width, height)
  81. ui.Refresh()
  82. for {
  83. select {
  84. case <-ui.close:
  85. return nil
  86. case event := <-events:
  87. switch event.Type {
  88. case termbox.EventResize:
  89. ui.manager.OnUiResize(ui, event.Width, event.Height)
  90. ui.Refresh()
  91. case termbox.EventKey:
  92. if event.Ch != 0 {
  93. ui.onCharacterEvent(event.Ch)
  94. } else {
  95. ui.onKeyEvent(Modifier(event.Mod), Key(event.Key))
  96. }
  97. }
  98. }
  99. }
  100. }
  101. func (ui *Ui) onCharacterEvent(ch rune) {
  102. if ui.activeElement != nil {
  103. ui.activeElement.View.uiCharacterEvent(ch)
  104. }
  105. }
  106. func (ui *Ui) onKeyEvent(mod Modifier, key Key) {
  107. if ui.keyListeners[key] != nil {
  108. for _, listener := range ui.keyListeners[key] {
  109. listener(ui, key)
  110. }
  111. }
  112. if ui.activeElement != nil {
  113. ui.activeElement.View.uiKeyEvent(mod, key)
  114. }
  115. }
  116. func (ui *Ui) Add(name string, view View) error {
  117. if _, ok := ui.elements[name]; ok {
  118. return errors.New("view already exists")
  119. }
  120. ui.elements[name] = &uiElement{
  121. Name: name,
  122. View: view,
  123. }
  124. view.uiInitialize(ui)
  125. return nil
  126. }
  127. func (ui *Ui) SetBounds(name string, x0, y0, x1, y1 int) error {
  128. element, ok := ui.elements[name]
  129. if !ok {
  130. return errors.New("view does not exist")
  131. }
  132. element.X0, element.Y0, element.X1, element.Y1 = x0, y0, x1, y1
  133. element.View.uiSetBounds(x0, y0, x1, y1)
  134. return nil
  135. }
  136. func (ui *Ui) AddKeyListener(listener KeyListener, key Key) {
  137. ui.keyListeners[key] = append(ui.keyListeners[key], listener)
  138. }