My mirror of the Barnard terminal client for Mumble.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
2.6 KiB

  1. package uiterm
  2. import (
  3. "strings"
  4. "github.com/nsf/termbox-go"
  5. )
  6. type Textview struct {
  7. Lines []string
  8. CurrentLine int
  9. Fg Attribute
  10. Bg Attribute
  11. parsedLines []string
  12. x0, y0, x1, y1 int
  13. }
  14. func (t *Textview) SetActive(ui *Ui, active bool) {
  15. }
  16. func (t *Textview) SetBounds(ui *Ui, x0, y0, x1, y1 int) {
  17. t.x0 = x0
  18. t.y0 = y0
  19. t.x1 = x1
  20. t.y1 = y1
  21. t.updateParsedLines()
  22. }
  23. func (t *Textview) ScrollUp() {
  24. if newLine := t.CurrentLine + 1; newLine < len(t.parsedLines) {
  25. t.CurrentLine = newLine
  26. }
  27. }
  28. func (t *Textview) ScrollDown() {
  29. if newLine := t.CurrentLine - 1; newLine >= 0 {
  30. t.CurrentLine = newLine
  31. }
  32. }
  33. func (t *Textview) ScrollTop() {
  34. if newLine := len(t.parsedLines) - 1; newLine > 0 {
  35. t.CurrentLine = newLine
  36. } else {
  37. t.CurrentLine = 0
  38. }
  39. }
  40. func (t *Textview) ScrollBottom() {
  41. t.CurrentLine = 0
  42. }
  43. func (t *Textview) updateParsedLines() {
  44. width := t.x1 - t.x0 - 3
  45. if t.Lines == nil || width <= 0 {
  46. t.parsedLines = nil
  47. return
  48. }
  49. parsed := make([]string, 0, len(t.Lines))
  50. for _, line := range t.Lines {
  51. current := ""
  52. chars := 0
  53. reader := strings.NewReader(line)
  54. for {
  55. if chars >= width {
  56. parsed = append(parsed, current)
  57. chars = 0
  58. current = ""
  59. }
  60. if reader.Len() <= 0 {
  61. if chars > 0 {
  62. parsed = append(parsed, current)
  63. }
  64. break
  65. }
  66. if ch, _, err := reader.ReadRune(); err == nil {
  67. current = current + string(ch)
  68. chars++
  69. }
  70. }
  71. }
  72. t.parsedLines = parsed
  73. }
  74. func (t *Textview) AddLine(line string) {
  75. t.Lines = append(t.Lines, line)
  76. t.updateParsedLines()
  77. }
  78. func (t *Textview) Clear() {
  79. t.Lines = nil
  80. t.CurrentLine = 0
  81. t.parsedLines = nil
  82. }
  83. func (t *Textview) Draw(ui *Ui) {
  84. var reader *strings.Reader
  85. line := len(t.parsedLines) - 1 - t.CurrentLine
  86. if line < 0 {
  87. line = 0
  88. }
  89. totalLines := len(t.parsedLines)
  90. if totalLines == 0 {
  91. totalLines = 1
  92. }
  93. currentScrollLine := t.y1 - 1 - int((float32(t.CurrentLine)/float32(totalLines))*float32(t.y1-t.y0))
  94. for y := t.y1 - 1; y >= t.y0; y-- {
  95. if t.parsedLines != nil && line >= 0 {
  96. reader = strings.NewReader(t.parsedLines[line])
  97. } else {
  98. reader = nil
  99. }
  100. for x := t.x0; x < t.x1; x++ {
  101. var chr rune = ' '
  102. if x == t.x1-1 { // scrollbar
  103. if y == currentScrollLine {
  104. chr = '█'
  105. } else {
  106. chr = '░'
  107. }
  108. } else if x < t.x1-3 {
  109. if reader != nil {
  110. if ch, _, err := reader.ReadRune(); err == nil {
  111. chr = ch
  112. }
  113. }
  114. }
  115. termbox.SetCell(x, y, chr, termbox.Attribute(t.Fg), termbox.Attribute(t.Bg))
  116. }
  117. line--
  118. }
  119. }
  120. func (t *Textview) KeyEvent(ui *Ui, mod Modifier, key Key) {
  121. }
  122. func (t *Textview) CharacterEvent(ui *Ui, chr rune) {
  123. }