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.

tree.go 2.7 KiB

10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
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. }