• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

fyne-io / fyne / 26603301562

28 May 2026 09:28PM UTC coverage: 60.442% (+0.04%) from 60.406%
26603301562

Pull #6323

github

andydotxyz
Fix what looks like an incorrect test
Pull Request #6323: Add form validation

114 of 143 new or added lines in 4 files covered. (79.72%)

6 existing lines in 3 files now uncovered.

26615 of 44034 relevant lines covered (60.44%)

678.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.26
/widget/entry_validation.go
1
package widget
2

3
import (
4
        "fyne.io/fyne/v2"
5
        "fyne.io/fyne/v2/canvas"
6
        "fyne.io/fyne/v2/theme"
7
)
8

9
var (
10
        _ fyne.Requireable = (*Entry)(nil)
11
        _ fyne.Validatable = (*Entry)(nil)
12
)
13

14
// HasValue is used for required validation and returns true if the text is not entry.
15
//
16
// Since: 2.8
17
func (e *Entry) HasValue() bool {
8✔
18
        return e.Text != ""
8✔
19
}
8✔
20

21
// SetRequiredChanged is intended for parent widgets or containers to hook into the required state.
22
// The function might be overwritten by a parent that cares about child state (e.g. widget.Form).
23
//
24
// Since: 2.8
25
func (e *Entry) SetRequiredChanged(callback func(bool)) {
38✔
26
        e.onRequiredChanged = callback
38✔
27
}
38✔
28

29
// Validate validates the current text in the widget.
30
func (e *Entry) Validate() (err error) {
53✔
31
        if e.Validator != nil {
76✔
32
                err = e.Validator(e.Text)
23✔
33
        }
23✔
34

35
        e.SetValidationError(err)
53✔
36
        return err
53✔
37
}
38

39
// validate works like Validate but only updates the internal state and does not refresh.
40
func (e *Entry) validate() {
552✔
41
        var err error
552✔
42

552✔
43
        if e.Validator != nil {
659✔
44
                err = e.Validator(e.Text)
107✔
45
        }
107✔
46
        e.setValidationError(err)
552✔
47
}
48

49
// SetOnValidationChanged is intended for parent widgets or containers to hook into the validation.
50
// The function might be overwritten by a parent that cares about child validation (e.g. widget.Form).
51
func (e *Entry) SetOnValidationChanged(callback func(error)) {
40✔
52
        e.onValidationChanged = callback
40✔
53

40✔
54
        if e.Validator != nil && callback != nil && e.Text != "" {
46✔
55
                if err := e.Validator(e.Text); err != nil {
10✔
56
                        callback(err)
4✔
57
                }
4✔
58
        }
59
}
60

61
// SetValidationError manually updates the validation status until the next input change.
62
func (e *Entry) SetValidationError(err error) {
57✔
63
        if !e.setValidationError(err) {
63✔
64
                return
6✔
65
        }
6✔
66

67
        e.Refresh()
51✔
68
}
69

70
// setValidationError sets the validation error and returns a bool to indicate if it changes.
71
// It assumes that the widget has a validator.
72
func (e *Entry) setValidationError(err error) bool {
609✔
73
        if e.AlwaysShowValidationError {
616✔
74
                e.validationError = err
7✔
75
                if e.onValidationChanged != nil {
7✔
NEW
76
                        e.onValidationChanged(err)
×
NEW
77
                }
×
78
                return true
7✔
79
        }
80

81
        gone := err == nil
602✔
82
        if !gone && (e.focused || (!e.hasFocused && e.Text == "")) {
658✔
83
                return false
56✔
84
        }
56✔
85

86
        e.validationError = err
546✔
87
        if e.onValidationChanged != nil {
577✔
88
                e.onValidationChanged(err)
31✔
89
        }
31✔
90

91
        return true
546✔
92
}
93

94
var _ fyne.Widget = (*validationStatus)(nil)
95

96
type validationStatus struct {
97
        BaseWidget
98
        entry *Entry
99
}
100

101
func newValidationStatus(e *Entry) *validationStatus {
22✔
102
        rs := &validationStatus{
22✔
103
                entry: e,
22✔
104
        }
22✔
105

22✔
106
        rs.ExtendBaseWidget(rs)
22✔
107
        return rs
22✔
108
}
22✔
109

110
func (r *validationStatus) CreateRenderer() fyne.WidgetRenderer {
22✔
111
        icon := &canvas.Image{}
22✔
112
        icon.Hide()
22✔
113
        return &validationStatusRenderer{
22✔
114
                WidgetRenderer: NewSimpleRenderer(icon),
22✔
115
                icon:           icon,
22✔
116
                entry:          r.entry,
22✔
117
        }
22✔
118
}
22✔
119

120
var _ fyne.WidgetRenderer = (*validationStatusRenderer)(nil)
121

122
type validationStatusRenderer struct {
123
        fyne.WidgetRenderer
124
        entry *Entry
125
        icon  *canvas.Image
126
}
127

128
func (r *validationStatusRenderer) Layout(size fyne.Size) {
22✔
129
        iconSize := r.entry.Theme().Size(theme.SizeNameInlineIcon)
22✔
130
        r.icon.Resize(fyne.NewSquareSize(iconSize))
22✔
131
        r.icon.Move(fyne.NewPos((size.Width-iconSize)/2, (size.Height-iconSize)/2))
22✔
132
}
22✔
133

134
func (r *validationStatusRenderer) MinSize() fyne.Size {
×
135
        iconSize := r.entry.Theme().Size(theme.SizeNameInlineIcon)
×
136
        return fyne.NewSquareSize(iconSize)
×
137
}
×
138

139
func (r *validationStatusRenderer) Refresh() {
141✔
140
        th := r.entry.Theme()
141✔
141
        if r.entry.Disabled() {
142✔
142
                r.icon.Hide()
1✔
143
                return
1✔
144
        }
1✔
145

146
        if r.entry.validationError == nil && r.entry.Text != "" && r.entry.Validator != nil {
217✔
147
                r.icon.Resource = th.Icon(theme.IconNameConfirm)
77✔
148
                r.icon.Show()
77✔
149
        } else if r.entry.validationError != nil && !r.entry.focused && (r.entry.dirty || r.entry.AlwaysShowValidationError) {
161✔
150
                r.icon.Resource = theme.NewErrorThemedResource(th.Icon(theme.IconNameError))
21✔
151
                r.icon.Show()
21✔
152
        } else {
63✔
153
                r.icon.Hide()
42✔
154
        }
42✔
155

156
        r.icon.Refresh()
140✔
157
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc