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.
 
 
 
 
 

149 lines
3.0 KiB

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