panel.go 2.7 KB

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