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.

171 lignes
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. }