249 lines
5.5 KiB
Go
249 lines
5.5 KiB
Go
package widget
|
|
|
|
import (
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/data/binding"
|
|
"fyne.io/fyne/v2/theme"
|
|
)
|
|
|
|
// Label widget is a label component with appropriate padding and layout.
|
|
type Label struct {
|
|
BaseWidget
|
|
Text string
|
|
Alignment fyne.TextAlign // The alignment of the text
|
|
Wrapping fyne.TextWrap // The wrapping of the text
|
|
TextStyle fyne.TextStyle // The style of the label text
|
|
|
|
// The truncation mode of the text
|
|
//
|
|
// Since: 2.4
|
|
Truncation fyne.TextTruncation
|
|
// Importance informs how the label should be styled, i.e. warning or disabled
|
|
//
|
|
// Since: 2.4
|
|
Importance Importance
|
|
|
|
// The theme size name for the text size of the label
|
|
//
|
|
// Since: 2.6
|
|
SizeName fyne.ThemeSizeName
|
|
|
|
// If set to true, Selectable indicates that this label should support select interaction
|
|
// to allow the text to be copied.
|
|
//
|
|
//Since: 2.6
|
|
Selectable bool
|
|
|
|
provider *RichText
|
|
binder basicBinder
|
|
selection *focusSelectable
|
|
}
|
|
|
|
// NewLabel creates a new label widget with the set text content
|
|
func NewLabel(text string) *Label {
|
|
return NewLabelWithStyle(text, fyne.TextAlignLeading, fyne.TextStyle{})
|
|
}
|
|
|
|
// NewLabelWithData returns a Label widget connected to the specified data source.
|
|
//
|
|
// Since: 2.0
|
|
func NewLabelWithData(data binding.String) *Label {
|
|
label := NewLabel("")
|
|
label.Bind(data)
|
|
|
|
return label
|
|
}
|
|
|
|
// NewLabelWithStyle creates a new label widget with the set text content
|
|
func NewLabelWithStyle(text string, alignment fyne.TextAlign, style fyne.TextStyle) *Label {
|
|
l := &Label{
|
|
Text: text,
|
|
Alignment: alignment,
|
|
TextStyle: style,
|
|
}
|
|
|
|
l.ExtendBaseWidget(l)
|
|
return l
|
|
}
|
|
|
|
// Bind connects the specified data source to this Label.
|
|
// The current value will be displayed and any changes in the data will cause the widget to update.
|
|
//
|
|
// Since: 2.0
|
|
func (l *Label) Bind(data binding.String) {
|
|
l.binder.SetCallback(l.updateFromData) // This could only be done once, maybe in ExtendBaseWidget?
|
|
l.binder.Bind(data)
|
|
}
|
|
|
|
// CreateRenderer is a private method to Fyne which links this widget to its renderer
|
|
func (l *Label) CreateRenderer() fyne.WidgetRenderer {
|
|
l.provider = NewRichTextWithText(l.Text)
|
|
l.ExtendBaseWidget(l)
|
|
l.syncSegments()
|
|
|
|
l.selection = &focusSelectable{}
|
|
l.selection.ExtendBaseWidget(l.selection)
|
|
l.selection.focus = l.selection
|
|
l.selection.style = l.TextStyle
|
|
l.selection.theme = l.Theme()
|
|
l.selection.provider = l.provider
|
|
|
|
return &labelRenderer{l}
|
|
}
|
|
|
|
// MinSize returns the size that this label should not shrink below.
|
|
//
|
|
// Implements: fyne.Widget
|
|
func (l *Label) MinSize() fyne.Size {
|
|
l.ExtendBaseWidget(l)
|
|
return l.BaseWidget.MinSize()
|
|
}
|
|
|
|
// Refresh triggers a redraw of the label.
|
|
//
|
|
// Implements: fyne.Widget
|
|
func (l *Label) Refresh() {
|
|
if l.provider == nil { // not created until visible
|
|
return
|
|
}
|
|
l.syncSegments()
|
|
l.provider.Refresh()
|
|
l.BaseWidget.Refresh()
|
|
}
|
|
|
|
// SelectedText returns the text currently selected in this Label.
|
|
// If the label is not Selectable it will return an empty string.
|
|
// If there is no selection it will return the empty string.
|
|
//
|
|
// Since: 2.6
|
|
func (l *Label) SelectedText() string {
|
|
if !l.Selectable || l.selection == nil {
|
|
return ""
|
|
}
|
|
|
|
return l.selection.SelectedText()
|
|
}
|
|
|
|
// SetText sets the text of the label
|
|
func (l *Label) SetText(text string) {
|
|
l.Text = text
|
|
l.Refresh()
|
|
}
|
|
|
|
// Unbind disconnects any configured data source from this Label.
|
|
// The current value will remain at the last value of the data source.
|
|
//
|
|
// Since: 2.0
|
|
func (l *Label) Unbind() {
|
|
l.binder.Unbind()
|
|
}
|
|
|
|
func (l *Label) syncSegments() {
|
|
var color fyne.ThemeColorName
|
|
switch l.Importance {
|
|
case LowImportance:
|
|
color = theme.ColorNameDisabled
|
|
case MediumImportance:
|
|
color = theme.ColorNameForeground
|
|
case HighImportance:
|
|
color = theme.ColorNamePrimary
|
|
case DangerImportance:
|
|
color = theme.ColorNameError
|
|
case WarningImportance:
|
|
color = theme.ColorNameWarning
|
|
case SuccessImportance:
|
|
color = theme.ColorNameSuccess
|
|
default:
|
|
color = theme.ColorNameForeground
|
|
}
|
|
|
|
sizeName := l.SizeName
|
|
if sizeName == "" {
|
|
sizeName = theme.SizeNameText
|
|
}
|
|
l.provider.Wrapping = l.Wrapping
|
|
l.provider.Truncation = l.Truncation
|
|
l.provider.Segments[0].(*TextSegment).Style = RichTextStyle{
|
|
Alignment: l.Alignment,
|
|
ColorName: color,
|
|
Inline: true,
|
|
TextStyle: l.TextStyle,
|
|
SizeName: sizeName,
|
|
}
|
|
l.provider.Segments[0].(*TextSegment).Text = l.Text
|
|
}
|
|
|
|
func (l *Label) updateFromData(data binding.DataItem) {
|
|
if data == nil {
|
|
return
|
|
}
|
|
textSource, ok := data.(binding.String)
|
|
if !ok {
|
|
return
|
|
}
|
|
val, err := textSource.Get()
|
|
if err != nil {
|
|
fyne.LogError("Error getting current data value", err)
|
|
return
|
|
}
|
|
l.SetText(val)
|
|
}
|
|
|
|
type labelRenderer struct {
|
|
l *Label
|
|
}
|
|
|
|
func (r *labelRenderer) Destroy() {
|
|
}
|
|
|
|
func (r *labelRenderer) Layout(s fyne.Size) {
|
|
r.l.selection.Resize(s)
|
|
r.l.provider.Resize(s)
|
|
}
|
|
|
|
func (r *labelRenderer) MinSize() fyne.Size {
|
|
return r.l.provider.MinSize()
|
|
}
|
|
|
|
func (r *labelRenderer) Objects() []fyne.CanvasObject {
|
|
if !r.l.Selectable {
|
|
return []fyne.CanvasObject{r.l.provider}
|
|
}
|
|
|
|
return []fyne.CanvasObject{r.l.selection, r.l.provider}
|
|
}
|
|
|
|
func (r *labelRenderer) Refresh() {
|
|
r.l.provider.Refresh()
|
|
|
|
sel := r.l.selection
|
|
if !r.l.Selectable || sel == nil {
|
|
return
|
|
}
|
|
|
|
sel.sizeName = r.l.SizeName
|
|
sel.style = r.l.TextStyle
|
|
sel.theme = r.l.Theme()
|
|
sel.Refresh()
|
|
}
|
|
|
|
type focusSelectable struct {
|
|
selectable
|
|
}
|
|
|
|
func (f *focusSelectable) FocusGained() {
|
|
f.focussed = true
|
|
f.Refresh()
|
|
}
|
|
|
|
func (f *focusSelectable) FocusLost() {
|
|
f.focussed = false
|
|
f.Refresh()
|
|
}
|
|
|
|
func (f *focusSelectable) TypedKey(*fyne.KeyEvent) {
|
|
}
|
|
|
|
func (f *focusSelectable) TypedRune(rune) {
|
|
}
|