label.go 4.1 KB

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