panel.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package door
  2. import "strings"
  3. type BorderStyle int
  4. const (
  5. NONE BorderStyle = iota
  6. SINGLE
  7. DOUBLE
  8. DOUBLE_SINGLE
  9. SINGLE_DOUBLE
  10. )
  11. type Panel struct {
  12. X int
  13. Y int
  14. Width int
  15. Style BorderStyle
  16. BorderColor string
  17. Lines []Line
  18. Title string
  19. TitleOffset int
  20. }
  21. // Output the panel
  22. func (p *Panel) Output() string {
  23. var style int = int(p.Style)
  24. var box_style *BoxStyle
  25. var output string
  26. if style > 0 {
  27. if Unicode {
  28. box_style = &BOXES_UNICODE[style-1]
  29. } else {
  30. box_style = &BOXES[style-1]
  31. }
  32. }
  33. row := p.Y
  34. if style > 0 {
  35. // Top line / border
  36. output += Goto(p.X, row) + p.BorderColor + box_style.top_left
  37. if p.Title != "" {
  38. output += strings.Repeat(box_style.top, p.TitleOffset) + p.Title
  39. }
  40. output += strings.Repeat(box_style.top, p.Width-(p.TitleOffset+len(p.Title))) + box_style.top_right
  41. row++
  42. }
  43. for _, line := range p.Lines {
  44. output += Goto(p.X, row)
  45. var joined bool = false
  46. if style > 0 {
  47. top := box_style.top
  48. if line.Text[0:len(top)] == top {
  49. // Yes, this line needs to be joined...
  50. output += p.BorderColor + box_style.middle_left + line.Output() + p.BorderColor + box_style.middle_right
  51. joined = true
  52. }
  53. }
  54. if !joined {
  55. if style > 0 {
  56. output += p.BorderColor + box_style.side
  57. }
  58. output += line.Output()
  59. if style > 0 {
  60. output += p.BorderColor + box_style.side
  61. }
  62. }
  63. row++
  64. }
  65. if style > 0 {
  66. // Bottom / border
  67. output += Goto(p.X, row) + p.BorderColor + box_style.bottom_left
  68. output += strings.Repeat(box_style.top, p.Width) + box_style.bottom_right
  69. }
  70. return output
  71. }
  72. // Output anything that has updated
  73. func (p *Panel) Update() string {
  74. var output string
  75. var style int = int(p.Style)
  76. row := p.Y
  77. col := p.X
  78. if style > 0 {
  79. row++
  80. col++
  81. }
  82. for _, line := range p.Lines {
  83. if line.Update() {
  84. // Yes, line was updated
  85. output += Goto(col, row) + line.Output()
  86. }
  87. row++
  88. }
  89. return output
  90. }
  91. // Output the updated line
  92. func (p *Panel) UpdateLine(index int) string {
  93. var output string
  94. var style int = int(p.Style)
  95. row := p.Y + index
  96. col := p.X
  97. if style > 0 {
  98. row++
  99. col++
  100. }
  101. line := &p.Lines[index]
  102. output += Goto(col, row) + line.Output()
  103. return output
  104. }
  105. // Goto the end
  106. func (p *Panel) GotoEnd() string {
  107. row := p.Y
  108. col := p.X
  109. if p.Style > 0 {
  110. row++
  111. col += 2
  112. }
  113. row += len(p.Lines)
  114. col += p.Width
  115. return Goto(col, row)
  116. }
  117. // Is the top line of this style a single line?
  118. func Single(bs BorderStyle) bool {
  119. switch bs {
  120. case SINGLE, SINGLE_DOUBLE:
  121. return true
  122. default:
  123. return false
  124. }
  125. }
  126. // Create a spacer line that will be connected maybe to the sides.
  127. func (p *Panel) Spacer() Line {
  128. l := Line{}
  129. var pos int
  130. if Single(p.Style) {
  131. pos = 0
  132. } else {
  133. pos = 1
  134. }
  135. if Unicode {
  136. l.Text = strings.Repeat(BOXES_UNICODE[pos].top, p.Width)
  137. } else {
  138. l.Text = strings.Repeat(BOXES[pos].top, p.Width)
  139. }
  140. return l
  141. }