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ů.

před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
před 10 roky
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package uiterm
  2. import (
  3. "strings"
  4. "github.com/nsf/termbox-go"
  5. )
  6. type TreeItem interface {
  7. TreeItemStyle(fg, bg Attribute, active bool) (Attribute, Attribute)
  8. String() string
  9. }
  10. type renderedTreeItem struct {
  11. //String string
  12. Level int
  13. Item TreeItem
  14. }
  15. type Tree struct {
  16. Fg Attribute
  17. Bg Attribute
  18. Generator func(item TreeItem) []TreeItem
  19. Listener func(ui *Ui, tree *Tree, item TreeItem)
  20. lines []renderedTreeItem
  21. activeLine int
  22. ui *Ui
  23. active bool
  24. x0, y0, x1, y1 int
  25. }
  26. func bounded(i, lower, upper int) int {
  27. if i < lower {
  28. return lower
  29. }
  30. if i > upper {
  31. return upper
  32. }
  33. return i
  34. }
  35. func (t *Tree) uiInitialize(ui *Ui) {
  36. t.ui = ui
  37. }
  38. func (t *Tree) uiSetActive(active bool) {
  39. t.active = active
  40. t.uiDraw()
  41. }
  42. func (t *Tree) uiSetBounds(x0, y0, x1, y1 int) {
  43. t.x0 = x0
  44. t.y0 = y0
  45. t.x1 = x1
  46. t.y1 = y1
  47. t.uiDraw()
  48. }
  49. func (t *Tree) Rebuild() {
  50. if t.Generator == nil {
  51. t.lines = []renderedTreeItem{}
  52. return
  53. }
  54. lines := []renderedTreeItem{}
  55. for _, item := range t.Generator(nil) {
  56. children := t.rebuild_rec(item, 0)
  57. if children != nil {
  58. lines = append(lines, children...)
  59. }
  60. }
  61. t.lines = lines
  62. t.activeLine = bounded(t.activeLine, 0, len(t.lines)-1)
  63. t.uiDraw()
  64. }
  65. func (t *Tree) rebuild_rec(parent TreeItem, level int) []renderedTreeItem {
  66. if parent == nil {
  67. return nil
  68. }
  69. lines := []renderedTreeItem{
  70. renderedTreeItem{
  71. Level: level,
  72. Item: parent,
  73. },
  74. }
  75. for _, item := range t.Generator(parent) {
  76. children := t.rebuild_rec(item, level+1)
  77. if children != nil {
  78. lines = append(lines, children...)
  79. }
  80. }
  81. return lines
  82. }
  83. func (t *Tree) uiDraw() {
  84. t.ui.beginDraw()
  85. defer t.ui.endDraw()
  86. if t.lines == nil {
  87. t.Rebuild()
  88. }
  89. line := 0
  90. for y := t.y0; y < t.y1; y++ {
  91. var reader *strings.Reader
  92. var item TreeItem
  93. level := 0
  94. if line < len(t.lines) {
  95. item = t.lines[line].Item
  96. level = t.lines[line].Level
  97. reader = strings.NewReader(item.String())
  98. }
  99. for x := t.x0; x < t.x1; x++ {
  100. var chr rune = ' '
  101. fg := t.Fg
  102. bg := t.Bg
  103. dx := x - t.x0
  104. dy := y - t.y0
  105. if reader != nil && level*2 <= dx {
  106. if ch, _, err := reader.ReadRune(); err == nil {
  107. chr = ch
  108. fg, bg = item.TreeItemStyle(fg, bg, t.active && t.activeLine == dy)
  109. }
  110. }
  111. termbox.SetCell(x, y, chr, termbox.Attribute(fg), termbox.Attribute(bg))
  112. }
  113. line++
  114. }
  115. }
  116. func (t *Tree) uiKeyEvent(mod Modifier, key Key) {
  117. switch key {
  118. case KeyArrowUp:
  119. t.activeLine = bounded(t.activeLine-1, 0, len(t.lines)-1)
  120. case KeyArrowDown:
  121. t.activeLine = bounded(t.activeLine+1, 0, len(t.lines)-1)
  122. case KeyEnter:
  123. if t.Listener != nil && t.activeLine >= 0 && t.activeLine < len(t.lines) {
  124. t.Listener(t.ui, t, t.lines[t.activeLine].Item)
  125. }
  126. }
  127. t.uiDraw()
  128. }
  129. func (t *Tree) uiCharacterEvent(ch rune) {
  130. }