panel.go 3.2 KB

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