panel.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. line.LineLength(&line.Text)
  50. var joined bool = false
  51. if style > 0 {
  52. top := box_style.top
  53. if line.Text[0:len(top)] == top {
  54. // Yes, this line needs to be joined...
  55. output += p.BorderColor + box_style.middle_left + line.Output() + p.BorderColor + box_style.middle_right
  56. joined = true
  57. }
  58. }
  59. if !joined {
  60. if style > 0 {
  61. output += p.BorderColor + box_style.side
  62. }
  63. output += line.Output()
  64. if style > 0 {
  65. output += p.BorderColor + box_style.side
  66. }
  67. }
  68. row++
  69. }
  70. if style > 0 {
  71. // Bottom / border
  72. output += Goto(p.X, row) + p.BorderColor + box_style.bottom_left
  73. output += strings.Repeat(box_style.top, p.Width) + box_style.bottom_right
  74. }
  75. return output
  76. }
  77. // Output anything that has updated
  78. func (p *Panel) Update() string {
  79. var output string
  80. var style int = int(p.Style)
  81. var row, col int
  82. row = p.Y
  83. col = p.X
  84. if style > 0 {
  85. row++
  86. col++
  87. }
  88. for idx := range p.Lines {
  89. if p.Lines[idx].Update() {
  90. // Yes, line was updated
  91. output += Goto(col, row) + p.Lines[idx].Output()
  92. }
  93. row++
  94. }
  95. return output
  96. }
  97. // Output the updated line
  98. func (p *Panel) UpdateLine(index int) string {
  99. var output string
  100. var style int = int(p.Style)
  101. p.Lines[index].Update()
  102. var row, col int
  103. row = p.Y + index
  104. col = p.X
  105. if style > 0 {
  106. row++
  107. col++
  108. }
  109. var line *Line = &p.Lines[index]
  110. output += Goto(col, row) + line.Output()
  111. return output
  112. }
  113. // Goto the end
  114. func (p *Panel) GotoEnd() string {
  115. var row, col int
  116. row = p.Y
  117. col = p.X
  118. if p.Style > 0 {
  119. row++
  120. col += 2
  121. }
  122. row += len(p.Lines)
  123. col += p.Width
  124. return Goto(col, row)
  125. }
  126. // Is the top line of this style a single line?
  127. func Single(bs BorderStyle) bool {
  128. switch bs {
  129. case SINGLE, SINGLE_DOUBLE:
  130. return true
  131. default:
  132. return false
  133. }
  134. }
  135. // Create a spacer line that will be connected maybe to the sides.
  136. func (p *Panel) Spacer() Line {
  137. var l Line = Line{}
  138. var pos int
  139. if Single(p.Style) {
  140. pos = 0
  141. } else {
  142. pos = 1
  143. }
  144. l.Text = strings.Repeat(BOXES[pos].top, p.Width)
  145. return l
  146. }
  147. func (p *Panel) Center() {
  148. p.CenterX()
  149. p.CenterY()
  150. }
  151. func (p *Panel) CenterX() {
  152. p.X = (Width - p.Width) / 2
  153. }
  154. func (p *Panel) CenterY() {
  155. p.Y = (Height - len(p.Lines)) / 2
  156. }