label.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package widget
  2. import (
  3. "fyne.io/fyne/v2"
  4. "fyne.io/fyne/v2/data/binding"
  5. "fyne.io/fyne/v2/internal/cache"
  6. )
  7. // Label widget is a label component with appropriate padding and layout.
  8. type Label struct {
  9. BaseWidget
  10. Text string
  11. Alignment fyne.TextAlign // The alignment of the Text
  12. Wrapping fyne.TextWrap // The wrapping of the Text
  13. TextStyle fyne.TextStyle // The style of the label text
  14. provider *RichText
  15. binder basicBinder
  16. }
  17. // NewLabel creates a new label widget with the set text content
  18. func NewLabel(text string) *Label {
  19. return NewLabelWithStyle(text, fyne.TextAlignLeading, fyne.TextStyle{})
  20. }
  21. // NewLabelWithData returns an Label widget connected to the specified data source.
  22. //
  23. // Since: 2.0
  24. func NewLabelWithData(data binding.String) *Label {
  25. label := NewLabel("")
  26. label.Bind(data)
  27. return label
  28. }
  29. // NewLabelWithStyle creates a new label widget with the set text content
  30. func NewLabelWithStyle(text string, alignment fyne.TextAlign, style fyne.TextStyle) *Label {
  31. l := &Label{
  32. Text: text,
  33. Alignment: alignment,
  34. TextStyle: style,
  35. }
  36. l.ExtendBaseWidget(l)
  37. return l
  38. }
  39. // Bind connects the specified data source to this Label.
  40. // The current value will be displayed and any changes in the data will cause the widget to update.
  41. //
  42. // Since: 2.0
  43. func (l *Label) Bind(data binding.String) {
  44. l.binder.SetCallback(l.updateFromData) // This could only be done once, maybe in ExtendBaseWidget?
  45. l.binder.Bind(data)
  46. }
  47. // CreateRenderer is a private method to Fyne which links this widget to its renderer
  48. func (l *Label) CreateRenderer() fyne.WidgetRenderer {
  49. l.provider = NewRichTextWithText(l.Text)
  50. l.ExtendBaseWidget(l)
  51. l.syncSegments()
  52. return l.provider.CreateRenderer()
  53. }
  54. // ExtendBaseWidget is used by an extending widget to make use of BaseWidget functionality.
  55. func (l *Label) ExtendBaseWidget(w fyne.Widget) {
  56. if w == nil {
  57. w = l
  58. }
  59. l.BaseWidget.ExtendBaseWidget(w)
  60. if l.provider != nil {
  61. l.provider.ExtendBaseWidget(l.super())
  62. }
  63. }
  64. // MinSize returns the size that this label should not shrink below.
  65. //
  66. // Implements: fyne.Widget
  67. func (l *Label) MinSize() fyne.Size {
  68. if l.provider == nil {
  69. l.ExtendBaseWidget(l)
  70. cache.Renderer(l.super())
  71. }
  72. return l.provider.MinSize()
  73. }
  74. // Refresh triggers a redraw of the label.
  75. //
  76. // Implements: fyne.Widget
  77. func (l *Label) Refresh() {
  78. if l.provider == nil { // not created until visible
  79. return
  80. }
  81. l.syncSegments()
  82. l.provider.Refresh()
  83. l.BaseWidget.Refresh()
  84. }
  85. // Resize sets a new size for the label.
  86. // This should only be called if it is not in a container with a layout manager.
  87. //
  88. // Implements: fyne.Widget
  89. func (l *Label) Resize(s fyne.Size) {
  90. l.BaseWidget.Resize(s)
  91. if l.provider != nil {
  92. l.provider.Resize(s)
  93. }
  94. }
  95. // SetText sets the text of the label
  96. func (l *Label) SetText(text string) {
  97. l.Text = text
  98. l.Refresh()
  99. }
  100. // Unbind disconnects any configured data source from this Label.
  101. // The current value will remain at the last value of the data source.
  102. //
  103. // Since: 2.0
  104. func (l *Label) Unbind() {
  105. l.binder.Unbind()
  106. }
  107. func (l *Label) syncSegments() {
  108. l.provider.Wrapping = l.Wrapping
  109. l.provider.Segments[0].(*TextSegment).Style = RichTextStyle{
  110. Alignment: l.Alignment,
  111. Inline: true,
  112. TextStyle: l.TextStyle,
  113. }
  114. l.provider.Segments[0].(*TextSegment).Text = l.Text
  115. }
  116. func (l *Label) updateFromData(data binding.DataItem) {
  117. if data == nil {
  118. return
  119. }
  120. textSource, ok := data.(binding.String)
  121. if !ok {
  122. return
  123. }
  124. val, err := textSource.Get()
  125. if err != nil {
  126. fyne.LogError("Error getting current data value", err)
  127. return
  128. }
  129. l.SetText(val)
  130. }