User interface toolkit for Go with support for SDL2 and HTML Canvas render targets.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

135 lines
2.7 KiB

  1. package ui
  2. import (
  3. "fmt"
  4. "strings"
  5. "git.kirsle.net/go/render"
  6. )
  7. // DefaultFont is the default font settings used for a Label.
  8. var DefaultFont = render.Text{
  9. Size: 12,
  10. Color: render.Black,
  11. }
  12. // Label is a simple text label widget.
  13. type Label struct {
  14. BaseWidget
  15. // Configurable fields for the constructor.
  16. Text string
  17. TextVariable *string
  18. IntVariable *int
  19. Font render.Text
  20. width int
  21. height int
  22. lineHeight int
  23. }
  24. // NewLabel creates a new label.
  25. func NewLabel(c Label) *Label {
  26. w := &Label{
  27. Text: c.Text,
  28. TextVariable: c.TextVariable,
  29. IntVariable: c.IntVariable,
  30. Font: DefaultFont,
  31. }
  32. if !c.Font.IsZero() {
  33. w.Font = c.Font
  34. }
  35. w.IDFunc(func() string {
  36. return fmt.Sprintf(`Label<"%s">`, w.text().Text)
  37. })
  38. return w
  39. }
  40. // text returns the label's displayed text, coming from the TextVariable if
  41. // available or else the Text attribute instead.
  42. func (w *Label) text() render.Text {
  43. if w.TextVariable != nil {
  44. w.Font.Text = *w.TextVariable
  45. return w.Font
  46. } else if w.IntVariable != nil {
  47. w.Font.Text = fmt.Sprintf("%d", *w.IntVariable)
  48. return w.Font
  49. }
  50. w.Font.Text = w.Text
  51. return w.Font
  52. }
  53. // Value returns the current text value displayed in the widget, whether it was
  54. // the hardcoded value or a TextVariable.
  55. func (w *Label) Value() string {
  56. return w.text().Text
  57. }
  58. // Compute the size of the label widget.
  59. func (w *Label) Compute(e render.Engine) {
  60. text := w.text()
  61. lines := strings.Split(text.Text, "\n")
  62. // Max rect to encompass all lines of text.
  63. var maxRect = render.Rect{}
  64. for _, line := range lines {
  65. if line == "" {
  66. line = "<empty>"
  67. }
  68. text.Text = line // only this line at this time.
  69. rect, err := e.ComputeTextRect(text)
  70. if err != nil {
  71. panic(fmt.Sprintf("%s: failed to compute text rect: %s", w, err)) // TODO return an error
  72. }
  73. if rect.W > maxRect.W {
  74. maxRect.W = rect.W
  75. }
  76. maxRect.H += rect.H
  77. w.lineHeight = int(rect.H)
  78. }
  79. var (
  80. padX = w.Font.Padding + w.Font.PadX
  81. padY = w.Font.Padding + w.Font.PadY
  82. )
  83. if !w.FixedSize() {
  84. w.ResizeAuto(render.Rect{
  85. W: maxRect.W + (padX * 2),
  86. H: maxRect.H + (padY * 2),
  87. })
  88. }
  89. // Call the BaseWidget Compute in case we have subscribers.
  90. w.BaseWidget.Compute(e)
  91. }
  92. // Present the label widget.
  93. func (w *Label) Present(e render.Engine, P render.Point) {
  94. if w.Hidden() {
  95. return
  96. }
  97. border := w.BoxThickness(1)
  98. var (
  99. text = w.text()
  100. padX = w.Font.Padding + w.Font.PadX
  101. padY = w.Font.Padding + w.Font.PadY
  102. )
  103. w.DrawBox(e, P)
  104. for i, line := range strings.Split(text.Text, "\n") {
  105. text.Text = line
  106. e.DrawText(text, render.Point{
  107. X: P.X + border + padX,
  108. Y: P.Y + border + padY + (i * w.lineHeight),
  109. })
  110. }
  111. // Call the BaseWidget Present in case we have subscribers.
  112. w.BaseWidget.Present(e, P)
  113. }