My mirror of the Barnard terminal client for Mumble.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

176 lignes
3.3 KiB

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