My mirror of the Barnard terminal client for Mumble.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

171 řádky
3.1 KiB

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