My mirror of the Barnard terminal client for Mumble.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

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